Delete trailing whitespace.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@62307 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Mikhail Glushenkov 2009-01-16 06:53:46 +00:00
parent a10f15949d
commit 5c1799b293
8 changed files with 420 additions and 420 deletions

View File

@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// //
// Defines a registry template for discovering pluggable modules. // Defines a registry template for discovering pluggable modules.
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#ifndef LLVM_SUPPORT_REGISTRY_H #ifndef LLVM_SUPPORT_REGISTRY_H
@ -23,34 +23,34 @@ namespace llvm {
class SimpleRegistryEntry { class SimpleRegistryEntry {
const char *Name, *Desc; const char *Name, *Desc;
T *(*Ctor)(); T *(*Ctor)();
public: public:
SimpleRegistryEntry(const char *N, const char *D, T *(*C)()) SimpleRegistryEntry(const char *N, const char *D, T *(*C)())
: Name(N), Desc(D), Ctor(C) : Name(N), Desc(D), Ctor(C)
{} {}
const char *getName() const { return Name; } const char *getName() const { return Name; }
const char *getDesc() const { return Desc; } const char *getDesc() const { return Desc; }
T *instantiate() const { return Ctor(); } T *instantiate() const { return Ctor(); }
}; };
/// Traits for registry entries. If using other than SimpleRegistryEntry, it /// Traits for registry entries. If using other than SimpleRegistryEntry, it
/// is necessary to define an alternate traits class. /// is necessary to define an alternate traits class.
template <typename T> template <typename T>
class RegistryTraits { class RegistryTraits {
RegistryTraits(); // Do not implement. RegistryTraits(); // Do not implement.
public: public:
typedef SimpleRegistryEntry<T> entry; typedef SimpleRegistryEntry<T> entry;
/// nameof/descof - Accessors for name and description of entries. These are /// nameof/descof - Accessors for name and description of entries. These are
// used to generate help for command-line options. // used to generate help for command-line options.
static const char *nameof(const entry &Entry) { return Entry.getName(); } static const char *nameof(const entry &Entry) { return Entry.getName(); }
static const char *descof(const entry &Entry) { return Entry.getDesc(); } static const char *descof(const entry &Entry) { return Entry.getDesc(); }
}; };
/// A global registry used in conjunction with static constructors to make /// A global registry used in conjunction with static constructors to make
/// pluggable components (like targets or garbage collectors) "just work" when /// pluggable components (like targets or garbage collectors) "just work" when
/// linked with an executable. /// linked with an executable.
@ -59,37 +59,37 @@ namespace llvm {
public: public:
typedef U traits; typedef U traits;
typedef typename U::entry entry; typedef typename U::entry entry;
class node; class node;
class listener; class listener;
class iterator; class iterator;
private: private:
Registry(); // Do not implement. Registry(); // Do not implement.
static void Announce(const entry &E) { static void Announce(const entry &E) {
for (listener *Cur = ListenerHead; Cur; Cur = Cur->Next) for (listener *Cur = ListenerHead; Cur; Cur = Cur->Next)
Cur->registered(E); Cur->registered(E);
} }
friend class node; friend class node;
static node *Head, *Tail; static node *Head, *Tail;
friend class listener; friend class listener;
static listener *ListenerHead, *ListenerTail; static listener *ListenerHead, *ListenerTail;
public: public:
class iterator; class iterator;
/// Node in linked list of entries. /// Node in linked list of entries.
/// ///
class node { class node {
friend class iterator; friend class iterator;
node *Next; node *Next;
const entry& Val; const entry& Val;
public: public:
node(const entry& V) : Next(0), Val(V) { node(const entry& V) : Next(0), Val(V) {
if (Tail) if (Tail)
@ -97,63 +97,63 @@ namespace llvm {
else else
Head = this; Head = this;
Tail = this; Tail = this;
Announce(V); Announce(V);
} }
}; };
/// Iterators for registry entries. /// Iterators for registry entries.
/// ///
class iterator { class iterator {
const node *Cur; const node *Cur;
public: public:
explicit iterator(const node *N) : Cur(N) {} explicit iterator(const node *N) : Cur(N) {}
bool operator==(const iterator &That) const { return Cur == That.Cur; } bool operator==(const iterator &That) const { return Cur == That.Cur; }
bool operator!=(const iterator &That) const { return Cur != That.Cur; } bool operator!=(const iterator &That) const { return Cur != That.Cur; }
iterator &operator++() { Cur = Cur->Next; return *this; } iterator &operator++() { Cur = Cur->Next; return *this; }
const entry &operator*() const { return Cur->Val; } const entry &operator*() const { return Cur->Val; }
const entry *operator->() const { return &Cur->Val; } const entry *operator->() const { return &Cur->Val; }
}; };
static iterator begin() { return iterator(Head); } static iterator begin() { return iterator(Head); }
static iterator end() { return iterator(0); } static iterator end() { return iterator(0); }
/// Abstract base class for registry listeners, which are informed when new /// Abstract base class for registry listeners, which are informed when new
/// entries are added to the registry. Simply subclass and instantiate: /// entries are added to the registry. Simply subclass and instantiate:
/// ///
/// class CollectorPrinter : public Registry<Collector>::listener { /// class CollectorPrinter : public Registry<Collector>::listener {
/// protected: /// protected:
/// void registered(const Registry<Collector>::entry &e) { /// void registered(const Registry<Collector>::entry &e) {
/// cerr << "collector now available: " << e->getName() << "\n"; /// cerr << "collector now available: " << e->getName() << "\n";
/// } /// }
/// ///
/// public: /// public:
/// CollectorPrinter() { init(); } // Print those already registered. /// CollectorPrinter() { init(); } // Print those already registered.
/// }; /// };
/// ///
/// CollectorPrinter Printer; /// CollectorPrinter Printer;
/// ///
class listener { class listener {
listener *Prev, *Next; listener *Prev, *Next;
friend void Registry::Announce(const entry &E); friend void Registry::Announce(const entry &E);
protected: protected:
/// Called when an entry is added to the registry. /// Called when an entry is added to the registry.
/// ///
virtual void registered(const entry &) = 0; virtual void registered(const entry &) = 0;
/// Calls 'registered' for each pre-existing entry. /// Calls 'registered' for each pre-existing entry.
/// ///
void init() { void init() {
for (iterator I = begin(), E = end(); I != E; ++I) for (iterator I = begin(), E = end(); I != E; ++I)
registered(*I); registered(*I);
} }
public: public:
listener() : Prev(ListenerTail), Next(0) { listener() : Prev(ListenerTail), Next(0) {
if (Prev) if (Prev)
@ -162,7 +162,7 @@ namespace llvm {
ListenerHead = this; ListenerHead = this;
ListenerTail = this; ListenerTail = this;
} }
virtual ~listener() { virtual ~listener() {
if (Next) if (Next)
Next->Prev = Prev; Next->Prev = Prev;
@ -174,79 +174,79 @@ namespace llvm {
ListenerHead = Next; ListenerHead = Next;
} }
}; };
/// A static registration template. Use like such: /// A static registration template. Use like such:
/// ///
/// Registry<Collector>::Add<FancyGC> /// Registry<Collector>::Add<FancyGC>
/// X("fancy-gc", "Newfangled garbage collector."); /// X("fancy-gc", "Newfangled garbage collector.");
/// ///
/// Use of this template requires that: /// Use of this template requires that:
/// ///
/// 1. The registered subclass has a default constructor. /// 1. The registered subclass has a default constructor.
// //
/// 2. The registry entry type has a constructor compatible with this /// 2. The registry entry type has a constructor compatible with this
/// signature: /// signature:
/// ///
/// entry(const char *Name, const char *ShortDesc, T *(*Ctor)()); /// entry(const char *Name, const char *ShortDesc, T *(*Ctor)());
/// ///
/// If you have more elaborate requirements, then copy and modify. /// If you have more elaborate requirements, then copy and modify.
/// ///
template <typename V> template <typename V>
class Add { class Add {
entry Entry; entry Entry;
node Node; node Node;
static T *CtorFn() { return new V(); } static T *CtorFn() { return new V(); }
public: public:
Add(const char *Name, const char *Desc) Add(const char *Name, const char *Desc)
: Entry(Name, Desc, CtorFn), Node(Entry) {} : Entry(Name, Desc, CtorFn), Node(Entry) {}
}; };
/// A command-line parser for a registry. Use like such: /// A command-line parser for a registry. Use like such:
/// ///
/// static cl::opt<Registry<Collector>::entry, false, /// static cl::opt<Registry<Collector>::entry, false,
/// Registry<Collector>::Parser> /// Registry<Collector>::Parser>
/// GCOpt("gc", cl::desc("Garbage collector to use."), /// GCOpt("gc", cl::desc("Garbage collector to use."),
/// cl::value_desc()); /// cl::value_desc());
/// ///
/// To make use of the value: /// To make use of the value:
/// ///
/// Collector *TheCollector = GCOpt->instantiate(); /// Collector *TheCollector = GCOpt->instantiate();
/// ///
class Parser : public cl::parser<const typename U::entry*>, public listener{ class Parser : public cl::parser<const typename U::entry*>, public listener{
typedef U traits; typedef U traits;
typedef typename U::entry entry; typedef typename U::entry entry;
protected: protected:
void registered(const entry &E) { void registered(const entry &E) {
addLiteralOption(traits::nameof(E), &E, traits::descof(E)); addLiteralOption(traits::nameof(E), &E, traits::descof(E));
} }
public: public:
void initialize(cl::Option &O) { void initialize(cl::Option &O) {
listener::init(); listener::init();
cl::parser<const typename U::entry*>::initialize(O); cl::parser<const typename U::entry*>::initialize(O);
} }
}; };
}; };
template <typename T, typename U> template <typename T, typename U>
typename Registry<T,U>::node *Registry<T,U>::Head; typename Registry<T,U>::node *Registry<T,U>::Head;
template <typename T, typename U> template <typename T, typename U>
typename Registry<T,U>::node *Registry<T,U>::Tail; typename Registry<T,U>::node *Registry<T,U>::Tail;
template <typename T, typename U> template <typename T, typename U>
typename Registry<T,U>::listener *Registry<T,U>::ListenerHead; typename Registry<T,U>::listener *Registry<T,U>::ListenerHead;
template <typename T, typename U> template <typename T, typename U>
typename Registry<T,U>::listener *Registry<T,U>::ListenerTail; typename Registry<T,U>::listener *Registry<T,U>::ListenerTail;
} }
#endif #endif

View File

@ -22,14 +22,14 @@
namespace llvm { namespace llvm {
class Module; class Module;
class TargetMachine; class TargetMachine;
struct TargetMachineRegistryEntry { struct TargetMachineRegistryEntry {
const char *Name; const char *Name;
const char *ShortDesc; const char *ShortDesc;
TargetMachine *(*CtorFn)(const Module &, const std::string &); TargetMachine *(*CtorFn)(const Module &, const std::string &);
unsigned (*ModuleMatchQualityFn)(const Module &M); unsigned (*ModuleMatchQualityFn)(const Module &M);
unsigned (*JITMatchQualityFn)(); unsigned (*JITMatchQualityFn)();
public: public:
TargetMachineRegistryEntry(const char *N, const char *SD, TargetMachineRegistryEntry(const char *N, const char *SD,
TargetMachine *(*CF)(const Module &, const std::string &), TargetMachine *(*CF)(const Module &, const std::string &),
@ -38,12 +38,12 @@ namespace llvm {
: Name(N), ShortDesc(SD), CtorFn(CF), ModuleMatchQualityFn(MMF), : Name(N), ShortDesc(SD), CtorFn(CF), ModuleMatchQualityFn(MMF),
JITMatchQualityFn(JMF) {} JITMatchQualityFn(JMF) {}
}; };
template<> template<>
class RegistryTraits<TargetMachine> { class RegistryTraits<TargetMachine> {
public: public:
typedef TargetMachineRegistryEntry entry; typedef TargetMachineRegistryEntry entry;
static const char *nameof(const entry &Entry) { return Entry.Name; } static const char *nameof(const entry &Entry) { return Entry.Name; }
static const char *descof(const entry &Entry) { return Entry.ShortDesc; } static const char *descof(const entry &Entry) { return Entry.ShortDesc; }
}; };
@ -67,12 +67,12 @@ namespace llvm {
/// themselves with the tool they are linked. Targets should define an /// themselves with the tool they are linked. Targets should define an
/// instance of this and implement the static methods described in the /// instance of this and implement the static methods described in the
/// TargetMachine comments. /// TargetMachine comments.
/// The type 'TargetMachineImpl' should provide a constructor with two /// The type 'TargetMachineImpl' should provide a constructor with two
/// parameters: /// parameters:
/// - const Module& M: the module that is being compiled: /// - const Module& M: the module that is being compiled:
/// - const std::string& FS: target-specific string describing target /// - const std::string& FS: target-specific string describing target
/// flavour. /// flavour.
template<class TargetMachineImpl> template<class TargetMachineImpl>
struct RegisterTarget { struct RegisterTarget {
RegisterTarget(const char *Name, const char *ShortDesc) RegisterTarget(const char *Name, const char *ShortDesc)
@ -85,7 +85,7 @@ namespace llvm {
private: private:
TargetMachineRegistry::entry Entry; TargetMachineRegistry::entry Entry;
TargetMachineRegistry::node Node; TargetMachineRegistry::node Node;
static TargetMachine *Allocator(const Module &M, const std::string &FS) { static TargetMachine *Allocator(const Module &M, const std::string &FS) {
return new TargetMachineImpl(M, FS); return new TargetMachineImpl(M, FS);
} }

View File

@ -10,7 +10,7 @@
// This file implements printing the assembly code for an Ocaml frametable. // This file implements printing the assembly code for an Ocaml frametable.
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "llvm/CodeGen/GCs.h" #include "llvm/CodeGen/GCs.h"
#include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/GCMetadataPrinter.h" #include "llvm/CodeGen/GCMetadataPrinter.h"
@ -28,11 +28,11 @@ namespace {
public: public:
void beginAssembly(raw_ostream &OS, AsmPrinter &AP, void beginAssembly(raw_ostream &OS, AsmPrinter &AP,
const TargetAsmInfo &TAI); const TargetAsmInfo &TAI);
void finishAssembly(raw_ostream &OS, AsmPrinter &AP, void finishAssembly(raw_ostream &OS, AsmPrinter &AP,
const TargetAsmInfo &TAI); const TargetAsmInfo &TAI);
}; };
} }
static GCMetadataPrinterRegistry::Add<OcamlGCMetadataPrinter> static GCMetadataPrinterRegistry::Add<OcamlGCMetadataPrinter>
@ -43,7 +43,7 @@ void llvm::linkOcamlGCPrinter() { }
static void EmitCamlGlobal(const Module &M, raw_ostream &OS, AsmPrinter &AP, static void EmitCamlGlobal(const Module &M, raw_ostream &OS, AsmPrinter &AP,
const TargetAsmInfo &TAI, const char *Id) { const TargetAsmInfo &TAI, const char *Id) {
const std::string &MId = M.getModuleIdentifier(); const std::string &MId = M.getModuleIdentifier();
std::string Mangled; std::string Mangled;
Mangled += TAI.getGlobalPrefix(); Mangled += TAI.getGlobalPrefix();
Mangled += "caml"; Mangled += "caml";
@ -51,10 +51,10 @@ static void EmitCamlGlobal(const Module &M, raw_ostream &OS, AsmPrinter &AP,
Mangled.append(MId.begin(), std::find(MId.begin(), MId.end(), '.')); Mangled.append(MId.begin(), std::find(MId.begin(), MId.end(), '.'));
Mangled += "__"; Mangled += "__";
Mangled += Id; Mangled += Id;
// Capitalize the first letter of the module name. // Capitalize the first letter of the module name.
Mangled[Letter] = toupper(Mangled[Letter]); Mangled[Letter] = toupper(Mangled[Letter]);
if (const char *GlobalDirective = TAI.getGlobalDirective()) if (const char *GlobalDirective = TAI.getGlobalDirective())
OS << GlobalDirective << Mangled << "\n"; OS << GlobalDirective << Mangled << "\n";
OS << Mangled << ":\n"; OS << Mangled << ":\n";
@ -64,13 +64,13 @@ void OcamlGCMetadataPrinter::beginAssembly(raw_ostream &OS, AsmPrinter &AP,
const TargetAsmInfo &TAI) { const TargetAsmInfo &TAI) {
AP.SwitchToSection(TAI.getTextSection()); AP.SwitchToSection(TAI.getTextSection());
EmitCamlGlobal(getModule(), OS, AP, TAI, "code_begin"); EmitCamlGlobal(getModule(), OS, AP, TAI, "code_begin");
AP.SwitchToSection(TAI.getDataSection()); AP.SwitchToSection(TAI.getDataSection());
EmitCamlGlobal(getModule(), OS, AP, TAI, "data_begin"); EmitCamlGlobal(getModule(), OS, AP, TAI, "data_begin");
} }
/// emitAssembly - Print the frametable. The ocaml frametable format is thus: /// emitAssembly - Print the frametable. The ocaml frametable format is thus:
/// ///
/// extern "C" struct align(sizeof(intptr_t)) { /// extern "C" struct align(sizeof(intptr_t)) {
/// uint16_t NumDescriptors; /// uint16_t NumDescriptors;
/// struct align(sizeof(intptr_t)) { /// struct align(sizeof(intptr_t)) {
@ -80,11 +80,11 @@ void OcamlGCMetadataPrinter::beginAssembly(raw_ostream &OS, AsmPrinter &AP,
/// uint16_t LiveOffsets[NumLiveOffsets]; /// uint16_t LiveOffsets[NumLiveOffsets];
/// } Descriptors[NumDescriptors]; /// } Descriptors[NumDescriptors];
/// } caml${module}__frametable; /// } caml${module}__frametable;
/// ///
/// Note that this precludes programs from stack frames larger than 64K /// Note that this precludes programs from stack frames larger than 64K
/// (FrameSize and LiveOffsets would overflow). FrameTablePrinter will abort if /// (FrameSize and LiveOffsets would overflow). FrameTablePrinter will abort if
/// either condition is detected in a function which uses the GC. /// either condition is detected in a function which uses the GC.
/// ///
void OcamlGCMetadataPrinter::finishAssembly(raw_ostream &OS, AsmPrinter &AP, void OcamlGCMetadataPrinter::finishAssembly(raw_ostream &OS, AsmPrinter &AP,
const TargetAsmInfo &TAI) { const TargetAsmInfo &TAI) {
const char *AddressDirective; const char *AddressDirective;
@ -99,19 +99,19 @@ void OcamlGCMetadataPrinter::finishAssembly(raw_ostream &OS, AsmPrinter &AP,
AP.SwitchToSection(TAI.getTextSection()); AP.SwitchToSection(TAI.getTextSection());
EmitCamlGlobal(getModule(), OS, AP, TAI, "code_end"); EmitCamlGlobal(getModule(), OS, AP, TAI, "code_end");
AP.SwitchToSection(TAI.getDataSection()); AP.SwitchToSection(TAI.getDataSection());
EmitCamlGlobal(getModule(), OS, AP, TAI, "data_end"); EmitCamlGlobal(getModule(), OS, AP, TAI, "data_end");
OS << AddressDirective << 0; // FIXME: Why does ocaml emit this?? OS << AddressDirective << 0; // FIXME: Why does ocaml emit this??
AP.EOL(); AP.EOL();
AP.SwitchToSection(TAI.getDataSection()); AP.SwitchToSection(TAI.getDataSection());
EmitCamlGlobal(getModule(), OS, AP, TAI, "frametable"); EmitCamlGlobal(getModule(), OS, AP, TAI, "frametable");
for (iterator I = begin(), IE = end(); I != IE; ++I) { for (iterator I = begin(), IE = end(); I != IE; ++I) {
GCFunctionInfo &FI = **I; GCFunctionInfo &FI = **I;
uint64_t FrameSize = FI.getFrameSize(); uint64_t FrameSize = FI.getFrameSize();
if (FrameSize >= 1<<16) { if (FrameSize >= 1<<16) {
cerr << "Function '" << FI.getFunction().getNameStart() cerr << "Function '" << FI.getFunction().getNameStart()
@ -120,10 +120,10 @@ void OcamlGCMetadataPrinter::finishAssembly(raw_ostream &OS, AsmPrinter &AP,
cerr << "(" << uintptr_t(&FI) << ")\n"; cerr << "(" << uintptr_t(&FI) << ")\n";
abort(); // Very rude! abort(); // Very rude!
} }
OS << "\t" << TAI.getCommentString() << " live roots for " OS << "\t" << TAI.getCommentString() << " live roots for "
<< FI.getFunction().getNameStart() << "\n"; << FI.getFunction().getNameStart() << "\n";
for (GCFunctionInfo::iterator J = FI.begin(), JE = FI.end(); J != JE; ++J) { for (GCFunctionInfo::iterator J = FI.begin(), JE = FI.end(); J != JE; ++J) {
size_t LiveCount = FI.live_size(J); size_t LiveCount = FI.live_size(J);
if (LiveCount >= 1<<16) { if (LiveCount >= 1<<16) {
@ -132,27 +132,27 @@ void OcamlGCMetadataPrinter::finishAssembly(raw_ostream &OS, AsmPrinter &AP,
<< "Live root count " << LiveCount << " >= 65536.\n"; << "Live root count " << LiveCount << " >= 65536.\n";
abort(); // Very rude! abort(); // Very rude!
} }
OS << AddressDirective OS << AddressDirective
<< TAI.getPrivateGlobalPrefix() << "label" << J->Num; << TAI.getPrivateGlobalPrefix() << "label" << J->Num;
AP.EOL("call return address"); AP.EOL("call return address");
AP.EmitInt16(FrameSize); AP.EmitInt16(FrameSize);
AP.EOL("stack frame size"); AP.EOL("stack frame size");
AP.EmitInt16(LiveCount); AP.EmitInt16(LiveCount);
AP.EOL("live root count"); AP.EOL("live root count");
for (GCFunctionInfo::live_iterator K = FI.live_begin(J), for (GCFunctionInfo::live_iterator K = FI.live_begin(J),
KE = FI.live_end(J); K != KE; ++K) { KE = FI.live_end(J); K != KE; ++K) {
assert(K->StackOffset < 1<<16 && assert(K->StackOffset < 1<<16 &&
"GC root stack offset is outside of fixed stack frame and out " "GC root stack offset is outside of fixed stack frame and out "
"of range for ocaml GC!"); "of range for ocaml GC!");
OS << "\t.word\t" << K->StackOffset; OS << "\t.word\t" << K->StackOffset;
AP.EOL("stack offset"); AP.EOL("stack offset");
} }
AP.EmitAlignment(AddressAlignLog); AP.EmitAlignment(AddressAlignLog);
} }
} }

View File

@ -9,11 +9,11 @@
// //
// This file implements lowering for the llvm.gc* intrinsics compatible with // This file implements lowering for the llvm.gc* intrinsics compatible with
// Objective Caml 3.10.0, which uses a liveness-accurate static stack map. // Objective Caml 3.10.0, which uses a liveness-accurate static stack map.
// //
// The frametable emitter is in OcamlGCPrinter.cpp. // The frametable emitter is in OcamlGCPrinter.cpp.
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "llvm/CodeGen/GCs.h" #include "llvm/CodeGen/GCs.h"
#include "llvm/CodeGen/GCStrategy.h" #include "llvm/CodeGen/GCStrategy.h"

File diff suppressed because it is too large Load Diff

View File

@ -36,26 +36,26 @@
using namespace llvm; using namespace llvm;
namespace { namespace {
class VISIBILITY_HIDDEN ShadowStackGC : public GCStrategy { class VISIBILITY_HIDDEN ShadowStackGC : public GCStrategy {
/// RootChain - This is the global linked-list that contains the chain of GC /// RootChain - This is the global linked-list that contains the chain of GC
/// roots. /// roots.
GlobalVariable *Head; GlobalVariable *Head;
/// StackEntryTy - Abstract type of a link in the shadow stack. /// StackEntryTy - Abstract type of a link in the shadow stack.
/// ///
const StructType *StackEntryTy; const StructType *StackEntryTy;
/// Roots - GC roots in the current function. Each is a pair of the /// Roots - GC roots in the current function. Each is a pair of the
/// intrinsic call and its corresponding alloca. /// intrinsic call and its corresponding alloca.
std::vector<std::pair<CallInst*,AllocaInst*> > Roots; std::vector<std::pair<CallInst*,AllocaInst*> > Roots;
public: public:
ShadowStackGC(); ShadowStackGC();
bool initializeCustomLowering(Module &M); bool initializeCustomLowering(Module &M);
bool performCustomLowering(Function &F); bool performCustomLowering(Function &F);
private: private:
bool IsNullValue(Value *V); bool IsNullValue(Value *V);
Constant *GetFrameMap(Function &F); Constant *GetFrameMap(Function &F);
@ -68,58 +68,58 @@ namespace {
}; };
} }
static GCRegistry::Add<ShadowStackGC> static GCRegistry::Add<ShadowStackGC>
X("shadow-stack", "Very portable GC for uncooperative code generators"); X("shadow-stack", "Very portable GC for uncooperative code generators");
namespace { namespace {
/// EscapeEnumerator - This is a little algorithm to find all escape points /// EscapeEnumerator - This is a little algorithm to find all escape points
/// from a function so that "finally"-style code can be inserted. In addition /// from a function so that "finally"-style code can be inserted. In addition
/// to finding the existing return and unwind instructions, it also (if /// to finding the existing return and unwind instructions, it also (if
/// necessary) transforms any call instructions into invokes and sends them to /// necessary) transforms any call instructions into invokes and sends them to
/// a landing pad. /// a landing pad.
/// ///
/// It's wrapped up in a state machine using the same transform C# uses for /// It's wrapped up in a state machine using the same transform C# uses for
/// 'yield return' enumerators, This transform allows it to be non-allocating. /// 'yield return' enumerators, This transform allows it to be non-allocating.
class VISIBILITY_HIDDEN EscapeEnumerator { class VISIBILITY_HIDDEN EscapeEnumerator {
Function &F; Function &F;
const char *CleanupBBName; const char *CleanupBBName;
// State. // State.
int State; int State;
Function::iterator StateBB, StateE; Function::iterator StateBB, StateE;
IRBuilder<> Builder; IRBuilder<> Builder;
public: public:
EscapeEnumerator(Function &F, const char *N = "cleanup") EscapeEnumerator(Function &F, const char *N = "cleanup")
: F(F), CleanupBBName(N), State(0) {} : F(F), CleanupBBName(N), State(0) {}
IRBuilder<> *Next() { IRBuilder<> *Next() {
switch (State) { switch (State) {
default: default:
return 0; return 0;
case 0: case 0:
StateBB = F.begin(); StateBB = F.begin();
StateE = F.end(); StateE = F.end();
State = 1; State = 1;
case 1: case 1:
// Find all 'return' and 'unwind' instructions. // Find all 'return' and 'unwind' instructions.
while (StateBB != StateE) { while (StateBB != StateE) {
BasicBlock *CurBB = StateBB++; BasicBlock *CurBB = StateBB++;
// Branches and invokes do not escape, only unwind and return do. // Branches and invokes do not escape, only unwind and return do.
TerminatorInst *TI = CurBB->getTerminator(); TerminatorInst *TI = CurBB->getTerminator();
if (!isa<UnwindInst>(TI) && !isa<ReturnInst>(TI)) if (!isa<UnwindInst>(TI) && !isa<ReturnInst>(TI))
continue; continue;
Builder.SetInsertPoint(TI->getParent(), TI); Builder.SetInsertPoint(TI->getParent(), TI);
return &Builder; return &Builder;
} }
State = 2; State = 2;
// Find all 'call' instructions. // Find all 'call' instructions.
SmallVector<Instruction*,16> Calls; SmallVector<Instruction*,16> Calls;
for (Function::iterator BB = F.begin(), for (Function::iterator BB = F.begin(),
@ -130,33 +130,33 @@ namespace {
if (!CI->getCalledFunction() || if (!CI->getCalledFunction() ||
!CI->getCalledFunction()->getIntrinsicID()) !CI->getCalledFunction()->getIntrinsicID())
Calls.push_back(CI); Calls.push_back(CI);
if (Calls.empty()) if (Calls.empty())
return 0; return 0;
// Create a cleanup block. // Create a cleanup block.
BasicBlock *CleanupBB = BasicBlock::Create(CleanupBBName, &F); BasicBlock *CleanupBB = BasicBlock::Create(CleanupBBName, &F);
UnwindInst *UI = new UnwindInst(CleanupBB); UnwindInst *UI = new UnwindInst(CleanupBB);
// Transform the 'call' instructions into 'invoke's branching to the // Transform the 'call' instructions into 'invoke's branching to the
// cleanup block. Go in reverse order to make prettier BB names. // cleanup block. Go in reverse order to make prettier BB names.
SmallVector<Value*,16> Args; SmallVector<Value*,16> Args;
for (unsigned I = Calls.size(); I != 0; ) { for (unsigned I = Calls.size(); I != 0; ) {
CallInst *CI = cast<CallInst>(Calls[--I]); CallInst *CI = cast<CallInst>(Calls[--I]);
// Split the basic block containing the function call. // Split the basic block containing the function call.
BasicBlock *CallBB = CI->getParent(); BasicBlock *CallBB = CI->getParent();
BasicBlock *NewBB = BasicBlock *NewBB =
CallBB->splitBasicBlock(CI, CallBB->getName() + ".cont"); CallBB->splitBasicBlock(CI, CallBB->getName() + ".cont");
// Remove the unconditional branch inserted at the end of CallBB. // Remove the unconditional branch inserted at the end of CallBB.
CallBB->getInstList().pop_back(); CallBB->getInstList().pop_back();
NewBB->getInstList().remove(CI); NewBB->getInstList().remove(CI);
// Create a new invoke instruction. // Create a new invoke instruction.
Args.clear(); Args.clear();
Args.append(CI->op_begin() + 1, CI->op_end()); Args.append(CI->op_begin() + 1, CI->op_end());
InvokeInst *II = InvokeInst::Create(CI->getOperand(0), InvokeInst *II = InvokeInst::Create(CI->getOperand(0),
NewBB, CleanupBB, NewBB, CleanupBB,
Args.begin(), Args.end(), Args.begin(), Args.end(),
@ -166,7 +166,7 @@ namespace {
CI->replaceAllUsesWith(II); CI->replaceAllUsesWith(II);
delete CI; delete CI;
} }
Builder.SetInsertPoint(UI->getParent(), UI); Builder.SetInsertPoint(UI->getParent(), UI);
return &Builder; return &Builder;
} }
@ -185,9 +185,9 @@ ShadowStackGC::ShadowStackGC() : Head(0), StackEntryTy(0) {
Constant *ShadowStackGC::GetFrameMap(Function &F) { Constant *ShadowStackGC::GetFrameMap(Function &F) {
// doInitialization creates the abstract type of this value. // doInitialization creates the abstract type of this value.
Type *VoidPtr = PointerType::getUnqual(Type::Int8Ty); Type *VoidPtr = PointerType::getUnqual(Type::Int8Ty);
// Truncate the ShadowStackDescriptor if some metadata is null. // Truncate the ShadowStackDescriptor if some metadata is null.
unsigned NumMeta = 0; unsigned NumMeta = 0;
SmallVector<Constant*,16> Metadata; SmallVector<Constant*,16> Metadata;
@ -197,33 +197,33 @@ Constant *ShadowStackGC::GetFrameMap(Function &F) {
NumMeta = I + 1; NumMeta = I + 1;
Metadata.push_back(ConstantExpr::getBitCast(C, VoidPtr)); Metadata.push_back(ConstantExpr::getBitCast(C, VoidPtr));
} }
Constant *BaseElts[] = { Constant *BaseElts[] = {
ConstantInt::get(Type::Int32Ty, Roots.size(), false), ConstantInt::get(Type::Int32Ty, Roots.size(), false),
ConstantInt::get(Type::Int32Ty, NumMeta, false), ConstantInt::get(Type::Int32Ty, NumMeta, false),
}; };
Constant *DescriptorElts[] = { Constant *DescriptorElts[] = {
ConstantStruct::get(BaseElts, 2), ConstantStruct::get(BaseElts, 2),
ConstantArray::get(ArrayType::get(VoidPtr, NumMeta), ConstantArray::get(ArrayType::get(VoidPtr, NumMeta),
Metadata.begin(), NumMeta) Metadata.begin(), NumMeta)
}; };
Constant *FrameMap = ConstantStruct::get(DescriptorElts, 2); Constant *FrameMap = ConstantStruct::get(DescriptorElts, 2);
std::string TypeName("gc_map."); std::string TypeName("gc_map.");
TypeName += utostr(NumMeta); TypeName += utostr(NumMeta);
F.getParent()->addTypeName(TypeName, FrameMap->getType()); F.getParent()->addTypeName(TypeName, FrameMap->getType());
// FIXME: Is this actually dangerous as WritingAnLLVMPass.html claims? Seems // FIXME: Is this actually dangerous as WritingAnLLVMPass.html claims? Seems
// that, short of multithreaded LLVM, it should be safe; all that is // that, short of multithreaded LLVM, it should be safe; all that is
// necessary is that a simple Module::iterator loop not be invalidated. // necessary is that a simple Module::iterator loop not be invalidated.
// Appending to the GlobalVariable list is safe in that sense. // Appending to the GlobalVariable list is safe in that sense.
// //
// All of the output passes emit globals last. The ExecutionEngine // All of the output passes emit globals last. The ExecutionEngine
// explicitly supports adding globals to the module after // explicitly supports adding globals to the module after
// initialization. // initialization.
// //
// Still, if it isn't deemed acceptable, then this transformation needs // Still, if it isn't deemed acceptable, then this transformation needs
// to be a ModulePass (which means it cannot be in the 'llc' pipeline // to be a ModulePass (which means it cannot be in the 'llc' pipeline
// (which uses a FunctionPassManager (which segfaults (not asserts) if // (which uses a FunctionPassManager (which segfaults (not asserts) if
@ -232,7 +232,7 @@ Constant *ShadowStackGC::GetFrameMap(Function &F) {
GlobalVariable::InternalLinkage, GlobalVariable::InternalLinkage,
FrameMap, "__gc_" + F.getName(), FrameMap, "__gc_" + F.getName(),
F.getParent()); F.getParent());
Constant *GEPIndices[2] = { ConstantInt::get(Type::Int32Ty, 0), Constant *GEPIndices[2] = { ConstantInt::get(Type::Int32Ty, 0),
ConstantInt::get(Type::Int32Ty, 0) }; ConstantInt::get(Type::Int32Ty, 0) };
return ConstantExpr::getGetElementPtr(GV, GEPIndices, 2); return ConstantExpr::getGetElementPtr(GV, GEPIndices, 2);
@ -245,11 +245,11 @@ const Type* ShadowStackGC::GetConcreteStackEntryType(Function &F) {
for (size_t I = 0; I != Roots.size(); I++) for (size_t I = 0; I != Roots.size(); I++)
EltTys.push_back(Roots[I].second->getAllocatedType()); EltTys.push_back(Roots[I].second->getAllocatedType());
Type *Ty = StructType::get(EltTys); Type *Ty = StructType::get(EltTys);
std::string TypeName("gc_stackentry."); std::string TypeName("gc_stackentry.");
TypeName += F.getName(); TypeName += F.getName();
F.getParent()->addTypeName(TypeName, Ty); F.getParent()->addTypeName(TypeName, Ty);
return Ty; return Ty;
} }
@ -267,25 +267,25 @@ bool ShadowStackGC::initializeCustomLowering(Module &M) {
StructType *FrameMapTy = StructType::get(EltTys); StructType *FrameMapTy = StructType::get(EltTys);
M.addTypeName("gc_map", FrameMapTy); M.addTypeName("gc_map", FrameMapTy);
PointerType *FrameMapPtrTy = PointerType::getUnqual(FrameMapTy); PointerType *FrameMapPtrTy = PointerType::getUnqual(FrameMapTy);
// struct StackEntry { // struct StackEntry {
// ShadowStackEntry *Next; // Caller's stack entry. // ShadowStackEntry *Next; // Caller's stack entry.
// FrameMap *Map; // Pointer to constant FrameMap. // FrameMap *Map; // Pointer to constant FrameMap.
// void *Roots[]; // Stack roots (in-place array, so we pretend). // void *Roots[]; // Stack roots (in-place array, so we pretend).
// }; // };
OpaqueType *RecursiveTy = OpaqueType::get(); OpaqueType *RecursiveTy = OpaqueType::get();
EltTys.clear(); EltTys.clear();
EltTys.push_back(PointerType::getUnqual(RecursiveTy)); EltTys.push_back(PointerType::getUnqual(RecursiveTy));
EltTys.push_back(FrameMapPtrTy); EltTys.push_back(FrameMapPtrTy);
PATypeHolder LinkTyH = StructType::get(EltTys); PATypeHolder LinkTyH = StructType::get(EltTys);
RecursiveTy->refineAbstractTypeTo(LinkTyH.get()); RecursiveTy->refineAbstractTypeTo(LinkTyH.get());
StackEntryTy = cast<StructType>(LinkTyH.get()); StackEntryTy = cast<StructType>(LinkTyH.get());
const PointerType *StackEntryPtrTy = PointerType::getUnqual(StackEntryTy); const PointerType *StackEntryPtrTy = PointerType::getUnqual(StackEntryTy);
M.addTypeName("gc_stackentry", LinkTyH.get()); // FIXME: Is this safe from M.addTypeName("gc_stackentry", LinkTyH.get()); // FIXME: Is this safe from
// a FunctionPass? // a FunctionPass?
// Get the root chain if it already exists. // Get the root chain if it already exists.
Head = M.getGlobalVariable("llvm_gc_root_chain"); Head = M.getGlobalVariable("llvm_gc_root_chain");
if (!Head) { if (!Head) {
@ -299,7 +299,7 @@ bool ShadowStackGC::initializeCustomLowering(Module &M) {
Head->setInitializer(Constant::getNullValue(StackEntryPtrTy)); Head->setInitializer(Constant::getNullValue(StackEntryPtrTy));
Head->setLinkage(GlobalValue::LinkOnceLinkage); Head->setLinkage(GlobalValue::LinkOnceLinkage);
} }
return true; return true;
} }
@ -313,11 +313,11 @@ void ShadowStackGC::CollectRoots(Function &F) {
// FIXME: Account for original alignment. Could fragment the root array. // FIXME: Account for original alignment. Could fragment the root array.
// Approach 1: Null initialize empty slots at runtime. Yuck. // Approach 1: Null initialize empty slots at runtime. Yuck.
// Approach 2: Emit a map of the array instead of just a count. // Approach 2: Emit a map of the array instead of just a count.
assert(Roots.empty() && "Not cleaned up?"); assert(Roots.empty() && "Not cleaned up?");
SmallVector<std::pair<CallInst*,AllocaInst*>,16> MetaRoots; SmallVector<std::pair<CallInst*,AllocaInst*>,16> MetaRoots;
for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E;) for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E;)
if (IntrinsicInst *CI = dyn_cast<IntrinsicInst>(II++)) if (IntrinsicInst *CI = dyn_cast<IntrinsicInst>(II++))
@ -330,7 +330,7 @@ void ShadowStackGC::CollectRoots(Function &F) {
else else
MetaRoots.push_back(Pair); MetaRoots.push_back(Pair);
} }
// Number roots with metadata (usually empty) at the beginning, so that the // Number roots with metadata (usually empty) at the beginning, so that the
// FrameMap::Meta array can be elided. // FrameMap::Meta array can be elided.
Roots.insert(Roots.begin(), MetaRoots.begin(), MetaRoots.end()); Roots.insert(Roots.begin(), MetaRoots.begin(), MetaRoots.end());
@ -343,9 +343,9 @@ ShadowStackGC::CreateGEP(IRBuilder<> &B, Value *BasePtr,
ConstantInt::get(Type::Int32Ty, Idx), ConstantInt::get(Type::Int32Ty, Idx),
ConstantInt::get(Type::Int32Ty, Idx2) }; ConstantInt::get(Type::Int32Ty, Idx2) };
Value* Val = B.CreateGEP(BasePtr, Indices, Indices + 3, Name); Value* Val = B.CreateGEP(BasePtr, Indices, Indices + 3, Name);
assert(isa<GetElementPtrInst>(Val) && "Unexpected folded constant"); assert(isa<GetElementPtrInst>(Val) && "Unexpected folded constant");
return dyn_cast<GetElementPtrInst>(Val); return dyn_cast<GetElementPtrInst>(Val);
} }
@ -355,7 +355,7 @@ ShadowStackGC::CreateGEP(IRBuilder<> &B, Value *BasePtr,
Value *Indices[] = { ConstantInt::get(Type::Int32Ty, 0), Value *Indices[] = { ConstantInt::get(Type::Int32Ty, 0),
ConstantInt::get(Type::Int32Ty, Idx) }; ConstantInt::get(Type::Int32Ty, Idx) };
Value *Val = B.CreateGEP(BasePtr, Indices, Indices + 2, Name); Value *Val = B.CreateGEP(BasePtr, Indices, Indices + 2, Name);
assert(isa<GetElementPtrInst>(Val) && "Unexpected folded constant"); assert(isa<GetElementPtrInst>(Val) && "Unexpected folded constant");
return dyn_cast<GetElementPtrInst>(Val); return dyn_cast<GetElementPtrInst>(Val);
@ -365,55 +365,55 @@ ShadowStackGC::CreateGEP(IRBuilder<> &B, Value *BasePtr,
bool ShadowStackGC::performCustomLowering(Function &F) { bool ShadowStackGC::performCustomLowering(Function &F) {
// Find calls to llvm.gcroot. // Find calls to llvm.gcroot.
CollectRoots(F); CollectRoots(F);
// If there are no roots in this function, then there is no need to add a // If there are no roots in this function, then there is no need to add a
// stack map entry for it. // stack map entry for it.
if (Roots.empty()) if (Roots.empty())
return false; return false;
// Build the constant map and figure the type of the shadow stack entry. // Build the constant map and figure the type of the shadow stack entry.
Value *FrameMap = GetFrameMap(F); Value *FrameMap = GetFrameMap(F);
const Type *ConcreteStackEntryTy = GetConcreteStackEntryType(F); const Type *ConcreteStackEntryTy = GetConcreteStackEntryType(F);
// Build the shadow stack entry at the very start of the function. // Build the shadow stack entry at the very start of the function.
BasicBlock::iterator IP = F.getEntryBlock().begin(); BasicBlock::iterator IP = F.getEntryBlock().begin();
IRBuilder<> AtEntry(IP->getParent(), IP); IRBuilder<> AtEntry(IP->getParent(), IP);
Instruction *StackEntry = AtEntry.CreateAlloca(ConcreteStackEntryTy, 0, Instruction *StackEntry = AtEntry.CreateAlloca(ConcreteStackEntryTy, 0,
"gc_frame"); "gc_frame");
while (isa<AllocaInst>(IP)) ++IP; while (isa<AllocaInst>(IP)) ++IP;
AtEntry.SetInsertPoint(IP->getParent(), IP); AtEntry.SetInsertPoint(IP->getParent(), IP);
// Initialize the map pointer and load the current head of the shadow stack. // Initialize the map pointer and load the current head of the shadow stack.
Instruction *CurrentHead = AtEntry.CreateLoad(Head, "gc_currhead"); Instruction *CurrentHead = AtEntry.CreateLoad(Head, "gc_currhead");
Instruction *EntryMapPtr = CreateGEP(AtEntry, StackEntry,0,1,"gc_frame.map"); Instruction *EntryMapPtr = CreateGEP(AtEntry, StackEntry,0,1,"gc_frame.map");
AtEntry.CreateStore(FrameMap, EntryMapPtr); AtEntry.CreateStore(FrameMap, EntryMapPtr);
// After all the allocas... // After all the allocas...
for (unsigned I = 0, E = Roots.size(); I != E; ++I) { for (unsigned I = 0, E = Roots.size(); I != E; ++I) {
// For each root, find the corresponding slot in the aggregate... // For each root, find the corresponding slot in the aggregate...
Value *SlotPtr = CreateGEP(AtEntry, StackEntry, 1 + I, "gc_root"); Value *SlotPtr = CreateGEP(AtEntry, StackEntry, 1 + I, "gc_root");
// And use it in lieu of the alloca. // And use it in lieu of the alloca.
AllocaInst *OriginalAlloca = Roots[I].second; AllocaInst *OriginalAlloca = Roots[I].second;
SlotPtr->takeName(OriginalAlloca); SlotPtr->takeName(OriginalAlloca);
OriginalAlloca->replaceAllUsesWith(SlotPtr); OriginalAlloca->replaceAllUsesWith(SlotPtr);
} }
// Move past the original stores inserted by GCStrategy::InitRoots. This isn't // Move past the original stores inserted by GCStrategy::InitRoots. This isn't
// really necessary (the collector would never see the intermediate state at // really necessary (the collector would never see the intermediate state at
// runtime), but it's nicer not to push the half-initialized entry onto the // runtime), but it's nicer not to push the half-initialized entry onto the
// shadow stack. // shadow stack.
while (isa<StoreInst>(IP)) ++IP; while (isa<StoreInst>(IP)) ++IP;
AtEntry.SetInsertPoint(IP->getParent(), IP); AtEntry.SetInsertPoint(IP->getParent(), IP);
// Push the entry onto the shadow stack. // Push the entry onto the shadow stack.
Instruction *EntryNextPtr = CreateGEP(AtEntry,StackEntry,0,0,"gc_frame.next"); Instruction *EntryNextPtr = CreateGEP(AtEntry,StackEntry,0,0,"gc_frame.next");
Instruction *NewHeadVal = CreateGEP(AtEntry,StackEntry, 0, "gc_newhead"); Instruction *NewHeadVal = CreateGEP(AtEntry,StackEntry, 0, "gc_newhead");
AtEntry.CreateStore(CurrentHead, EntryNextPtr); AtEntry.CreateStore(CurrentHead, EntryNextPtr);
AtEntry.CreateStore(NewHeadVal, Head); AtEntry.CreateStore(NewHeadVal, Head);
// For each instruction that escapes... // For each instruction that escapes...
EscapeEnumerator EE(F, "gc_cleanup"); EscapeEnumerator EE(F, "gc_cleanup");
while (IRBuilder<> *AtExit = EE.Next()) { while (IRBuilder<> *AtExit = EE.Next()) {
@ -424,7 +424,7 @@ bool ShadowStackGC::performCustomLowering(Function &F) {
Value *SavedHead = AtExit->CreateLoad(EntryNextPtr2, "gc_savedhead"); Value *SavedHead = AtExit->CreateLoad(EntryNextPtr2, "gc_savedhead");
AtExit->CreateStore(SavedHead, Head); AtExit->CreateStore(SavedHead, Head);
} }
// Delete the original allocas (which are no longer used) and the intrinsic // Delete the original allocas (which are no longer used) and the intrinsic
// calls (which are no longer valid). Doing this last avoids invalidating // calls (which are no longer valid). Doing this last avoids invalidating
// iterators. // iterators.
@ -432,7 +432,7 @@ bool ShadowStackGC::performCustomLowering(Function &F) {
Roots[I].first->eraseFromParent(); Roots[I].first->eraseFromParent();
Roots[I].second->eraseFromParent(); Roots[I].second->eraseFromParent();
} }
Roots.clear(); Roots.clear();
return true; return true;
} }

View File

@ -26,13 +26,13 @@ static cl::opt<const TargetMachineRegistry::entry*, false,
MArch("march", cl::desc("Architecture to generate assembly for:")); MArch("march", cl::desc("Architecture to generate assembly for:"));
static cl::opt<std::string> static cl::opt<std::string>
MCPU("mcpu", MCPU("mcpu",
cl::desc("Target a specific cpu type (-mcpu=help for details)"), cl::desc("Target a specific cpu type (-mcpu=help for details)"),
cl::value_desc("cpu-name"), cl::value_desc("cpu-name"),
cl::init("")); cl::init(""));
static cl::list<std::string> static cl::list<std::string>
MAttrs("mattr", MAttrs("mattr",
cl::CommaSeparated, cl::CommaSeparated,
cl::desc("Target specific attributes (-mattr=help for details)"), cl::desc("Target specific attributes (-mattr=help for details)"),
cl::value_desc("a1,+a2,-a3,...")); cl::value_desc("a1,+a2,-a3,..."));

View File

@ -53,7 +53,7 @@ OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"));
static cl::opt<bool> Force("f", cl::desc("Overwrite output files")); static cl::opt<bool> Force("f", cl::desc("Overwrite output files"));
static cl::opt<bool> Fast("fast", static cl::opt<bool> Fast("fast",
cl::desc("Generate code quickly, potentially sacrificing code quality")); cl::desc("Generate code quickly, potentially sacrificing code quality"));
static cl::opt<std::string> static cl::opt<std::string>
@ -64,13 +64,13 @@ static cl::opt<const TargetMachineRegistry::entry*, false,
MArch("march", cl::desc("Architecture to generate code for:")); MArch("march", cl::desc("Architecture to generate code for:"));
static cl::opt<std::string> static cl::opt<std::string>
MCPU("mcpu", MCPU("mcpu",
cl::desc("Target a specific cpu type (-mcpu=help for details)"), cl::desc("Target a specific cpu type (-mcpu=help for details)"),
cl::value_desc("cpu-name"), cl::value_desc("cpu-name"),
cl::init("")); cl::init(""));
static cl::list<std::string> static cl::list<std::string>
MAttrs("mattr", MAttrs("mattr",
cl::CommaSeparated, cl::CommaSeparated,
cl::desc("Target specific attributes (-mattr=help for details)"), cl::desc("Target specific attributes (-mattr=help for details)"),
cl::value_desc("a1,+a2,-a3,...")); cl::value_desc("a1,+a2,-a3,..."));
@ -134,14 +134,14 @@ static raw_ostream *GetOutputStream(const char *ProgName) {
return Out; return Out;
} }
if (InputFilename == "-") { if (InputFilename == "-") {
OutputFilename = "-"; OutputFilename = "-";
return &outs(); return &outs();
} }
OutputFilename = GetFileNameRoot(InputFilename); OutputFilename = GetFileNameRoot(InputFilename);
bool Binary = false; bool Binary = false;
switch (FileType) { switch (FileType) {
case TargetMachine::AssemblyFile: case TargetMachine::AssemblyFile:
@ -164,7 +164,7 @@ static raw_ostream *GetOutputStream(const char *ProgName) {
Binary = true; Binary = true;
break; break;
} }
if (!Force && std::ifstream(OutputFilename.c_str())) { if (!Force && std::ifstream(OutputFilename.c_str())) {
// If force is not specified, make sure not to overwrite a file! // If force is not specified, make sure not to overwrite a file!
std::cerr << ProgName << ": error opening '" << OutputFilename std::cerr << ProgName << ": error opening '" << OutputFilename
@ -172,11 +172,11 @@ static raw_ostream *GetOutputStream(const char *ProgName) {
<< "Use -f command line argument to force output\n"; << "Use -f command line argument to force output\n";
return 0; return 0;
} }
// Make sure that the Out file gets unlinked from the disk if we get a // Make sure that the Out file gets unlinked from the disk if we get a
// SIGINT // SIGINT
sys::RemoveFileOnSignal(sys::Path(OutputFilename)); sys::RemoveFileOnSignal(sys::Path(OutputFilename));
std::string error; std::string error;
raw_ostream *Out = new raw_fd_ostream(OutputFilename.c_str(), Binary, error); raw_ostream *Out = new raw_fd_ostream(OutputFilename.c_str(), Binary, error);
if (!error.empty()) { if (!error.empty()) {
@ -184,7 +184,7 @@ static raw_ostream *GetOutputStream(const char *ProgName) {
delete Out; delete Out;
return 0; return 0;
} }
return Out; return Out;
} }
@ -198,7 +198,7 @@ int main(int argc, char **argv) {
// Load the module to be compiled... // Load the module to be compiled...
std::string ErrorMessage; std::string ErrorMessage;
std::auto_ptr<Module> M; std::auto_ptr<Module> M;
std::auto_ptr<MemoryBuffer> Buffer( std::auto_ptr<MemoryBuffer> Buffer(
MemoryBuffer::getFileOrSTDIN(InputFilename, &ErrorMessage)); MemoryBuffer::getFileOrSTDIN(InputFilename, &ErrorMessage));
if (Buffer.get()) if (Buffer.get())
@ -209,11 +209,11 @@ int main(int argc, char **argv) {
return 1; return 1;
} }
Module &mod = *M.get(); Module &mod = *M.get();
// If we are supposed to override the target triple, do so now. // If we are supposed to override the target triple, do so now.
if (!TargetTriple.empty()) if (!TargetTriple.empty())
mod.setTargetTriple(TargetTriple); mod.setTargetTriple(TargetTriple);
// Allocate target machine. First, check whether the user has // Allocate target machine. First, check whether the user has
// explicitly specified an architecture to compile for. // explicitly specified an architecture to compile for.
if (MArch == 0) { if (MArch == 0) {
@ -236,7 +236,7 @@ int main(int argc, char **argv) {
Features.AddFeature(MAttrs[i]); Features.AddFeature(MAttrs[i]);
FeaturesStr = Features.getString(); FeaturesStr = Features.getString();
} }
std::auto_ptr<TargetMachine> target(MArch->CtorFn(mod, FeaturesStr)); std::auto_ptr<TargetMachine> target(MArch->CtorFn(mod, FeaturesStr));
assert(target.get() && "Could not allocate target machine!"); assert(target.get() && "Could not allocate target machine!");
TargetMachine &Target = *target.get(); TargetMachine &Target = *target.get();
@ -244,7 +244,7 @@ int main(int argc, char **argv) {
// Figure out where we are going to send the output... // Figure out where we are going to send the output...
raw_ostream *Out = GetOutputStream(argv[0]); raw_ostream *Out = GetOutputStream(argv[0]);
if (Out == 0) return 1; if (Out == 0) return 1;
// If this target requires addPassesToEmitWholeFile, do it now. This is // If this target requires addPassesToEmitWholeFile, do it now. This is
// used by strange things like the C backend. // used by strange things like the C backend.
if (Target.WantsWholeFile()) { if (Target.WantsWholeFile()) {
@ -252,7 +252,7 @@ int main(int argc, char **argv) {
PM.add(new TargetData(*Target.getTargetData())); PM.add(new TargetData(*Target.getTargetData()));
if (!NoVerify) if (!NoVerify)
PM.add(createVerifierPass()); PM.add(createVerifierPass());
// Ask the target to add backend passes as necessary. // Ask the target to add backend passes as necessary.
if (Target.addPassesToEmitWholeFile(PM, *Out, FileType, Fast)) { if (Target.addPassesToEmitWholeFile(PM, *Out, FileType, Fast)) {
std::cerr << argv[0] << ": target does not support generation of this" std::cerr << argv[0] << ": target does not support generation of this"
@ -268,12 +268,12 @@ int main(int argc, char **argv) {
ExistingModuleProvider Provider(M.release()); ExistingModuleProvider Provider(M.release());
FunctionPassManager Passes(&Provider); FunctionPassManager Passes(&Provider);
Passes.add(new TargetData(*Target.getTargetData())); Passes.add(new TargetData(*Target.getTargetData()));
#ifndef NDEBUG #ifndef NDEBUG
if (!NoVerify) if (!NoVerify)
Passes.add(createVerifierPass()); Passes.add(createVerifierPass());
#endif #endif
// Ask the target to add backend passes as necessary. // Ask the target to add backend passes as necessary.
MachineCodeEmitter *MCE = 0; MachineCodeEmitter *MCE = 0;
@ -306,18 +306,18 @@ int main(int argc, char **argv) {
sys::Path(OutputFilename).eraseFromDisk(); sys::Path(OutputFilename).eraseFromDisk();
return 1; return 1;
} }
Passes.doInitialization(); Passes.doInitialization();
// Run our queue of passes all at once now, efficiently. // Run our queue of passes all at once now, efficiently.
// TODO: this could lazily stream functions out of the module. // TODO: this could lazily stream functions out of the module.
for (Module::iterator I = mod.begin(), E = mod.end(); I != E; ++I) for (Module::iterator I = mod.begin(), E = mod.end(); I != E; ++I)
if (!I->isDeclaration()) if (!I->isDeclaration())
Passes.run(*I); Passes.run(*I);
Passes.doFinalization(); Passes.doFinalization();
} }
// Delete the ostream if it's not a stdout stream // Delete the ostream if it's not a stdout stream
if (Out != &outs()) delete Out; if (Out != &outs()) delete Out;