Adapt to frontend injecting implicit 'return 0' for betterC main

This fixes lit-test codegen/betterC_typeinfo.d.
This commit is contained in:
Martin 2018-02-25 01:25:02 +01:00
parent 97514dd52f
commit 1b8a3b9d7d
2 changed files with 41 additions and 47 deletions

View file

@ -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);

View file

@ -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 {