mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-23 08:13:13 +01:00
Make -release only disable bounds checking in non-@safe code.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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->()
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user