47 #define DEBUG_TYPE "shadow-stack-gc-lowering" 62 std::vector<std::pair<CallInst *, AllocaInst *>> Roots;
67 ShadowStackGCLowering();
69 bool doInitialization(
Module &M)
override;
73 bool IsNullValue(
Value *V);
82 Type *Ty,
Value *BasePtr,
int Idx1,
int Idx2,
91 "Shadow Stack GC Lowering",
false,
false)
98 ShadowStackGCLowering::ShadowStackGCLowering() :
FunctionPass(
ID) {
107 unsigned NumMeta = 0;
109 for (
unsigned I = 0;
I != Roots.size(); ++
I) {
110 Constant *
C = cast<Constant>(Roots[
I].first->getArgOperand(1));
156 Type *ShadowStackGCLowering::GetConcreteStackEntryType(
Function &F) {
158 std::vector<Type *> EltTys;
159 EltTys.push_back(StackEntryTy);
160 for (
size_t I = 0;
I != Roots.size();
I++)
161 EltTys.push_back(Roots[
I].second->getAllocatedType());
168 bool ShadowStackGCLowering::doInitialization(
Module &M) {
171 if (F.
hasGC() && F.
getGC() == std::string(
"shadow-stack")) {
184 std::vector<Type *> EltTys;
202 EltTys.push_back(FrameMapPtrTy);
207 Head = M.getGlobalVariable(
"llvm_gc_root_chain");
214 }
else if (Head->hasExternalLinkage() && Head->isDeclaration()) {
222 bool ShadowStackGCLowering::IsNullValue(
Value *V) {
224 return C->isNullValue();
228 void ShadowStackGCLowering::CollectRoots(
Function &F) {
233 assert(Roots.empty() &&
"Not cleaned up?");
240 if (
Function *F = CI->getCalledFunction())
242 std::pair<CallInst *, AllocaInst *> Pair = std::make_pair(
244 cast<AllocaInst>(CI->getArgOperand(0)->stripPointerCasts()));
245 if (IsNullValue(CI->getArgOperand(1)))
246 Roots.push_back(Pair);
248 MetaRoots.push_back(Pair);
253 Roots.insert(Roots.begin(), MetaRoots.begin(), MetaRoots.end());
258 Value *BasePtr,
int Idx,
266 assert(isa<GetElementPtrInst>(Val) &&
"Unexpected folded constant");
273 int Idx,
const char *Name) {
278 assert(isa<GetElementPtrInst>(Val) &&
"Unexpected folded constant");
287 F.
getGC() != std::string(
"shadow-stack"))
301 Value *FrameMap = GetFrameMap(F);
302 Type *ConcreteStackEntryTy = GetConcreteStackEntryType(F);
309 AtEntry.CreateAlloca(ConcreteStackEntryTy,
nullptr,
"gc_frame");
311 while (isa<AllocaInst>(IP))
313 AtEntry.SetInsertPoint(IP->getParent(), IP);
316 Instruction *CurrentHead = AtEntry.CreateLoad(Head,
"gc_currhead");
317 Instruction *EntryMapPtr = CreateGEP(Context, AtEntry, ConcreteStackEntryTy,
318 StackEntry, 0, 1,
"gc_frame.map");
319 AtEntry.CreateStore(FrameMap, EntryMapPtr);
322 for (
unsigned I = 0,
E = Roots.size();
I !=
E; ++
I) {
324 Value *SlotPtr = CreateGEP(Context, AtEntry, ConcreteStackEntryTy,
325 StackEntry, 1 +
I,
"gc_root");
337 while (isa<StoreInst>(IP))
339 AtEntry.SetInsertPoint(IP->getParent(), IP);
342 Instruction *EntryNextPtr = CreateGEP(Context, AtEntry, ConcreteStackEntryTy,
343 StackEntry, 0, 0,
"gc_frame.next");
344 Instruction *NewHeadVal = CreateGEP(Context, AtEntry, ConcreteStackEntryTy,
345 StackEntry, 0,
"gc_newhead");
346 AtEntry.CreateStore(CurrentHead, EntryNextPtr);
347 AtEntry.CreateStore(NewHeadVal, Head);
355 CreateGEP(Context, *AtExit, ConcreteStackEntryTy, StackEntry, 0, 0,
357 Value *SavedHead = AtExit->CreateLoad(EntryNextPtr2,
"gc_savedhead");
358 AtExit->CreateStore(SavedHead, Head);
364 for (
unsigned I = 0,
E = Roots.size();
I !=
E; ++
I) {
365 Roots[
I].first->eraseFromParent();
366 Roots[
I].second->eraseFromParent();
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
This class represents lattice values for constants.
A Module instance is used to store all the information related to an LLVM module. ...
static Constant * getGetElementPtr(Type *Ty, Constant *C, ArrayRef< Constant *> IdxList, bool InBounds=false, Optional< unsigned > InRangeIndex=None, Type *OnlyIfReducedTy=nullptr)
Getelementptr form.
void push_back(const T &Elt)
void initializeShadowStackGCLoweringPass(PassRegistry &)
FunctionPass * createShadowStackGCLoweringPass()
ShadowStackGCLowering - Implements the custom lowering mechanism used by the shadow stack GC...
static Constant * get(ArrayType *T, ArrayRef< Constant *> V)
static Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
iterator begin()
Instruction iterator methods.
EscapeEnumerator - This is a little algorithm to find all escape points from a function so that "fina...
#define INITIALIZE_PASS_DEPENDENCY(depName)
amdgpu Simplify well known AMD library false Value Value const Twine & Name
Class to represent struct types.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
An analysis pass which caches information about the entire Module.
bool isNullValue() const
Return true if this is the value that would be returned by getNullValue.
Type * getType() const
All values are typed, get the type of this value.
const std::string & getGC() const
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
INITIALIZE_PASS_BEGIN(ShadowStackGCLowering, DEBUG_TYPE, "Shadow Stack GC Lowering", false, false) INITIALIZE_PASS_END(ShadowStackGCLowering
void setBody(ArrayRef< Type *> Elements, bool isPacked=false)
Specify a body for an opaque identified type.
void takeName(Value *V)
Transfer the name from V to this value.
Class to represent pointers.
static Constant * getBitCast(Constant *C, Type *Ty, bool OnlyIfReduced=false)
const BasicBlock & getEntryBlock() const
an instruction for type-safe pointer arithmetic to access elements of arrays and structs ...
static bool runOnFunction(Function &F, bool PostInlining)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
The instances of the Type class are immutable: once they are created, they are never changed...
This is an important class for using LLVM in a threaded context.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This is an important base class in LLVM.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
FunctionPass class - This class is used to implement most global optimizations.
static Constant * get(StructType *T, ArrayRef< Constant *> V)
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE, "Assign register bank of generic virtual registers", false, false) RegBankSelect
Value * CreateGEP(Value *Ptr, ArrayRef< Value *> IdxList, const Twine &Name="")
Iterator for intrusive lists based on ilist_node.
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the generic address space (address sp...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Keep one copy of function when linking (inline)
Module.h This file contains the declarations for the Module class.
static Constant * get(Type *Ty, uint64_t V, bool isSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
std::string utostr(uint64_t X, bool isNeg=false)
Intrinsic::ID getIntrinsicID() const LLVM_READONLY
getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...
bool hasGC() const
hasGC/getGC/setGC/clearGC - The name of the garbage collection algorithm to use during code generatio...
static IntegerType * getInt32Ty(LLVMContext &C)
StringRef getName() const
Return a constant reference to the value's name.
static ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Rename collisions when linking (static functions).
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Module * getParent()
Get the module that this global value is contained inside of...
LLVM Value Representation.
static StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
std::vector< uint32_t > Metadata
PAL metadata represented as a vector.
A wrapper class for inspecting calls to intrinsic functions.
an instruction to allocate memory on the stack