diff --git a/gen/arrays.cpp b/gen/arrays.cpp index 48bf9a21..f18ac8e7 100644 --- a/gen/arrays.cpp +++ b/gen/arrays.cpp @@ -106,64 +106,20 @@ void DtoArrayInit(Loc& loc, DValue* array, DValue* value, int op) LOG_SCOPE; #if DMDV2 - if (op != -1 && op != TOKblit && arrayNeedsPostblit(array->type)) { DtoArraySetAssign(loc, array, value, op); return; } - - LLValue* ptr = DtoArrayPtr(array); - LLValue* dim; - if (array->type->ty == Tsarray) { - // Calculate length of the static array - LLValue* rv = array->getRVal(); - const LLArrayType* t = isaArray(rv->getType()->getContainedType(0)); - uint64_t c = t->getNumElements(); - while (t = isaArray(t->getContainedType(0))) - c *= t->getNumElements(); - assert(c > 0); - dim = DtoConstSize_t(c); - ptr = DtoBitCast(ptr, DtoType(DtoArrayElementType(array->type)->pointerTo())); - } else { - dim = DtoArrayLen(array); - } - -#else // DMDV1 +#endif LLValue* dim = DtoArrayLen(array); LLValue* ptr = DtoArrayPtr(array); - -#endif - - LLValue* val; - - // give slices and complex values storage (and thus an address to pass) - if (value->isSlice() || value->type->ty == Tdelegate) - { - val = DtoAlloca(value->getType(), ".tmpparam"); - DVarValue lval(value->getType(), val); - DtoAssign(loc, &lval, value); - } - else - { - val = value->getRVal(); - } - assert(val); - - // prepare runtime call - LLSmallVector args; - args.push_back(ptr); - args.push_back(dim); - args.push_back(val); - - // determine the right runtime function to call - const char* funcname = NULL; Type* arrayelemty = array->getType()->nextOf()->toBasetype(); - Type* valuety = value->getType()->toBasetype(); // lets first optimize all zero initializations down to a memset. // this simplifies codegen later on as llvm null's have no address! + LLValue *val = value->getRVal(); if (isaConstant(val) && isaConstant(val)->isNullValue()) { size_t X = getTypePaddedSize(val->getType()); @@ -172,103 +128,48 @@ void DtoArrayInit(Loc& loc, DValue* array, DValue* value, int op) return; } - // if not a zero initializer, call the appropriate runtime function! - switch (valuety->ty) - { - case Tbool: - val = gIR->ir->CreateZExt(val, LLType::getInt8Ty(gIR->context()), ".bool"); - // fall through + // create blocks + llvm::BasicBlock* oldend = gIR->scopeend(); + llvm::BasicBlock* condbb = llvm::BasicBlock::Create(gIR->context(), "arrayinit.cond", + gIR->topfunc(), oldend); + llvm::BasicBlock* bodybb = llvm::BasicBlock::Create(gIR->context(), "arrayinit.body", + gIR->topfunc(), oldend); + llvm::BasicBlock* endbb = llvm::BasicBlock::Create(gIR->context(), "arrayinit.end", + gIR->topfunc(), oldend); - case Tvoid: - case Tchar: - case Tint8: - case Tuns8: - Logger::println("Using memset for array init"); - DtoMemSet(ptr, val, dim); - return; + // initialize iterator + LLValue *itr = DtoAlloca(Type::tsize_t, "arrayinit.itr"); + DtoStore(DtoConstSize_t(0), itr); - case Twchar: - case Tint16: - case Tuns16: - funcname = "_d_array_init_i16"; - break; + // move into the for condition block, ie. start the loop + assert(!gIR->scopereturned()); + llvm::BranchInst::Create(condbb, gIR->scopebb()); - case Tdchar: - case Tint32: - case Tuns32: - funcname = "_d_array_init_i32"; - break; + // replace current scope + gIR->scope() = IRScope(condbb,bodybb); - case Tint64: - case Tuns64: - funcname = "_d_array_init_i64"; - break; + // create the condition + LLValue* cond_val = gIR->ir->CreateICmpNE(DtoLoad(itr), dim, "arrayinit.condition"); - case Tfloat32: - case Timaginary32: - funcname = "_d_array_init_float"; - break; + // conditional branch + assert(!gIR->scopereturned()); + llvm::BranchInst::Create(bodybb, endbb, cond_val, gIR->scopebb()); - case Tfloat64: - case Timaginary64: - funcname = "_d_array_init_double"; - break; + // rewrite scope + gIR->scope() = IRScope(bodybb, endbb); - case Tfloat80: - case Timaginary80: - funcname = "_d_array_init_real"; - break; + // assign array element value + DValue *arrayelem = new DVarValue(arrayelemty, DtoGEP1(ptr, DtoLoad(itr), "arrayinit.arrayelem")); + DtoAssign(loc, arrayelem, value, op); - case Tcomplex32: - funcname = "_d_array_init_cfloat"; - break; + // increment iterator + DtoStore(gIR->ir->CreateAdd(DtoLoad(itr), DtoConstSize_t(1), "arrayinit.new_itr"), itr); - case Tcomplex64: - funcname = "_d_array_init_cdouble"; - break; + // loop + llvm::BranchInst::Create(condbb, gIR->scopebb()); - case Tcomplex80: - funcname = "_d_array_init_creal"; - 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: - funcname = "_d_array_init_mem"; - assert(arrayelemty == valuety && "ArrayInit doesn't work on elem-initialized static arrays"); - args[0] = DtoBitCast(args[0], getVoidPtrType()); - args[2] = DtoBitCast(args[2], getVoidPtrType()); - args.push_back(DtoConstSize_t(getTypePaddedSize(DtoTypeNotVoid(arrayelemty)))); - break; - - default: - error("unhandled array init: %s = %s", array->getType()->toChars(), value->getType()->toChars()); - assert(0 && "unhandled array init"); - } - - if (Logger::enabled()) - { - Logger::cout() << "ptr = " << *args[0] << std::endl; - Logger::cout() << "dim = " << *args[1] << std::endl; - Logger::cout() << "val = " << *args[2] << std::endl; - } - - LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, funcname); - assert(fn); - if (Logger::enabled()) - Logger::cout() << "calling array init function: " << *fn <<'\n'; - LLCallSite call = gIR->CreateCallOrInvoke(fn, args.begin(), args.end()); - call.setCallingConv(llvm::CallingConv::C); + // rewrite the scope + gIR->scope() = IRScope(endbb, oldend); } ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/gen/runtime.cpp b/gen/runtime.cpp index 0ad25f6c..7c3ff780 100644 --- a/gen/runtime.cpp +++ b/gen/runtime.cpp @@ -534,39 +534,10 @@ static void LLVM_D_BuildRuntimeModule() ///////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////// - #define ARRAY_INIT(TY,suffix) \ - { \ - std::string fname = (llvm::StringRef("_d_array_init_") + llvm::StringRef(suffix)).str(); \ - std::vector types; \ - types.push_back(rt_ptr(TY)); \ - types.push_back(sizeTy); \ - types.push_back(TY); \ - const llvm::FunctionType* fty = llvm::FunctionType::get(voidTy, types, false); \ - llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M) \ - ->setAttributes(Attr_1_NoCapture); \ - } - - ARRAY_INIT(shortTy,"i16") - ARRAY_INIT(intTy,"i32") - ARRAY_INIT(longTy,"i64") - ARRAY_INIT(floatTy,"float") - ARRAY_INIT(doubleTy,"double") - ARRAY_INIT(realTy,"real") - ARRAY_INIT(cfloatTy,"cfloat") - ARRAY_INIT(cdoubleTy,"cdouble") - ARRAY_INIT(crealTy,"creal") - ARRAY_INIT(voidPtrTy,"pointer") - - #undef ARRAY_INIT - - // array init mem - // void _d_array_init_mem(void* a, size_t na, void* v, size_t nv) - // + // array slice copy when assertions are on! // void _d_array_slice_copy(void* dst, size_t dstlen, void* src, size_t srclen) { - llvm::StringRef fname("_d_array_init_mem"); - llvm::StringRef fname2("_d_array_slice_copy"); + llvm::StringRef fname("_d_array_slice_copy"); std::vector types; types.push_back(voidPtrTy); types.push_back(sizeTy); @@ -575,8 +546,6 @@ static void LLVM_D_BuildRuntimeModule() const llvm::FunctionType* fty = llvm::FunctionType::get(voidTy, types, false); llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M) ->setAttributes(Attr_1_3_NoCapture); - llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname2, M) - ->setAttributes(Attr_1_3_NoCapture); } /////////////////////////////////////////////////////////////////////////////////////