Refactor code to hide direct IrFunction->func usage and add convenient functions (#1911)

This commit is contained in:
Ivan Butygin 2017-01-18 00:40:32 +03:00 committed by Johan Engelen
parent 09cef87178
commit a26bfc1223
17 changed files with 158 additions and 73 deletions

View file

@ -90,7 +90,7 @@ DValue *DtoNewClass(Loc &loc, TypeClass *tc, NewExp *newexp) {
// custom allocator
else if (newexp->allocator) {
DtoResolveFunction(newexp->allocator);
DFuncValue dfn(newexp->allocator, getIrFunc(newexp->allocator)->func);
DFuncValue dfn(newexp->allocator, DtoCallee(newexp->allocator));
DValue *res = DtoCallFunction(newexp->loc, nullptr, &dfn, newexp->newargs);
mem = DtoBitCast(DtoRVal(res), DtoType(tc), ".newclass_custom");
}
@ -133,7 +133,7 @@ DValue *DtoNewClass(Loc &loc, TypeClass *tc, NewExp *newexp) {
Logger::println("Calling constructor");
assert(newexp->arguments != NULL);
DtoResolveFunction(newexp->member);
DFuncValue dfn(newexp->member, getIrFunc(newexp->member)->func, mem);
DFuncValue dfn(newexp->member, DtoCallee(newexp->member), mem);
return DtoCallFunction(newexp->loc, tc, &dfn, newexp->arguments);
}
@ -485,7 +485,7 @@ static LLConstant *build_class_dtor(ClassDeclaration *cd) {
DtoResolveFunction(dtor);
return llvm::ConstantExpr::getBitCast(
getIrFunc(dtor)->func, getPtrToType(LLType::getInt8Ty(gIR->context())));
DtoCallee(dtor), getPtrToType(LLType::getInt8Ty(gIR->context())));
}
static ClassFlags::Type build_classinfo_flags(ClassDeclaration *cd) {

View file

@ -828,7 +828,7 @@ ldc::DISubprogram ldc::DIBuilder::EmitSubProgram(FuncDeclaration *fd) {
auto SP = DBuilder.createFunction(
CU, // context
fd->toPrettyChars(), // name
getIrFunc(fd)->func->getName(), // linkage name
getIrFunc(fd)->getLLVMFuncName(), // linkage name
file, // file
fd->loc.linnum, // line no
DIFnType, // type
@ -839,12 +839,12 @@ ldc::DISubprogram ldc::DIBuilder::EmitSubProgram(FuncDeclaration *fd) {
isOptimizationEnabled() // isOptimized
#if LDC_LLVM_VER < 308
,
getIrFunc(fd)->func
DtoFunction(fd)
#endif
);
#if LDC_LLVM_VER >= 308
if (fd->fbody)
getIrFunc(fd)->func->setSubprogram(SP);
DtoFunction(fd)->setSubprogram(SP);
#endif
return SP;
}
@ -888,12 +888,12 @@ ldc::DISubprogram ldc::DIBuilder::EmitThunk(llvm::Function *Thunk,
isOptimizationEnabled() // isOptimized
#if LDC_LLVM_VER < 308
,
getIrFunc(fd)->func
DtoFunction(fd)
#endif
);
#if LDC_LLVM_VER >= 308
if (fd->fbody)
getIrFunc(fd)->func->setSubprogram(SP);
DtoFunction(fd)->setSubprogram(SP);
#endif
return SP;
}

View file

@ -323,7 +323,7 @@ static llvm::Function *DtoDeclareVaFunction(FuncDeclaration *fdecl) {
}
assert(func);
getIrFunc(fdecl)->func = func;
getIrFunc(fdecl)->setLLVMFunc(func);
return func;
}
@ -548,7 +548,7 @@ void DtoDeclareFunction(FuncDeclaration *fdecl) {
IF_LOG Logger::cout() << "func = " << *func << std::endl;
// add func to IRFunc
irFunc->func = func;
irFunc->setLLVMFunc(func);
// parameter attributes
if (!DtoIsIntrinsic(fdecl)) {
@ -781,12 +781,14 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
}
if (fd->ir->isDefined()) {
llvm::Function *func = getIrFunc(fd)->getLLVMFunc();
assert(nullptr != func);
if (!linkageAvailableExternally &&
(getIrFunc(fd)->func->getLinkage() ==
(func->getLinkage() ==
llvm::GlobalValue::AvailableExternallyLinkage)) {
// Fix linkage
const auto lwc = lowerFuncLinkage(fd);
setLinkage(lwc, getIrFunc(fd)->func);
setLinkage(lwc, func);
}
return;
}
@ -917,7 +919,7 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
const auto f = static_cast<TypeFunction *>(fd->type->toBasetype());
IrFuncTy &irFty = irFunc->irFty;
llvm::Function *func = irFunc->func;
llvm::Function *func = irFunc->getLLVMFunc();
const auto lwc = lowerFuncLinkage(fd);
if (linkageAvailableExternally) {
@ -1027,7 +1029,7 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
defineParameters(irFty, *fd->parameters);
// Initialize PGO state for this function
funcGen.pgo.assignRegionCounters(fd, irFunc->func);
funcGen.pgo.assignRegionCounters(fd, func);
DtoCreateNestedContext(funcGen);

View file

@ -56,7 +56,7 @@ IrFunction *IRState::func() {
}
llvm::Function *IRState::topfunc() {
return func()->func;
return func()->getLLVMFunc();
}
llvm::Instruction *IRState::topallocapoint() {
@ -126,6 +126,11 @@ LLCallSite IRState::CreateCallOrInvoke(LLValue *Callee, LLValue *Arg1,
return funcGen().callOrInvoke(Callee, args, Name);
}
bool IRState::isMainFunc(const IrFunction *func) const {
assert(func != nullptr);
return func->getLLVMFunc() == mainFunc;
}
bool IRState::emitArrayBoundsChecks() {
if (global.params.useArrayBounds != BOUNDSCHECKsafeonly) {
return global.params.useArrayBounds == BOUNDSCHECKon;

View file

@ -161,6 +161,8 @@ struct IRState {
LLValue *Arg2, LLValue *Arg3, LLValue *Arg4,
const char *Name = "");
bool isMainFunc(const IrFunction *func) const;
// this holds the array being indexed or sliced so $ will work
// might be a better way but it works. problem is I only get a
// VarDeclaration for __dollar, but I can't see how to get the

View file

@ -1383,7 +1383,7 @@ void callPostblit(Loc &loc, Expression *exp, LLValue *val) {
}
DtoResolveFunction(fd);
Expressions args;
DFuncValue dfn(fd, getIrFunc(fd)->func, val);
DFuncValue dfn(fd, DtoCallee(fd), val);
DtoCallFunction(loc, Type::basic[Tvoid], &dfn, &args);
}
}
@ -1588,9 +1588,9 @@ DValue *DtoSymbolAddress(Loc &loc, Type *type, Declaration *decl) {
// We need to codegen the function here, because literals are not added
// to the module member list.
DtoDefineFunction(flitdecl);
assert(getIrFunc(flitdecl)->func);
assert(DtoCallee(flitdecl));
return new DFuncValue(flitdecl, getIrFunc(flitdecl)->func);
return new DFuncValue(flitdecl, DtoCallee(flitdecl));
}
if (FuncDeclaration *fdecl = decl->isFuncDeclaration()) {
@ -1607,7 +1607,7 @@ DValue *DtoSymbolAddress(Loc &loc, Type *type, Declaration *decl) {
}
DtoResolveFunction(fdecl);
return new DFuncValue(fdecl, fdecl->llvmInternal != LLVMva_arg
? getIrFunc(fdecl)->func
? DtoCallee(fdecl)
: nullptr);
}
@ -1661,7 +1661,7 @@ llvm::Constant *DtoConstSymbolAddress(Loc &loc, Declaration *decl) {
// static function
if (FuncDeclaration *fd = decl->isFuncDeclaration()) {
DtoResolveFunction(fd);
return getIrFunc(fd)->func;
return DtoCallee(fd);
}
llvm_unreachable("Taking constant address not implemented.");

View file

@ -48,7 +48,7 @@ llvm::Function *buildForwarderFunction(
}
if (funcs.size() == 1) {
return getIrFunc(funcs.front())->func;
return DtoCallee(funcs.front());
}
}
@ -74,7 +74,7 @@ llvm::Function *buildForwarderFunction(
// ... calling the given functions, and...
for (auto func : funcs) {
const auto f = getIrFunc(func)->func;
const auto f = DtoCallee(func);
#if LDC_LLVM_VER < 307
const auto call = builder.CreateCall(f, "");
const auto ft = call->getCalledFunction()->getFunctionType();

View file

@ -602,7 +602,7 @@ void addCoverageAnalysis(Module *m) {
FuncDeclaration::genCfunc(nullptr, Type::tvoid, ctorname.c_str());
fd->linkage = LINKd;
IrFunction *irfunc = getIrFunc(fd, true);
irfunc->func = ctor;
irfunc->setLLVMFunc(ctor);
getIrModule(m)->sharedCtors.push_back(fd);
}

View file

@ -133,7 +133,7 @@ void RTTIBuilder::push_size_as_vp(uint64_t s) {
void RTTIBuilder::push_funcptr(FuncDeclaration *fd, Type *castto) {
if (fd) {
DtoResolveFunction(fd);
LLConstant *F = getIrFunc(fd)->func;
LLConstant *F = DtoCallee(fd);
if (castto) {
F = DtoBitCast(F, DtoType(castto));
}

View file

@ -132,14 +132,14 @@ public:
auto &funcGen = irs->funcGen();
IrFunction *const f = &funcGen.irFunc;
FuncDeclaration *const fd = f->decl;
LLFunction *const llFunc = f->func;
llvm::FunctionType *funcType = f->getLLVMFuncType();
emitInstrumentationFnLeave(fd);
// is there a return value expression?
if (stmt->exp || (!stmt->exp && (llFunc == irs->mainFunc))) {
if (stmt->exp || (!stmt->exp && irs->isMainFunc(f))) {
// if the function's return type is void, it uses sret
if (llFunc->getReturnType() == LLType::getVoidTy(irs->context())) {
if (funcType->getReturnType() == LLType::getVoidTy(irs->context())) {
assert(!f->type->isref);
LLValue *sretPointer = getIrFunc(fd)->sretArg;
@ -181,7 +181,7 @@ public:
}
} else {
// the return type is not void, so this is a normal "register" return
if (!stmt->exp && (llFunc == irs->mainFunc)) {
if (!stmt->exp && irs->isMainFunc(f)) {
returnValue =
LLConstant::getNullValue(irs->mainFunc->getReturnType());
} else {
@ -207,7 +207,7 @@ public:
// If the function returns a struct or a static array, and the return
// value is a pointer to a struct or a static array, load from it
// before returning.
if (returnValue->getType() != llFunc->getReturnType() &&
if (returnValue->getType() != funcType->getReturnType() &&
DtoIsInMemoryOnly(f->type->next) &&
isaPointer(returnValue->getType())) {
Logger::println("Loading value for return");
@ -215,18 +215,18 @@ public:
}
// can happen for classes and void main
if (returnValue->getType() != llFunc->getReturnType()) {
if (returnValue->getType() != funcType->getReturnType()) {
// for the main function this only happens if it is declared as void
// and then contains a return (exp); statement. Since the actual
// return type remains i32, we just throw away the exp value
// and return 0 instead
// if we're not in main, just bitcast
if (llFunc == irs->mainFunc) {
if (irs->isMainFunc(f)) {
returnValue =
LLConstant::getNullValue(irs->mainFunc->getReturnType());
} else {
returnValue =
irs->ir->CreateBitCast(returnValue, llFunc->getReturnType());
irs->ir->CreateBitCast(returnValue, funcType->getReturnType());
}
IF_LOG Logger::cout() << "return value after cast: " << *returnValue
@ -235,7 +235,7 @@ public:
}
} else {
// no return value expression means it's a void function.
assert(llFunc->getReturnType() == LLType::getVoidTy(irs->context()));
assert(funcType->getReturnType() == LLType::getVoidTy(irs->context()));
}
// If there are no cleanups to run, we try to keep the IR simple and

View file

@ -508,9 +508,9 @@ public:
// added
// to the module member list.
Declaration_codegen(fd, p);
assert(getIrFunc(fd)->func);
assert(DtoCallee(fd));
result = getIrFunc(fd)->func;
result = DtoCallee(fd);
}
}

View file

@ -703,7 +703,7 @@ public:
FuncDeclaration *fdecl = dve->var->isFuncDeclaration();
assert(fdecl);
DtoDeclareFunction(fdecl);
fnval = new DFuncValue(fdecl, getIrFunc(fdecl)->func, DtoRVal(dve->e1));
fnval = new DFuncValue(fdecl, DtoCallee(fdecl), DtoRVal(dve->e1));
} else {
fnval = toElem(e->e1);
}
@ -852,7 +852,7 @@ public:
FuncDeclaration *fd = fv->func;
assert(fd);
DtoResolveFunction(fd);
result = new DFuncValue(fd, getIrFunc(fd)->func);
result = new DFuncValue(fd, DtoCallee(fd));
return;
}
if (v->isIm()) {
@ -961,7 +961,7 @@ public:
if (nonFinal) {
funcval = DtoVirtualFunctionPointer(l, fdecl, e->toChars());
} else {
funcval = getIrFunc(fdecl)->func;
funcval = DtoCallee(fdecl);
}
assert(funcval);
@ -1478,7 +1478,7 @@ public:
if (e->allocator) {
// custom allocator
DtoResolveFunction(e->allocator);
DFuncValue dfn(e->allocator, getIrFunc(e->allocator)->func);
DFuncValue dfn(e->allocator, DtoCallee(e->allocator));
DValue *res = DtoCallFunction(e->loc, nullptr, &dfn, e->newargs);
mem = DtoBitCast(DtoRVal(res), DtoType(ntype->pointerTo()),
".newstruct_custom");
@ -1507,7 +1507,7 @@ public:
IF_LOG Logger::println("Calling constructor");
assert(e->arguments != NULL);
DtoResolveFunction(e->member);
DFuncValue dfn(e->member, getIrFunc(e->member)->func, mem);
DFuncValue dfn(e->member, DtoCallee(e->member), mem);
DtoCallFunction(e->loc, ts, &dfn, e->arguments);
}
}
@ -1694,7 +1694,7 @@ public:
->sym->inv) != nullptr) {
Logger::print("calling struct invariant");
DtoResolveFunction(invdecl);
DFuncValue invfunc(invdecl, getIrFunc(invdecl)->func, DtoRVal(cond));
DFuncValue invfunc(invdecl, DtoCallee(invdecl), DtoRVal(cond));
DtoCallFunction(e->loc, nullptr, &invfunc, nullptr);
}
}
@ -1917,7 +1917,7 @@ public:
}
}
castfptr = getIrFunc(e->func)->func;
castfptr = DtoCallee(e->func);
}
castfptr = DtoBitCast(castfptr, dgty->getContainedType(1));
@ -2166,7 +2166,7 @@ public:
DtoDeclareFunction(fd);
assert(!fd->isNested());
}
assert(getIrFunc(fd)->func);
assert(DtoCallee(fd));
}
//////////////////////////////////////////////////////////////////////////////
@ -2210,12 +2210,12 @@ public:
cval = DtoBitCast(cval, dgty->getContainedType(0));
LLValue *castfptr =
DtoBitCast(getIrFunc(fd)->func, dgty->getContainedType(1));
DtoBitCast(DtoCallee(fd), dgty->getContainedType(1));
result = new DImValue(e->type, DtoAggrPair(cval, castfptr, ".func"));
} else {
result = new DFuncValue(e->type, fd, getIrFunc(fd)->func);
result = new DFuncValue(e->type, fd, DtoCallee(fd));
}
}

View file

@ -256,11 +256,10 @@ void TryCatchScope::emitCatchBodiesMSVC(IRState &irs, llvm::Value *) {
// if no landing pad is created, the catch blocks are unused, but
// the verifier complains if there are catchpads without personality
// so we can just set it unconditionally
if (!irs.func()->func->hasPersonalityFn()) {
if (!irs.func()->hasLLVMPersonalityFn()) {
const char *personality = "__CxxFrameHandler3";
LLFunction *personalityFn =
getRuntimeFunction(Loc(), irs.module, personality);
irs.func()->func->setPersonalityFn(personalityFn);
irs.func()->setLLVMPersonalityFn(
getRuntimeFunction(Loc(), irs.module, personality));
}
}
@ -623,11 +622,9 @@ llvm::LandingPadInst *createLandingPadInst(IRState &irs) {
LLStructType::get(LLType::getInt8PtrTy(irs.context()),
LLType::getInt32Ty(irs.context()), nullptr);
#if LDC_LLVM_VER >= 307
LLFunction *currentFunction = irs.func()->func;
if (!currentFunction->hasPersonalityFn()) {
LLFunction *personalityFn =
getRuntimeFunction(Loc(), irs.module, "_d_eh_personality");
currentFunction->setPersonalityFn(personalityFn);
if (!irs.func()->hasLLVMPersonalityFn()) {
irs.func()->setLLVMPersonalityFn(
getRuntimeFunction(Loc(), irs.module, "_d_eh_personality"));
}
return irs.ir->CreateLandingPad(retType, 0);
#else
@ -753,12 +750,10 @@ llvm::BasicBlock *TryCatchFinallyScopes::getOrCreateResumeUnwindBlock() {
#if LDC_LLVM_VER >= 308
llvm::BasicBlock *
TryCatchFinallyScopes::emitLandingPadMSVC(CleanupCursor cleanupScope) {
LLFunction *currentFunction = irs.func()->func;
if (!currentFunction->hasPersonalityFn()) {
if (!irs.func()->hasLLVMPersonalityFn()) {
const char *personality = "__CxxFrameHandler3";
LLFunction *personalityFn =
getRuntimeFunction(Loc(), irs.module, personality);
currentFunction->setPersonalityFn(personalityFn);
irs.func()->setLLVMPersonalityFn(
getRuntimeFunction(Loc(), irs.module, personality));
}
if (cleanupScope == 0)

View file

@ -134,7 +134,7 @@ const char *getFirstElemString(StructLiteralExp *sle) {
// @allocSize(1)
// @allocSize(0,2)
void applyAttrAllocSize(StructLiteralExp *sle, IrFunction *irFunc) {
llvm::Function *func = irFunc->func;
llvm::Function *func = irFunc->getLLVMFunc();
checkStructElems(sle, {Type::tint32, Type::tint32});
auto sizeArgIdx = getIntElem(sle, 0);
@ -236,6 +236,7 @@ void applyAttrOptStrategy(StructLiteralExp *sle, IrFunction *irFunc) {
checkStructElems(sle, {Type::tstring});
llvm::StringRef value = getStringElem(sle, 0);
llvm::Function *func = irFunc->getLLVMFunc();
if (value == "none") {
if (irFunc->decl->inlining == PINLINEalways) {
sle->error("cannot combine '@ldc.attributes.%s(\"none\")' with "
@ -244,11 +245,11 @@ void applyAttrOptStrategy(StructLiteralExp *sle, IrFunction *irFunc) {
return;
}
irFunc->decl->inlining = PINLINEnever;
irFunc->func->addFnAttr(llvm::Attribute::OptimizeNone);
func->addFnAttr(llvm::Attribute::OptimizeNone);
} else if (value == "optsize") {
irFunc->func->addFnAttr(llvm::Attribute::OptimizeForSize);
func->addFnAttr(llvm::Attribute::OptimizeForSize);
} else if (value == "minsize") {
irFunc->func->addFnAttr(llvm::Attribute::MinSize);
func->addFnAttr(llvm::Attribute::MinSize);
} else {
sle->warning(
"ignoring unrecognized parameter '%s' for '@ldc.attributes.%s'",
@ -359,7 +360,7 @@ void applyFuncDeclUDAs(FuncDeclaration *decl, IrFunction *irFunc) {
if (!decl->userAttribDecl)
return;
llvm::Function *func = irFunc->func;
llvm::Function *func = irFunc->getLLVMFunc();
assert(func);
Expressions *attrs = decl->userAttribDecl->getAttributes();

View file

@ -200,7 +200,7 @@ LLConstant *IrAggr::getVtblInit() {
DtoResolveFunction(fd);
assert(isIrFuncCreated(fd) && "invalid vtbl function");
c = DtoBitCast(getIrFunc(fd)->func, voidPtrType);
c = DtoBitCast(DtoCallee(fd), voidPtrType);
if (cd->isFuncHidden(fd)) {
// fd is hidden from the view of this class. If fd overlaps with any
@ -328,7 +328,7 @@ llvm::GlobalVariable *IrAggr::getInterfaceVtbl(BaseClass *b, bool new_instance,
if (fd->interfaceVirtual)
thunkOffset -= fd->interfaceVirtual->offset;
if (thunkOffset == 0) {
constants.push_back(DtoBitCast(irFunc->func, voidPtrTy));
constants.push_back(DtoBitCast(irFunc->getLLVMCallee(), voidPtrTy));
continue;
}
@ -344,11 +344,12 @@ llvm::GlobalVariable *IrAggr::getInterfaceVtbl(BaseClass *b, bool new_instance,
if (!thunk) {
const LinkageWithCOMDAT lwc(LLGlobalValue::LinkOnceODRLinkage,
supportsCOMDAT());
const auto callee = irFunc->getLLVMCallee();
thunk = LLFunction::Create(
isaFunction(irFunc->func->getType()->getContainedType(0)), lwc.first,
isaFunction(callee->getType()->getContainedType(0)), lwc.first,
thunkName, &gIR->module);
setLinkage(lwc, thunk);
thunk->copyAttributesFrom(irFunc->func);
thunk->copyAttributesFrom(callee);
// Thunks themselves don't have an identity, only the target
// function has.
@ -375,7 +376,7 @@ llvm::GlobalVariable *IrAggr::getInterfaceVtbl(BaseClass *b, bool new_instance,
sizeof(FuncDeclaration)));
thunkFd->ir = new IrDsymbol();
auto thunkFunc = getIrFunc(thunkFd, true); // create the IrFunction
thunkFunc->func = thunk;
thunkFunc->setLLVMFunc(thunk);
thunkFunc->type = irFunc->type;
gIR->funcGenStates.emplace_back(new FuncGenState(*thunkFunc, *gIR));
@ -394,7 +395,7 @@ llvm::GlobalVariable *IrAggr::getInterfaceVtbl(BaseClass *b, bool new_instance,
// latter being just for IR readablilty).
std::vector<LLValue *> args;
llvm::Function::arg_iterator thunkArg = thunk->arg_begin();
llvm::Function::arg_iterator origArg = irFunc->func->arg_begin();
llvm::Function::arg_iterator origArg = callee->arg_begin();
for (; thunkArg != thunk->arg_end(); ++thunkArg, ++origArg) {
thunkArg->setName(origArg->getName());
args.push_back(&(*thunkArg));
@ -416,8 +417,8 @@ llvm::GlobalVariable *IrAggr::getInterfaceVtbl(BaseClass *b, bool new_instance,
gIR->DBuilder.EmitStopPoint(fd->loc);
// call the real vtbl function.
llvm::CallInst *call = gIR->ir->CreateCall(irFunc->func, args);
call->setCallingConv(irFunc->func->getCallingConv());
llvm::CallInst *call = gIR->ir->CreateCall(callee, args);
call->setCallingConv(irFunc->getCallingConv());
call->setTailCallKind(llvm::CallInst::TCK_Tail);
// return from the thunk

View file

@ -38,6 +38,47 @@ void IrFunction::setAlwaysInline() {
func->addFnAttr(llvm::Attribute::AlwaysInline);
}
void IrFunction::setLLVMFunc(llvm::Function *function) {
assert(function != nullptr);
func = function;
}
llvm::Function *IrFunction::getLLVMFunc() const {
return func;
}
llvm::CallingConv::ID IrFunction::getCallingConv() const {
assert(func != nullptr);
return func->getCallingConv();
}
llvm::FunctionType *IrFunction::getLLVMFuncType() const {
assert(func != nullptr);
return func->getFunctionType();
}
#if LDC_LLVM_VER >= 307
bool IrFunction::hasLLVMPersonalityFn() const {
assert(func != nullptr);
return func->hasPersonalityFn();
}
void IrFunction::setLLVMPersonalityFn(llvm::Constant *personality) {
assert(func != nullptr);
func->setPersonalityFn(personality);
}
#endif
llvm::StringRef IrFunction::getLLVMFuncName() const {
assert(func != nullptr);
return func->getName();
}
llvm::Function *IrFunction::getLLVMCallee() const {
assert(func != nullptr);
return func;
}
IrFunction *getIrFunc(FuncDeclaration *decl, bool create) {
if (!isIrFuncCreated(decl) && create) {
assert(decl->ir->irFunc == NULL);
@ -55,3 +96,13 @@ bool isIrFuncCreated(FuncDeclaration *decl) {
assert(t == IrDsymbol::FuncType || t == IrDsymbol::NotSet);
return t == IrDsymbol::FuncType;
}
llvm::Function *DtoFunction(FuncDeclaration *decl, bool create) {
assert(decl != nullptr);
return getIrFunc(decl, create)->getLLVMFunc();
}
llvm::Function *DtoCallee(FuncDeclaration *decl, bool create) {
assert(decl != nullptr);
return getIrFunc(decl, create)->getLLVMCallee();
}

View file

@ -34,7 +34,24 @@ struct IrFunction {
void setNeverInline();
void setAlwaysInline();
llvm::Function *func = nullptr;
void setLLVMFunc(llvm::Function *function);
/// Returns the associated LLVM function.
/// Use getLLVMCallee() for the LLVM function to be used for calls.
llvm::Function *getLLVMFunc() const;
llvm::CallingConv::ID getCallingConv() const;
llvm::FunctionType *getLLVMFuncType() const;
llvm::StringRef getLLVMFuncName() const;
#if LDC_LLVM_VER >= 307
bool hasLLVMPersonalityFn() const;
void setLLVMPersonalityFn(llvm::Constant *personality);
#endif
/// Returns the associated LLVM function to be used for calls (potentially
/// some sort of wrapper, e.g., a JIT wrapper).
llvm::Function *getLLVMCallee() const;
FuncDeclaration *decl = nullptr;
TypeFunction *type = nullptr;
@ -71,9 +88,20 @@ struct IrFunction {
/// Stores the FastMath options for this functions.
/// These are set e.g. by math related UDA's from ldc.attributes.
llvm::FastMathFlags FMF;
private:
llvm::Function *func = nullptr;
};
IrFunction *getIrFunc(FuncDeclaration *decl, bool create = false);
bool isIrFuncCreated(FuncDeclaration *decl);
/// Returns the associated LLVM function.
/// Use DtoCallee() for the LLVM function to be used for calls.
llvm::Function *DtoFunction(FuncDeclaration *decl, bool create = false);
/// Returns the associated LLVM function to be used for calls (potentially
/// some sort of wrapper, e.g., a JIT wrapper).
llvm::Function *DtoCallee(FuncDeclaration *decl, bool create = false);
#endif