FunctionType* ArgumentRecovery::createFunctionType(TargetInfo& info, const CallInformation& callInfo, llvm::Module& module, StringRef returnTypeName, SmallVectorImpl<string>& parameterNames) { LLVMContext& ctx = module.getContext(); Type* integer = Type::getIntNTy(ctx, info.getPointerSize() * CHAR_BIT); SmallVector<Type*, 8> parameterTypes; for (const auto& param : callInfo.parameters()) { if (param.type == ValueInformation::IntegerRegister) { parameterTypes.push_back(integer); parameterNames.push_back(param.registerInfo->name); } else if (param.type == ValueInformation::Stack) { parameterTypes.push_back(integer); parameterNames.emplace_back(); raw_string_ostream(parameterNames.back()) << "sp" << param.frameBaseOffset; } else { llvm_unreachable("not implemented"); } } SmallVector<Type*, 2> returnTypes; for (const auto& ret : callInfo.returns()) { if (ret.type == ValueInformation::IntegerRegister) { returnTypes.push_back(integer); } else { llvm_unreachable("not implemented"); } } Type* returnType; if (returnTypes.size() == 0) { returnType = Type::getVoidTy(ctx); } else if (returnTypes.size() == 1) { returnType = returnTypes.front(); } else { StructType* structTy = StructType::create(ctx, returnTypeName); structTy->setBody(returnTypes); md::setRecoveredReturnFieldNames(module, *structTy, callInfo); returnType = structTy; } assert(!callInfo.isVararg() && "not implemented"); return FunctionType::get(returnType, parameterTypes, false); }
void TypeMapTy::linkDefinedTypeBodies() { SmallVector<Type *, 16> Elements; for (StructType *SrcSTy : SrcDefinitionsToResolve) { StructType *DstSTy = cast<StructType>(MappedTypes[SrcSTy]); assert(DstSTy->isOpaque()); // Map the body of the source type over to a new body for the dest type. Elements.resize(SrcSTy->getNumElements()); for (unsigned I = 0, E = Elements.size(); I != E; ++I) Elements[I] = get(SrcSTy->getElementType(I)); DstSTy->setBody(Elements, SrcSTy->isPacked()); DstStructTypesSet.switchToNonOpaque(DstSTy); } SrcDefinitionsToResolve.clear(); DstResolvedOpaqueTypes.clear(); }
int main(int argc, char **argv) { InitializeNativeTarget(); LLVMContext &Context = getGlobalContext(); Module *m = new Module("test", Context); Type *intTy = Type::getInt64Ty(Context); StructType* structTy = StructType::create(Context, "struct.list"); std::vector<Type*> fields; fields.push_back(intTy); fields.push_back(PointerType::get(structTy, 0)); if (structTy->isOpaque()) { structTy->setBody(fields, false); } /* * int f1(struct x *p) { return p->next->l1; } */ std::vector<Type*> args_type; args_type.push_back(PointerType::get(structTy, 0)); FunctionType *fnTy = FunctionType::get(intTy, args_type, false); Function *func = Function::Create(fnTy, GlobalValue::ExternalLinkage, "f1", m); Value *v = func->arg_begin(); BasicBlock *bb = BasicBlock::Create(Context, "EntryBlock", func); IRBuilder<> *builder = new IRBuilder<>(bb); v = builder->CreateStructGEP(v, 1); v = builder->CreateLoad(v, "load0"); v = builder->CreateStructGEP(v, 0); v = builder->CreateLoad(v, "load1"); builder->CreateRet(v); (*m).dump(); { ExecutionEngine *ee = EngineBuilder(m). setEngineKind(EngineKind::JIT).create(); void *f = ee->getPointerToFunction(func); typedef int (*func_t) (struct x *); struct x o = {10, NULL}, v = {}; v.next = &o; std::cout << ((func_t)f)(&v) << std::endl; } return 0; }
StructType *StructType::get(LLVMContext &Context, ArrayRef<Type*> ETypes, bool isPacked) { LLVMContextImpl *pImpl = Context.pImpl; AnonStructTypeKeyInfo::KeyTy Key(ETypes, isPacked); auto I = pImpl->AnonStructTypes.find_as(Key); StructType *ST; if (I == pImpl->AnonStructTypes.end()) { // Value not found. Create a new type! ST = new (Context.pImpl->TypeAllocator) StructType(Context); ST->setSubclassData(SCDB_IsLiteral); // Literal struct. ST->setBody(ETypes, isPacked); Context.pImpl->AnonStructTypes.insert(ST); } else { ST = *I; } return ST; }
void Preparer::expandGlobal(Module &M, GlobalVariable *GV) { if (GV->isDeclaration()) return; if (GV->getLinkage() == GlobalValue::AppendingLinkage) return; Type *OrigType = GV->getType()->getTypeAtIndex((unsigned)0); StructType *NewType = StructType::create(GV->getContext(), "pad_global_type"); NewType->setBody(OrigType, IntegerType::get(GV->getContext(), 8), NULL); // FIXME: AddressSpace? GlobalVariable *NewGV; Constant *NewInit = NULL; if (GV->hasInitializer()) { assert(GV->getInitializer()->getType() == OrigType); NewInit = ConstantStruct::get(NewType, GV->getInitializer(), ConstantInt::get(IntegerType::get(GV->getContext(), 8), 0), NULL); } NewGV = new GlobalVariable(M, NewType, GV->isConstant(), GV->getLinkage(), NewInit, "pad_global", GV, GV->isThreadLocal(), 0); Constant *NewValue = ConstantExpr::getBitCast(NewGV, GV->getType()); assert(NewValue->getType() == GV->getType()); GV->replaceAllUsesWith(NewValue); }
bool PNaClSjLjEH::runOnModule(Module &M) { Type *JmpBufTy = ArrayType::get(Type::getInt8Ty(M.getContext()), kPNaClJmpBufSize); // Define "struct ExceptionFrame". StructType *ExceptionFrameTy = StructType::create(M.getContext(), "ExceptionFrame"); Type *ExceptionFrameFields[] = { JmpBufTy, // jmp_buf ExceptionFrameTy->getPointerTo(), // struct ExceptionFrame *next Type::getInt32Ty(M.getContext()) // Exception info (clause list ID) }; ExceptionFrameTy->setBody(ExceptionFrameFields); ExceptionInfoWriter ExcInfoWriter(&M.getContext()); for (Module::iterator Func = M.begin(), E = M.end(); Func != E; ++Func) { FuncRewriter Rewriter(ExceptionFrameTy, &ExcInfoWriter, Func); Rewriter.expandFunc(); } ExcInfoWriter.defineGlobalVariables(&M); return true; }
/// linkDefinedTypeBodies - Produce a body for an opaque type in the dest /// module from a type definition in the source module. void TypeMapTy::linkDefinedTypeBodies() { SmallVector<Type*, 16> Elements; SmallString<16> TmpName; // Note that processing entries in this loop (calling 'get') can add new // entries to the SrcDefinitionsToResolve vector. while (!SrcDefinitionsToResolve.empty()) { StructType *SrcSTy = SrcDefinitionsToResolve.pop_back_val(); StructType *DstSTy = cast<StructType>(MappedTypes[SrcSTy]); // TypeMap is a many-to-one mapping, if there were multiple types that // provide a body for DstSTy then previous iterations of this loop may have // already handled it. Just ignore this case. if (!DstSTy->isOpaque()) continue; assert(!SrcSTy->isOpaque() && "Not resolving a definition?"); // Map the body of the source type over to a new body for the dest type. Elements.resize(SrcSTy->getNumElements()); for (unsigned i = 0, e = Elements.size(); i != e; ++i) Elements[i] = getImpl(SrcSTy->getElementType(i)); DstSTy->setBody(Elements, SrcSTy->isPacked()); // If DstSTy has no name or has a longer name than STy, then viciously steal // STy's name. if (!SrcSTy->hasName()) continue; StringRef SrcName = SrcSTy->getName(); if (!DstSTy->hasName() || DstSTy->getName().size() > SrcName.size()) { TmpName.insert(TmpName.end(), SrcName.begin(), SrcName.end()); SrcSTy->setName(""); DstSTy->setName(TmpName.str()); TmpName.clear(); } } DstResolvedOpaqueTypes.clear(); }
StructType *StructType::create(LLVMContext &Context, ArrayRef<Type*> Elements, StringRef Name, bool isPacked) { StructType *ST = create(Context, Name); ST->setBody(Elements, isPacked); return ST; }
bool AllocateDataSegment::runOnModule(Module &M) { DataLayout DL(&M); Type *I8 = Type::getInt8Ty(M.getContext()); Type *I32 = Type::getInt32Ty(M.getContext()); Type *IntPtrType = DL.getIntPtrType(M.getContext()); // First, we do a pass over the global variables, in which we compute // the amount of required padding between them and consequently their // addresses relative to the memory base of the sandbox. References to each // global are then replaced with direct memory pointers. uint32_t VarOffset = 0; DenseMap<GlobalVariable*, uint32_t> VarPadding; for (Module::global_iterator GV = M.global_begin(), E = M.global_end(); GV != E; ++GV) { assert(GV->hasInitializer()); uint32_t Padding = getPadding(VarOffset, GV, DL); VarPadding[GV] = Padding; VarOffset += Padding; GV->replaceAllUsesWith( ConstantExpr::getIntToPtr( ConstantInt::get(IntPtrType, DataSegmentBaseAddress + VarOffset), GV->getType())); VarOffset += DL.getTypeStoreSize(GV->getType()->getPointerElementType()); } // Using the offsets computed above, we prepare the layout and the contents // of the desired data structure. After the type and initializer of each // global is copied, the global is not needed any more and it is erased. SmallVector<Type*, 10> TemplateLayout; SmallVector<Constant*, 10> TemplateData; for (Module::global_iterator It = M.global_begin(), E = M.global_end(); It != E; ) { GlobalVariable *GV = It++; uint32_t Padding = VarPadding[GV]; if (Padding > 0) { Type *PaddingType = ArrayType::get(I8, Padding); TemplateLayout.push_back(PaddingType); TemplateData.push_back(ConstantAggregateZero::get(PaddingType)); } TemplateLayout.push_back(GV->getType()->getPointerElementType()); TemplateData.push_back(GV->getInitializer()); GV->eraseFromParent(); } // Finally, we create the struct and size global variables. StructType *TemplateType = StructType::create(M.getContext(), ExternalSymName_DataSegment); TemplateType->setBody(TemplateLayout, /*isPacked=*/true); Constant *Template = ConstantStruct::get(TemplateType, TemplateData); new GlobalVariable(M, Template->getType(), /*isConstant=*/true, GlobalVariable::ExternalLinkage, Template, ExternalSymName_DataSegment); Constant *TemplateSize = ConstantInt::get(I32, DL.getTypeAllocSize(TemplateType)); new GlobalVariable(M, TemplateSize->getType(), /*isConstant=*/true, GlobalVariable::ExternalLinkage, TemplateSize, ExternalSymName_DataSegmentSize); return true; }
void doGlobalInit(Module *M) { //create the "reg" struct type StructType *regs = StructType::create(M->getContext(), "struct.regs"); vector<Type *> regFields; initInstructionDispatch(); //UPDATEREGS -- when we add something to 'regs', add it here //GPRs regFields.push_back(IntegerType::get(M->getContext(), 32)); // EAX // 0 regFields.push_back(IntegerType::get(M->getContext(), 32)); // EBX // 1 regFields.push_back(IntegerType::get(M->getContext(), 32)); // ECX // 2 regFields.push_back(IntegerType::get(M->getContext(), 32)); // EDX // 3 regFields.push_back(IntegerType::get(M->getContext(), 32)); // ESI // 4 regFields.push_back(IntegerType::get(M->getContext(), 32)); // EDI // 5 regFields.push_back(IntegerType::get(M->getContext(), 32)); // ESP // 6 regFields.push_back(IntegerType::get(M->getContext(), 32)); // EBP // 7 // 32 bytes //flags regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // CF // 8 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // PF // 9 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // AF // 10 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // ZF // 11 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // SF // 12 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // OF // 13 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // DF // 14 // 28 bytes // FPU ArrayType *fpu_regs = ArrayType::get(Type::getX86_FP80Ty(M->getContext()), 8); regFields.push_back(fpu_regs); // 80 bytes // 15 // FPU Status Word regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // FPU BUSY // 16 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // Condition Code C3 // 17 regFields.push_back(IntegerType::get(M->getContext(), 3)); // TOP OF STACK // 18 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // Condition Code C2 // 19 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // Condition Code C1 // 20 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // Condition Code C0 // 21 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // Error Summary Status // 22 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // Stack Fault // 23 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // Precision Flag // 24 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // Underflow Flag // 25 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // Overflow Flag // 26 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // ZeroDivide Flag // 27 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // Denormalized Operand Flag // 28 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // Invalid Operation Flag // 29 // 56 bytes // 80 + 56 + 28 + 32 = 196 bytes regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // FPU Infinity Flag // 30 regFields.push_back(IntegerType::get(M->getContext(), 2)); // FPU Rounding Control // 31 regFields.push_back(IntegerType::get(M->getContext(), 2)); // FPU Precision Control // 32 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // FPU Precision Mask // 33 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // FPU Underflow Mask // 34 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // FPU Overflow Mask // 35 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // FPU Zero Divide Mask // 36 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // FPU Denormal Operand Mask // 37 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // FPU Invalid Operation Mask // 38 // FPU tag word; 8 element array of 2-bit entries ArrayType *fpu_tag_word = ArrayType::get(Type::getIntNTy(M->getContext(), 8), 8); regFields.push_back(fpu_tag_word); // 80 bytes // 39 regFields.push_back(IntegerType::getInt16Ty(M->getContext())); // Last Instruction Ptr Segment 40 regFields.push_back(IntegerType::getInt32Ty(M->getContext())); // Last Instruction Ptr Offset 41 regFields.push_back(IntegerType::getInt16Ty(M->getContext())); // Last Data Ptr Segment 42 regFields.push_back(IntegerType::getInt32Ty(M->getContext())); // Last Data Ptr Offset 43 regFields.push_back(IntegerType::get(M->getContext(), 11)); // FPU FOPCODE 44 // vector registers regFields.push_back(IntegerType::getIntNTy(M->getContext(), 128)); // XMM0 45 regFields.push_back(IntegerType::getIntNTy(M->getContext(), 128)); // XMM1 46 regFields.push_back(IntegerType::getIntNTy(M->getContext(), 128)); // XMM2 47 regFields.push_back(IntegerType::getIntNTy(M->getContext(), 128)); // XMM3 48 regFields.push_back(IntegerType::getIntNTy(M->getContext(), 128)); // XMM4 49 regFields.push_back(IntegerType::getIntNTy(M->getContext(), 128)); // XMM5 50 regFields.push_back(IntegerType::getIntNTy(M->getContext(), 128)); // XMM6 51 regFields.push_back(IntegerType::getIntNTy(M->getContext(), 128)); // XMM7 52 // non-register values in structRegs regFields.push_back(IntegerType::getInt32Ty(M->getContext())); // 53: stack base (biggest value) regFields.push_back(IntegerType::getInt32Ty(M->getContext())); // 54: stack limit (smallest value) PointerType *ptrToRegs = PointerType::get(regs, 0); regs->setBody(regFields, true); vector<Type*> callValArgs; callValArgs.push_back(Type::getInt32Ty(M->getContext())); callValArgs.push_back(ptrToRegs); FunctionType *callVal = FunctionType::get( Type::getVoidTy(M->getContext()), callValArgs, false); //GlobalVariable* g_StateBackup = // new GlobalVariable(*M, regs, false, GlobalValue::ExternalLinkage, 0, "state.backup"); Type *int32ty = IntegerType::getInt32Ty(M->getContext()); g_StateBackup = new GlobalVariable(*M, int32ty, false, GlobalValue::PrivateLinkage, 0, "state.backup"); g_StateBackup->setThreadLocalMode(GlobalVariable::GeneralDynamicTLSModel); Constant *zero = ConstantInt::get(int32ty, 0, false); g_StateBackup->setInitializer(zero); g_RegStruct = regs; g_PRegStruct = ptrToRegs; archAddCallValue(M); return; }
// Transforms any type that could transitively reference a function pointer // into a simplified type. // We enter this function trying to determine the mapping of a type. Because // of how structs are handled (not interned by llvm - see further comments // below) we may be working with temporary types - types (pointers, for example) // transitively referencing "tentative" structs. For that reason, we do not // memoize anything here, except for structs. The latter is so that we avoid // unnecessary repeated creation of types (pointers, function types, etc), // as we try to map a given type. SimplifiedFuncTypeMap::MappingResult SimplifiedFuncTypeMap::getSimpleAggregateTypeInternal(LLVMContext &Ctx, Type *Ty, StructMap &Tentatives) { // Leverage the map for types we encounter on the way. auto Found = MappedTypes.find(Ty); if (Found != MappedTypes.end()) { return {Found->second, Found->second != Ty}; } if (auto *OldFnTy = dyn_cast<FunctionType>(Ty)) { return getSimpleFuncType(Ctx, Tentatives, OldFnTy); } if (auto PtrTy = dyn_cast<PointerType>(Ty)) { auto NewTy = getSimpleAggregateTypeInternal( Ctx, PtrTy->getPointerElementType(), Tentatives); return {NewTy->getPointerTo(PtrTy->getAddressSpace()), NewTy.isChanged()}; } if (auto ArrTy = dyn_cast<ArrayType>(Ty)) { auto NewTy = getSimpleAggregateTypeInternal( Ctx, ArrTy->getArrayElementType(), Tentatives); return {ArrayType::get(NewTy, ArrTy->getArrayNumElements()), NewTy.isChanged()}; } if (auto VecTy = dyn_cast<VectorType>(Ty)) { auto NewTy = getSimpleAggregateTypeInternal( Ctx, VecTy->getVectorElementType(), Tentatives); return {VectorType::get(NewTy, VecTy->getVectorNumElements()), NewTy.isChanged()}; } // LLVM doesn't intern identified structs (the ones with a name). This, // together with the fact that such structs can be recursive, // complicates things a bit. We want to make sure that we only change // "unsimplified" structs (those that somehow reference funcs that // are not simple). // We don't want to change "simplified" structs, otherwise converting // instruction types will become trickier. if (auto StructTy = dyn_cast<StructType>(Ty)) { ParamTypeVector ElemTypes; if (!StructTy->isLiteral()) { // Literals - struct without a name - cannot be recursive, so we // don't need to form tentatives. auto Found = Tentatives.find(StructTy); // Having a tentative means we are in a recursion trying to map this // particular struct, so arriving back to it is not a change. // We will determine if this struct is actually // changed by checking its other fields. if (Found != Tentatives.end()) { return {Found->second, false}; } // We have never seen this struct, so we start a tentative. std::string NewName = StructTy->getStructName(); NewName += ".simplified"; StructType *Tentative = StructType::create(Ctx, NewName); Tentatives[StructTy] = Tentative; bool Changed = isChangedStruct(Ctx, StructTy, ElemTypes, Tentatives); Tentatives.erase(StructTy); // We can now decide the mapping of the struct. We will register it // early with MappedTypes, to avoid leaking tentatives unnecessarily. // We are leaking the created struct here, but there is no way to // correctly delete it. if (!Changed) { return {MappedTypes[StructTy] = StructTy, false}; } else { Tentative->setBody(ElemTypes, StructTy->isPacked()); return {MappedTypes[StructTy] = Tentative, true}; } } else { bool Changed = isChangedStruct(Ctx, StructTy, ElemTypes, Tentatives); return {MappedTypes[StructTy] = StructType::get(Ctx, ElemTypes, StructTy->isPacked()), Changed}; } } // Anything else stays the same. return {Ty, false}; }
int main() { InitializeNativeTarget(); LLVMContext& Context = getGlobalContext(); Module *M = new Module("test C++ exception handling ", Context); StructType* MyStructType = StructType::create(Context, "struct.MyStruct"); Type* MyStructFields[] = { Type::getInt32Ty(Context), Type::getInt32Ty(Context) }; MyStructType->setBody(MyStructFields); GlobalValue* throwFunc = cast<GlobalValue>(M->getOrInsertFunction("throwMyStruct", Type::getVoidTy(Context), NULL)); GlobalValue* MyStructTypeInfo = cast<GlobalValue>(M->getOrInsertGlobal("MyStructTypeInfo", Type::getInt8Ty(Context))); Function* gxx_personality = Function::Create(FunctionType::get(Type::getInt32Ty(Context), true), Function::ExternalLinkage, "__gxx_personality_v0", M); Function* begin_catch = Function::Create(FunctionType::get(Type::getInt8PtrTy(Context), Type::getInt8PtrTy(Context), false), Function::ExternalLinkage, "__cxa_begin_catch", M); Function* end_catch = Function::Create(FunctionType::get(Type::getVoidTy(Context), false), Function::ExternalLinkage, "__cxa_end_catch", M); Function* testExceptions = cast<Function>(M->getOrInsertFunction("testExceptions", Type::getInt32Ty(Context), NULL)); BasicBlock* entryBB = BasicBlock::Create(Context, "", testExceptions); BasicBlock* landPadBB = BasicBlock::Create(Context, "landPad", testExceptions); BasicBlock* noErrorBB = BasicBlock::Create(Context, "noError", testExceptions); IRBuilder<> builder(entryBB); Value* invokeThrow = builder.CreateInvoke(throwFunc, noErrorBB, landPadBB); builder.SetInsertPoint(noErrorBB); builder.CreateRet( builder.getInt32(666) ); // should never happen //writing landingpad! <<<<<<< builder.SetInsertPoint(landPadBB); Value* gxx_personality_i8 = builder.CreateBitCast(gxx_personality, Type::getInt8PtrTy(Context)); Type* caughtType = StructType::get(builder.getInt8PtrTy(), builder.getInt32Ty(), NULL); LandingPadInst* caughtResult = builder.CreateLandingPad(caughtType, gxx_personality_i8, 1); // we can catch any C++ exception we want // but now we are catching MyStruct caughtResult->addClause(MyStructTypeInfo); //we are sure to catch MyStruct so no other checks are needed //if throwMyStruct() throws anything but MyStruct it won't pass to the current landingpad BB Value* thrownExctn = builder.CreateExtractValue(caughtResult, 0); Value* thrownObject = builder.CreateCall(begin_catch, thrownExctn); Value* object = builder.CreateBitCast(thrownObject, MyStructType->getPointerTo()); Value* resultPtr = builder.CreateStructGEP(object, 1); Value* result = builder.CreateLoad(resultPtr); builder.CreateCall(end_catch); builder.CreateRet( result ); // << z.y TargetOptions Opts; Opts.JITExceptionHandling = true; // DO NOT FORGET THIS OPTION !!!!!!11 ExecutionEngine* EE = EngineBuilder(M) .setEngineKind(EngineKind::JIT) .setTargetOptions(Opts) .create(); EE->addGlobalMapping(throwFunc, reinterpret_cast<void*>(&throwMyStruct)); EE->addGlobalMapping(MyStructTypeInfo, MyStruct::getTypeInfo()); verifyFunction(*testExceptions); outs() << *testExceptions; std::vector<GenericValue> noArgs; GenericValue gv = EE->runFunction(testExceptions, noArgs); outs() << "\ntestExceptions result: " << gv.IntVal << "\n"; delete EE; llvm_shutdown(); return 0; }
void doGlobalInit(Module *M) { unsigned int regWidth = getPointerSize(M); //create the "reg" struct type StructType *regs = StructType::create(M->getContext(), "struct.regs"); vector<Type *> regFields; initInstructionDispatch(); //UPDATEREGS -- when we add something to 'regs', add it here //GPRs regFields.push_back(IntegerType::get(M->getContext(), regWidth)); // RAX/EAX // 0 regFields.push_back(IntegerType::get(M->getContext(), regWidth)); // RBX/EBX // 1 regFields.push_back(IntegerType::get(M->getContext(), regWidth)); // RCX/ECX // 2 regFields.push_back(IntegerType::get(M->getContext(), regWidth)); // RDX/EDX // 3 regFields.push_back(IntegerType::get(M->getContext(), regWidth)); // RSI/ESI // 4 regFields.push_back(IntegerType::get(M->getContext(), regWidth)); // RDI/EDI // 5 regFields.push_back(IntegerType::get(M->getContext(), regWidth)); // RSP/ESP // 6 regFields.push_back(IntegerType::get(M->getContext(), regWidth)); // RBP/EBP // 7 if(getSystemArch(M) == _X86_64_){ regFields.push_back(IntegerType::get(M->getContext(), regWidth)); // R8 // 8 regFields.push_back(IntegerType::get(M->getContext(), regWidth)); // R9 // 9 regFields.push_back(IntegerType::get(M->getContext(), regWidth)); // R10 // 10 regFields.push_back(IntegerType::get(M->getContext(), regWidth)); // R11 // 11 regFields.push_back(IntegerType::get(M->getContext(), regWidth)); // R12 // 12 regFields.push_back(IntegerType::get(M->getContext(), regWidth)); // R13 // 13 regFields.push_back(IntegerType::get(M->getContext(), regWidth)); // R14 // 14 regFields.push_back(IntegerType::get(M->getContext(), regWidth)); // R15 // 15 // RIP for rip relative instructions regFields.push_back(IntegerType::get(M->getContext(), regWidth)); // RIP // 16 } //flags regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // CF // 17 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // PF // 18 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // AF // 19 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // ZF // 20 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // SF // 21 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // OF // 22 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // DF // 23 ArrayType *fpu_regs = ArrayType::get(Type::getX86_FP80Ty(M->getContext()), 8); regFields.push_back(fpu_regs); // 80 bytes 24 // FPU Status Word regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // FPU BUSY // 25 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // Condition Code C3 // 26 regFields.push_back(IntegerType::get(M->getContext(), 3)); // TOP OF STACK // 27 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // Condition Code C2 // 28 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // Condition Code C1 // 29 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // Condition Code C0 // 30 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // Error Summary Status // 31 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // Stack Fault // 32 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // Precision Flag // 33 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // Underflow Flag // 34 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // Overflow Flag // 35 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // ZeroDivide Flag // 36 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // Denormalized Operand Flag // 37 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // Invalid Operation Flag // 38 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // FPU Infinity Flag // 39 regFields.push_back(IntegerType::get(M->getContext(), 2)); // FPU Rounding Control // 40 regFields.push_back(IntegerType::get(M->getContext(), 2)); // FPU Precision Control // 41 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // FPU Precision Mask // 42 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // FPU Underflow Mask // 43 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // FPU Overflow Mask // 44 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // FPU Zero Divide Mask // 45 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // FPU Denormal Operand Mask // 46 regFields.push_back(IntegerType::getInt1Ty(M->getContext())); // FPU Invalid Operation Mask // 47 // FPU tag word; 8 element array of 2-bit entries ArrayType *fpu_tag_word = ArrayType::get(Type::getIntNTy(M->getContext(), 8), 8); regFields.push_back(fpu_tag_word); // 48 regFields.push_back(IntegerType::getInt16Ty(M->getContext())); // Last Instruction Ptr Segment 49 regFields.push_back(IntegerType::getIntNTy(M->getContext(), regWidth)); // Last Instruction Ptr Offset 50 regFields.push_back(IntegerType::getInt16Ty(M->getContext())); // Last Data Ptr Segment 51 regFields.push_back(IntegerType::getIntNTy(M->getContext(), regWidth)); // Last Data Ptr Offset 52 regFields.push_back(IntegerType::get(M->getContext(), 11)); // FPU FOPCODE 53 // vector registers regFields.push_back(IntegerType::getIntNTy(M->getContext(), 128)); // XMM0 54 regFields.push_back(IntegerType::getIntNTy(M->getContext(), 128)); // XMM1 55 regFields.push_back(IntegerType::getIntNTy(M->getContext(), 128)); // XMM2 56 regFields.push_back(IntegerType::getIntNTy(M->getContext(), 128)); // XMM3 57 regFields.push_back(IntegerType::getIntNTy(M->getContext(), 128)); // XMM4 58 regFields.push_back(IntegerType::getIntNTy(M->getContext(), 128)); // XMM5 59 regFields.push_back(IntegerType::getIntNTy(M->getContext(), 128)); // XMM6 60 regFields.push_back(IntegerType::getIntNTy(M->getContext(), 128)); // XMM7 61 if(getSystemArch(M) == _X86_64_){ regFields.push_back(IntegerType::getIntNTy(M->getContext(), 128)); // XMM8 62 regFields.push_back(IntegerType::getIntNTy(M->getContext(), 128)); // XMM9 63 regFields.push_back(IntegerType::getIntNTy(M->getContext(), 128)); // XMM10 64 regFields.push_back(IntegerType::getIntNTy(M->getContext(), 128)); // XMM11 65 regFields.push_back(IntegerType::getIntNTy(M->getContext(), 128)); // XMM12 66 regFields.push_back(IntegerType::getIntNTy(M->getContext(), 128)); // XMM13 67 regFields.push_back(IntegerType::getIntNTy(M->getContext(), 128)); // XMM14 68 regFields.push_back(IntegerType::getIntNTy(M->getContext(), 128)); // XMM15 69 } // non-register values in structRegs regFields.push_back(IntegerType::getIntNTy(M->getContext(), regWidth)); // 70: stack base (biggest value) regFields.push_back(IntegerType::getIntNTy(M->getContext(), regWidth)); // 71: stack limit (smallest value) PointerType *ptrToRegs = PointerType::get(regs, 0); regs->setBody(regFields, true); vector<Type*> callValArgs; callValArgs.push_back(Type::getIntNTy(M->getContext(), regWidth)); callValArgs.push_back(ptrToRegs); FunctionType *callVal = FunctionType::get( Type::getVoidTy(M->getContext()), callValArgs, false); //GlobalVariable* g_StateBackup = // new GlobalVariable(*M, regs, false, GlobalValue::ExternalLinkage, 0, "state.backup"); Type *intType = IntegerType::getIntNTy(M->getContext(), regWidth); g_StateBackup = new GlobalVariable(*M, intType, false, GlobalValue::PrivateLinkage, 0, "state.backup"); g_StateBackup->setThreadLocalMode(GlobalVariable::GeneralDynamicTLSModel); Constant *zero = ConstantInt::get(intType, 0, false); g_StateBackup->setInitializer(zero); g_RegStruct = regs; g_PRegStruct = ptrToRegs; archAddCallValue(M); return; }
static PointerType *buildTlsTemplate(Module &M, std::vector<VarInfo> *TlsVars) { std::vector<Type*> FieldBssTypes; std::vector<Type*> FieldInitTypes; std::vector<Constant*> FieldInitValues; PassState State(&M); for (Module::global_iterator GV = M.global_begin(); GV != M.global_end(); ++GV) { if (GV->isThreadLocal()) { if (!GV->hasInitializer()) { // Since this is a whole-program transformation, "extern" TLS // variables are not allowed at this point. report_fatal_error(std::string("TLS variable without an initializer: ") + GV->getName()); } if (!GV->getInitializer()->isNullValue()) { addVarToTlsTemplate(&State, &FieldInitTypes, &FieldInitValues, GV); VarInfo Info; Info.TlsVar = GV; Info.IsBss = false; Info.TemplateIndex = FieldInitTypes.size() - 1; TlsVars->push_back(Info); } } } // Handle zero-initialized TLS variables in a second pass, because // these should follow non-zero-initialized TLS variables. for (Module::global_iterator GV = M.global_begin(); GV != M.global_end(); ++GV) { if (GV->isThreadLocal() && GV->getInitializer()->isNullValue()) { addVarToTlsTemplate(&State, &FieldBssTypes, NULL, GV); VarInfo Info; Info.TlsVar = GV; Info.IsBss = true; Info.TemplateIndex = FieldBssTypes.size() - 1; TlsVars->push_back(Info); } } // Add final alignment padding so that // (struct tls_struct *) __nacl_read_tp() - 1 // gives the correct, aligned start of the TLS variables given the // x86-style layout we are using. This requires some more bytes to // be memset() to zero at runtime. This wastage doesn't seem // important gives that we're not trying to optimize packing by // reordering to put similarly-aligned variables together. padToAlignment(&State, &FieldBssTypes, NULL, State.Alignment); // We create the TLS template structs as "packed" because we insert // alignment padding ourselves, and LLVM's implicit insertion of // padding would interfere with ours. tls_bss_template can start at // a non-aligned address immediately following the last field in // tls_init_template. StructType *InitTemplateType = StructType::create(M.getContext(), "tls_init_template"); InitTemplateType->setBody(FieldInitTypes, /*isPacked=*/true); StructType *BssTemplateType = StructType::create(M.getContext(), "tls_bss_template"); BssTemplateType->setBody(FieldBssTypes, /*isPacked=*/true); StructType *TemplateType = StructType::create(M.getContext(), "tls_struct"); SmallVector<Type*, 2> TemplateTopFields; TemplateTopFields.push_back(InitTemplateType); TemplateTopFields.push_back(BssTemplateType); TemplateType->setBody(TemplateTopFields, /*isPacked=*/true); PointerType *TemplatePtrType = PointerType::get(TemplateType, 0); // We define the following symbols, which are the same as those // defined by NaCl's original customized binutils linker scripts: // __tls_template_start // __tls_template_tdata_end // __tls_template_end // We also define __tls_template_alignment, which was not defined by // the original linker scripts. const char *StartSymbol = "__tls_template_start"; Constant *TemplateData = ConstantStruct::get(InitTemplateType, FieldInitValues); GlobalVariable *TemplateDataVar = new GlobalVariable(M, InitTemplateType, /*isConstant=*/true, GlobalValue::InternalLinkage, TemplateData); setGlobalVariableValue(M, StartSymbol, TemplateDataVar); TemplateDataVar->setName(StartSymbol); Constant *TdataEnd = ConstantExpr::getGetElementPtr( TemplateDataVar, ConstantInt::get(M.getContext(), APInt(32, 1))); setGlobalVariableValue(M, "__tls_template_tdata_end", TdataEnd); Constant *TotalEnd = ConstantExpr::getGetElementPtr( ConstantExpr::getBitCast(TemplateDataVar, TemplatePtrType), ConstantInt::get(M.getContext(), APInt(32, 1))); setGlobalVariableValue(M, "__tls_template_end", TotalEnd); const char *AlignmentSymbol = "__tls_template_alignment"; Type *i32 = Type::getInt32Ty(M.getContext()); GlobalVariable *AlignmentVar = new GlobalVariable( M, i32, /*isConstant=*/true, GlobalValue::InternalLinkage, ConstantInt::get(M.getContext(), APInt(32, State.Alignment))); setGlobalVariableValue(M, AlignmentSymbol, AlignmentVar); AlignmentVar->setName(AlignmentSymbol); return TemplatePtrType; }