[svn r113] Added initial support for associative arrays (AAs).

Fixed some problems with the string runtime support functions.
Fixed initialization of array of structs.
Fixed slice assignment where LHS is slice but RHS is dynamic array.
Fixed problems with result of assignment expressions.
Fixed foreach problems with key type mismatches.
This commit is contained in:
Tomas Lindquist Olsen 2007-11-21 04:13:15 +01:00
parent a807cbfc91
commit d51e392b8d
25 changed files with 756 additions and 122 deletions

View file

@ -1515,6 +1515,7 @@ Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
nm = name[n->ty == Twchar]; nm = name[n->ty == Twchar];
fd = FuncDeclaration::genCfunc(Type::tindex, nm); fd = FuncDeclaration::genCfunc(Type::tindex, nm);
fd->llvmRunTimeHack = true; fd->llvmRunTimeHack = true;
((TypeFunction*)fd->type)->llvmRetInPtr = true;
ec = new VarExp(0, fd); ec = new VarExp(0, fd);
e = e->castTo(sc, n->arrayOf()); // convert to dynamic array e = e->castTo(sc, n->arrayOf()); // convert to dynamic array
arguments = new Expressions(); arguments = new Expressions();
@ -1533,6 +1534,7 @@ Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
nm = name[n->ty == Twchar]; nm = name[n->ty == Twchar];
fd = FuncDeclaration::genCfunc(Type::tindex, nm); fd = FuncDeclaration::genCfunc(Type::tindex, nm);
fd->llvmRunTimeHack = true; fd->llvmRunTimeHack = true;
((TypeFunction*)fd->type)->llvmRetInPtr = true;
ec = new VarExp(0, fd); ec = new VarExp(0, fd);
e = e->castTo(sc, n->arrayOf()); // convert to dynamic array e = e->castTo(sc, n->arrayOf()); // convert to dynamic array
arguments = new Expressions(); arguments = new Expressions();
@ -1551,6 +1553,8 @@ Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
assert(size); assert(size);
dup = (ident == Id::dup); dup = (ident == Id::dup);
fd = FuncDeclaration::genCfunc(Type::tindex, dup ? Id::adDup : Id::adReverse); fd = FuncDeclaration::genCfunc(Type::tindex, dup ? Id::adDup : Id::adReverse);
fd->llvmRunTimeHack = true;
((TypeFunction*)fd->type)->llvmRetInPtr = true;
ec = new VarExp(0, fd); ec = new VarExp(0, fd);
e = e->castTo(sc, n->arrayOf()); // convert to dynamic array e = e->castTo(sc, n->arrayOf()); // convert to dynamic array
arguments = new Expressions(); arguments = new Expressions();
@ -1571,6 +1575,7 @@ Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
fd = FuncDeclaration::genCfunc(tint32->arrayOf(), fd = FuncDeclaration::genCfunc(tint32->arrayOf(),
(char*)(n->ty == Tbit ? "_adSortBit" : "_adSort")); (char*)(n->ty == Tbit ? "_adSortBit" : "_adSort"));
fd->llvmRunTimeHack = true; fd->llvmRunTimeHack = true;
((TypeFunction*)fd->type)->llvmRetInPtr = true;
ec = new VarExp(0, fd); ec = new VarExp(0, fd);
e = e->castTo(sc, n->arrayOf()); // convert to dynamic array e = e->castTo(sc, n->arrayOf()); // convert to dynamic array
arguments = new Expressions(); arguments = new Expressions();

153
gen/aa.cpp Normal file
View file

@ -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<llvm::Value*> 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<llvm::Value*> 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);
}
/////////////////////////////////////////////////////////////////////////////////////

7
gen/aa.h Normal file
View file

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

View file

