Don't forward-declare magic intrinsics mapping to instructions

It's ugly in general, and apparently causes LTO issues on Windows.

This required a larger refactoring.
This commit is contained in:
Martin Kinkelin 2024-03-16 16:02:51 +01:00
parent be00cbb189
commit 078f0532ca
6 changed files with 39 additions and 92 deletions

View file

@ -293,37 +293,7 @@ llvm::FunctionType *DtoFunctionType(Type *type, IrFuncTy &irFty, Type *thistype,
////////////////////////////////////////////////////////////////////////////////
static llvm::FunctionType *DtoVaFunctionType(FuncDeclaration *fdecl) {
IrFuncTy &irFty = getIrFunc(fdecl, true)->irFty;
if (irFty.funcType) {
return irFty.funcType;
}
irFty.ret = new IrFuncTyArg(Type::tvoid, false);
irFty.args.push_back(new IrFuncTyArg(pointerTo(Type::tvoid), false));
if (fdecl->llvmInternal == LLVMva_start) {
irFty.funcType = GET_INTRINSIC_DECL(vastart)->getFunctionType();
} else if (fdecl->llvmInternal == LLVMva_copy) {
irFty.funcType = GET_INTRINSIC_DECL(vacopy)->getFunctionType();
irFty.args.push_back(new IrFuncTyArg(pointerTo(Type::tvoid), false));
} else if (fdecl->llvmInternal == LLVMva_end) {
irFty.funcType = GET_INTRINSIC_DECL(vaend)->getFunctionType();
}
assert(irFty.funcType);
return irFty.funcType;
}
////////////////////////////////////////////////////////////////////////////////
llvm::FunctionType *DtoFunctionType(FuncDeclaration *fdecl) {
// handle for C vararg intrinsics
if (DtoIsVaIntrinsic(fdecl)) {
return DtoVaFunctionType(fdecl);
}
Type *dthis = nullptr, *dnest = nullptr;
if (fdecl->ident == Id::ensure || fdecl->ident == Id::require) {
@ -366,25 +336,6 @@ llvm::FunctionType *DtoFunctionType(FuncDeclaration *fdecl) {
////////////////////////////////////////////////////////////////////////////////
static llvm::Function *DtoDeclareVaFunction(FuncDeclaration *fdecl) {
DtoVaFunctionType(fdecl);
llvm::Function *func = nullptr;
if (fdecl->llvmInternal == LLVMva_start) {
func = GET_INTRINSIC_DECL(vastart);
} else if (fdecl->llvmInternal == LLVMva_copy) {
func = GET_INTRINSIC_DECL(vacopy);
} else if (fdecl->llvmInternal == LLVMva_end) {
func = GET_INTRINSIC_DECL(vaend);
}
assert(func);
getIrFunc(fdecl)->setLLVMFunc(func);
return func;
}
////////////////////////////////////////////////////////////////////////////////
void DtoResolveFunction(FuncDeclaration *fdecl, const bool willDeclare) {
if ((!global.params.useUnitTests || !fdecl->type) &&
fdecl->isUnitTestDeclaration()) {
@ -412,21 +363,7 @@ void DtoResolveFunction(FuncDeclaration *fdecl, const bool willDeclare) {
if (TemplateInstance *tinst = fdecl->parent->isTemplateInstance()) {
if (TemplateDeclaration *tempdecl =
tinst->tempdecl->isTemplateDeclaration()) {
if (tempdecl->llvmInternal == LLVMva_arg) {
Logger::println("magic va_arg found");
fdecl->llvmInternal = LLVMva_arg;
fdecl->ir->setDefined();
return; // this gets mapped to an instruction so a declaration makes
// no sense
}
if (tempdecl->llvmInternal == LLVMva_start) {
Logger::println("magic va_start found");
fdecl->llvmInternal = LLVMva_start;
} else if (tempdecl->llvmInternal == LLVMintrinsic) {
Logger::println("overloaded intrinsic found");
assert(fdecl->llvmInternal == LLVMintrinsic);
assert(fdecl->mangleOverride.length);
} else if (tempdecl->llvmInternal == LLVMinline_asm) {
if (tempdecl->llvmInternal == LLVMinline_asm) {
Logger::println("magic inline asm found");
TypeFunction *tf = static_cast<TypeFunction *>(fdecl->type);
if (tf->parameterList.varargs != VARARGvariadic ||
@ -436,13 +373,13 @@ void DtoResolveFunction(FuncDeclaration *fdecl, const bool willDeclare) {
"variadic with no explicit parameters");
fatal();
}
fdecl->llvmInternal = LLVMinline_asm;
assert(fdecl->llvmInternal == LLVMinline_asm);
fdecl->ir->setDefined();
return; // this gets mapped to a special inline asm call, no point in
// going on.
} else if (tempdecl->llvmInternal == LLVMinline_ir) {
Logger::println("magic inline ir found");
fdecl->llvmInternal = LLVMinline_ir;
assert(fdecl->llvmInternal == LLVMinline_ir);
fdecl->_linkage = LINK::c;
Type *type = fdecl->type;
assert(type->ty == TY::Tfunction);
@ -457,6 +394,13 @@ void DtoResolveFunction(FuncDeclaration *fdecl, const bool willDeclare) {
}
}
// magic intrinsics are mapped to instructions, no point in fwd-declaring some
// non-existing function
if (DtoIsMagicIntrinsic(fdecl)) {
fdecl->ir->setDefined();
return;
}
DtoFunctionType(fdecl);
IF_LOG Logger::println("DtoResolveFunction(%s): %s", fdecl->toPrettyChars(),
@ -610,24 +554,19 @@ void DtoDeclareFunction(FuncDeclaration *fdecl, const bool willDefine) {
// create IrFunction
IrFunction *irFunc = getIrFunc(fdecl, true);
LLFunction *vafunc = nullptr;
if (DtoIsVaIntrinsic(fdecl)) {
vafunc = DtoDeclareVaFunction(fdecl);
}
// Calling convention.
//
// DMD treats _Dmain as having C calling convention and this has been
// hardcoded into druntime, even if the frontend type has D linkage (Bugzilla
// issue 9028).
const bool forceC = vafunc || DtoIsIntrinsic(fdecl) || fdecl->isMain();
const bool forceC = DtoIsIntrinsic(fdecl) || fdecl->isMain();
// mangled name
const auto irMangle = getIRMangledName(fdecl, forceC ? LINK::c : f->linkage);
// construct function
LLFunctionType *functype = DtoFunctionType(fdecl);
LLFunction *func = vafunc ? vafunc : gIR->module.getFunction(irMangle);
LLFunction *func = gIR->module.getFunction(irMangle);
if (!func) {
// All function declarations are "external" - any other linkage type
// is set when actually defining the function, except extern_weak.