71 using namespace wholeprogramdevirt;
73 #define DEBUG_TYPE "wholeprogramdevirt"
80 bool IsAfter, uint64_t Size) {
85 MinByte = std::max(MinByte,
Target.minAfterBytes());
87 MinByte = std::max(MinByte,
Target.minBeforeBytes());
110 std::vector<ArrayRef<uint8_t>> Used;
113 :
Target.TM->Bits->Before.BytesUsed;
114 uint64_t
Offset = IsAfter ? MinByte -
Target.minAfterBytes()
115 : MinByte -
Target.minBeforeBytes();
120 Used.push_back(VTUsed.
slice(Offset));
125 for (
unsigned I = 0;; ++
I) {
126 uint8_t BitsUsed = 0;
127 for (
auto &&
B : Used)
130 if (BitsUsed != 0xff)
131 return (MinByte +
I) * 8 +
137 for (
unsigned I = 0;; ++
I) {
138 for (
auto &&
B : Used) {
140 while ((
I + Byte) <
B.size() && Byte < (Size / 8)) {
146 return (MinByte +
I) * 8;
154 unsigned BitWidth, int64_t &OffsetByte, uint64_t &OffsetBit) {
156 OffsetByte = -(AllocBefore / 8 + 1);
158 OffsetByte = -((AllocBefore + 7) / 8 + (BitWidth + 7) / 8);
159 OffsetBit = AllocBefore % 8;
163 Target.setBeforeBit(AllocBefore);
165 Target.setBeforeBytes(AllocBefore, (BitWidth + 7) / 8);
171 unsigned BitWidth, int64_t &OffsetByte, uint64_t &OffsetBit) {
173 OffsetByte = AllocAfter / 8;
175 OffsetByte = (AllocAfter + 7) / 8;
176 OffsetBit = AllocAfter % 8;
180 Target.setAfterBit(AllocAfter);
182 Target.setAfterBytes(AllocAfter, (BitWidth + 7) / 8);
188 IsBigEndian(Fn->
getParent()->getDataLayout().isBigEndian()), WasDevirt(
false) {}
218 const VTableSlot &RHS) {
219 return LHS.TypeID == RHS.TypeID && LHS.ByteOffset == RHS.ByteOffset;
229 struct VirtualCallSite {
236 unsigned *NumUnsafeUses;
238 void emitRemark(
const Twine &OptName,
const Twine &TargetName) {
242 CS.getInstruction()->getDebugLoc(),
243 OptName +
": devirtualized a call to " + TargetName);
246 void replaceAndErase(
const Twine &OptName,
const Twine &TargetName,
247 bool RemarksEnabled,
Value *New) {
249 emitRemark(OptName, TargetName);
250 CS->replaceAllUsesWith(New);
251 if (
auto II = dyn_cast<InvokeInst>(
CS.getInstruction())) {
253 II->getUnwindDest()->removePredecessor(II->getParent());
255 CS->eraseFromParent();
262 struct DevirtModule {
280 std::map<CallInst *, unsigned> NumUnsafeUsesForTypeTest;
283 : M(M), Int8Ty(
Type::getInt8Ty(M.getContext())),
284 Int8PtrTy(
Type::getInt8PtrTy(M.getContext())),
286 RemarksEnabled(areRemarksEnabled()) {}
288 bool areRemarksEnabled();
291 void scanTypeCheckedLoadUsers(
Function *TypeCheckedLoadFunc);
293 void buildTypeIdentifierMap(
294 std::vector<VTableBits> &
Bits,
298 tryFindVirtualCallTargets(std::vector<VirtualCallTarget> &TargetsForSlot,
299 const std::set<TypeMemberInfo> &TypeMemberInfos,
300 uint64_t ByteOffset);
303 bool tryEvaluateFunctionsWithArgs(
309 bool tryUniqueRetValOpt(
unsigned BitWidth,
320 struct WholeProgramDevirt :
public ModulePass {
327 bool runOnModule(
Module &M)
override {
331 return DevirtModule(M).run();
338 "Whole program devirtualization",
false,
false)
339 char WholeProgramDevirt::
ID = 0;
342 return new WholeProgramDevirt;
347 if (!DevirtModule(M).run())
352 void DevirtModule::buildTypeIdentifierMap(
353 std::vector<VTableBits> &
Bits,
367 Bits.back().GV = &GV;
368 Bits.back().ObjectSize =
370 BitsPtr = &Bits.back();
378 cast<ConstantAsMetadata>(
Type->getOperand(0))->getValue())
381 TypeIdMap[
TypeID].insert({BitsPtr, Offset});
395 if (
auto *
C = dyn_cast<ConstantStruct>(I)) {
401 return getPointerAtOffset(cast<Constant>(I->
getOperand(Op)),
404 if (
auto *
C = dyn_cast<ConstantArray>(I)) {
408 unsigned Op = Offset / ElemSize;
409 if (Op >=
C->getNumOperands())
412 return getPointerAtOffset(cast<Constant>(I->
getOperand(Op)),
418 bool DevirtModule::tryFindVirtualCallTargets(
419 std::vector<VirtualCallTarget> &TargetsForSlot,
420 const std::set<TypeMemberInfo> &TypeMemberInfos, uint64_t ByteOffset) {
422 if (!
TM.Bits->GV->isConstant())
425 Constant *
Ptr = getPointerAtOffset(
TM.Bits->GV->getInitializer(),
426 TM.Offset + ByteOffset);
436 if (Fn->getName() ==
"__cxa_pure_virtual")
439 TargetsForSlot.push_back({Fn, &
TM});
443 return !TargetsForSlot.
empty();
446 bool DevirtModule::trySingleImplDevirt(
451 Function *TheFn = TargetsForSlot[0].Fn;
452 for (
auto &&
Target : TargetsForSlot)
457 TargetsForSlot[0].WasDevirt =
true;
459 for (
auto &&VCallSite : CallSites) {
461 VCallSite.emitRemark(
"single-impl", TheFn->
getName());
463 TheFn, VCallSite.CS.getCalledValue()->
getType()));
465 if (VCallSite.NumUnsafeUses)
466 --*VCallSite.NumUnsafeUses;
471 bool DevirtModule::tryEvaluateFunctionsWithArgs(
479 for (
unsigned I = 0; I != Args.
size(); ++
I)
480 if (
Target.Fn->getFunctionType()->getParamType(I + 1) !=
488 EvalArgs.insert(EvalArgs.end(), Args.
begin(), Args.
end());
490 if (!
Eval.EvaluateFunction(
Target.Fn, RetVal, EvalArgs) ||
491 !isa<ConstantInt>(RetVal))
493 Target.RetVal = cast<ConstantInt>(RetVal)->getZExtValue();
498 bool DevirtModule::tryUniformRetValOpt(
503 uint64_t TheRetVal = TargetsForSlot[0].RetVal;
505 if (
Target.RetVal != TheRetVal)
509 for (
auto Call : CallSites)
510 Call.replaceAndErase(
"uniform-ret-val", TargetsForSlot[0].Fn->getName(),
511 RemarksEnabled, TheRetValConst);
513 for (
auto &&
Target : TargetsForSlot)
518 bool DevirtModule::tryUniqueRetValOpt(
522 auto tryUniqueRetValOptFor = [&](
bool IsOne) {
525 if (
Target.RetVal == (IsOne ? 1 : 0)) {
537 for (
auto &&Call : CallSites) {
539 Value *OneAddr =
B.CreateBitCast(UniqueMember->
Bits->
GV, Int8PtrTy);
540 OneAddr =
B.CreateConstGEP1_64(OneAddr, UniqueMember->
Offset);
542 Call.VTable, OneAddr);
543 Call.replaceAndErase(
"unique-ret-val", TargetsForSlot[0].Fn->getName(),
544 RemarksEnabled, Cmp);
548 for (
auto &&
Target : TargetsForSlot)
555 if (tryUniqueRetValOptFor(
true))
557 if (tryUniqueRetValOptFor(
false))
563 bool DevirtModule::tryVirtualConstProp(
578 if (!
Target.Fn->doesNotAccessMemory() ||
Target.Fn->arg_empty() ||
579 !
Target.Fn->arg_begin()->use_empty() ||
580 Target.Fn->getReturnType() != RetType)
586 struct ByAPIntValue {
587 bool operator()(
const std::vector<ConstantInt *> &
A,
588 const std::vector<ConstantInt *> &
B)
const {
589 return std::lexicographical_compare(
590 A.begin(), A.end(), B.begin(), B.end(),
596 std::map<std::vector<ConstantInt *>, std::vector<VirtualCallSite>,
598 VCallSitesByConstantArg;
599 for (
auto &&VCallSite : CallSites) {
600 std::vector<ConstantInt *>
Args;
601 if (VCallSite.CS.getType() != RetType)
604 make_range(VCallSite.CS.arg_begin() + 1, VCallSite.CS.arg_end())) {
605 if (!isa<ConstantInt>(Arg))
607 Args.push_back(cast<ConstantInt>(&Arg));
609 if (Args.size() + 1 != VCallSite.CS.arg_size())
612 VCallSitesByConstantArg[
Args].push_back(VCallSite);
615 for (
auto &&CSByConstantArg : VCallSitesByConstantArg) {
616 if (!tryEvaluateFunctionsWithArgs(TargetsForSlot, CSByConstantArg.first))
619 if (tryUniformRetValOpt(RetType, TargetsForSlot, CSByConstantArg.second))
622 if (tryUniqueRetValOpt(BitWidth, TargetsForSlot, CSByConstantArg.second))
627 uint64_t AllocBefore =
629 uint64_t AllocAfter =
634 uint64_t TotalPaddingBefore = 0, TotalPaddingAfter = 0;
635 for (
auto &&
Target : TargetsForSlot) {
636 TotalPaddingBefore += std::max<int64_t>(
637 (AllocBefore + 7) / 8 -
Target.allocatedBeforeBytes() - 1, 0);
638 TotalPaddingAfter += std::max<int64_t>(
639 (AllocAfter + 7) / 8 -
Target.allocatedAfterBytes() - 1, 0);
644 if (
std::min(TotalPaddingBefore, TotalPaddingAfter) > 128)
651 if (TotalPaddingBefore <= TotalPaddingAfter)
659 for (
auto &&
Target : TargetsForSlot)
663 for (
auto Call : CSByConstantArg.second) {
665 Value *Addr = B.CreateConstGEP1_64(
Call.VTable, OffsetByte);
667 Value *Bits = B.CreateLoad(Addr);
669 Value *BitsAndBit = B.CreateAnd(Bits, Bit);
671 Call.replaceAndErase(
"virtual-const-prop-1-bit",
672 TargetsForSlot[0].Fn->
getName(),
673 RemarksEnabled, IsBitSet);
676 Value *Val = B.CreateLoad(RetType, ValAddr);
677 Call.replaceAndErase(
"virtual-const-prop",
678 TargetsForSlot[0].Fn->
getName(),
679 RemarksEnabled, Val);
686 void DevirtModule::rebuildGlobal(
VTableBits &B) {
696 for (
size_t I = 0, Size = B.
Before.
Bytes.size(); I != Size / 2; ++
I)
720 NewInit->getType(), NewGV,
725 Alias->takeName(B.
GV);
731 bool DevirtModule::areRemarksEnabled() {
737 return DI.isEnabled();
740 void DevirtModule::scanTypeTestUsers(
Function *TypeTestFunc,
763 if (!Assumes.
empty()) {
765 cast<MetadataAsValue>(CI->getArgOperand(1))->getMetadata();
767 if (SeenPtrs.
insert(Ptr).second) {
769 CallSlots[{TypeId,
Call.Offset}].push_back(
770 {CI->getArgOperand(0),
Call.CS,
nullptr});
776 for (
auto Assume : Assumes)
777 Assume->eraseFromParent();
781 CI->eraseFromParent();
785 void DevirtModule::scanTypeCheckedLoadUsers(
Function *TypeCheckedLoadFunc) {
788 for (
auto I = TypeCheckedLoadFunc->
use_begin(),
796 Value *Ptr = CI->getArgOperand(0);
797 Value *Offset = CI->getArgOperand(1);
798 Value *TypeIdValue = CI->getArgOperand(2);
799 Metadata *TypeId = cast<MetadataAsValue>(TypeIdValue)->getMetadata();
804 bool HasNonCallUses =
false;
815 (LoadedPtrs.
size() == 1 && !HasNonCallUses) ? LoadedPtrs[0] : CI);
816 Value *
GEP = LoadB.CreateGEP(Int8Ty, Ptr, Offset);
818 Value *LoadedValue = LoadB.CreateLoad(Int8PtrTy, GEPPtr);
822 LoadedPtr->eraseFromParent();
826 IRBuilder<> CallB((Preds.
size() == 1 && !HasNonCallUses) ? Preds[0] : CI);
827 CallInst *TypeTestCall = CallB.CreateCall(TypeTestFunc, {
Ptr, TypeIdValue});
831 Pred->eraseFromParent();
838 if (!CI->use_empty()) {
841 Pair = B.CreateInsertValue(Pair, LoadedValue, {0});
842 Pair = B.CreateInsertValue(Pair, TypeTestCall, {1});
843 CI->replaceAllUsesWith(Pair);
847 auto &NumUnsafeUses = NumUnsafeUsesForTypeTest[TypeTestCall];
848 NumUnsafeUses = DevirtCalls.
size();
856 CallSlots[{TypeId,
Call.Offset}].push_back(
857 {
Ptr,
Call.CS, &NumUnsafeUses});
860 CI->eraseFromParent();
864 bool DevirtModule::run() {
871 if ((!TypeTestFunc || TypeTestFunc->
use_empty() || !AssumeFunc ||
873 (!TypeCheckedLoadFunc || TypeCheckedLoadFunc->
use_empty()))
876 if (TypeTestFunc && AssumeFunc)
877 scanTypeTestUsers(TypeTestFunc, AssumeFunc);
879 if (TypeCheckedLoadFunc)
880 scanTypeCheckedLoadUsers(TypeCheckedLoadFunc);
883 std::vector<VTableBits>
Bits;
885 buildTypeIdentifierMap(Bits, TypeIdMap);
886 if (TypeIdMap.
empty())
890 bool DidVirtualConstProp =
false;
891 std::map<std::string, Function*> DevirtTargets;
892 for (
auto &S : CallSlots) {
896 std::vector<VirtualCallTarget> TargetsForSlot;
897 if (!tryFindVirtualCallTargets(TargetsForSlot, TypeIdMap[S.first.TypeID],
901 if (!trySingleImplDevirt(TargetsForSlot, S.second) &&
902 tryVirtualConstProp(TargetsForSlot, S.second))
903 DidVirtualConstProp =
true;
907 for (
const auto &
T : TargetsForSlot)
909 DevirtTargets[
T.Fn->getName()] =
T.Fn;
912 if (RemarksEnabled) {
914 for (
const auto &DT : DevirtTargets) {
919 Twine(
"devirtualized ") + F->getName());
925 if (TypeCheckedLoadFunc) {
927 for (
auto &&U : NumUnsafeUsesForTypeTest) {
930 U.first->eraseFromParent();
937 if (DidVirtualConstProp)
void push_back(const T &Elt)
A parsed version of the target data layout string in and methods for querying it. ...
LinkageTypes getLinkage() const
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
VisibilityTypes getVisibility() const
static unsigned getHashValue(const VTableSlot &I)
const char * getName() const
getName - Get the target name.
A Module instance is used to store all the information related to an LLVM module. ...
static Constant * getAnon(ArrayRef< Constant * > V, bool Packed=false)
Return an anonymous struct that has the specified elements.
VirtualCallTarget(Function *Fn, const TypeMemberInfo *TM)
const GlobalListType & getGlobalList() const
Get the Module's list of global variables (constant).
This provides a very simple, boring adaptor for a begin and end iterator into a range type...
void initializeWholeProgramDevirtPass(PassRegistry &)
This class represents a function call, abstracting a target machine's calling convention.
static Constant * getGetElementPtr(Type *Ty, Constant *C, ArrayRef< Constant * > IdxList, bool InBounds=false, Optional< unsigned > InRangeIndex=None, Type *OnlyIfReducedTy=nullptr)
Getelementptr form.
Like Internal, but omit from symbol table.
This class implements a map that also provides access to all stored values in a deterministic order...
uint64_t alignTo(uint64_t Value, uint64_t Align, uint64_t Skew=0)
Returns the next integer (mod 2**64) that is greater than or equal to Value and is a multiple of Alig...
unsigned getBitWidth() const
Get the number of bits in this IntegerType.
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
void emitOptimizationRemark(LLVMContext &Ctx, const char *PassName, const Function &Fn, const DebugLoc &DLoc, const Twine &Msg)
Emit an optimization-applied message.
void setAfterReturnValues(MutableArrayRef< VirtualCallTarget > Targets, uint64_t AllocAfter, unsigned BitWidth, int64_t &OffsetByte, uint64_t &OffsetBit)
static Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
StringRef getName() const
Return a constant reference to the value's name.
void setBeforeReturnValues(MutableArrayRef< VirtualCallTarget > Targets, uint64_t AllocBefore, unsigned BitWidth, int64_t &OffsetByte, uint64_t &OffsetBit)
ArrayRef< T > slice(size_t N, size_t M) const
slice(n, m) - Chop off the first N elements of the array, and keep M elements in the array...
Used to lazily calculate structure layout information for a target machine, based on the DataLayout s...
StringRef getName(ID id)
Return the LLVM name for an intrinsic, such as "llvm.ppc.altivec.lvx".
void findDevirtualizableCallsForTypeCheckedLoad(SmallVectorImpl< DevirtCallSite > &DevirtCalls, SmallVectorImpl< Instruction * > &LoadedPtrs, SmallVectorImpl< Instruction * > &Preds, bool &HasNonCallUses, CallInst *CI)
Given a call to the intrinsic .type.checked.load, find all devirtualizable call sites based on the ca...
DILocation * get() const
Get the underlying DILocation.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
const StructLayout * getStructLayout(StructType *Ty) const
Returns a StructLayout object, indicating the alignment of the struct, its size, and the offsets of i...
const APInt & getValue() const
Return the constant as an APInt value reference.
static Constant * get(LLVMContext &Context, ArrayRef< uint8_t > Elts)
get() constructors - Return a constant with array type with an element count and element type matchin...
The returned value is undefined.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
TypeID
Definitions of all of the base types for the Type system.
void eraseFromParent() override
eraseFromParent - This method unlinks 'this' from the containing module and deletes it...
static bool isEqual(const VTableSlot &LHS, const VTableSlot &RHS)
LLVM_NODISCARD bool empty() const
static VTableSlot getTombstoneKey()
GraphT::NodeRef Eval(DominatorTreeBaseByGraphTraits< GraphT > &DT, typename GraphT::NodeRef VIn, unsigned LastLinked)
Class to represent array types.
Function Alias Analysis false
StringRef getSection() const
Get the custom section of this global if it has one.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Function * getDeclaration(Module *M, ID id, ArrayRef< Type * > Tys=None)
Create or insert an LLVM Function declaration for an intrinsic, and return it.
ModulePass * createWholeProgramDevirtPass()
This pass implements whole-program devirtualization using type metadata.
static GCRegistry::Add< OcamlGC > B("ocaml","ocaml 3.10-compatible GC")
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Type * getElementType() const
size_t size() const
size - Get the array size.
Maximum length of the test input libFuzzer tries to guess a good value based on the corpus and reports it always prefer smaller inputs during the corpus shuffle When libFuzzer itself reports a bug this exit code will be used If indicates the maximal total time in seconds to run the fuzzer minimizes the provided crash input Use with etc Experimental Use value profile to guide fuzzing Number of simultaneous worker processes to run the jobs If min(jobs, NumberOfCpuCores()/2)\" is used.") FUZZER_FLAG_INT(reload
Class to represent pointers.
bool ult(const APInt &RHS) const
Unsigned less than comparison.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
Function * getFunction(StringRef Name) const
Look up the specified function in the module symbol table.
uint64_t getElementOffset(unsigned Idx) const
static Constant * getBitCast(Constant *C, Type *Ty, bool OnlyIfReduced=false)
A set of analyses that are preserved following a run of a transformation pass.
Constant * stripPointerCasts()
std::size_t countTrailingZeros(T Val, ZeroBehavior ZB=ZB_Width)
Count number of 0's from the least significant bit to the most stopping at the first 1...
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
The instances of the Type class are immutable: once they are created, they are never changed...
A call site that could be devirtualized.
const Comdat * getComdat() const
This is an important base class in LLVM.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &)
This file contains the declarations for the subclasses of Constant, which represent the different fla...
std::pair< iterator, bool > insert(const ValueT &V)
void findDevirtualizableCallsForTypeTest(SmallVectorImpl< DevirtCallSite > &DevirtCalls, SmallVectorImpl< CallInst * > &Assumes, CallInst *CI)
Given a call to the intrinsic .type.test, find all devirtualizable call sites based on the call and r...
Value * getOperand(unsigned i) const
void reserve(size_type NumEntries)
Grow the densemap so that it can contain at least NumEntries items before resizing again...
Class to represent integer types.
bool isPointerTy() const
True if this is an instance of PointerType.
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This class evaluates LLVM IR, producing the Constant representing each SSA instruction.
const FunctionListType & getFunctionList() const
Get the Module's list of functions (constant).
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
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 the shared class of boolean and integer constants.
uint64_t getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Module.h This file contains the declarations for the Module class.
Type * getType() const
All values are typed, get the type of this value.
uint64_t getSizeInBytes() const
unsigned getElementContainingOffset(uint64_t Offset) const
Given a valid byte offset into the structure, returns the structure index that contains it...
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.
static BranchInst * Create(BasicBlock *IfTrue, Instruction *InsertBefore=nullptr)
static ConstantInt * getTrue(LLVMContext &Context)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack","Very portable GC for uncooperative code generators")
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Target - Wrapper for Target specific information.
bool isConstant() const
If the value is a global constant, its value is immutable throughout the runtime execution of the pro...
DISubprogram * getSubprogram() const
Get the attached subprogram.
PointerType * getType() const
Global values are always pointers.
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
std::vector< uint8_t > Bytes
uint64_t findLowestOffset(ArrayRef< VirtualCallTarget > Targets, bool IsAfter, uint64_t Size)
static VTableSlot getEmptyKey()
LLVM_ATTRIBUTE_ALWAYS_INLINE size_type size() const
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
LLVM_NODISCARD bool empty() const
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
const BasicBlock & front() const
LLVM Value Representation.
static const Function * getParent(const Value *V)
PointerType * getPointerTo(unsigned AddrSpace=0) const
Return a pointer to the current type.
iterator_range< global_iterator > globals()
A container for analyses that lazily runs them and caches their results.
unsigned getPointerSize(unsigned AS=0) const
Layout pointer size FIXME: The defaults need to be removed once all of the backends/clients are updat...
static GCRegistry::Add< ErlangGC > A("erlang","erlang-compatible garbage collector")
void setSection(StringRef S)
Change the section for this global.
static GlobalAlias * create(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage, const Twine &Name, Constant *Aliasee, Module *Parent)
If a parent module is specified, the alias is automatically inserted into the end of the specified mo...
LLVMContext & getContext() const
Get the global data context.