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
- 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

View file

@ -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;

View file

@ -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)

View file

@ -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)

View file

@ -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)

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);
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);
}

View file

@ -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);

View file

@ -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());

View file

@ -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);

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
// 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;

View file

@ -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

View file

@ -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;
}

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 = "");
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);

View file

@ -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()

View file

@ -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

View file

@ -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);

View file

@ -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)

View file

@ -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);
}

View file

@ -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

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(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

View file

@ -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()