Merge branch 'master' into merge-2.068

Conflicts:
	runtime/druntime
This commit is contained in:
Martin 2015-09-26 14:21:43 +02:00
commit d45170464e
22 changed files with 269 additions and 267 deletions

View file

@ -99,7 +99,7 @@ build_script:
- cd ninja-ldc - cd ninja-ldc
- cmake -G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=c:\projects\ldc-x64 -DLLVM_ROOT_DIR=c:/projects/llvm-x64 -DLIBCONFIG_INCLUDE_DIR=c:/projects/libconfig/lib -DLIBCONFIG_LIBRARY=c:/projects/libconfig/lib/x64/ReleaseStatic/libconfig.lib ..\ldc - cmake -G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=c:\projects\ldc-x64 -DLLVM_ROOT_DIR=c:/projects/llvm-x64 -DLIBCONFIG_INCLUDE_DIR=c:/projects/libconfig/lib -DLIBCONFIG_LIBRARY=c:/projects/libconfig/lib/x64/ReleaseStatic/libconfig.lib ..\ldc
# Work around LDC issue #930 # Work around LDC issue #930
- ps: (gc build.ninja).replace('runtime/std/string-unittest-debug.obj -w -d -g -unittest', 'runtime/std/string-unittest-debug.obj -w -d -unittest') | sc build.ninja - ps: (gc build.ninja).replace('runtime/std/string-unittest-debug.obj -w -d -g -link-debuglib -unittest', 'runtime/std/string-unittest-debug.obj -w -d -link-debuglib -unittest') | sc build.ninja
# Build LDC, druntime and phobos # Build LDC, druntime and phobos
- ninja -j2 - ninja -j2

View file

