mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-11 18:33:14 +01:00
[svn r112] Fixed 'case 1,2,3:' style case statements.
Fixed a bunch of bugs with return/break/continue in loops. Fixed support for the DMDFE hidden implicit return value variable. This can be needed for some foreach statements where the loop body is converted to a nested delegate, but also possibly returns from the function. Added std.math to phobos. Added AA runtime support code, done ground work for implementing AAs. Several other bugfixes.
This commit is contained in:
@@ -5870,6 +5870,7 @@ Expression *AddrExp::semantic(Scope *sc)
|
||||
{
|
||||
VarExp *dve = (VarExp *)e1;
|
||||
FuncDeclaration *f = dve->var->isFuncDeclaration();
|
||||
VarDeclaration *v = dve->var->isVarDeclaration();
|
||||
|
||||
if (f && f->isNested())
|
||||
{ Expression *e;
|
||||
@@ -5878,6 +5879,10 @@ Expression *AddrExp::semantic(Scope *sc)
|
||||
e = e->semantic(sc);
|
||||
return e;
|
||||
}
|
||||
else if (v)
|
||||
{
|
||||
v->llvmNeedsStorage = true;
|
||||
}
|
||||
}
|
||||
else if (e1->op == TOKarray)
|
||||
{
|
||||
@@ -7543,6 +7548,7 @@ Expression *XorAssignExp::semantic(Scope *sc)
|
||||
AddExp::AddExp(Loc loc, Expression *e1, Expression *e2)
|
||||
: BinExp(loc, TOKadd, sizeof(AddExp), e1, e2)
|
||||
{
|
||||
llvmFieldIndex = false;
|
||||
}
|
||||
|
||||
Expression *AddExp::semantic(Scope *sc)
|
||||
|
||||
@@ -1121,6 +1121,9 @@ struct AddExp : BinExp
|
||||
Identifier *opId_r();
|
||||
|
||||
elem *toElem(IRState *irs);
|
||||
|
||||
// LLVMDC
|
||||
bool llvmFieldIndex;
|
||||
};
|
||||
|
||||
struct MinExp : BinExp
|
||||
|
||||
@@ -4309,6 +4309,11 @@ L1:
|
||||
b = new AddrExp(e->loc, e);
|
||||
b->type = e->type->pointerTo();
|
||||
b = new AddExp(e->loc, b, new IntegerExp(e->loc, v->offset, Type::tint32));
|
||||
#if IN_LLVM
|
||||
// LLVMDC modification
|
||||
// this is *essential*
|
||||
((AddExp*)b)->llvmFieldIndex = true;
|
||||
#endif
|
||||
b->type = v->type->pointerTo();
|
||||
e = new PtrExp(e->loc, b);
|
||||
e->type = v->type;
|
||||
|
||||
@@ -1437,7 +1437,7 @@ Statement *ForeachStatement::semantic(Scope *sc)
|
||||
exps->push(aggr);
|
||||
size_t keysize = taa->key->size();
|
||||
keysize = (keysize + 3) & ~3;
|
||||
exps->push(new IntegerExp(0, keysize, Type::tint32));
|
||||
exps->push(new IntegerExp(0, keysize, Type::tsize_t));
|
||||
exps->push(flde);
|
||||
e = new CallExp(loc, ec, exps);
|
||||
e->type = Type::tindex; // don't run semantic() on e
|
||||
|
||||
@@ -46,6 +46,7 @@ struct ScopeStatement;
|
||||
struct TryCatchStatement;
|
||||
struct HdrGenState;
|
||||
struct InterState;
|
||||
struct CaseStatement;
|
||||
|
||||
enum TOK;
|
||||
|
||||
@@ -114,6 +115,7 @@ struct Statement : Object
|
||||
virtual CompoundStatement *isCompoundStatement() { return NULL; }
|
||||
virtual ReturnStatement *isReturnStatement() { return NULL; }
|
||||
virtual IfStatement *isIfStatement() { return NULL; }
|
||||
virtual CaseStatement* isCaseStatement() { return NULL; }
|
||||
};
|
||||
|
||||
struct ExpStatement : Statement
|
||||
@@ -436,6 +438,8 @@ struct CaseStatement : Statement
|
||||
Statement *inlineScan(InlineScanState *iss);
|
||||
|
||||
void toIR(IRState *irs);
|
||||
|
||||
CaseStatement* isCaseStatement() { return this; }
|
||||
};
|
||||
|
||||
struct DefaultStatement : Statement
|
||||
|
||||
@@ -369,7 +369,7 @@ static llvm::Value* get_slice_ptr(DSliceValue* e, llvm::Value*& sz)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void DtoArrayCopy(DSliceValue* dst, DSliceValue* src)
|
||||
void DtoArrayCopySlices(DSliceValue* dst, DSliceValue* src)
|
||||
{
|
||||
llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
|
||||
@@ -390,6 +390,25 @@ void DtoArrayCopy(DSliceValue* dst, DSliceValue* src)
|
||||
new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
|
||||
}
|
||||
|
||||
void DtoArrayCopyToSlice(DSliceValue* dst, DValue* src)
|
||||
{
|
||||
llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
|
||||
llvm::Value* sz1;
|
||||
llvm::Value* dstarr = new llvm::BitCastInst(get_slice_ptr(dst,sz1),arrty,"tmp",gIR->scopebb());
|
||||
llvm::Value* srcarr = new llvm::BitCastInst(DtoArrayPtr(src),arrty,"tmp",gIR->scopebb());
|
||||
|
||||
llvm::Function* fn = (global.params.is64bit) ? LLVM_DeclareMemCpy64() : LLVM_DeclareMemCpy32();
|
||||
std::vector<llvm::Value*> llargs;
|
||||
llargs.resize(4);
|
||||
llargs[0] = dstarr;
|
||||
llargs[1] = srcarr;
|
||||
llargs[2] = sz1;
|
||||
llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
|
||||
|
||||
new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
void DtoStaticArrayCopy(llvm::Value* dst, llvm::Value* src)
|
||||
{
|
||||
|
||||
@@ -10,7 +10,8 @@ llvm::Constant* DtoConstArrayInitializer(ArrayInitializer* si);
|
||||
llvm::Constant* DtoConstSlice(llvm::Constant* dim, llvm::Constant* ptr);
|
||||
llvm::Constant* DtoConstStaticArray(const llvm::Type* t, llvm::Constant* c);
|
||||
|
||||
void DtoArrayCopy(DSliceValue* dst, DSliceValue* src);
|
||||
void DtoArrayCopySlices(DSliceValue* dst, DSliceValue* src);
|
||||
void DtoArrayCopyToSlice(DSliceValue* dst, DValue* src);
|
||||
|
||||
void DtoArrayInit(llvm::Value* l, llvm::Value* r);
|
||||
void DtoArrayInit(llvm::Value* ptr, llvm::Value* dim, llvm::Value* val);
|
||||
|
||||
@@ -378,6 +378,8 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
|
||||
}
|
||||
if (f->llvmUsesThis) {
|
||||
iarg->setName("this");
|
||||
fdecl->llvmThisVar = iarg;
|
||||
assert(fdecl->llvmThisVar);
|
||||
++iarg;
|
||||
}
|
||||
int varargs = -1;
|
||||
@@ -426,6 +428,8 @@ void DtoDefineFunc(FuncDeclaration* fd)
|
||||
if (fd->llvmDefined) return;
|
||||
fd->llvmDefined = true;
|
||||
|
||||
assert(fd->llvmDeclared);
|
||||
|
||||
Logger::println("DtoDefineFunc(%s)", fd->toPrettyChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
@@ -474,6 +478,7 @@ void DtoDefineFunc(FuncDeclaration* fd)
|
||||
assert(fd->llvmIRFunc);
|
||||
gIR->functions.push_back(fd->llvmIRFunc);
|
||||
|
||||
/* // moved to declaration
|
||||
// this handling
|
||||
if (f->llvmUsesThis) {
|
||||
Logger::println("uses this");
|
||||
@@ -483,6 +488,7 @@ void DtoDefineFunc(FuncDeclaration* fd)
|
||||
fd->llvmThisVar = func->arg_begin();
|
||||
assert(fd->llvmThisVar != 0);
|
||||
}
|
||||
*/
|
||||
|
||||
if (fd->isMain())
|
||||
gIR->emitMain = true;
|
||||
@@ -497,6 +503,12 @@ void DtoDefineFunc(FuncDeclaration* fd)
|
||||
f->llvmAllocaPoint = new llvm::BitCastInst(llvm::ConstantInt::get(llvm::Type::Int32Ty,0,false),llvm::Type::Int32Ty,"alloca point",gIR->scopebb());
|
||||
gIR->func()->allocapoint = f->llvmAllocaPoint;
|
||||
|
||||
// need result variable? (not nested)
|
||||
if (fd->vresult && !fd->vresult->nestedref) {
|
||||
Logger::println("non-nested vresult value");
|
||||
fd->vresult->llvmValue = new llvm::AllocaInst(DtoType(fd->vresult->type),"function_vresult",f->llvmAllocaPoint);
|
||||
}
|
||||
|
||||
// give arguments storage
|
||||
size_t n = Argument::dim(f->parameters);
|
||||
for (int i=0; i < n; ++i) {
|
||||
@@ -524,7 +536,14 @@ void DtoDefineFunc(FuncDeclaration* fd)
|
||||
|
||||
llvm::Value* parentNested = NULL;
|
||||
if (FuncDeclaration* fd2 = fd->toParent()->isFuncDeclaration()) {
|
||||
parentNested = fd2->llvmNested;
|
||||
if (!fd->isStatic())
|
||||
parentNested = fd2->llvmNested;
|
||||
}
|
||||
|
||||
// need result variable? (nested)
|
||||
if (fd->vresult && fd->vresult->nestedref) {
|
||||
Logger::println("nested vresult value: %s", fd->vresult->toChars());
|
||||
fd->llvmNestedVars.insert(fd->vresult);
|
||||
}
|
||||
|
||||
// construct nested variables struct
|
||||
|
||||
@@ -82,10 +82,6 @@ IRScope& IRState::scope()
|
||||
}
|
||||
|
||||
llvm::BasicBlock* IRState::scopebb()
|
||||
{
|
||||
return scopebegin();
|
||||
}
|
||||
llvm::BasicBlock* IRState::scopebegin()
|
||||
{
|
||||
IRScope& s = scope();
|
||||
assert(s.begin);
|
||||
|
||||
@@ -158,9 +158,8 @@ struct IRState
|
||||
// basic block scopes
|
||||
std::vector<IRScope> scopes;
|
||||
IRScope& scope();
|
||||
llvm::BasicBlock* scopebegin();
|
||||
llvm::BasicBlock* scopeend();
|
||||
llvm::BasicBlock* scopebb();
|
||||
llvm::BasicBlock* scopeend();
|
||||
bool scopereturned();
|
||||
|
||||
// loop blocks
|
||||
|
||||
@@ -163,7 +163,7 @@ void IfStatement::toIR(IRState* p)
|
||||
Logger::cout() << "if conditional: " << *cond_val << '\n';
|
||||
cond_val = DtoBoolean(cond_val);
|
||||
}
|
||||
llvm::Value* ifgoback = new llvm::BranchInst(ifbb, elsebb, cond_val, gIR->scopebegin());
|
||||
llvm::Value* ifgoback = new llvm::BranchInst(ifbb, elsebb, cond_val, gIR->scopebb());
|
||||
|
||||
// replace current scope
|
||||
gIR->scope() = IRScope(ifbb,elsebb);
|
||||
@@ -171,7 +171,7 @@ void IfStatement::toIR(IRState* p)
|
||||
// do scoped statements
|
||||
ifbody->toIR(p);
|
||||
if (!gIR->scopereturned()) {
|
||||
new llvm::BranchInst(endbb,gIR->scopebegin());
|
||||
new llvm::BranchInst(endbb,gIR->scopebb());
|
||||
}
|
||||
|
||||
if (elsebody) {
|
||||
@@ -179,7 +179,7 @@ void IfStatement::toIR(IRState* p)
|
||||
gIR->scope() = IRScope(elsebb,endbb);
|
||||
elsebody->toIR(p);
|
||||
if (!gIR->scopereturned()) {
|
||||
new llvm::BranchInst(endbb,gIR->scopebegin());
|
||||
new llvm::BranchInst(endbb,gIR->scopebb());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,14 +199,14 @@ void ScopeStatement::toIR(IRState* p)
|
||||
llvm::BasicBlock* beginbb = 0;
|
||||
|
||||
// remove useless branches by clearing and reusing the current basicblock
|
||||
llvm::BasicBlock* bb = p->scopebegin();
|
||||
llvm::BasicBlock* bb = p->scopebb();
|
||||
if (bb->empty()) {
|
||||
beginbb = bb;
|
||||
}
|
||||
else {
|
||||
assert(!p->scopereturned());
|
||||
beginbb = new llvm::BasicBlock("scope", p->topfunc(), oldend);
|
||||
new llvm::BranchInst(beginbb, p->scopebegin());
|
||||
new llvm::BranchInst(beginbb, p->scopebb());
|
||||
}
|
||||
llvm::BasicBlock* endbb = new llvm::BasicBlock("endscope", p->topfunc(), oldend);
|
||||
|
||||
@@ -234,7 +234,7 @@ void WhileStatement::toIR(IRState* p)
|
||||
|
||||
// move into the while block
|
||||
p->ir->CreateBr(whilebb);
|
||||
//new llvm::BranchInst(whilebb, gIR->scopebegin());
|
||||
//new llvm::BranchInst(whilebb, gIR->scopebb());
|
||||
|
||||
// replace current scope
|
||||
gIR->scope() = IRScope(whilebb,endbb);
|
||||
@@ -256,7 +256,8 @@ void WhileStatement::toIR(IRState* p)
|
||||
p->loopbbs.pop_back();
|
||||
|
||||
// loop
|
||||
new llvm::BranchInst(whilebb, gIR->scopebegin());
|
||||
if (!gIR->scopereturned())
|
||||
new llvm::BranchInst(whilebb, gIR->scopebb());
|
||||
|
||||
// rewrite the scope
|
||||
gIR->scope() = IRScope(endbb,oldend);
|
||||
@@ -276,13 +277,16 @@ void DoStatement::toIR(IRState* p)
|
||||
llvm::BasicBlock* endbb = new llvm::BasicBlock("enddowhile", gIR->topfunc(), oldend);
|
||||
|
||||
// move into the while block
|
||||
new llvm::BranchInst(dowhilebb, gIR->scopebegin());
|
||||
assert(!gIR->scopereturned());
|
||||
new llvm::BranchInst(dowhilebb, gIR->scopebb());
|
||||
|
||||
// replace current scope
|
||||
gIR->scope() = IRScope(dowhilebb,endbb);
|
||||
|
||||
// do-while body code
|
||||
p->loopbbs.push_back(IRScope(dowhilebb,endbb));
|
||||
body->toIR(p);
|
||||
p->loopbbs.pop_back();
|
||||
|
||||
// create the condition
|
||||
DValue* cond_e = condition->toElem(p);
|
||||
@@ -290,7 +294,7 @@ void DoStatement::toIR(IRState* p)
|
||||
delete cond_e;
|
||||
|
||||
// conditional branch
|
||||
llvm::Value* ifbreak = new llvm::BranchInst(dowhilebb, endbb, cond_val, gIR->scopebegin());
|
||||
llvm::Value* ifbreak = new llvm::BranchInst(dowhilebb, endbb, cond_val, gIR->scopebb());
|
||||
|
||||
// rewrite the scope
|
||||
gIR->scope() = IRScope(endbb,oldend);
|
||||
@@ -316,7 +320,7 @@ void ForStatement::toIR(IRState* p)
|
||||
init->toIR(p);
|
||||
|
||||
// move into the for condition block, ie. start the loop
|
||||
new llvm::BranchInst(forbb, gIR->scopebegin());
|
||||
new llvm::BranchInst(forbb, gIR->scopebb());
|
||||
|
||||
p->loopbbs.push_back(IRScope(forincbb,endbb));
|
||||
|
||||
@@ -338,7 +342,8 @@ void ForStatement::toIR(IRState* p)
|
||||
body->toIR(p);
|
||||
|
||||
// move into the for increment block
|
||||
new llvm::BranchInst(forincbb, gIR->scopebegin());
|
||||
if (!gIR->scopereturned())
|
||||
new llvm::BranchInst(forincbb, gIR->scopebb());
|
||||
gIR->scope() = IRScope(forincbb, endbb);
|
||||
|
||||
// increment
|
||||
@@ -348,7 +353,8 @@ void ForStatement::toIR(IRState* p)
|
||||
}
|
||||
|
||||
// loop
|
||||
new llvm::BranchInst(forbb, gIR->scopebegin());
|
||||
if (!gIR->scopereturned())
|
||||
new llvm::BranchInst(forbb, gIR->scopebb());
|
||||
|
||||
p->loopbbs.pop_back();
|
||||
|
||||
@@ -368,7 +374,7 @@ void BreakStatement::toIR(IRState* p)
|
||||
assert(0);
|
||||
}
|
||||
else {
|
||||
new llvm::BranchInst(gIR->loopbbs.back().end, gIR->scopebegin());
|
||||
new llvm::BranchInst(gIR->loopbbs.back().end, gIR->scopebb());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -384,7 +390,7 @@ void ContinueStatement::toIR(IRState* p)
|
||||
assert(0);
|
||||
}
|
||||
else {
|
||||
new llvm::BranchInst(gIR->loopbbs.back().begin, gIR->scopebegin());
|
||||
new llvm::BranchInst(gIR->loopbbs.back().begin, gIR->scopebb());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -527,25 +533,33 @@ void SwitchStatement::toIR(IRState* p)
|
||||
llvm::BasicBlock* oldend = gIR->scopeend();
|
||||
|
||||
// collect the needed cases
|
||||
typedef std::pair<llvm::BasicBlock*, llvm::ConstantInt*> CasePair;
|
||||
typedef std::pair<llvm::BasicBlock*, std::vector<llvm::ConstantInt*> > CasePair;
|
||||
std::vector<CasePair> vcases;
|
||||
std::vector<Statement*> vbodies;
|
||||
for (int i=0; i<cases->dim; ++i)
|
||||
{
|
||||
CaseStatement* cs = (CaseStatement*)cases->data[i];
|
||||
|
||||
// get the case value
|
||||
DValue* e = cs->exp->toElem(p);
|
||||
DConstValue* ce = e->isConst();
|
||||
assert(ce);
|
||||
llvm::ConstantInt* ec = isaConstantInt(ce->c);
|
||||
assert(ec);
|
||||
delete e;
|
||||
|
||||
// create the case bb with a nice label
|
||||
std::string lblname("case"+std::string(cs->exp->toChars()));
|
||||
llvm::BasicBlock* bb = new llvm::BasicBlock(lblname, p->topfunc(), oldend);
|
||||
|
||||
vcases.push_back(CasePair(bb,ec));
|
||||
std::vector<llvm::ConstantInt*> tmp;
|
||||
CaseStatement* last;
|
||||
do {
|
||||
// get the case value
|
||||
DValue* e = cs->exp->toElem(p);
|
||||
DConstValue* ce = e->isConst();
|
||||
assert(ce);
|
||||
llvm::ConstantInt* ec = isaConstantInt(ce->c);
|
||||
assert(ec);
|
||||
tmp.push_back(ec);
|
||||
last = cs;
|
||||
}
|
||||
while (cs = cs->statement->isCaseStatement());
|
||||
|
||||
vcases.push_back(CasePair(bb, tmp));
|
||||
vbodies.push_back(last->statement);
|
||||
}
|
||||
|
||||
// default
|
||||
@@ -566,7 +580,11 @@ void SwitchStatement::toIR(IRState* p)
|
||||
size_t n = vcases.size();
|
||||
for (size_t i=0; i<n; ++i)
|
||||
{
|
||||
si->addCase(vcases[i].second, vcases[i].first);
|
||||
size_t nc = vcases[i].second.size();
|
||||
for (size_t j=0; j<nc; ++j)
|
||||
{
|
||||
si->addCase(vcases[i].second[j], vcases[i].first);
|
||||
}
|
||||
}
|
||||
|
||||
// insert case statements
|
||||
@@ -576,7 +594,7 @@ void SwitchStatement::toIR(IRState* p)
|
||||
p->scope() = IRScope(vcases[i].first,nextbb);
|
||||
|
||||
p->loopbbs.push_back(IRScope(p->scopebb(),endbb));
|
||||
static_cast<CaseStatement*>(cases->data[i])->statement->toIR(p);
|
||||
vbodies[i]->toIR(p);
|
||||
p->loopbbs.pop_back();
|
||||
|
||||
llvm::BasicBlock* curbb = p->scopebb();
|
||||
@@ -605,6 +623,15 @@ void SwitchStatement::toIR(IRState* p)
|
||||
gIR->scope() = IRScope(endbb,oldend);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
void CaseStatement::toIR(IRState* p)
|
||||
{
|
||||
Logger::println("CaseStatement::toIR(): %s", toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
assert(0);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void UnrolledLoopStatement::toIR(IRState* p)
|
||||
@@ -735,7 +762,7 @@ void ForeachStatement::toIR(IRState* p)
|
||||
}
|
||||
new llvm::BranchInst(bodybb, endbb, done, p->scopebb());
|
||||
|
||||
// body
|
||||
// init body
|
||||
p->scope() = IRScope(bodybb,nextbb);
|
||||
|
||||
// get value for this iteration
|
||||
@@ -750,12 +777,10 @@ void ForeachStatement::toIR(IRState* p)
|
||||
DValue* dst = new DVarValue(value->type, valvar, true);
|
||||
DValue* src = new DVarValue(value->type, value->llvmValue, true);
|
||||
DtoAssign(dst, src);
|
||||
delete dst;
|
||||
delete src;
|
||||
value->llvmValue = valvar;
|
||||
}
|
||||
|
||||
// body
|
||||
// emit body
|
||||
p->loopbbs.push_back(IRScope(nextbb,endbb));
|
||||
body->toIR(p);
|
||||
p->loopbbs.pop_back();
|
||||
@@ -860,7 +885,7 @@ void SynchronizedStatement::toIR(IRState* p)
|
||||
//STUBST(ReturnStatement);
|
||||
//STUBST(ContinueStatement);
|
||||
STUBST(DefaultStatement);
|
||||
STUBST(CaseStatement);
|
||||
//STUBST(CaseStatement);
|
||||
//STUBST(SwitchStatement);
|
||||
STUBST(SwitchErrorStatement);
|
||||
STUBST(Statement);
|
||||
|
||||
32
gen/toir.cpp
32
gen/toir.cpp
@@ -488,7 +488,9 @@ DValue* AssignExp::toElem(IRState* p)
|
||||
DtoAssign(l, r);
|
||||
}
|
||||
|
||||
return l;
|
||||
if (l->isSlice() || l->isComplex())
|
||||
return l;
|
||||
return new DImValue(type, l->getRVal());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -507,7 +509,8 @@ DValue* AddExp::toElem(IRState* p)
|
||||
Type* e2type = DtoDType(e2->type);
|
||||
|
||||
if (e1type != e2type) {
|
||||
if (e1type->ty == Tpointer && e1next && e1next->ty == Tstruct) {
|
||||
if (llvmFieldIndex) {
|
||||
assert(e1type->ty == Tpointer && e1next && e1next->ty == Tstruct);
|
||||
Logger::println("add to AddrExp of struct");
|
||||
assert(r->isConst());
|
||||
llvm::ConstantInt* cofs = llvm::cast<llvm::ConstantInt>(r->isConst()->c);
|
||||
@@ -1001,8 +1004,9 @@ 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");
|
||||
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));
|
||||
}
|
||||
}
|
||||
@@ -1155,12 +1159,15 @@ DValue* SymOffExp::toElem(IRState* p)
|
||||
|
||||
DValue* AddrExp::toElem(IRState* p)
|
||||
{
|
||||
Logger::print("AddrExp::toElem: %s | %s\n", toChars(), type->toChars());
|
||||
Logger::println("AddrExp::toElem: %s | %s", toChars(), type->toChars());
|
||||
LOG_SCOPE;
|
||||
DValue* v = e1->toElem(p);
|
||||
if (v->isField())
|
||||
if (v->isField()) {
|
||||
Logger::println("is field");
|
||||
return v;
|
||||
}
|
||||
else if (DFuncValue* fv = v->isFunc()) {
|
||||
Logger::println("is func");
|
||||
//Logger::println("FuncDeclaration");
|
||||
FuncDeclaration* fd = fv->func;
|
||||
assert(fd);
|
||||
@@ -1169,8 +1176,10 @@ DValue* AddrExp::toElem(IRState* p)
|
||||
return new DFuncValue(fd, fd->llvmValue);
|
||||
}
|
||||
else if (DImValue* im = v->isIm()) {
|
||||
Logger::println("is immediate");
|
||||
return v;
|
||||
}
|
||||
Logger::println("is nothing special");
|
||||
return new DFieldValue(type, v->getLVal(), false);
|
||||
}
|
||||
|
||||
@@ -1178,7 +1187,7 @@ DValue* AddrExp::toElem(IRState* p)
|
||||
|
||||
DValue* PtrExp::toElem(IRState* p)
|
||||
{
|
||||
Logger::print("PtrExp::toElem: %s | %s\n", toChars(), type->toChars());
|
||||
Logger::println("PtrExp::toElem: %s | %s", toChars(), type->toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
DValue* a = e1->toElem(p);
|
||||
@@ -1552,7 +1561,7 @@ DValue* EqualExp::toElem(IRState* p)
|
||||
|
||||
Type* t = DtoDType(e1->type);
|
||||
Type* e2t = DtoDType(e2->type);
|
||||
assert(t == e2t);
|
||||
//assert(t == e2t);
|
||||
|
||||
llvm::Value* eval = 0;
|
||||
|
||||
@@ -1571,7 +1580,12 @@ DValue* EqualExp::toElem(IRState* p)
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
eval = new llvm::ICmpInst(cmpop, l->getRVal(), r->getRVal(), "tmp", p->scopebb());
|
||||
llvm::Value* lv = l->getRVal();
|
||||
llvm::Value* rv = r->getRVal();
|
||||
if (rv->getType() != lv->getType()) {
|
||||
rv = DtoBitCast(rv, lv->getType());
|
||||
}
|
||||
eval = new llvm::ICmpInst(cmpop, lv, rv, "tmp", p->scopebb());
|
||||
}
|
||||
else if (t->iscomplex())
|
||||
{
|
||||
@@ -2212,7 +2226,7 @@ DValue* FuncExp::toElem(IRState* p)
|
||||
if (fd->isNested()) Logger::println("nested");
|
||||
Logger::println("kind = %s\n", fd->kind());
|
||||
|
||||
DtoForceDeclareDsymbol(fd);
|
||||
DtoForceDefineDsymbol(fd);
|
||||
|
||||
bool temp = false;
|
||||
llvm::Value* lval = NULL;
|
||||
|
||||
@@ -174,6 +174,13 @@ const llvm::Type* DtoType(Type* t)
|
||||
return DtoType(bt);
|
||||
}
|
||||
|
||||
// associative arrays
|
||||
case Taarray:
|
||||
{
|
||||
// TODO this is a kludge
|
||||
return llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
}
|
||||
|
||||
default:
|
||||
printf("trying to convert unknown type with value %d\n", t->ty);
|
||||
assert(0);
|
||||
@@ -796,7 +803,15 @@ llvm::Value* DtoNestedVariable(VarDeclaration* vd)
|
||||
|
||||
// on this stack
|
||||
if (fd == f) {
|
||||
llvm::Value* v = DtoGEPi(vd->llvmValue,0,unsigned(vd->llvmNestedIndex),"tmp");
|
||||
llvm::Value* vdv = vd->llvmValue;
|
||||
if (!vdv)
|
||||
{
|
||||
Logger::println(":o null vd->llvmValue for: %s", vd->toChars());
|
||||
vdv = fd->llvmNested;
|
||||
assert(vdv);
|
||||
}
|
||||
assert(vd->llvmNestedIndex != ~0);
|
||||
llvm::Value* v = DtoGEPi(vdv,0,unsigned(vd->llvmNestedIndex),"tmp");
|
||||
if (vd->isParameter() && (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type))) {
|
||||
Logger::cout() << "1267 loading: " << *v << '\n';
|
||||
v = gIR->ir->CreateLoad(v,"tmp");
|
||||
@@ -859,7 +874,7 @@ void DtoAssign(DValue* lhs, DValue* rhs)
|
||||
// lhs is slice
|
||||
if (DSliceValue* s = lhs->isSlice()) {
|
||||
if (DSliceValue* s2 = rhs->isSlice()) {
|
||||
DtoArrayCopy(s, s2);
|
||||
DtoArrayCopySlices(s, s2);
|
||||
}
|
||||
else if (t->next == t2) {
|
||||
if (s->len)
|
||||
@@ -867,8 +882,9 @@ void DtoAssign(DValue* lhs, DValue* rhs)
|
||||
else
|
||||
DtoArrayInit(s->ptr, rhs->getRVal());
|
||||
}
|
||||
else
|
||||
assert(rhs->inPlace());
|
||||
else {
|
||||
DtoArrayCopyToSlice(s, rhs);
|
||||
}
|
||||
}
|
||||
// rhs is slice
|
||||
else if (DSliceValue* s = rhs->isSlice()) {
|
||||
@@ -926,8 +942,15 @@ void DtoAssign(DValue* lhs, DValue* rhs)
|
||||
DtoComplexAssign(dst, rhs->getRVal());
|
||||
}
|
||||
else {
|
||||
llvm::Value* l;
|
||||
if (DLRValue* lr = lhs->isLRValue()) {
|
||||
l = lr->getLVal();
|
||||
rhs = DtoCast(rhs, lr->getLType());
|
||||
}
|
||||
else {
|
||||
l = lhs->getLVal();
|
||||
}
|
||||
llvm::Value* r = rhs->getRVal();
|
||||
llvm::Value* l = lhs->getLVal();
|
||||
Logger::cout() << "assign\nlhs: " << *l << "rhs: " << *r << '\n';
|
||||
const llvm::Type* lit = l->getType()->getContainedType(0);
|
||||
if (r->getType() != lit) { // :(
|
||||
@@ -1124,6 +1147,7 @@ DValue* DtoCastClass(DValue* val, Type* _to)
|
||||
DValue* DtoCast(DValue* val, Type* to)
|
||||
{
|
||||
Type* fromtype = DtoDType(val->getType());
|
||||
Logger::println("Casting from '%s' to '%s'", fromtype->toChars(), to->toChars());
|
||||
if (fromtype->isintegral()) {
|
||||
return DtoCastInt(val, to);
|
||||
}
|
||||
|
||||
@@ -142,6 +142,7 @@ lphobos/gcstats.d
|
||||
lphobos/internal
|
||||
lphobos/internal/aApply.d
|
||||
lphobos/internal/aApplyR.d
|
||||
lphobos/internal/aaA.d
|
||||
lphobos/internal/adi.d
|
||||
lphobos/internal/arrays.d
|
||||
lphobos/internal/cmath2.d
|
||||
@@ -181,6 +182,7 @@ lphobos/std/conv.d
|
||||
lphobos/std/ctype.d
|
||||
lphobos/std/format.d
|
||||
lphobos/std/intrinsic.d
|
||||
lphobos/std/math.d
|
||||
lphobos/std/moduleinit.d
|
||||
lphobos/std/outofmemory.d
|
||||
lphobos/std/stdarg.d
|
||||
@@ -229,6 +231,7 @@ lphobos/typeinfos2.d
|
||||
runalltests.d
|
||||
test
|
||||
test/a.d
|
||||
test/aa1.d
|
||||
test/alignment.d
|
||||
test/alloca1.d
|
||||
test/arrayinit.d
|
||||
@@ -310,6 +313,9 @@ test/bug64.d
|
||||
test/bug66.d
|
||||
test/bug7.d
|
||||
test/bug70.d
|
||||
test/bug71.d
|
||||
test/bug72.d
|
||||
test/bug73.d
|
||||
test/bug8.d
|
||||
test/bug9.d
|
||||
test/c.d
|
||||
@@ -401,6 +407,7 @@ test/structs5.d
|
||||
test/structs6.d
|
||||
test/structs7.d
|
||||
test/switch1.d
|
||||
test/switch2.d
|
||||
test/sync1.d
|
||||
test/templ1.d
|
||||
test/templ2.d
|
||||
|
||||
@@ -20,7 +20,7 @@ llvm-link -f -o=../lib/llvmdcore.bc `ls obj/internal.*.bc` ../lib/llvmdcore.bc o
|
||||
|
||||
|
||||
echo "compiling typeinfo 1"
|
||||
rebuild typeinfos1.d -c -oqobj -dc=llvmdc-posix -v || exit 1
|
||||
rebuild typeinfos1.d -c -oqobj -dc=llvmdc-posix || exit 1
|
||||
llvm-link -f -o=../lib/llvmdcore.bc `ls obj/typeinfo1.*.bc` ../lib/llvmdcore.bc || exit 1
|
||||
|
||||
echo "compiling typeinfo 2"
|
||||
@@ -33,10 +33,12 @@ llvmdc internal/aApplyR.d -c -odobj || exit 1
|
||||
llvm-link -f -o=../lib/llvmdcore.bc obj/aApply.bc obj/aApplyR.bc ../lib/llvmdcore.bc || exit 1
|
||||
|
||||
echo "compiling array runtime support"
|
||||
llvmdc internal/qsort2.d -c -odobj || exit
|
||||
llvmdc internal/qsort2.d -c -odobj || exit 1
|
||||
llvm-link -f -o=../lib/llvmdcore.bc obj/qsort2.bc ../lib/llvmdcore.bc || exit 1
|
||||
llvmdc internal/adi.d -c -odobj || exit
|
||||
llvmdc internal/adi.d -c -odobj || exit 1
|
||||
llvm-link -f -o=../lib/llvmdcore.bc obj/adi.bc ../lib/llvmdcore.bc || exit 1
|
||||
llvmdc internal/aaA.d -c -odobj || exit 1
|
||||
llvm-link -f -o=../lib/llvmdcore.bc obj/aaA.bc ../lib/llvmdcore.bc || exit 1
|
||||
|
||||
echo "compiling object implementation"
|
||||
llvmdc internal/objectimpl.d -c -odobj || exit 1
|
||||
|
||||
821
lphobos/internal/aaA.d
Normal file
821
lphobos/internal/aaA.d
Normal file
@@ -0,0 +1,821 @@
|
||||
//_ aaA.d
|
||||
|
||||
/**
|
||||
* Part of the D programming language runtime library.
|
||||
* Implementation of associative arrays.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000-2007 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
|
||||
//import std.stdio;
|
||||
import std.c.stdarg;
|
||||
import std.c.stdio;
|
||||
import std.c.stdlib;
|
||||
import std.c.string;
|
||||
import std.string;
|
||||
|
||||
import std.outofmemory;
|
||||
|
||||
// Auto-rehash and pre-allocate - Dave Fladebo
|
||||
|
||||
static size_t[] prime_list = [
|
||||
97UL, 389UL,
|
||||
1543UL, 6151UL,
|
||||
24593UL, 98317UL,
|
||||
393241UL, 1572869UL,
|
||||
6291469UL, 25165843UL,
|
||||
100663319UL, 402653189UL,
|
||||
1610612741UL, 4294967291UL
|
||||
];
|
||||
|
||||
/* 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;
|
||||
|
||||
struct Array
|
||||
{
|
||||
size_t length;
|
||||
void* ptr;
|
||||
}
|
||||
|
||||
struct aaA
|
||||
{
|
||||
aaA *left;
|
||||
aaA *right;
|
||||
hash_t hash;
|
||||
/* key */
|
||||
/* value */
|
||||
}
|
||||
|
||||
struct BB
|
||||
{
|
||||
aaA*[] b;
|
||||
size_t nodes; // total number of aaA nodes
|
||||
}
|
||||
|
||||
/* This is the type actually seen by the programmer, although
|
||||
* it is completely opaque.
|
||||
*/
|
||||
|
||||
struct AA
|
||||
{
|
||||
BB* a;
|
||||
}
|
||||
|
||||
/**********************************
|
||||
* Align to next pointer boundary, so that
|
||||
* GC won't be faced with misaligned pointers
|
||||
* in value.
|
||||
*/
|
||||
|
||||
size_t aligntsize(size_t tsize)
|
||||
{
|
||||
// Is pointer alignment on the x64 4 bytes or 8?
|
||||
return (tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1);
|
||||
}
|
||||
|
||||
extern (C):
|
||||
|
||||
/*************************************************
|
||||
* Invariant for aa.
|
||||
*/
|
||||
|
||||
/+
|
||||
void _aaInvAh(aaA*[] aa)
|
||||
{
|
||||
for (size_t i = 0; i < aa.length; i++)
|
||||
{
|
||||
if (aa[i])
|
||||
_aaInvAh_x(aa[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private int _aaCmpAh_x(aaA *e1, aaA *e2)
|
||||
{ int c;
|
||||
|
||||
c = e1.hash - e2.hash;
|
||||
if (c == 0)
|
||||
{
|
||||
c = e1.key.length - e2.key.length;
|
||||
if (c == 0)
|
||||
c = memcmp((char *)e1.key, (char *)e2.key, e1.key.length);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
private void _aaInvAh_x(aaA *e)
|
||||
{
|
||||
hash_t key_hash;
|
||||
aaA *e1;
|
||||
aaA *e2;
|
||||
|
||||
key_hash = getHash(e.key);
|
||||
assert(key_hash == e.hash);
|
||||
|
||||
while (1)
|
||||
{ int c;
|
||||
|
||||
e1 = e.left;
|
||||
if (e1)
|
||||
{
|
||||
_aaInvAh_x(e1); // ordinary recursion
|
||||
do
|
||||
{
|
||||
c = _aaCmpAh_x(e1, e);
|
||||
assert(c < 0);
|
||||
e1 = e1.right;
|
||||
} while (e1 != null);
|
||||
}
|
||||
|
||||
e2 = e.right;
|
||||
if (e2)
|
||||
{
|
||||
do
|
||||
{
|
||||
c = _aaCmpAh_x(e, e2);
|
||||
assert(c < 0);
|
||||
e2 = e2.left;
|
||||
} while (e2 != null);
|
||||
e = e.right; // tail recursion
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
+/
|
||||
|
||||
/****************************************************
|
||||
* Determine number of entries in associative array.
|
||||
*/
|
||||
|
||||
size_t _aaLen(AA aa)
|
||||
in
|
||||
{
|
||||
//printf("_aaLen()+\n");
|
||||
//_aaInv(aa);
|
||||
}
|
||||
out (result)
|
||||
{
|
||||
size_t len = 0;
|
||||
|
||||
void _aaLen_x(aaA* ex)
|
||||
{
|
||||
auto e = ex;
|
||||
len++;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (e.right)
|
||||
_aaLen_x(e.right);
|
||||
e = e.left;
|
||||
if (!e)
|
||||
break;
|
||||
len++;
|
||||
}
|
||||
}
|
||||
|
||||
if (aa.a)
|
||||
{
|
||||
foreach (e; aa.a.b)
|
||||
{
|
||||
if (e)
|
||||
_aaLen_x(e);
|
||||
}
|
||||
}
|
||||
assert(len == result);
|
||||
|
||||
//printf("_aaLen()-\n");
|
||||
}
|
||||
body
|
||||
{
|
||||
return aa.a ? aa.a.nodes : 0;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************
|
||||
* Get pointer to value in associative array indexed by key.
|
||||
* Add entry for key if it is not already there.
|
||||
*/
|
||||
|
||||
void* _aaGet(AA* aa, TypeInfo keyti, size_t valuesize, ...)
|
||||
in
|
||||
{
|
||||
assert(aa);
|
||||
}
|
||||
out (result)
|
||||
{
|
||||
assert(result);
|
||||
assert(aa.a);
|
||||
assert(aa.a.b.length);
|
||||
//assert(_aaInAh(*aa.a, key));
|
||||
}
|
||||
body
|
||||
{
|
||||
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.a.b.length)
|
||||
{
|
||||
alias aaA *pa;
|
||||
auto len = prime_list[0];
|
||||
|
||||
aa.a.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];
|
||||
while ((e = *pe) != null)
|
||||
{
|
||||
if (key_hash == e.hash)
|
||||
{
|
||||
auto c = keyti.compare(pkey, e + 1);
|
||||
if (c == 0)
|
||||
goto Lret;
|
||||
pe = (c < 0) ? &e.left : &e.right;
|
||||
}
|
||||
else
|
||||
pe = (key_hash < e.hash) ? &e.left : &e.right;
|
||||
}
|
||||
|
||||
// Not found, create new elem
|
||||
//printf("create new one\n");
|
||||
e = cast(aaA *) cast(void*) new void[aaA.sizeof + keysize + valuesize];
|
||||
memcpy(e + 1, pkey, keysize);
|
||||
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)
|
||||
{
|
||||
_aaRehash(aa,keyti);
|
||||
}
|
||||
|
||||
Lret:
|
||||
return cast(void *)(e + 1) + keysize;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************
|
||||
* Get pointer to value in associative array indexed by key.
|
||||
* Returns null if it is not already there.
|
||||
*/
|
||||
|
||||
void* _aaGetRvalue(AA aa, TypeInfo keyti, size_t valuesize, ...)
|
||||
{
|
||||
//printf("_aaGetRvalue(valuesize = %u)\n", valuesize);
|
||||
if (!aa.a)
|
||||
return null;
|
||||
|
||||
auto pkey = cast(void *)(&valuesize + 1);
|
||||
auto keysize = aligntsize(keyti.tsize());
|
||||
auto len = aa.a.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];
|
||||
while (e != null)
|
||||
{
|
||||
if (key_hash == e.hash)
|
||||
{
|
||||
auto c = keyti.compare(pkey, e + 1);
|
||||
if (c == 0)
|
||||
return cast(void *)(e + 1) + keysize;
|
||||
e = (c < 0) ? e.left : e.right;
|
||||
}
|
||||
else
|
||||
e = (key_hash < e.hash) ? e.left : e.right;
|
||||
}
|
||||
}
|
||||
return null; // not found, caller will throw exception
|
||||
}
|
||||
|
||||
|
||||
/*************************************************
|
||||
* Determine if key is in aa.
|
||||
* Returns:
|
||||
* null not in aa
|
||||
* !=null in aa, return pointer to value
|
||||
*/
|
||||
|
||||
void* _aaIn(AA aa, TypeInfo keyti, ...)
|
||||
in
|
||||
{
|
||||
}
|
||||
out (result)
|
||||
{
|
||||
//assert(result == 0 || result == 1);
|
||||
}
|
||||
body
|
||||
{
|
||||
if (aa.a)
|
||||
{
|
||||
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;
|
||||
|
||||
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];
|
||||
while (e != null)
|
||||
{
|
||||
if (key_hash == e.hash)
|
||||
{
|
||||
auto c = keyti.compare(pkey, e + 1);
|
||||
if (c == 0)
|
||||
return cast(void *)(e + 1) + aligntsize(keyti.tsize());
|
||||
e = (c < 0) ? e.left : e.right;
|
||||
}
|
||||
else
|
||||
e = (key_hash < e.hash) ? e.left : e.right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Not found
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************
|
||||
* Delete key entry in aa[].
|
||||
* If key is not in aa[], do nothing.
|
||||
*/
|
||||
|
||||
void _aaDel(AA aa, TypeInfo keyti, ...)
|
||||
{
|
||||
auto pkey = cast(void *)(&keyti + 1);
|
||||
aaA* e;
|
||||
|
||||
if (aa.a && aa.a.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];
|
||||
while ((e = *pe) != null) // null means not found
|
||||
{
|
||||
if (key_hash == e.hash)
|
||||
{
|
||||
auto c = keyti.compare(pkey, e + 1);
|
||||
if (c == 0)
|
||||
{
|
||||
if (!e.left && !e.right)
|
||||
{
|
||||
*pe = null;
|
||||
}
|
||||
else if (e.left && !e.right)
|
||||
{
|
||||
*pe = e.left;
|
||||
e.left = null;
|
||||
}
|
||||
else if (!e.left && e.right)
|
||||
{
|
||||
*pe = e.right;
|
||||
e.right = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pe = e.left;
|
||||
e.left = null;
|
||||
do
|
||||
pe = &(*pe).right;
|
||||
while (*pe);
|
||||
*pe = e.right;
|
||||
e.right = null;
|
||||
}
|
||||
|
||||
aa.a.nodes--;
|
||||
|
||||
// Should notify GC that e can be free'd now
|
||||
break;
|
||||
}
|
||||
pe = (c < 0) ? &e.left : &e.right;
|
||||
}
|
||||
else
|
||||
pe = (key_hash < e.hash) ? &e.left : &e.right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/********************************************
|
||||
* Produce array of values from aa.
|
||||
*/
|
||||
|
||||
ArrayRet_t _aaValues(AA aa, size_t keysize, size_t valuesize)
|
||||
in
|
||||
{
|
||||
assert(keysize == aligntsize(keysize));
|
||||
}
|
||||
body
|
||||
{
|
||||
size_t resi;
|
||||
Array a;
|
||||
|
||||
void _aaValues_x(aaA* e)
|
||||
{
|
||||
do
|
||||
{
|
||||
memcpy(a.ptr + resi * valuesize,
|
||||
cast(byte*)e + aaA.sizeof + keysize,
|
||||
valuesize);
|
||||
resi++;
|
||||
if (e.left)
|
||||
{ if (!e.right)
|
||||
{ e = e.left;
|
||||
continue;
|
||||
}
|
||||
_aaValues_x(e.left);
|
||||
}
|
||||
e = e.right;
|
||||
} while (e != null);
|
||||
}
|
||||
|
||||
if (aa.a)
|
||||
{
|
||||
a.length = _aaLen(aa);
|
||||
a.ptr = (new void[a.length * valuesize]).ptr;
|
||||
resi = 0;
|
||||
foreach (e; aa.a.b)
|
||||
{
|
||||
if (e)
|
||||
_aaValues_x(e);
|
||||
}
|
||||
assert(resi == a.length);
|
||||
}
|
||||
return *cast(ArrayRet_t*)(&a);
|
||||
}
|
||||
|
||||
|
||||
/********************************************
|
||||
* Rehash an array.
|
||||
*/
|
||||
|
||||
void* _aaRehash(AA* paa, TypeInfo keyti)
|
||||
in
|
||||
{
|
||||
//_aaInvAh(paa);
|
||||
}
|
||||
out (result)
|
||||
{
|
||||
//_aaInvAh(result);
|
||||
}
|
||||
body
|
||||
{
|
||||
BB newb;
|
||||
|
||||
void _aaRehash_x(aaA* olde)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
auto left = olde.left;
|
||||
auto right = olde.right;
|
||||
olde.left = null;
|
||||
olde.right = null;
|
||||
|
||||
aaA* e;
|
||||
|
||||
//printf("rehash %p\n", olde);
|
||||
auto key_hash = olde.hash;
|
||||
size_t i = key_hash % newb.b.length;
|
||||
auto pe = &newb.b[i];
|
||||
while ((e = *pe) != null)
|
||||
{
|
||||
//printf("\te = %p, e.left = %p, e.right = %p\n", e, e.left, e.right);
|
||||
assert(e.left != e);
|
||||
assert(e.right != e);
|
||||
if (key_hash == e.hash)
|
||||
{
|
||||
auto c = keyti.compare(olde + 1, e + 1);
|
||||
assert(c != 0);
|
||||
pe = (c < 0) ? &e.left : &e.right;
|
||||
}
|
||||
else
|
||||
pe = (key_hash < e.hash) ? &e.left : &e.right;
|
||||
}
|
||||
*pe = olde;
|
||||
|
||||
if (right)
|
||||
{
|
||||
if (!left)
|
||||
{ olde = right;
|
||||
continue;
|
||||
}
|
||||
_aaRehash_x(right);
|
||||
}
|
||||
if (!left)
|
||||
break;
|
||||
olde = left;
|
||||
}
|
||||
}
|
||||
|
||||
//printf("Rehash\n");
|
||||
if (paa.a)
|
||||
{
|
||||
auto aa = paa.a;
|
||||
auto len = _aaLen(*paa);
|
||||
if (len)
|
||||
{ size_t i;
|
||||
|
||||
for (i = 0; i < prime_list.length - 1; i++)
|
||||
{
|
||||
if (len <= prime_list[i])
|
||||
break;
|
||||
}
|
||||
len = prime_list[i];
|
||||
newb.b = new aaA*[len];
|
||||
|
||||
foreach (e; aa.b)
|
||||
{
|
||||
if (e)
|
||||
_aaRehash_x(e);
|
||||
}
|
||||
|
||||
newb.nodes = aa.nodes;
|
||||
}
|
||||
|
||||
*paa.a = newb;
|
||||
}
|
||||
return (*paa).a;
|
||||
}
|
||||
|
||||
|
||||
/********************************************
|
||||
* Produce array of N byte keys from aa.
|
||||
*/
|
||||
|
||||
ArrayRet_t _aaKeys(AA aa, size_t keysize)
|
||||
{
|
||||
byte[] res;
|
||||
size_t resi;
|
||||
|
||||
void _aaKeys_x(aaA* e)
|
||||
{
|
||||
do
|
||||
{
|
||||
memcpy(&res[resi * keysize], cast(byte*)(e + 1), keysize);
|
||||
resi++;
|
||||
if (e.left)
|
||||
{ if (!e.right)
|
||||
{ e = e.left;
|
||||
continue;
|
||||
}
|
||||
_aaKeys_x(e.left);
|
||||
}
|
||||
e = e.right;
|
||||
} while (e != null);
|
||||
}
|
||||
|
||||
auto len = _aaLen(aa);
|
||||
if (!len)
|
||||
return 0;
|
||||
res = cast(byte[])new void[len * keysize];
|
||||
resi = 0;
|
||||
foreach (e; aa.a.b)
|
||||
{
|
||||
if (e)
|
||||
_aaKeys_x(e);
|
||||
}
|
||||
assert(resi == len);
|
||||
|
||||
Array a;
|
||||
a.length = len;
|
||||
a.ptr = res.ptr;
|
||||
return *cast(ArrayRet_t*)(&a);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************
|
||||
* 'apply' for associative arrays - to support foreach
|
||||
*/
|
||||
|
||||
// dg is D, but _aaApply() is C
|
||||
extern (D) typedef int delegate(void *) dg_t;
|
||||
|
||||
int _aaApply(AA aa, size_t keysize, dg_t dg)
|
||||
in
|
||||
{
|
||||
assert(aligntsize(keysize) == keysize);
|
||||
}
|
||||
body
|
||||
{ int result;
|
||||
|
||||
//printf("_aaApply(aa = x%llx, keysize = %d, dg = x%llx)\n", aa.a, keysize, dg);
|
||||
|
||||
int treewalker(aaA* e)
|
||||
{ int result;
|
||||
|
||||
do
|
||||
{
|
||||
//printf("treewalker(e = %p, dg = x%llx)\n", e, dg);
|
||||
result = dg(cast(void *)(e + 1) + keysize);
|
||||
if (result)
|
||||
break;
|
||||
if (e.right)
|
||||
{ if (!e.left)
|
||||
{
|
||||
e = e.right;
|
||||
continue;
|
||||
}
|
||||
result = treewalker(e.right);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
e = e.left;
|
||||
} while (e);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (aa.a)
|
||||
{
|
||||
foreach (e; aa.a.b)
|
||||
{
|
||||
if (e)
|
||||
{
|
||||
result = treewalker(e);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// dg is D, but _aaApply2() is C
|
||||
extern (D) typedef int delegate(void *, void *) dg2_t;
|
||||
|
||||
int _aaApply2(AA aa, size_t keysize, dg2_t dg)
|
||||
in
|
||||
{
|
||||
assert(aligntsize(keysize) == keysize);
|
||||
}
|
||||
body
|
||||
{ int result;
|
||||
|
||||
//printf("_aaApply(aa = x%llx, keysize = %d, dg = x%llx)\n", aa.a, keysize, dg);
|
||||
|
||||
int treewalker(aaA* e)
|
||||
{ int result;
|
||||
|
||||
do
|
||||
{
|
||||
//printf("treewalker(e = %p, dg = x%llx)\n", e, dg);
|
||||
result = dg(cast(void *)(e + 1), cast(void *)(e + 1) + keysize);
|
||||
if (result)
|
||||
break;
|
||||
if (e.right)
|
||||
{ if (!e.left)
|
||||
{
|
||||
e = e.right;
|
||||
continue;
|
||||
}
|
||||
result = treewalker(e.right);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
e = e.left;
|
||||
} while (e);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (aa.a)
|
||||
{
|
||||
foreach (e; aa.a.b)
|
||||
{
|
||||
if (e)
|
||||
{
|
||||
result = treewalker(e);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/***********************************
|
||||
* Construct an associative array of type ti from
|
||||
* length pairs of key/value pairs.
|
||||
*/
|
||||
|
||||
extern (C)
|
||||
BB* _d_assocarrayliteralT(TypeInfo_AssociativeArray ti, size_t length, ...)
|
||||
{
|
||||
auto valuesize = ti.next.tsize(); // value size
|
||||
auto keyti = ti.key;
|
||||
auto keysize = keyti.tsize(); // key size
|
||||
BB* result;
|
||||
|
||||
//printf("_d_assocarrayliteralT(keysize = %d, valuesize = %d, length = %d)\n", keysize, valuesize, length);
|
||||
//writefln("tivalue = %s", ti.next.classinfo.name);
|
||||
if (length == 0 || valuesize == 0 || keysize == 0)
|
||||
{
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
va_list q;
|
||||
va_start!(size_t)(q, length);
|
||||
|
||||
result = new BB();
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < prime_list.length - 1; i++)
|
||||
{
|
||||
if (length <= prime_list[i])
|
||||
break;
|
||||
}
|
||||
auto len = prime_list[i];
|
||||
result.b = new aaA*[len];
|
||||
|
||||
size_t keystacksize = (keysize + int.sizeof - 1) & ~(int.sizeof - 1);
|
||||
size_t valuestacksize = (valuesize + int.sizeof - 1) & ~(int.sizeof - 1);
|
||||
|
||||
size_t keytsize = aligntsize(keysize);
|
||||
|
||||
for (size_t j = 0; j < length; j++)
|
||||
{ void* pkey = q;
|
||||
q += keystacksize;
|
||||
void* pvalue = q;
|
||||
q += valuestacksize;
|
||||
aaA* e;
|
||||
|
||||
auto key_hash = keyti.getHash(pkey);
|
||||
//printf("hash = %d\n", key_hash);
|
||||
i = key_hash % len;
|
||||
auto pe = &result.b[i];
|
||||
while (1)
|
||||
{
|
||||
e = *pe;
|
||||
if (!e)
|
||||
{
|
||||
// Not found, create new elem
|
||||
//printf("create new one\n");
|
||||
e = cast(aaA *) cast(void*) new void[aaA.sizeof + keytsize + valuesize];
|
||||
memcpy(e + 1, pkey, keysize);
|
||||
e.hash = key_hash;
|
||||
*pe = e;
|
||||
result.nodes++;
|
||||
break;
|
||||
}
|
||||
if (key_hash == e.hash)
|
||||
{
|
||||
auto c = keyti.compare(pkey, e + 1);
|
||||
if (c == 0)
|
||||
break;
|
||||
pe = (c < 0) ? &e.left : &e.right;
|
||||
}
|
||||
else
|
||||
pe = (key_hash < e.hash) ? &e.left : &e.right;
|
||||
}
|
||||
memcpy(cast(void *)(e + 1) + keytsize, pvalue, valuesize);
|
||||
}
|
||||
|
||||
va_end(q);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import
|
||||
std.array,
|
||||
std.ctype,
|
||||
std.intrinsic,
|
||||
std.math,
|
||||
std.moduleinit,
|
||||
std.outofmemory,
|
||||
std.stdint,
|
||||
@@ -12,6 +13,9 @@ std.stdarg,
|
||||
std.uni,
|
||||
std.utf,
|
||||
|
||||
//std.format,
|
||||
//std.string,
|
||||
|
||||
std.c.fenv,
|
||||
std.c.locale,
|
||||
std.c.math,
|
||||
|
||||
1563
lphobos/std/format.d
Normal file
1563
lphobos/std/format.d
Normal file
File diff suppressed because it is too large
Load Diff
1954
lphobos/std/math.d
Normal file
1954
lphobos/std/math.d
Normal file
File diff suppressed because it is too large
Load Diff
4083
lphobos/std/string.d
Normal file
4083
lphobos/std/string.d
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
module typeinfos2;
|
||||
|
||||
import
|
||||
//typeinfo2.to_AC,
|
||||
typeinfo2.ti_AC,
|
||||
typeinfo2.ti_Adouble,
|
||||
typeinfo2.ti_Afloat,
|
||||
typeinfo2.ti_Ag,
|
||||
|
||||
6
test/aa1.d
Normal file
6
test/aa1.d
Normal file
@@ -0,0 +1,6 @@
|
||||
module aa1;
|
||||
|
||||
void main()
|
||||
{
|
||||
int[int] aai;
|
||||
}
|
||||
9
test/bug70.d
Normal file
9
test/bug70.d
Normal file
@@ -0,0 +1,9 @@
|
||||
module bug70;
|
||||
|
||||
void main()
|
||||
{
|
||||
for (;false;)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
20
test/bug71.d
Normal file
20
test/bug71.d
Normal file
@@ -0,0 +1,20 @@
|
||||
module bug71;
|
||||
|
||||
void main()
|
||||
{
|
||||
static TypeInfo skipCI(TypeInfo valti)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
if (valti.classinfo.name.length == 18 &&
|
||||
valti.classinfo.name[9..18] == "Invariant")
|
||||
valti = (cast(TypeInfo_Invariant)valti).next;
|
||||
else if (valti.classinfo.name.length == 14 &&
|
||||
valti.classinfo.name[9..14] == "Const")
|
||||
valti = (cast(TypeInfo_Const)valti).next;
|
||||
else
|
||||
break;
|
||||
}
|
||||
return valti;
|
||||
}
|
||||
}
|
||||
8
test/bug72.d
Normal file
8
test/bug72.d
Normal file
@@ -0,0 +1,8 @@
|
||||
module bug72;
|
||||
|
||||
void main()
|
||||
{
|
||||
char c = void;
|
||||
int i = void;
|
||||
c += i;
|
||||
}
|
||||
14
test/bug73.d
Normal file
14
test/bug73.d
Normal file
@@ -0,0 +1,14 @@
|
||||
int find(char[] s, dchar c)
|
||||
{
|
||||
// c is a universal character
|
||||
foreach (int i, dchar c2; s)
|
||||
{
|
||||
if (c == c2)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
}
|
||||
12
test/switch2.d
Normal file
12
test/switch2.d
Normal file
@@ -0,0 +1,12 @@
|
||||
module switch2;
|
||||
|
||||
void main()
|
||||
{
|
||||
int i = 2;
|
||||
switch(i)
|
||||
{
|
||||
case 0: assert(0);
|
||||
case 1,2: printf("hello world\n"); break;
|
||||
default: assert(0);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user