diff --git a/dmd/mtype.c b/dmd/mtype.c index 577fef43..19683448 100644 --- a/dmd/mtype.c +++ b/dmd/mtype.c @@ -1515,6 +1515,7 @@ Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident) nm = name[n->ty == Twchar]; fd = FuncDeclaration::genCfunc(Type::tindex, nm); fd->llvmRunTimeHack = true; + ((TypeFunction*)fd->type)->llvmRetInPtr = true; ec = new VarExp(0, fd); e = e->castTo(sc, n->arrayOf()); // convert to dynamic array arguments = new Expressions(); @@ -1533,6 +1534,7 @@ Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident) nm = name[n->ty == Twchar]; fd = FuncDeclaration::genCfunc(Type::tindex, nm); fd->llvmRunTimeHack = true; + ((TypeFunction*)fd->type)->llvmRetInPtr = true; ec = new VarExp(0, fd); e = e->castTo(sc, n->arrayOf()); // convert to dynamic array arguments = new Expressions(); @@ -1551,6 +1553,8 @@ Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident) assert(size); dup = (ident == Id::dup); fd = FuncDeclaration::genCfunc(Type::tindex, dup ? Id::adDup : Id::adReverse); + fd->llvmRunTimeHack = true; + ((TypeFunction*)fd->type)->llvmRetInPtr = true; ec = new VarExp(0, fd); e = e->castTo(sc, n->arrayOf()); // convert to dynamic array arguments = new Expressions(); @@ -1571,6 +1575,7 @@ Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident) fd = FuncDeclaration::genCfunc(tint32->arrayOf(), (char*)(n->ty == Tbit ? "_adSortBit" : "_adSort")); fd->llvmRunTimeHack = true; + ((TypeFunction*)fd->type)->llvmRetInPtr = true; ec = new VarExp(0, fd); e = e->castTo(sc, n->arrayOf()); // convert to dynamic array arguments = new Expressions(); diff --git a/gen/aa.cpp b/gen/aa.cpp new file mode 100644 index 00000000..3bffeb60 --- /dev/null +++ b/gen/aa.cpp @@ -0,0 +1,153 @@ +#include "gen/llvm.h" + +#include "mtype.h" +#include "declaration.h" +#include "aggregate.h" + +#include "gen/aa.h" +#include "gen/runtime.h" +#include "gen/tollvm.h" +#include "gen/logger.h" +#include "gen/irstate.h" +#include "gen/dvalue.h" + +// makes sure the key value lives in memory so it can be passed to the runtime functions without problems +// returns the pointer +static llvm::Value* to_pkey(DValue* key) +{ + Type* keytype = key->getType(); + bool needmem = !DtoIsPassedByRef(keytype); + llvm::Value* pkey; + if (key->isIm()) { + pkey = key->getRVal(); + } + else if (DVarValue* var = key->isVar()) { + if (var->lval) { + pkey = key->getLVal(); + needmem = false; + } + else { + pkey = key->getRVal(); + } + } + else if (key->isConst()) { + needmem = true; + pkey = key->getRVal(); + } + else { + assert(0); + } + + // give memory + if (needmem) { + llvm::Value* tmp = new llvm::AllocaInst(DtoType(keytype), "aatmpkeystorage", gIR->topallocapoint()); + DtoStore(pkey, tmp); + pkey = tmp; + } + + return pkey; +} + +///////////////////////////////////////////////////////////////////////////////////// + +DValue* DtoAAIndex(Type* type, DValue* aa, DValue* key) +{ + // call: + // extern(C) void* _aaGet(AA* aa, TypeInfo keyti, void* pkey, size_t valuesize) + + // first get the runtime function + llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_aaGet"); + const llvm::FunctionType* funcTy = func->getFunctionType(); + + // aa param + llvm::Value* aaval = aa->getLVal(); + aaval = DtoBitCast(aaval, funcTy->getParamType(0)); + + // keyti param + Type* keytype = key->getType(); + keytype->getTypeInfo(NULL); + TypeInfoDeclaration* tid = keytype->getTypeInfoDeclaration(); + assert(tid); + DtoResolveDsymbol(Type::typeinfo); + DtoForceDeclareDsymbol(tid); + assert(tid->llvmValue); + llvm::Value* keyti = tid->llvmValue; + keyti = DtoBitCast(keyti, funcTy->getParamType(1)); + + // pkey param + llvm::Value* pkey = to_pkey(key); + pkey = DtoBitCast(pkey, funcTy->getParamType(2)); + + // valuesize param + llvm::Value* valsize = DtoConstSize_t(gTargetData->getTypeSize(DtoType(type))); + + // build arg vector + std::vector args; + args.push_back(aaval); + args.push_back(keyti); + args.push_back(pkey); + args.push_back(valsize); + + // call runtime + llvm::Value* ret = gIR->ir->CreateCall(func, args.begin(), args.end(), "aaGet"); + + // cast return value + const llvm::Type* targettype = llvm::PointerType::get(DtoType(type)); + if (ret->getType() != targettype) + ret = DtoBitCast(ret, targettype); + + return new DVarValue(type, ret, true); +} + +///////////////////////////////////////////////////////////////////////////////////// + +DValue* DtoAAIn(Type* type, DValue* aa, DValue* key) +{ + // call: + // extern(C) void* _aaIn(AA aa*, TypeInfo keyti, void* pkey) + + // first get the runtime function + llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_aaIn"); + const llvm::FunctionType* funcTy = func->getFunctionType(); + + Logger::cout() << "_aaIn = " << *func << '\n'; + + // aa param + llvm::Value* aaval = aa->getRVal(); + Logger::cout() << "aaval: " << *aaval << '\n'; + Logger::cout() << "totype: " << *funcTy->getParamType(0) << '\n'; + aaval = DtoBitCast(aaval, funcTy->getParamType(0)); + + // keyti param + Type* keytype = key->getType(); + keytype->getTypeInfo(NULL); + TypeInfoDeclaration* tid = keytype->getTypeInfoDeclaration(); + assert(tid); + DtoResolveDsymbol(Type::typeinfo); + DtoForceDeclareDsymbol(tid); + assert(tid->llvmValue); + llvm::Value* keyti = tid->llvmValue; + keyti = DtoBitCast(keyti, funcTy->getParamType(1)); + + // pkey param + llvm::Value* pkey = to_pkey(key); + pkey = DtoBitCast(pkey, funcTy->getParamType(2)); + + // build arg vector + std::vector args; + args.push_back(aaval); + args.push_back(keyti); + args.push_back(pkey); + + // call runtime + llvm::Value* ret = gIR->ir->CreateCall(func, args.begin(), args.end(), "aaIn"); + + // cast return value + const llvm::Type* targettype = DtoType(type); + if (ret->getType() != targettype) + ret = DtoBitCast(ret, targettype); + + return new DImValue(type, ret); +} + +///////////////////////////////////////////////////////////////////////////////////// diff --git a/gen/aa.h b/gen/aa.h new file mode 100644 index 00000000..49d22794 --- /dev/null +++ b/gen/aa.h @@ -0,0 +1,7 @@ +#ifndef LLVMDC_GEN_AA_H +#define LLVMDC_GEN_AA_H + +DValue* DtoAAIndex(Type* type, DValue* aa, DValue* key); +DValue* DtoAAIn(Type* type, DValue* aa, DValue* key); + +#endif // LLVMDC_GEN_AA_H diff --git a/gen/arrays.cpp b/gen/arrays.cpp index e94143ab..0e1d554d 100644 --- a/gen/arrays.cpp +++ b/gen/arrays.cpp @@ -151,11 +151,11 @@ static size_t checkRectArrayInit(const llvm::Type* pt, constLLVMTypeP& finalty) void DtoArrayInit(llvm::Value* ptr, llvm::Value* dim, llvm::Value* val) { - Logger::println("HELLO"); Logger::cout() << "array: " << *ptr << " dim: " << *dim << " val: " << *val << '\n'; const llvm::Type* pt = ptr->getType()->getContainedType(0); const llvm::Type* t = val->getType(); const llvm::Type* finalTy; + size_t aggrsz = 0; if (size_t arrsz = checkRectArrayInit(pt, finalTy)) { assert(finalTy == t); llvm::Constant* c = isaConstant(dim); @@ -164,12 +164,27 @@ void DtoArrayInit(llvm::Value* ptr, llvm::Value* dim, llvm::Value* val) ptr = gIR->ir->CreateBitCast(ptr, llvm::PointerType::get(finalTy), "tmp"); } else if (isaStruct(t)) { - assert(0); + aggrsz = gTargetData->getTypeSize(t); + llvm::Constant* c = isaConstant(val); + if (c && c->isNullValue()) { + llvm::Value* nbytes; + if (aggrsz == 1) + nbytes = dim; + else + nbytes = gIR->ir->CreateMul(dim, DtoConstSize_t(aggrsz), "tmp"); + DtoMemSetZero(ptr,nbytes); + return; + } + else { + ptr = gIR->ir->CreateBitCast(ptr, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp"); + } } else { assert(t == pt); } + Logger::cout() << "array: " << *ptr << " dim: " << *dim << " val: " << *val << '\n'; + std::vector args; args.push_back(ptr); args.push_back(dim); @@ -177,7 +192,11 @@ void DtoArrayInit(llvm::Value* ptr, llvm::Value* dim, llvm::Value* val) const char* funcname = NULL; - if (isaPointer(t)) { + if (aggrsz) { + funcname = "_d_array_init_mem"; + args.push_back(DtoConstSize_t(aggrsz)); + } + else if (isaPointer(t)) { funcname = "_d_array_init_pointer"; const llvm::Type* dstty = llvm::PointerType::get(llvm::PointerType::get(llvm::Type::Int8Ty)); diff --git a/gen/functions.cpp b/gen/functions.cpp index 0b6d6eba..0c06a97b 100644 --- a/gen/functions.cpp +++ b/gen/functions.cpp @@ -44,6 +44,7 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const llvm::Type* thistype } else { assert(rt); + Type* rtfin = DtoDType(rt); if (DtoIsPassedByRef(rt)) { rettype = llvm::PointerType::get(DtoType(rt)); actualRettype = llvm::Type::VoidTy; diff --git a/gen/statements.cpp b/gen/statements.cpp index 992c904f..400126e6 100644 --- a/gen/statements.cpp +++ b/gen/statements.cpp @@ -128,8 +128,8 @@ void ExpStatement::toIR(IRState* p) Logger::println("ExpStatement::toIR(%d): %s", esi++, toChars()); LOG_SCOPE; -// if (global.params.symdebug) -// DtoDwarfStopPoint(loc.linnum); + if (global.params.symdebug) + DtoDwarfStopPoint(loc.linnum); if (exp != 0) { elem* e = exp->toElem(p); @@ -731,6 +731,18 @@ void ForeachStatement::toIR(IRState* p) assert(0 && "aggregate type is not Tarray or Tsarray"); } + if (niters->getType() != keytype) + { + size_t sz1 = gTargetData->getTypeSize(niters->getType()); + size_t sz2 = gTargetData->getTypeSize(keytype); + if (sz1 < sz2) + niters = gIR->ir->CreateZExt(niters, keytype, "foreachtrunckey"); + else if (sz1 > sz2) + niters = gIR->ir->CreateTrunc(niters, keytype, "foreachtrunckey"); + else + niters = gIR->ir->CreateBitCast(niters, keytype, "foreachtrunckey"); + } + llvm::Constant* delta = 0; if (op == TOKforeach) { new llvm::StoreInst(zerokey, keyvar, p->scopebb()); diff --git a/gen/toir.cpp b/gen/toir.cpp index e93e9977..e9b3679e 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -30,6 +30,7 @@ #include "gen/typeinf.h" #include "gen/complex.h" #include "gen/dvalue.h" +#include "gen/aa.h" ////////////////////////////////////////////////////////////////////////////////////////// @@ -66,6 +67,7 @@ DValue* DeclarationExp::toElem(IRState* p) //allocainst->setAlignment(vd->type->alignsize()); // TODO vd->llvmValue = allocainst; } + Logger::cout() << "llvm value for decl: " << *vd->llvmValue << '\n'; DValue* ie = DtoInitializer(vd->init); } @@ -409,8 +411,13 @@ DValue* StringExp::toElem(IRState* p) else if (p->topexp()->e2 == this) { DValue* arr = p->topexp()->v; assert(arr); - DtoSetArray(arr->getLVal(), clen, arrptr); - return new DImValue(type, arr->getLVal(), true); + if (arr->isSlice()) { + return new DSliceValue(type, clen, arrptr); + } + else { + DtoSetArray(arr->getRVal(), clen, arrptr); + return new DImValue(type, arr->getLVal(), true); + } } assert(0); } @@ -490,7 +497,14 @@ DValue* AssignExp::toElem(IRState* p) if (l->isSlice() || l->isComplex()) return l; - return new DImValue(type, l->getRVal()); + + llvm::Value* v; + if (l->isVar() && l->isVar()->lval) + v = l->getLVal(); + else + v = l->getRVal(); + + return new DVarValue(type, v, true); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -893,15 +907,26 @@ DValue* CallExp::toElem(IRState* p) llvm::Value* tlv = topexp->v->getLVal(); assert(isaStruct(tlv->getType()->getContainedType(0))); llargs[j] = tlv; - if (DtoIsPassedByRef(tf->next)) { + isInPlace = true; + /*if (DtoIsPassedByRef(tf->next)) { isInPlace = true; } else - assert(0); + assert(0);*/ } else { llargs[j] = new llvm::AllocaInst(argiter->get()->getContainedType(0),"rettmp",p->topallocapoint()); } + + if (dfn && dfn->func && dfn->func->llvmRunTimeHack) { + const llvm::Type* rettype = llvm::PointerType::get(DtoType(type)); + if (llargs[j]->getType() != llfnty->getParamType(j)) { + Logger::println("llvmRunTimeHack==true - force casting return value param"); + Logger::cout() << "casting: " << *llargs[j] << " to type: " << *llfnty->getParamType(j) << '\n'; + llargs[j] = DtoBitCast(llargs[j], llfnty->getParamType(j)); + } + } + ++j; ++argiter; } @@ -1004,10 +1029,12 @@ DValue* CallExp::toElem(IRState* p) llargs[j] = DtoArgument(llfnty->getParamType(j), fnarg, (Expression*)arguments->data[i]); // this hack is necessary :/ if (dfn && dfn->func && dfn->func->llvmRunTimeHack) { - Logger::println("llvmRunTimeHack==true - force casting argument"); - if (llargs[j]->getType() != llfnty->getParamType(j)) { - Logger::cout() << "from: " << *llargs[j]->getType() << " to: " << *llfnty->getParamType(j); - llargs[j] = DtoBitCast(llargs[j], llfnty->getParamType(j)); + if (llfnty->getParamType(j) != NULL) { + if (llargs[j]->getType() != llfnty->getParamType(j)) { + Logger::println("llvmRunTimeHack==true - force casting argument"); + Logger::cout() << "casting: " << *llargs[j] << " to type: " << *llfnty->getParamType(j) << '\n'; + llargs[j] = DtoBitCast(llargs[j], llfnty->getParamType(j)); + } } } } @@ -1024,12 +1051,21 @@ DValue* CallExp::toElem(IRState* p) if (llfnty->getReturnType() != llvm::Type::VoidTy) varname = "tmp"; - Logger::cout() << "Calling: " << *funcval->getType() << '\n'; + Logger::cout() << "Calling: " << *funcval << '\n'; // call the function llvm::CallInst* call = new llvm::CallInst(funcval, llargs.begin(), llargs.end(), varname, p->scopebb()); llvm::Value* retllval = (retinptr) ? llargs[0] : call; + if (retinptr && dfn && dfn->func && dfn->func->llvmRunTimeHack) { + const llvm::Type* rettype = llvm::PointerType::get(DtoType(type)); + if (retllval->getType() != rettype) { + Logger::println("llvmRunTimeHack==true - force casting return value"); + Logger::cout() << "from: " << *retllval->getType() << " to: " << *rettype << '\n'; + retllval = DtoBitCast(retllval, rettype); + } + } + // set calling convention if (dfn && dfn->func) { int li = dfn->func->llvmInternal; @@ -1328,7 +1364,13 @@ DValue* IndexExp::toElem(IRState* p) arrptr = new llvm::LoadInst(arrptr,"tmp",p->scopebb()); arrptr = new llvm::GetElementPtrInst(arrptr,r->getRVal(),"tmp",p->scopebb()); } - assert(arrptr); + else if (e1type->ty == Taarray) { + return DtoAAIndex(type, l, r); + } + else { + Logger::println("invalid index exp! e1type: %s", e1type->toChars()); + assert(0); + } return new DVarValue(type, arrptr, true); } @@ -2452,11 +2494,24 @@ llvm::Constant* StructLiteralExp::toConstElem(IRState* p) ////////////////////////////////////////////////////////////////////////////////////////// +DValue* InExp::toElem(IRState* p) +{ + Logger::print("InExp::toElem: %s | %s\n", toChars(), type->toChars()); + LOG_SCOPE; + + DValue* key = e1->toElem(p); + DValue* aa = e2->toElem(p); + + return DtoAAIn(type, aa, key); +} + +////////////////////////////////////////////////////////////////////////////////////////// + #define STUB(x) DValue *x::toElem(IRState * p) {error("Exp type "#x" not implemented: %s", toChars()); fatal(); return 0; } //STUB(IdentityExp); //STUB(CondExp); //STUB(EqualExp); -STUB(InExp); +//STUB(InExp); //STUB(CmpExp); //STUB(AndAndExp); //STUB(OrOrExp); diff --git a/gen/tollvm.cpp b/gen/tollvm.cpp index d80699be..5998f93a 100644 --- a/gen/tollvm.cpp +++ b/gen/tollvm.cpp @@ -177,8 +177,11 @@ const llvm::Type* DtoType(Type* t) // associative arrays case Taarray: { - // TODO this is a kludge - return llvm::PointerType::get(llvm::Type::Int8Ty); + TypeAArray* taa = (TypeAArray*)t; + std::vector types; + types.push_back(DtoType(taa->key)); + types.push_back(DtoType(taa->next)); + return llvm::PointerType::get(llvm::StructType::get(types)); } default: @@ -1236,6 +1239,32 @@ llvm::Constant* DtoConstNullPtr(const llvm::Type* t) ////////////////////////////////////////////////////////////////////////////////////////// +void DtoMemSetZero(llvm::Value* dst, llvm::Value* nbytes) +{ + llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty); + llvm::Value *dstarr; + if (dst->getType() == arrty) + { + dstarr = dst; + } + else + { + dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb()); + } + + llvm::Function* fn = (global.params.is64bit) ? LLVM_DeclareMemSet64() : LLVM_DeclareMemSet32(); + std::vector llargs; + llargs.resize(4); + llargs[0] = dstarr; + llargs[1] = llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false); + llargs[2] = nbytes; + llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); + + new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb()); +} + +////////////////////////////////////////////////////////////////////////////////////////// + void DtoMemCpy(llvm::Value* dst, llvm::Value* src, llvm::Value* nbytes) { assert(dst->getType() == src->getType()); diff --git a/gen/tollvm.h b/gen/tollvm.h index 01d1d642..baefdafa 100644 --- a/gen/tollvm.h +++ b/gen/tollvm.h @@ -74,6 +74,7 @@ void DtoForceConstInitDsymbol(Dsymbol* dsym); void DtoForceDefineDsymbol(Dsymbol* dsym); // llvm wrappers +void DtoMemSetZero(llvm::Value* dst, llvm::Value* nbytes); void DtoMemCpy(llvm::Value* dst, llvm::Value* src, llvm::Value* nbytes); bool DtoCanLoad(llvm::Value* ptr); llvm::Value* DtoLoad(llvm::Value* src); diff --git a/gen/typinf.cpp b/gen/typinf.cpp index c8677fef..b427151c 100644 --- a/gen/typinf.cpp +++ b/gen/typinf.cpp @@ -654,33 +654,69 @@ void TypeInfoStaticArrayDeclaration::toDt(dt_t **pdt) void TypeInfoAssociativeArrayDeclaration::llvmDeclare() { - assert(0 && "TypeInfoAssociativeArrayDeclaration"); + Logger::println("TypeInfoAssociativeArrayDeclaration::toDt() %s", toChars()); + LOG_SCOPE; + + // init typeinfo class + ClassDeclaration* base = Type::typeinfoassociativearray; + DtoResolveClass(base); + + // get type of typeinfo class + const llvm::StructType* stype = isaStruct(base->type->llvmType->get()); + + // create the symbol + llvmValue = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,NULL,toChars(),gIR->module); } void TypeInfoAssociativeArrayDeclaration::llvmDefine() { - assert(0 && "TypeInfoAssociativeArrayDeclaration"); + Logger::println("TypeInfoAssociativeArrayDeclaration::toDt() %s", toChars()); + LOG_SCOPE; + + // init typeinfo class + ClassDeclaration* base = Type::typeinfoassociativearray; + DtoForceConstInitDsymbol(base); + + // get type of typeinfo class + const llvm::StructType* stype = isaStruct(base->type->llvmType->get()); + + // initializer vector + std::vector sinits; + // first is always the vtable + sinits.push_back(base->llvmVtbl); + + // get type + assert(tinfo->ty == Taarray); + TypeAArray *tc = (TypeAArray *)tinfo; + + // value typeinfo + tc->next->getTypeInfo(NULL); + + // get symbol + assert(tc->next->vtinfo); + DtoForceDeclareDsymbol(tc->next->vtinfo); + llvm::Constant* castbase = isaConstant(tc->next->vtinfo->llvmValue); + castbase = llvm::ConstantExpr::getBitCast(castbase, stype->getElementType(1)); + sinits.push_back(castbase); + + // key typeinfo + tc->index->getTypeInfo(NULL); + + // get symbol + assert(tc->index->vtinfo); + DtoForceDeclareDsymbol(tc->index->vtinfo); + castbase = isaConstant(tc->index->vtinfo->llvmValue); + castbase = llvm::ConstantExpr::getBitCast(castbase, stype->getElementType(2)); + sinits.push_back(castbase); + + // create the symbol + llvm::Constant* tiInit = llvm::ConstantStruct::get(stype, sinits); + isaGlobalVar(llvmValue)->setInitializer(tiInit); } void TypeInfoAssociativeArrayDeclaration::toDt(dt_t **pdt) { - assert(0 && "TypeInfoAssociativeArrayDeclaration"); - - /* - //printf("TypeInfoAssociativeArrayDeclaration::toDt()\n"); - dtxoff(pdt, Type::typeinfoassociativearray->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_AssociativeArray - dtdword(pdt, 0); // monitor - - assert(tinfo->ty == Taarray); - - TypeAArray *tc = (TypeAArray *)tinfo; - - tc->next->getTypeInfo(NULL); - dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for array of type - - tc->index->getTypeInfo(NULL); - dtxoff(pdt, tc->index->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for array of type - */ + assert(0); } /* ========================================================================= */ diff --git a/llvmdc.kdevelop b/llvmdc.kdevelop index aad6bdd4..6e1b8637 100644 --- a/llvmdc.kdevelop +++ b/llvmdc.kdevelop @@ -98,7 +98,7 @@ false - *.bc + *.bc,*.ll false diff --git a/llvmdc.kdevelop.filelist b/llvmdc.kdevelop.filelist index 19774945..316a646b 100644 --- a/llvmdc.kdevelop.filelist +++ b/llvmdc.kdevelop.filelist @@ -100,6 +100,8 @@ dmd/utf.h dmd/version.c dmd/version.h gen +gen/aa.cpp +gen/aa.h gen/arrays.cpp gen/arrays.h gen/binops.cpp @@ -136,6 +138,7 @@ gen/typinf.cpp lphobos lphobos/crc32.d lphobos/gc +lphobos/gc/gcbits.d lphobos/gc/gclinux.d lphobos/gc/gcstub.d lphobos/gcstats.d @@ -145,7 +148,6 @@ lphobos/internal/aApplyR.d lphobos/internal/aaA.d lphobos/internal/adi.d lphobos/internal/arrays.d -lphobos/internal/cmath2.d lphobos/internal/contract.d lphobos/internal/mem.d lphobos/internal/moduleinit.d @@ -232,6 +234,10 @@ runalltests.d test test/a.d test/aa1.d +test/aa2.d +test/aa3.d +test/aa4.d +test/aa5.d test/alignment.d test/alloca1.d test/arrayinit.d @@ -240,6 +246,7 @@ test/arrays10.d test/arrays11.d test/arrays12.d test/arrays13.d +test/arrays14.d test/arrays2.d test/arrays3.d test/arrays4.d @@ -316,6 +323,7 @@ test/bug70.d test/bug71.d test/bug72.d test/bug73.d +test/bug74.d test/bug8.d test/bug9.d test/c.d @@ -418,6 +426,7 @@ test/typeinfo.d test/typeinfo10.d test/typeinfo11.d test/typeinfo12.d +test/typeinfo13.d test/typeinfo2.d test/typeinfo3.d test/typeinfo4.d diff --git a/lphobos/build.sh b/lphobos/build.sh index 2448c4c8..a35ece55 100755 --- a/lphobos/build.sh +++ b/lphobos/build.sh @@ -51,7 +51,8 @@ llvm-link -f -o=../lib/llvmdcore.bc `ls obj/llvm.*.bc` ../lib/llvmdcore.bc || ex echo "compiling garbage collector" llvmdc gc/gclinux.d -c -odobj || exit 1 llvmdc gc/gcstub.d -c -odobj -Igc || exit 1 -llvm-link -f -o=../lib/llvmdcore.bc obj/gclinux.bc obj/gcstub.bc ../lib/llvmdcore.bc || exit 1 +llvmdc gc/gcbits.d -c -odobj -Igc || exit 1 +llvm-link -f -o=../lib/llvmdcore.bc obj/gclinux.bc obj/gcstub.bc obj/gcbits.bc ../lib/llvmdcore.bc || exit 1 echo "compiling phobos" rebuild phobos.d -c -oqobj -dc=llvmdc-posix || exit 1 diff --git a/lphobos/gc/gcbits.d b/lphobos/gc/gcbits.d new file mode 100644 index 00000000..e30b02cb --- /dev/null +++ b/lphobos/gc/gcbits.d @@ -0,0 +1,176 @@ + +// Copyright (C) 2001-2002 by Digital Mars +// All Rights Reserved +// www.digitalmars.com +// Written by Walter Bright + +import std.c.string; +import std.c.stdlib; +import std.outofmemory; +import std.intrinsic; + +//version = Asm86; +version = bitops; + +struct GCBits +{ + const int BITS_PER_WORD = 32; + const int BITS_SHIFT = 5; + const int BITS_MASK = 31; + + uint *data = null; + uint nwords = 0; // allocated words in data[] excluding sentinals + uint nbits = 0; // number of bits in data[] excluding sentinals + + void Dtor() + { + if (data) + { + free(data); + data = null; + } + } + + invariant + { + if (data) + { + assert(nwords * data[0].sizeof * 8 >= nbits); + } + } + + void alloc(uint nbits) + { + this.nbits = nbits; + nwords = (nbits + (BITS_PER_WORD - 1)) >> BITS_SHIFT; + data = cast(uint *)calloc(nwords + 2, uint.sizeof); + if (!data) + _d_OutOfMemory(); + } + + uint test(uint i) + in + { + assert(i < nbits); + } + body + { + //return (cast(bit *)(data + 1))[i]; + return data[1 + (i >> BITS_SHIFT)] & (1 << (i & BITS_MASK)); + } + + void set(uint i) + in + { + assert(i < nbits); + } + body + { + //(cast(bit *)(data + 1))[i] = 1; + data[1 + (i >> BITS_SHIFT)] |= (1 << (i & BITS_MASK)); + } + + void clear(uint i) + in + { + assert(i < nbits); + } + body + { + //(cast(bit *)(data + 1))[i] = 0; + data[1 + (i >> BITS_SHIFT)] &= ~(1 << (i & BITS_MASK)); + } + + uint testClear(uint i) + { + version (bitops) + { + return std.intrinsic.btr(data + 1, i); + } + else version (Asm86) + { + asm + { + naked ; + mov EAX,data[EAX] ; + mov ECX,i-4[ESP] ; + btr 4[EAX],ECX ; + sbb EAX,EAX ; + ret 4 ; + } + } + else + { uint result; + + //result = (cast(bit *)(data + 1))[i]; + //(cast(bit *)(data + 1))[i] = 0; + + uint *p = &data[1 + (i >> BITS_SHIFT)]; + uint mask = (1 << (i & BITS_MASK)); + result = *p & mask; + *p &= ~mask; + return result; + } + } + + void zero() + { + memset(data + 1, 0, nwords * uint.sizeof); + } + + void copy(GCBits *f) + in + { + assert(nwords == f.nwords); + } + body + { + memcpy(data + 1, f.data + 1, nwords * uint.sizeof); + } + + uint *base() + in + { + assert(data); + } + body + { + return data + 1; + } +} + +unittest +{ + GCBits b; + + b.alloc(786); + assert(b.test(123) == 0); + assert(b.testClear(123) == 0); + b.set(123); + assert(b.test(123) != 0); + assert(b.testClear(123) != 0); + assert(b.test(123) == 0); + + b.set(785); + b.set(0); + assert(b.test(785) != 0); + assert(b.test(0) != 0); + b.zero(); + assert(b.test(785) == 0); + assert(b.test(0) == 0); + + GCBits b2; + b2.alloc(786); + b2.set(38); + b.copy(&b2); + assert(b.test(38) != 0); + b2.Dtor(); + + b.Dtor(); +} + +/+ +void main() +{ +} ++/ diff --git a/lphobos/internal/aaA.d b/lphobos/internal/aaA.d index a2a58e38..c0f3962c 100644 --- a/lphobos/internal/aaA.d +++ b/lphobos/internal/aaA.d @@ -27,13 +27,19 @@ * distribution. */ +/* + * Modified for LLVMDC by Tomas Lindquist Olsen. + * The DMD implementation wont quite work due to the differences in how + * structs are handled. + */ + //import std.stdio; import std.c.stdarg; import std.c.stdio; import std.c.stdlib; import std.c.string; -import std.string; +//import std.string; import std.outofmemory; @@ -51,17 +57,17 @@ static size_t[] prime_list = [ /* This is the type of the return value for dynamic arrays. * It should be a type that is returned in registers. - * Although DMD will return types of Array in registers, - * gcc will not, so we instead use a 'long'. */ -alias long ArrayRet_t; +alias Array ArrayRet_t; +pragma(LLVM_internal, "notypeinfo") struct Array { size_t length; void* ptr; } +pragma(LLVM_internal, "notypeinfo") struct aaA { aaA *left; @@ -71,6 +77,7 @@ struct aaA /* value */ } +pragma(LLVM_internal, "notypeinfo") struct BB { aaA*[] b; @@ -81,10 +88,7 @@ struct BB * it is completely opaque. */ -struct AA -{ - BB* a; -} +alias BB* AA; /********************************** * Align to next pointer boundary, so that @@ -198,9 +202,9 @@ size_t _aaLen(AA aa) } } - if (aa.a) + if (aa) { - foreach (e; aa.a.b) + foreach (e; aa.b) { if (e) _aaLen_x(e); @@ -212,7 +216,7 @@ size_t _aaLen(AA aa) } body { - return aa.a ? aa.a.nodes : 0; + return aa ? aa.nodes : 0; } @@ -221,7 +225,7 @@ size_t _aaLen(AA aa) * Add entry for key if it is not already there. */ -void* _aaGet(AA* aa, TypeInfo keyti, size_t valuesize, ...) +void* _aaGet(AA* aa, TypeInfo keyti, void* pkey, size_t valuesize) in { assert(aa); @@ -229,32 +233,32 @@ void* _aaGet(AA* aa, TypeInfo keyti, size_t valuesize, ...) out (result) { assert(result); - assert(aa.a); - assert(aa.a.b.length); - //assert(_aaInAh(*aa.a, key)); + assert(*aa); + assert((*aa).b.length); + //assert(_aaInAh(*aa, key)); } body { - auto pkey = cast(void *)(&valuesize + 1); + //auto pkey = cast(void *)(&valuesize + 1); size_t i; aaA* e; auto keysize = aligntsize(keyti.tsize()); - if (!aa.a) - aa.a = new BB(); + if (!*aa) + *aa = new BB(); - if (!aa.a.b.length) + if (!(*aa).b.length) { alias aaA *pa; auto len = prime_list[0]; - aa.a.b = new pa[len]; + (*aa).b = new pa[len]; } auto key_hash = keyti.getHash(pkey); //printf("hash = %d\n", key_hash); - i = key_hash % aa.a.b.length; - auto pe = &aa.a.b[i]; + i = key_hash % (*aa).b.length; + auto pe = &(*aa).b[i]; while ((e = *pe) != null) { if (key_hash == e.hash) @@ -275,9 +279,9 @@ void* _aaGet(AA* aa, TypeInfo keyti, size_t valuesize, ...) e.hash = key_hash; *pe = e; - auto nodes = ++aa.a.nodes; - //printf("length = %d, nodes = %d\n", (*aa.a).length, nodes); - if (nodes > aa.a.b.length * 4) + auto nodes = ++(*aa).nodes; + //printf("length = %d, nodes = %d\n", (*aa).length, nodes); + if (nodes > (*aa).b.length * 4) { _aaRehash(aa,keyti); } @@ -292,22 +296,22 @@ void* _aaGet(AA* aa, TypeInfo keyti, size_t valuesize, ...) * Returns null if it is not already there. */ -void* _aaGetRvalue(AA aa, TypeInfo keyti, size_t valuesize, ...) +void* _aaGetRvalue(AA aa, TypeInfo keyti, size_t valuesize, void* pkey) { //printf("_aaGetRvalue(valuesize = %u)\n", valuesize); - if (!aa.a) + if (!aa) return null; - auto pkey = cast(void *)(&valuesize + 1); + //auto pkey = cast(void *)(&valuesize + 1); auto keysize = aligntsize(keyti.tsize()); - auto len = aa.a.b.length; + auto len = aa.b.length; if (len) { auto key_hash = keyti.getHash(pkey); //printf("hash = %d\n", key_hash); size_t i = key_hash % len; - auto e = aa.a.b[i]; + auto e = aa.b[i]; while (e != null) { if (key_hash == e.hash) @@ -332,7 +336,7 @@ void* _aaGetRvalue(AA aa, TypeInfo keyti, size_t valuesize, ...) * !=null in aa, return pointer to value */ -void* _aaIn(AA aa, TypeInfo keyti, ...) +void* _aaIn(AA aa, TypeInfo keyti, void* pkey) in { } @@ -342,19 +346,19 @@ void* _aaIn(AA aa, TypeInfo keyti, ...) } body { - if (aa.a) + if (aa) { - auto pkey = cast(void *)(&keyti + 1); + //auto pkey = cast(void *)(&keyti + 1); - //printf("_aaIn(), .length = %d, .ptr = %x\n", aa.a.length, cast(uint)aa.a.ptr); - auto len = aa.a.b.length; + //printf("_aaIn(), .length = %d, .ptr = %x\n", aa.length, cast(uint)aa.ptr); + auto len = aa.b.length; if (len) { auto key_hash = keyti.getHash(pkey); //printf("hash = %d\n", key_hash); size_t i = key_hash % len; - auto e = aa.a.b[i]; + auto e = aa.b[i]; while (e != null) { if (key_hash == e.hash) @@ -380,17 +384,17 @@ void* _aaIn(AA aa, TypeInfo keyti, ...) * If key is not in aa[], do nothing. */ -void _aaDel(AA aa, TypeInfo keyti, ...) +void _aaDel(AA aa, TypeInfo keyti, void* pkey) { - auto pkey = cast(void *)(&keyti + 1); + //auto pkey = cast(void *)(&keyti + 1); aaA* e; - if (aa.a && aa.a.b.length) + if (aa && aa.b.length) { auto key_hash = keyti.getHash(pkey); //printf("hash = %d\n", key_hash); - size_t i = key_hash % aa.a.b.length; - auto pe = &aa.a.b[i]; + size_t i = key_hash % aa.b.length; + auto pe = &aa.b[i]; while ((e = *pe) != null) // null means not found { if (key_hash == e.hash) @@ -423,7 +427,7 @@ void _aaDel(AA aa, TypeInfo keyti, ...) e.right = null; } - aa.a.nodes--; + aa.nodes--; // Should notify GC that e can be free'd now break; @@ -470,19 +474,19 @@ ArrayRet_t _aaValues(AA aa, size_t keysize, size_t valuesize) } while (e != null); } - if (aa.a) + if (aa) { a.length = _aaLen(aa); a.ptr = (new void[a.length * valuesize]).ptr; resi = 0; - foreach (e; aa.a.b) + foreach (e; aa.b) { if (e) _aaValues_x(e); } assert(resi == a.length); } - return *cast(ArrayRet_t*)(&a); + return a; } @@ -493,6 +497,7 @@ ArrayRet_t _aaValues(AA aa, size_t keysize, size_t valuesize) void* _aaRehash(AA* paa, TypeInfo keyti) in { + assert(paa); //_aaInvAh(paa); } out (result) @@ -549,9 +554,9 @@ void* _aaRehash(AA* paa, TypeInfo keyti) } //printf("Rehash\n"); - if (paa.a) + if (paa) { - auto aa = paa.a; + auto aa = *paa; auto len = _aaLen(*paa); if (len) { size_t i; @@ -573,9 +578,9 @@ void* _aaRehash(AA* paa, TypeInfo keyti) newb.nodes = aa.nodes; } - *paa.a = newb; + **paa = newb; } - return (*paa).a; + return *paa; } @@ -607,20 +612,17 @@ ArrayRet_t _aaKeys(AA aa, size_t keysize) auto len = _aaLen(aa); if (!len) - return 0; + return ArrayRet_t.init; res = cast(byte[])new void[len * keysize]; resi = 0; - foreach (e; aa.a.b) + foreach (e; aa.b) { if (e) _aaKeys_x(e); } assert(resi == len); - Array a; - a.length = len; - a.ptr = res.ptr; - return *cast(ArrayRet_t*)(&a); + return Array(len, res.ptr); } @@ -639,7 +641,7 @@ in body { int result; - //printf("_aaApply(aa = x%llx, keysize = %d, dg = x%llx)\n", aa.a, keysize, dg); + //printf("_aaApply(aa = x%llx, keysize = %d, dg = x%llx)\n", aa, keysize, dg); int treewalker(aaA* e) { int result; @@ -666,9 +668,9 @@ body return result; } - if (aa.a) + if (aa) { - foreach (e; aa.a.b) + foreach (e; aa.b) { if (e) { @@ -692,7 +694,7 @@ in body { int result; - //printf("_aaApply(aa = x%llx, keysize = %d, dg = x%llx)\n", aa.a, keysize, dg); + //printf("_aaApply(aa = x%llx, keysize = %d, dg = x%llx)\n", aa, keysize, dg); int treewalker(aaA* e) { int result; @@ -719,9 +721,9 @@ body return result; } - if (aa.a) + if (aa) { - foreach (e; aa.a.b) + foreach (e; aa.b) { if (e) { diff --git a/lphobos/internal/adi.d b/lphobos/internal/adi.d index 2aff3777..1b6064cb 100644 --- a/lphobos/internal/adi.d +++ b/lphobos/internal/adi.d @@ -51,7 +51,7 @@ struct Array * reversed. */ -extern (C) long _adReverseChar(char[] a) +extern (C) char[] _adReverseChar(char[] a) { if (a.length > 1) { @@ -111,7 +111,7 @@ extern (C) long _adReverseChar(char[] a) hi = hi - 1 + (stridehi - stridelo); } } - return *cast(long*)(&a); + return a; } unittest @@ -147,7 +147,7 @@ unittest * reversed. */ -extern (C) long _adReverseWchar(wchar[] a) +extern (C) wchar[] _adReverseWchar(wchar[] a) { if (a.length > 1) { @@ -205,7 +205,7 @@ extern (C) long _adReverseWchar(wchar[] a) hi = hi - 1 + (stridehi - stridelo); } } - return *cast(long*)(&a); + return a; } unittest @@ -230,13 +230,8 @@ unittest * Support for array.reverse property. */ -extern (C) long _adReverse(Array a, size_t szelem) - out (result) - { - assert(result is *cast(long*)(&a)); - } - body - { +extern (C) Array _adReverse(Array a, size_t szelem) +{ if (a.length >= 2) { byte* tmp; @@ -272,8 +267,8 @@ extern (C) long _adReverse(Array a, size_t szelem) //delete tmp; } } - return *cast(long*)(&a); - } + return a; +} unittest { @@ -364,7 +359,7 @@ unittest * Sort array of chars. */ -extern (C) long _adSortChar(char[] a) +extern (C) char[] _adSortChar(char[] a) { if (a.length > 1) { @@ -379,14 +374,14 @@ extern (C) long _adSortChar(char[] a) } delete da; } - return *cast(long*)(&a); + return a; } /********************************************** * Sort array of wchars. */ -extern (C) long _adSortWchar(wchar[] a) +extern (C) wchar[] _adSortWchar(wchar[] a) { if (a.length > 1) { @@ -401,7 +396,7 @@ extern (C) long _adSortWchar(wchar[] a) } delete da; } - return *cast(long*)(&a); + return a; } /********************************************** @@ -803,3 +798,41 @@ unittest assert(a >= e); } } + +/********************************** + * Support for array.dup property. + */ + +extern(C) +void* _d_realloc(void*, size_t); + +extern(C) +Array _adDupT(TypeInfo ti, Array a) +{ + Array r; + if (a.length) + { + auto sizeelem = ti.next.tsize(); // array element size + auto size = a.length * sizeelem; + r.ptr = _d_realloc(null,size); + r.length = a.length; + memcpy(r.ptr, a.ptr, size); + } + return r; +} + +unittest +{ + int[] a; + int[] b; + int i; + + debug(adi) printf("array.dup.unittest\n"); + + a = new int[3]; + a[0] = 1; a[1] = 2; a[2] = 3; + b = a.dup; + assert(b.length == 3); + for (i = 0; i < 3; i++) + assert(b[i] == i + 1); +} diff --git a/lphobos/internal/arrays.d b/lphobos/internal/arrays.d index a81c3656..db9120a3 100644 --- a/lphobos/internal/arrays.d +++ b/lphobos/internal/arrays.d @@ -78,7 +78,7 @@ void _d_array_init_pointer(void** a, size_t n, void* v) *p++ = v; } -void _d_array_init(void* a, size_t na, void* v, size_t nv) +void _d_array_init_mem(void* a, size_t na, void* v, size_t nv) { auto p = a; auto end = a + na*nv; diff --git a/lphobos/internal/qsort2.d b/lphobos/internal/qsort2.d index 21febcde..c02c9f39 100644 --- a/lphobos/internal/qsort2.d +++ b/lphobos/internal/qsort2.d @@ -14,6 +14,7 @@ import std.c.stdlib; +pragma(LLVM_internal, "notypeinfo") struct Array { size_t length; @@ -27,14 +28,14 @@ extern (C) int cmp(void* p1, void* p2) return tiglobal.compare(p1, p2); } -extern (C) long _adSort(Array a, TypeInfo ti) +extern (C) Array _adSort(Array a, TypeInfo ti) { synchronized { tiglobal = ti; std.c.stdlib.qsort(a.ptr, a.length, cast(size_t)ti.tsize(), &cmp); } - return *cast(long*)(&a); + return a; } diff --git a/test/aa1.d b/test/aa1.d index 40baf0e0..822733be 100644 --- a/test/aa1.d +++ b/test/aa1.d @@ -3,4 +3,13 @@ module aa1; void main() { int[int] aai; + assert(aai is null); + aai[0] = 52; + assert(aai !is null); + int i = aai[0]; + assert(i == 52); + aai[32] = 123; + int j = aai[32]; + assert(i == 52); + assert(j == 123); } diff --git a/test/aa2.d b/test/aa2.d new file mode 100644 index 00000000..36f3c44b --- /dev/null +++ b/test/aa2.d @@ -0,0 +1,12 @@ +module aa2; + +void main() +{ + long[float] aa; + long* p = 2.0f in aa; + assert(!p); + aa[4f] = 23; + p = 4f in aa; + assert(p); + assert(*p == 23); +} diff --git a/test/aa3.d b/test/aa3.d new file mode 100644 index 00000000..7e354e27 --- /dev/null +++ b/test/aa3.d @@ -0,0 +1,24 @@ +module aa3; + +void main() +{ + int[string] aa; + {aa["hello"] = 1;} + {int* p = "" in aa;} + aa[" worl"] = 2; + aa["d"] = 3; + aa["thisisgreat"] = 10; + int sum; + string cat; + { + foreach(k,v;aa) + { + printf("int[%.*s] = %d\n", k.length, k.ptr, v); + sum += v; + cat ~= k; + } + } + assert(sum == 16); + printf("cat = %.*s\n", cat.length, cat.ptr); + assert(cat.length == 22); +} diff --git a/test/aa4.d b/test/aa4.d new file mode 100644 index 00000000..50999bbe --- /dev/null +++ b/test/aa4.d @@ -0,0 +1,20 @@ +module aa4; + +void main() +{ + int[int] aa; + aa = addkey(aa,42,12); + int* p = haskey(aa,42); + assert(p && *p == 12); +} + +int[int] addkey(int[int] aa, int key, int val) +{ + aa[key] = val; + return aa; +} + +int* haskey(int[int] aa, int key) +{ + return key in aa; +} diff --git a/test/aa5.d b/test/aa5.d new file mode 100644 index 00000000..c73e40b0 --- /dev/null +++ b/test/aa5.d @@ -0,0 +1,9 @@ +module aa5; + +void main() +{ + int[int] aa; + aa[42] = 1; + int i = aa[42]; + assert(i == 1); +} diff --git a/test/arrays14.d b/test/arrays14.d new file mode 100644 index 00000000..5c8a5dbe --- /dev/null +++ b/test/arrays14.d @@ -0,0 +1,7 @@ +module arrays14; + +void main() +{ + auto s = "hello world"; + auto d = s.dup; +} diff --git a/test/typeinfo13.d b/test/typeinfo13.d new file mode 100644 index 00000000..5c3b3528 --- /dev/null +++ b/test/typeinfo13.d @@ -0,0 +1,13 @@ +module typeinfo13; + +void main() +{ + float[long] aa; + auto ti = typeid(typeof(aa)); + assert(ti.toString() == "float[long]"); + assert(ti.next() is typeid(float)); + assert(ti.tsize() == size_t.sizeof); + auto aati = cast(TypeInfo_AssociativeArray)ti; + assert(aati.value is typeid(float)); + assert(aati.key is typeid(long)); +}