mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-08 11:56:12 +03:00
Only non-typesafe variadics need to take LLVM varargs (#2127)
* gen/functions: Re-clang-format, minor style cleanup [nfc] * Only non-typesafe variadics need to take LLVM varargs GitHub: Fixes #2121.
This commit is contained in:
parent
ebfdc25323
commit
c9112f3daf
3 changed files with 34 additions and 37 deletions
|
@ -123,21 +123,15 @@ llvm::FunctionType *DtoFunctionType(Type *type, IrFuncTy &irFty, Type *thistype,
|
||||||
++nextLLArgIdx;
|
++nextLLArgIdx;
|
||||||
}
|
}
|
||||||
|
|
||||||
// vararg functions are special too
|
// Non-typesafe variadics (both C and D styles) are also variadics on the LLVM
|
||||||
if (f->varargs) {
|
// level.
|
||||||
if (f->linkage == LINKd) {
|
const bool isLLVMVariadic = (f->varargs == 1);
|
||||||
// d style with hidden args
|
if (isLLVMVariadic && f->linkage == LINKd) {
|
||||||
// 2 (array) is handled by the frontend
|
// Add extra `_arguments` parameter for D-style variadic functions.
|
||||||
if (f->varargs == 1) {
|
|
||||||
// _arguments
|
|
||||||
newIrFty.arg_arguments =
|
newIrFty.arg_arguments =
|
||||||
new IrFuncTyArg(Type::dtypeinfo->type->arrayOf(), false);
|
new IrFuncTyArg(Type::dtypeinfo->type->arrayOf(), false);
|
||||||
++nextLLArgIdx;
|
++nextLLArgIdx;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
newIrFty.c_vararg = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if this _Dmain() doesn't have an argument, we force it to have one
|
// if this _Dmain() doesn't have an argument, we force it to have one
|
||||||
const size_t numExplicitDArgs = Parameter::dim(f->parameters);
|
const size_t numExplicitDArgs = Parameter::dim(f->parameters);
|
||||||
|
@ -226,7 +220,7 @@ llvm::FunctionType *DtoFunctionType(Type *type, IrFuncTy &irFty, Type *thistype,
|
||||||
}
|
}
|
||||||
|
|
||||||
irFty.funcType =
|
irFty.funcType =
|
||||||
LLFunctionType::get(irFty.ret->ltype, argtypes, irFty.c_vararg);
|
LLFunctionType::get(irFty.ret->ltype, argtypes, isLLVMVariadic);
|
||||||
|
|
||||||
IF_LOG Logger::cout() << "Final function type: " << *irFty.funcType << "\n";
|
IF_LOG Logger::cout() << "Final function type: " << *irFty.funcType << "\n";
|
||||||
|
|
||||||
|
@ -518,15 +512,13 @@ void DtoDeclareFunction(FuncDeclaration *fdecl) {
|
||||||
vafunc = DtoDeclareVaFunction(fdecl);
|
vafunc = DtoDeclareVaFunction(fdecl);
|
||||||
}
|
}
|
||||||
|
|
||||||
// calling convention
|
// Calling convention.
|
||||||
LINK link = f->linkage;
|
//
|
||||||
if (vafunc || DtoIsIntrinsic(fdecl)
|
|
||||||
// DMD treats _Dmain as having C calling convention and this has been
|
// DMD treats _Dmain as having C calling convention and this has been
|
||||||
// hardcoded into druntime, even if the frontend type has D linkage.
|
// hardcoded into druntime, even if the frontend type has D linkage (Bugzilla
|
||||||
// See Bugzilla issue 9028.
|
// issue 9028).
|
||||||
|| fdecl->isMain()) {
|
const bool forceC = vafunc || DtoIsIntrinsic(fdecl) || fdecl->isMain();
|
||||||
link = LINKc;
|
const auto link = forceC ? LINKc : f->linkage;
|
||||||
}
|
|
||||||
|
|
||||||
// mangled name
|
// mangled name
|
||||||
std::string mangledName = getMangledName(fdecl, link);
|
std::string mangledName = getMangledName(fdecl, link);
|
||||||
|
@ -540,7 +532,8 @@ void DtoDeclareFunction(FuncDeclaration *fdecl) {
|
||||||
func = LLFunction::Create(functype, llvm::GlobalValue::ExternalLinkage,
|
func = LLFunction::Create(functype, llvm::GlobalValue::ExternalLinkage,
|
||||||
mangledName, &gIR->module);
|
mangledName, &gIR->module);
|
||||||
} else if (func->getFunctionType() != functype) {
|
} else if (func->getFunctionType() != functype) {
|
||||||
error(fdecl->loc, "Function type does not match previously declared "
|
error(fdecl->loc,
|
||||||
|
"Function type does not match previously declared "
|
||||||
"function with the same mangled name: %s",
|
"function with the same mangled name: %s",
|
||||||
mangleExact(fdecl));
|
mangleExact(fdecl));
|
||||||
fatal();
|
fatal();
|
||||||
|
@ -793,8 +786,7 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
|
||||||
llvm::Function *func = getIrFunc(fd)->getLLVMFunc();
|
llvm::Function *func = getIrFunc(fd)->getLLVMFunc();
|
||||||
assert(nullptr != func);
|
assert(nullptr != func);
|
||||||
if (!linkageAvailableExternally &&
|
if (!linkageAvailableExternally &&
|
||||||
(func->getLinkage() ==
|
(func->getLinkage() == llvm::GlobalValue::AvailableExternallyLinkage)) {
|
||||||
llvm::GlobalValue::AvailableExternallyLinkage)) {
|
|
||||||
// Fix linkage
|
// Fix linkage
|
||||||
const auto lwc = lowerFuncLinkage(fd);
|
const auto lwc = lowerFuncLinkage(fd);
|
||||||
setLinkage(lwc, func);
|
setLinkage(lwc, func);
|
||||||
|
@ -817,7 +809,8 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
|
||||||
// This function failed semantic3() with errors but the errors were gagged.
|
// This function failed semantic3() with errors but the errors were gagged.
|
||||||
// In contrast to DMD we immediately bail out here, since other parts of
|
// In contrast to DMD we immediately bail out here, since other parts of
|
||||||
// the codegen expect irFunc to be set for defined functions.
|
// the codegen expect irFunc to be set for defined functions.
|
||||||
error(fd->loc, "Internal Compiler Error: function not fully analyzed; "
|
error(fd->loc,
|
||||||
|
"Internal Compiler Error: function not fully analyzed; "
|
||||||
"previous unreported errors compiling %s?",
|
"previous unreported errors compiling %s?",
|
||||||
fd->toPrettyChars());
|
fd->toPrettyChars());
|
||||||
fatal();
|
fatal();
|
||||||
|
@ -878,7 +871,8 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
|
||||||
assert(fd->ident != Id::empty);
|
assert(fd->ident != Id::empty);
|
||||||
|
|
||||||
if (fd->semanticRun != PASSsemantic3done) {
|
if (fd->semanticRun != PASSsemantic3done) {
|
||||||
error(fd->loc, "Internal Compiler Error: function not fully analyzed; "
|
error(fd->loc,
|
||||||
|
"Internal Compiler Error: function not fully analyzed; "
|
||||||
"previous unreported errors compiling %s?",
|
"previous unreported errors compiling %s?",
|
||||||
fd->toPrettyChars());
|
fd->toPrettyChars());
|
||||||
fatal();
|
fatal();
|
||||||
|
@ -1063,8 +1057,7 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
|
||||||
gIR->scopebb());
|
gIR->scopebb());
|
||||||
|
|
||||||
// copy _arguments to a memory location
|
// copy _arguments to a memory location
|
||||||
irFunc->_arguments =
|
irFunc->_arguments = DtoAllocaDump(irFunc->_arguments, 0, "_arguments_mem");
|
||||||
DtoAllocaDump(irFunc->_arguments, 0, "_arguments_mem");
|
|
||||||
|
|
||||||
// Push cleanup block that calls va_end to match the va_start call.
|
// Push cleanup block that calls va_end to match the va_start call.
|
||||||
{
|
{
|
||||||
|
|
|
@ -101,9 +101,6 @@ struct IrFuncTy {
|
||||||
using ArgList = std::vector<IrFuncTyArg *>;
|
using ArgList = std::vector<IrFuncTyArg *>;
|
||||||
ArgList args;
|
ArgList args;
|
||||||
|
|
||||||
// C varargs
|
|
||||||
bool c_vararg = false;
|
|
||||||
|
|
||||||
// range of normal parameters to reverse
|
// range of normal parameters to reverse
|
||||||
bool reverseParams = false;
|
bool reverseParams = false;
|
||||||
|
|
||||||
|
|
7
tests/codegen/varargs.d
Normal file
7
tests/codegen/varargs.d
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
// RUN: %ldc -output-ll -of=%t.ll %s && FileCheck %s < %t.ll
|
||||||
|
|
||||||
|
// Make sure typesafe variadics are not lowered to LLVM variadics.
|
||||||
|
void typesafe(size_t[2] a...) {}
|
||||||
|
// CHECK: define{{.*}}typesafe
|
||||||
|
// CHECK-NOT: ...
|
||||||
|
// CHECK-SAME: {
|
Loading…
Add table
Add a link
Reference in a new issue