mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-22 10:24:26 +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:
@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user