void code_emitter::setup_xy_vars_from_closure () { Value *t_var = lookup_internal(::lookup_internal(filter->v.mathmap.internals, "t", true)); Value *xy_vars_untyped = builder->CreateCall4(module->getFunction(string("calc_closure_xy_vars")), invocation_arg, closure_arg, t_var, init_frame_function); xy_vars_var = builder->CreateBitCast(xy_vars_untyped, PointerType::getUnqual(xy_vars_type)); }
void EmitMemSet(IRBuilder<>& B, Value* Dst, Value* Val, Value* Len, const Analysis& A) { Dst = B.CreateBitCast(Dst, PointerType::getUnqual(B.getInt8Ty())); CallSite CS = B.CreateMemSet(Dst, Val, Len, 1 /*Align*/, false /*isVolatile*/); if (A.CGNode) A.CGNode->addCalledFunction(CS, A.CG->getOrInsertFunction(CS.getCalledFunction())); }
void code_emitter::setup_filter_function (bool is_main_filter_function) { Function *filter_function = is_main_filter_function ? lookup_main_filter_function(module, filter) : lookup_filter_function(module, filter); Function::arg_iterator args = filter_function->arg_begin(); Value *slice_arg = NULL; if (is_main_filter_function) { slice_arg = args++; slice_arg->setName("slice"); } else { invocation_arg = args++; invocation_arg->setName("invocation"); } closure_arg = args++; closure_arg->setName("closure"); if (is_main_filter_function) { x_vars_var = args++; x_vars_var->setName("x_vars"); y_vars_var = args++; y_vars_var->setName("y_vars"); } set_internal(::lookup_internal(filter->v.mathmap.internals, "x", true), args++); set_internal(::lookup_internal(filter->v.mathmap.internals, "y", true), args++); set_internal(::lookup_internal(filter->v.mathmap.internals, "t", true), args++); pools_arg = args++; pools_arg->setName("pools"); BasicBlock *block = BasicBlock::Create("entry", filter_function); builder = new IRBuilder<> (block); if (is_main_filter_function) { x_vars_var = builder->CreateBitCast(x_vars_var, PointerType::getUnqual(x_vars_type)); y_vars_var = builder->CreateBitCast(y_vars_var, PointerType::getUnqual(y_vars_type)); frame_arg = builder->CreateCall(module->getFunction(string("get_slice_frame")), slice_arg); invocation_arg = builder->CreateCall(module->getFunction(string("get_frame_invocation")), frame_arg); } set_internals_from_invocation(invocation_arg); if (is_main_filter_function) set_xy_vars_from_frame (); else setup_xy_vars_from_closure (); alloc_complex_copy_var(); current_function = filter_function; }
CodeGenBlock::CodeGenBlock(int args, int locals, CodeGenLexicalScope *enclosingScope, CodeGenModule *Mod) : CodeGenLexicalScope(Mod), parentScope(enclosingScope) { Value *enclosingContext = enclosingScope->getContext(); // Define the layout of a block BlockTy = StructType::get( Mod->Context, IdTy, // 0 - isa. IMPTy, // 1 - Function pointer. Type::getInt32Ty(Mod->Context),// 2 - Number of args. enclosingContext->getType(), // 3 - Context. NULL); std::vector<const Type*> argTy; argTy.push_back(PointerType::getUnqual(BlockTy)); // FIXME: Broken on Etoile runtime - _cmd needs to be a GEP on _call argTy.push_back(SelTy); for (int i=0 ; i<args ; ++i) { argTy.push_back(IdTy); } FunctionType *BlockFunctionTy = FunctionType::get(IdTy, argTy, false); IRBuilder<> *MethodBuilder = enclosingScope->getBuilder(); // Create the block object // The NewBlock function gets a block from a pool. It should really be // inlined. Block = MethodBuilder->CreateAlloca(BlockTy); Module *TheModule = CGM->getModule(); // Create the block function CurrentFunction = Function::Create(BlockFunctionTy, GlobalValue::InternalLinkage, "BlockFunction", TheModule); InitialiseFunction(Args, Locals, locals); // Set the isa pointer Value *isa = MethodBuilder->CreateLoad( TheModule->getGlobalVariable(".smalltalk_block_stack_class", true)); storeInStruct(MethodBuilder, Block, isa, 0); // Store the block function in the object storeInStruct(MethodBuilder, Block, MethodBuilder->CreateBitCast(CurrentFunction, IMPTy), 1); // Store the number of arguments storeInStruct(MethodBuilder, Block, ConstantInt::get(Type::getInt32Ty(Mod->Context), args), 2); // Set the context storeInStruct(MethodBuilder, Block, enclosingScope->getContext(), 3); }
// Calls to setjmp(p) are lowered to _setjmp3(p, 0) by the frontend. // The idea behind _setjmp3 is that it takes an optional number of personality // specific parameters to indicate how to restore the personality-specific frame // state when longjmp is initiated. Typically, the current TryLevel is saved. void WinEHStatePass::rewriteSetJmpCallSite(IRBuilder<> &Builder, Function &F, CallSite CS, Value *State) { // Don't rewrite calls with a weird number of arguments. if (CS.getNumArgOperands() != 2) return; Instruction *Inst = CS.getInstruction(); SmallVector<OperandBundleDef, 1> OpBundles; CS.getOperandBundlesAsDefs(OpBundles); SmallVector<Value *, 3> OptionalArgs; if (Personality == EHPersonality::MSVC_CXX) { OptionalArgs.push_back(CxxLongjmpUnwind); OptionalArgs.push_back(State); OptionalArgs.push_back(emitEHLSDA(Builder, &F)); } else if (Personality == EHPersonality::MSVC_X86SEH) { OptionalArgs.push_back(SehLongjmpUnwind); OptionalArgs.push_back(State); if (UseStackGuard) OptionalArgs.push_back(Cookie); } else { llvm_unreachable("unhandled personality!"); } SmallVector<Value *, 5> Args; Args.push_back( Builder.CreateBitCast(CS.getArgOperand(0), Builder.getInt8PtrTy())); Args.push_back(Builder.getInt32(OptionalArgs.size())); Args.append(OptionalArgs.begin(), OptionalArgs.end()); CallSite NewCS; if (CS.isCall()) { auto *CI = cast<CallInst>(Inst); CallInst *NewCI = Builder.CreateCall(SetJmp3, Args, OpBundles); NewCI->setTailCallKind(CI->getTailCallKind()); NewCS = NewCI; } else { auto *II = cast<InvokeInst>(Inst); NewCS = Builder.CreateInvoke( SetJmp3, II->getNormalDest(), II->getUnwindDest(), Args, OpBundles); } NewCS.setCallingConv(CS.getCallingConv()); NewCS.setAttributes(CS.getAttributes()); NewCS->setDebugLoc(CS->getDebugLoc()); Instruction *NewInst = NewCS.getInstruction(); NewInst->takeName(Inst); Inst->replaceAllUsesWith(NewInst); Inst->eraseFromParent(); }
void EmitMemSet(IRBuilder<>& B, Value* Dst, Value* Val, Value* Len, const Analysis& A) { Dst = B.CreateBitCast(Dst, PointerType::getUnqual(B.getInt8Ty())); Module *M = B.GetInsertBlock()->getParent()->getParent(); Type* intTy = Len->getType(); Type *VoidPtrTy = PointerType::getUnqual(B.getInt8Ty()); Type *Tys[2] = {VoidPtrTy, intTy}; Function *MemSet = Intrinsic::getDeclaration(M, Intrinsic::memset, llvm::makeArrayRef(Tys, 2)); Value *Align = ConstantInt::get(B.getInt32Ty(), 1); CallSite CS = B.CreateCall5(MemSet, Dst, Val, Len, Align, B.getFalse()); if (A.CGNode) A.CGNode->addCalledFunction(CS, A.CG->getOrInsertFunction(MemSet)); }
void WinEHStatePass::linkExceptionRegistration(IRBuilder<> &Builder, Function *Handler) { // Emit the .safeseh directive for this function. Handler->addFnAttr("safeseh"); Type *LinkTy = getEHLinkRegistrationType(); // Handler = Handler Value *HandlerI8 = Builder.CreateBitCast(Handler, Builder.getInt8PtrTy()); Builder.CreateStore(HandlerI8, Builder.CreateStructGEP(LinkTy, Link, 1)); // Next = [fs:00] Constant *FSZero = Constant::getNullValue(LinkTy->getPointerTo()->getPointerTo(257)); Value *Next = Builder.CreateLoad(FSZero); Builder.CreateStore(Next, Builder.CreateStructGEP(LinkTy, Link, 0)); // [fs:00] = Link Builder.CreateStore(Link, FSZero); }
Value* code_emitter::convert_complex_return_value (Value *result) { /* The result is complex, whose representation differs between archs, and we need to transform it into another arch-dependent representation. */ if (sizeof(gpointer) == 4) { Value *local = complex_copy_var; Value *local_ptr = builder->CreateBitCast(local, PointerType::getUnqual(Type::Int64Ty)); builder->CreateStore(result, local_ptr); result = builder->CreateLoad(local); } else if (sizeof(gpointer) == 8) result = builder->CreateExtractValue(result, 0); else g_assert_not_reached(); return result; }
Value* ColExpression::getValue() { IRBuilder<>* builder = codegen::getBuilder(); DataType dt = codegen::getAttType(index); Value* tupleptr = codegen::getTupleptr(); Value *indices[1]; indices[0] = ConstantInt::get(Type::getInt32Ty(getGlobalContext()), (uint64_t) index); ArrayRef<Value*> indicesRef(indices); Value *dataptr = builder->CreateInBoundsGEP(tupleptr, indicesRef); switch(dt){ case DOUBLE: return builder->CreateLoad( builder->CreateBitCast(dataptr, Type::getDoublePtrTy(getGlobalContext())) ); case LONG: case STRING: case DATE: return builder->CreateLoad(dataptr); } }
Value* code_emitter::setup_init_x_or_y_function (string function_name, const char *internal_name, StructType *vars_type) { current_function = module->getFunction(function_name); Value *slice_arg; Function::arg_iterator args = current_function->arg_begin(); slice_arg = args++; slice_arg->setName("slice"); closure_arg = args++; closure_arg->setName("closure"); set_internal(::lookup_internal(filter->v.mathmap.internals, internal_name, true), args++); set_internal(::lookup_internal(filter->v.mathmap.internals, "t", true), args++); BasicBlock *block = BasicBlock::Create("entry", current_function); builder = new IRBuilder<> (block); frame_arg = builder->CreateCall(module->getFunction(string("get_slice_frame")), slice_arg); invocation_arg = builder->CreateCall(module->getFunction(string("get_frame_invocation")), frame_arg); pools_arg = builder->CreateCall(module->getFunction("get_slice_pools"), slice_arg); set_internals_from_invocation(invocation_arg); set_xy_vars_from_frame(); ret_var = builder->CreateCall2(module->getFunction(string("_mathmap_pools_alloc")), pools_arg, emit_sizeof(vars_type)); Value *vars_var = builder->CreateBitCast(ret_var, PointerType::getUnqual(vars_type)); alloc_complex_copy_var(); return vars_var; }
void code_emitter::setup_init_frame_function () { Value *t_arg; Function::arg_iterator args = init_frame_function->arg_begin(); invocation_arg = args++; invocation_arg->setName("invocation"); //frame_arg = args++; //frame_arg->setName("frame"); closure_arg = args++; closure_arg->setName("closure"); t_arg = args++; t_arg->setName("t"); pools_arg = args++; pools_arg->setName("pools"); BasicBlock *block = BasicBlock::Create("entry", init_frame_function); builder = new IRBuilder<> (block); //invocation_arg = builder->CreateCall(module->getFunction(string("get_frame_invocation")), frame_arg); //pools_arg = builder->CreateCall(module->getFunction(string("get_frame_pools")), frame_arg); set_internal(::lookup_internal(filter->v.mathmap.internals, "t", true), t_arg); set_internals_from_invocation(invocation_arg); ret_var = builder->CreateCall2(module->getFunction(string("_mathmap_pools_alloc")), pools_arg, emit_sizeof(xy_vars_type)); xy_vars_var = builder->CreateBitCast(ret_var, PointerType::getUnqual(xy_vars_type)); alloc_complex_copy_var(); current_function = init_frame_function; }
std::pair<Value *, Value *> AMDGPUPromoteAlloca::getLocalSizeYZ(IRBuilder<> &Builder) { if (!IsAMDHSA) { Function *LocalSizeYFn = Intrinsic::getDeclaration(Mod, Intrinsic::r600_read_local_size_y); Function *LocalSizeZFn = Intrinsic::getDeclaration(Mod, Intrinsic::r600_read_local_size_z); CallInst *LocalSizeY = Builder.CreateCall(LocalSizeYFn, {}); CallInst *LocalSizeZ = Builder.CreateCall(LocalSizeZFn, {}); LocalSizeY->setMetadata(LLVMContext::MD_range, MaxWorkGroupSizeRange); LocalSizeZ->setMetadata(LLVMContext::MD_range, MaxWorkGroupSizeRange); return std::make_pair(LocalSizeY, LocalSizeZ); } // We must read the size out of the dispatch pointer. assert(IsAMDGCN); // We are indexing into this struct, and want to extract the workgroup_size_* // fields. // // typedef struct hsa_kernel_dispatch_packet_s { // uint16_t header; // uint16_t setup; // uint16_t workgroup_size_x ; // uint16_t workgroup_size_y; // uint16_t workgroup_size_z; // uint16_t reserved0; // uint32_t grid_size_x ; // uint32_t grid_size_y ; // uint32_t grid_size_z; // // uint32_t private_segment_size; // uint32_t group_segment_size; // uint64_t kernel_object; // // #ifdef HSA_LARGE_MODEL // void *kernarg_address; // #elif defined HSA_LITTLE_ENDIAN // void *kernarg_address; // uint32_t reserved1; // #else // uint32_t reserved1; // void *kernarg_address; // #endif // uint64_t reserved2; // hsa_signal_t completion_signal; // uint64_t wrapper // } hsa_kernel_dispatch_packet_t // Function *DispatchPtrFn = Intrinsic::getDeclaration(Mod, Intrinsic::amdgcn_dispatch_ptr); CallInst *DispatchPtr = Builder.CreateCall(DispatchPtrFn, {}); DispatchPtr->addAttribute(AttributeSet::ReturnIndex, Attribute::NoAlias); DispatchPtr->addAttribute(AttributeSet::ReturnIndex, Attribute::NonNull); // Size of the dispatch packet struct. DispatchPtr->addDereferenceableAttr(AttributeSet::ReturnIndex, 64); Type *I32Ty = Type::getInt32Ty(Mod->getContext()); Value *CastDispatchPtr = Builder.CreateBitCast( DispatchPtr, PointerType::get(I32Ty, AMDGPUAS::CONSTANT_ADDRESS)); // We could do a single 64-bit load here, but it's likely that the basic // 32-bit and extract sequence is already present, and it is probably easier // to CSE this. The loads should be mergable later anyway. Value *GEPXY = Builder.CreateConstInBoundsGEP1_64(CastDispatchPtr, 1); LoadInst *LoadXY = Builder.CreateAlignedLoad(GEPXY, 4); Value *GEPZU = Builder.CreateConstInBoundsGEP1_64(CastDispatchPtr, 2); LoadInst *LoadZU = Builder.CreateAlignedLoad(GEPZU, 4); MDNode *MD = llvm::MDNode::get(Mod->getContext(), None); LoadXY->setMetadata(LLVMContext::MD_invariant_load, MD); LoadZU->setMetadata(LLVMContext::MD_invariant_load, MD); LoadZU->setMetadata(LLVMContext::MD_range, MaxWorkGroupSizeRange); // Extract y component. Upper half of LoadZU should be zero already. Value *Y = Builder.CreateLShr(LoadXY, 16); return std::make_pair(Y, LoadZU); }
void GNUstep::IMPCacher::SpeculativelyInline(Instruction *call, Function *function) { BasicBlock *beforeCallBB = call->getParent(); BasicBlock *callBB = SplitBlock(beforeCallBB, call, Owner); BasicBlock *inlineBB = BasicBlock::Create(Context, "inline", callBB->getParent()); BasicBlock::iterator iter = call; iter++; BasicBlock *afterCallBB = SplitBlock(iter->getParent(), iter, Owner); removeTerminator(beforeCallBB); // Put a branch before the call, testing whether the callee really is the // function IRBuilder<> B = IRBuilder<>(beforeCallBB); Value *callee = isa<CallInst>(call) ? cast<CallInst>(call)->getCalledValue() : cast<InvokeInst>(call)->getCalledValue(); const FunctionType *FTy = function->getFunctionType(); const FunctionType *calleeTy = cast<FunctionType>( cast<PointerType>(callee->getType())->getElementType()); if (calleeTy != FTy) { callee = B.CreateBitCast(callee, function->getType()); } Value *isInlineValid = B.CreateICmpEQ(callee, function); B.CreateCondBr(isInlineValid, inlineBB, callBB); // In the inline BB, add a copy of the call, but this time calling the real // version. Instruction *inlineCall = call->clone(); Value *inlineResult= inlineCall; inlineBB->getInstList().push_back(inlineCall); B.SetInsertPoint(inlineBB); if (calleeTy != FTy) { for (unsigned i=0 ; i<FTy->getNumParams() ; i++) { LLVMType *callType = calleeTy->getParamType(i); LLVMType *argType = FTy->getParamType(i); if (callType != argType) { inlineCall->setOperand(i, new BitCastInst(inlineCall->getOperand(i), argType, "", inlineCall)); } } if (FTy->getReturnType() != calleeTy->getReturnType()) { if (FTy->getReturnType() == Type::getVoidTy(Context)) { inlineResult = Constant::getNullValue(calleeTy->getReturnType()); } else { inlineResult = new BitCastInst(inlineCall, calleeTy->getReturnType(), "", inlineBB); } } } B.CreateBr(afterCallBB); // Unify the return values if (call->getType() != Type::getVoidTy(Context)) { PHINode *phi = CreatePHI(call->getType(), 2, "", afterCallBB->begin()); call->replaceAllUsesWith(phi); phi->addIncoming(call, callBB); phi->addIncoming(inlineResult, inlineBB); } // Really do the real inlining InlineFunctionInfo IFI(0, 0); if (CallInst *c = dyn_cast<CallInst>(inlineCall)) { c->setCalledFunction(function); InlineFunction(c, IFI); } else if (InvokeInst *c = dyn_cast<InvokeInst>(inlineCall)) { c->setCalledFunction(function); InlineFunction(c, IFI); } }
void code_emitter::set_xy_vars_from_frame () { Value *xy_vars_untyped = builder->CreateCall(module->getFunction(string("get_frame_xy_vars")), frame_arg); xy_vars_var = builder->CreateBitCast(xy_vars_untyped, PointerType::getUnqual(xy_vars_type)); }