mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-07 19:36:06 +03:00
Merge branch 'master' into merge-2.068
Conflicts: runtime/druntime
This commit is contained in:
commit
d45170464e
22 changed files with 269 additions and 267 deletions
|
@ -99,7 +99,7 @@ build_script:
|
|||
- 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
|
||||
# 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
|
||||
- ninja -j2
|
||||
|
||||
|
|
|
@ -90,15 +90,18 @@ static cl::list<std::string, StringsAdapter> importPaths("I",
|
|||
cl::Prefix);
|
||||
|
||||
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::ZeroOrMore);
|
||||
|
||||
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::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
|
||||
namespace llvm {
|
||||
|
@ -420,8 +423,7 @@ static void parseCommandLine(int argc, char **argv, Strings &sourceFiles, bool &
|
|||
else
|
||||
{
|
||||
// Parse comma-separated default library list.
|
||||
std::stringstream libNames(
|
||||
global.params.symdebug ? debugLib : defaultLib);
|
||||
std::stringstream libNames(linkDebugLib ? debugLib : defaultLib);
|
||||
while (libNames.good())
|
||||
{
|
||||
std::string lib;
|
||||
|
|
|
@ -110,14 +110,13 @@ struct AArch64TargetABI : TargetABI
|
|||
}
|
||||
|
||||
void vaCopy(LLValue* pDest, LLValue* src) {
|
||||
// Analog to va_start, we need to allocate a __va_list struct on the stack first
|
||||
// and set the passed 'dest' char* pointer to its address.
|
||||
LLValue* valistmem = DtoRawAlloca(getValistType(), 0, "__va_list_mem");
|
||||
DtoStore(DtoBitCast(valistmem, getVoidPtrType()), pDest);
|
||||
|
||||
// Now bitcopy the source struct over the destination struct.
|
||||
src = DtoBitCast(src, valistmem->getType());
|
||||
DtoStore(DtoLoad(src), valistmem); // *(__va_list*)dest = *(__va_list*)src
|
||||
// Analog to va_start, we need to allocate a new __va_list struct on the stack,
|
||||
// fill it with a bitcopy of the source struct...
|
||||
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()),
|
||||
DtoBitCast(pDest, getPtrToType(getVoidPtrType())));
|
||||
}
|
||||
|
||||
LLValue* prepareVaArg(LLValue* pAp)
|
||||
|
|
|
@ -82,24 +82,23 @@ struct LLTypeMemoryLayout
|
|||
/// Removes padding fields for (non-union-containing!) structs
|
||||
struct RemoveStructPadding : ABIRewrite {
|
||||
/// 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");
|
||||
getL(dty, v, lval);
|
||||
return lval;
|
||||
}
|
||||
|
||||
/// 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, DValue* v, LLValue* lval) {
|
||||
void getL(Type* dty, LLValue* v, LLValue* lval) {
|
||||
// Make sure the padding is zero, so struct comparisons work.
|
||||
// TODO: Only do this if there's padding, and/or only initialize padding.
|
||||
DtoMemSetZero(lval, DtoConstSize_t(getTypePaddedSize(DtoType(dty))));
|
||||
DtoPaddedStruct(dty->toBasetype(), v->getRVal(), lval);
|
||||
DtoPaddedStruct(dty->toBasetype(), v, lval);
|
||||
}
|
||||
|
||||
/// put out rewritten value
|
||||
LLValue* put(Type* dty, DValue* v) {
|
||||
return DtoUnpaddedStruct(dty->toBasetype(), v->getRVal());
|
||||
LLValue* put(DValue* v) {
|
||||
return DtoUnpaddedStruct(v->getType()->toBasetype(), v->getRVal());
|
||||
}
|
||||
|
||||
/// return the transformed type for this rewrite
|
||||
|
@ -154,26 +153,22 @@ struct IntegerRewrite : ABIRewrite
|
|||
return LLTypeMemoryLayout::typesAreEquivalent(llType, integerType);
|
||||
}
|
||||
|
||||
LLValue* get(Type* dty, DValue* dv)
|
||||
LLValue* get(Type* dty, LLValue* v)
|
||||
{
|
||||
LLValue* integer = dv->getRVal();
|
||||
LLValue* integerDump = storeToMemory(integer, 0, ".IntegerRewrite_dump");
|
||||
|
||||
LLValue* integerDump = DtoAllocaDump(v, dty, ".IntegerRewrite_dump");
|
||||
LLType* type = DtoType(dty);
|
||||
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(integer, lval);
|
||||
storeToMemory(v, lval);
|
||||
}
|
||||
|
||||
LLValue* put(Type* dty, DValue* dv)
|
||||
LLValue* put(DValue* dv)
|
||||
{
|
||||
assert(dty == dv->getType());
|
||||
LLValue* address = getAddressOf(dv);
|
||||
LLType* integerType = getIntegerType(dty->size());
|
||||
LLType* integerType = getIntegerType(dv->getType()->size());
|
||||
return loadFromMemory(address, integerType, ".IntegerRewrite_putResult");
|
||||
}
|
||||
|
||||
|
@ -205,21 +200,19 @@ struct ExplicitByvalRewrite : ABIRewrite
|
|||
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(pointer, ".ExplicitByvalRewrite_getResult");
|
||||
return DtoLoad(v, ".ExplicitByvalRewrite_getResult");
|
||||
}
|
||||
|
||||
void getL(Type* dty, DValue* v, LLValue* lval)
|
||||
void getL(Type* dty, LLValue* v, LLValue* lval)
|
||||
{
|
||||
LLValue* pointer = v->getRVal();
|
||||
DtoAggrCopy(lval, pointer);
|
||||
DtoAggrCopy(lval, v);
|
||||
}
|
||||
|
||||
LLValue* put(Type* dty, DValue* v)
|
||||
LLValue* put(DValue* v)
|
||||
{
|
||||
if (DtoIsPassedByRef(dty))
|
||||
if (DtoIsPassedByRef(v->getType()))
|
||||
{
|
||||
LLValue* originalPointer = v->getRVal();
|
||||
LLType* type = originalPointer->getType()->getPointerElementType();
|
||||
|
@ -228,9 +221,7 @@ struct ExplicitByvalRewrite : ABIRewrite
|
|||
return copyForCallee;
|
||||
}
|
||||
|
||||
LLValue* originalValue = v->getRVal();
|
||||
LLValue* copyForCallee = storeToMemory(originalValue, alignment, ".ExplicitByvalRewrite_putResult");
|
||||
return copyForCallee;
|
||||
return DtoAllocaDump(v->getRVal(), alignment, ".ExplicitByvalRewrite_putResult");
|
||||
}
|
||||
|
||||
LLType* type(Type* dty, LLType* t)
|
||||
|
|
|
@ -160,22 +160,21 @@ namespace {
|
|||
* memory so that it's then readable as the other type (i.e., bit-casting).
|
||||
*/
|
||||
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);
|
||||
return loadFromMemory(address, type, ".X86_64_C_struct_rewrite_getResult");
|
||||
}
|
||||
|
||||
void getL(Type* dty, DValue* v, LLValue* lval) {
|
||||
storeToMemory(v->getRVal(), lval);
|
||||
void getL(Type* dty, LLValue* v, LLValue* lval) {
|
||||
storeToMemory(v, lval);
|
||||
}
|
||||
|
||||
LLValue* put(Type* dty, DValue* v) {
|
||||
assert(dty == v->getType());
|
||||
LLValue* put(DValue* v) {
|
||||
LLValue* address = getAddressOf(v);
|
||||
|
||||
LLType* abiTy = getAbiType(dty);
|
||||
LLType* abiTy = getAbiType(v->getType());
|
||||
assert(abiTy && "Why are we rewriting a non-rewritten type?");
|
||||
|
||||
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.
|
||||
*/
|
||||
struct ImplicitByvalRewrite : ABIRewrite {
|
||||
LLValue* get(Type* dty, DValue* v) {
|
||||
LLValue* pointer = v->getRVal();
|
||||
return DtoLoad(pointer, ".ImplicitByvalRewrite_getResult");
|
||||
LLValue* get(Type* dty, LLValue* v) {
|
||||
return DtoLoad(v, ".ImplicitByvalRewrite_getResult");
|
||||
}
|
||||
|
||||
void getL(Type* dty, DValue* v, LLValue* lval) {
|
||||
LLValue* pointer = v->getRVal();
|
||||
DtoAggrCopy(lval, pointer);
|
||||
void getL(Type* dty, LLValue* v, LLValue* lval) {
|
||||
DtoAggrCopy(lval, v);
|
||||
}
|
||||
|
||||
LLValue* put(Type* dty, DValue* v) {
|
||||
assert(dty == v->getType());
|
||||
LLValue* put(DValue* v) {
|
||||
return getAddressOf(v);
|
||||
}
|
||||
|
||||
|
@ -388,15 +384,13 @@ LLValue* X86_64TargetABI::prepareVaStart(LLValue* pAp) {
|
|||
}
|
||||
|
||||
void X86_64TargetABI::vaCopy(LLValue* pDest, LLValue* src) {
|
||||
// Analog to va_start, we need to allocate a __va_list struct on the stack first
|
||||
// and set the passed 'dest' char* pointer to its address.
|
||||
LLValue* valistmem = DtoRawAlloca(getValistType(), 0, "__va_list_mem");
|
||||
// Analog to va_start, we need to allocate a new __va_list struct on the stack,
|
||||
// fill it with a bitcopy of the source struct...
|
||||
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()),
|
||||
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)
|
||||
|
|
27
gen/abi.cpp
27
gen/abi.cpp
|
@ -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);
|
||||
assert(rval->getType() == lval->getType()->getContainedType(0));
|
||||
|
@ -49,29 +49,22 @@ LLValue* ABIRewrite::getAddressOf(DValue* v)
|
|||
if (v->isLVal())
|
||||
return v->getLVal();
|
||||
|
||||
return storeToMemory(v->getRVal(), 0, ".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;
|
||||
return DtoAllocaDump(v, ".getAddressOf_dump");
|
||||
}
|
||||
|
||||
void ABIRewrite::storeToMemory(LLValue* rval, LLValue* address)
|
||||
{
|
||||
LLType* pointerType = address->getType();
|
||||
assert(pointerType->isPointerTy());
|
||||
LLType* pointerElementType = pointerType->getPointerElementType();
|
||||
LLType* pointeeType = pointerType->getPointerElementType();
|
||||
|
||||
LLType* rvalType = rval->getType();
|
||||
if (rvalType != pointerElementType)
|
||||
if (rvalType != pointeeType)
|
||||
{
|
||||
if (getTypeStoreSize(rvalType) > getTypeAllocSize(pointerElementType))
|
||||
if (getTypeStoreSize(rvalType) > getTypeAllocSize(pointeeType))
|
||||
{
|
||||
// not enough allocated memory
|
||||
LLValue* paddedDump = storeToMemory(rval, 0, ".storeToMemory_paddedDump");
|
||||
LLValue* paddedDump = DtoAllocaDump(rval, 0, ".storeToMemory_paddedDump");
|
||||
DtoAggrCopy(address, paddedDump);
|
||||
return;
|
||||
}
|
||||
|
@ -86,16 +79,16 @@ LLValue* ABIRewrite::loadFromMemory(LLValue* address, LLType* asType, const char
|
|||
{
|
||||
LLType* pointerType = address->getType();
|
||||
assert(pointerType->isPointerTy());
|
||||
LLType* pointerElementType = pointerType->getPointerElementType();
|
||||
LLType* pointeeType = pointerType->getPointerElementType();
|
||||
|
||||
if (asType == pointerElementType)
|
||||
if (asType == pointeeType)
|
||||
return DtoLoad(address, name);
|
||||
|
||||
if (getTypeStoreSize(asType) > getTypeAllocSize(pointerElementType))
|
||||
if (getTypeStoreSize(asType) > getTypeAllocSize(pointeeType))
|
||||
{
|
||||
// not enough allocated memory
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
10
gen/abi.h
10
gen/abi.h
|
@ -44,14 +44,14 @@ struct ABIRewrite
|
|||
virtual ~ABIRewrite() {}
|
||||
|
||||
/// 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
|
||||
/// 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
|
||||
virtual llvm::Value* put(Type* dty, DValue* v) = 0;
|
||||
virtual llvm::Value* put(DValue* v) = 0;
|
||||
|
||||
/// should return the transformed type for this rewrite
|
||||
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.
|
||||
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
|
||||
// pointer doesn't need to match the value type (=> suited for bit-casting).
|
||||
static void storeToMemory(llvm::Value* rval, llvm::Value* address);
|
||||
|
|
|
@ -150,8 +150,7 @@ static void DtoArrayInit(Loc& loc, LLValue* ptr, LLValue* length, DValue* dvalue
|
|||
gIR->topfunc());
|
||||
|
||||
// initialize iterator
|
||||
LLValue *itr = DtoAlloca(Type::tsize_t, "arrayinit.itr");
|
||||
DtoStore(DtoConstSize_t(0), itr);
|
||||
LLValue *itr = DtoAllocaDump(DtoConstSize_t(0), 0, "arrayinit.itr");
|
||||
|
||||
// move into the for condition block, ie. start the loop
|
||||
assert(!gIR->scopereturned());
|
||||
|
|
|
@ -512,7 +512,7 @@ void CompoundAsmStatement_toIR(CompoundAsmStatement *stmt, IRState* p)
|
|||
|
||||
// location of the special value determining the goto label
|
||||
// will be set if post-asm dispatcher block is needed
|
||||
llvm::AllocaInst* jump_target = 0;
|
||||
LLValue* jump_target = 0;
|
||||
|
||||
{
|
||||
FuncDeclaration* fd = gIR->func()->decl;
|
||||
|
@ -577,8 +577,7 @@ void CompoundAsmStatement_toIR(CompoundAsmStatement *stmt, IRState* p)
|
|||
outSetterStmt->code += asmGotoEndLabel.str()+":\n";
|
||||
|
||||
// create storage for and initialize the temporary
|
||||
jump_target = DtoAlloca(Type::tint32, "__llvm_jump_target");
|
||||
gIR->ir->CreateStore(DtoConstUint(0), jump_target);
|
||||
jump_target = DtoAllocaDump(DtoConstUint(0), 0, "__llvm_jump_target");
|
||||
// setup variable for output from asm
|
||||
outSetterStmt->out_c = "=*m,";
|
||||
outSetterStmt->out.push_back(jump_target);
|
||||
|
|
|
@ -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
|
||||
// cannot do this in all cases).
|
||||
if (!loc.linnum &&
|
||||
!IR->ir->getCurrentDebugLocation()
|
||||
#if LDC_LLVM_VER < 307
|
||||
.isUnknown()
|
||||
#if LDC_LLVM_VER >= 307
|
||||
IR->ir->getCurrentDebugLocation()
|
||||
#else
|
||||
!IR->ir->getCurrentDebugLocation().isUnknown()
|
||||
#endif
|
||||
)
|
||||
return;
|
||||
|
|
|
@ -819,8 +819,7 @@ void DtoDefineFunction(FuncDeclaration* fd)
|
|||
LLValue* thismem = thisvar;
|
||||
if (!irFty.arg_this->byref)
|
||||
{
|
||||
thismem = DtoRawAlloca(thisvar->getType(), 0, "this"); // FIXME: align?
|
||||
DtoStore(thisvar, thismem);
|
||||
thismem = DtoAllocaDump(thisvar, 0, "this");
|
||||
irFunc->thisArg = thismem;
|
||||
}
|
||||
|
||||
|
@ -832,12 +831,7 @@ void DtoDefineFunction(FuncDeclaration* fd)
|
|||
|
||||
// give the 'nestArg' storage
|
||||
if (irFty.arg_nest)
|
||||
{
|
||||
LLValue *nestArg = irFunc->nestArg;
|
||||
LLValue *val = DtoRawAlloca(nestArg->getType(), 0, "nestedFrame");
|
||||
DtoStore(nestArg, val);
|
||||
irFunc->nestArg = val;
|
||||
}
|
||||
irFunc->nestArg = DtoAllocaDump(irFunc->nestArg, 0, "nestedFrame");
|
||||
|
||||
// give arguments storage and debug info
|
||||
if (fd->parameters)
|
||||
|
@ -873,8 +867,7 @@ void DtoDefineFunction(FuncDeclaration* fd)
|
|||
LLValue* mem = DtoAlloca(irparam->arg->type, vd->ident->toChars());
|
||||
|
||||
// let the abi transform the argument back first
|
||||
DImValue arg_dval(vd->type, irparam->value);
|
||||
irFty.getParam(vd->type, llArgIdx, &arg_dval, mem);
|
||||
irFty.getParam(vd->type, llArgIdx, irparam->value, mem);
|
||||
|
||||
// set the arg var value to the alloca
|
||||
irparam->value = mem;
|
||||
|
@ -912,10 +905,7 @@ void DtoDefineFunction(FuncDeclaration* fd)
|
|||
llvm::CallInst::Create(GET_INTRINSIC_DECL(vastart), vaStartArg, "", gIR->scopebb());
|
||||
|
||||
// copy _arguments to a memory location
|
||||
LLType* argumentsType = irFunc->_arguments->getType();
|
||||
LLValue* argumentsmem = DtoRawAlloca(argumentsType, 0, "_arguments_mem");
|
||||
new llvm::StoreInst(irFunc->_arguments, argumentsmem, gIR->scopebb());
|
||||
irFunc->_arguments = argumentsmem;
|
||||
irFunc->_arguments = DtoAllocaDump(irFunc->_arguments, 0, "_arguments_mem");
|
||||
}
|
||||
|
||||
// output function body
|
||||
|
|
|
@ -174,6 +174,42 @@ LLValue* DtoGcMalloc(Loc& loc, LLType* lltype, const char* 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
|
||||
|
@ -1404,11 +1440,8 @@ LLValue* makeLValue(Loc& loc, DValue* value)
|
|||
needsMemory = false;
|
||||
}
|
||||
|
||||
if (needsMemory) {
|
||||
LLValue* tmp = DtoAlloca(valueType, ".makelvaluetmp");
|
||||
DtoStoreZextI8(valuePointer, tmp);
|
||||
valuePointer = tmp;
|
||||
}
|
||||
if (needsMemory)
|
||||
valuePointer = DtoAllocaDump(value, ".makelvaluetmp");
|
||||
|
||||
return valuePointer;
|
||||
}
|
||||
|
|
|
@ -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 = "");
|
||||
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
|
||||
void DtoAssert(Module* M, Loc& loc, DValue* msg);
|
||||
|
||||
|
|
|
@ -70,7 +70,12 @@ static std::string getProgram(const char *name, const cl::opt<std::string> &opt,
|
|||
|
||||
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");
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string getArchiver()
|
||||
|
|
|
@ -191,7 +191,7 @@ public:
|
|||
dval = toElemDtor(ae);
|
||||
}
|
||||
// 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";
|
||||
|
@ -1150,7 +1150,7 @@ public:
|
|||
if (stmt->key)
|
||||
keyvar = DtoRawVarDeclaration(stmt->key);
|
||||
else
|
||||
keyvar = DtoRawAlloca(keytype, 0, "foreachkey"); // FIXME: align?
|
||||
keyvar = DtoRawAlloca(keytype, 0, "foreachkey");
|
||||
LLValue* zerokey = LLConstantInt::get(keytype, 0, false);
|
||||
|
||||
// value
|
||||
|
|
|
@ -166,9 +166,9 @@ static void addExplicitArguments(std::vector<LLValue*>& args, AttrSet& attrs,
|
|||
|
||||
llvm::Value* llVal = NULL;
|
||||
if (isVararg)
|
||||
llVal = irFty.putParam(argType, *irArg, argval);
|
||||
llVal = irFty.putParam(*irArg, argval);
|
||||
else
|
||||
llVal = irFty.putParam(argType, i, argval);
|
||||
llVal = irFty.putParam(i, argval);
|
||||
|
||||
const size_t llArgIdx = implicitLLArgCount +
|
||||
(irFty.reverseParams ? explicitLLArgCount - i - 1 : i);
|
||||
|
@ -412,12 +412,8 @@ errorLoad:
|
|||
load->setAlignment(getTypeAllocSize(load->getType()));
|
||||
load->setAtomic(llvm::AtomicOrdering(atomicOrdering));
|
||||
llvm::Value* val = load;
|
||||
if (val->getType() != ptrTy) {
|
||||
llvm::Value* tmp = DtoRawAlloca(val->getType(), 0);
|
||||
DtoStore(val, tmp);
|
||||
tmp = DtoBitCast(tmp, ptrTy->getPointerTo());
|
||||
val = tmp;
|
||||
}
|
||||
if (val->getType() != ptrTy)
|
||||
val = DtoAllocaDump(val, retType);
|
||||
result = new DImValue(retType, val);
|
||||
return true;
|
||||
}
|
||||
|
@ -468,11 +464,8 @@ errorCmpxchg:
|
|||
LLValue* ret = p->ir->CreateAtomicCmpXchg(ptr, cmp, val, llvm::AtomicOrdering(atomicOrdering));
|
||||
#endif
|
||||
llvm::Value* retVal = ret;
|
||||
if (retVal->getType() != retTy) {
|
||||
llvm::Value* tmp = DtoRawAlloca(retVal->getType(), 0);
|
||||
DtoStore(retVal, tmp);
|
||||
retVal = DtoBitCast(tmp, retTy->getPointerTo());
|
||||
}
|
||||
if (retVal->getType() != retTy)
|
||||
retVal = DtoAllocaDump(retVal, exp3->type);
|
||||
result = new DImValue(exp3->type, retVal);
|
||||
return true;
|
||||
}
|
||||
|
@ -629,29 +622,34 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
|
|||
DFuncValue* dfnval = fnval->isFunc();
|
||||
|
||||
// handle intrinsics
|
||||
bool intrinsic = (dfnval && dfnval->func && DtoIsIntrinsic(dfnval->func));
|
||||
const bool intrinsic = (dfnval && dfnval->func && DtoIsIntrinsic(dfnval->func));
|
||||
|
||||
// get function type info
|
||||
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
|
||||
bool retinptr = irFty.arg_sret;
|
||||
bool thiscall = irFty.arg_this;
|
||||
bool delegatecall = (calleeType->toBasetype()->ty == Tdelegate);
|
||||
bool nestedcall = irFty.arg_nest;
|
||||
bool dvarargs = irFty.arg_arguments;
|
||||
const bool thiscall = irFty.arg_this;
|
||||
const bool delegatecall = (calleeType->toBasetype()->ty == Tdelegate);
|
||||
const bool nestedcall = irFty.arg_nest;
|
||||
const bool dvarargs = irFty.arg_arguments;
|
||||
|
||||
// get callee llvm value
|
||||
LLValue* callable = DtoCallableValue(fnval);
|
||||
LLFunctionType* callableTy = DtoExtractFunctionType(callable->getType());
|
||||
LLValue* const callable = DtoCallableValue(fnval);
|
||||
LLFunctionType* const callableTy = DtoExtractFunctionType(callable->getType());
|
||||
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';
|
||||
|
||||
// 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
|
||||
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
|
||||
// value is not a pointer to a struct or a static array, store it to
|
||||
// a stack slot before continuing.
|
||||
Type* dReturnType = tf->next;
|
||||
TY returnTy = dReturnType->toBasetype()->ty;
|
||||
bool storeReturnValueOnStack =
|
||||
(returnTy == Tstruct && !isaPointer(retllval)) ||
|
||||
(returnTy == Tsarray && isaArray(retllval));
|
||||
|
||||
bool retValIsAlloca = false;
|
||||
|
||||
// Ignore ABI for intrinsics
|
||||
if (!intrinsic && !retinptr)
|
||||
{
|
||||
// do abi specific return value fixups
|
||||
DImValue dretval(dReturnType, retllval);
|
||||
if (storeReturnValueOnStack)
|
||||
{
|
||||
Logger::println("Storing return value to stack slot");
|
||||
LLValue* mem = DtoRawAlloca(DtoType(dReturnType), 0);
|
||||
irFty.getRet(dReturnType, &dretval, mem);
|
||||
LLValue* mem = DtoAlloca(returntype);
|
||||
irFty.getRet(returntype, retllval, mem);
|
||||
retllval = mem;
|
||||
retValIsAlloca = true;
|
||||
storeReturnValueOnStack = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
retllval = irFty.getRet(dReturnType, &dretval);
|
||||
retllval = irFty.getRet(returntype, retllval);
|
||||
storeReturnValueOnStack =
|
||||
(returnTy == Tstruct && !isaPointer(retllval)) ||
|
||||
(returnTy == Tsarray && isaArray(retllval));
|
||||
|
@ -831,19 +829,16 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
|
|||
if (storeReturnValueOnStack)
|
||||
{
|
||||
Logger::println("Storing return value to stack slot");
|
||||
LLValue* mem = DtoRawAlloca(retllval->getType(), 0);
|
||||
DtoStore(retllval, mem);
|
||||
retllval = mem;
|
||||
retllval = DtoAllocaDump(retllval, returntype);
|
||||
retValIsAlloca = true;
|
||||
}
|
||||
|
||||
// repaint the type if necessary
|
||||
if (resulttype)
|
||||
{
|
||||
Type* rbase = stripModifiers(resulttype->toBasetype(), true);
|
||||
Type* nextbase = stripModifiers(tf->nextOf()->toBasetype(), true);
|
||||
Type* nextbase = stripModifiers(returntype->toBasetype(), true);
|
||||
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)
|
||||
{
|
||||
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
|
||||
// type will be used, give the return value storage here
|
||||
// so that we get the right amount of indirections.
|
||||
LLValue* tmp = DtoAlloca(rbase, ".aalvauetmp");
|
||||
LLValue* val = DtoInsertValue(
|
||||
llvm::UndefValue::get(DtoType(rbase)), retllval, 0);
|
||||
DtoStore(val, tmp);
|
||||
retllval = tmp;
|
||||
retllval = DtoAllocaDump(val, rbase, ".aalvaluetmp");
|
||||
retinptr = true;
|
||||
break;
|
||||
}
|
||||
|
@ -923,7 +916,6 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
|
|||
}
|
||||
IF_LOG Logger::cout() << "final return value: " << *retllval << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
// set calling convention and parameter attributes
|
||||
#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
|
||||
// or if we are returning a reference
|
||||
// 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 DImValue(resulttype, retllval);
|
||||
|
|
14
gen/toir.cpp
14
gen/toir.cpp
|
@ -302,8 +302,7 @@ public:
|
|||
if (result && result->getType()->ty != Tvoid &&
|
||||
(result->isIm() || result->isSlice())
|
||||
) {
|
||||
llvm::AllocaInst* alloca = DtoAlloca(result->getType());
|
||||
DtoStoreZextI8(result->getRVal(), alloca);
|
||||
LLValue* alloca = DtoAllocaDump(result);
|
||||
result = new DVarValue(result->getType(), alloca);
|
||||
}
|
||||
|
||||
|
@ -1121,9 +1120,7 @@ public:
|
|||
else
|
||||
{
|
||||
assert(v->isSlice());
|
||||
LLValue* rval = v->getRVal();
|
||||
lval = DtoRawAlloca(rval->getType(), 0, ".tmp_slice_storage");
|
||||
DtoStore(rval, lval);
|
||||
lval = DtoAllocaDump(v, ".tmp_slice_storage");
|
||||
}
|
||||
|
||||
IF_LOG Logger::cout() << "lval: " << *lval << '\n';
|
||||
|
@ -2589,7 +2586,7 @@ public:
|
|||
}
|
||||
else
|
||||
{
|
||||
llvm::Value* storage = DtoRawAlloca(llStoType, 0, "arrayliteral");
|
||||
llvm::Value* storage = DtoRawAlloca(llStoType, e->type->alignsize(), "arrayliteral");
|
||||
initializeArrayLiteral(p, e, storage);
|
||||
result = new DImValue(e->type, storage);
|
||||
}
|
||||
|
@ -2628,7 +2625,7 @@ public:
|
|||
DtoResolveStruct(e->sd);
|
||||
|
||||
// alloca a stack slot
|
||||
e->inProgressMemory = DtoRawAlloca(DtoType(e->type), 0, ".structliteral");
|
||||
e->inProgressMemory = DtoAlloca(e->type, ".structliteral");
|
||||
|
||||
// fill the allocated struct literal
|
||||
write_struct_literal(e->loc, e->inProgressMemory, e->sd, e->elements);
|
||||
|
@ -2795,9 +2792,8 @@ public:
|
|||
LruntimeInit:
|
||||
|
||||
// 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);
|
||||
DtoStore(LLConstant::getNullValue(DtoType(e->type)), tmp);
|
||||
|
||||
const size_t n = e->keys->dim;
|
||||
for (size_t i = 0; i<n; ++i)
|
||||
|
|
|
@ -19,65 +19,70 @@ IrFuncTyArg::IrFuncTyArg(Type* t, bool bref, const AttrBuilder& a)
|
|||
: type(t), parametersIdx(0),
|
||||
ltype(t != Type::tvoid && bref ? DtoType(t->pointerTo()) : DtoType(t)),
|
||||
attrs(a), byref(bref), rewrite(0)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
bool IrFuncTyArg::isInReg() const { return attrs.contains(LDC_ATTRIBUTE(InReg)); }
|
||||
bool IrFuncTyArg::isSRet() const { return attrs.contains(LDC_ATTRIBUTE(StructRet)); }
|
||||
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);
|
||||
|
||||
if (ret->rewrite) {
|
||||
Logger::println("Rewrite: putRet");
|
||||
LOG_SCOPE
|
||||
return ret->rewrite->put(dty, val);
|
||||
}
|
||||
return val->getRVal();
|
||||
return ret->rewrite->put(dval);
|
||||
}
|
||||
|
||||
llvm::Value* IrFuncTy::getRet(Type* dty, DValue* val)
|
||||
return dval->getRVal();
|
||||
}
|
||||
|
||||
llvm::Value* IrFuncTy::getRet(Type* dty, LLValue* val)
|
||||
{
|
||||
assert(!arg_sret);
|
||||
|
||||
if (ret->rewrite) {
|
||||
Logger::println("Rewrite: getRet");
|
||||
LOG_SCOPE
|
||||
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);
|
||||
|
||||
if (ret->rewrite) {
|
||||
Logger::println("Rewrite: getRet (getL)");
|
||||
LOG_SCOPE
|
||||
ret->rewrite->getL(dty, val, lval);
|
||||
ret->rewrite->getL(dty, val, address);
|
||||
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");
|
||||
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) {
|
||||
Logger::println("Rewrite: putParam");
|
||||
LOG_SCOPE
|
||||
return arg.rewrite->put(dty, val);
|
||||
}
|
||||
return val->getRVal();
|
||||
return arg.rewrite->put(dval);
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
|
@ -85,9 +90,9 @@ void IrFuncTy::getParam(Type* dty, size_t idx, DValue* val, llvm::Value* lval)
|
|||
{
|
||||
Logger::println("Rewrite: getParam (getL)");
|
||||
LOG_SCOPE
|
||||
args[idx]->rewrite->getL(dty, val, lval);
|
||||
args[idx]->rewrite->getL(dty, val, address);
|
||||
return;
|
||||
}
|
||||
|
||||
DtoStoreZextI8(val->getRVal(), lval);
|
||||
DtoStoreZextI8(val, address);
|
||||
}
|
||||
|
|
|
@ -133,13 +133,13 @@ struct IrFuncTy
|
|||
tag(NULL)
|
||||
{}
|
||||
|
||||
llvm::Value* putRet(Type* dty, DValue* dval);
|
||||
llvm::Value* getRet(Type* dty, DValue* dval);
|
||||
void getRet(Type* dty, DValue* dval, llvm::Value* lval);
|
||||
llvm::Value* putRet(DValue* dval);
|
||||
llvm::Value* getRet(Type* dty, llvm::Value* val);
|
||||
void getRet(Type* dty, llvm::Value* val, llvm::Value* address);
|
||||
|
||||
llvm::Value* putParam(Type* dty, size_t idx, DValue* dval);
|
||||
llvm::Value* putParam(Type* dty, const IrFuncTyArg& arg, DValue* dval);
|
||||
void getParam(Type* dty, size_t idx, DValue* dval, llvm::Value* lval);
|
||||
llvm::Value* putParam(size_t idx, DValue* dval);
|
||||
llvm::Value* putParam(const IrFuncTyArg& arg, DValue* dval);
|
||||
void getParam(Type* dty, size_t idx, llvm::Value* val, llvm::Value* address);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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(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_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 ;")
|
||||
if(MSVC)
|
||||
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
|
|
@ -25,11 +25,11 @@ endfunction()
|
|||
# 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.
|
||||
# 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})
|
||||
|
||||
if(MULTILIB AND host_model EQUAL 64)
|
||||
# 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)
|
||||
endif()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue