LLValue *DLValue::getRVal() { if (DtoIsInMemoryOnly(type->toBasetype())) { llvm_unreachable("getRVal() for memory-only type"); return nullptr; } LLValue *rawValue = DtoLoad(val); if (type->toBasetype()->ty != Tbool) return rawValue; assert(rawValue->getType() == llvm::Type::getInt8Ty(gIR->context())); return gIR->ir->CreateTrunc(rawValue, llvm::Type::getInt1Ty(gIR->context())); }
DRValue *DLValue::getRVal() { if (DtoIsInMemoryOnly(type)) { llvm_unreachable("getRVal() for memory-only type"); return nullptr; } LLValue *rval = DtoLoad(val); if (type->toBasetype()->ty == Tbool) { assert(rval->getType() == llvm::Type::getInt8Ty(gIR->context())); if (isOptimizationEnabled()) { // attach range metadata for i8 being loaded: [0, 2) llvm::MDBuilder mdBuilder(gIR->context()); llvm::cast<llvm::LoadInst>(rval)->setMetadata( llvm::LLVMContext::MD_range, mdBuilder.createRange(llvm::APInt(8, 0), llvm::APInt(8, 2))); } // truncate to i1 rval = gIR->ir->CreateTrunc(rval, llvm::Type::getInt1Ty(gIR->context())); } return new DImValue(type, rval); }
DImValue::DImValue(Type *t, llvm::Value *v) : DValue(t, v) { assert(!DtoIsInMemoryOnly(t) && "Cannot represent memory-only type as immediate DValue"); }
bool returnInArg(TypeFunction *tf, bool) override { return !tf->isref && DtoIsInMemoryOnly(tf->next); }
DRValue::DRValue(Type *t, LLValue *v) : DValue(t, v) { assert(!DtoIsInMemoryOnly(t) && "Cannot represent memory-only type as DRValue"); }
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.addByVal(DtoAlignment(argType)); } 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) && DtoIsInMemoryOnly(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; } }