@ -90,15 +90,18 @@ static cl::list<std::string, StringsAdapter> importPaths("I",
cl::Prefix); cl::Prefix);
static cl::opt<std::string> defaultLib("defaultlib", static cl::opt<std::string> defaultLib("defaultlib",
cl::desc("Default libraries for non-debug-info build (overrides previous)"), cl::desc("Default libraries to link with (overrides previous)"),
cl::value_desc("lib1,lib2,..."), cl::value_desc("lib1,lib2,..."),
cl::ZeroOrMore); cl::ZeroOrMore);
static cl::opt<std::string> debugLib("debuglib", static cl::opt<std::string> debugLib("debuglib",
cl::desc("Default libraries for debug info build (overrides previous)"), cl::desc("Debug versions of default libraries (overrides previous)"),
cl::value_desc("lib1,lib2,..."), cl::value_desc("lib1,lib2,..."),
cl::ZeroOrMore); cl::ZeroOrMore);
static cl::opt<bool> linkDebugLib("link-debuglib",
cl::desc("Link with libraries specified in -debuglib, not -defaultlib"),
cl::ZeroOrMore);
#if LDC_LLVM_VER < 304 #if LDC_LLVM_VER < 304
namespace llvm { namespace llvm {
@ -420,8 +423,7 @@ static void parseCommandLine(int argc, char **argv, Strings &sourceFiles, bool &
else else
{ {
// Parse comma-separated default library list. // Parse comma-separated default library list.
std::stringstream libNames( std::stringstream libNames(linkDebugLib ? debugLib : defaultLib);
global.params.symdebug ? debugLib : defaultLib);
while (libNames.good()) while (libNames.good())
{ {
std::string lib; std::string lib;

View file

@ -110,14 +110,13 @@ struct AArch64TargetABI : TargetABI
} }
void vaCopy(LLValue* pDest, LLValue* src) { void vaCopy(LLValue* pDest, LLValue* src) {
// Analog to va_start, we need to allocate a __va_list struct on the stack first // Analog to va_start, we need to allocate a new __va_list struct on the stack,
// and set the passed 'dest' char* pointer to its address. // fill it with a bitcopy of the source struct...
LLValue* valistmem = DtoRawAlloca(getValistType(), 0, "__va_list_mem"); src = DtoLoad(DtoBitCast(src, getValistType()->getPointerTo())); // *(__va_list*)src
DtoStore(DtoBitCast(valistmem, getVoidPtrType()), pDest); LLValue* valistmem = DtoAllocaDump(src, 0, "__va_list_mem");
// ... and finally set the passed 'dest' char* pointer to the new struct's address.
// Now bitcopy the source struct over the destination struct. DtoStore(DtoBitCast(valistmem, getVoidPtrType()),
src = DtoBitCast(src, valistmem->getType()); DtoBitCast(pDest, getPtrToType(getVoidPtrType())));
DtoStore(DtoLoad(src), valistmem); // *(__va_list*)dest = *(__va_list*)src
} }
LLValue* prepareVaArg(LLValue* pAp) LLValue* prepareVaArg(LLValue* pAp)

View file

@ -82,24 +82,23 @@ struct LLTypeMemoryLayout
/// Removes padding fields for (non-union-containing!) structs /// Removes padding fields for (non-union-containing!) structs
struct RemoveStructPadding : ABIRewrite { struct RemoveStructPadding : ABIRewrite {
/// get a rewritten value back to its original form /// get a rewritten value back to its original form
LLValue* get(Type* dty, DValue* v) { LLValue* get(Type* dty, LLValue* v) {
LLValue* lval = DtoAlloca(dty, ".rewritetmp"); LLValue* lval = DtoAlloca(dty, ".rewritetmp");
getL(dty, v, lval); getL(dty, v, lval);
return lval; return lval;
} }
/// get a rewritten value back to its original form and store result in provided lvalue /// get a rewritten value back to its original form and store result in provided lvalue
/// this one is optional and defaults to calling the one above void getL(Type* dty, LLValue* v, LLValue* lval) {
void getL(Type* dty, DValue* v, LLValue* lval) {
// Make sure the padding is zero, so struct comparisons work. // Make sure the padding is zero, so struct comparisons work.
// TODO: Only do this if there's padding, and/or only initialize padding. // TODO: Only do this if there's padding, and/or only initialize padding.
DtoMemSetZero(lval, DtoConstSize_t(getTypePaddedSize(DtoType(dty)))); DtoMemSetZero(lval, DtoConstSize_t(getTypePaddedSize(DtoType(dty))));
DtoPaddedStruct(dty->toBasetype(), v->getRVal(), lval); DtoPaddedStruct(dty->toBasetype(), v, lval);
} }
/// put out rewritten value /// put out rewritten value
LLValue* put(Type* dty, DValue* v) { LLValue* put(DValue* v) {
return DtoUnpaddedStruct(dty->toBasetype(), v->getRVal()); return DtoUnpaddedStruct(v->getType()->toBasetype(), v->getRVal());
} }
/// return the transformed type for this rewrite /// return the transformed type for this rewrite
@ -154,26 +153,22 @@ struct IntegerRewrite : ABIRewrite
return LLTypeMemoryLayout::typesAreEquivalent(llType, integerType); return LLTypeMemoryLayout::typesAreEquivalent(llType, integerType);
} }
LLValue* get(Type* dty, DValue* dv) LLValue* get(Type* dty, LLValue* v)
{ {
LLValue* integer = dv->getRVal(); LLValue* integerDump = DtoAllocaDump(v, dty, ".IntegerRewrite_dump");
LLValue* integerDump = storeToMemory(integer, 0, ".IntegerRewrite_dump");
LLType* type = DtoType(dty); LLType* type = DtoType(dty);
return loadFromMemory(integerDump, type, ".IntegerRewrite_getResult"); return loadFromMemory(integerDump, type, ".IntegerRewrite_getResult");
} }
void getL(Type* dty, DValue* dv, LLValue* lval) void getL(Type* dty, LLValue* v, LLValue* lval)
{ {
LLValue* integer = dv->getRVal(); storeToMemory(v, lval);
storeToMemory(integer, lval);
} }
LLValue* put(Type* dty, DValue* dv) LLValue* put(DValue* dv)
{ {
assert(dty == dv->getType());
LLValue* address = getAddressOf(dv); LLValue* address = getAddressOf(dv);
LLType* integerType = getIntegerType(dty->size()); LLType* integerType = getIntegerType(dv->getType()->size());
return loadFromMemory(address, integerType, ".IntegerRewrite_putResult"); return loadFromMemory(address, integerType, ".IntegerRewrite_putResult");
} }
@ -205,21 +200,19 @@ struct ExplicitByvalRewrite : ABIRewrite
ExplicitByvalRewrite(size_t alignment = 16) : alignment(alignment) ExplicitByvalRewrite(size_t alignment = 16) : alignment(alignment)
{ } { }
LLValue* get(Type* dty, DValue* v) LLValue* get(Type* dty, LLValue* v)
{ {
LLValue* pointer = v->getRVal(); return DtoLoad(v, ".ExplicitByvalRewrite_getResult");
return DtoLoad(pointer, ".ExplicitByvalRewrite_getResult");
} }
void getL(Type* dty, DValue* v, LLValue* lval) void getL(Type* dty, LLValue* v, LLValue* lval)
{ {
LLValue* pointer = v->getRVal(); DtoAggrCopy(lval, v);
DtoAggrCopy(lval, pointer);
} }
LLValue* put(Type* dty, DValue* v) LLValue* put(DValue* v)
{ {
if (DtoIsPassedByRef(dty)) if (DtoIsPassedByRef(v->getType()))
{ {
LLValue* originalPointer = v->getRVal(); LLValue* originalPointer = v->getRVal();
LLType* type = originalPointer->getType()->getPointerElementType(); LLType* type = originalPointer->getType()->getPointerElementType();
@ -228,9 +221,7 @@ struct ExplicitByvalRewrite : ABIRewrite
return copyForCallee; return copyForCallee;
} }
LLValue* originalValue = v->getRVal(); return DtoAllocaDump(v->getRVal(), alignment, ".ExplicitByvalRewrite_putResult");
LLValue* copyForCallee = storeToMemory(originalValue, alignment, ".ExplicitByvalRewrite_putResult");
return copyForCallee;
} }
LLType* type(Type* dty, LLType* t) LLType* type(Type* dty, LLType* t)

View file

@ -160,22 +160,21 @@ namespace {
* memory so that it's then readable as the other type (i.e., bit-casting). * memory so that it's then readable as the other type (i.e., bit-casting).
*/ */
struct X86_64_C_struct_rewrite : ABIRewrite { struct X86_64_C_struct_rewrite : ABIRewrite {
LLValue* get(Type* dty, DValue* v) LLValue* get(Type* dty, LLValue* v)
{ {
LLValue* address = storeToMemory(v->getRVal(), 0, ".X86_64_C_struct_rewrite_dump"); LLValue* address = DtoAllocaDump(v, dty, ".X86_64_C_struct_rewrite_dump");
LLType* type = DtoType(dty); LLType* type = DtoType(dty);
return loadFromMemory(address, type, ".X86_64_C_struct_rewrite_getResult"); return loadFromMemory(address, type, ".X86_64_C_struct_rewrite_getResult");
} }
void getL(Type* dty, DValue* v, LLValue* lval) { void getL(Type* dty, LLValue* v, LLValue* lval) {
storeToMemory(v->getRVal(), lval); storeToMemory(v, lval);
} }
LLValue* put(Type* dty, DValue* v) { LLValue* put(DValue* v) {
assert(dty == v->getType());
LLValue* address = getAddressOf(v); LLValue* address = getAddressOf(v);
LLType* abiTy = getAbiType(dty); LLType* abiTy = getAbiType(v->getType());
assert(abiTy && "Why are we rewriting a non-rewritten type?"); assert(abiTy && "Why are we rewriting a non-rewritten type?");
return loadFromMemory(address, abiTy, ".X86_64_C_struct_rewrite_putResult"); return loadFromMemory(address, abiTy, ".X86_64_C_struct_rewrite_putResult");
@ -195,18 +194,15 @@ struct X86_64_C_struct_rewrite : ABIRewrite {
* the ByVal LLVM attribute. * the ByVal LLVM attribute.
*/ */
struct ImplicitByvalRewrite : ABIRewrite { struct ImplicitByvalRewrite : ABIRewrite {
LLValue* get(Type* dty, DValue* v) { LLValue* get(Type* dty, LLValue* v) {
LLValue* pointer = v->getRVal(); return DtoLoad(v, ".ImplicitByvalRewrite_getResult");
return DtoLoad(pointer, ".ImplicitByvalRewrite_getResult");
} }
void getL(Type* dty, DValue* v, LLValue* lval) { void getL(Type* dty, LLValue* v, LLValue* lval) {
LLValue* pointer = v->getRVal(); DtoAggrCopy(lval, v);
DtoAggrCopy(lval, pointer);
} }
LLValue* put(Type* dty, DValue* v) { LLValue* put(DValue* v) {
assert(dty == v->getType());
return getAddressOf(v); return getAddressOf(v);
} }
@ -388,15 +384,13 @@ LLValue* X86_64TargetABI::prepareVaStart(LLValue* pAp) {
} }
void X86_64TargetABI::vaCopy(LLValue* pDest, LLValue* src) { void X86_64TargetABI::vaCopy(LLValue* pDest, LLValue* src) {
// Analog to va_start, we need to allocate a __va_list struct on the stack first // Analog to va_start, we need to allocate a new __va_list struct on the stack,
// and set the passed 'dest' char* pointer to its address. // fill it with a bitcopy of the source struct...
LLValue* valistmem = DtoRawAlloca(getValistType(), 0, "__va_list_mem"); src = DtoLoad(DtoBitCast(src, getValistType()->getPointerTo())); // *(__va_list*)src
LLValue* valistmem = DtoAllocaDump(src, 0, "__va_list_mem");
// ... and finally set the passed 'dest' char* pointer to the new struct's address.
DtoStore(DtoBitCast(valistmem, getVoidPtrType()), DtoStore(DtoBitCast(valistmem, getVoidPtrType()),
DtoBitCast(pDest, getPtrToType(getVoidPtrType()))); DtoBitCast(pDest, getPtrToType(getVoidPtrType())));
// Now bitcopy the source struct over the destination struct.
src = DtoBitCast(src, valistmem->getType());
DtoStore(DtoLoad(src), valistmem); // *(__va_list*)dest = *(__va_list*)src
} }
LLValue* X86_64TargetABI::prepareVaArg(LLValue* pAp) LLValue* X86_64TargetABI::prepareVaArg(LLValue* pAp)

View file

@ -28,7 +28,7 @@
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
void ABIRewrite::getL(Type* dty, DValue* v, LLValue* lval) void ABIRewrite::getL(Type* dty, LLValue* v, LLValue* lval)
{ {
LLValue* rval = get(dty, v); LLValue* rval = get(dty, v);
assert(rval->getType() == lval->getType()->getContainedType(0)); assert(rval->getType() == lval->getType()->getContainedType(0));
@ -49,29 +49,22 @@ LLValue* ABIRewrite::getAddressOf(DValue* v)
if (v->isLVal()) if (v->isLVal())
return v->getLVal(); return v->getLVal();
return storeToMemory(v->getRVal(), 0, ".getAddressOf_dump"); return DtoAllocaDump(v, ".getAddressOf_dump");
}
LLValue* ABIRewrite::storeToMemory(LLValue* rval, size_t alignment, const char* name)
{
LLValue* address = DtoRawAlloca(rval->getType(), alignment, name);
DtoStore(rval, address);
return address;
} }
void ABIRewrite::storeToMemory(LLValue* rval, LLValue* address) void ABIRewrite::storeToMemory(LLValue* rval, LLValue* address)
{ {
LLType* pointerType = address->getType(); LLType* pointerType = address->getType();
assert(pointerType->isPointerTy()); assert(pointerType->isPointerTy());
LLType* pointerElementType = pointerType->getPointerElementType(); LLType* pointeeType = pointerType->getPointerElementType();
LLType* rvalType = rval->getType(); LLType* rvalType = rval->getType();
if (rvalType != pointerElementType) if (rvalType != pointeeType)
{ {
if (getTypeStoreSize(rvalType) > getTypeAllocSize(pointerElementType)) if (getTypeStoreSize(rvalType) > getTypeAllocSize(pointeeType))
{ {
// not enough allocated memory // not enough allocated memory
LLValue* paddedDump = storeToMemory(rval, 0, ".storeToMemory_paddedDump"); LLValue* paddedDump = DtoAllocaDump(rval, 0, ".storeToMemory_paddedDump");
DtoAggrCopy(address, paddedDump); DtoAggrCopy(address, paddedDump);
return; return;
} }
@ -86,16 +79,16 @@ LLValue* ABIRewrite::loadFromMemory(LLValue* address, LLType* asType, const char
{ {
LLType* pointerType = address->getType(); LLType* pointerType = address->getType();
assert(pointerType->isPointerTy()); assert(pointerType->isPointerTy());
LLType* pointerElementType = pointerType->getPointerElementType(); LLType* pointeeType = pointerType->getPointerElementType();
if (asType == pointerElementType) if (asType == pointeeType)
return DtoLoad(address, name); return DtoLoad(address, name);
if (getTypeStoreSize(asType) > getTypeAllocSize(pointerElementType)) if (getTypeStoreSize(asType) > getTypeAllocSize(pointeeType))
{ {
// not enough allocated memory // not enough allocated memory
LLValue* paddedDump = DtoRawAlloca(asType, 0, ".loadFromMemory_paddedDump"); LLValue* paddedDump = DtoRawAlloca(asType, 0, ".loadFromMemory_paddedDump");
DtoMemCpy(paddedDump, address, DtoConstSize_t(getTypeAllocSize(pointerElementType))); DtoMemCpy(paddedDump, address, DtoConstSize_t(getTypeAllocSize(pointeeType)));
return DtoLoad(paddedDump, name); return DtoLoad(paddedDump, name);
} }

View file

@ -44,14 +44,14 @@ struct ABIRewrite
virtual ~ABIRewrite() {} virtual ~ABIRewrite() {}
/// get a rewritten value back to its original form /// get a rewritten value back to its original form
virtual llvm::Value* get(Type* dty, DValue* v) = 0; virtual llvm::Value* get(Type* dty, llvm::Value* v) = 0;
/// get a rewritten value back to its original form and store result in provided lvalue /// get a rewritten value back to its original form and store result in provided lvalue
/// this one is optional and defaults to calling the one above /// this one is optional and defaults to calling the one above
virtual void getL(Type* dty, DValue* v, llvm::Value* lval); virtual void getL(Type* dty, llvm::Value* v, llvm::Value* lval);
/// put out rewritten value /// put out rewritten value
virtual llvm::Value* put(Type* dty, DValue* v) = 0; virtual llvm::Value* put(DValue* v) = 0;
/// should return the transformed type for this rewrite /// should return the transformed type for this rewrite
virtual llvm::Type* type(Type* dty, llvm::Type* t) = 0; virtual llvm::Type* type(Type* dty, llvm::Type* t) = 0;
@ -62,10 +62,6 @@ protected:
// Returns the address of a D value, storing it to memory first if need be. // Returns the address of a D value, storing it to memory first if need be.
static llvm::Value* getAddressOf(DValue* v); static llvm::Value* getAddressOf(DValue* v);
// Stores a LL value to memory and returns its address.
static llvm::Value* storeToMemory(llvm::Value* rval, size_t alignment = 0,
const char* name = ".store_result");
// Stores a LL value to a specified memory address. The element type of the provided // Stores a LL value to a specified memory address. The element type of the provided
// pointer doesn't need to match the value type (=> suited for bit-casting). // pointer doesn't need to match the value type (=> suited for bit-casting).
static void storeToMemory(llvm::Value* rval, llvm::Value* address); static void storeToMemory(llvm::Value* rval, llvm::Value* address);

View file

@ -150,8 +150,7 @@ static void DtoArrayInit(Loc& loc, LLValue* ptr, LLValue* length, DValue* dvalue
gIR->topfunc()); gIR->topfunc());
// initialize iterator // initialize iterator
LLValue *itr = DtoAlloca(Type::tsize_t, "arrayinit.itr"); LLValue *itr = DtoAllocaDump(DtoConstSize_t(0), 0, "arrayinit.itr");
DtoStore(DtoConstSize_t(0), itr);
// move into the for condition block, ie. start the loop // move into the for condition block, ie. start the loop
assert(!gIR->scopereturned()); assert(!gIR->scopereturned());

View file

@ -512,7 +512,7 @@ void CompoundAsmStatement_toIR(CompoundAsmStatement *stmt, IRState* p)
// location of the special value determining the goto label // location of the special value determining the goto label
// will be set if post-asm dispatcher block is needed // will be set if post-asm dispatcher block is needed
llvm::AllocaInst* jump_target = 0; LLValue* jump_target = 0;
{ {
FuncDeclaration* fd = gIR->func()->decl; FuncDeclaration* fd = gIR->func()->decl;
@ -577,8 +577,7 @@ void CompoundAsmStatement_toIR(CompoundAsmStatement *stmt, IRState* p)
outSetterStmt->code += asmGotoEndLabel.str()+":\n"; outSetterStmt->code += asmGotoEndLabel.str()+":\n";
// create storage for and initialize the temporary // create storage for and initialize the temporary
jump_target = DtoAlloca(Type::tint32, "__llvm_jump_target"); jump_target = DtoAllocaDump(DtoConstUint(0), 0, "__llvm_jump_target");
gIR->ir->CreateStore(DtoConstUint(0), jump_target);
// setup variable for output from asm // setup variable for output from asm
outSetterStmt->out_c = "=*m,"; outSetterStmt->out_c = "=*m,";
outSetterStmt->out.push_back(jump_target); outSetterStmt->out.push_back(jump_target);

View file

@ -841,9 +841,10 @@ void ldc::DIBuilder::EmitStopPoint(Loc& loc)
// (line 0), then we can just ignore it (see GitHub issue #998 for why we // (line 0), then we can just ignore it (see GitHub issue #998 for why we
// cannot do this in all cases). // cannot do this in all cases).
if (!loc.linnum && if (!loc.linnum &&
!IR->ir->getCurrentDebugLocation() #if LDC_LLVM_VER >= 307
#if LDC_LLVM_VER < 307 IR->ir->getCurrentDebugLocation()
.isUnknown() #else
!IR->ir->getCurrentDebugLocation().isUnknown()
#endif #endif
) )
return; return;

View file

@ -819,8 +819,7 @@ void DtoDefineFunction(FuncDeclaration* fd)
LLValue* thismem = thisvar; LLValue* thismem = thisvar;
if (!irFty.arg_this->byref) if (!irFty.arg_this->byref)
{ {
thismem = DtoRawAlloca(thisvar->getType(), 0, "this"); // FIXME: align? thismem = DtoAllocaDump(thisvar, 0, "this");
DtoStore(thisvar, thismem);
irFunc->thisArg = thismem; irFunc->thisArg = thismem;
} }
@ -832,12 +831,7 @@ void DtoDefineFunction(FuncDeclaration* fd)
// give the 'nestArg' storage // give the 'nestArg' storage
if (irFty.arg_nest) if (irFty.arg_nest)
{ irFunc->nestArg = DtoAllocaDump(irFunc->nestArg, 0, "nestedFrame");
LLValue *nestArg = irFunc->nestArg;
LLValue *val = DtoRawAlloca(nestArg->getType(), 0, "nestedFrame");
DtoStore(nestArg, val);
irFunc->nestArg = val;
}
// give arguments storage and debug info // give arguments storage and debug info
if (fd->parameters) if (fd->parameters)
@ -873,8 +867,7 @@ void DtoDefineFunction(FuncDeclaration* fd)
LLValue* mem = DtoAlloca(irparam->arg->type, vd->ident->toChars()); LLValue* mem = DtoAlloca(irparam->arg->type, vd->ident->toChars());
// let the abi transform the argument back first // let the abi transform the argument back first
DImValue arg_dval(vd->type, irparam->value); irFty.getParam(vd->type, llArgIdx, irparam->value, mem);
irFty.getParam(vd->type, llArgIdx, &arg_dval, mem);
// set the arg var value to the alloca // set the arg var value to the alloca
irparam->value = mem; irparam->value = mem;
@ -912,10 +905,7 @@ void DtoDefineFunction(FuncDeclaration* fd)
llvm::CallInst::Create(GET_INTRINSIC_DECL(vastart), vaStartArg, "", gIR->scopebb()); llvm::CallInst::Create(GET_INTRINSIC_DECL(vastart), vaStartArg, "", gIR->scopebb());
// copy _arguments to a memory location // copy _arguments to a memory location
LLType* argumentsType = irFunc->_arguments->getType(); irFunc->_arguments = DtoAllocaDump(irFunc->_arguments, 0, "_arguments_mem");
LLValue* argumentsmem = DtoRawAlloca(argumentsType, 0, "_arguments_mem");
new llvm::StoreInst(irFunc->_arguments, argumentsmem, gIR->scopebb());
irFunc->_arguments = argumentsmem;
} }
// output function body // output function body

View file

@ -174,6 +174,42 @@ LLValue* DtoGcMalloc(Loc& loc, LLType* lltype, const char* name)
return DtoBitCast(mem, getPtrToType(lltype), name); return DtoBitCast(mem, getPtrToType(lltype), name);
} }
LLValue* DtoAllocaDump(DValue* val, const char* name)
{
return DtoAllocaDump(val->getRVal(), val->getType(), name);
}
LLValue* DtoAllocaDump(DValue* val, Type* asType, const char* name)
{
return DtoAllocaDump(val->getRVal(), asType, name);
}
LLValue* DtoAllocaDump(DValue* val, LLType* asType, int alignment, const char* name)
{
return DtoAllocaDump(val->getRVal(), asType, alignment, name);
}
LLValue* DtoAllocaDump(LLValue* val, int alignment, const char* name)
{
return DtoAllocaDump(val, val->getType(), alignment, name);
}
LLValue* DtoAllocaDump(LLValue* val, Type* asType, const char* name)
{
return DtoAllocaDump(val, DtoType(asType), asType->alignsize(), name);
}
LLValue* DtoAllocaDump(LLValue* val, LLType* asType, int alignment, const char* name)
{
LLType* valType = i1ToI8(val->getType());
asType = i1ToI8(asType);
LLType* allocaType = (
getTypeStoreSize(valType) <= getTypeAllocSize(asType) ? asType : valType);
LLValue* mem = DtoRawAlloca(allocaType, alignment, name);
DtoStoreZextI8(val, DtoBitCast(mem, valType->getPointerTo()));
return DtoBitCast(mem, asType->getPointerTo());
}
/****************************************************************************************/ /****************************************************************************************/
/*//////////////////////////////////////////////////////////////////////////////////////// /*////////////////////////////////////////////////////////////////////////////////////////
// ASSERT HELPER // ASSERT HELPER
@ -1404,11 +1440,8 @@ LLValue* makeLValue(Loc& loc, DValue* value)
needsMemory = false; needsMemory = false;
} }
if (needsMemory) { if (needsMemory)
LLValue* tmp = DtoAlloca(valueType, ".makelvaluetmp"); valuePointer = DtoAllocaDump(value, ".makelvaluetmp");
DtoStoreZextI8(valuePointer, tmp);
valuePointer = tmp;
}
return valuePointer; return valuePointer;
} }

View file

@ -37,6 +37,13 @@ llvm::AllocaInst* DtoArrayAlloca(Type* type, unsigned arraysize, const char* nam
llvm::AllocaInst* DtoRawAlloca(LLType* lltype, size_t alignment, const char* name = ""); llvm::AllocaInst* DtoRawAlloca(LLType* lltype, size_t alignment, const char* name = "");
LLValue* DtoGcMalloc(Loc& loc, LLType* lltype, const char* name = ""); LLValue* DtoGcMalloc(Loc& loc, LLType* lltype, const char* name = "");
LLValue* DtoAllocaDump(DValue* val, const char* name = "");
LLValue* DtoAllocaDump(DValue* val, Type* asType, const char* name = "");
LLValue* DtoAllocaDump(DValue* val, LLType* asType, int alignment = 0, const char* name = "");
LLValue* DtoAllocaDump(LLValue* val, int alignment = 0, const char* name = "");
LLValue* DtoAllocaDump(LLValue* val, Type* asType, const char* name = "");
LLValue* DtoAllocaDump(LLValue* val, LLType* asType, int alignment = 0, const char* name = "");
// assertion generator // assertion generator
void DtoAssert(Module* M, Loc& loc, DValue* msg); void DtoAssert(Module* M, Loc& loc, DValue* msg);

View file

@ -70,7 +70,12 @@ static std::string getProgram(const char *name, const cl::opt<std::string> &opt,
std::string getGcc() std::string getGcc()
{ {
#if defined(__FreeBSD__) && __FreeBSD__ >= 10
// Default compiler on FreeBSD 10 is clang
return getProgram("clang", gcc, "CC");
#else
return getProgram("gcc", gcc, "CC"); return getProgram("gcc", gcc, "CC");
#endif
} }
std::string getArchiver() std::string getArchiver()

View file

@ -191,7 +191,7 @@ public:
dval = toElemDtor(ae); dval = toElemDtor(ae);
} }
// do abi specific transformations on the return value // do abi specific transformations on the return value
returnValue = getIrFunc(irs->func()->decl)->irFty.putRet(stmt->exp->type, dval); returnValue = getIrFunc(irs->func()->decl)->irFty.putRet(dval);
} }
IF_LOG Logger::cout() << "return value is '" << returnValue << "'\n"; IF_LOG Logger::cout() << "return value is '" << returnValue << "'\n";
@ -1150,7 +1150,7 @@ public:
if (stmt->key) if (stmt->key)
keyvar = DtoRawVarDeclaration(stmt->key); keyvar = DtoRawVarDeclaration(stmt->key);
else else
keyvar = DtoRawAlloca(keytype, 0, "foreachkey"); // FIXME: align? keyvar = DtoRawAlloca(keytype, 0, "foreachkey");
LLValue* zerokey = LLConstantInt::get(keytype, 0, false); LLValue* zerokey = LLConstantInt::get(keytype, 0, false);
// value // value

View file

@ -166,9 +166,9 @@ static void addExplicitArguments(std::vector<LLValue*>& args, AttrSet& attrs,
llvm::Value* llVal = NULL; llvm::Value* llVal = NULL;
if (isVararg) if (isVararg)
llVal = irFty.putParam(argType, *irArg, argval); llVal = irFty.putParam(*irArg, argval);
else else
llVal = irFty.putParam(argType, i, argval); llVal = irFty.putParam(i, argval);
const size_t llArgIdx = implicitLLArgCount + const size_t llArgIdx = implicitLLArgCount +
(irFty.reverseParams ? explicitLLArgCount - i - 1 : i); (irFty.reverseParams ? explicitLLArgCount - i - 1 : i);
@ -412,12 +412,8 @@ errorLoad:
load->setAlignment(getTypeAllocSize(load->getType())); load->setAlignment(getTypeAllocSize(load->getType()));
load->setAtomic(llvm::AtomicOrdering(atomicOrdering)); load->setAtomic(llvm::AtomicOrdering(atomicOrdering));
llvm::Value* val = load; llvm::Value* val = load;
if (val->getType() != ptrTy) { if (val->getType() != ptrTy)
llvm::Value* tmp = DtoRawAlloca(val->getType(), 0); val = DtoAllocaDump(val, retType);
DtoStore(val, tmp);
tmp = DtoBitCast(tmp, ptrTy->getPointerTo());
val = tmp;
}
result = new DImValue(retType, val); result = new DImValue(retType, val);
return true; return true;
} }
@ -468,11 +464,8 @@ errorCmpxchg:
LLValue* ret = p->ir->CreateAtomicCmpXchg(ptr, cmp, val, llvm::AtomicOrdering(atomicOrdering)); LLValue* ret = p->ir->CreateAtomicCmpXchg(ptr, cmp, val, llvm::AtomicOrdering(atomicOrdering));
#endif #endif
llvm::Value* retVal = ret; llvm::Value* retVal = ret;
if (retVal->getType() != retTy) { if (retVal->getType() != retTy)
llvm::Value* tmp = DtoRawAlloca(retVal->getType(), 0); retVal = DtoAllocaDump(retVal, exp3->type);
DtoStore(retVal, tmp);
retVal = DtoBitCast(tmp, retTy->getPointerTo());
}
result = new DImValue(exp3->type, retVal); result = new DImValue(exp3->type, retVal);
return true; return true;
} }
@ -629,29 +622,34 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
DFuncValue* dfnval = fnval->isFunc(); DFuncValue* dfnval = fnval->isFunc();
// handle intrinsics // handle intrinsics
bool intrinsic = (dfnval && dfnval->func && DtoIsIntrinsic(dfnval->func)); const bool intrinsic = (dfnval && dfnval->func && DtoIsIntrinsic(dfnval->func));
// get function type info // get function type info
IrFuncTy& irFty = DtoIrTypeFunction(fnval); IrFuncTy& irFty = DtoIrTypeFunction(fnval);
TypeFunction* tf = DtoTypeFunction(fnval); TypeFunction* const tf = DtoTypeFunction(fnval);
Type* const returntype = tf->next;
const TY returnTy = returntype->toBasetype()->ty;
if (resulttype == NULL)
resulttype = returntype;
// misc // misc
bool retinptr = irFty.arg_sret; bool retinptr = irFty.arg_sret;
bool thiscall = irFty.arg_this; const bool thiscall = irFty.arg_this;
bool delegatecall = (calleeType->toBasetype()->ty == Tdelegate); const bool delegatecall = (calleeType->toBasetype()->ty == Tdelegate);
bool nestedcall = irFty.arg_nest; const bool nestedcall = irFty.arg_nest;
bool dvarargs = irFty.arg_arguments; const bool dvarargs = irFty.arg_arguments;
// get callee llvm value // get callee llvm value
LLValue* callable = DtoCallableValue(fnval); LLValue* const callable = DtoCallableValue(fnval);
LLFunctionType* callableTy = DtoExtractFunctionType(callable->getType()); LLFunctionType* const callableTy = DtoExtractFunctionType(callable->getType());
assert(callableTy); assert(callableTy);
llvm::CallingConv::ID callconv = gABI->callingConv(callableTy, tf->linkage); const llvm::CallingConv::ID callconv = gABI->callingConv(callableTy, tf->linkage);
// IF_LOG Logger::cout() << "callable: " << *callable << '\n'; // IF_LOG Logger::cout() << "callable: " << *callable << '\n';
// get number of explicit arguments // get number of explicit arguments
size_t n_arguments = arguments ? arguments->dim : 0; const size_t n_arguments = arguments ? arguments->dim : 0;
// get llvm argument iterator, for types // get llvm argument iterator, for types
LLFunctionType::param_iterator argTypesBegin = callableTy->param_begin(); LLFunctionType::param_iterator argTypesBegin = callableTy->param_begin();
@ -800,28 +798,28 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
// If the function returns a struct or a static array, and the return // If the function returns a struct or a static array, and the return
// value is not a pointer to a struct or a static array, store it to // value is not a pointer to a struct or a static array, store it to
// a stack slot before continuing. // a stack slot before continuing.
Type* dReturnType = tf->next;
TY returnTy = dReturnType->toBasetype()->ty;
bool storeReturnValueOnStack = bool storeReturnValueOnStack =
(returnTy == Tstruct && !isaPointer(retllval)) || (returnTy == Tstruct && !isaPointer(retllval)) ||
(returnTy == Tsarray && isaArray(retllval)); (returnTy == Tsarray && isaArray(retllval));
bool retValIsAlloca = false;
// Ignore ABI for intrinsics // Ignore ABI for intrinsics
if (!intrinsic && !retinptr) if (!intrinsic && !retinptr)
{ {
// do abi specific return value fixups // do abi specific return value fixups
DImValue dretval(dReturnType, retllval);
if (storeReturnValueOnStack) if (storeReturnValueOnStack)
{ {
Logger::println("Storing return value to stack slot"); Logger::println("Storing return value to stack slot");
LLValue* mem = DtoRawAlloca(DtoType(dReturnType), 0); LLValue* mem = DtoAlloca(returntype);
irFty.getRet(dReturnType, &dretval, mem); irFty.getRet(returntype, retllval, mem);
retllval = mem; retllval = mem;
retValIsAlloca = true;
storeReturnValueOnStack = false; storeReturnValueOnStack = false;
} }
else else
{ {
retllval = irFty.getRet(dReturnType, &dretval); retllval = irFty.getRet(returntype, retllval);
storeReturnValueOnStack = storeReturnValueOnStack =
(returnTy == Tstruct && !isaPointer(retllval)) || (returnTy == Tstruct && !isaPointer(retllval)) ||
(returnTy == Tsarray && isaArray(retllval)); (returnTy == Tsarray && isaArray(retllval));
@ -831,19 +829,16 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
if (storeReturnValueOnStack) if (storeReturnValueOnStack)
{ {
Logger::println("Storing return value to stack slot"); Logger::println("Storing return value to stack slot");
LLValue* mem = DtoRawAlloca(retllval->getType(), 0); retllval = DtoAllocaDump(retllval, returntype);
DtoStore(retllval, mem); retValIsAlloca = true;
retllval = mem;
} }
// repaint the type if necessary // repaint the type if necessary
if (resulttype)
{
Type* rbase = stripModifiers(resulttype->toBasetype(), true); Type* rbase = stripModifiers(resulttype->toBasetype(), true);
Type* nextbase = stripModifiers(tf->nextOf()->toBasetype(), true); Type* nextbase = stripModifiers(returntype->toBasetype(), true);
if (!rbase->equals(nextbase)) if (!rbase->equals(nextbase))
{ {
IF_LOG Logger::println("repainting return value from '%s' to '%s'", tf->nextOf()->toChars(), rbase->toChars()); IF_LOG Logger::println("repainting return value from '%s' to '%s'", returntype->toChars(), rbase->toChars());
switch(rbase->ty) switch(rbase->ty)
{ {
case Tarray: case Tarray:
@ -875,11 +870,9 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
// by value and not in an sret argument, so if the struct // by value and not in an sret argument, so if the struct
// type will be used, give the return value storage here // type will be used, give the return value storage here
// so that we get the right amount of indirections. // so that we get the right amount of indirections.
LLValue* tmp = DtoAlloca(rbase, ".aalvauetmp");
LLValue* val = DtoInsertValue( LLValue* val = DtoInsertValue(
llvm::UndefValue::get(DtoType(rbase)), retllval, 0); llvm::UndefValue::get(DtoType(rbase)), retllval, 0);
DtoStore(val, tmp); retllval = DtoAllocaDump(val, rbase, ".aalvaluetmp");
retllval = tmp;
retinptr = true; retinptr = true;
break; break;
} }
@ -923,7 +916,6 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
} }
IF_LOG Logger::cout() << "final return value: " << *retllval << '\n'; IF_LOG Logger::cout() << "final return value: " << *retllval << '\n';
} }
}
// set calling convention and parameter attributes // set calling convention and parameter attributes
#if LDC_LLVM_VER >= 303 #if LDC_LLVM_VER >= 303
@ -967,7 +959,7 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
// if we are returning through a pointer arg // if we are returning through a pointer arg
// or if we are returning a reference // or if we are returning a reference
// make sure we provide a lvalue back! // make sure we provide a lvalue back!
if (retinptr || (tf->isref && returnTy != Tvoid)) if (retinptr || (tf->isref && returnTy != Tvoid) || retValIsAlloca)
return new DVarValue(resulttype, retllval); return new DVarValue(resulttype, retllval);
return new DImValue(resulttype, retllval); return new DImValue(resulttype, retllval);

View file

@ -302,8 +302,7 @@ public:
if (result && result->getType()->ty != Tvoid && if (result && result->getType()->ty != Tvoid &&
(result->isIm() || result->isSlice()) (result->isIm() || result->isSlice())
) { ) {
llvm::AllocaInst* alloca = DtoAlloca(result->getType()); LLValue* alloca = DtoAllocaDump(result);
DtoStoreZextI8(result->getRVal(), alloca);
result = new DVarValue(result->getType(), alloca); result = new DVarValue(result->getType(), alloca);
} }
@ -1121,9 +1120,7 @@ public:
else else
{ {
assert(v->isSlice()); assert(v->isSlice());
LLValue* rval = v->getRVal(); lval = DtoAllocaDump(v, ".tmp_slice_storage");
lval = DtoRawAlloca(rval->getType(), 0, ".tmp_slice_storage");
DtoStore(rval, lval);
} }
IF_LOG Logger::cout() << "lval: " << *lval << '\n'; IF_LOG Logger::cout() << "lval: " << *lval << '\n';
@ -2589,7 +2586,7 @@ public:
} }
else else
{ {
llvm::Value* storage = DtoRawAlloca(llStoType, 0, "arrayliteral"); llvm::Value* storage = DtoRawAlloca(llStoType, e->type->alignsize(), "arrayliteral");
initializeArrayLiteral(p, e, storage); initializeArrayLiteral(p, e, storage);
result = new DImValue(e->type, storage); result = new DImValue(e->type, storage);
} }
@ -2628,7 +2625,7 @@ public:
DtoResolveStruct(e->sd); DtoResolveStruct(e->sd);
// alloca a stack slot // alloca a stack slot
e->inProgressMemory = DtoRawAlloca(DtoType(e->type), 0, ".structliteral"); e->inProgressMemory = DtoAlloca(e->type, ".structliteral");
// fill the allocated struct literal // fill the allocated struct literal
write_struct_literal(e->loc, e->inProgressMemory, e->sd, e->elements); write_struct_literal(e->loc, e->inProgressMemory, e->sd, e->elements);
@ -2795,9 +2792,8 @@ public:
LruntimeInit: LruntimeInit:
// it should be possible to avoid the temporary in some cases // it should be possible to avoid the temporary in some cases
LLValue* tmp = DtoAlloca(e->type, "aaliteral"); LLValue* tmp = DtoAllocaDump(LLConstant::getNullValue(DtoType(e->type)), e->type, "aaliteral");
result = new DVarValue(e->type, tmp); result = new DVarValue(e->type, tmp);
DtoStore(LLConstant::getNullValue(DtoType(e->type)), tmp);
const size_t n = e->keys->dim; const size_t n = e->keys->dim;
for (size_t i = 0; i<n; ++i) for (size_t i = 0; i<n; ++i)

View file

@ -19,65 +19,70 @@ IrFuncTyArg::IrFuncTyArg(Type* t, bool bref, const AttrBuilder& a)
: type(t), parametersIdx(0), : type(t), parametersIdx(0),
ltype(t != Type::tvoid && bref ? DtoType(t->pointerTo()) : DtoType(t)), ltype(t != Type::tvoid && bref ? DtoType(t->pointerTo()) : DtoType(t)),
attrs(a), byref(bref), rewrite(0) attrs(a), byref(bref), rewrite(0)
{ {}
}
bool IrFuncTyArg::isInReg() const { return attrs.contains(LDC_ATTRIBUTE(InReg)); } bool IrFuncTyArg::isInReg() const { return attrs.contains(LDC_ATTRIBUTE(InReg)); }
bool IrFuncTyArg::isSRet() const { return attrs.contains(LDC_ATTRIBUTE(StructRet)); } bool IrFuncTyArg::isSRet() const { return attrs.contains(LDC_ATTRIBUTE(StructRet)); }
bool IrFuncTyArg::isByVal() const { return attrs.contains(LDC_ATTRIBUTE(ByVal)); } bool IrFuncTyArg::isByVal() const { return attrs.contains(LDC_ATTRIBUTE(ByVal)); }
llvm::Value* IrFuncTy::putRet(Type* dty, DValue* val) llvm::Value* IrFuncTy::putRet(DValue* dval)
{ {
assert(!arg_sret); assert(!arg_sret);
if (ret->rewrite) { if (ret->rewrite) {
Logger::println("Rewrite: putRet"); Logger::println("Rewrite: putRet");
LOG_SCOPE LOG_SCOPE
return ret->rewrite->put(dty, val); return ret->rewrite->put(dval);
}
return val->getRVal();
} }
llvm::Value* IrFuncTy::getRet(Type* dty, DValue* val) return dval->getRVal();
}
llvm::Value* IrFuncTy::getRet(Type* dty, LLValue* val)
{ {
assert(!arg_sret); assert(!arg_sret);
if (ret->rewrite) { if (ret->rewrite) {
Logger::println("Rewrite: getRet"); Logger::println("Rewrite: getRet");
LOG_SCOPE LOG_SCOPE
return ret->rewrite->get(dty, val); return ret->rewrite->get(dty, val);
} }
return val->getRVal();
return val;
} }
void IrFuncTy::getRet(Type* dty, DValue* val, llvm::Value* lval) void IrFuncTy::getRet(Type* dty, LLValue* val, LLValue* address)
{ {
assert(!arg_sret); assert(!arg_sret);
if (ret->rewrite) { if (ret->rewrite) {
Logger::println("Rewrite: getRet (getL)"); Logger::println("Rewrite: getRet (getL)");
LOG_SCOPE LOG_SCOPE
ret->rewrite->getL(dty, val, lval); ret->rewrite->getL(dty, val, address);
return; return;
} }
DtoStoreZextI8(val->getRVal(), lval); DtoStoreZextI8(val, address);
} }
llvm::Value* IrFuncTy::putParam(Type* dty, size_t idx, DValue* val) llvm::Value* IrFuncTy::putParam(size_t idx, DValue* dval)
{ {
assert(idx < args.size() && "invalid putParam"); assert(idx < args.size() && "invalid putParam");
return putParam(dty, *args[idx], val); return putParam(*args[idx], dval);
} }
llvm::Value* IrFuncTy::putParam(Type* dty, const IrFuncTyArg& arg, DValue* val) llvm::Value* IrFuncTy::putParam(const IrFuncTyArg& arg, DValue* dval)
{ {
if (arg.rewrite) { if (arg.rewrite) {
Logger::println("Rewrite: putParam"); Logger::println("Rewrite: putParam");
LOG_SCOPE LOG_SCOPE
return arg.rewrite->put(dty, val); return arg.rewrite->put(dval);
}
return val->getRVal();
} }
void IrFuncTy::getParam(Type* dty, size_t idx, DValue* val, llvm::Value* lval) return dval->getRVal();
}
void IrFuncTy::getParam(Type* dty, size_t idx, LLValue* val, LLValue* address)
{ {
assert(idx < args.size() && "invalid getParam"); assert(idx < args.size() && "invalid getParam");
@ -85,9 +90,9 @@ void IrFuncTy::getParam(Type* dty, size_t idx, DValue* val, llvm::Value* lval)
{ {
Logger::println("Rewrite: getParam (getL)"); Logger::println("Rewrite: getParam (getL)");
LOG_SCOPE LOG_SCOPE
args[idx]->rewrite->getL(dty, val, lval); args[idx]->rewrite->getL(dty, val, address);
return; return;
} }
DtoStoreZextI8(val->getRVal(), lval); DtoStoreZextI8(val, address);
} }

View file

@ -133,13 +133,13 @@ struct IrFuncTy
tag(NULL) tag(NULL)
{} {}
llvm::Value* putRet(Type* dty, DValue* dval); llvm::Value* putRet(DValue* dval);
llvm::Value* getRet(Type* dty, DValue* dval); llvm::Value* getRet(Type* dty, llvm::Value* val);
void getRet(Type* dty, DValue* dval, llvm::Value* lval); void getRet(Type* dty, llvm::Value* val, llvm::Value* address);
llvm::Value* putParam(Type* dty, size_t idx, DValue* dval); llvm::Value* putParam(size_t idx, DValue* dval);
llvm::Value* putParam(Type* dty, const IrFuncTyArg& arg, DValue* dval); llvm::Value* putParam(const IrFuncTyArg& arg, DValue* dval);
void getParam(Type* dty, size_t idx, DValue* dval, llvm::Value* lval); void getParam(Type* dty, size_t idx, llvm::Value* val, llvm::Value* address);
}; };
#endif #endif

View file

@ -13,7 +13,7 @@ set(BUILD_BC_LIBS OFF CACHE BOOL
set(INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/include/d CACHE PATH "Path to install D modules to") set(INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/include/d CACHE PATH "Path to install D modules to")
set(BUILD_SHARED_LIBS OFF CACHE BOOL "Whether to build the runtime as a shared library") set(BUILD_SHARED_LIBS OFF CACHE BOOL "Whether to build the runtime as a shared library")
set(D_FLAGS -w;-d CACHE STRING "Runtime build flags, separated by ;") set(D_FLAGS -w;-d CACHE STRING "Runtime build flags, separated by ;")
set(D_FLAGS_DEBUG -g CACHE STRING "Runtime build flags (debug libraries), separated by ;") set(D_FLAGS_DEBUG -g;-link-debuglib CACHE STRING "Runtime build flags (debug libraries), separated by ;")
set(D_FLAGS_RELEASE -O3;-release CACHE STRING "Runtime build flags (release libraries), separated by ;") set(D_FLAGS_RELEASE -O3;-release CACHE STRING "Runtime build flags (release libraries), separated by ;")
if(MSVC) if(MSVC)
set(LINK_WITH_MSVCRT ON CACHE BOOL "Link with MSVCRT.lib (DLL) instead of LIBCMT.lib (static)") set(LINK_WITH_MSVCRT ON CACHE BOOL "Link with MSVCRT.lib (DLL) instead of LIBCMT.lib (static)")

@ -1 +1 @@
Subproject commit e2689182f1db1b2dfe3edf1923317a962d8fc5f4 Subproject commit 5cedb90e29fdbb4dc76d58c183c8ea7342572b74

View file

@ -25,11 +25,11 @@ endfunction()
# Would like to specify the "-release" flag for relase builds, but some of the # Would like to specify the "-release" flag for relase builds, but some of the
# tests (e.g. 'testdstress') depend on contracts and invariants being active. # tests (e.g. 'testdstress') depend on contracts and invariants being active.
# Need a solution integrated with d_do_test. # Need a solution integrated with d_do_test.
add_testsuite("-debug" -gc ${host_model}) add_testsuite("-debug" "-gc -link-debuglib" ${host_model})
add_testsuite("" -O3 ${host_model}) add_testsuite("" -O3 ${host_model})
if(MULTILIB AND host_model EQUAL 64) if(MULTILIB AND host_model EQUAL 64)
# Also test in 32 bit mode on x86_64 multilib builds. # Also test in 32 bit mode on x86_64 multilib builds.
add_testsuite("-debug-32" -gc 32) add_testsuite("-debug-32" "-gc -link-debuglib" 32)
add_testsuite("-32" -O3 32) add_testsuite("-32" -O3 32)
endif() endif()