From d1814b8ac557609a9b54395f6708a513ebaf5a3a Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Wed, 9 Nov 2016 19:01:08 +0100 Subject: [PATCH 1/9] Implement the betterC switch like DMD does. Namely, don't emit the ModuleInfo. --- dmd2/globals.h | 2 +- driver/cl_options.cpp | 5 +++++ driver/ldmd.cpp | 1 + gen/module.cpp | 4 ++-- tests/linking/betterc.d | 15 +++++++++++++++ 5 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 tests/linking/betterc.d diff --git a/dmd2/globals.h b/dmd2/globals.h index 2ff4b19812e..eeaa22648f2 100644 --- a/dmd2/globals.h +++ b/dmd2/globals.h @@ -128,6 +128,7 @@ struct Param bool addMain; // LDC_FIXME: Implement. bool allInst; // LDC_FIXME: Implement. unsigned nestedTmpl; // maximum nested template instantiations + bool betterC; // be a "better C" compiler; no dependency on D runtime #else bool pic; // generate position-independent-code for shared libs bool color; // use ANSI colors in console output @@ -136,7 +137,6 @@ struct Param bool nofloat; // code should not pull in floating point support bool ignoreUnsupportedPragmas; // rather than error on them bool enforcePropertySyntax; - bool betterC; // be a "better C" compiler; no dependency on D runtime bool addMain; // add a default main() function bool allInst; // generate code for all template instantiations #endif diff --git a/driver/cl_options.cpp b/driver/cl_options.cpp index 173c3a09dac..ec47e4a26ad 100644 --- a/driver/cl_options.cpp +++ b/driver/cl_options.cpp @@ -408,6 +408,11 @@ cl::opt cl::desc("implement http://wiki.dlang.org/DIP25 (experimental)"), cl::location(global.params.useDIP25)); +cl::opt betterC( + "betterC", + cl::desc("omit generating some runtime information and helper functions"), + cl::location(global.params.betterC)); + cl::opt coverageAnalysis( "cov", cl::desc("Compile-in code coverage analysis\n(use -cov=n for n% " "minimum required coverage)"), diff --git a/driver/ldmd.cpp b/driver/ldmd.cpp index 2988a3ed517..5ccaa765d4d 100644 --- a/driver/ldmd.cpp +++ b/driver/ldmd.cpp @@ -159,6 +159,7 @@ Usage:\n\ files.d D source files\n\ @cmdfile read arguments from cmdfile\n\ -allinst generate code for all template instantiations\n\ + -betterC omit generating some runtime information and helper functions\n\ -c do not link\n\ -color[=on|off] force colored console output on or off\n\ -conf=path use config file at path\n\ diff --git a/gen/module.cpp b/gen/module.cpp index cc04cf807c7..57b02cbdab1 100644 --- a/gen/module.cpp +++ b/gen/module.cpp @@ -743,8 +743,8 @@ void codegenModule(IRState *irs, Module *m, bool emitFullModuleInfo) { } // Skip emission of all the additional module metadata if requested by the - // user. - if (!m->noModuleInfo) { + // user or the betterC switch is on. + if (!global.params.betterC && !m->noModuleInfo) { // generate ModuleInfo genModuleInfo(m, emitFullModuleInfo); diff --git a/tests/linking/betterc.d b/tests/linking/betterc.d new file mode 100644 index 00000000000..a7047188777 --- /dev/null +++ b/tests/linking/betterc.d @@ -0,0 +1,15 @@ +// RUN: %ldc -betterC -c -output-ll -of=%t.ll %s && FileCheck %s < %t.ll +// RUN: %ldc -betterC -defaultlib= -run %s + +// CHECK-NOT: ModuleInfoZ +// CHECK-NOT: ModuleRefZ +// CHECK-NOT: call void @ldc.register_dso +version (CRuntime_Microsoft) { + extern(C) int mainCRTStartup() { + return 0; + } +} + +extern (C) int main() { + return 0; +} From 3675624c815d0a88f864c47568289e8209b9799d Mon Sep 17 00:00:00 2001 From: Martin Date: Fri, 13 Oct 2017 19:27:13 +0200 Subject: [PATCH 2/9] Ignore -defaultlib/-debuglib for -betterC Analogous to DMD. --- driver/main.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/driver/main.cpp b/driver/main.cpp index 6b27493ca48..839eeb6418d 100644 --- a/driver/main.cpp +++ b/driver/main.cpp @@ -459,12 +459,10 @@ static void parseCommandLine(int argc, char **argv, Strings &sourceFiles, } if (noDefaultLib) { - deprecation( - Loc(), - "-nodefaultlib is deprecated, as " - "-defaultlib/-debuglib now override the existing list instead of " - "appending to it. Please use the latter instead."); - } else { + deprecation(Loc(), "-nodefaultlib is deprecated, as -defaultlib/-debuglib " + "now override the existing list instead of appending to " + "it. Please use the latter instead."); + } else if (!global.params.betterC) { // Parse comma-separated default library list. std::stringstream libNames(linkDebugLib ? debugLib : defaultLib); while (libNames.good()) { From f523082472aeafcbe4453b2aa3ccc6fd3e4e6ca6 Mon Sep 17 00:00:00 2001 From: Martin Date: Fri, 13 Oct 2017 19:49:24 +0200 Subject: [PATCH 3/9] -betterC: Use C assert function Instead of druntime's _d_assert[_msg], _d_arraybounds and _d_switch_error. Tested by dmd-testsuite's runnable/cassert and compilable/betterCarray. --- gen/aa.cpp | 10 ++-------- gen/arrays.cpp | 21 +++++++++++++-------- gen/llvmhelpers.cpp | 28 +++++++++++++++++++++++++++- gen/llvmhelpers.h | 3 ++- gen/runtime.cpp | 24 ++++++++++++++++++++++++ gen/runtime.h | 1 + gen/statements.cpp | 10 ++++++++-- gen/toir.cpp | 12 ++++++++++-- gen/tollvm.cpp | 24 +++++++++++++++--------- gen/tollvm.h | 1 + 10 files changed, 103 insertions(+), 31 deletions(-) diff --git a/gen/aa.cpp b/gen/aa.cpp index 587cde57dc3..76c497dfbcc 100644 --- a/gen/aa.cpp +++ b/gen/aa.cpp @@ -12,6 +12,7 @@ #include "declaration.h" #include "module.h" #include "mtype.h" +#include "gen/arrays.h" #include "gen/dvalue.h" #include "gen/irstate.h" #include "gen/llvm.h" @@ -91,14 +92,7 @@ DValue *DtoAAIndex(Loc &loc, Type *type, DValue *aa, DValue *key, bool lvalue) { gIR->scope() = IRScope(failbb); - llvm::Function *errorfn = - getRuntimeFunction(loc, gIR->module, "_d_arraybounds"); - gIR->CreateCallOrInvoke( - errorfn, DtoModuleFileName(gIR->func()->decl->getModule(), loc), - DtoConstUint(loc.linnum)); - - // the function does not return - gIR->ir->CreateUnreachable(); + DtoBoundsCheckFailCall(gIR, loc); // if ok, proceed in okbb gIR->scope() = IRScope(okbb); diff --git a/gen/arrays.cpp b/gen/arrays.cpp index e96d0e34a78..463bd54528f 100644 --- a/gen/arrays.cpp +++ b/gen/arrays.cpp @@ -1216,12 +1216,17 @@ void DtoIndexBoundsCheck(Loc &loc, DValue *arr, DValue *index) { } void DtoBoundsCheckFailCall(IRState *irs, Loc &loc) { - llvm::Function *errorfn = - getRuntimeFunction(loc, irs->module, "_d_arraybounds"); - irs->CreateCallOrInvoke( - errorfn, DtoModuleFileName(irs->func()->decl->getModule(), loc), - DtoConstUint(loc.linnum)); - - // the function does not return - irs->ir->CreateUnreachable(); + Module *const module = irs->func()->decl->getModule(); + + if (global.params.betterC) { + DtoCAssert(module, loc, DtoConstCString("array overflow")); + } else { + llvm::Function *errorfn = + getRuntimeFunction(loc, irs->module, "_d_arraybounds"); + irs->CreateCallOrInvoke(errorfn, DtoModuleFileName(module, loc), + DtoConstUint(loc.linnum)); + + // the function does not return + irs->ir->CreateUnreachable(); + } } diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 19417a40d3c..75392f4365c 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -265,11 +265,37 @@ void DtoAssert(Module *M, Loc &loc, DValue *msg) { gIR->ir->CreateUnreachable(); } +void DtoCAssert(Module *M, Loc &loc, LLValue *msg) { + const auto file = DtoConstCString(loc.filename ? loc.filename + : M->srcfile->name->toChars()); + const auto line = DtoConstUint(loc.linnum); + const auto fn = getCAssertFunction(loc, gIR->module); + + llvm::SmallVector args; + if (global.params.targetTriple.isOSDarwin()) { + const auto irFunc = gIR->func(); + const auto funcName = + irFunc && irFunc->decl ? irFunc->decl->toPrettyChars() : ""; + args.push_back(DtoConstCString(funcName)); + args.push_back(file); + args.push_back(line); + args.push_back(msg); + } else { + args.push_back(msg); + args.push_back(file); + args.push_back(line); + } + + gIR->func()->scopes->callOrInvoke(fn, args); + + gIR->ir->CreateUnreachable(); +} + /****************************************************************************** * MODULE FILE NAME ******************************************************************************/ -LLValue *DtoModuleFileName(Module *M, const Loc &loc) { +LLConstant *DtoModuleFileName(Module *M, const Loc &loc) { return DtoConstString(loc.filename ? loc.filename : M->srcfile->name->toChars()); } diff --git a/gen/llvmhelpers.h b/gen/llvmhelpers.h index b9934966a9c..37667d62380 100644 --- a/gen/llvmhelpers.h +++ b/gen/llvmhelpers.h @@ -56,9 +56,10 @@ LLValue *DtoAllocaDump(LLValue *val, LLType *asType, int alignment = 0, // assertion generator void DtoAssert(Module *M, Loc &loc, DValue *msg); +void DtoCAssert(Module *M, Loc &loc, LLValue *msg); // returns module file name -LLValue *DtoModuleFileName(Module *M, const Loc &loc); +LLConstant *DtoModuleFileName(Module *M, const Loc &loc); /// emits goto to LabelStatement with the target identifier void DtoGoto(Loc &loc, LabelDsymbol *target); diff --git a/gen/runtime.cpp b/gen/runtime.cpp index e112a2f1846..c6ac5030d30 100644 --- a/gen/runtime.cpp +++ b/gen/runtime.cpp @@ -178,6 +178,19 @@ llvm::GlobalVariable *getRuntimeGlobal(Loc &loc, llvm::Module &target, g->getLinkage(), nullptr, g->getName()); } +static const char *getCAssertFunctionName() { + if (global.params.targetTriple.isOSDarwin()) { + return "__assert_rtn"; + } else if (global.params.targetTriple.isWindowsMSVCEnvironment()) { + return "_assert"; + } + return "__assert"; +} + +llvm::Function *getCAssertFunction(const Loc &loc, llvm::Module &target) { + return getRuntimeFunction(loc, target, getCAssertFunctionName()); +} + //////////////////////////////////////////////////////////////////////////////// // extern (D) alias dg_t = int delegate(void*); @@ -347,6 +360,17 @@ static void buildRuntimeModule() { ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// + // C assert function: + // OSX: void __assert_rtn(const char *func, const char *file, unsigned line, + // const char *msg) + // else: void [_]_assert(const char *msg, const char *file, unsigned line) + createFwdDecl( + LINKc, Type::tvoid, {getCAssertFunctionName()}, + global.params.targetTriple->isOSDarwin() + ? llvm::ArrayRef({voidPtrTy, voidPtrTy, uintTy, voidPtrTy}) + : llvm::ArrayRef({voidPtrTy, voidPtrTy, uintTy}), + {}, Attr_Cold_NoReturn); + // void _d_assert(string file, uint line) // void _d_arraybounds(string file, uint line) createFwdDecl(LINKc, Type::tvoid, {"_d_assert", "_d_arraybounds"}, diff --git a/gen/runtime.h b/gen/runtime.h index 3c6118391a5..6e5cab2261f 100644 --- a/gen/runtime.h +++ b/gen/runtime.h @@ -31,5 +31,6 @@ llvm::Function *getRuntimeFunction(const Loc &loc, llvm::Module &target, llvm::GlobalVariable * getRuntimeGlobal(const Loc &loc, llvm::Module &target, const char *name); +llvm::Function *getCAssertFunction(const Loc &loc, llvm::Module &target); #endif // LDC_GEN_RUNTIME_H diff --git a/gen/statements.cpp b/gen/statements.cpp index df075a24d08..ff31daa9789 100644 --- a/gen/statements.cpp +++ b/gen/statements.cpp @@ -1506,11 +1506,17 @@ class ToIRVisitor : public Visitor { stmt->loc.toChars()); LOG_SCOPE; + Module *const module = irs->func()->decl->getModule(); + + if (global.params.betterC) { + DtoCAssert(module, stmt->loc, DtoConstCString("no switch default")); + return; + } + llvm::Function *fn = getRuntimeFunction(stmt->loc, irs->module, "_d_switch_error"); - LLValue *moduleInfoSymbol = - getIrModule(irs->func()->decl->getModule())->moduleInfoSymbol(); + LLValue *moduleInfoSymbol = getIrModule(module)->moduleInfoSymbol(); LLType *moduleInfoType = DtoType(Module::moduleinfo->type); LLCallSite call = irs->CreateCallOrInvoke( diff --git a/gen/toir.cpp b/gen/toir.cpp index 9093040bb94..4faacfb3f16 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -1889,8 +1889,16 @@ class ToElemVisitor : public Visitor { * msg is not evaluated at all. So should use toElemDtor() * instead of toElem(). */ - DtoAssert(p->func()->decl->getModule(), e->loc, - e->msg ? toElemDtor(e->msg) : nullptr); + DValue *const msg = e->msg ? toElemDtor(e->msg) : nullptr; + Module *const module = p->func()->decl->getModule(); + if (global.params.betterC) { + const auto cMsg = + msg ? DtoArrayPtr(msg) // assuming `msg` is null-terminated, like DMD + : DtoConstCString(e->e1->toChars()); + DtoCAssert(module, e->e1->loc, cMsg); + } else { + DtoAssert(module, e->loc, msg); + } // passed: p->scope() = IRScope(passedbb); diff --git a/gen/tollvm.cpp b/gen/tollvm.cpp index 7794a124bd9..74a3d6f7652 100644 --- a/gen/tollvm.cpp +++ b/gen/tollvm.cpp @@ -463,12 +463,13 @@ LLConstant *DtoConstFP(Type *t, longdouble value) { //////////////////////////////////////////////////////////////////////////////// -LLConstant *DtoConstString(const char *str) { +LLConstant *DtoConstCString(const char *str) { llvm::StringRef s(str ? str : ""); - llvm::GlobalVariable *gvar = (gIR->stringLiteral1ByteCache.find(s) == - gIR->stringLiteral1ByteCache.end()) - ? nullptr - : gIR->stringLiteral1ByteCache[s]; + + const auto it = gIR->stringLiteral1ByteCache.find(s); + llvm::GlobalVariable *gvar = + it == gIR->stringLiteral1ByteCache.end() ? nullptr : it->getValue(); + if (gvar == nullptr) { llvm::Constant *init = llvm::ConstantDataArray::getString(gIR->context(), s, true); @@ -482,14 +483,19 @@ LLConstant *DtoConstString(const char *str) { #endif gIR->stringLiteral1ByteCache[s] = gvar; } + LLConstant *idxs[] = {DtoConstUint(0), DtoConstUint(0)}; - return DtoConstSlice(DtoConstSize_t(s.size()), - llvm::ConstantExpr::getGetElementPtr( + return llvm::ConstantExpr::getGetElementPtr( #if LDC_LLVM_VER >= 307 gvar->getInitializer()->getType(), #endif - gvar, idxs, true), - Type::tchar->arrayOf()); + gvar, idxs, true); +} + +LLConstant *DtoConstString(const char *str) { + LLConstant *cString = DtoConstCString(str); + LLConstant *length = DtoConstSize_t(str ? strlen(str) : 0); + return DtoConstSlice(length, cString, Type::tchar->arrayOf()); } //////////////////////////////////////////////////////////////////////////////// diff --git a/gen/tollvm.h b/gen/tollvm.h index 169b227131e..27edf66827d 100644 --- a/gen/tollvm.h +++ b/gen/tollvm.h @@ -93,6 +93,7 @@ LLConstantInt *DtoConstInt(int i); LLConstantInt *DtoConstUbyte(unsigned char i); LLConstant *DtoConstFP(Type *t, longdouble value); +LLConstant *DtoConstCString(const char *); LLConstant *DtoConstString(const char *); LLConstant *DtoConstBool(bool); From bbbad1e5acaa41d5ea291358be81b2cc30d86b85 Mon Sep 17 00:00:00 2001 From: Martin Date: Sat, 14 Oct 2017 17:10:52 +0200 Subject: [PATCH 4/9] Skip TypeInfo definitions for -betterC --- gen/typinf.cpp | 4 ++-- tests/codegen/betterC_typeinfo.d | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 tests/codegen/betterC_typeinfo.d diff --git a/gen/typinf.cpp b/gen/typinf.cpp index b8bd5b4f789..b03d1624003 100644 --- a/gen/typinf.cpp +++ b/gen/typinf.cpp @@ -737,8 +737,8 @@ void TypeInfoDeclaration_codegen(TypeInfoDeclaration *decl, IRState *p) { emitTypeMetadata(decl); - // this is a declaration of a builtin __initZ var - if (builtinTypeInfo(decl->tinfo)) { + // check if the definition can be elided + if (global.params.betterC || builtinTypeInfo(decl->tinfo)) { return; } diff --git a/tests/codegen/betterC_typeinfo.d b/tests/codegen/betterC_typeinfo.d new file mode 100644 index 00000000000..fce8a1188d0 --- /dev/null +++ b/tests/codegen/betterC_typeinfo.d @@ -0,0 +1,22 @@ +// Make sure the file can be compiled and linked successfully with -betterC. +// Also test that druntime and Phobos aren't in the linker command line. +// RUN: %ldc -betterC %s -v > %t.log +// RUN: FileCheck %s --check-prefix=WITHOUT_TI < %t.log +// WITHOUT_TI-NOT: druntime-ldc +// WITHOUT_TI-NOT: phobos2-ldc + +// With version=WITH_TI, make sure the file can be compiled with -betterC... +// RUN: %ldc -betterC -d-version=WITH_TI -c -of=%t%obj %s +// ... but not linked due to the undefined TypeInfo. +// RUN: not %ldc -betterC %t%obj > %t.fail 2>&1 +// RUN: FileCheck %s --check-prefix=WITH_TI < %t.fail +// WITH_TI: _D37TypeInfo_S16betterC_typeinfo8MyStruct6__initZ + +struct MyStruct { int a; } + +extern (C) void main() +{ + auto s = MyStruct(); + version (WITH_TI) + auto ti = typeid(MyStruct); +} From 0b5cc95eef93c6d2bb7f7840c5d4f6d236778b9c Mon Sep 17 00:00:00 2001 From: Johan Engelen Date: Thu, 26 Oct 2017 21:46:42 +0200 Subject: [PATCH 5/9] Add "D_betterC" version. (#2385) Cherry-pick from upstream DMD, https://github.com/dlang/dmd/pull/7132 --- driver/main.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/driver/main.cpp b/driver/main.cpp index 839eeb6418d..a6ad0474d76 100644 --- a/driver/main.cpp +++ b/driver/main.cpp @@ -858,6 +858,10 @@ static void registerPredefinedVersions() { VersionCondition::addPredefinedGlobalIdent("D_NoBoundsChecks"); } + if (global.params.betterC) { + VersionCondition::addPredefinedGlobalIdent("D_BetterC"); + } + registerPredefinedTargetVersions(); // Pass sanitizer arguments to linker. Requires clang. From 612c8a7fb9a751048d5251b23517ba48c631a6fb Mon Sep 17 00:00:00 2001 From: Martin Date: Sun, 19 Nov 2017 17:15:28 +0100 Subject: [PATCH 6/9] Android: Use proper C assert function signature --- gen/llvmhelpers.cpp | 5 +++++ gen/runtime.cpp | 34 ++++++++++++++++++++++++---------- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 75392f4365c..fdac03a1178 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -280,6 +280,11 @@ void DtoCAssert(Module *M, Loc &loc, LLValue *msg) { args.push_back(file); args.push_back(line); args.push_back(msg); + } else if (global.params.targetTriple.getEnvironment() == + llvm::Triple::Android) { + args.push_back(file); + args.push_back(line); + args.push_back(msg); } else { args.push_back(msg); args.push_back(file); diff --git a/gen/runtime.cpp b/gen/runtime.cpp index c6ac5030d30..a745f34eb39 100644 --- a/gen/runtime.cpp +++ b/gen/runtime.cpp @@ -178,6 +178,13 @@ llvm::GlobalVariable *getRuntimeGlobal(Loc &loc, llvm::Module &target, g->getLinkage(), nullptr, g->getName()); } +// C assert function: +// OSX: void __assert_rtn(const char *func, const char *file, unsigned line, +// const char *msg) +// Android: void __assert(const char *file, int line, const char *msg) +// MSVC: void _assert(const char *msg, const char *file, unsigned line) +// else: void __assert(const char *msg, const char *file, unsigned line) + static const char *getCAssertFunctionName() { if (global.params.targetTriple.isOSDarwin()) { return "__assert_rtn"; @@ -187,6 +194,19 @@ static const char *getCAssertFunctionName() { return "__assert"; } +static std::vector getCAssertFunctionParamTypes() { + const auto voidPtr = Type::tvoidptr; + const auto uint = Type::tuns32; + + if (global.params.targetTriple.isOSDarwin()) { + return {voidPtr, voidPtr, uint, voidPtr}; + } + if (global.params.targetTriple.getEnvironment() == llvm::Triple::Android) { + return {voidPtr, uint, voidPtr}; + } + return {voidPtr, voidPtr, uint}; +} + llvm::Function *getCAssertFunction(const Loc &loc, llvm::Module &target) { return getRuntimeFunction(loc, target, getCAssertFunctionName()); } @@ -360,16 +380,10 @@ static void buildRuntimeModule() { ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// - // C assert function: - // OSX: void __assert_rtn(const char *func, const char *file, unsigned line, - // const char *msg) - // else: void [_]_assert(const char *msg, const char *file, unsigned line) - createFwdDecl( - LINKc, Type::tvoid, {getCAssertFunctionName()}, - global.params.targetTriple->isOSDarwin() - ? llvm::ArrayRef({voidPtrTy, voidPtrTy, uintTy, voidPtrTy}) - : llvm::ArrayRef({voidPtrTy, voidPtrTy, uintTy}), - {}, Attr_Cold_NoReturn); + // C assert function + createFwdDecl(LINKc, Type::tvoid, {getCAssertFunctionName()}, + getCAssertFunctionParamTypes(), {}, + Attr_Cold_NoReturn); // void _d_assert(string file, uint line) // void _d_arraybounds(string file, uint line) From 08041422d60cd3a077e0e684b180e737e1992391 Mon Sep 17 00:00:00 2001 From: Oleg Nykytenko Date: Fri, 9 Feb 2018 18:07:07 +0200 Subject: [PATCH 7/9] Solaris: fix assert for betterC build. (#2566) * Solaris: fix assert for betterC build. * Added parens to avoid relying on operator precedence rules. --- gen/llvmhelpers.cpp | 8 ++++++++ gen/runtime.cpp | 6 +++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index fdac03a1178..e9d42927e71 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -280,6 +280,14 @@ void DtoCAssert(Module *M, Loc &loc, LLValue *msg) { args.push_back(file); args.push_back(line); args.push_back(msg); + } else if (global.params.targetTriple.isOSSolaris()) { + const auto irFunc = gIR->func(); + const auto funcName = + (irFunc && irFunc->decl) ? irFunc->decl->toPrettyChars() : ""; + args.push_back(msg); + args.push_back(file); + args.push_back(line); + args.push_back(DtoConstCString(funcName)); } else if (global.params.targetTriple.getEnvironment() == llvm::Triple::Android) { args.push_back(file); diff --git a/gen/runtime.cpp b/gen/runtime.cpp index a745f34eb39..5d9b1385788 100644 --- a/gen/runtime.cpp +++ b/gen/runtime.cpp @@ -183,6 +183,8 @@ llvm::GlobalVariable *getRuntimeGlobal(Loc &loc, llvm::Module &target, // const char *msg) // Android: void __assert(const char *file, int line, const char *msg) // MSVC: void _assert(const char *msg, const char *file, unsigned line) +// Solaris: void __assert_c99(const char *assertion, const char *filename, int line_num, +// const char *funcname); // else: void __assert(const char *msg, const char *file, unsigned line) static const char *getCAssertFunctionName() { @@ -190,6 +192,8 @@ static const char *getCAssertFunctionName() { return "__assert_rtn"; } else if (global.params.targetTriple.isWindowsMSVCEnvironment()) { return "_assert"; + } else if (global.params.targetTriple.isOSSolaris()) { + return "__assert_c99"; } return "__assert"; } @@ -198,7 +202,7 @@ static std::vector getCAssertFunctionParamTypes() { const auto voidPtr = Type::tvoidptr; const auto uint = Type::tuns32; - if (global.params.targetTriple.isOSDarwin()) { + if (global.params.targetTriple.isOSDarwin() || global.params.targetTriple.isOSSolaris()) { return {voidPtr, voidPtr, uint, voidPtr}; } if (global.params.targetTriple.getEnvironment() == llvm::Triple::Android) { From eac89a34eab37bc1c57b469a6af9b78798560625 Mon Sep 17 00:00:00 2001 From: Martin Date: Sat, 24 Feb 2018 14:20:22 +0100 Subject: [PATCH 8/9] Adapt lit-test tests/codegen/betterC_typeinfo.d The frontend now errors out when coming across a typeid expression in betterC mode. That error is checked in dmd-testsuite's fail_compilation/betterc.d. --- tests/codegen/betterC_typeinfo.d | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/tests/codegen/betterC_typeinfo.d b/tests/codegen/betterC_typeinfo.d index fce8a1188d0..12f2814fc5d 100644 --- a/tests/codegen/betterC_typeinfo.d +++ b/tests/codegen/betterC_typeinfo.d @@ -1,22 +1,13 @@ // Make sure the file can be compiled and linked successfully with -betterC. // Also test that druntime and Phobos aren't in the linker command line. // RUN: %ldc -betterC %s -v > %t.log -// RUN: FileCheck %s --check-prefix=WITHOUT_TI < %t.log -// WITHOUT_TI-NOT: druntime-ldc -// WITHOUT_TI-NOT: phobos2-ldc - -// With version=WITH_TI, make sure the file can be compiled with -betterC... -// RUN: %ldc -betterC -d-version=WITH_TI -c -of=%t%obj %s -// ... but not linked due to the undefined TypeInfo. -// RUN: not %ldc -betterC %t%obj > %t.fail 2>&1 -// RUN: FileCheck %s --check-prefix=WITH_TI < %t.fail -// WITH_TI: _D37TypeInfo_S16betterC_typeinfo8MyStruct6__initZ +// RUN: FileCheck %s < %t.log +// CHECK-NOT: druntime-ldc +// CHECK-NOT: phobos2-ldc struct MyStruct { int a; } extern (C) void main() { auto s = MyStruct(); - version (WITH_TI) - auto ti = typeid(MyStruct); } From a99737073addf194ad6cd36396e7f03f6307d9bc Mon Sep 17 00:00:00 2001 From: Martin Date: Sat, 31 Mar 2018 01:22:00 +0200 Subject: [PATCH 9/9] Error out when trying to concatenate arrays in -betterC mode This fixes the error message for fail_compilation/test18312.d, which used to be: Error: `TypeInfo` cannot be used with -betterC --- gen/toir.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/gen/toir.cpp b/gen/toir.cpp index 4faacfb3f16..92a48314007 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -2347,6 +2347,17 @@ class ToElemVisitor : public Visitor { e->type->toChars()); LOG_SCOPE; + if (global.params.betterC) { + error( + e->loc, + "array concatenation of expression `%s` requires the GC which is not " + "available with -betterC", + e->toChars()); + result = + new DSliceValue(e->type, llvm::UndefValue::get(DtoType(e->type)), llvm::UndefValue::get(DtoType(e->type))); + return; + } + result = DtoCatArrays(e->loc, e->type, e->e1, e->e2); }