Make -release only disable bounds checking in non-@safe code.

This commit is contained in:
David Nadlinger
2013-06-17 13:07:33 +02:00
parent 1215ffacd3
commit 235bb94878
9 changed files with 42 additions and 17 deletions

View File

@@ -193,13 +193,9 @@ struct Param
bool useInvariants; // generate class invariant checks
bool useIn; // generate precondition checks
bool useOut; // generate postcondition checks
#if IN_LLVM
bool useArrayBounds;
#else
char useArrayBounds; // 0: no array bounds checks
// 1: array bounds checks for safe functions only
// 2: array bounds checks for all functions
#endif
bool noboundscheck; // no array bounds checking at all
bool stackstomp; // add stack stomping code
bool useSwitchError; // check for switches without a default

View File

@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "driver/cl_options.h"
#include "mars.h"
#include "gen/cl_helpers.h"
#include "gen/logger.h"
#include "llvm/Support/CommandLine.h"
@@ -221,7 +222,7 @@ struct D_DebugStorage {
if (str.empty()) {
// Bare "-d-debug" has a special meaning.
global.params.useAssert = true;
global.params.useArrayBounds = true;
global.params.useArrayBounds = 2;
global.params.useInvariants = true;
global.params.useIn = true;
global.params.useOut = true;
@@ -320,11 +321,8 @@ static cl::opt<bool, true, FlagParser> asserts("asserts",
cl::location(global.params.useAssert),
cl::init(true));
static cl::opt<bool, true, FlagParser> boundsChecks("boundscheck",
cl::desc("(*) Enable array bounds checks"),
cl::value_desc("bool"),
cl::location(global.params.useArrayBounds),
cl::init(true));
cl::opt<BoolOrDefaultAdapter, false, FlagParser> boundsChecks("boundscheck",
cl::desc("(*) Enable array bounds checks"));
static cl::opt<bool, true, FlagParser> invariants("invariants",
cl::desc("(*) Enable invariants"),
@@ -348,8 +346,9 @@ static cl::opt<MultiSetter, true, FlagParser> contracts("contracts",
cl::desc("(*) Enable function pre- and post-conditions"),
cl::location(ContractsSetter));
bool nonSafeBoundsChecks = true;
static MultiSetter ReleaseSetter(true, &global.params.useAssert,
&global.params.useArrayBounds, &global.params.useInvariants,
&nonSafeBoundsChecks, &global.params.useInvariants,
&global.params.useOut, &global.params.useIn, NULL);
static cl::opt<MultiSetter, true, cl::parser<bool> > release("release",
cl::desc("Disables asserts, invariants, contracts and boundscheck"),

View File

@@ -15,7 +15,7 @@
#ifndef LDC_DRIVER_CL_OPTIONS_H
#define LDC_DRIVER_CL_OPTIONS_H
#include "mars.h"
#include "gen/cl_helpers.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/CommandLine.h"
#include <deque>
@@ -63,6 +63,9 @@ namespace opts {
extern cl::opt<bool, true> singleObj;
extern cl::opt<bool> linkonceTemplates;
extern cl::opt<BoolOrDefaultAdapter, false, FlagParser> boundsChecks;
extern bool nonSafeBoundsChecks;
// Arguments to -d-debug
extern std::vector<std::string> debugArgs;
// Arguments to -run

View File

@@ -175,6 +175,7 @@ int main(int argc, char** argv)
global.params.argv0 = argv[0];
#endif
global.params.useSwitchError = 1;
global.params.useArrayBounds = 2;
global.params.linkswitches = new Strings();
global.params.libfiles = new Strings();
@@ -369,6 +370,14 @@ int main(int argc, char** argv)
if (global.params.useUnitTests)
global.params.useAssert = 1;
// Bounds checking is a bit peculiar: -enable/disable-boundscheck is an
// absolute decision. Only if no explicit option is specified, -release
// downgrades useArrayBounds 2 to 1 (only for safe functions).
if (opts::boundsChecks == cl::BOU_UNSET)
global.params.useArrayBounds = opts::nonSafeBoundsChecks ? 2 : 1;
else
global.params.useArrayBounds = (opts::boundsChecks == cl::BOU_TRUE) ? 2 : 0;
// LDC output determination
// if we don't link, autodetect target from extension

View File

@@ -80,7 +80,7 @@ DValue* DtoAAIndex(Loc& loc, Type* type, DValue* aa, DValue* key, bool lvalue)
// Only check bounds for rvalues ('aa[key]').
// Lvalue use ('aa[key] = value') auto-adds an element.
if (!lvalue && global.params.useArrayBounds) {
if (!lvalue && gIR->emitArrayBoundsChecks()) {
llvm::BasicBlock* oldend = gIR->scopeend();
llvm::BasicBlock* failbb = llvm::BasicBlock::Create(gIR->context(), "aaboundscheckfail", gIR->topfunc(), oldend);
llvm::BasicBlock* okbb = llvm::BasicBlock::Create(gIR->context(), "aaboundsok", gIR->topfunc(), oldend);

View File

@@ -385,7 +385,7 @@ static LLValue* get_slice_ptr(DSliceValue* e, LLValue*& sz)
static void copySlice(LLValue* dstarr, LLValue* sz1, LLValue* srcarr, LLValue* sz2)
{
if (global.params.useAssert || global.params.useArrayBounds)
if (global.params.useAssert || gIR->emitArrayBoundsChecks())
{
LLValue* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_array_slice_copy");
gIR->CreateCallOrInvoke4(fn, dstarr, sz1, srcarr, sz2);

View File

@@ -165,6 +165,21 @@ LLCallSite IRState::CreateCallOrInvoke4(LLValue* Callee, LLValue* Arg1, LLValue*
return CreateCallOrInvoke(Callee, args, Name);
}
bool IRState::emitArrayBoundsChecks()
{
int p = global.params.useArrayBounds;
// 0 or 2 are absolute decisions.
if (p != 1) return p != 0;
// Safe functions only.
if (functions.empty()) return false;
Type* t = func()->decl->type;
return t->ty == Tfunction && ((TypeFunction*)t)->trust == TRUSTsafe;
}
//////////////////////////////////////////////////////////////////////////////////////////
IRBuilder<>* IRBuilderHelper::operator->()

View File

@@ -208,6 +208,9 @@ struct IRState
// 'used' array solely for keeping a reference to globals
std::vector<LLConstant*> usedArray;
/// Whether to emit array bounds checking in the current function.
bool emitArrayBoundsChecks();
};
template <typename T>

View File

@@ -1609,12 +1609,12 @@ DValue* IndexExp::toElem(IRState* p)
arrptr = DtoGEP1(l->getRVal(),r->getRVal());
}
else if (e1type->ty == Tsarray) {
if(global.params.useArrayBounds)
if (gIR->emitArrayBoundsChecks())
DtoArrayBoundsCheck(loc, l, r);
arrptr = DtoGEP(l->getRVal(), zero, r->getRVal());
}
else if (e1type->ty == Tarray) {
if(global.params.useArrayBounds)
if (gIR->emitArrayBoundsChecks())
DtoArrayBoundsCheck(loc, l, r);
arrptr = DtoArrayPtr(l);
arrptr = DtoGEP1(arrptr,r->getRVal());
@@ -1672,7 +1672,7 @@ DValue* SliceExp::toElem(IRState* p)
LLValue* vlo = lo->getRVal();
LLValue* vup = up->getRVal();
if(global.params.useArrayBounds)
if (gIR->emitArrayBoundsChecks())
DtoArrayBoundsCheck(loc, e, up, lo);
// offset by lower