mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-03 08:30:47 +03:00
Adapt to frontend injecting implicit 'return 0' for betterC main
This fixes lit-test codegen/betterC_typeinfo.d.
This commit is contained in:
parent
97514dd52f
commit
1b8a3b9d7d
2 changed files with 41 additions and 47 deletions
|
@ -52,6 +52,10 @@
|
|||
#include "llvm/Target/TargetOptions.h"
|
||||
#include <iostream>
|
||||
|
||||
static bool isMainFunction(FuncDeclaration *fd) {
|
||||
return fd->isMain() || (global.params.betterC && fd->isCMain());
|
||||
}
|
||||
|
||||
llvm::FunctionType *DtoFunctionType(Type *type, IrFuncTy &irFty, Type *thistype,
|
||||
Type *nesttype, bool isMain, bool isCtor,
|
||||
bool isIntrinsic, bool hasSel) {
|
||||
|
@ -79,7 +83,8 @@ llvm::FunctionType *DtoFunctionType(Type *type, IrFuncTy &irFty, Type *thistype,
|
|||
unsigned nextLLArgIdx = 0;
|
||||
|
||||
if (isMain) {
|
||||
// _Dmain always returns i32, no matter what the type in the D main() is.
|
||||
// D and C main functions always return i32, even if declared as returning
|
||||
// void.
|
||||
newIrFty.ret = new IrFuncTyArg(Type::tint32, false);
|
||||
} else {
|
||||
Type *rt = f->next;
|
||||
|
@ -137,10 +142,10 @@ llvm::FunctionType *DtoFunctionType(Type *type, IrFuncTy &irFty, Type *thistype,
|
|||
++nextLLArgIdx;
|
||||
}
|
||||
|
||||
// if this _Dmain() doesn't have an argument, we force it to have one
|
||||
const size_t numExplicitDArgs = Parameter::dim(f->parameters);
|
||||
|
||||
if (isMain && numExplicitDArgs == 0) {
|
||||
// if this _Dmain() doesn't have an argument, we force it to have one
|
||||
if (isMain && f->linkage != LINKc && numExplicitDArgs == 0) {
|
||||
Type *mainargs = Type::tchar->arrayOf()->arrayOf();
|
||||
newIrFty.args.push_back(new IrFuncTyArg(mainargs, false));
|
||||
++nextLLArgIdx;
|
||||
|
@ -300,9 +305,10 @@ llvm::FunctionType *DtoFunctionType(FuncDeclaration *fdecl) {
|
|||
}
|
||||
}
|
||||
|
||||
LLFunctionType *functype = DtoFunctionType(
|
||||
fdecl->type, getIrFunc(fdecl, true)->irFty, dthis, dnest, fdecl->isMain(),
|
||||
fdecl->isCtorDeclaration(), DtoIsIntrinsic(fdecl), hasSel);
|
||||
LLFunctionType *functype =
|
||||
DtoFunctionType(fdecl->type, getIrFunc(fdecl, true)->irFty, dthis, dnest,
|
||||
isMainFunction(fdecl), fdecl->isCtorDeclaration(),
|
||||
DtoIsIntrinsic(fdecl), hasSel);
|
||||
|
||||
return functype;
|
||||
}
|
||||
|
@ -589,7 +595,7 @@ void DtoDeclareFunction(FuncDeclaration *fdecl) {
|
|||
}
|
||||
|
||||
// main
|
||||
if (fdecl->isMain()) {
|
||||
if (isMainFunction(fdecl)) {
|
||||
// Detect multiple main functions, which is disallowed. DMD checks this
|
||||
// in the glue code, so we need to do it here as well.
|
||||
if (gIR->mainFunc) {
|
||||
|
@ -1175,7 +1181,7 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
|
|||
gIR->DBuilder.EmitStopPoint(fd->endloc);
|
||||
if (func->getReturnType() == LLType::getVoidTy(gIR->context())) {
|
||||
gIR->ir->CreateRetVoid();
|
||||
} else if (!fd->isMain()) {
|
||||
} else if (!gIR->isMainFunc(irFunc)) {
|
||||
CompoundAsmStatement *asmb = fd->fbody->endsWithAsm();
|
||||
if (asmb) {
|
||||
assert(asmb->abiret);
|
||||
|
|
|
@ -98,9 +98,13 @@ public:
|
|||
emitInstrumentationFnLeave(fd);
|
||||
|
||||
// is there a return value expression?
|
||||
if (stmt->exp || (!stmt->exp && irs->isMainFunc(f))) {
|
||||
const bool isMainFunc = irs->isMainFunc(f);
|
||||
if (stmt->exp || isMainFunc) {
|
||||
if (!stmt->exp) {
|
||||
// implicitly return 0 for the main function
|
||||
returnValue = LLConstant::getNullValue(funcType->getReturnType());
|
||||
} else if (funcType->getReturnType()->isVoidTy()) {
|
||||
// if the function's return type is void, it uses sret
|
||||
if (funcType->getReturnType() == LLType::getVoidTy(irs->context())) {
|
||||
assert(!f->type->isref);
|
||||
|
||||
LLValue *sretPointer = getIrFunc(fd)->sretArg;
|
||||
|
@ -142,10 +146,6 @@ public:
|
|||
}
|
||||
} else {
|
||||
// the return type is not void, so this is a normal "register" return
|
||||
if (!stmt->exp && irs->isMainFunc(f)) {
|
||||
returnValue =
|
||||
LLConstant::getNullValue(irs->mainFunc->getReturnType());
|
||||
} else {
|
||||
if (stmt->exp->op == TOKnull) {
|
||||
stmt->exp->type = f->type->next;
|
||||
}
|
||||
|
@ -162,7 +162,6 @@ public:
|
|||
}
|
||||
// do abi specific transformations on the return value
|
||||
returnValue = getIrFunc(fd)->irFty.putRet(dval);
|
||||
}
|
||||
|
||||
// Hack around LDC assuming structs and static arrays are in memory:
|
||||
// If the function returns a struct or a static array, and the return
|
||||
|
@ -175,23 +174,12 @@ public:
|
|||
returnValue = DtoLoad(returnValue);
|
||||
}
|
||||
|
||||
// can happen for classes and void main
|
||||
// can happen for classes
|
||||
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 (irs->isMainFunc(f)) {
|
||||
returnValue =
|
||||
LLConstant::getNullValue(irs->mainFunc->getReturnType());
|
||||
} else {
|
||||
returnValue =
|
||||
irs->ir->CreateBitCast(returnValue, funcType->getReturnType());
|
||||
}
|
||||
|
||||
IF_LOG Logger::cout() << "return value after cast: " << *returnValue
|
||||
<< '\n';
|
||||
IF_LOG Logger::cout()
|
||||
<< "return value after cast: " << *returnValue << '\n';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue