[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:
Tomas Lindquist Olsen
2007-11-20 05:29:20 +01:00
parent adab52fad9
commit a807cbfc91
27 changed files with 8677 additions and 59 deletions

View File

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

View File

@@ -1121,6 +1121,9 @@ struct AddExp : BinExp
Identifier *opId_r();
elem *toElem(IRState *irs);
// LLVMDC
bool llvmFieldIndex;
};
struct MinExp : BinExp

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -82,10 +82,6 @@ IRScope& IRState::scope()
}
llvm::BasicBlock* IRState::scopebb()
{
return scopebegin();
}
llvm::BasicBlock* IRState::scopebegin()
{
IRScope& s = scope();
assert(s.begin);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

1954
lphobos/std/math.d Normal file

File diff suppressed because it is too large Load Diff

4083
lphobos/std/string.d Normal file

File diff suppressed because it is too large Load Diff

View File

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

@@ -0,0 +1,6 @@
module aa1;
void main()
{
int[int] aai;
}

9
test/bug70.d Normal file
View File

@@ -0,0 +1,9 @@
module bug70;
void main()
{
for (;false;)
{
break;
}
}

20
test/bug71.d Normal file
View 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
View File

@@ -0,0 +1,8 @@
module bug72;
void main()
{
char c = void;
int i = void;
c += i;
}

14
test/bug73.d Normal file
View 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
View 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);
}
}