LLConstant *DtoGEPi(LLConstant *ptr, unsigned i0, unsigned i1) { LLPointerType *p = isaPointer(ptr); (void)p; assert(p && "GEP expects a pointer type"); LLValue *indices[] = {DtoConstUint(i0), DtoConstUint(i1)}; return llvm::ConstantExpr::getGetElementPtr( p->getElementType(), ptr, indices, /* InBounds = */ true); }
LLValue* DtoGEPi1(LLValue* ptr, unsigned i, const char* var, llvm::BasicBlock* bb) { LLPointerType* p = isaPointer(ptr); assert(p && "GEP expects a pointer type"); return llvm::GetElementPtrInst::Create( #if LDC_LLVM_VER >= 307 p->getElementType(), #endif ptr, DtoConstUint(i), var, bb ? bb : gIR->scopebb()); }
LLConstant* DtoGEPi(LLConstant* ptr, unsigned i0, unsigned i1) { LLPointerType* p = isaPointer(ptr); assert(p && "GEP expects a pointer type"); LLValue* v[] = { DtoConstUint(i0), DtoConstUint(i1) }; return llvm::ConstantExpr::getGetElementPtr( #if LDC_LLVM_VER >= 307 p->getElementType(), #endif ptr, v, true); }
LLValue* DtoGEP(LLValue* ptr, LLValue* i0, LLValue* i1, const char* var, llvm::BasicBlock* bb) { LLPointerType* p = isaPointer(ptr); assert(p && "GEP expects a pointer type"); LLValue* v[] = { i0, i1 }; return llvm::GetElementPtrInst::Create( #if LDC_LLVM_VER >= 307 p->getElementType(), #endif ptr, v, var, bb ? bb : gIR->scopebb()); }
LLFunctionType *DtoExtractFunctionType(LLType *type) { if (LLFunctionType *fty = isaFunction(type)) { return fty; } if (LLPointerType *pty = isaPointer(type)) { if (LLFunctionType *fty = isaFunction(pty->getElementType())) { return fty; } } return nullptr; }
void DtoNestedInit(VarDeclaration* vd) { Logger::println("DtoNestedInit for %s", vd->toChars()); LOG_SCOPE IrFunction* irfunc = gIR->func()->decl->ir.irFunc; LLValue* nestedVar = irfunc->nestedVar; if (nestedCtx == NCArray) { // alloca as usual if no value already if (!vd->ir.irLocal->value) vd->ir.irLocal->value = DtoAlloca(vd->type, vd->toChars()); // store the address into the nested vars array assert(vd->ir.irLocal->nestedIndex >= 0); LLValue* gep = DtoGEPi(nestedVar, 0, vd->ir.irLocal->nestedIndex); assert(isaPointer(vd->ir.irLocal->value)); LLValue* val = DtoBitCast(vd->ir.irLocal->value, getVoidPtrType()); DtoAlignedStore(val, gep); } else if (nestedCtx == NCHybrid) { assert(vd->ir.irLocal->value && "Nested variable without storage?"); if (!vd->isParameter() && (vd->isRef() || vd->isOut())) { unsigned vardepth = vd->ir.irLocal->nestedDepth; LLValue* val = NULL; // Retrieve frame pointer if (vardepth == irfunc->depth) { val = nestedVar; } else { FuncDeclaration *parentfunc = getParentFunc(vd, true); assert(parentfunc && "No parent function for nested variable?"); val = DtoGEPi(nestedVar, 0, vardepth); val = DtoAlignedLoad(val, (std::string(".frame.") + parentfunc->toChars()).c_str()); } val = DtoGEPi(val, 0, vd->ir.irLocal->nestedIndex, vd->toChars()); storeVariable(vd, val); } else { // Already initialized in DtoCreateNestedContext } } else { assert(0 && "Not implemented yet"); } }
static void storeVariable(VarDeclaration *vd, LLValue *dst) { LLValue *value = vd->ir.irLocal->value; int ty = vd->type->ty; FuncDeclaration *fd = getParentFunc(vd, true); assert(fd && "No parent function for nested variable?"); if (fd->needsClosure() && !vd->isRef() && (ty == Tstruct || ty == Tsarray) && isaPointer(value->getType())) { // Copy structs and static arrays LLValue *mem = DtoGcMalloc(vd->loc, DtoType(vd->type), ".gc_mem"); DtoAggrCopy(mem, value); DtoAlignedStore(mem, dst); } else // Store the address into the frame DtoAlignedStore(value, dst); }
static void addExplicitArguments(std::vector<LLValue *> &args, AttrSet &attrs, IrFuncTy &irFty, LLFunctionType *callableTy, const std::vector<DValue *> &argvals, int numFormalParams) { // Number of arguments added to the LLVM type that are implicit on the // frontend side of things (this, context pointers, etc.) const size_t implicitLLArgCount = args.size(); // Number of formal arguments in the LLVM type (i.e. excluding varargs). const size_t formalLLArgCount = irFty.args.size(); // The number of explicit arguments in the D call expression (including // varargs), not all of which necessarily generate a LLVM argument. const size_t explicitDArgCount = argvals.size(); // construct and initialize an IrFuncTyArg object for each vararg std::vector<IrFuncTyArg *> optionalIrArgs; for (size_t i = numFormalParams; i < explicitDArgCount; i++) { Type *argType = argvals[i]->getType(); bool passByVal = gABI->passByVal(argType); AttrBuilder initialAttrs; if (passByVal) { initialAttrs.add(LLAttribute::ByVal); } else { initialAttrs.add(DtoShouldExtend(argType)); } optionalIrArgs.push_back(new IrFuncTyArg(argType, passByVal, initialAttrs)); optionalIrArgs.back()->parametersIdx = i; } // let the ABI rewrite the IrFuncTyArg objects gABI->rewriteVarargs(irFty, optionalIrArgs); const size_t explicitLLArgCount = formalLLArgCount + optionalIrArgs.size(); args.resize(implicitLLArgCount + explicitLLArgCount, static_cast<llvm::Value *>(nullptr)); // Iterate the explicit arguments from left to right in the D source, // which is the reverse of the LLVM order if irFty.reverseParams is true. for (size_t i = 0; i < explicitLLArgCount; ++i) { const bool isVararg = (i >= irFty.args.size()); IrFuncTyArg *irArg = nullptr; if (isVararg) { irArg = optionalIrArgs[i - numFormalParams]; } else { irArg = irFty.args[i]; } DValue *const argval = argvals[irArg->parametersIdx]; Type *const argType = argval->getType(); llvm::Value *llVal = nullptr; if (isVararg) { llVal = irFty.putParam(*irArg, argval); } else { llVal = irFty.putParam(i, argval); } const size_t llArgIdx = implicitLLArgCount + (irFty.reverseParams ? explicitLLArgCount - i - 1 : i); llvm::Type *const callableArgType = (isVararg ? nullptr : callableTy->getParamType(llArgIdx)); // Hack around LDC assuming structs and static arrays are in memory: // If the function wants a struct, and the argument value is a // pointer to a struct, load from it before passing it in. if (isaPointer(llVal) && DtoIsPassedByRef(argType) && ((!isVararg && !isaPointer(callableArgType)) || (isVararg && !irArg->byref && !irArg->isByVal()))) { Logger::println("Loading struct type for function argument"); llVal = DtoLoad(llVal); } // parameter type mismatch, this is hard to get rid of if (!isVararg && llVal->getType() != callableArgType) { IF_LOG { Logger::cout() << "arg: " << *llVal << '\n'; Logger::cout() << "expects: " << *callableArgType << '\n'; } if (isaStruct(llVal)) { llVal = DtoAggrPaint(llVal, callableArgType); } else { llVal = DtoBitCast(llVal, callableArgType); } } args[llArgIdx] = llVal; // +1 as index 0 contains the function attributes. attrs.add(llArgIdx + 1, irArg->attrs); if (isVararg) { delete irArg; } }
DVarValue::DVarValue(Type* t, LLValue* llvmValue) : DValue(t), var(0), val(llvmValue) { assert(isaPointer(llvmValue)); }
DVarValue::DVarValue(Type* t, VarDeclaration* vd, LLValue* llvmValue) : DValue(t), var(vd), val(llvmValue) { assert(isaPointer(llvmValue)); }