-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.
This commit is contained in:
Martin 2017-10-13 19:49:24 +02:00
parent fbbbeecaca
commit 30b858781b
10 changed files with 106 additions and 32 deletions

View file

@ -12,6 +12,7 @@
#include "declaration.h" #include "declaration.h"
#include "module.h" #include "module.h"
#include "mtype.h" #include "mtype.h"
#include "gen/arrays.h"
#include "gen/dvalue.h" #include "gen/dvalue.h"
#include "gen/irstate.h" #include "gen/irstate.h"
#include "gen/llvm.h" #include "gen/llvm.h"
@ -91,14 +92,7 @@ DLValue *DtoAAIndex(Loc &loc, Type *type, DValue *aa, DValue *key,
gIR->scope() = IRScope(failbb); gIR->scope() = IRScope(failbb);
llvm::Function *errorfn = DtoBoundsCheckFailCall(gIR, loc);
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();
// if ok, proceed in okbb // if ok, proceed in okbb
gIR->scope() = IRScope(okbb); gIR->scope() = IRScope(okbb);

View file

@ -1377,12 +1377,17 @@ void DtoIndexBoundsCheck(Loc &loc, DValue *arr, DValue *index) {
} }
void DtoBoundsCheckFailCall(IRState *irs, Loc &loc) { void DtoBoundsCheckFailCall(IRState *irs, Loc &loc) {
llvm::Function *errorfn = Module *const module = irs->func()->decl->getModule();
getRuntimeFunction(loc, irs->module, "_d_arraybounds");
irs->CreateCallOrInvoke(
errorfn, DtoModuleFileName(irs->func()->decl->getModule(), loc),
DtoConstUint(loc.linnum));
// the function does not return if (global.params.betterC) {
irs->ir->CreateUnreachable(); 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();
}
} }

View file

@ -278,11 +278,37 @@ void DtoAssert(Module *M, Loc &loc, DValue *msg) {
gIR->ir->CreateUnreachable(); 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<LLValue *, 4> 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->funcGen().callOrInvoke(fn, args);
gIR->ir->CreateUnreachable();
}
/****************************************************************************** /******************************************************************************
* MODULE FILE NAME * MODULE FILE NAME
******************************************************************************/ ******************************************************************************/
LLValue *DtoModuleFileName(Module *M, const Loc &loc) { LLConstant *DtoModuleFileName(Module *M, const Loc &loc) {
return DtoConstString(loc.filename ? loc.filename return DtoConstString(loc.filename ? loc.filename
: M->srcfile->name->toChars()); : M->srcfile->name->toChars());
} }

View file

