/// SymbolicallyEvaluateGEP - If we can symbolically evaluate the specified GEP /// constant expression, do so. static Constant *SymbolicallyEvaluateGEP(Constant** Ops, unsigned NumOps, const Type *ResultTy, const TargetData *TD) { Constant *Ptr = Ops[0]; if (!cast<PointerType>(Ptr->getType())->getElementType()->isSized()) return 0; if (TD && Ptr->isNullValue()) { // If this is a constant expr gep that is effectively computing an // "offsetof", fold it into 'cast int Size to T*' instead of 'gep 0, 0, 12' bool isFoldableGEP = true; for (unsigned i = 1; i != NumOps; ++i) if (!isa<ConstantInt>(Ops[i])) { isFoldableGEP = false; break; } if (isFoldableGEP) { uint64_t Offset = TD->getIndexedOffset(Ptr->getType(), (Value**)Ops+1, NumOps-1); Constant *C = ConstantInt::get(TD->getIntPtrType(), Offset); return ConstantExpr::getIntToPtr(C, ResultTy); } } return 0; }
/// runStaticConstructorsDestructors - This method is used to execute all of /// the static constructors or destructors for a module, depending on the /// value of isDtors. void ExecutionEngine::runStaticConstructorsDestructors(Module *module, bool isDtors) { const char *Name = isDtors ? "llvm.global_dtors" : "llvm.global_ctors"; // Execute global ctors/dtors for each module in the program. GlobalVariable *GV = module->getNamedGlobal(Name); // If this global has internal linkage, or if it has a use, then it must be // an old-style (llvmgcc3) static ctor with __main linked in and in use. If // this is the case, don't execute any of the global ctors, __main will do // it. if (!GV || GV->isDeclaration() || GV->hasLocalLinkage()) return; // Should be an array of '{ int, void ()* }' structs. The first value is // the init priority, which we ignore. ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer()); if (!InitList) return; for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) if (ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(i))) { if (CS->getNumOperands() != 2) return; // Not array of 2-element structs. Constant *FP = CS->getOperand(1); if (FP->isNullValue()) break; // Found a null terminator, exit. if (ConstantExpr *CE = dyn_cast<ConstantExpr>(FP)) if (CE->isCast()) FP = CE->getOperand(0); if (Function *F = dyn_cast<Function>(FP)) { // Execute the ctor/dtor function! runFunction(F, std::vector<GenericValue>()); } } }
void PIC16AsmPrinter::EmitRomData (Module &M) { SwitchToSection(TAI->getReadOnlySection()); IsRomData = true; for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) { if (!I->hasInitializer()) // External global require no code. continue; Constant *C = I->getInitializer(); const PointerType *PtrTy = I->getType(); int AddrSpace = PtrTy->getAddressSpace(); if ((!C->isNullValue()) && (AddrSpace == PIC16ISD::ROM_SPACE)) { if (EmitSpecialLLVMGlobal(I)) continue; // Any variables reaching here with "." in its name is a local scope // variable and should not be printed in global data section. std::string name = Mang->getValueName(I); if (name.find(".") != std::string::npos) continue; I->setSection(TAI->getReadOnlySection()->getName()); O << name; EmitGlobalConstant(C, AddrSpace); O << "\n"; } } IsRomData = false; }
void PIC16AsmPrinter::EmitUnInitData (Module &M) { SwitchToSection(TAI->getBSSSection_()); const TargetData *TD = TM.getTargetData(); for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) { if (!I->hasInitializer()) // External global require no code. continue; Constant *C = I->getInitializer(); if (C->isNullValue()) { if (EmitSpecialLLVMGlobal(I)) continue; // Any variables reaching here with "." in its name is a local scope // variable and should not be printed in global data section. std::string name = Mang->getValueName(I); if (name.find(".") != std::string::npos) continue; I->setSection(TAI->getBSSSection_()->getName()); const Type *Ty = C->getType(); unsigned Size = TD->getTypePaddedSize(Ty); O << name << " " <<"RES"<< " " << Size ; O << "\n"; } } }
// Instrument memset/memmove/memcpy bool AddressSanitizer::instrumentMemIntrinsic(AsanFunctionContext &AFC, MemIntrinsic *MI) { Value *Dst = MI->getDest(); MemTransferInst *MemTran = dyn_cast<MemTransferInst>(MI); Value *Src = MemTran ? MemTran->getSource() : 0; Value *Length = MI->getLength(); Constant *ConstLength = dyn_cast<Constant>(Length); Instruction *InsertBefore = MI; if (ConstLength) { if (ConstLength->isNullValue()) return false; } else { // The size is not a constant so it could be zero -- check at run-time. IRBuilder<> IRB(InsertBefore); Value *Cmp = IRB.CreateICmpNE(Length, Constant::getNullValue(Length->getType())); InsertBefore = splitBlockAndInsertIfThen(Cmp, false); } instrumentMemIntrinsicParam(AFC, MI, Dst, Length, InsertBefore, true); if (Src) instrumentMemIntrinsicParam(AFC, MI, Src, Length, InsertBefore, false); return true; }
/// allocateIDATA - allocate an initialized global into an existing /// or new section and return that section. const MCSection * PIC16TargetObjectFile::allocateIDATA(const GlobalVariable *GV) const{ assert(GV->hasInitializer() && "This global doesn't need space"); Constant *C = GV->getInitializer(); assert(!C->isNullValue() && "initialized globals has zero initializer"); assert(GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE && "can allocate initialized RAM data only"); // Find how much space this global needs. const TargetData *TD = TM->getTargetData(); const Type *Ty = C->getType(); unsigned ValSize = TD->getTypeAllocSize(Ty); // Go through all IDATA Sections and assign this variable // to the first available section having enough space. PIC16Section *Found = NULL; for (unsigned i = 0; i < IDATASections_.size(); i++) { if (DataBankSize - IDATASections_[i]->getSize() >= ValSize) { Found = IDATASections_[i]; break; } } // No IDATA section spacious enough was found. Crate a new one. if (!Found) { std::string name = PAN::getIdataSectionName(IDATASections_.size()); Found = getPIC16DataSection(name.c_str(), IDATA); } // Insert the GV into this IDATA. Found->Items.push_back(GV); Found->setSize(Found->getSize() + ValSize); return Found; }
static void addTryBlockMapEntry(WinEHFuncInfo &FuncInfo, int TryLow, int TryHigh, int CatchHigh, ArrayRef<const CatchPadInst *> Handlers) { WinEHTryBlockMapEntry TBME; TBME.TryLow = TryLow; TBME.TryHigh = TryHigh; TBME.CatchHigh = CatchHigh; assert(TBME.TryLow <= TBME.TryHigh); for (const CatchPadInst *CPI : Handlers) { WinEHHandlerType HT; Constant *TypeInfo = cast<Constant>(CPI->getArgOperand(0)); if (TypeInfo->isNullValue()) HT.TypeDescriptor = nullptr; else HT.TypeDescriptor = cast<GlobalVariable>(TypeInfo->stripPointerCasts()); HT.Adjectives = cast<ConstantInt>(CPI->getArgOperand(1))->getZExtValue(); HT.Handler = CPI->getParent(); if (auto *AI = dyn_cast<AllocaInst>(CPI->getArgOperand(2)->stripPointerCasts())) HT.CatchObj.Alloca = AI; else HT.CatchObj.Alloca = nullptr; TBME.HandlerArray.push_back(HT); } FuncInfo.TryBlockMap.push_back(TBME); }
void ControlFlowIntegrity::PatchDtorFunctions(void) { GlobalVariable *global_dtors = _M.getNamedGlobal("llvm.global_dtors"); // check for dtor section if (!global_dtors || !global_dtors->getOperand(0)) { return; } Constant *c = global_dtors->getInitializer(); if (!c) report_fatal_error("llvm.global_dtors without initializer!", false); ConstantArray *CA = dyn_cast<ConstantArray>(c); if (!CA) report_fatal_error("Cast to ConstantArray failed", true); for (Value *Op : ValueOpRange(*CA)) { ConstantStruct *CS = dyn_cast<ConstantStruct>(Op); if (!CS) report_fatal_error("Cast to ConstantStruct failed", true); Constant *FP = CS->getOperand(1); if (FP->isNullValue()) break; // found a NULL termintator, stop here Function *F = dyn_cast_or_null<Function>(FP); if (F == NULL) { // Strip off constant expression cast ConstantExpr *CE = dyn_cast<ConstantExpr>(FP); if (!CE) report_fatal_error("Cast to ConstantExpr failed", true); if (CE->isCast()) { FP = CE->getOperand(0); } F = dyn_cast_or_null<Function>(FP); } if (!F) report_fatal_error("Cast to Function failed", true); // set visibility to hidden (do not export), unless it is already // local (for ex. static), in which case we have to make it non-static if (F->hasLocalLinkage()) { F->setLinkage(llvm::GlobalValue::ExternalLinkage); } F->setVisibility(GlobalValue::HiddenVisibility); _FiniFunctions.insert(F->getName()); } if (global_dtors->getNumUses() > 0) report_fatal_error("llvm.global_dtors uses count is > 0!", false); global_dtors->removeFromParent(); }
Constant *ShadowStackGC::GetFrameMap(Function &F) { // doInitialization creates the abstract type of this value. Type *VoidPtr = Type::getInt8PtrTy(F.getContext()); // Truncate the ShadowStackDescriptor if some metadata is null. unsigned NumMeta = 0; SmallVector<Constant*, 16> Metadata; for (unsigned I = 0; I != Roots.size(); ++I) { Constant *C = cast<Constant>(Roots[I].first->getArgOperand(1)); if (!C->isNullValue()) NumMeta = I + 1; Metadata.push_back(ConstantExpr::getBitCast(C, VoidPtr)); } Metadata.resize(NumMeta); Type *Int32Ty = Type::getInt32Ty(F.getContext()); Constant *BaseElts[] = { ConstantInt::get(Int32Ty, Roots.size(), false), ConstantInt::get(Int32Ty, NumMeta, false), }; Constant *DescriptorElts[] = { ConstantStruct::get(FrameMapTy, BaseElts), ConstantArray::get(ArrayType::get(VoidPtr, NumMeta), Metadata) }; Type *EltTys[] = { DescriptorElts[0]->getType(),DescriptorElts[1]->getType()}; StructType *STy = StructType::create(EltTys, "gc_map."+utostr(NumMeta)); Constant *FrameMap = ConstantStruct::get(STy, DescriptorElts); // 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 // provided a ModulePass))). Constant *GV = new GlobalVariable(*F.getParent(), FrameMap->getType(), true, GlobalVariable::InternalLinkage, FrameMap, "__gc_" + F.getName()); Constant *GEPIndices[2] = { ConstantInt::get(Type::getInt32Ty(F.getContext()), 0), ConstantInt::get(Type::getInt32Ty(F.getContext()), 0) }; return ConstantExpr::getGetElementPtr(GV, GEPIndices); }
static void addConditions(CallSite CS, const ConditionsTy &Conditions) { for (auto &Cond : Conditions) { Value *Arg = Cond.first->getOperand(0); Constant *ConstVal = cast<Constant>(Cond.first->getOperand(1)); if (Cond.second == ICmpInst::ICMP_EQ) setConstantInArgument(CS, Arg, ConstVal); else if (ConstVal->getType()->isPointerTy() && ConstVal->isNullValue()) { assert(Cond.second == ICmpInst::ICMP_NE); addNonNullAttribute(CS, Arg); } } }
// what a hack static Function *getStubFunctionForCtorList(Module *m, GlobalVariable *gv, std::string name) { assert(!gv->isDeclaration() && !gv->hasInternalLinkage() && "do not support old LLVM style constructor/destructor lists"); std::vector<Type *> nullary; Function *fn = Function::Create(FunctionType::get(Type::getVoidTy(m->getContext()), nullary, false), GlobalVariable::InternalLinkage, name, m); BasicBlock *bb = BasicBlock::Create(m->getContext(), "entry", fn); // From lli: // Should be an array of '{ int, void ()* }' structs. The first value is // the init priority, which we ignore. ConstantArray *arr = dyn_cast<ConstantArray>(gv->getInitializer()); if (arr) { for (unsigned i=0; i<arr->getNumOperands(); i++) { ConstantStruct *cs = cast<ConstantStruct>(arr->getOperand(i)); #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 5) // There is a third *optional* element in global_ctor elements (``i8 // @data``). assert((cs->getNumOperands() == 2 || cs->getNumOperands() == 3) && "unexpected element in ctor initializer list"); #else assert(cs->getNumOperands()==2 && "unexpected element in ctor initializer list"); #endif Constant *fp = cs->getOperand(1); if (!fp->isNullValue()) { if (llvm::ConstantExpr *ce = dyn_cast<llvm::ConstantExpr>(fp)) fp = ce->getOperand(0); if (Function *f = dyn_cast<Function>(fp)) { CallInst::Create(f, "", bb); } else { assert(0 && "unable to get function pointer from ctor initializer list"); } } } } ReturnInst::Create(m->getContext(), bb); return fn; }
static bool isSuitableForBSS(const GlobalVariable *GV) { Constant *C = GV->getInitializer(); // Must have zero initializer. if (!C->isNullValue()) return false; // Leave constant zeros in readonly constant sections, so they can be shared. if (GV->isConstant()) return false; // If the global has an explicit section specified, don't put it in BSS. if (!GV->getSection().empty()) return false; // If -nozero-initialized-in-bss is specified, don't ever use BSS. if (NoZerosInBSS) return false; // Otherwise, put it in BSS! return true; }
static void RemoveFunctionReferences(Module *M, const char* Name) { auto *UsedVar = M->getGlobalVariable(Name, true); if (!UsedVar || !UsedVar->hasInitializer()) return; if (isa<ConstantAggregateZero>(UsedVar->getInitializer())) { assert(UsedVar->use_empty()); UsedVar->eraseFromParent(); return; } auto *OldUsedVal = cast<ConstantArray>(UsedVar->getInitializer()); std::vector<Constant*> Used; for(Value *V : OldUsedVal->operand_values()) { Constant *Op = cast<Constant>(V->stripPointerCasts()); if(!Op->isNullValue()) { Used.push_back(cast<Constant>(V)); } } auto *NewValElemTy = OldUsedVal->getType()->getElementType(); auto *NewValTy = ArrayType::get(NewValElemTy, Used.size()); auto *NewUsedVal = ConstantArray::get(NewValTy, Used); UsedVar->mutateType(NewUsedVal->getType()->getPointerTo()); UsedVar->setInitializer(NewUsedVal); }
void MemoryInstrumenter::lowerGlobalCtors(Module &M) { // Find llvm.global_ctors. GlobalVariable *GV = M.getNamedGlobal("llvm.global_ctors"); if (!GV) return; assert(!GV->isDeclaration() && !GV->hasLocalLinkage()); // Should be an array of '{ int, void ()* }' structs. The first value is // the init priority, which must be 65535 if the bitcode is generated using // clang. if (ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer())) { for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) { ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(i)); assert(CS); assert(CS->getNumOperands() == 2); // Get the priority. ConstantInt *Priority = dyn_cast<ConstantInt>(CS->getOperand(0)); assert(Priority); // TODO: For now, we assume all priorities must be 65535. assert(Priority->equalsInt(65535)); // Get the constructor function. Constant *FP = CS->getOperand(1); if (FP->isNullValue()) break; // Found a null terminator, exit. // Explicitly call the constructor at the main entry. CallInst::Create(FP, "", Main->begin()->getFirstNonPHI()); } } // Clear the global_ctors array. // Use eraseFromParent() instead of removeFromParent(). GV->eraseFromParent(); }
static LazyValueInfo::Tristate getPredicateResult(unsigned Pred, Constant *C, LVILatticeVal &Result, const DataLayout *DL, TargetLibraryInfo *TLI) { // If we know the value is a constant, evaluate the conditional. Constant *Res = nullptr; if (Result.isConstant()) { Res = ConstantFoldCompareInstOperands(Pred, Result.getConstant(), C, DL, TLI); if (ConstantInt *ResCI = dyn_cast<ConstantInt>(Res)) return ResCI->isZero() ? LazyValueInfo::False : LazyValueInfo::True; return LazyValueInfo::Unknown; } if (Result.isConstantRange()) { ConstantInt *CI = dyn_cast<ConstantInt>(C); if (!CI) return LazyValueInfo::Unknown; ConstantRange CR = Result.getConstantRange(); if (Pred == ICmpInst::ICMP_EQ) { if (!CR.contains(CI->getValue())) return LazyValueInfo::False; if (CR.isSingleElement() && CR.contains(CI->getValue())) return LazyValueInfo::True; } else if (Pred == ICmpInst::ICMP_NE) { if (!CR.contains(CI->getValue())) return LazyValueInfo::True; if (CR.isSingleElement() && CR.contains(CI->getValue())) return LazyValueInfo::False; } // Handle more complex predicates. ConstantRange TrueValues = ICmpInst::makeConstantRange((ICmpInst::Predicate)Pred, CI->getValue()); if (TrueValues.contains(CR)) return LazyValueInfo::True; if (TrueValues.inverse().contains(CR)) return LazyValueInfo::False; return LazyValueInfo::Unknown; } if (Result.isNotConstant()) { // If this is an equality comparison, we can try to fold it knowing that // "V != C1". if (Pred == ICmpInst::ICMP_EQ) { // !C1 == C -> false iff C1 == C. Res = ConstantFoldCompareInstOperands(ICmpInst::ICMP_NE, Result.getNotConstant(), C, DL, TLI); if (Res->isNullValue()) return LazyValueInfo::False; } else if (Pred == ICmpInst::ICMP_NE) { // !C1 != C -> true iff C1 == C. Res = ConstantFoldCompareInstOperands(ICmpInst::ICMP_NE, Result.getNotConstant(), C, DL, TLI); if (Res->isNullValue()) return LazyValueInfo::True; } return LazyValueInfo::Unknown; } return LazyValueInfo::Unknown; }
bool ReduceCrashingFunctions::TestFuncs(std::vector<Function*> &Funcs) { // If main isn't present, claim there is no problem. if (KeepMain && std::find(Funcs.begin(), Funcs.end(), BD.getProgram()->getFunction("main")) == Funcs.end()) return false; // Clone the program to try hacking it apart... ValueToValueMapTy VMap; Module *M = CloneModule(BD.getProgram(), VMap); // Convert list to set for fast lookup... std::set<Function*> Functions; for (unsigned i = 0, e = Funcs.size(); i != e; ++i) { Function *CMF = cast<Function>(VMap[Funcs[i]]); assert(CMF && "Function not in module?!"); assert(CMF->getFunctionType() == Funcs[i]->getFunctionType() && "wrong ty"); assert(CMF->getName() == Funcs[i]->getName() && "wrong name"); Functions.insert(CMF); } outs() << "Checking for crash with only these functions: "; PrintFunctionList(Funcs); outs() << ": "; if (!ReplaceFuncsWithNull) { // Loop over and delete any functions which we aren't supposed to be playing // with... for (Function &I : *M) if (!I.isDeclaration() && !Functions.count(&I)) DeleteFunctionBody(&I); } else { std::vector<GlobalValue*> ToRemove; // First, remove aliases to functions we're about to purge. for (GlobalAlias &Alias : M->aliases()) { Constant *Root = Alias.getAliasee()->stripPointerCasts(); Function *F = dyn_cast<Function>(Root); if (F) { if (Functions.count(F)) // We're keeping this function. continue; } else if (Root->isNullValue()) { // This referenced a globalalias that we've already replaced, // so we still need to replace this alias. } else if (!F) { // Not a function, therefore not something we mess with. continue; } PointerType *Ty = cast<PointerType>(Alias.getType()); Constant *Replacement = ConstantPointerNull::get(Ty); Alias.replaceAllUsesWith(Replacement); ToRemove.push_back(&Alias); } for (Function &I : *M) { if (!I.isDeclaration() && !Functions.count(&I)) { PointerType *Ty = cast<PointerType>(I.getType()); Constant *Replacement = ConstantPointerNull::get(Ty); I.replaceAllUsesWith(Replacement); ToRemove.push_back(&I); } } for (auto *F : ToRemove) { F->eraseFromParent(); } // Finally, remove any null members from any global intrinsic. RemoveFunctionReferences(M, "llvm.used"); RemoveFunctionReferences(M, "llvm.compiler.used"); } // Try running the hacked up program... if (TestFn(BD, M)) { BD.setNewProgram(M); // It crashed, keep the trimmed version... // Make sure to use function pointers that point into the now-current // module. Funcs.assign(Functions.begin(), Functions.end()); return true; } delete M; return false; }
// // Method: postOrderInline() // // Description: // This methods does a post order traversal of the call graph and performs // bottom-up inlining of the DSGraphs. // void BUDataStructures::postOrderInline (Module & M) { // Variables used for Tarjan SCC-finding algorithm. These are passed into // the recursive function used to find SCCs. std::vector<const Function*> Stack; std::map<const Function*, unsigned> ValMap; unsigned NextID = 1; // Do post order traversal on the global ctors. Use this information to update // the globals graph. const char *Name = "llvm.global_ctors"; GlobalVariable *GV = M.getNamedGlobal(Name); if (GV && !(GV->isDeclaration()) && !(GV->hasLocalLinkage())) { // Should be an array of '{ int, void ()* }' structs. The first value is // the init priority, which we ignore. ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer()); if (InitList) { for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) if (ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(i))) { if (CS->getNumOperands() != 2) break; // Not array of 2-element structs. Constant *FP = CS->getOperand(1); if (FP->isNullValue()) break; // Found a null terminator, exit. if (ConstantExpr *CE = dyn_cast<ConstantExpr>(FP)) if (CE->isCast()) FP = CE->getOperand(0); Function *F = dyn_cast<Function>(FP); if (F && !F->isDeclaration() && !ValMap.count(F)) { calculateGraphs(F, Stack, NextID, ValMap); CloneAuxIntoGlobal(getDSGraph(*F)); } } GlobalsGraph->removeTriviallyDeadNodes(); GlobalsGraph->maskIncompleteMarkers(); // Mark external globals incomplete. GlobalsGraph->markIncompleteNodes(DSGraph::IgnoreGlobals); GlobalsGraph->computeExternalFlags(DSGraph::DontMarkFormalsExternal); GlobalsGraph->computeIntPtrFlags(); // // Create equivalence classes for aliasing globals so that we only need to // record one global per DSNode. // formGlobalECs(); // propogte information calculated // from the globals graph to the other graphs. for (Module::iterator F = M.begin(); F != M.end(); ++F) { if (!(F->isDeclaration())){ DSGraph *Graph = getDSGraph(*F); cloneGlobalsInto(Graph, DSGraph::DontCloneCallNodes | DSGraph::DontCloneAuxCallNodes); Graph->buildCallGraph(callgraph, GlobalFunctionList, filterCallees); Graph->maskIncompleteMarkers(); Graph->markIncompleteNodes(DSGraph::MarkFormalArgs | DSGraph::IgnoreGlobals); Graph->computeExternalFlags(DSGraph::DontMarkFormalsExternal); Graph->computeIntPtrFlags(); } } } } // // Start the post order traversal with the main() function. If there is no // main() function, don't worry; we'll have a separate traversal for inlining // graphs for functions not reachable from main(). // Function *MainFunc = M.getFunction ("main"); if (MainFunc && !MainFunc->isDeclaration()) { calculateGraphs(MainFunc, Stack, NextID, ValMap); CloneAuxIntoGlobal(getDSGraph(*MainFunc)); } // // Calculate the graphs for any functions that are unreachable from main... // for (Function &F : M) if (!F.isDeclaration() && !ValMap.count(&F)) { if (MainFunc) DEBUG(errs() << debugname << ": Function unreachable from main: " << F.getName() << "\n"); calculateGraphs(&F, Stack, NextID, ValMap); // Calculate all graphs. CloneAuxIntoGlobal(getDSGraph(F)); // Mark this graph as processed. Do this by finding all functions // in the graph that map to it, and mark them visited. // Note that this really should be handled neatly by calculateGraphs // itself, not here. However this catches the worst offenders. DSGraph *G = getDSGraph(F); for(DSGraph::retnodes_iterator RI = G->retnodes_begin(), RE = G->retnodes_end(); RI != RE; ++RI) { if (getDSGraph(*RI->first) == G) { if (!ValMap.count(RI->first)) ValMap[RI->first] = ~0U; else assert(ValMap[RI->first] == ~0U); } } } return; }
void ControlFlowIntegrity::ParseAnnotations(void) { GlobalVariable *global_ctors = _M.getNamedGlobal("llvm.global.annotations"); // check for ctor section if (!global_ctors || !global_ctors->getOperand(0)) { return; } Constant *c = global_ctors->getInitializer(); if (!c) report_fatal_error("llvm.global.annotations without initializer!", false); ConstantArray *CA = dyn_cast<ConstantArray>(c); if (!CA) report_fatal_error("Cast to ConstantArray failed", true); for (Value *Op : ValueOpRange(*CA)) { ConstantStruct *CS = dyn_cast<ConstantStruct>(Op); if (!CS) report_fatal_error("Cast to ConstantStruct failed", true); Constant *FP = CS->getOperand(0); if (FP->isNullValue()) break; // found a NULL termintator, stop here ConstantExpr *CE; Function *F = dyn_cast_or_null<Function>(FP); if (F == NULL) { // Strip off constant expression cast CE = dyn_cast<ConstantExpr>(FP); if (!CE) report_fatal_error("Cast to ConstantExpr failed", true); if (CE->isCast()) { FP = CE->getOperand(0); F = dyn_cast_or_null<Function>(FP); } } if (!F) report_fatal_error("Cast to Function failed", true); Constant *SP = CS->getOperand(1); if (SP->isNullValue()) break; // found a NULL termintator, stop here // Strip off constant expression cast CE = dyn_cast<ConstantExpr>(SP); if (!CE) report_fatal_error("Cast to ConstantExpr failed", true); if (CE->isCast()) { SP = CE->getOperand(0); } Value *V = SP->getOperand(0); GlobalVariable *GV = dyn_cast_or_null<GlobalVariable>(V); if (!GV) report_fatal_error("Cast to GlobalVariable failed", false); assert(GV && "cast to GlobalVariable failed"); Constant *cval = GV->getInitializer(); const StringRef s = (cast<ConstantDataArray>(cval))->getAsCString(); if (s == ANNOTATION_IGNORE_BLOCK) { _IgnoredBlocksFunctions.insert(F->getName()); } } if (global_ctors->getNumUses() > 0) report_fatal_error("llvm.global.annotations uses count is > 0", false); }
bool SparcAsmPrinter::doFinalization(Module &M) { const TargetData *TD = TM.getTargetData(); // Print out module-level global variables here. for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) if (I->hasInitializer()) { // External global require no code // Check to see if this is a special global used by LLVM, if so, emit it. if (EmitSpecialLLVMGlobal(I)) continue; O << "\n\n"; std::string name = Mang->getValueName(I); Constant *C = I->getInitializer(); unsigned Size = TD->getABITypeSize(C->getType()); unsigned Align = TD->getPreferredAlignment(I); if (C->isNullValue() && (I->hasLinkOnceLinkage() || I->hasInternalLinkage() || I->hasWeakLinkage() /* FIXME: Verify correct */)) { SwitchToDataSection(".data", I); if (I->hasInternalLinkage()) O << "\t.local " << name << "\n"; O << "\t.comm " << name << "," << TD->getABITypeSize(C->getType()) << "," << Align; O << "\n"; } else { switch (I->getLinkage()) { case GlobalValue::LinkOnceLinkage: case GlobalValue::WeakLinkage: // FIXME: Verify correct for weak. // Nonnull linkonce -> weak O << "\t.weak " << name << "\n"; SwitchToDataSection("", I); O << "\t.section\t\".llvm.linkonce.d." << name << "\",\"aw\",@progbits\n"; break; case GlobalValue::AppendingLinkage: // FIXME: appending linkage variables should go into a section of // their name or something. For now, just emit them as external. case GlobalValue::ExternalLinkage: // If external or appending, declare as a global symbol O << "\t.globl " << name << "\n"; // FALL THROUGH case GlobalValue::InternalLinkage: if (C->isNullValue()) SwitchToDataSection(".bss", I); else SwitchToDataSection(".data", I); break; case GlobalValue::GhostLinkage: cerr << "Should not have any unmaterialized functions!\n"; abort(); case GlobalValue::DLLImportLinkage: cerr << "DLLImport linkage is not supported by this target!\n"; abort(); case GlobalValue::DLLExportLinkage: cerr << "DLLExport linkage is not supported by this target!\n"; abort(); default: assert(0 && "Unknown linkage type!"); } O << "\t.align " << Align << "\n"; O << "\t.type " << name << ",#object\n"; O << "\t.size " << name << "," << Size << "\n"; O << name << ":\n"; EmitGlobalConstant(C); } } return AsmPrinter::doFinalization(M); }
/// getPredicateOnEdge - Determine whether the specified value comparison /// with a constant is known to be true or false on the specified CFG edge. /// Pred is a CmpInst predicate. LazyValueInfo::Tristate LazyValueInfo::getPredicateOnEdge(unsigned Pred, Value *V, Constant *C, BasicBlock *FromBB, BasicBlock *ToBB) { LVILatticeVal Result = getCache(PImpl).getValueOnEdge(V, FromBB, ToBB); // If we know the value is a constant, evaluate the conditional. Constant *Res = 0; if (Result.isConstant()) { Res = ConstantFoldCompareInstOperands(Pred, Result.getConstant(), C, TD, TLI); if (ConstantInt *ResCI = dyn_cast<ConstantInt>(Res)) return ResCI->isZero() ? False : True; return Unknown; } if (Result.isConstantRange()) { ConstantInt *CI = dyn_cast<ConstantInt>(C); if (!CI) return Unknown; ConstantRange CR = Result.getConstantRange(); if (Pred == ICmpInst::ICMP_EQ) { if (!CR.contains(CI->getValue())) return False; if (CR.isSingleElement() && CR.contains(CI->getValue())) return True; } else if (Pred == ICmpInst::ICMP_NE) { if (!CR.contains(CI->getValue())) return True; if (CR.isSingleElement() && CR.contains(CI->getValue())) return False; } // Handle more complex predicates. ConstantRange TrueValues = ICmpInst::makeConstantRange((ICmpInst::Predicate)Pred, CI->getValue()); if (TrueValues.contains(CR)) return True; if (TrueValues.inverse().contains(CR)) return False; return Unknown; } if (Result.isNotConstant()) { // If this is an equality comparison, we can try to fold it knowing that // "V != C1". if (Pred == ICmpInst::ICMP_EQ) { // !C1 == C -> false iff C1 == C. Res = ConstantFoldCompareInstOperands(ICmpInst::ICMP_NE, Result.getNotConstant(), C, TD, TLI); if (Res->isNullValue()) return False; } else if (Pred == ICmpInst::ICMP_NE) { // !C1 != C -> true iff C1 == C. Res = ConstantFoldCompareInstOperands(ICmpInst::ICMP_NE, Result.getNotConstant(), C, TD, TLI); if (Res->isNullValue()) return True; } return Unknown; } return Unknown; }
/// getFeasibleSuccessors - Return a vector of booleans to indicate which /// successors are reachable from a given terminator instruction. void SparseSolver::getFeasibleSuccessors(TerminatorInst &TI, SmallVectorImpl<bool> &Succs, bool AggressiveUndef) { Succs.resize(TI.getNumSuccessors()); if (TI.getNumSuccessors() == 0) return; if (BranchInst *BI = dyn_cast<BranchInst>(&TI)) { if (BI->isUnconditional()) { Succs[0] = true; return; } LatticeVal BCValue; if (AggressiveUndef) BCValue = getOrInitValueState(BI->getCondition()); else BCValue = getLatticeState(BI->getCondition()); if (BCValue == LatticeFunc->getOverdefinedVal() || BCValue == LatticeFunc->getUntrackedVal()) { // Overdefined condition variables can branch either way. Succs[0] = Succs[1] = true; return; } // If undefined, neither is feasible yet. if (BCValue == LatticeFunc->getUndefVal()) return; Constant *C = LatticeFunc->GetConstant(BCValue, BI->getCondition(), *this); if (C == 0 || !isa<ConstantInt>(C)) { // Non-constant values can go either way. Succs[0] = Succs[1] = true; return; } // Constant condition variables mean the branch can only go a single way Succs[C->isNullValue()] = true; return; } if (isa<InvokeInst>(TI)) { // Invoke instructions successors are always executable. // TODO: Could ask the lattice function if the value can throw. Succs[0] = Succs[1] = true; return; } if (isa<IndirectBrInst>(TI)) { Succs.assign(Succs.size(), true); return; } SwitchInst &SI = cast<SwitchInst>(TI); LatticeVal SCValue; if (AggressiveUndef) SCValue = getOrInitValueState(SI.getCondition()); else SCValue = getLatticeState(SI.getCondition()); if (SCValue == LatticeFunc->getOverdefinedVal() || SCValue == LatticeFunc->getUntrackedVal()) { // All destinations are executable! Succs.assign(TI.getNumSuccessors(), true); return; } // If undefined, neither is feasible yet. if (SCValue == LatticeFunc->getUndefVal()) return; Constant *C = LatticeFunc->GetConstant(SCValue, SI.getCondition(), *this); if (C == 0 || !isa<ConstantInt>(C)) { // All destinations are executable! Succs.assign(TI.getNumSuccessors(), true); return; } SwitchInst::CaseIt Case = SI.findCaseValue(cast<ConstantInt>(C)); Succs[Case.getSuccessorIndex()] = true; }
/// Evaluate all instructions in block BB, returning true if successful, false /// if we can't evaluate it. NewBB returns the next BB that control flows into, /// or null upon return. bool Evaluator::EvaluateBlock(BasicBlock::iterator CurInst, BasicBlock *&NextBB) { // This is the main evaluation loop. while (1) { Constant *InstResult = nullptr; DEBUG(dbgs() << "Evaluating Instruction: " << *CurInst << "\n"); if (StoreInst *SI = dyn_cast<StoreInst>(CurInst)) { if (!SI->isSimple()) { DEBUG(dbgs() << "Store is not simple! Can not evaluate.\n"); return false; // no volatile/atomic accesses. } Constant *Ptr = getVal(SI->getOperand(1)); if (auto *FoldedPtr = ConstantFoldConstant(Ptr, DL, TLI)) { DEBUG(dbgs() << "Folding constant ptr expression: " << *Ptr); Ptr = FoldedPtr; DEBUG(dbgs() << "; To: " << *Ptr << "\n"); } if (!isSimpleEnoughPointerToCommit(Ptr)) { // If this is too complex for us to commit, reject it. DEBUG(dbgs() << "Pointer is too complex for us to evaluate store."); return false; } Constant *Val = getVal(SI->getOperand(0)); // If this might be too difficult for the backend to handle (e.g. the addr // of one global variable divided by another) then we can't commit it. if (!isSimpleEnoughValueToCommit(Val, SimpleConstants, DL)) { DEBUG(dbgs() << "Store value is too complex to evaluate store. " << *Val << "\n"); return false; } if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Ptr)) { if (CE->getOpcode() == Instruction::BitCast) { DEBUG(dbgs() << "Attempting to resolve bitcast on constant ptr.\n"); // If we're evaluating a store through a bitcast, then we need // to pull the bitcast off the pointer type and push it onto the // stored value. Ptr = CE->getOperand(0); Type *NewTy = cast<PointerType>(Ptr->getType())->getElementType(); // In order to push the bitcast onto the stored value, a bitcast // from NewTy to Val's type must be legal. If it's not, we can try // introspecting NewTy to find a legal conversion. while (!Val->getType()->canLosslesslyBitCastTo(NewTy)) { // If NewTy is a struct, we can convert the pointer to the struct // into a pointer to its first member. // FIXME: This could be extended to support arrays as well. if (StructType *STy = dyn_cast<StructType>(NewTy)) { NewTy = STy->getTypeAtIndex(0U); IntegerType *IdxTy = IntegerType::get(NewTy->getContext(), 32); Constant *IdxZero = ConstantInt::get(IdxTy, 0, false); Constant * const IdxList[] = {IdxZero, IdxZero}; Ptr = ConstantExpr::getGetElementPtr(nullptr, Ptr, IdxList); if (auto *FoldedPtr = ConstantFoldConstant(Ptr, DL, TLI)) Ptr = FoldedPtr; // If we can't improve the situation by introspecting NewTy, // we have to give up. } else { DEBUG(dbgs() << "Failed to bitcast constant ptr, can not " "evaluate.\n"); return false; } } // If we found compatible types, go ahead and push the bitcast // onto the stored value. Val = ConstantExpr::getBitCast(Val, NewTy); DEBUG(dbgs() << "Evaluated bitcast: " << *Val << "\n"); } } MutatedMemory[Ptr] = Val; } else if (BinaryOperator *BO = dyn_cast<BinaryOperator>(CurInst)) { InstResult = ConstantExpr::get(BO->getOpcode(), getVal(BO->getOperand(0)), getVal(BO->getOperand(1))); DEBUG(dbgs() << "Found a BinaryOperator! Simplifying: " << *InstResult << "\n"); } else if (CmpInst *CI = dyn_cast<CmpInst>(CurInst)) { InstResult = ConstantExpr::getCompare(CI->getPredicate(), getVal(CI->getOperand(0)), getVal(CI->getOperand(1))); DEBUG(dbgs() << "Found a CmpInst! Simplifying: " << *InstResult << "\n"); } else if (CastInst *CI = dyn_cast<CastInst>(CurInst)) { InstResult = ConstantExpr::getCast(CI->getOpcode(), getVal(CI->getOperand(0)), CI->getType()); DEBUG(dbgs() << "Found a Cast! Simplifying: " << *InstResult << "\n"); } else if (SelectInst *SI = dyn_cast<SelectInst>(CurInst)) { InstResult = ConstantExpr::getSelect(getVal(SI->getOperand(0)), getVal(SI->getOperand(1)), getVal(SI->getOperand(2))); DEBUG(dbgs() << "Found a Select! Simplifying: " << *InstResult << "\n"); } else if (auto *EVI = dyn_cast<ExtractValueInst>(CurInst)) { InstResult = ConstantExpr::getExtractValue( getVal(EVI->getAggregateOperand()), EVI->getIndices()); DEBUG(dbgs() << "Found an ExtractValueInst! Simplifying: " << *InstResult << "\n"); } else if (auto *IVI = dyn_cast<InsertValueInst>(CurInst)) { InstResult = ConstantExpr::getInsertValue( getVal(IVI->getAggregateOperand()), getVal(IVI->getInsertedValueOperand()), IVI->getIndices()); DEBUG(dbgs() << "Found an InsertValueInst! Simplifying: " << *InstResult << "\n"); } else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(CurInst)) { Constant *P = getVal(GEP->getOperand(0)); SmallVector<Constant*, 8> GEPOps; for (User::op_iterator i = GEP->op_begin() + 1, e = GEP->op_end(); i != e; ++i) GEPOps.push_back(getVal(*i)); InstResult = ConstantExpr::getGetElementPtr(GEP->getSourceElementType(), P, GEPOps, cast<GEPOperator>(GEP)->isInBounds()); DEBUG(dbgs() << "Found a GEP! Simplifying: " << *InstResult << "\n"); } else if (LoadInst *LI = dyn_cast<LoadInst>(CurInst)) { if (!LI->isSimple()) { DEBUG(dbgs() << "Found a Load! Not a simple load, can not evaluate.\n"); return false; // no volatile/atomic accesses. } Constant *Ptr = getVal(LI->getOperand(0)); if (auto *FoldedPtr = ConstantFoldConstant(Ptr, DL, TLI)) { Ptr = FoldedPtr; DEBUG(dbgs() << "Found a constant pointer expression, constant " "folding: " << *Ptr << "\n"); } InstResult = ComputeLoadResult(Ptr); if (!InstResult) { DEBUG(dbgs() << "Failed to compute load result. Can not evaluate load." "\n"); return false; // Could not evaluate load. } DEBUG(dbgs() << "Evaluated load: " << *InstResult << "\n"); } else if (AllocaInst *AI = dyn_cast<AllocaInst>(CurInst)) { if (AI->isArrayAllocation()) { DEBUG(dbgs() << "Found an array alloca. Can not evaluate.\n"); return false; // Cannot handle array allocs. } Type *Ty = AI->getAllocatedType(); AllocaTmps.push_back( make_unique<GlobalVariable>(Ty, false, GlobalValue::InternalLinkage, UndefValue::get(Ty), AI->getName())); InstResult = AllocaTmps.back().get(); DEBUG(dbgs() << "Found an alloca. Result: " << *InstResult << "\n"); } else if (isa<CallInst>(CurInst) || isa<InvokeInst>(CurInst)) { CallSite CS(&*CurInst); // Debug info can safely be ignored here. if (isa<DbgInfoIntrinsic>(CS.getInstruction())) { DEBUG(dbgs() << "Ignoring debug info.\n"); ++CurInst; continue; } // Cannot handle inline asm. if (isa<InlineAsm>(CS.getCalledValue())) { DEBUG(dbgs() << "Found inline asm, can not evaluate.\n"); return false; } if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(CS.getInstruction())) { if (MemSetInst *MSI = dyn_cast<MemSetInst>(II)) { if (MSI->isVolatile()) { DEBUG(dbgs() << "Can not optimize a volatile memset " << "intrinsic.\n"); return false; } Constant *Ptr = getVal(MSI->getDest()); Constant *Val = getVal(MSI->getValue()); Constant *DestVal = ComputeLoadResult(getVal(Ptr)); if (Val->isNullValue() && DestVal && DestVal->isNullValue()) { // This memset is a no-op. DEBUG(dbgs() << "Ignoring no-op memset.\n"); ++CurInst; continue; } } if (II->getIntrinsicID() == Intrinsic::lifetime_start || II->getIntrinsicID() == Intrinsic::lifetime_end) { DEBUG(dbgs() << "Ignoring lifetime intrinsic.\n"); ++CurInst; continue; } if (II->getIntrinsicID() == Intrinsic::invariant_start) { // We don't insert an entry into Values, as it doesn't have a // meaningful return value. if (!II->use_empty()) { DEBUG(dbgs() << "Found unused invariant_start. Can't evaluate.\n"); return false; } ConstantInt *Size = cast<ConstantInt>(II->getArgOperand(0)); Value *PtrArg = getVal(II->getArgOperand(1)); Value *Ptr = PtrArg->stripPointerCasts(); if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Ptr)) { Type *ElemTy = GV->getValueType(); if (!Size->isMinusOne() && Size->getValue().getLimitedValue() >= DL.getTypeStoreSize(ElemTy)) { Invariants.insert(GV); DEBUG(dbgs() << "Found a global var that is an invariant: " << *GV << "\n"); } else { DEBUG(dbgs() << "Found a global var, but can not treat it as an " "invariant.\n"); } } // Continue even if we do nothing. ++CurInst; continue; } else if (II->getIntrinsicID() == Intrinsic::assume) { DEBUG(dbgs() << "Skipping assume intrinsic.\n"); ++CurInst; continue; } DEBUG(dbgs() << "Unknown intrinsic. Can not evaluate.\n"); return false; } // Resolve function pointers. Function *Callee = dyn_cast<Function>(getVal(CS.getCalledValue())); if (!Callee || Callee->isInterposable()) { DEBUG(dbgs() << "Can not resolve function pointer.\n"); return false; // Cannot resolve. } SmallVector<Constant*, 8> Formals; for (User::op_iterator i = CS.arg_begin(), e = CS.arg_end(); i != e; ++i) Formals.push_back(getVal(*i)); if (Callee->isDeclaration()) { // If this is a function we can constant fold, do it. if (Constant *C = ConstantFoldCall(CS, Callee, Formals, TLI)) { InstResult = C; DEBUG(dbgs() << "Constant folded function call. Result: " << *InstResult << "\n"); } else { DEBUG(dbgs() << "Can not constant fold function call.\n"); return false; } } else { if (Callee->getFunctionType()->isVarArg()) { DEBUG(dbgs() << "Can not constant fold vararg function call.\n"); return false; } Constant *RetVal = nullptr; // Execute the call, if successful, use the return value. ValueStack.emplace_back(); if (!EvaluateFunction(Callee, RetVal, Formals)) { DEBUG(dbgs() << "Failed to evaluate function.\n"); return false; } ValueStack.pop_back(); InstResult = RetVal; if (InstResult) { DEBUG(dbgs() << "Successfully evaluated function. Result: " << *InstResult << "\n\n"); } else { DEBUG(dbgs() << "Successfully evaluated function. Result: 0\n\n"); } } } else if (isa<TerminatorInst>(CurInst)) { DEBUG(dbgs() << "Found a terminator instruction.\n"); if (BranchInst *BI = dyn_cast<BranchInst>(CurInst)) { if (BI->isUnconditional()) { NextBB = BI->getSuccessor(0); } else { ConstantInt *Cond = dyn_cast<ConstantInt>(getVal(BI->getCondition())); if (!Cond) return false; // Cannot determine. NextBB = BI->getSuccessor(!Cond->getZExtValue()); } } else if (SwitchInst *SI = dyn_cast<SwitchInst>(CurInst)) { ConstantInt *Val = dyn_cast<ConstantInt>(getVal(SI->getCondition())); if (!Val) return false; // Cannot determine. NextBB = SI->findCaseValue(Val)->getCaseSuccessor(); } else if (IndirectBrInst *IBI = dyn_cast<IndirectBrInst>(CurInst)) { Value *Val = getVal(IBI->getAddress())->stripPointerCasts(); if (BlockAddress *BA = dyn_cast<BlockAddress>(Val)) NextBB = BA->getBasicBlock(); else return false; // Cannot determine. } else if (isa<ReturnInst>(CurInst)) { NextBB = nullptr; } else { // invoke, unwind, resume, unreachable. DEBUG(dbgs() << "Can not handle terminator."); return false; // Cannot handle this terminator. } // We succeeded at evaluating this block! DEBUG(dbgs() << "Successfully evaluated block.\n"); return true; } else { // Did not know how to evaluate this! DEBUG(dbgs() << "Failed to evaluate block due to unhandled instruction." "\n"); return false; } if (!CurInst->use_empty()) { if (auto *FoldedInstResult = ConstantFoldConstant(InstResult, DL, TLI)) InstResult = FoldedInstResult; setVal(&*CurInst, InstResult); } // If we just processed an invoke, we finished evaluating the block. if (InvokeInst *II = dyn_cast<InvokeInst>(CurInst)) { NextBB = II->getNormalDest(); DEBUG(dbgs() << "Found an invoke instruction. Finished Block.\n\n"); return true; } // Advance program counter. ++CurInst; } }
void IA64AsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) { const TargetData *TD = TM.getTargetData(); if (!GVar->hasInitializer()) return; // External global require no code // Check to see if this is a special global used by LLVM, if so, emit it. if (EmitSpecialLLVMGlobal(GVar)) return; O << "\n\n"; std::string name = Mang->getValueName(GVar); Constant *C = GVar->getInitializer(); unsigned Size = TD->getTypePaddedSize(C->getType()); unsigned Align = TD->getPreferredAlignmentLog(GVar); printVisibility(name, GVar->getVisibility()); SwitchToSection(TAI->SectionForGlobal(GVar)); if (C->isNullValue() && !GVar->hasSection()) { if (!GVar->isThreadLocal() && (GVar->hasLocalLinkage() || GVar->isWeakForLinker())) { if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. if (GVar->hasLocalLinkage()) { O << "\t.lcomm " << name << "#," << Size << ',' << (1 << Align); O << '\n'; } else { O << "\t.common " << name << "#," << Size << ',' << (1 << Align); O << '\n'; } return; } } switch (GVar->getLinkage()) { case GlobalValue::LinkOnceAnyLinkage: case GlobalValue::LinkOnceODRLinkage: case GlobalValue::CommonLinkage: case GlobalValue::WeakAnyLinkage: case GlobalValue::WeakODRLinkage: // Nonnull linkonce -> weak O << "\t.weak " << name << '\n'; break; case GlobalValue::AppendingLinkage: // FIXME: appending linkage variables should go into a section of // their name or something. For now, just emit them as external. case GlobalValue::ExternalLinkage: // If external or appending, declare as a global symbol O << TAI->getGlobalDirective() << name << '\n'; // FALL THROUGH case GlobalValue::InternalLinkage: case GlobalValue::PrivateLinkage: break; case GlobalValue::GhostLinkage: cerr << "GhostLinkage cannot appear in IA64AsmPrinter!\n"; abort(); case GlobalValue::DLLImportLinkage: cerr << "DLLImport linkage is not supported by this target!\n"; abort(); case GlobalValue::DLLExportLinkage: cerr << "DLLExport linkage is not supported by this target!\n"; abort(); default: assert(0 && "Unknown linkage type!"); } EmitAlignment(Align, GVar); if (TAI->hasDotTypeDotSizeDirective()) { O << "\t.type " << name << ",@object\n"; O << "\t.size " << name << ',' << Size << '\n'; } O << name << ":\n"; EmitGlobalConstant(C); }