本文整理汇总了C++中Constant::getType方法的典型用法代码示例。如果您正苦于以下问题:C++ Constant::getType方法的具体用法?C++ Constant::getType怎么用?C++ Constant::getType使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类Constant
的用法示例。
在下文中一共展示了Constant::getType方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: EmitGlobalVariable
void XCoreAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
// Check to see if this is a special global used by LLVM, if so, emit it.
if (!GV->hasInitializer() ||
EmitSpecialLLVMGlobal(GV))
return;
const TargetData *TD = TM.getTargetData();
OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GV, Mang,TM));
MCSymbol *GVSym = Mang->getSymbol(GV);
Constant *C = GV->getInitializer();
unsigned Align = (unsigned)TD->getPreferredTypeAlignmentShift(C->getType());
// Mark the start of the global
OutStreamer.EmitRawText("\t.cc_top " + Twine(GVSym->getName()) + ".data," +
GVSym->getName());
switch (GV->getLinkage()) {
case GlobalValue::AppendingLinkage:
report_fatal_error("AppendingLinkage is not supported by this target!");
case GlobalValue::LinkOnceAnyLinkage:
case GlobalValue::LinkOnceODRLinkage:
case GlobalValue::WeakAnyLinkage:
case GlobalValue::WeakODRLinkage:
case GlobalValue::ExternalLinkage:
emitArrayBound(GVSym, GV);
OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global);
// TODO Use COMDAT groups for LinkOnceLinkage
if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage())
OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Weak);
// FALL THROUGH
case GlobalValue::InternalLinkage:
case GlobalValue::PrivateLinkage:
case GlobalValue::LinkerPrivateLinkage:
break;
case GlobalValue::DLLImportLinkage:
llvm_unreachable("DLLImport linkage is not supported by this target!");
case GlobalValue::DLLExportLinkage:
llvm_unreachable("DLLExport linkage is not supported by this target!");
default:
llvm_unreachable("Unknown linkage type!");
}
EmitAlignment(Align > 2 ? Align : 2, GV);
unsigned Size = TD->getTypeAllocSize(C->getType());
if (GV->isThreadLocal()) {
Size *= MaxThreads;
}
if (MAI->hasDotTypeDotSizeDirective()) {
OutStreamer.EmitSymbolAttribute(GVSym, MCSA_ELF_TypeObject);
OutStreamer.EmitRawText("\t.size " + Twine(GVSym->getName()) + "," +
Twine(Size));
}
OutStreamer.EmitLabel(GVSym);
EmitGlobalConstant(C);
if (GV->isThreadLocal()) {
for (unsigned i = 1; i < MaxThreads; ++i)
EmitGlobalConstant(C);
}
// The ABI requires that unsigned scalar types smaller than 32 bits
// are padded to 32 bits.
if (Size < 4)
OutStreamer.EmitZeros(4 - Size, 0);
// Mark the end of the global
OutStreamer.EmitRawText("\t.cc_bottom " + Twine(GVSym->getName()) + ".data");
}
示例2: llvm_asm_file_end
// llvm_asm_file_end - Finish the .s file.
void llvm_asm_file_end(void) {
timevar_push(TV_LLVM_PERFILE);
llvm_shutdown_obj X; // Call llvm_shutdown() on exit.
if (flag_pch_file) {
writeLLVMTypesStringTable();
writeLLVMValues();
}
// Add an llvm.global_ctors global if needed.
if (!StaticCtors.empty())
CreateStructorsList(StaticCtors, "llvm.global_ctors");
// Add an llvm.global_dtors global if needed.
if (!StaticDtors.empty())
CreateStructorsList(StaticDtors, "llvm.global_dtors");
if (!AttributeUsedGlobals.empty()) {
const Type *SBP = PointerType::get(Type::Int8Ty);
ArrayType *AT = ArrayType::get(SBP, AttributeUsedGlobals.size());
Constant *Init = ConstantArray::get(AT, AttributeUsedGlobals);
GlobalValue* gv = new GlobalVariable(AT, false,
GlobalValue::AppendingLinkage, Init,
"llvm.used", TheModule);
gv->setSection("llvm.metadata");
AttributeUsedGlobals.clear();
}
// Add llvm.noinline
if (!AttributeNoinlineFunctions.empty()) {
const Type *SBP= PointerType::get(Type::Int8Ty);
ArrayType *AT = ArrayType::get(SBP, AttributeNoinlineFunctions.size());
Constant *Init = ConstantArray::get(AT, AttributeNoinlineFunctions);
GlobalValue *gv = new GlobalVariable(AT, false,
GlobalValue::AppendingLinkage, Init,
"llvm.noinline", TheModule);
gv->setSection("llvm.metadata");
// Clear vector
AttributeNoinlineFunctions.clear();
}
// Add llvm.global.annotations
if (!AttributeAnnotateGlobals.empty()) {
Constant *Array =
ConstantArray::get(ArrayType::get(AttributeAnnotateGlobals[0]->getType(),
AttributeAnnotateGlobals.size()),
AttributeAnnotateGlobals);
GlobalValue *gv = new GlobalVariable(Array->getType(), false,
GlobalValue::AppendingLinkage, Array,
"llvm.global.annotations", TheModule);
gv->setSection("llvm.metadata");
AttributeAnnotateGlobals.clear();
}
// Finish off the per-function pass.
if (PerFunctionPasses)
PerFunctionPasses->doFinalization();
// Run module-level optimizers, if any are present.
if (PerModulePasses)
PerModulePasses->run(*TheModule);
// Run the code generator, if present.
if (CodeGenPasses) {
CodeGenPasses->doInitialization();
for (Module::iterator I = TheModule->begin(), E = TheModule->end();
I != E; ++I)
if (!I->isDeclaration())
CodeGenPasses->run(*I);
CodeGenPasses->doFinalization();
}
AsmOutStream->flush();
fflush(asm_out_file);
delete AsmOutStream;
AsmOutStream = 0;
delete AsmOutFile;
AsmOutFile = 0;
timevar_pop(TV_LLVM_PERFILE);
}
示例3: emit_global_to_llvm
/// emit_global_to_llvm - Emit the specified VAR_DECL or aggregate CONST_DECL to
/// LLVM as a global variable. This function implements the end of
/// assemble_variable.
void emit_global_to_llvm(tree decl) {
if (errorcount || sorrycount) return;
// FIXME: Support alignment on globals: DECL_ALIGN.
// FIXME: DECL_PRESERVE_P indicates the var is marked with attribute 'used'.
// Global register variables don't turn into LLVM GlobalVariables.
if (TREE_CODE(decl) == VAR_DECL && DECL_REGISTER(decl))
return;
timevar_push(TV_LLVM_GLOBALS);
// Get or create the global variable now.
GlobalVariable *GV = cast<GlobalVariable>(DECL_LLVM(decl));
// Convert the initializer over.
Constant *Init;
if (DECL_INITIAL(decl) == 0 || DECL_INITIAL(decl) == error_mark_node) {
// This global should be zero initialized. Reconvert the type in case the
// forward def of the global and the real def differ in type (e.g. declared
// as 'int A[]', and defined as 'int A[100]').
Init = Constant::getNullValue(ConvertType(TREE_TYPE(decl)));
} else {
assert((TREE_CONSTANT(DECL_INITIAL(decl)) ||
TREE_CODE(DECL_INITIAL(decl)) == STRING_CST) &&
"Global initializer should be constant!");
// Temporarily set an initializer for the global, so we don't infinitely
// recurse. If we don't do this, we can hit cases where we see "oh a global
// with an initializer hasn't been initialized yet, call emit_global_to_llvm
// on it". When constructing the initializer it might refer to itself.
// this can happen for things like void *G = &G;
//
GV->setInitializer(UndefValue::get(GV->getType()->getElementType()));
Init = TreeConstantToLLVM::Convert(DECL_INITIAL(decl));
}
// If we had a forward definition that has a type that disagrees with our
// initializer, insert a cast now. This sort of thing occurs when we have a
// global union, and the LLVM type followed a union initializer that is
// different from the union element used for the type.
if (GV->getType()->getElementType() != Init->getType()) {
GV->removeFromParent();
GlobalVariable *NGV = new GlobalVariable(Init->getType(), GV->isConstant(),
GlobalValue::ExternalLinkage, 0,
GV->getName(), TheModule);
GV->replaceAllUsesWith(ConstantExpr::getBitCast(NGV, GV->getType()));
delete GV;
SET_DECL_LLVM(decl, NGV);
GV = NGV;
}
// Set the initializer.
GV->setInitializer(Init);
// Set thread local (TLS)
if (TREE_CODE(decl) == VAR_DECL && DECL_THREAD_LOCAL(decl))
GV->setThreadLocal(true);
// Set the linkage.
if (!TREE_PUBLIC(decl)) {
GV->setLinkage(GlobalValue::InternalLinkage);
} else if (DECL_WEAK(decl) || DECL_ONE_ONLY(decl) ||
(DECL_COMMON(decl) && // DECL_COMMON is only meaningful if no init
(!DECL_INITIAL(decl) || DECL_INITIAL(decl) == error_mark_node))) {
// llvm-gcc also includes DECL_VIRTUAL_P here.
GV->setLinkage(GlobalValue::WeakLinkage);
} else if (DECL_COMDAT(decl)) {
GV->setLinkage(GlobalValue::LinkOnceLinkage);
}
#ifdef TARGET_ADJUST_LLVM_LINKAGE
TARGET_ADJUST_LLVM_LINKAGE(GV,decl);
#endif /* TARGET_ADJUST_LLVM_LINKAGE */
// Handle visibility style
if (TREE_PUBLIC(decl)) {
if (DECL_VISIBILITY(decl) == VISIBILITY_HIDDEN)
GV->setVisibility(GlobalValue::HiddenVisibility);
else if (DECL_VISIBILITY(decl) == VISIBILITY_PROTECTED)
GV->setVisibility(GlobalValue::ProtectedVisibility);
}
// Set the section for the global.
if (TREE_CODE(decl) == VAR_DECL || TREE_CODE(decl) == CONST_DECL) {
if (DECL_SECTION_NAME(decl)) {
GV->setSection(TREE_STRING_POINTER(DECL_SECTION_NAME(decl)));
#ifdef LLVM_IMPLICIT_TARGET_GLOBAL_VAR_SECTION
} else if (const char *Section =
LLVM_IMPLICIT_TARGET_GLOBAL_VAR_SECTION(decl)) {
GV->setSection(Section);
#endif
}
// Set the alignment for the global if one of the following condition is met
// 1) DECL_ALIGN_UNIT does not match alignment as per ABI specification
// 2) DECL_ALIGN is set by user.
//.........这里部分代码省略.........
示例4: runOnModule
bool SanitizerCoverageModule::runOnModule(Module &M) {
if (Options.CoverageType == SanitizerCoverageOptions::SCK_None)
return false;
C = &(M.getContext());
DL = &M.getDataLayout();
CurModule = &M;
IntptrTy = Type::getIntNTy(*C, DL->getPointerSizeInBits());
Type *VoidTy = Type::getVoidTy(*C);
IRBuilder<> IRB(*C);
Type *Int8PtrTy = PointerType::getUnqual(IRB.getInt8Ty());
Type *Int32PtrTy = PointerType::getUnqual(IRB.getInt32Ty());
Int64PtrTy = PointerType::getUnqual(IRB.getInt64Ty());
Int64Ty = IRB.getInt64Ty();
SanCovFunction = checkSanitizerInterfaceFunction(
M.getOrInsertFunction(kSanCovName, VoidTy, Int32PtrTy, nullptr));
SanCovWithCheckFunction = checkSanitizerInterfaceFunction(
M.getOrInsertFunction(kSanCovWithCheckName, VoidTy, Int32PtrTy, nullptr));
SanCovIndirCallFunction =
checkSanitizerInterfaceFunction(M.getOrInsertFunction(
kSanCovIndirCallName, VoidTy, IntptrTy, IntptrTy, nullptr));
SanCovTraceCmpFunction =
checkSanitizerInterfaceFunction(M.getOrInsertFunction(
kSanCovTraceCmp, VoidTy, Int64Ty, Int64Ty, Int64Ty, nullptr));
SanCovTraceSwitchFunction =
checkSanitizerInterfaceFunction(M.getOrInsertFunction(
kSanCovTraceSwitch, VoidTy, Int64Ty, Int64PtrTy, nullptr));
// We insert an empty inline asm after cov callbacks to avoid callback merge.
EmptyAsm = InlineAsm::get(FunctionType::get(IRB.getVoidTy(), false),
StringRef(""), StringRef(""),
/*hasSideEffects=*/true);
SanCovTraceEnter = checkSanitizerInterfaceFunction(
M.getOrInsertFunction(kSanCovTraceEnter, VoidTy, Int32PtrTy, nullptr));
SanCovTraceBB = checkSanitizerInterfaceFunction(
M.getOrInsertFunction(kSanCovTraceBB, VoidTy, Int32PtrTy, nullptr));
// At this point we create a dummy array of guards because we don't
// know how many elements we will need.
Type *Int32Ty = IRB.getInt32Ty();
Type *Int8Ty = IRB.getInt8Ty();
GuardArray =
new GlobalVariable(M, Int32Ty, false, GlobalValue::ExternalLinkage,
nullptr, "__sancov_gen_cov_tmp");
if (Options.Use8bitCounters)
EightBitCounterArray =
new GlobalVariable(M, Int8Ty, false, GlobalVariable::ExternalLinkage,
nullptr, "__sancov_gen_cov_tmp");
for (auto &F : M)
runOnFunction(F);
auto N = NumberOfInstrumentedBlocks();
// Now we know how many elements we need. Create an array of guards
// with one extra element at the beginning for the size.
Type *Int32ArrayNTy = ArrayType::get(Int32Ty, N + 1);
GlobalVariable *RealGuardArray = new GlobalVariable(
M, Int32ArrayNTy, false, GlobalValue::PrivateLinkage,
Constant::getNullValue(Int32ArrayNTy), "__sancov_gen_cov");
// Replace the dummy array with the real one.
GuardArray->replaceAllUsesWith(
IRB.CreatePointerCast(RealGuardArray, Int32PtrTy));
GuardArray->eraseFromParent();
GlobalVariable *RealEightBitCounterArray;
if (Options.Use8bitCounters) {
// Make sure the array is 16-aligned.
static const int kCounterAlignment = 16;
Type *Int8ArrayNTy =
ArrayType::get(Int8Ty, RoundUpToAlignment(N, kCounterAlignment));
RealEightBitCounterArray = new GlobalVariable(
M, Int8ArrayNTy, false, GlobalValue::PrivateLinkage,
Constant::getNullValue(Int8ArrayNTy), "__sancov_gen_cov_counter");
RealEightBitCounterArray->setAlignment(kCounterAlignment);
EightBitCounterArray->replaceAllUsesWith(
IRB.CreatePointerCast(RealEightBitCounterArray, Int8PtrTy));
EightBitCounterArray->eraseFromParent();
}
// Create variable for module (compilation unit) name
Constant *ModNameStrConst =
ConstantDataArray::getString(M.getContext(), M.getName(), true);
GlobalVariable *ModuleName =
new GlobalVariable(M, ModNameStrConst->getType(), true,
GlobalValue::PrivateLinkage, ModNameStrConst);
Function *CtorFunc;
std::tie(CtorFunc, std::ignore) = createSanitizerCtorAndInitFunctions(
M, kSanCovModuleCtorName, kSanCovModuleInitName,
{Int32PtrTy, IntptrTy, Int8PtrTy, Int8PtrTy},
{IRB.CreatePointerCast(RealGuardArray, Int32PtrTy),
ConstantInt::get(IntptrTy, N),
Options.Use8bitCounters
? IRB.CreatePointerCast(RealEightBitCounterArray, Int8PtrTy)
: Constant::getNullValue(Int8PtrTy),
//.........这里部分代码省略.........
示例5: jl_dump_native
void jl_dump_native(const char *bc_fname, const char *unopt_bc_fname, const char *obj_fname, const char *sysimg_data, size_t sysimg_len)
{
JL_TIMING(NATIVE_DUMP);
// We don't want to use MCJIT's target machine because
// it uses the large code model and we may potentially
// want less optimizations there.
Triple TheTriple = Triple(jl_TargetMachine->getTargetTriple());
// make sure to emit the native object format, even if FORCE_ELF was set in codegen
#if defined(_OS_WINDOWS_)
TheTriple.setObjectFormat(Triple::COFF);
#elif defined(_OS_DARWIN_)
TheTriple.setObjectFormat(Triple::MachO);
TheTriple.setOS(llvm::Triple::MacOSX);
#endif
std::unique_ptr<TargetMachine>
TM(jl_TargetMachine->getTarget().createTargetMachine(
TheTriple.getTriple(),
jl_TargetMachine->getTargetCPU(),
jl_TargetMachine->getTargetFeatureString(),
jl_TargetMachine->Options,
#if defined(_OS_LINUX_) || defined(_OS_FREEBSD_)
Reloc::PIC_,
#else
Optional<Reloc::Model>(),
#endif
#if defined(_CPU_PPC_) || defined(_CPU_PPC64_)
// On PPC the small model is limited to 16bit offsets
CodeModel::Medium,
#else
// Use small model so that we can use signed 32bits offset in the function and GV tables
CodeModel::Small,
#endif
CodeGenOpt::Aggressive // -O3 TODO: respect command -O0 flag?
));
legacy::PassManager PM;
addTargetPasses(&PM, TM.get());
// set up optimization passes
SmallVector<char, 128> bc_Buffer;
SmallVector<char, 128> obj_Buffer;
SmallVector<char, 128> unopt_bc_Buffer;
raw_svector_ostream bc_OS(bc_Buffer);
raw_svector_ostream obj_OS(obj_Buffer);
raw_svector_ostream unopt_bc_OS(unopt_bc_Buffer);
std::vector<NewArchiveMember> bc_Archive;
std::vector<NewArchiveMember> obj_Archive;
std::vector<NewArchiveMember> unopt_bc_Archive;
std::vector<std::string> outputs;
if (unopt_bc_fname)
PM.add(createBitcodeWriterPass(unopt_bc_OS));
if (bc_fname || obj_fname)
addOptimizationPasses(&PM, jl_options.opt_level, true);
if (bc_fname)
PM.add(createBitcodeWriterPass(bc_OS));
if (obj_fname)
if (TM->addPassesToEmitFile(PM, obj_OS, TargetMachine::CGFT_ObjectFile, false))
jl_safe_printf("ERROR: target does not support generation of object files\n");
// Reset the target triple to make sure it matches the new target machine
shadow_output->setTargetTriple(TM->getTargetTriple().str());
#if JL_LLVM_VERSION >= 40000
DataLayout DL = TM->createDataLayout();
DL.reset(DL.getStringRepresentation() + "-ni:10:11:12");
shadow_output->setDataLayout(DL);
#else
shadow_output->setDataLayout(TM->createDataLayout());
#endif
// add metadata information
if (imaging_mode) {
emit_offset_table(shadow_output, jl_sysimg_gvars, "jl_sysimg_gvars");
emit_offset_table(shadow_output, jl_sysimg_fvars, "jl_sysimg_fvars");
// reflect the address of the jl_RTLD_DEFAULT_handle variable
// back to the caller, so that we can check for consistency issues
GlobalValue *jlRTLD_DEFAULT_var = shadow_output->getNamedValue("jl_RTLD_DEFAULT_handle");
addComdat(new GlobalVariable(*shadow_output,
jlRTLD_DEFAULT_var->getType(),
true,
GlobalVariable::ExternalLinkage,
jlRTLD_DEFAULT_var,
"jl_RTLD_DEFAULT_handle_pointer"));
}
// do the actual work
auto add_output = [&] (Module &M, StringRef unopt_bc_Name, StringRef bc_Name, StringRef obj_Name) {
PM.run(M);
if (unopt_bc_fname)
emit_result(unopt_bc_Archive, unopt_bc_Buffer, unopt_bc_Name, outputs);
if (bc_fname)
emit_result(bc_Archive, bc_Buffer, bc_Name, outputs);
if (obj_fname)
emit_result(obj_Archive, obj_Buffer, obj_Name, outputs);
};
add_output(*shadow_output, "unopt.bc", "text.bc", "text.o");
LLVMContext &Context = shadow_output->getContext();
//.........这里部分代码省略.........
示例6: replaceDirectCallers
/// Replace direct callers of Old with New. Also add parameters to the call to
/// \p New, which are defined by the FuncIdx's value in \p Params.
bool SwiftMergeFunctions::replaceDirectCallers(Function *Old, Function *New,
const ParamInfos &Params, unsigned FuncIdx) {
bool AllReplaced = true;
SmallVector<CallInst *, 8> Callers;
for (Use &U : Old->uses()) {
auto *I = dyn_cast<Instruction>(U.getUser());
if (!I) {
AllReplaced = false;
continue;
}
FunctionEntry *FE = getEntry(I->getFunction());
if (FE)
removeEquivalenceClassFromTree(FE);
auto *CI = dyn_cast<CallInst>(I);
if (!CI || CI->getCalledValue() != Old) {
AllReplaced = false;
continue;
}
Callers.push_back(CI);
}
if (!AllReplaced)
return false;
for (CallInst *CI : Callers) {
auto &Context = New->getContext();
auto NewPAL = New->getAttributes();
SmallVector<Type *, 8> OldParamTypes;
SmallVector<Value *, 16> NewArgs;
SmallVector<AttributeSet, 8> NewArgAttrs;
IRBuilder<> Builder(CI);
FunctionType *NewFuncTy = New->getFunctionType();
(void) NewFuncTy;
unsigned ParamIdx = 0;
// Add the existing parameters.
for (Value *OldArg : CI->arg_operands()) {
NewArgAttrs.push_back(NewPAL.getParamAttributes(ParamIdx));
NewArgs.push_back(OldArg);
OldParamTypes.push_back(OldArg->getType());
++ParamIdx;
}
// Add the new parameters.
for (const ParamInfo &PI : Params) {
assert(ParamIdx < NewFuncTy->getNumParams());
Constant *ArgValue = PI.Values[FuncIdx];
assert(ArgValue != Old &&
"should not try to replace all callers of self referencing functions");
NewArgs.push_back(ArgValue);
OldParamTypes.push_back(ArgValue->getType());
++ParamIdx;
}
auto *FType = FunctionType::get(Old->getFunctionType()->getReturnType(),
OldParamTypes, false);
auto *FPtrType = PointerType::get(FType,
cast<PointerType>(New->getType())->getAddressSpace());
Value *Callee = ConstantExpr::getBitCast(New, FPtrType);
CallInst *NewCI = Builder.CreateCall(Callee, NewArgs);
NewCI->setCallingConv(CI->getCallingConv());
// Don't transfer attributes from the function to the callee. Function
// attributes typically aren't relevant to the calling convention or ABI.
NewCI->setAttributes(AttributeList::get(Context, /*FnAttrs=*/AttributeSet(),
NewPAL.getRetAttributes(),
NewArgAttrs));
CI->replaceAllUsesWith(NewCI);
CI->eraseFromParent();
}
assert(Old->use_empty() && "should have replaced all uses of old function");
return Old->hasLocalLinkage();
}
示例7: setType
ConstantExpression::ConstantExpression(Constant constant) :
constant { constant }
{
auto type = constant.getType();
setType(*type);
}
示例8: GlobalVariable
// Create a constant for Str so that we can pass it to the run-time lib.
static GlobalVariable *createPrivateGlobalForString(Module &M, StringRef Str) {
Constant *StrConst = ConstantDataArray::getString(M.getContext(), Str);
return new GlobalVariable(M, StrConst->getType(), true,
GlobalValue::PrivateLinkage, StrConst, "");
}
示例9: doMerge
bool GlobalMerge::doMerge(SmallVectorImpl<GlobalVariable*> &Globals,
Module &M, bool isConst, unsigned AddrSpace) const {
const TargetLowering *TLI = TM->getTargetLowering();
const DataLayout *DL = TLI->getDataLayout();
// FIXME: Infer the maximum possible offset depending on the actual users
// (these max offsets are different for the users inside Thumb or ARM
// functions)
unsigned MaxOffset = TLI->getMaximalGlobalOffset();
// FIXME: Find better heuristics
std::stable_sort(Globals.begin(), Globals.end(),
[DL](const GlobalVariable *GV1, const GlobalVariable *GV2) {
Type *Ty1 = cast<PointerType>(GV1->getType())->getElementType();
Type *Ty2 = cast<PointerType>(GV2->getType())->getElementType();
return (DL->getTypeAllocSize(Ty1) < DL->getTypeAllocSize(Ty2));
});
Type *Int32Ty = Type::getInt32Ty(M.getContext());
assert(Globals.size() > 1);
// FIXME: This simple solution merges globals all together as maximum as
// possible. However, with this solution it would be hard to remove dead
// global symbols at link-time. An alternative solution could be checking
// global symbols references function by function, and make the symbols
// being referred in the same function merged and we would probably need
// to introduce heuristic algorithm to solve the merge conflict from
// different functions.
for (size_t i = 0, e = Globals.size(); i != e; ) {
size_t j = 0;
uint64_t MergedSize = 0;
std::vector<Type*> Tys;
std::vector<Constant*> Inits;
bool HasExternal = false;
GlobalVariable *TheFirstExternal = 0;
for (j = i; j != e; ++j) {
Type *Ty = Globals[j]->getType()->getElementType();
MergedSize += DL->getTypeAllocSize(Ty);
if (MergedSize > MaxOffset) {
break;
}
Tys.push_back(Ty);
Inits.push_back(Globals[j]->getInitializer());
if (Globals[j]->hasExternalLinkage() && !HasExternal) {
HasExternal = true;
TheFirstExternal = Globals[j];
}
}
// If merged variables doesn't have external linkage, we needn't to expose
// the symbol after merging.
GlobalValue::LinkageTypes Linkage = HasExternal
? GlobalValue::ExternalLinkage
: GlobalValue::InternalLinkage;
// If merged variables have external linkage, we use symbol name of the
// first variable merged as the suffix of global symbol name. This would
// be able to avoid the link-time naming conflict for globalm symbols.
Twine MergedGVName = HasExternal
? "_MergedGlobals_" + TheFirstExternal->getName()
: "_MergedGlobals";
StructType *MergedTy = StructType::get(M.getContext(), Tys);
Constant *MergedInit = ConstantStruct::get(MergedTy, Inits);
GlobalVariable *MergedGV = new GlobalVariable(
M, MergedTy, isConst, Linkage, MergedInit, MergedGVName, nullptr,
GlobalVariable::NotThreadLocal, AddrSpace);
for (size_t k = i; k < j; ++k) {
GlobalValue::LinkageTypes Linkage = Globals[k]->getLinkage();
std::string Name = Globals[k]->getName();
Constant *Idx[2] = {
ConstantInt::get(Int32Ty, 0),
ConstantInt::get(Int32Ty, k-i)
};
Constant *GEP = ConstantExpr::getInBoundsGetElementPtr(MergedGV, Idx);
Globals[k]->replaceAllUsesWith(GEP);
Globals[k]->eraseFromParent();
if (Linkage != GlobalValue::InternalLinkage) {
// Generate a new alias...
auto *PTy = cast<PointerType>(GEP->getType());
GlobalAlias::create(PTy->getElementType(), PTy->getAddressSpace(),
Linkage, Name, GEP, &M);
}
NumMerged++;
}
i = j;
}
return true;
}
示例10: doInitialization
bool ProfilingPass::doInitialization(Module &M)
{
LLVMContext& context = M.getContext();
Function* mainFunc = M.getFunction("main");
const string moduleName = M.getModuleIdentifier();
if (mainFunc!=NULL) {
//BasicBlock* entryBlock = &mainFunc->front();
Constant* Init = ConstantArray::get(context,moduleName,true); // Convert it to an LLVM Type
GlobalVariable* nameStr = new GlobalVariable(Init->getType(), true, GlobalValue::InternalLinkage, Init, "NameStr" );
M.getGlobalList().push_back( nameStr ); // Insert it into the list of globals for module
std::vector<Constant*>IndicesC(2);
IndicesC[0] = Constant::getNullValue(Type::getInt32Ty(context));
IndicesC[1] = ConstantInt::get(Type::getInt32Ty(context),0);
Constant *getElemExpr = ConstantExpr::getGetElementPtr(nameStr, &IndicesC[0], IndicesC.size());
vector<Value*> initInjectArgs;
initInjectArgs.push_back( getElemExpr );
FunctionType* initInjectionFuncType = FunctionType::get(Type::getVoidTy(context),
vector<const Type*>(1, PointerType::get(Type::getInt8Ty(context),0)),0);
//BasicBlock *exitBlock = &mainFunc->back();
Instruction *I;
for (inst_iterator fi = inst_begin(mainFunc), fe = inst_end(mainFunc); fi!=fe; ++fi){
I = &*fi;
if(isa<ReturnInst>(I))
break;
}
BasicBlock *retblock = I->getParent(); //*retpred = retblock->getSinglePredecessor();
Instruction *term = retblock->getTerminator();
Constant *endFunc = M.getOrInsertFunction("endProfiling", initInjectionFuncType);
vector<Value*> countArgs(1);
//const IntegerType* itype = IntegerType::get(context,32);
//Value* branchVal = ConstantInt::get(itype, BRANCH );
CallInst::Create(endFunc, initInjectArgs.begin(), initInjectArgs.end(), "", term);
}
else
{
Constant* Init = ConstantArray::get(context,moduleName,true); // Convert it to an LLVM Type
GlobalVariable* nameStr = new GlobalVariable(Init->getType(), true, GlobalValue::InternalLinkage, Init, "NameStr" );
M.getGlobalList().push_back( nameStr );
}
//***********************************************************************************************************
//code for loading configure file should be here
ifstream config ("llfi_configure.txt");
if (config.is_open())
{
// we need to extract information from config file here Qining
// this loop is used to know if the file is end
while ( config.good() )
{
string line;
getline (config,line);
if(line.empty()) continue;
//if the line is empty, just skip.
//Any block of configure is started with one specific function
unsigned found = line.find("FUNCTION_NAME:");
if (found < line.length())
{
//std::cout << "\nfound FUNCTION_NAME at " << found << '\n';
std::string func_name = line.substr (found + string("FUNCTION_NAME:").length(),line.length() - found - string("FUNCTION_NAME:").length());
//first, I need to trim it
while(func_name[0] == ' ')
{
func_name.erase(0, 1);
}
while(func_name[func_name.length() - 1] == ' ')
{
func_name.erase(func_name.length() - 1, 0);
}
//so now I've got the name of the function
if(func_name.empty()) continue;
std::cout << "The func_name is " << func_name << "\n";
map_func_argu[func_name] = set<unsigned int>(); // create entry
//map_func_fault_type[func_name] = set<unsigned int>();
//second, I need to load argument set and type set
do
{
line.clear();
getline(config,line); // get the next line
if(!config.good()) break; // if the new line is the end of file, our job is done.
if(line.find("ARGUMENT:") < line.length())
{
//insert argument id to argument set
std::string arg_set = line.substr(line.find("ARGUMENT:")+string("ARGUMENT:").length(), line.length() - line.find("ARGUMENT:")-string("ARGUMENT:").length());
std::string arg;
while(!arg_set.empty())
{
while(arg_set[0] <= '9' && arg_set[0] >= '0')
{
arg.append(arg_set.substr(0,1));
if(!arg_set.empty()) arg_set.erase(0,1);
}
if(!arg.empty())
{
unsigned int arg_num = atoi(arg.c_str()) - 1;
map_func_argu[func_name].insert(arg_num);
std::cout << "\tinclude arg: " << arg_num+1 << "\n";
}
arg.clear();
//.........这里部分代码省略.........
示例11: EvaluateBlock
/// 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 (ConstantExpr *CE = dyn_cast<ConstantExpr>(Ptr)) {
DEBUG(dbgs() << "Folding constant ptr expression: " << *Ptr);
Ptr = ConstantFoldConstantExpression(CE, DL, TLI);
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 (ConstantExpr *CE = dyn_cast<ConstantExpr>(Ptr))
Ptr = ConstantFoldConstantExpression(CE, DL, TLI);
// 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());
//.........这里部分代码省略.........
示例12: constructCheckHandlers
void InitializeSoftBound:: constructCheckHandlers(Module & module){
Type* void_ty = Type::getVoidTy(module.getContext());
Type* void_ptr_ty = PointerType::getUnqual(Type::getInt8Ty(module.getContext()));
Type* size_ty = Type::getInt64Ty(module.getContext());
module.getOrInsertFunction("__softboundcets_spatial_load_dereference_check",
void_ty, void_ptr_ty, void_ptr_ty,
void_ptr_ty, size_ty, NULL);
module.getOrInsertFunction("__softboundcets_spatial_store_dereference_check",
void_ty, void_ptr_ty, void_ptr_ty,
void_ptr_ty, size_ty, NULL);
module.getOrInsertFunction("__softboundcets_temporal_load_dereference_check",
void_ty, void_ptr_ty, size_ty,
void_ptr_ty, void_ptr_ty, NULL);
module.getOrInsertFunction("__softboundcets_temporal_store_dereference_check",
void_ty, void_ptr_ty, size_ty,
void_ptr_ty, void_ptr_ty, NULL);
Function* global_init = (Function *) module.getOrInsertFunction("__softboundcets_global_init",
void_ty, NULL);
global_init->setDoesNotThrow();
global_init->setLinkage(GlobalValue::InternalLinkage);
BasicBlock* BB = BasicBlock::Create(module.getContext(),
"entry", global_init);
Function* softboundcets_init = (Function*) module.getOrInsertFunction("__softboundcets_init", void_ty, Type::getInt32Ty(module.getContext()), NULL);
SmallVector<Value*, 8> args;
Constant * const_one = ConstantInt::get(Type::getInt32Ty(module.getContext()), 1);
args.push_back(const_one);
Instruction* ret = ReturnInst::Create(module.getContext(), BB);
CallInst::Create(softboundcets_init, args, "", ret);
Type * Int32Type = IntegerType::getInt32Ty(module.getContext());
std::vector<Constant *> CtorInits;
CtorInits.push_back(ConstantInt::get(Int32Type, 0));
CtorInits.push_back(global_init);
StructType * ST = ConstantStruct::getTypeForElements(CtorInits, false);
Constant * RuntimeCtorInit = ConstantStruct::get(ST, CtorInits);
//
// Get the current set of static global constructors and add the new ctor
// to the list.
//
std::vector<Constant *> CurrentCtors;
GlobalVariable * GVCtor = module.getNamedGlobal ("llvm.global_ctors");
if (GVCtor) {
if (Constant * C = GVCtor->getInitializer()) {
for (unsigned index = 0; index < C->getNumOperands(); ++index) {
CurrentCtors.push_back (dyn_cast<Constant>(C->getOperand (index)));
}
}
}
CurrentCtors.push_back(RuntimeCtorInit);
//
// Create a new initializer.
//
ArrayType * AT = ArrayType::get (RuntimeCtorInit-> getType(),
CurrentCtors.size());
Constant * NewInit = ConstantArray::get (AT, CurrentCtors);
//
// Create the new llvm.global_ctors global variable and remove the old one
// if it existed.
//
Value * newGVCtor = new GlobalVariable (module,
NewInit->getType(),
false,
GlobalValue::AppendingLinkage,
NewInit,
"llvm.global_ctors");
if (GVCtor) {
newGVCtor->takeName (GVCtor);
GVCtor->eraseFromParent ();
}
}
示例13: runOnModule
virtual bool runOnModule(Module &M) {
LLVMContext &C = M.getContext();
Function *printError_func = (Function*)M.getOrInsertFunction("printErrorMessage", Type::getVoidTy(C), NULL);
BasicBlock* entryBlock = BasicBlock::Create(C, "", printError_func);
IRBuilder<> builder(entryBlock);
Constant *msg = ConstantArray::get(C, "ERROR! Array Index Out of Bounds", true);
Constant *zero_32 = Constant::getNullValue(IntegerType::getInt32Ty(C));
Constant *gep_params[] = {zero_32, zero_32};
GlobalVariable *errorMsg = new GlobalVariable(M, msg->getType(), true, GlobalValue::InternalLinkage, msg, "errorMsg");
Function *puts_func = (Function*)(M.getOrInsertFunction("puts", IntegerType::getInt32Ty(C), PointerType::getUnqual(IntegerType::getInt8Ty(C)), NULL));
Constant *msgptr = ConstantExpr::getGetElementPtr(errorMsg, gep_params);
Value *puts_params[] = {msgptr};
CallInst *puts_call = builder.CreateCall(puts_func, puts_params);
puts_call->setTailCall(false);
Function *exit_func = cast<Function>(M.getOrInsertFunction("exit", IntegerType::getVoidTy(C), Type::getInt32Ty(C),NULL));
Value *exit_val = ConstantInt::get(IntegerType::getInt32Ty(C), 1);
//create exit block. This block prints the error and calls exit system function
BasicBlock* exitBlock = BasicBlock::Create(C, "exitBlock", printError_func);
builder.CreateBr(exitBlock);
builder.SetInsertPoint(exitBlock);
builder.CreateCall(exit_func,exit_val);
builder.CreateBr(exitBlock);
int checksInserted = 0;
for (Module::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI)
{
//leave func defs alone
if (!MI->isDeclaration())
{
for (inst_iterator I = inst_begin(*MI), E = inst_end(*MI); I != E; ++I)
{
Instruction *inst = &*I;
if(GetElementPtrInst *gep = dyn_cast<GetElementPtrInst>(inst))
{
if (const ArrayType *ar = dyn_cast<ArrayType>(gep->getPointerOperandType()->getElementType()))
{
//increment checks inserted counter
checksInserted++;
//create split in basic block for function call insertion (branch)
Instruction* next = inst->getNextNode();
BasicBlock* oldBlock = inst->getParent();
BasicBlock* newBlock = SplitBlock(oldBlock, next, this);
//get upper limit and index used
unsigned upperLim = ar->getNumElements();
int index = gep->getNumOperands() - 1;
Value *vIndexUsed = gep->getOperand(index);
Value *vUpperLimit = ConstantInt::get(vIndexUsed->getType(), upperLim);
BasicBlock* checkUpperBlock = BasicBlock::Create(C, "checkUpperBlock", MI, newBlock);
BasicBlock* checkLowerBlock = BasicBlock::Create(C, "checkLowerBlock", MI, checkUpperBlock);
builder.SetInsertPoint(oldBlock);
//remove old terminator
TerminatorInst* term = oldBlock->getTerminator();
term->eraseFromParent();
//insert new one
builder.CreateBr(checkUpperBlock);
//configure uppper bound test
builder.SetInsertPoint(checkUpperBlock);
Value* condUpperInst = builder.CreateICmpSLT(vIndexUsed, vUpperLimit, "checkUpperBounds");
BasicBlock* errorBlock = BasicBlock::Create(C, "errorBlock", MI, newBlock);
builder.CreateCondBr(condUpperInst, checkLowerBlock, errorBlock);
//configure lower bound test
builder.SetInsertPoint(checkLowerBlock);
Value *vLowerLimit = ConstantInt::get(vIndexUsed->getType(), -1);
Value *condLowerInst = builder.CreateICmpSGT(vIndexUsed, vLowerLimit, "checkLowerBounds");
builder.CreateCondBr(condLowerInst, newBlock, errorBlock);
//setup error block. All this block does is call func to print error and exit
builder.SetInsertPoint(errorBlock);
builder.CreateCall(printError_func);
builder.CreateBr(errorBlock);
}
}
}
}
}
errs() << "This pass has inserted " << checksInserted << " checks\n";
return true;
}
示例14: ResolveConstantExpr
// ResolveConstantExpr - Resolve the constant expression until it stop
// yielding other constant expressions.
CstExprResTy ELFWriter::ResolveConstantExpr(const Constant *CV) {
const TargetData *TD = TM.getTargetData();
// There ins't constant expression inside others anymore
if (!isa<ConstantExpr>(CV))
return std::make_pair(CV, 0);
const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV);
switch (CE->getOpcode()) {
case Instruction::BitCast:
return ResolveConstantExpr(CE->getOperand(0));
case Instruction::GetElementPtr: {
const Constant *ptrVal = CE->getOperand(0);
SmallVector<Value*, 8> idxVec(CE->op_begin()+1, CE->op_end());
int64_t Offset = TD->getIndexedOffset(ptrVal->getType(), &idxVec[0],
idxVec.size());
return std::make_pair(ptrVal, Offset);
}
case Instruction::IntToPtr: {
Constant *Op = CE->getOperand(0);
Op = ConstantExpr::getIntegerCast(Op, TD->getIntPtrType(CV->getContext()),
false/*ZExt*/);
return ResolveConstantExpr(Op);
}
case Instruction::PtrToInt: {
Constant *Op = CE->getOperand(0);
const Type *Ty = CE->getType();
// We can emit the pointer value into this slot if the slot is an
// integer slot greater or equal to the size of the pointer.
if (TD->getTypeAllocSize(Ty) == TD->getTypeAllocSize(Op->getType()))
return ResolveConstantExpr(Op);
llvm_unreachable("Integer size less then pointer size");
}
case Instruction::Add:
case Instruction::Sub: {
// Only handle cases where there's a constant expression with GlobalValue
// as first operand and ConstantInt as second, which are the cases we can
// solve direclty using a relocation entry. GlobalValue=Op0, CstInt=Op1
// 1) Instruction::Add => (global) + CstInt
// 2) Instruction::Sub => (global) + -CstInt
const Constant *Op0 = CE->getOperand(0);
const Constant *Op1 = CE->getOperand(1);
assert(isa<ConstantInt>(Op1) && "Op1 must be a ConstantInt");
CstExprResTy Res = ResolveConstantExpr(Op0);
assert(isa<GlobalValue>(Res.first) && "Op0 must be a GlobalValue");
const APInt &RHS = cast<ConstantInt>(Op1)->getValue();
switch (CE->getOpcode()) {
case Instruction::Add:
return std::make_pair(Res.first, RHS.getSExtValue());
case Instruction::Sub:
return std::make_pair(Res.first, (-RHS).getSExtValue());
}
}
}
report_fatal_error(CE->getOpcodeName() +
StringRef(": Unsupported ConstantExpr type"));
return std::make_pair(CV, 0); // silence warning
}
示例15: CleanupAndPrepareModules
/// CleanupAndPrepareModules - Get the specified modules ready for code
/// generator testing.
///
static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test,
Module *Safe) {
// Clean up the modules, removing extra cruft that we don't need anymore...
Test = BD.performFinalCleanups(Test);
// If we are executing the JIT, we have several nasty issues to take care of.
if (!BD.isExecutingJIT()) return;
// First, if the main function is in the Safe module, we must add a stub to
// the Test module to call into it. Thus, we create a new function `main'
// which just calls the old one.
if (Function *oldMain = Safe->getFunction("main"))
if (!oldMain->isDeclaration()) {
// Rename it
oldMain->setName("llvm_bugpoint_old_main");
// Create a NEW `main' function with same type in the test module.
Function *newMain = Function::Create(oldMain->getFunctionType(),
GlobalValue::ExternalLinkage,
"main", Test);
// Create an `oldmain' prototype in the test module, which will
// corresponds to the real main function in the same module.
Function *oldMainProto = Function::Create(oldMain->getFunctionType(),
GlobalValue::ExternalLinkage,
oldMain->getName(), Test);
// Set up and remember the argument list for the main function.
std::vector<Value*> args;
for (Function::arg_iterator
I = newMain->arg_begin(), E = newMain->arg_end(),
OI = oldMain->arg_begin(); I != E; ++I, ++OI) {
I->setName(OI->getName()); // Copy argument names from oldMain
args.push_back(I);
}
// Call the old main function and return its result
BasicBlock *BB = BasicBlock::Create(Safe->getContext(), "entry", newMain);
CallInst *call = CallInst::Create(oldMainProto, args, "", BB);
// If the type of old function wasn't void, return value of call
ReturnInst::Create(Safe->getContext(), call, BB);
}
// The second nasty issue we must deal with in the JIT is that the Safe
// module cannot directly reference any functions defined in the test
// module. Instead, we use a JIT API call to dynamically resolve the
// symbol.
// Add the resolver to the Safe module.
// Prototype: void *getPointerToNamedFunction(const char* Name)
Constant *resolverFunc =
Safe->getOrInsertFunction("getPointerToNamedFunction",
Type::getInt8PtrTy(Safe->getContext()),
Type::getInt8PtrTy(Safe->getContext()),
(Type *)0);
// Use the function we just added to get addresses of functions we need.
for (Module::iterator F = Safe->begin(), E = Safe->end(); F != E; ++F) {
if (F->isDeclaration() && !F->use_empty() && &*F != resolverFunc &&
!F->isIntrinsic() /* ignore intrinsics */) {
Function *TestFn = Test->getFunction(F->getName());
// Don't forward functions which are external in the test module too.
if (TestFn && !TestFn->isDeclaration()) {
// 1. Add a string constant with its name to the global file
Constant *InitArray =
ConstantDataArray::getString(F->getContext(), F->getName());
GlobalVariable *funcName =
new GlobalVariable(*Safe, InitArray->getType(), true /*isConstant*/,
GlobalValue::InternalLinkage, InitArray,
F->getName() + "_name");
// 2. Use `GetElementPtr *funcName, 0, 0' to convert the string to an
// sbyte* so it matches the signature of the resolver function.
// GetElementPtr *funcName, ulong 0, ulong 0
std::vector<Constant*> GEPargs(2,
Constant::getNullValue(Type::getInt32Ty(F->getContext())));
Value *GEP = ConstantExpr::getGetElementPtr(funcName, GEPargs);
std::vector<Value*> ResolverArgs;
ResolverArgs.push_back(GEP);
// Rewrite uses of F in global initializers, etc. to uses of a wrapper
// function that dynamically resolves the calls to F via our JIT API
if (!F->use_empty()) {
// Create a new global to hold the cached function pointer.
Constant *NullPtr = ConstantPointerNull::get(F->getType());
GlobalVariable *Cache =
new GlobalVariable(*F->getParent(), F->getType(),
false, GlobalValue::InternalLinkage,
NullPtr,F->getName()+".fpcache");
// Construct a new stub function that will re-route calls to F
FunctionType *FuncTy = F->getFunctionType();
Function *FuncWrapper = Function::Create(FuncTy,
GlobalValue::InternalLinkage,
F->getName() + "_wrapper",
F->getParent());
BasicBlock *EntryBB = BasicBlock::Create(F->getContext(),
//.........这里部分代码省略.........