mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-05-01 13:37:55 +00:00
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:
parent
a10f15949d
commit
5c1799b293
@ -8,7 +8,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Defines a registry template for discovering pluggable modules.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_SUPPORT_REGISTRY_H
|
||||
@ -23,34 +23,34 @@ namespace llvm {
|
||||
class SimpleRegistryEntry {
|
||||
const char *Name, *Desc;
|
||||
T *(*Ctor)();
|
||||
|
||||
|
||||
public:
|
||||
SimpleRegistryEntry(const char *N, const char *D, T *(*C)())
|
||||
: Name(N), Desc(D), Ctor(C)
|
||||
{}
|
||||
|
||||
|
||||
const char *getName() const { return Name; }
|
||||
const char *getDesc() const { return Desc; }
|
||||
T *instantiate() const { return Ctor(); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/// Traits for registry entries. If using other than SimpleRegistryEntry, it
|
||||
/// is necessary to define an alternate traits class.
|
||||
template <typename T>
|
||||
class RegistryTraits {
|
||||
RegistryTraits(); // Do not implement.
|
||||
|
||||
|
||||
public:
|
||||
typedef SimpleRegistryEntry<T> entry;
|
||||
|
||||
|
||||
/// nameof/descof - Accessors for name and description of entries. These are
|
||||
// used to generate help for command-line options.
|
||||
static const char *nameof(const entry &Entry) { return Entry.getName(); }
|
||||
static const char *descof(const entry &Entry) { return Entry.getDesc(); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/// A global registry used in conjunction with static constructors to make
|
||||
/// pluggable components (like targets or garbage collectors) "just work" when
|
||||
/// linked with an executable.
|
||||
@ -59,37 +59,37 @@ namespace llvm {
|
||||
public:
|
||||
typedef U traits;
|
||||
typedef typename U::entry entry;
|
||||
|
||||
|
||||
class node;
|
||||
class listener;
|
||||
class iterator;
|
||||
|
||||
|
||||
private:
|
||||
Registry(); // Do not implement.
|
||||
|
||||
|
||||
static void Announce(const entry &E) {
|
||||
for (listener *Cur = ListenerHead; Cur; Cur = Cur->Next)
|
||||
Cur->registered(E);
|
||||
}
|
||||
|
||||
|
||||
friend class node;
|
||||
static node *Head, *Tail;
|
||||
|
||||
|
||||
friend class listener;
|
||||
static listener *ListenerHead, *ListenerTail;
|
||||
|
||||
|
||||
public:
|
||||
class iterator;
|
||||
|
||||
|
||||
|
||||
|
||||
/// Node in linked list of entries.
|
||||
///
|
||||
///
|
||||
class node {
|
||||
friend class iterator;
|
||||
|
||||
|
||||
node *Next;
|
||||
const entry& Val;
|
||||
|
||||
|
||||
public:
|
||||
node(const entry& V) : Next(0), Val(V) {
|
||||
if (Tail)
|
||||
@ -97,63 +97,63 @@ namespace llvm {
|
||||
else
|
||||
Head = this;
|
||||
Tail = this;
|
||||
|
||||
|
||||
Announce(V);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/// Iterators for registry entries.
|
||||
///
|
||||
///
|
||||
class iterator {
|
||||
const node *Cur;
|
||||
|
||||
|
||||
public:
|
||||
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; }
|
||||
iterator &operator++() { Cur = Cur->Next; return *this; }
|
||||
const entry &operator*() const { return Cur->Val; }
|
||||
const entry *operator->() const { return &Cur->Val; }
|
||||
};
|
||||
|
||||
|
||||
static iterator begin() { return iterator(Head); }
|
||||
static iterator end() { return iterator(0); }
|
||||
|
||||
|
||||
|
||||
|
||||
/// Abstract base class for registry listeners, which are informed when new
|
||||
/// entries are added to the registry. Simply subclass and instantiate:
|
||||
///
|
||||
///
|
||||
/// class CollectorPrinter : public Registry<Collector>::listener {
|
||||
/// protected:
|
||||
/// void registered(const Registry<Collector>::entry &e) {
|
||||
/// cerr << "collector now available: " << e->getName() << "\n";
|
||||
/// }
|
||||
///
|
||||
///
|
||||
/// public:
|
||||
/// CollectorPrinter() { init(); } // Print those already registered.
|
||||
/// };
|
||||
///
|
||||
///
|
||||
/// CollectorPrinter Printer;
|
||||
///
|
||||
///
|
||||
class listener {
|
||||
listener *Prev, *Next;
|
||||
|
||||
|
||||
friend void Registry::Announce(const entry &E);
|
||||
|
||||
|
||||
protected:
|
||||
/// Called when an entry is added to the registry.
|
||||
///
|
||||
///
|
||||
virtual void registered(const entry &) = 0;
|
||||
|
||||
|
||||
/// Calls 'registered' for each pre-existing entry.
|
||||
///
|
||||
///
|
||||
void init() {
|
||||
for (iterator I = begin(), E = end(); I != E; ++I)
|
||||
registered(*I);
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
listener() : Prev(ListenerTail), Next(0) {
|
||||
if (Prev)
|
||||
@ -162,7 +162,7 @@ namespace llvm {
|
||||
ListenerHead = this;
|
||||
ListenerTail = this;
|
||||
}
|
||||
|
||||
|
||||
virtual ~listener() {
|
||||
if (Next)
|
||||
Next->Prev = Prev;
|
||||
@ -174,79 +174,79 @@ namespace llvm {
|
||||
ListenerHead = Next;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/// A static registration template. Use like such:
|
||||
///
|
||||
///
|
||||
/// Registry<Collector>::Add<FancyGC>
|
||||
/// X("fancy-gc", "Newfangled garbage collector.");
|
||||
///
|
||||
///
|
||||
/// Use of this template requires that:
|
||||
///
|
||||
///
|
||||
/// 1. The registered subclass has a default constructor.
|
||||
//
|
||||
//
|
||||
/// 2. The registry entry type has a constructor compatible with this
|
||||
/// signature:
|
||||
///
|
||||
///
|
||||
/// entry(const char *Name, const char *ShortDesc, T *(*Ctor)());
|
||||
///
|
||||
///
|
||||
/// If you have more elaborate requirements, then copy and modify.
|
||||
///
|
||||
///
|
||||
template <typename V>
|
||||
class Add {
|
||||
entry Entry;
|
||||
node Node;
|
||||
|
||||
|
||||
static T *CtorFn() { return new V(); }
|
||||
|
||||
|
||||
public:
|
||||
Add(const char *Name, const char *Desc)
|
||||
: Entry(Name, Desc, CtorFn), Node(Entry) {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/// A command-line parser for a registry. Use like such:
|
||||
///
|
||||
///
|
||||
/// static cl::opt<Registry<Collector>::entry, false,
|
||||
/// Registry<Collector>::Parser>
|
||||
/// GCOpt("gc", cl::desc("Garbage collector to use."),
|
||||
/// cl::value_desc());
|
||||
///
|
||||
///
|
||||
/// To make use of the value:
|
||||
///
|
||||
///
|
||||
/// Collector *TheCollector = GCOpt->instantiate();
|
||||
///
|
||||
///
|
||||
class Parser : public cl::parser<const typename U::entry*>, public listener{
|
||||
typedef U traits;
|
||||
typedef typename U::entry entry;
|
||||
|
||||
|
||||
protected:
|
||||
void registered(const entry &E) {
|
||||
addLiteralOption(traits::nameof(E), &E, traits::descof(E));
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
void initialize(cl::Option &O) {
|
||||
listener::init();
|
||||
cl::parser<const typename U::entry*>::initialize(O);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename T, typename U>
|
||||
typename Registry<T,U>::node *Registry<T,U>::Head;
|
||||
|
||||
|
||||
template <typename T, typename U>
|
||||
typename Registry<T,U>::node *Registry<T,U>::Tail;
|
||||
|
||||
|
||||
template <typename T, typename U>
|
||||
typename Registry<T,U>::listener *Registry<T,U>::ListenerHead;
|
||||
|
||||
|
||||
template <typename T, typename U>
|
||||
typename Registry<T,U>::listener *Registry<T,U>::ListenerTail;
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -22,14 +22,14 @@
|
||||
namespace llvm {
|
||||
class Module;
|
||||
class TargetMachine;
|
||||
|
||||
|
||||
struct TargetMachineRegistryEntry {
|
||||
const char *Name;
|
||||
const char *ShortDesc;
|
||||
TargetMachine *(*CtorFn)(const Module &, const std::string &);
|
||||
unsigned (*ModuleMatchQualityFn)(const Module &M);
|
||||
unsigned (*JITMatchQualityFn)();
|
||||
|
||||
|
||||
public:
|
||||
TargetMachineRegistryEntry(const char *N, const char *SD,
|
||||
TargetMachine *(*CF)(const Module &, const std::string &),
|
||||
@ -38,12 +38,12 @@ namespace llvm {
|
||||
: Name(N), ShortDesc(SD), CtorFn(CF), ModuleMatchQualityFn(MMF),
|
||||
JITMatchQualityFn(JMF) {}
|
||||
};
|
||||
|
||||
|
||||
template<>
|
||||
class RegistryTraits<TargetMachine> {
|
||||
public:
|
||||
typedef TargetMachineRegistryEntry entry;
|
||||
|
||||
|
||||
static const char *nameof(const entry &Entry) { return Entry.Name; }
|
||||
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
|
||||
/// instance of this and implement the static methods described in the
|
||||
/// TargetMachine comments.
|
||||
/// The type 'TargetMachineImpl' should provide a constructor with two
|
||||
/// The type 'TargetMachineImpl' should provide a constructor with two
|
||||
/// parameters:
|
||||
/// - 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.
|
||||
|
||||
|
||||
template<class TargetMachineImpl>
|
||||
struct RegisterTarget {
|
||||
RegisterTarget(const char *Name, const char *ShortDesc)
|
||||
@ -85,7 +85,7 @@ namespace llvm {
|
||||
private:
|
||||
TargetMachineRegistry::entry Entry;
|
||||
TargetMachineRegistry::node Node;
|
||||
|
||||
|
||||
static TargetMachine *Allocator(const Module &M, const std::string &FS) {
|
||||
return new TargetMachineImpl(M, FS);
|
||||
}
|
||||
|
@ -10,7 +10,7 @@
|
||||
// This file implements printing the assembly code for an Ocaml frametable.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
#include "llvm/CodeGen/GCs.h"
|
||||
#include "llvm/CodeGen/AsmPrinter.h"
|
||||
#include "llvm/CodeGen/GCMetadataPrinter.h"
|
||||
@ -28,11 +28,11 @@ namespace {
|
||||
public:
|
||||
void beginAssembly(raw_ostream &OS, AsmPrinter &AP,
|
||||
const TargetAsmInfo &TAI);
|
||||
|
||||
|
||||
void finishAssembly(raw_ostream &OS, AsmPrinter &AP,
|
||||
const TargetAsmInfo &TAI);
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
static GCMetadataPrinterRegistry::Add<OcamlGCMetadataPrinter>
|
||||
@ -43,7 +43,7 @@ void llvm::linkOcamlGCPrinter() { }
|
||||
static void EmitCamlGlobal(const Module &M, raw_ostream &OS, AsmPrinter &AP,
|
||||
const TargetAsmInfo &TAI, const char *Id) {
|
||||
const std::string &MId = M.getModuleIdentifier();
|
||||
|
||||
|
||||
std::string Mangled;
|
||||
Mangled += TAI.getGlobalPrefix();
|
||||
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 += "__";
|
||||
Mangled += Id;
|
||||
|
||||
|
||||
// Capitalize the first letter of the module name.
|
||||
Mangled[Letter] = toupper(Mangled[Letter]);
|
||||
|
||||
|
||||
if (const char *GlobalDirective = TAI.getGlobalDirective())
|
||||
OS << GlobalDirective << Mangled << "\n";
|
||||
OS << Mangled << ":\n";
|
||||
@ -64,13 +64,13 @@ void OcamlGCMetadataPrinter::beginAssembly(raw_ostream &OS, AsmPrinter &AP,
|
||||
const TargetAsmInfo &TAI) {
|
||||
AP.SwitchToSection(TAI.getTextSection());
|
||||
EmitCamlGlobal(getModule(), OS, AP, TAI, "code_begin");
|
||||
|
||||
|
||||
AP.SwitchToSection(TAI.getDataSection());
|
||||
EmitCamlGlobal(getModule(), OS, AP, TAI, "data_begin");
|
||||
}
|
||||
|
||||
/// emitAssembly - Print the frametable. The ocaml frametable format is thus:
|
||||
///
|
||||
///
|
||||
/// extern "C" struct align(sizeof(intptr_t)) {
|
||||
/// uint16_t NumDescriptors;
|
||||
/// struct align(sizeof(intptr_t)) {
|
||||
@ -80,11 +80,11 @@ void OcamlGCMetadataPrinter::beginAssembly(raw_ostream &OS, AsmPrinter &AP,
|
||||
/// uint16_t LiveOffsets[NumLiveOffsets];
|
||||
/// } Descriptors[NumDescriptors];
|
||||
/// } caml${module}__frametable;
|
||||
///
|
||||
///
|
||||
/// Note that this precludes programs from stack frames larger than 64K
|
||||
/// (FrameSize and LiveOffsets would overflow). FrameTablePrinter will abort if
|
||||
/// either condition is detected in a function which uses the GC.
|
||||
///
|
||||
///
|
||||
void OcamlGCMetadataPrinter::finishAssembly(raw_ostream &OS, AsmPrinter &AP,
|
||||
const TargetAsmInfo &TAI) {
|
||||
const char *AddressDirective;
|
||||
@ -99,19 +99,19 @@ void OcamlGCMetadataPrinter::finishAssembly(raw_ostream &OS, AsmPrinter &AP,
|
||||
|
||||
AP.SwitchToSection(TAI.getTextSection());
|
||||
EmitCamlGlobal(getModule(), OS, AP, TAI, "code_end");
|
||||
|
||||
|
||||
AP.SwitchToSection(TAI.getDataSection());
|
||||
EmitCamlGlobal(getModule(), OS, AP, TAI, "data_end");
|
||||
|
||||
|
||||
OS << AddressDirective << 0; // FIXME: Why does ocaml emit this??
|
||||
AP.EOL();
|
||||
|
||||
|
||||
AP.SwitchToSection(TAI.getDataSection());
|
||||
EmitCamlGlobal(getModule(), OS, AP, TAI, "frametable");
|
||||
|
||||
|
||||
for (iterator I = begin(), IE = end(); I != IE; ++I) {
|
||||
GCFunctionInfo &FI = **I;
|
||||
|
||||
|
||||
uint64_t FrameSize = FI.getFrameSize();
|
||||
if (FrameSize >= 1<<16) {
|
||||
cerr << "Function '" << FI.getFunction().getNameStart()
|
||||
@ -120,10 +120,10 @@ void OcamlGCMetadataPrinter::finishAssembly(raw_ostream &OS, AsmPrinter &AP,
|
||||
cerr << "(" << uintptr_t(&FI) << ")\n";
|
||||
abort(); // Very rude!
|
||||
}
|
||||
|
||||
|
||||
OS << "\t" << TAI.getCommentString() << " live roots for "
|
||||
<< FI.getFunction().getNameStart() << "\n";
|
||||
|
||||
|
||||
for (GCFunctionInfo::iterator J = FI.begin(), JE = FI.end(); J != JE; ++J) {
|
||||
size_t LiveCount = FI.live_size(J);
|
||||
if (LiveCount >= 1<<16) {
|
||||
@ -132,27 +132,27 @@ void OcamlGCMetadataPrinter::finishAssembly(raw_ostream &OS, AsmPrinter &AP,
|
||||
<< "Live root count " << LiveCount << " >= 65536.\n";
|
||||
abort(); // Very rude!
|
||||
}
|
||||
|
||||
|
||||
OS << AddressDirective
|
||||
<< TAI.getPrivateGlobalPrefix() << "label" << J->Num;
|
||||
AP.EOL("call return address");
|
||||
|
||||
|
||||
AP.EmitInt16(FrameSize);
|
||||
AP.EOL("stack frame size");
|
||||
|
||||
|
||||
AP.EmitInt16(LiveCount);
|
||||
AP.EOL("live root count");
|
||||
|
||||
|
||||
for (GCFunctionInfo::live_iterator K = FI.live_begin(J),
|
||||
KE = FI.live_end(J); K != KE; ++K) {
|
||||
assert(K->StackOffset < 1<<16 &&
|
||||
"GC root stack offset is outside of fixed stack frame and out "
|
||||
"of range for ocaml GC!");
|
||||
|
||||
|
||||
OS << "\t.word\t" << K->StackOffset;
|
||||
AP.EOL("stack offset");
|
||||
}
|
||||
|
||||
|
||||
AP.EmitAlignment(AddressAlignLog);
|
||||
}
|
||||
}
|
||||
|
@ -9,11 +9,11 @@
|
||||
//
|
||||
// This file implements lowering for the llvm.gc* intrinsics compatible with
|
||||
// Objective Caml 3.10.0, which uses a liveness-accurate static stack map.
|
||||
//
|
||||
//
|
||||
// The frametable emitter is in OcamlGCPrinter.cpp.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
#include "llvm/CodeGen/GCs.h"
|
||||
#include "llvm/CodeGen/GCStrategy.h"
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -36,26 +36,26 @@
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
class VISIBILITY_HIDDEN ShadowStackGC : public GCStrategy {
|
||||
/// RootChain - This is the global linked-list that contains the chain of GC
|
||||
/// roots.
|
||||
GlobalVariable *Head;
|
||||
|
||||
|
||||
/// StackEntryTy - Abstract type of a link in the shadow stack.
|
||||
///
|
||||
///
|
||||
const StructType *StackEntryTy;
|
||||
|
||||
|
||||
/// Roots - GC roots in the current function. Each is a pair of the
|
||||
/// intrinsic call and its corresponding alloca.
|
||||
std::vector<std::pair<CallInst*,AllocaInst*> > Roots;
|
||||
|
||||
|
||||
public:
|
||||
ShadowStackGC();
|
||||
|
||||
|
||||
bool initializeCustomLowering(Module &M);
|
||||
bool performCustomLowering(Function &F);
|
||||
|
||||
|
||||
private:
|
||||
bool IsNullValue(Value *V);
|
||||
Constant *GetFrameMap(Function &F);
|
||||
@ -68,58 +68,58 @@ namespace {
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
static GCRegistry::Add<ShadowStackGC>
|
||||
X("shadow-stack", "Very portable GC for uncooperative code generators");
|
||||
|
||||
|
||||
namespace {
|
||||
/// EscapeEnumerator - This is a little algorithm to find all escape points
|
||||
/// from a function so that "finally"-style code can be inserted. In addition
|
||||
/// to finding the existing return and unwind instructions, it also (if
|
||||
/// necessary) transforms any call instructions into invokes and sends them to
|
||||
/// a landing pad.
|
||||
///
|
||||
///
|
||||
/// 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.
|
||||
class VISIBILITY_HIDDEN EscapeEnumerator {
|
||||
Function &F;
|
||||
const char *CleanupBBName;
|
||||
|
||||
|
||||
// State.
|
||||
int State;
|
||||
Function::iterator StateBB, StateE;
|
||||
IRBuilder<> Builder;
|
||||
|
||||
|
||||
public:
|
||||
EscapeEnumerator(Function &F, const char *N = "cleanup")
|
||||
: F(F), CleanupBBName(N), State(0) {}
|
||||
|
||||
|
||||
IRBuilder<> *Next() {
|
||||
switch (State) {
|
||||
default:
|
||||
return 0;
|
||||
|
||||
|
||||
case 0:
|
||||
StateBB = F.begin();
|
||||
StateE = F.end();
|
||||
State = 1;
|
||||
|
||||
|
||||
case 1:
|
||||
// Find all 'return' and 'unwind' instructions.
|
||||
while (StateBB != StateE) {
|
||||
BasicBlock *CurBB = StateBB++;
|
||||
|
||||
|
||||
// Branches and invokes do not escape, only unwind and return do.
|
||||
TerminatorInst *TI = CurBB->getTerminator();
|
||||
if (!isa<UnwindInst>(TI) && !isa<ReturnInst>(TI))
|
||||
continue;
|
||||
|
||||
|
||||
Builder.SetInsertPoint(TI->getParent(), TI);
|
||||
return &Builder;
|
||||
}
|
||||
|
||||
|
||||
State = 2;
|
||||
|
||||
|
||||
// Find all 'call' instructions.
|
||||
SmallVector<Instruction*,16> Calls;
|
||||
for (Function::iterator BB = F.begin(),
|
||||
@ -130,33 +130,33 @@ namespace {
|
||||
if (!CI->getCalledFunction() ||
|
||||
!CI->getCalledFunction()->getIntrinsicID())
|
||||
Calls.push_back(CI);
|
||||
|
||||
|
||||
if (Calls.empty())
|
||||
return 0;
|
||||
|
||||
|
||||
// Create a cleanup block.
|
||||
BasicBlock *CleanupBB = BasicBlock::Create(CleanupBBName, &F);
|
||||
UnwindInst *UI = new UnwindInst(CleanupBB);
|
||||
|
||||
|
||||
// Transform the 'call' instructions into 'invoke's branching to the
|
||||
// cleanup block. Go in reverse order to make prettier BB names.
|
||||
SmallVector<Value*,16> Args;
|
||||
for (unsigned I = Calls.size(); I != 0; ) {
|
||||
CallInst *CI = cast<CallInst>(Calls[--I]);
|
||||
|
||||
|
||||
// Split the basic block containing the function call.
|
||||
BasicBlock *CallBB = CI->getParent();
|
||||
BasicBlock *NewBB =
|
||||
CallBB->splitBasicBlock(CI, CallBB->getName() + ".cont");
|
||||
|
||||
|
||||
// Remove the unconditional branch inserted at the end of CallBB.
|
||||
CallBB->getInstList().pop_back();
|
||||
NewBB->getInstList().remove(CI);
|
||||
|
||||
|
||||
// Create a new invoke instruction.
|
||||
Args.clear();
|
||||
Args.append(CI->op_begin() + 1, CI->op_end());
|
||||
|
||||
|
||||
InvokeInst *II = InvokeInst::Create(CI->getOperand(0),
|
||||
NewBB, CleanupBB,
|
||||
Args.begin(), Args.end(),
|
||||
@ -166,7 +166,7 @@ namespace {
|
||||
CI->replaceAllUsesWith(II);
|
||||
delete CI;
|
||||
}
|
||||
|
||||
|
||||
Builder.SetInsertPoint(UI->getParent(), UI);
|
||||
return &Builder;
|
||||
}
|
||||
@ -185,9 +185,9 @@ ShadowStackGC::ShadowStackGC() : Head(0), StackEntryTy(0) {
|
||||
|
||||
Constant *ShadowStackGC::GetFrameMap(Function &F) {
|
||||
// doInitialization creates the abstract type of this value.
|
||||
|
||||
|
||||
Type *VoidPtr = PointerType::getUnqual(Type::Int8Ty);
|
||||
|
||||
|
||||
// Truncate the ShadowStackDescriptor if some metadata is null.
|
||||
unsigned NumMeta = 0;
|
||||
SmallVector<Constant*,16> Metadata;
|
||||
@ -197,33 +197,33 @@ Constant *ShadowStackGC::GetFrameMap(Function &F) {
|
||||
NumMeta = I + 1;
|
||||
Metadata.push_back(ConstantExpr::getBitCast(C, VoidPtr));
|
||||
}
|
||||
|
||||
|
||||
Constant *BaseElts[] = {
|
||||
ConstantInt::get(Type::Int32Ty, Roots.size(), false),
|
||||
ConstantInt::get(Type::Int32Ty, NumMeta, false),
|
||||
};
|
||||
|
||||
|
||||
Constant *DescriptorElts[] = {
|
||||
ConstantStruct::get(BaseElts, 2),
|
||||
ConstantArray::get(ArrayType::get(VoidPtr, NumMeta),
|
||||
Metadata.begin(), NumMeta)
|
||||
};
|
||||
|
||||
|
||||
Constant *FrameMap = ConstantStruct::get(DescriptorElts, 2);
|
||||
|
||||
|
||||
std::string TypeName("gc_map.");
|
||||
TypeName += utostr(NumMeta);
|
||||
F.getParent()->addTypeName(TypeName, FrameMap->getType());
|
||||
|
||||
|
||||
// FIXME: Is this actually dangerous as WritingAnLLVMPass.html claims? Seems
|
||||
// that, short of multithreaded LLVM, it should be safe; all that is
|
||||
// necessary is that a simple Module::iterator loop not be invalidated.
|
||||
// Appending to the GlobalVariable list is safe in that sense.
|
||||
//
|
||||
//
|
||||
// All of the output passes emit globals last. The ExecutionEngine
|
||||
// explicitly supports adding globals to the module after
|
||||
// initialization.
|
||||
//
|
||||
//
|
||||
// Still, if it isn't deemed acceptable, then this transformation needs
|
||||
// to be a ModulePass (which means it cannot be in the 'llc' pipeline
|
||||
// (which uses a FunctionPassManager (which segfaults (not asserts) if
|
||||
@ -232,7 +232,7 @@ Constant *ShadowStackGC::GetFrameMap(Function &F) {
|
||||
GlobalVariable::InternalLinkage,
|
||||
FrameMap, "__gc_" + F.getName(),
|
||||
F.getParent());
|
||||
|
||||
|
||||
Constant *GEPIndices[2] = { ConstantInt::get(Type::Int32Ty, 0),
|
||||
ConstantInt::get(Type::Int32Ty, 0) };
|
||||
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++)
|
||||
EltTys.push_back(Roots[I].second->getAllocatedType());
|
||||
Type *Ty = StructType::get(EltTys);
|
||||
|
||||
|
||||
std::string TypeName("gc_stackentry.");
|
||||
TypeName += F.getName();
|
||||
F.getParent()->addTypeName(TypeName, Ty);
|
||||
|
||||
|
||||
return Ty;
|
||||
}
|
||||
|
||||
@ -267,25 +267,25 @@ bool ShadowStackGC::initializeCustomLowering(Module &M) {
|
||||
StructType *FrameMapTy = StructType::get(EltTys);
|
||||
M.addTypeName("gc_map", FrameMapTy);
|
||||
PointerType *FrameMapPtrTy = PointerType::getUnqual(FrameMapTy);
|
||||
|
||||
|
||||
// struct StackEntry {
|
||||
// ShadowStackEntry *Next; // Caller's stack entry.
|
||||
// FrameMap *Map; // Pointer to constant FrameMap.
|
||||
// void *Roots[]; // Stack roots (in-place array, so we pretend).
|
||||
// };
|
||||
OpaqueType *RecursiveTy = OpaqueType::get();
|
||||
|
||||
|
||||
EltTys.clear();
|
||||
EltTys.push_back(PointerType::getUnqual(RecursiveTy));
|
||||
EltTys.push_back(FrameMapPtrTy);
|
||||
PATypeHolder LinkTyH = StructType::get(EltTys);
|
||||
|
||||
|
||||
RecursiveTy->refineAbstractTypeTo(LinkTyH.get());
|
||||
StackEntryTy = cast<StructType>(LinkTyH.get());
|
||||
const PointerType *StackEntryPtrTy = PointerType::getUnqual(StackEntryTy);
|
||||
M.addTypeName("gc_stackentry", LinkTyH.get()); // FIXME: Is this safe from
|
||||
// a FunctionPass?
|
||||
|
||||
|
||||
// Get the root chain if it already exists.
|
||||
Head = M.getGlobalVariable("llvm_gc_root_chain");
|
||||
if (!Head) {
|
||||
@ -299,7 +299,7 @@ bool ShadowStackGC::initializeCustomLowering(Module &M) {
|
||||
Head->setInitializer(Constant::getNullValue(StackEntryPtrTy));
|
||||
Head->setLinkage(GlobalValue::LinkOnceLinkage);
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -313,11 +313,11 @@ void ShadowStackGC::CollectRoots(Function &F) {
|
||||
// FIXME: Account for original alignment. Could fragment the root array.
|
||||
// Approach 1: Null initialize empty slots at runtime. Yuck.
|
||||
// Approach 2: Emit a map of the array instead of just a count.
|
||||
|
||||
|
||||
assert(Roots.empty() && "Not cleaned up?");
|
||||
|
||||
|
||||
SmallVector<std::pair<CallInst*,AllocaInst*>,16> MetaRoots;
|
||||
|
||||
|
||||
for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
|
||||
for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E;)
|
||||
if (IntrinsicInst *CI = dyn_cast<IntrinsicInst>(II++))
|
||||
@ -330,7 +330,7 @@ void ShadowStackGC::CollectRoots(Function &F) {
|
||||
else
|
||||
MetaRoots.push_back(Pair);
|
||||
}
|
||||
|
||||
|
||||
// Number roots with metadata (usually empty) at the beginning, so that the
|
||||
// FrameMap::Meta array can be elided.
|
||||
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, Idx2) };
|
||||
Value* Val = B.CreateGEP(BasePtr, Indices, Indices + 3, Name);
|
||||
|
||||
|
||||
assert(isa<GetElementPtrInst>(Val) && "Unexpected folded constant");
|
||||
|
||||
|
||||
return dyn_cast<GetElementPtrInst>(Val);
|
||||
}
|
||||
|
||||
@ -355,7 +355,7 @@ ShadowStackGC::CreateGEP(IRBuilder<> &B, Value *BasePtr,
|
||||
Value *Indices[] = { ConstantInt::get(Type::Int32Ty, 0),
|
||||
ConstantInt::get(Type::Int32Ty, Idx) };
|
||||
Value *Val = B.CreateGEP(BasePtr, Indices, Indices + 2, Name);
|
||||
|
||||
|
||||
assert(isa<GetElementPtrInst>(Val) && "Unexpected folded constant");
|
||||
|
||||
return dyn_cast<GetElementPtrInst>(Val);
|
||||
@ -365,55 +365,55 @@ ShadowStackGC::CreateGEP(IRBuilder<> &B, Value *BasePtr,
|
||||
bool ShadowStackGC::performCustomLowering(Function &F) {
|
||||
// Find calls to llvm.gcroot.
|
||||
CollectRoots(F);
|
||||
|
||||
|
||||
// If there are no roots in this function, then there is no need to add a
|
||||
// stack map entry for it.
|
||||
if (Roots.empty())
|
||||
return false;
|
||||
|
||||
|
||||
// Build the constant map and figure the type of the shadow stack entry.
|
||||
Value *FrameMap = GetFrameMap(F);
|
||||
const Type *ConcreteStackEntryTy = GetConcreteStackEntryType(F);
|
||||
|
||||
|
||||
// Build the shadow stack entry at the very start of the function.
|
||||
BasicBlock::iterator IP = F.getEntryBlock().begin();
|
||||
IRBuilder<> AtEntry(IP->getParent(), IP);
|
||||
|
||||
|
||||
Instruction *StackEntry = AtEntry.CreateAlloca(ConcreteStackEntryTy, 0,
|
||||
"gc_frame");
|
||||
|
||||
|
||||
while (isa<AllocaInst>(IP)) ++IP;
|
||||
AtEntry.SetInsertPoint(IP->getParent(), IP);
|
||||
|
||||
|
||||
// Initialize the map pointer and load the current head of the shadow stack.
|
||||
Instruction *CurrentHead = AtEntry.CreateLoad(Head, "gc_currhead");
|
||||
Instruction *EntryMapPtr = CreateGEP(AtEntry, StackEntry,0,1,"gc_frame.map");
|
||||
AtEntry.CreateStore(FrameMap, EntryMapPtr);
|
||||
|
||||
|
||||
// After all the allocas...
|
||||
for (unsigned I = 0, E = Roots.size(); I != E; ++I) {
|
||||
// For each root, find the corresponding slot in the aggregate...
|
||||
Value *SlotPtr = CreateGEP(AtEntry, StackEntry, 1 + I, "gc_root");
|
||||
|
||||
|
||||
// And use it in lieu of the alloca.
|
||||
AllocaInst *OriginalAlloca = Roots[I].second;
|
||||
SlotPtr->takeName(OriginalAlloca);
|
||||
OriginalAlloca->replaceAllUsesWith(SlotPtr);
|
||||
}
|
||||
|
||||
|
||||
// Move past the original stores inserted by GCStrategy::InitRoots. This isn't
|
||||
// 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
|
||||
// shadow stack.
|
||||
while (isa<StoreInst>(IP)) ++IP;
|
||||
AtEntry.SetInsertPoint(IP->getParent(), IP);
|
||||
|
||||
|
||||
// Push the entry onto the shadow stack.
|
||||
Instruction *EntryNextPtr = CreateGEP(AtEntry,StackEntry,0,0,"gc_frame.next");
|
||||
Instruction *NewHeadVal = CreateGEP(AtEntry,StackEntry, 0, "gc_newhead");
|
||||
AtEntry.CreateStore(CurrentHead, EntryNextPtr);
|
||||
AtEntry.CreateStore(NewHeadVal, Head);
|
||||
|
||||
|
||||
// For each instruction that escapes...
|
||||
EscapeEnumerator EE(F, "gc_cleanup");
|
||||
while (IRBuilder<> *AtExit = EE.Next()) {
|
||||
@ -424,7 +424,7 @@ bool ShadowStackGC::performCustomLowering(Function &F) {
|
||||
Value *SavedHead = AtExit->CreateLoad(EntryNextPtr2, "gc_savedhead");
|
||||
AtExit->CreateStore(SavedHead, Head);
|
||||
}
|
||||
|
||||
|
||||
// Delete the original allocas (which are no longer used) and the intrinsic
|
||||
// calls (which are no longer valid). Doing this last avoids invalidating
|
||||
// iterators.
|
||||
@ -432,7 +432,7 @@ bool ShadowStackGC::performCustomLowering(Function &F) {
|
||||
Roots[I].first->eraseFromParent();
|
||||
Roots[I].second->eraseFromParent();
|
||||
}
|
||||
|
||||
|
||||
Roots.clear();
|
||||
return true;
|
||||
}
|
||||
|
@ -26,13 +26,13 @@ static cl::opt<const TargetMachineRegistry::entry*, false,
|
||||
MArch("march", cl::desc("Architecture to generate assembly for:"));
|
||||
|
||||
static cl::opt<std::string>
|
||||
MCPU("mcpu",
|
||||
MCPU("mcpu",
|
||||
cl::desc("Target a specific cpu type (-mcpu=help for details)"),
|
||||
cl::value_desc("cpu-name"),
|
||||
cl::init(""));
|
||||
|
||||
static cl::list<std::string>
|
||||
MAttrs("mattr",
|
||||
MAttrs("mattr",
|
||||
cl::CommaSeparated,
|
||||
cl::desc("Target specific attributes (-mattr=help for details)"),
|
||||
cl::value_desc("a1,+a2,-a3,..."));
|
||||
|
@ -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> Fast("fast",
|
||||
static cl::opt<bool> Fast("fast",
|
||||
cl::desc("Generate code quickly, potentially sacrificing code quality"));
|
||||
|
||||
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:"));
|
||||
|
||||
static cl::opt<std::string>
|
||||
MCPU("mcpu",
|
||||
MCPU("mcpu",
|
||||
cl::desc("Target a specific cpu type (-mcpu=help for details)"),
|
||||
cl::value_desc("cpu-name"),
|
||||
cl::init(""));
|
||||
|
||||
static cl::list<std::string>
|
||||
MAttrs("mattr",
|
||||
MAttrs("mattr",
|
||||
cl::CommaSeparated,
|
||||
cl::desc("Target specific attributes (-mattr=help for details)"),
|
||||
cl::value_desc("a1,+a2,-a3,..."));
|
||||
@ -134,14 +134,14 @@ static raw_ostream *GetOutputStream(const char *ProgName) {
|
||||
|
||||
return Out;
|
||||
}
|
||||
|
||||
|
||||
if (InputFilename == "-") {
|
||||
OutputFilename = "-";
|
||||
return &outs();
|
||||
}
|
||||
|
||||
OutputFilename = GetFileNameRoot(InputFilename);
|
||||
|
||||
|
||||
bool Binary = false;
|
||||
switch (FileType) {
|
||||
case TargetMachine::AssemblyFile:
|
||||
@ -164,7 +164,7 @@ static raw_ostream *GetOutputStream(const char *ProgName) {
|
||||
Binary = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (!Force && std::ifstream(OutputFilename.c_str())) {
|
||||
// If force is not specified, make sure not to overwrite a file!
|
||||
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";
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Make sure that the Out file gets unlinked from the disk if we get a
|
||||
// SIGINT
|
||||
sys::RemoveFileOnSignal(sys::Path(OutputFilename));
|
||||
|
||||
|
||||
std::string error;
|
||||
raw_ostream *Out = new raw_fd_ostream(OutputFilename.c_str(), Binary, error);
|
||||
if (!error.empty()) {
|
||||
@ -184,7 +184,7 @@ static raw_ostream *GetOutputStream(const char *ProgName) {
|
||||
delete Out;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
return Out;
|
||||
}
|
||||
|
||||
@ -198,7 +198,7 @@ int main(int argc, char **argv) {
|
||||
// Load the module to be compiled...
|
||||
std::string ErrorMessage;
|
||||
std::auto_ptr<Module> M;
|
||||
|
||||
|
||||
std::auto_ptr<MemoryBuffer> Buffer(
|
||||
MemoryBuffer::getFileOrSTDIN(InputFilename, &ErrorMessage));
|
||||
if (Buffer.get())
|
||||
@ -209,11 +209,11 @@ int main(int argc, char **argv) {
|
||||
return 1;
|
||||
}
|
||||
Module &mod = *M.get();
|
||||
|
||||
|
||||
// If we are supposed to override the target triple, do so now.
|
||||
if (!TargetTriple.empty())
|
||||
mod.setTargetTriple(TargetTriple);
|
||||
|
||||
|
||||
// Allocate target machine. First, check whether the user has
|
||||
// explicitly specified an architecture to compile for.
|
||||
if (MArch == 0) {
|
||||
@ -236,7 +236,7 @@ int main(int argc, char **argv) {
|
||||
Features.AddFeature(MAttrs[i]);
|
||||
FeaturesStr = Features.getString();
|
||||
}
|
||||
|
||||
|
||||
std::auto_ptr<TargetMachine> target(MArch->CtorFn(mod, FeaturesStr));
|
||||
assert(target.get() && "Could not allocate target machine!");
|
||||
TargetMachine &Target = *target.get();
|
||||
@ -244,7 +244,7 @@ int main(int argc, char **argv) {
|
||||
// Figure out where we are going to send the output...
|
||||
raw_ostream *Out = GetOutputStream(argv[0]);
|
||||
if (Out == 0) return 1;
|
||||
|
||||
|
||||
// If this target requires addPassesToEmitWholeFile, do it now. This is
|
||||
// used by strange things like the C backend.
|
||||
if (Target.WantsWholeFile()) {
|
||||
@ -252,7 +252,7 @@ int main(int argc, char **argv) {
|
||||
PM.add(new TargetData(*Target.getTargetData()));
|
||||
if (!NoVerify)
|
||||
PM.add(createVerifierPass());
|
||||
|
||||
|
||||
// Ask the target to add backend passes as necessary.
|
||||
if (Target.addPassesToEmitWholeFile(PM, *Out, FileType, Fast)) {
|
||||
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());
|
||||
FunctionPassManager Passes(&Provider);
|
||||
Passes.add(new TargetData(*Target.getTargetData()));
|
||||
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (!NoVerify)
|
||||
Passes.add(createVerifierPass());
|
||||
#endif
|
||||
|
||||
|
||||
// Ask the target to add backend passes as necessary.
|
||||
MachineCodeEmitter *MCE = 0;
|
||||
|
||||
@ -306,18 +306,18 @@ int main(int argc, char **argv) {
|
||||
sys::Path(OutputFilename).eraseFromDisk();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
Passes.doInitialization();
|
||||
|
||||
|
||||
// Run our queue of passes all at once now, efficiently.
|
||||
// TODO: this could lazily stream functions out of the module.
|
||||
for (Module::iterator I = mod.begin(), E = mod.end(); I != E; ++I)
|
||||
if (!I->isDeclaration())
|
||||
Passes.run(*I);
|
||||
|
||||
|
||||
Passes.doFinalization();
|
||||
}
|
||||
|
||||
|
||||
// Delete the ostream if it's not a stdout stream
|
||||
if (Out != &outs()) delete Out;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user