@ -61,9 +61,10 @@ LLValue *DtoAllocaDump(LLValue *val, LLType *asType, int alignment = 0,
// assertion generator // assertion generator
void DtoAssert(Module *M, Loc &loc, DValue *msg); void DtoAssert(Module *M, Loc &loc, DValue *msg);
void DtoCAssert(Module *M, Loc &loc, LLValue *msg);
// returns module file name // 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 /// emits goto to LabelStatement with the target identifier
void DtoGoto(Loc &loc, LabelDsymbol *target); void DtoGoto(Loc &loc, LabelDsymbol *target);

View file

@ -160,6 +160,21 @@ llvm::Function *getRuntimeFunction(const Loc &loc, llvm::Module &target,
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
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*); // extern (D) alias dg_t = int delegate(void*);
static Type *rt_dg1() { static Type *rt_dg1() {
static Type *dg_t = nullptr; static Type *dg_t = nullptr;
@ -330,6 +345,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<Type *>({voidPtrTy, voidPtrTy, uintTy, voidPtrTy})
: llvm::ArrayRef<Type *>({voidPtrTy, voidPtrTy, uintTy}),
{}, Attr_Cold_NoReturn);
// void _d_assert(string file, uint line) // void _d_assert(string file, uint line)
// void _d_arraybounds(string file, uint line) // void _d_arraybounds(string file, uint line)
createFwdDecl(LINKc, Type::tvoid, {"_d_assert", "_d_arraybounds"}, createFwdDecl(LINKc, Type::tvoid, {"_d_assert", "_d_arraybounds"},

View file

@ -30,6 +30,8 @@ void freeRuntime();
llvm::Function *getRuntimeFunction(const Loc &loc, llvm::Module &target, llvm::Function *getRuntimeFunction(const Loc &loc, llvm::Module &target,
const char *name); const char *name);
llvm::Function *getCAssertFunction(const Loc &loc, llvm::Module &target);
void emitInstrumentationFnEnter(FuncDeclaration *decl); void emitInstrumentationFnEnter(FuncDeclaration *decl);
void emitInstrumentationFnLeave(FuncDeclaration *decl); void emitInstrumentationFnLeave(FuncDeclaration *decl);

View file

@ -1648,11 +1648,17 @@ public:
auto &PGO = irs->funcGen().pgo; auto &PGO = irs->funcGen().pgo;
PGO.setCurrentStmt(stmt); PGO.setCurrentStmt(stmt);
Module *const module = irs->func()->decl->getModule();
if (global.params.betterC) {
DtoCAssert(module, stmt->loc, DtoConstCString("no switch default"));
return;
}
llvm::Function *fn = llvm::Function *fn =
getRuntimeFunction(stmt->loc, irs->module, "_d_switch_error"); getRuntimeFunction(stmt->loc, irs->module, "_d_switch_error");
LLValue *moduleInfoSymbol = LLValue *moduleInfoSymbol = getIrModule(module)->moduleInfoSymbol();
getIrModule(irs->func()->decl->getModule())->moduleInfoSymbol();
LLType *moduleInfoType = DtoType(Module::moduleinfo->type); LLType *moduleInfoType = DtoType(Module::moduleinfo->type);
LLCallSite call = irs->CreateCallOrInvoke( LLCallSite call = irs->CreateCallOrInvoke(

View file

@ -1684,8 +1684,16 @@ public:
* msg is not evaluated at all. So should use toElemDtor() * msg is not evaluated at all. So should use toElemDtor()
* instead of toElem(). * instead of toElem().
*/ */
DtoAssert(p->func()->decl->getModule(), e->loc, DValue *const msg = e->msg ? toElemDtor(e->msg) : nullptr;
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: // passed:
p->scope() = IRScope(passedbb); p->scope() = IRScope(passedbb);

View file

@ -413,12 +413,13 @@ LLConstant *DtoConstFP(Type *t, const real_t value) {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
LLConstant *DtoConstString(const char *str) { LLConstant *DtoConstCString(const char *str) {
llvm::StringRef s(str ? str : ""); llvm::StringRef s(str ? str : "");
llvm::GlobalVariable *gvar = (gIR->stringLiteral1ByteCache.find(s) ==
gIR->stringLiteral1ByteCache.end()) const auto it = gIR->stringLiteral1ByteCache.find(s);
? nullptr llvm::GlobalVariable *gvar =
: gIR->stringLiteral1ByteCache[s]; it == gIR->stringLiteral1ByteCache.end() ? nullptr : it->getValue();
if (gvar == nullptr) { if (gvar == nullptr) {
llvm::Constant *init = llvm::Constant *init =
llvm::ConstantDataArray::getString(gIR->context(), s, true); llvm::ConstantDataArray::getString(gIR->context(), s, true);
@ -432,12 +433,16 @@ LLConstant *DtoConstString(const char *str) {
#endif #endif
gIR->stringLiteral1ByteCache[s] = gvar; gIR->stringLiteral1ByteCache[s] = gvar;
} }
LLConstant *idxs[] = {DtoConstUint(0), DtoConstUint(0)}; LLConstant *idxs[] = {DtoConstUint(0), DtoConstUint(0)};
return DtoConstSlice(DtoConstSize_t(s.size()), return llvm::ConstantExpr::getGetElementPtr(gvar->getInitializer()->getType(),
llvm::ConstantExpr::getGetElementPtr( gvar, idxs, true);
gvar->getInitializer()->getType(), }
gvar, idxs, true),
Type::tchar->arrayOf()); LLConstant *DtoConstString(const char *str) {
LLConstant *cString = DtoConstCString(str);
LLConstant *length = DtoConstSize_t(str ? strlen(str) : 0);
return DtoConstSlice(length, cString, Type::tchar->arrayOf());
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View file

@ -97,6 +97,7 @@ LLConstantInt *DtoConstInt(int i);
LLConstantInt *DtoConstUbyte(unsigned char i); LLConstantInt *DtoConstUbyte(unsigned char i);
LLConstant *DtoConstFP(Type *t, real_t value); LLConstant *DtoConstFP(Type *t, real_t value);
LLConstant *DtoConstCString(const char *);
LLConstant *DtoConstString(const char *); LLConstant *DtoConstString(const char *);
LLConstant *DtoConstBool(bool); LLConstant *DtoConstBool(bool);