diff --git a/gen/arrays.cpp b/gen/arrays.cpp index e022aad3..b8caa367 100644 --- a/gen/arrays.cpp +++ b/gen/arrays.cpp @@ -130,99 +130,97 @@ void DtoArrayInit(DValue* array, DValue* value) LLValue* ptr = DtoArrayPtr(array); LLValue* val = value->getRVal(); - Logger::cout() << "llvm values:\n" << " ptr: " << *ptr << " dim: " << *dim << " val: " << *val << '\n'; - - const LLType* pt = ptr->getType()->getContainedType(0); - const LLType* t = val->getType(); - - size_t aggrsz = 0; - Type* valtype = value->getType()->toBasetype(); - - const char* funcname = NULL; - + // prepare runtime call LLSmallVector args; args.push_back(ptr); args.push_back(dim); args.push_back(val); - // if t is a primitive type, use the corresponding runtime function - if (t == LLType::Int1Ty) { - funcname = "_d_array_init_i1"; - } - else if (t == LLType::Int8Ty) { - funcname = "_d_array_init_i8"; - } - else if (t == LLType::Int16Ty) { - funcname = "_d_array_init_i16"; - } - else if (t == LLType::Int32Ty) { - funcname = "_d_array_init_i32"; - } - else if (t == LLType::Int64Ty) { - funcname = "_d_array_init_i64"; - } - else if (t == LLType::FloatTy) { - funcname = "_d_array_init_float"; - } - else if (t == LLType::DoubleTy) { - funcname = "_d_array_init_double"; - } - else if (t == getPtrToType(LLType::Int8Ty)) { - funcname = "_d_array_init_pointer"; + // determine the right runtime function to call + const char* funcname = NULL; + Type* t = value->getType()->toBasetype(); - const LLType* dstty = getPtrToType(getVoidPtrType()); - if (args[0]->getType() != dstty) - args[0] = DtoBitCast(args[0],dstty); - - const LLType* valty = getVoidPtrType(); - if (args[2]->getType() != valty) - args[2] = DtoBitCast(args[2],valty); - } - // handle array rhs - else if (value->getType()->ty == Tarray || value->getType()->ty == Tsarray) + // lets first optimize all zero initializations down to a memset. + // this simplifies codegen later on as llvm null's have no address! + if (isaConstant(val) && isaConstant(val)->isNullValue()) { - const LLArrayType* dstarrty = isaArray(pt); - assert(dstarrty); - const LLPointerType* srcty = isaPointer(t); - assert(dstarrty == srcty->getElementType()); - - funcname = "_d_array_init_mem"; - - args[0] = gIR->ir->CreateBitCast(ptr, getVoidPtrType(), "tmp"); - args[2] = gIR->ir->CreateBitCast(val, getVoidPtrType(), "tmp"); - - size_t n_inner = getABITypeSize(srcty->getElementType()); - args.push_back(DtoConstSize_t(n_inner)); - } - // handle null aggregate - else if (isaStruct(t)) - { - aggrsz = getABITypeSize(t); - LLConstant* c = isaConstant(val); - assert(c && c->isNullValue()); - LLValue* nbytes; - if (aggrsz == 1) - nbytes = dim; - else - nbytes = gIR->ir->CreateMul(dim, DtoConstSize_t(aggrsz), "tmp"); - DtoMemSetZero(ptr,nbytes); + size_t X = getABITypeSize(val->getType()); + LLValue* nbytes = gIR->ir->CreateMul(dim, DtoConstSize_t(X), ".nbytes"); + DtoMemSetZero(ptr, nbytes); return; } - // handle general aggregate case - else if (DtoIsPassedByRef(valtype)) + + // if not a zero initializer, call the appropriate runtime function! + switch (t->ty) { + case Tbool: + funcname = "_d_array_init_i1"; + break; + + case Tvoid: + case Tchar: + case Tint8: + case Tuns8: + funcname = "_d_array_init_i8"; + break; + + case Twchar: + case Tint16: + case Tuns16: + funcname = "_d_array_init_i16"; + break; + + case Tdchar: + case Tint32: + case Tuns32: + funcname = "_d_array_init_i32"; + break; + + case Tint64: + case Tuns64: + funcname = "_d_array_init_i64"; + break; + + case Tfloat32: + case Timaginary32: + funcname = "_d_array_init_float"; + break; + + case Tfloat64: + case Timaginary64: + funcname = "_d_array_init_double"; + break; + + case Tfloat80: + case Timaginary80: + funcname = "_d_array_init_real"; + break; + + case Tpointer: + case Tclass: + funcname = "_d_array_init_pointer"; + args[0] = DtoBitCast(args[0], getPtrToType(getVoidPtrType())); + args[2] = DtoBitCast(args[2], getVoidPtrType()); + break; + + // this currently acts as a kind of fallback for all the bastards... + // FIXME: this is probably too slow. + case Tstruct: + case Tdelegate: + case Tarray: + case Tsarray: + case Tcomplex32: + case Tcomplex64: + case Tcomplex80: funcname = "_d_array_init_mem"; + args[0] = DtoBitCast(args[0], getVoidPtrType()); + args[2] = DtoBitCast(args[2], getVoidPtrType()); + args.push_back(DtoConstSize_t(getABITypeSize(DtoType(t)))); + break; - args[0] = gIR->ir->CreateBitCast(ptr, getVoidPtrType(), "tmp"); - args[2] = gIR->ir->CreateBitCast(val, getVoidPtrType(), "tmp"); - - aggrsz = getABITypeSize(pt); - args.push_back(DtoConstSize_t(aggrsz)); - } - else - { - Logger::cout() << *ptr->getType() << " = " << *val->getType() << '\n'; - assert(0); + default: + error("unhandled array init: %s = %s", array->getType()->toChars(), value->getType()->toChars()); + assert(0 && "unhandled array init"); } LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, funcname); diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index ff460fd9..f47e0232 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -3,6 +3,7 @@ #include "mars.h" #include "init.h" +#include "id.h" #include "gen/tollvm.h" #include "gen/llvmhelpers.h" @@ -465,6 +466,16 @@ LLValue* DtoNestedVariable(VarDeclaration* vd) LLValue* ptr = DtoNestedContext(func); assert(ptr && "nested var, but no context"); + // if the nested var is a this pointer it's a class member and not a magic struct + // so we're done here! + // this happens since 1.033 for some reason... always correct ? + if (vd->ident == Id::This) + { + return ptr; + } + + // handle a "normal" nested variable + // we must cast here to be sure. nested classes just have a void* ptr = DtoBitCast(ptr, func->ir.irFunc->nestedVar->getType()); diff --git a/gen/runtime.cpp b/gen/runtime.cpp index 29113154..3195ba0e 100644 --- a/gen/runtime.cpp +++ b/gen/runtime.cpp @@ -194,6 +194,7 @@ static void LLVM_D_BuildRuntimeModule() const LLType* longTy = LLType::Int64Ty; const LLType* floatTy = LLType::FloatTy; const LLType* doubleTy = LLType::DoubleTy; + const LLType* realTy = (global.params.useFP80) ? LLType::X86_FP80Ty : LLType::DoubleTy; const LLType* sizeTy = DtoSize_t(); const LLType* voidPtrTy = rt_ptr(byteTy); const LLType* stringTy = rt_array(byteTy); @@ -361,6 +362,7 @@ static void LLVM_D_BuildRuntimeModule() ARRAY_INIT(longTy,"i64") ARRAY_INIT(floatTy,"float") ARRAY_INIT(doubleTy,"double") + ARRAY_INIT(realTy,"real") ARRAY_INIT(voidPtrTy,"pointer") #undef ARRAY_INIT diff --git a/gen/toir.cpp b/gen/toir.cpp index e18d3f06..5bb1a85d 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -234,7 +234,12 @@ DValue* VarExp::toElem(IRState* p) // function parameter else if (vd->isParameter()) { Logger::println("function param"); - if (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type) || llvm::isa(vd->ir.getIrValue())) { + FuncDeclaration* fd = vd->toParent2()->isFuncDeclaration(); + if (fd && fd != p->func()->decl) { + Logger::println("nested parameter"); + return new DVarValue(vd, DtoNestedVariable(vd), true); + } + else if (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type) || llvm::isa(vd->ir.getIrValue())) { return new DVarValue(vd, vd->ir.getIrValue(), true); } else if (llvm::isa(vd->ir.getIrValue())) { @@ -1543,7 +1548,19 @@ DValue* SliceExp::toElem(IRState* p) else { assert(e1->type->toBasetype()->ty != Tpointer); - elen = DtoArrayLen(e); + // if the sliceee is a static array, we use the length of that as DMD seems + // to give contrary inconsistent sizesin some multidimensional static array cases. + // (namely default initialization, int[16][16] arr; -> int[256] arr = 0;) + if (etype->ty == Tsarray) + { + TypeSArray* tsa = (TypeSArray*)etype; + elen = DtoConstSize_t(tsa->dim->toUInteger()); + } + // for normal code the actual array length is what we want! + else + { + elen = DtoArrayLen(e); + } } return new DSliceValue(type, elen, eptr); diff --git a/tango/lib/compiler/llvmdc/arrays.d b/tango/lib/compiler/llvmdc/arrays.d index 198b60bd..b9b2b65a 100644 --- a/tango/lib/compiler/llvmdc/arrays.d +++ b/tango/lib/compiler/llvmdc/arrays.d @@ -68,6 +68,14 @@ void _d_array_init_double(double* a, size_t n, double v) *p++ = v; } +void _d_array_init_real(real* a, size_t n, real v) +{ + auto p = a; + auto end = a+n; + while (p !is end) + *p++ = v; +} + void _d_array_init_pointer(void** a, size_t n, void* v) { auto p = a; diff --git a/test/multiarr1.d b/test/multiarr1.d index 90fabffe..9258ef19 100644 --- a/test/multiarr1.d +++ b/test/multiarr1.d @@ -3,9 +3,16 @@ module multiarr1; void main() { int[16][16] a; + assert(a[0][0] == 0); + assert(a[0][1] == 0); + assert(a[0][2] == 0); + assert(a[0][3] == 0); + assert(a[10][13] == 0); + assert(a[15][15] == 0); a[10][13] = 42; - //assert(a[0][0] == 0); - //assert(a[10][13] == 42); + assert(a[0][0] == 0); + assert(a[10][13] == 42); + assert(a[15][15] == 0); { int* l = cast(int*)a; l += 10*16+13; diff --git a/test/staticarrays.d b/test/staticarrays.d index 5de4decd..1d76c99d 100644 --- a/test/staticarrays.d +++ b/test/staticarrays.d @@ -65,8 +65,14 @@ void refs() } } +void vals() +{ + S[5] structs; +} + void main() { numbers(); refs(); + vals(); }