@ -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) void DtoArrayInit(llvm::Value* ptr, llvm::Value* dim, llvm::Value* val)
{ {
Logger::println("HELLO");
Logger::cout() << "array: " << *ptr << " dim: " << *dim << " val: " << *val << '\n'; Logger::cout() << "array: " << *ptr << " dim: " << *dim << " val: " << *val << '\n';
const llvm::Type* pt = ptr->getType()->getContainedType(0); const llvm::Type* pt = ptr->getType()->getContainedType(0);
const llvm::Type* t = val->getType(); const llvm::Type* t = val->getType();
const llvm::Type* finalTy; const llvm::Type* finalTy;
size_t aggrsz = 0;
if (size_t arrsz = checkRectArrayInit(pt, finalTy)) { if (size_t arrsz = checkRectArrayInit(pt, finalTy)) {
assert(finalTy == t); assert(finalTy == t);
llvm::Constant* c = isaConstant(dim); 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"); ptr = gIR->ir->CreateBitCast(ptr, llvm::PointerType::get(finalTy), "tmp");
} }
else if (isaStruct(t)) { 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 { else {
assert(t == pt); assert(t == pt);
} }
Logger::cout() << "array: " << *ptr << " dim: " << *dim << " val: " << *val << '\n';
std::vector<llvm::Value*> args; std::vector<llvm::Value*> args;
args.push_back(ptr); args.push_back(ptr);
args.push_back(dim); args.push_back(dim);
@ -177,7 +192,11 @@ void DtoArrayInit(llvm::Value* ptr, llvm::Value* dim, llvm::Value* val)
const char* funcname = NULL; 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"; funcname = "_d_array_init_pointer";
const llvm::Type* dstty = llvm::PointerType::get(llvm::PointerType::get(llvm::Type::Int8Ty)); const llvm::Type* dstty = llvm::PointerType::get(llvm::PointerType::get(llvm::Type::Int8Ty));

View file

@ -44,6 +44,7 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const llvm::Type* thistype
} }
else { else {
assert(rt); assert(rt);
Type* rtfin = DtoDType(rt);
if (DtoIsPassedByRef(rt)) { if (DtoIsPassedByRef(rt)) {
rettype = llvm::PointerType::get(DtoType(rt)); rettype = llvm::PointerType::get(DtoType(rt));
actualRettype = llvm::Type::VoidTy; actualRettype = llvm::Type::VoidTy;

View file

@ -128,8 +128,8 @@ void ExpStatement::toIR(IRState* p)
Logger::println("ExpStatement::toIR(%d): %s", esi++, toChars()); Logger::println("ExpStatement::toIR(%d): %s", esi++, toChars());
LOG_SCOPE; LOG_SCOPE;
// if (global.params.symdebug) if (global.params.symdebug)
// DtoDwarfStopPoint(loc.linnum); DtoDwarfStopPoint(loc.linnum);
if (exp != 0) { if (exp != 0) {
elem* e = exp->toElem(p); elem* e = exp->toElem(p);
@ -731,6 +731,18 @@ void ForeachStatement::toIR(IRState* p)
assert(0 && "aggregate type is not Tarray or Tsarray"); 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; llvm::Constant* delta = 0;
if (op == TOKforeach) { if (op == TOKforeach) {
new llvm::StoreInst(zerokey, keyvar, p->scopebb()); new llvm::StoreInst(zerokey, keyvar, p->scopebb());

View file

@ -30,6 +30,7 @@
#include "gen/typeinf.h" #include "gen/typeinf.h"
#include "gen/complex.h" #include "gen/complex.h"
#include "gen/dvalue.h" #include "gen/dvalue.h"
#include "gen/aa.h"
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
@ -66,6 +67,7 @@ DValue* DeclarationExp::toElem(IRState* p)
//allocainst->setAlignment(vd->type->alignsize()); // TODO //allocainst->setAlignment(vd->type->alignsize()); // TODO
vd->llvmValue = allocainst; vd->llvmValue = allocainst;
} }
Logger::cout() << "llvm value for decl: " << *vd->llvmValue << '\n'; Logger::cout() << "llvm value for decl: " << *vd->llvmValue << '\n';
DValue* ie = DtoInitializer(vd->init); DValue* ie = DtoInitializer(vd->init);
} }
@ -409,9 +411,14 @@ DValue* StringExp::toElem(IRState* p)
else if (p->topexp()->e2 == this) { else if (p->topexp()->e2 == this) {
DValue* arr = p->topexp()->v; DValue* arr = p->topexp()->v;
assert(arr); assert(arr);
DtoSetArray(arr->getLVal(), clen, arrptr); if (arr->isSlice()) {
return new DSliceValue(type, clen, arrptr);
}
else {
DtoSetArray(arr->getRVal(), clen, arrptr);
return new DImValue(type, arr->getLVal(), true); return new DImValue(type, arr->getLVal(), true);
} }
}
assert(0); assert(0);
} }
else if (dtype->ty == Tsarray) { else if (dtype->ty == Tsarray) {
@ -490,7 +497,14 @@ DValue* AssignExp::toElem(IRState* p)
if (l->isSlice() || l->isComplex()) if (l->isSlice() || l->isComplex())
return l; 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(); llvm::Value* tlv = topexp->v->getLVal();
assert(isaStruct(tlv->getType()->getContainedType(0))); assert(isaStruct(tlv->getType()->getContainedType(0)));
llargs[j] = tlv; llargs[j] = tlv;
if (DtoIsPassedByRef(tf->next)) { isInPlace = true;
/*if (DtoIsPassedByRef(tf->next)) {
isInPlace = true; isInPlace = true;
} }
else else
assert(0); assert(0);*/
} }
else { else {
llargs[j] = new llvm::AllocaInst(argiter->get()->getContainedType(0),"rettmp",p->topallocapoint()); 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; ++j;
++argiter; ++argiter;
} }
@ -1004,13 +1029,15 @@ DValue* CallExp::toElem(IRState* p)
llargs[j] = DtoArgument(llfnty->getParamType(j), fnarg, (Expression*)arguments->data[i]); llargs[j] = DtoArgument(llfnty->getParamType(j), fnarg, (Expression*)arguments->data[i]);
// this hack is necessary :/ // this hack is necessary :/
if (dfn && dfn->func && dfn->func->llvmRunTimeHack) { if (dfn && dfn->func && dfn->func->llvmRunTimeHack) {
Logger::println("llvmRunTimeHack==true - force casting argument"); if (llfnty->getParamType(j) != NULL) {
if (llargs[j]->getType() != llfnty->getParamType(j)) { if (llargs[j]->getType() != llfnty->getParamType(j)) {
Logger::cout() << "from: " << *llargs[j]->getType() << " to: " << *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)); llargs[j] = DtoBitCast(llargs[j], llfnty->getParamType(j));
} }
} }
} }
}
Logger::println("%d params passed", n); Logger::println("%d params passed", n);
for (int i=0; i<n; ++i) { for (int i=0; i<n; ++i) {
assert(llargs[i]); assert(llargs[i]);
@ -1024,12 +1051,21 @@ DValue* CallExp::toElem(IRState* p)
if (llfnty->getReturnType() != llvm::Type::VoidTy) if (llfnty->getReturnType() != llvm::Type::VoidTy)
varname = "tmp"; varname = "tmp";
Logger::cout() << "Calling: " << *funcval->getType() << '\n'; Logger::cout() << "Calling: " << *funcval << '\n';
// call the function // call the function
llvm::CallInst* call = new llvm::CallInst(funcval, llargs.begin(), llargs.end(), varname, p->scopebb()); llvm::CallInst* call = new llvm::CallInst(funcval, llargs.begin(), llargs.end(), varname, p->scopebb());
llvm::Value* retllval = (retinptr) ? llargs[0] : call; 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 // set calling convention
if (dfn && dfn->func) { if (dfn && dfn->func) {
int li = dfn->func->llvmInternal; 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::LoadInst(arrptr,"tmp",p->scopebb());
arrptr = new llvm::GetElementPtrInst(arrptr,r->getRVal(),"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); 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; } #define STUB(x) DValue *x::toElem(IRState * p) {error("Exp type "#x" not implemented: %s", toChars()); fatal(); return 0; }
//STUB(IdentityExp); //STUB(IdentityExp);
//STUB(CondExp); //STUB(CondExp);
//STUB(EqualExp); //STUB(EqualExp);
STUB(InExp); //STUB(InExp);
//STUB(CmpExp); //STUB(CmpExp);
//STUB(AndAndExp); //STUB(AndAndExp);
//STUB(OrOrExp); //STUB(OrOrExp);

View file

@ -177,8 +177,11 @@ const llvm::Type* DtoType(Type* t)
// associative arrays // associative arrays
case Taarray: case Taarray:
{ {
// TODO this is a kludge TypeAArray* taa = (TypeAArray*)t;
return llvm::PointerType::get(llvm::Type::Int8Ty); std::vector<const llvm::Type*> types;
types.push_back(DtoType(taa->key));
types.push_back(DtoType(taa->next));
return llvm::PointerType::get(llvm::StructType::get(types));
} }
default: 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<llvm::Value*> 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) void DtoMemCpy(llvm::Value* dst, llvm::Value* src, llvm::Value* nbytes)
{ {
assert(dst->getType() == src->getType()); assert(dst->getType() == src->getType());

View file

@ -74,6 +74,7 @@ void DtoForceConstInitDsymbol(Dsymbol* dsym);
void DtoForceDefineDsymbol(Dsymbol* dsym); void DtoForceDefineDsymbol(Dsymbol* dsym);
// llvm wrappers // llvm wrappers
void DtoMemSetZero(llvm::Value* dst, llvm::Value* nbytes);
void DtoMemCpy(llvm::Value* dst, llvm::Value* src, llvm::Value* nbytes); void DtoMemCpy(llvm::Value* dst, llvm::Value* src, llvm::Value* nbytes);
bool DtoCanLoad(llvm::Value* ptr); bool DtoCanLoad(llvm::Value* ptr);
llvm::Value* DtoLoad(llvm::Value* src); llvm::Value* DtoLoad(llvm::Value* src);

View file

@ -654,33 +654,69 @@ void TypeInfoStaticArrayDeclaration::toDt(dt_t **pdt)
void TypeInfoAssociativeArrayDeclaration::llvmDeclare() 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() 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<llvm::Constant*> 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) void TypeInfoAssociativeArrayDeclaration::toDt(dt_t **pdt)
{ {
assert(0 && "TypeInfoAssociativeArrayDeclaration"); assert(0);
/*
//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
*/
} }
/* ========================================================================= */ /* ========================================================================= */

View file

@ -98,7 +98,7 @@
<hidenonlocation>false</hidenonlocation> <hidenonlocation>false</hidenonlocation>
</groups> </groups>
<tree> <tree>
<hidepatterns>*.bc</hidepatterns> <hidepatterns>*.bc,*.ll</hidepatterns>
<hidenonprojectfiles>false</hidenonprojectfiles> <hidenonprojectfiles>false</hidenonprojectfiles>
</tree> </tree>
</kdevfileview> </kdevfileview>

View file

@ -100,6 +100,8 @@ dmd/utf.h
dmd/version.c dmd/version.c
dmd/version.h dmd/version.h
gen gen
gen/aa.cpp
gen/aa.h
gen/arrays.cpp gen/arrays.cpp
gen/arrays.h gen/arrays.h
gen/binops.cpp gen/binops.cpp
@ -136,6 +138,7 @@ gen/typinf.cpp
lphobos lphobos
lphobos/crc32.d lphobos/crc32.d
lphobos/gc lphobos/gc
lphobos/gc/gcbits.d
lphobos/gc/gclinux.d lphobos/gc/gclinux.d
lphobos/gc/gcstub.d lphobos/gc/gcstub.d
lphobos/gcstats.d lphobos/gcstats.d
@ -145,7 +148,6 @@ lphobos/internal/aApplyR.d
lphobos/internal/aaA.d lphobos/internal/aaA.d
lphobos/internal/adi.d lphobos/internal/adi.d
lphobos/internal/arrays.d lphobos/internal/arrays.d
lphobos/internal/cmath2.d
lphobos/internal/contract.d lphobos/internal/contract.d
lphobos/internal/mem.d lphobos/internal/mem.d
lphobos/internal/moduleinit.d lphobos/internal/moduleinit.d
@ -232,6 +234,10 @@ runalltests.d
test test
test/a.d test/a.d
test/aa1.d test/aa1.d
test/aa2.d
test/aa3.d
test/aa4.d
test/aa5.d
test/alignment.d test/alignment.d
test/alloca1.d test/alloca1.d
test/arrayinit.d test/arrayinit.d
@ -240,6 +246,7 @@ test/arrays10.d
test/arrays11.d test/arrays11.d
test/arrays12.d test/arrays12.d
test/arrays13.d test/arrays13.d
test/arrays14.d
test/arrays2.d test/arrays2.d
test/arrays3.d test/arrays3.d
test/arrays4.d test/arrays4.d
@ -316,6 +323,7 @@ test/bug70.d
test/bug71.d test/bug71.d
test/bug72.d test/bug72.d
test/bug73.d test/bug73.d
test/bug74.d
test/bug8.d test/bug8.d
test/bug9.d test/bug9.d
test/c.d test/c.d
@ -418,6 +426,7 @@ test/typeinfo.d
test/typeinfo10.d test/typeinfo10.d
test/typeinfo11.d test/typeinfo11.d
test/typeinfo12.d test/typeinfo12.d
test/typeinfo13.d
test/typeinfo2.d test/typeinfo2.d
test/typeinfo3.d test/typeinfo3.d
test/typeinfo4.d test/typeinfo4.d

View file

@ -51,7 +51,8 @@ llvm-link -f -o=../lib/llvmdcore.bc `ls obj/llvm.*.bc` ../lib/llvmdcore.bc || ex
echo "compiling garbage collector" echo "compiling garbage collector"
llvmdc gc/gclinux.d -c -odobj || exit 1 llvmdc gc/gclinux.d -c -odobj || exit 1
llvmdc gc/gcstub.d -c -odobj -Igc || 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" echo "compiling phobos"
rebuild phobos.d -c -oqobj -dc=llvmdc-posix || exit 1 rebuild phobos.d -c -oqobj -dc=llvmdc-posix || exit 1

176
lphobos/gc/gcbits.d Normal file
View file

@ -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()
{
}
+/

View file

@ -27,13 +27,19 @@
* distribution. * 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.stdio;
import std.c.stdarg; import std.c.stdarg;
import std.c.stdio; import std.c.stdio;
import std.c.stdlib; import std.c.stdlib;
import std.c.string; import std.c.string;
import std.string; //import std.string;
import std.outofmemory; import std.outofmemory;
@ -51,17 +57,17 @@ static size_t[] prime_list = [
/* This is the type of the return value for dynamic arrays. /* This is the type of the return value for dynamic arrays.
* It should be a type that is returned in registers. * 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 struct Array
{ {
size_t length; size_t length;
void* ptr; void* ptr;
} }
pragma(LLVM_internal, "notypeinfo")
struct aaA struct aaA
{ {
aaA *left; aaA *left;
@ -71,6 +77,7 @@ struct aaA
/* value */ /* value */
} }
pragma(LLVM_internal, "notypeinfo")
struct BB struct BB
{ {
aaA*[] b; aaA*[] b;
@ -81,10 +88,7 @@ struct BB
* it is completely opaque. * it is completely opaque.
*/ */
struct AA alias BB* AA;
{
BB* a;
}
/********************************** /**********************************
* Align to next pointer boundary, so that * 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) if (e)
_aaLen_x(e); _aaLen_x(e);
@ -212,7 +216,7 @@ size_t _aaLen(AA aa)
} }
body 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. * 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 in
{ {
assert(aa); assert(aa);
@ -229,32 +233,32 @@ void* _aaGet(AA* aa, TypeInfo keyti, size_t valuesize, ...)
out (result) out (result)
{ {
assert(result); assert(result);
assert(aa.a); assert(*aa);
assert(aa.a.b.length); assert((*aa).b.length);
//assert(_aaInAh(*aa.a, key)); //assert(_aaInAh(*aa, key));
} }
body body
{ {
auto pkey = cast(void *)(&valuesize + 1); //auto pkey = cast(void *)(&valuesize + 1);
size_t i; size_t i;
aaA* e; aaA* e;
auto keysize = aligntsize(keyti.tsize()); auto keysize = aligntsize(keyti.tsize());
if (!aa.a) if (!*aa)
aa.a = new BB(); *aa = new BB();
if (!aa.a.b.length) if (!(*aa).b.length)
{ {
alias aaA *pa; alias aaA *pa;
auto len = prime_list[0]; auto len = prime_list[0];
aa.a.b = new pa[len]; (*aa).b = new pa[len];
} }
auto key_hash = keyti.getHash(pkey); auto key_hash = keyti.getHash(pkey);
//printf("hash = %d\n", key_hash); //printf("hash = %d\n", key_hash);
i = key_hash % aa.a.b.length; i = key_hash % (*aa).b.length;
auto pe = &aa.a.b[i]; auto pe = &(*aa).b[i];
while ((e = *pe) != null) while ((e = *pe) != null)
{ {
if (key_hash == e.hash) if (key_hash == e.hash)
@ -275,9 +279,9 @@ void* _aaGet(AA* aa, TypeInfo keyti, size_t valuesize, ...)
e.hash = key_hash; e.hash = key_hash;
*pe = e; *pe = e;
auto nodes = ++aa.a.nodes; auto nodes = ++(*aa).nodes;
//printf("length = %d, nodes = %d\n", (*aa.a).length, nodes); //printf("length = %d, nodes = %d\n", (*aa).length, nodes);
if (nodes > aa.a.b.length * 4) if (nodes > (*aa).b.length * 4)
{ {
_aaRehash(aa,keyti); _aaRehash(aa,keyti);
} }
@ -292,22 +296,22 @@ void* _aaGet(AA* aa, TypeInfo keyti, size_t valuesize, ...)
* Returns null if it is not already there. * 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); //printf("_aaGetRvalue(valuesize = %u)\n", valuesize);
if (!aa.a) if (!aa)
return null; return null;
auto pkey = cast(void *)(&valuesize + 1); //auto pkey = cast(void *)(&valuesize + 1);
auto keysize = aligntsize(keyti.tsize()); auto keysize = aligntsize(keyti.tsize());
auto len = aa.a.b.length; auto len = aa.b.length;
if (len) if (len)
{ {
auto key_hash = keyti.getHash(pkey); auto key_hash = keyti.getHash(pkey);
//printf("hash = %d\n", key_hash); //printf("hash = %d\n", key_hash);
size_t i = key_hash % len; size_t i = key_hash % len;
auto e = aa.a.b[i]; auto e = aa.b[i];
while (e != null) while (e != null)
{ {
if (key_hash == e.hash) 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 * !=null in aa, return pointer to value
*/ */
void* _aaIn(AA aa, TypeInfo keyti, ...) void* _aaIn(AA aa, TypeInfo keyti, void* pkey)
in in
{ {
} }
@ -342,19 +346,19 @@ void* _aaIn(AA aa, TypeInfo keyti, ...)
} }
body 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); //printf("_aaIn(), .length = %d, .ptr = %x\n", aa.length, cast(uint)aa.ptr);
auto len = aa.a.b.length; auto len = aa.b.length;
if (len) if (len)
{ {
auto key_hash = keyti.getHash(pkey); auto key_hash = keyti.getHash(pkey);
//printf("hash = %d\n", key_hash); //printf("hash = %d\n", key_hash);
size_t i = key_hash % len; size_t i = key_hash % len;
auto e = aa.a.b[i]; auto e = aa.b[i];
while (e != null) while (e != null)
{ {
if (key_hash == e.hash) if (key_hash == e.hash)
@ -380,17 +384,17 @@ void* _aaIn(AA aa, TypeInfo keyti, ...)
* If key is not in aa[], do nothing. * 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; aaA* e;
if (aa.a && aa.a.b.length) if (aa && aa.b.length)
{ {
auto key_hash = keyti.getHash(pkey); auto key_hash = keyti.getHash(pkey);
//printf("hash = %d\n", key_hash); //printf("hash = %d\n", key_hash);
size_t i = key_hash % aa.a.b.length; size_t i = key_hash % aa.b.length;
auto pe = &aa.a.b[i]; auto pe = &aa.b[i];
while ((e = *pe) != null) // null means not found while ((e = *pe) != null) // null means not found
{ {
if (key_hash == e.hash) if (key_hash == e.hash)
@ -423,7 +427,7 @@ void _aaDel(AA aa, TypeInfo keyti, ...)
e.right = null; e.right = null;
} }
aa.a.nodes--; aa.nodes--;
// Should notify GC that e can be free'd now // Should notify GC that e can be free'd now
break; break;
@ -470,19 +474,19 @@ ArrayRet_t _aaValues(AA aa, size_t keysize, size_t valuesize)
} while (e != null); } while (e != null);
} }
if (aa.a) if (aa)
{ {
a.length = _aaLen(aa); a.length = _aaLen(aa);
a.ptr = (new void[a.length * valuesize]).ptr; a.ptr = (new void[a.length * valuesize]).ptr;
resi = 0; resi = 0;
foreach (e; aa.a.b) foreach (e; aa.b)
{ {
if (e) if (e)
_aaValues_x(e); _aaValues_x(e);
} }
assert(resi == a.length); 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) void* _aaRehash(AA* paa, TypeInfo keyti)
in in
{ {
assert(paa);
//_aaInvAh(paa); //_aaInvAh(paa);
} }
out (result) out (result)
@ -549,9 +554,9 @@ void* _aaRehash(AA* paa, TypeInfo keyti)
} }
//printf("Rehash\n"); //printf("Rehash\n");
if (paa.a) if (paa)
{ {
auto aa = paa.a; auto aa = *paa;
auto len = _aaLen(*paa); auto len = _aaLen(*paa);
if (len) if (len)
{ size_t i; { size_t i;
@ -573,9 +578,9 @@ void* _aaRehash(AA* paa, TypeInfo keyti)
newb.nodes = aa.nodes; 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); auto len = _aaLen(aa);
if (!len) if (!len)
return 0; return ArrayRet_t.init;
res = cast(byte[])new void[len * keysize]; res = cast(byte[])new void[len * keysize];
resi = 0; resi = 0;
foreach (e; aa.a.b) foreach (e; aa.b)
{ {
if (e) if (e)
_aaKeys_x(e); _aaKeys_x(e);
} }
assert(resi == len); assert(resi == len);
Array a; return Array(len, res.ptr);
a.length = len;
a.ptr = res.ptr;
return *cast(ArrayRet_t*)(&a);
} }
@ -639,7 +641,7 @@ in
body body
{ int result; { 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 treewalker(aaA* e)
{ int result; { int result;
@ -666,9 +668,9 @@ body
return result; return result;
} }
if (aa.a) if (aa)
{ {
foreach (e; aa.a.b) foreach (e; aa.b)
{ {
if (e) if (e)
{ {
@ -692,7 +694,7 @@ in
body body
{ int result; { 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 treewalker(aaA* e)
{ int result; { int result;
@ -719,9 +721,9 @@ body
return result; return result;
} }
if (aa.a) if (aa)
{ {
foreach (e; aa.a.b) foreach (e; aa.b)
{ {
if (e) if (e)
{ {

View file

@ -51,7 +51,7 @@ struct Array
* reversed. * reversed.
*/ */
extern (C) long _adReverseChar(char[] a) extern (C) char[] _adReverseChar(char[] a)
{ {
if (a.length > 1) if (a.length > 1)
{ {
@ -111,7 +111,7 @@ extern (C) long _adReverseChar(char[] a)
hi = hi - 1 + (stridehi - stridelo); hi = hi - 1 + (stridehi - stridelo);
} }
} }
return *cast(long*)(&a); return a;
} }
unittest unittest
@ -147,7 +147,7 @@ unittest
* reversed. * reversed.
*/ */
extern (C) long _adReverseWchar(wchar[] a) extern (C) wchar[] _adReverseWchar(wchar[] a)
{ {
if (a.length > 1) if (a.length > 1)
{ {
@ -205,7 +205,7 @@ extern (C) long _adReverseWchar(wchar[] a)
hi = hi - 1 + (stridehi - stridelo); hi = hi - 1 + (stridehi - stridelo);
} }
} }
return *cast(long*)(&a); return a;
} }
unittest unittest
@ -230,12 +230,7 @@ unittest
* Support for array.reverse property. * Support for array.reverse property.
*/ */
extern (C) long _adReverse(Array a, size_t szelem) extern (C) Array _adReverse(Array a, size_t szelem)
out (result)
{
assert(result is *cast(long*)(&a));
}
body
{ {
if (a.length >= 2) if (a.length >= 2)
{ {
@ -272,7 +267,7 @@ extern (C) long _adReverse(Array a, size_t szelem)
//delete tmp; //delete tmp;
} }
} }
return *cast(long*)(&a); return a;
} }
unittest unittest
@ -364,7 +359,7 @@ unittest
* Sort array of chars. * Sort array of chars.
*/ */
extern (C) long _adSortChar(char[] a) extern (C) char[] _adSortChar(char[] a)
{ {
if (a.length > 1) if (a.length > 1)
{ {
@ -379,14 +374,14 @@ extern (C) long _adSortChar(char[] a)
} }
delete da; delete da;
} }
return *cast(long*)(&a); return a;
} }
/********************************************** /**********************************************
* Sort array of wchars. * Sort array of wchars.
*/ */
extern (C) long _adSortWchar(wchar[] a) extern (C) wchar[] _adSortWchar(wchar[] a)
{ {
if (a.length > 1) if (a.length > 1)
{ {
@ -401,7 +396,7 @@ extern (C) long _adSortWchar(wchar[] a)
} }
delete da; delete da;
} }
return *cast(long*)(&a); return a;
} }
/********************************************** /**********************************************
@ -803,3 +798,41 @@ unittest
assert(a >= e); 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);
}

View file

@ -78,7 +78,7 @@ void _d_array_init_pointer(void** a, size_t n, void* v)
*p++ = 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 p = a;
auto end = a + na*nv; auto end = a + na*nv;

View file

@ -14,6 +14,7 @@
import std.c.stdlib; import std.c.stdlib;
pragma(LLVM_internal, "notypeinfo")
struct Array struct Array
{ {
size_t length; size_t length;
@ -27,14 +28,14 @@ extern (C) int cmp(void* p1, void* p2)
return tiglobal.compare(p1, p2); return tiglobal.compare(p1, p2);
} }
extern (C) long _adSort(Array a, TypeInfo ti) extern (C) Array _adSort(Array a, TypeInfo ti)
{ {
synchronized synchronized
{ {
tiglobal = ti; tiglobal = ti;
std.c.stdlib.qsort(a.ptr, a.length, cast(size_t)ti.tsize(), &cmp); std.c.stdlib.qsort(a.ptr, a.length, cast(size_t)ti.tsize(), &cmp);
} }
return *cast(long*)(&a); return a;
} }

View file

@ -3,4 +3,13 @@ module aa1;
void main() void main()
{ {
int[int] aai; 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);
} }

12
test/aa2.d Normal file
View file

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

24
test/aa3.d Normal file
View file

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

20
test/aa4.d Normal file
View file

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

9
test/aa5.d Normal file
View file

@ -0,0 +1,9 @@
module aa5;
void main()
{
int[int] aa;
aa[42] = 1;
int i = aa[42];
assert(i == 1);
}

7
test/arrays14.d Normal file
View file

@ -0,0 +1,7 @@
module arrays14;
void main()
{
auto s = "hello world";
auto d = s.dup;
}

13
test/typeinfo13.d Normal file
View file

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