# HG changeset patch # User lindquist # Date 1193796692 -3600 # Node ID b706170e24a904ed5a8c52c386e06d7a75b5ea31 # Parent d7e764e62462616c69b5561d849e3b3dd93a745a [svn r77] Fixed foreach on slice. Fixed some nested function problems when accessing outer function parameters. Major changes to handling of structs. Initial support for unions. Probably more... diff -r d7e764e62462 -r b706170e24a9 demos/qd.d --- a/demos/qd.d Mon Oct 29 03:28:12 2007 +0100 +++ b/demos/qd.d Wed Oct 31 03:11:32 2007 +0100 @@ -1,7 +1,7 @@ -// modified version of scrapple.qd to work with llvmdc -import std.stdio; +module qd; -//version(none) +/* +import std.c.time: sleep; void main() { screen(640, 480); pset(10, 10); @@ -16,8 +16,9 @@ paint(200, 200, Black); pset(10, 11); pset(10, 11, Black); pset(10, 10); - SDL_Delay(5000); + sleep(5); } +*/ extern(C) { struct SDL_Rect { @@ -50,31 +51,90 @@ int SDL_LockSurface(SDL_Surface *); void SDL_UnlockSurface(SDL_Surface *); SDL_Surface * SDL_SetVideoMode(int width, int height, int bpp, uint flags); + SDL_Surface *SDL_CreateRGBSurface(uint flags, int width, int height, int depth, uint Rmask=0, uint Gmask=0, uint Bmask=0, uint Amask=0); int SDL_Flip(SDL_Surface *); - void SDL_Delay(uint); + void SDL_UpdateRect (SDL_Surface *screen, int x, int y, uint w, uint h); + int SDL_UpperBlit(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect); + alias SDL_UpperBlit SDL_BlitSurface; + int SDL_SetAlpha(SDL_Surface *surface, uint flags, ubyte alpha); + int SDL_SetColorKey(SDL_Surface *surface, uint flag, uint key); + int SDL_FillRect(SDL_Surface *dst, SDL_Rect *dstrect, uint color); const uint SDL_SWSURFACE=0; const uint SDL_HWSURFACE=1; const uint SDL_DOUBLEBUF=0x40000000; const uint SDL_FULLSCREEN=0x80000000; + const uint SDL_SRCALPHA=0x00010000; + const uint SDL_SRCCOLORKEY=0x00001000; + void SDL_Delay(uint ms); + uint SDL_GetTicks(); + + enum SDLKey { + Unknown = 0, First = 0, + Escape = 27, + LCtrl = 306, + } + enum SDLMod { + KMOD_NONE = 0x0000, + KMOD_LSHIFT= 0x0001, KMOD_RSHIFT= 0x0002, + KMOD_LCTRL = 0x0040, KMOD_RCTRL = 0x0080, KMOD_CTRL = 0x00C0, + KMOD_LALT = 0x0100, KMOD_RALT = 0x0200, KMOD_ALT = 0x0300, + KMOD_LMETA = 0x0400, KMOD_RMETA = 0x0800, + KMOD_NUM = 0x1000, KMOD_CAPS = 0x2000, KMOD_MODE = 0x4000, + KMOD_RESERVED = 0x8000 + }; + + struct SDL_keysym { ubyte scancode; SDLKey sym; SDLMod mod; ushort unicode; } + enum SDL_EventType : ubyte { + NoEvent=0, Active, KeyDown, KeyUp, + MouseMotion, MouseButtonDown, MouseButtonUp, + JoyAxisMotion, JoyBallMotion, JoyHatMotion, JoyButtonDown, JoyButtonUp, + Quit, SysWMEvent + } + union SDL_Event { + SDL_EventType type; + struct Active { SDL_EventType type, gain, state; }; Active active; + struct Key { SDL_EventType type, which, state; SDL_keysym keysym; }; Key key; + struct Motion { SDL_EventType type, which, state; ushort x, y; short xrel, yrel; }; Motion motion; + struct Button { SDL_EventType type, which, button, state; ushort x, y; }; Button button; + struct Jaxis { SDL_EventType type, which, axis; short value; }; Jaxis jaxis; + struct Jball { SDL_EventType type, which, ball; short xrel, yrel; }; Jball jball; + struct Jhat { SDL_EventType type, which, hat, value; }; Jhat jhat; + struct Jbutton { SDL_EventType type, which, button, state; }; Jbutton jbutton; + struct Resize { SDL_EventType type; int w, h; }; Resize resize; + struct Expose { SDL_EventType type; }; Expose expose; + struct Quit { SDL_EventType type; }; Quit quit; + struct User { SDL_EventType type; int code; void *data1, data2; }; User user; + struct Syswm { SDL_EventType type; void *msg; }; Syswm syswm; + } + + int SDL_PollEvent(SDL_Event *event); } SDL_Surface *display; -void putpixel32(SDL_Surface *surf, int x, int y, ubyte[4] col) { - uint *bufp = cast(uint *)surf.pixels + y*surf.pitch/4 + x; - *bufp = SDL_MapRGBA(surf.format, col[0], col[1], col[2], col[3]); +void putpixel32(int x, int y, ubyte[4] col) { + uint *bufp = cast(uint *)display.pixels + y*display.pitch/4 + x; + *bufp = SDL_MapRGBA(display.format, col[0], col[1], col[2], col[3]); } -void getpixel32(SDL_Surface *surf, int x, int y, ubyte[4] *col) { - uint *bufp = cast(uint *)surf.pixels + y*surf.pitch/4 + x; - SDL_GetRGBA(*bufp, surf.format, &(*col)[0], &(*col)[1], &(*col)[2], &(*col)[3]); +void putpixel32(int x, int y, ubyte[3] col) { + uint *bufp = cast(uint *)display.pixels + y*display.pitch/4 + x; + *bufp = SDL_MapRGBA(display.format, col[0], col[1], col[2], 0); +} + +void getpixel32(int x, int y, ubyte[4] *col) { + uint *bufp = cast(uint *)display.pixels + y*display.pitch/4 + x; + SDL_GetRGBA(*bufp, display.format, &(*col)[0], &(*col)[1], &(*col)[2], &(*col)[3]); } struct rgb { ubyte[3] values; + ubyte r() { return values[0]; } + ubyte g() { return values[1]; } + ubyte b() { return values[2]; } rgb opCat(rgb other) { rgb res; - foreach (id, ref v; res.values) v=(values[id]+other.values[id])/2; + foreach (id, ref v; res.values) v=cast(ubyte)((values[id]+other.values[id])/2); return res; } bool opEquals(rgb r) { @@ -82,9 +142,21 @@ } } -void putpixel(SDL_Surface *surf, int x, int y, rgb c) { - if ( (x<0) || (y<0) || (x!>8; + c[1]=cast(ubyte)(c[1]*178+color.g*77)>>8; + c[2]=cast(ubyte)(c[2]*178+color.b*77)>>8; + putpixel32(x, y, c); + } + } +} + void pset(T...)(int x, int y, T params) { SDL_LockSurface(display); - scope(exit) { SDL_UnlockSurface(display); SDL_Flip(display); } + scope(exit) { SDL_UnlockSurface(display); if (doFlip) flip; } execParams(params); - putpixel(display, x, y, color); + putpixel32(x, y, color.values); } rgb pget(int x, int y) { SDL_LockSurface(display); scope(exit) SDL_UnlockSurface(display); ubyte[4] c; - getpixel32(display, x, y, &c); + getpixel32(x, y, &c); rgb res; res.values[]=c[0..3]; return res; } void swap(T)(ref T a, ref T b) { T c=a; a=b; b=c; } - -T abs(T)(T f) { return f < 0 ? -f : f; } +T abs(T)(T a) { return (a<0) ? -a : a; } void bresenham(bool countUp=true, bool steep=false)(int x0, int y0, int x1, int y1) { auto deltax = x1 - x0, deltay = y1 - y0; @@ -163,9 +262,10 @@ const string name="x"; } auto error = 0f; + ubyte[4] col; col[0..3]=color.values; for (auto var1 = mixin(name~'0'); var1 <= mixin(name~'1'); ++var1) { - static if (steep) putpixel(display, var2, var1, color); - else putpixel(display, var1, var2, color); + static if (steep) putpixel(var2, var1, col); + else putpixel(var1, var2, col); error += Δerror; if (abs(error) >= 1f) { static if (countUp) { var2++; error -= 1f; } else { var2--; error += 1f; }} } @@ -178,13 +278,10 @@ execParams(p); static if (select!(back_rgb, T)!=-1) { SDL_LockSurface(display); - scope(exit) { SDL_UnlockSurface(display); SDL_Flip(display); } - auto xend=max(x0, x1); - for (int x=min(x0, x1); x<=xend; ++x) { - auto yend=max(y0, y1); - for (int y=min(y0, y1); y<=yend; ++y) { - putpixel(display, x, y, back); - } + scope(exit) { SDL_UnlockSurface(display); if (doFlip) flip; } + auto yend=max(y0, y1); + for (int y=min(y0, y1); y<=yend; ++y) { + hline(min(x0, x1), y, max(x0, x1)-min(x0, x1), back); } } static if (select!(box_rgb, T)!=-1) { @@ -195,7 +292,7 @@ } static if (select!(box_rgb, T)+select!(back_rgb, T)==-2) { SDL_LockSurface(display); - scope(exit) { SDL_UnlockSurface(display); SDL_Flip(display); } + scope(exit) { SDL_UnlockSurface(display); if (doFlip) flip; } bool steep = abs(y1 - y0) > abs(x1 - x0); void turn() { swap(x0, x1); swap(y0, y1); } if (steep) { if (y1 < y0) turn; } @@ -226,10 +323,10 @@ auto stopx="~(first?"y2square*xradius":"0")~"; auto stopy="~(first?"0":"x2square*yradius")~"; while (stopx"~(first?">=":"<=")~"stopy) { - putpixel(display, cx+x, cy+y, color); - putpixel(display, cx+x, cy-y, color); - putpixel(display, cx-x, cy+y, color); - putpixel(display, cx-x, cy-y, color); + putpixel(cx+x, cy+y, col); + putpixel(cx+x, cy-y, col); + putpixel(cx-x, cy+y, col); + putpixel(cx-x, cy-y, col); "~yx~"++; stop"~yx~"+="~xy~"2square; error+="~yx~"change; @@ -244,26 +341,37 @@ "; } -void circle(T...)(int cx, int cy, int xradius, T t) { +import std.stdio; +void circle(T...)(T t) { + static assert(T.length!<3, "Circle: Needs x, y and radius"); + int cx=t[0], cy=t[1], xradius=t[2]; SDL_LockSurface(display); - scope(exit) { SDL_UnlockSurface(display); SDL_Flip(display); } - execParams(t); + scope(exit) { SDL_UnlockSurface(display); if (doFlip) flip; } + execParams(t[3..$]); auto yradius=xradius; - static if (T.length && is(T[0]: int)) yradius=t[0]; + if (xradius!>0) return; + static if (T.length>3 && is(T[3]: int)) yradius=t[3]; static if (select!(back_rgb, T) != -1) { auto ratio=xradius*1f/yradius; + auto back_sdl=SDL_MapRGBA(display.format, back.values[0], back.values[1], back.values[2], 0); for (int i=0; i<=yradius; ++i) { ushort j=cast(ushort)(sqrt(cast(real)(yradius*yradius-i*i))*ratio); - for (int lx=cx-j; lx<=cx+j; ++lx) putpixel(display, lx, cy+i, back); - for (int lx=cx-j; lx<=cx+j; ++lx) putpixel(display, lx, cy-i, back); + hline(cx-j, cy+i, 2*j, back_sdl); + hline(cx-j, cy-i, 2*j, back_sdl); } } auto x2square=2*xradius*xradius; auto y2square=2*yradius*yradius; + ubyte[4] col; col[0..3]=color.values; { mixin(circle_bresenham_pass!(true).str); } { mixin(circle_bresenham_pass!(false).str); } } +float distance(float x1, float y1, float x2, float y2) { + auto x=x1-x2, y=y1-y2; + return sqrt(x*x+y*y); +} + struct floodfill_node { int x, y; static floodfill_node opCall(int x, int y) { @@ -275,7 +383,7 @@ void paint(T...)(int x, int y, T t) { SDL_LockSurface(display); - scope(exit) { SDL_UnlockSurface(display); SDL_Flip(display); } + scope(exit) { SDL_UnlockSurface(display); if (doFlip) flip; } execParams(t); bool border=true; if (select!(back_rgb, T) == -1) { @@ -300,7 +408,7 @@ if (e>=0) do e--; while (e>=0 && check(pget(e, y))); //SDL_Flip(display); for (int i=e+1; i +#include +#include struct Identifier; struct Type; @@ -101,7 +103,8 @@ llvm::Constant* llvmVtbl; llvm::ConstantStruct* llvmConstVtbl; llvm::Constant* llvmInitZ; - virtual void offsetToIndex(Type* t, unsigned os, std::vector& result); // converts a DMD field offsets to LLVM struct index vector + bool llvmHasUnions; + virtual size_t offsetToIndex(Type* t, unsigned os, std::vector& result); // converts a DMD field offsets to LLVM struct index vector AggregateDeclaration *isAggregateDeclaration() { return this; } }; @@ -237,7 +240,7 @@ Symbol *vtblsym; - virtual void offsetToIndex(Type* t, unsigned os, std::vector& result); + virtual size_t offsetToIndex(Type* t, unsigned os, std::vector& result); ClassDeclaration *isClassDeclaration() { return (ClassDeclaration *)this; } }; diff -r d7e764e62462 -r b706170e24a9 dmd/attrib.c --- a/dmd/attrib.c Mon Oct 29 03:28:12 2007 +0100 +++ b/dmd/attrib.c Wed Oct 31 03:11:32 2007 +0100 @@ -887,13 +887,17 @@ llvm_internal = LLVMva_intrinsic; assert(args->dim == 2); } + else if (strcmp(str,"notypeinfo")==0) { + llvm_internal = LLVMnotypeinfo; + assert(args->dim == 1); + } else { error("unknown pragma command: %s", str); } } else error("1st argument must be a string"); - + if (llvm_internal) switch (llvm_internal) { @@ -910,12 +914,13 @@ else error("2nd argument must be a string"); break; - + case LLVMnull: case LLVMva_arg: case LLVMva_start: + case LLVMnotypeinfo: break; - + default: assert(0); } @@ -988,6 +993,10 @@ } break; + case LLVMnotypeinfo: + s->llvmInternal = llvm_internal; + break; + default: assert(0 && "invalid LLVM_internal pragma got through :/"); } diff -r d7e764e62462 -r b706170e24a9 dmd/declaration.c --- a/dmd/declaration.c Mon Oct 29 03:28:12 2007 +0100 +++ b/dmd/declaration.c Wed Oct 31 03:11:32 2007 +0100 @@ -550,6 +550,8 @@ canassign = 0; value = NULL; llvmNestedIndex = -1; + llvmFieldIndex = -1; + llvmFieldIndexOffset = 0; } Dsymbol *VarDeclaration::syntaxCopy(Dsymbol *s) diff -r d7e764e62462 -r b706170e24a9 dmd/declaration.h --- a/dmd/declaration.h Mon Oct 29 03:28:12 2007 +0100 +++ b/dmd/declaration.h Wed Oct 31 03:11:32 2007 +0100 @@ -260,6 +260,8 @@ // LLVMDC int llvmNestedIndex; + int llvmFieldIndex; + size_t llvmFieldIndexOffset; }; /**************************************************************/ diff -r d7e764e62462 -r b706170e24a9 dmd/struct.c --- a/dmd/struct.c Mon Oct 29 03:28:12 2007 +0100 +++ b/dmd/struct.c Wed Oct 31 03:11:32 2007 +0100 @@ -50,6 +50,7 @@ llvmConstVtbl = NULL; llvmInitZ = NULL; llvmInProgress = false; + llvmHasUnions = false; } enum PROT AggregateDeclaration::prot() diff -r d7e764e62462 -r b706170e24a9 gen/enums.h --- a/gen/enums.h Mon Oct 29 03:28:12 2007 +0100 +++ b/gen/enums.h Wed Oct 31 03:11:32 2007 +0100 @@ -7,5 +7,6 @@ LLVMbind, LLVMva_arg, LLVMva_start, - LLVMva_intrinsic + LLVMva_intrinsic, + LLVMnotypeinfo }; diff -r d7e764e62462 -r b706170e24a9 gen/irstate.c --- a/gen/irstate.c Mon Oct 29 03:28:12 2007 +0100 +++ b/gen/irstate.c Wed Oct 31 03:11:32 2007 +0100 @@ -15,7 +15,7 @@ #include "tollvm.h" IRState* gIR = 0; -llvm::TargetData* gTargetData = 0; +const llvm::TargetData* gTargetData = 0; ////////////////////////////////////////////////////////////////////////////////////////// IRScope::IRScope() diff -r d7e764e62462 -r b706170e24a9 gen/irstate.h --- a/gen/irstate.h Mon Oct 29 03:28:12 2007 +0100 +++ b/gen/irstate.h Wed Oct 31 03:11:32 2007 +0100 @@ -4,13 +4,14 @@ #include #include #include +#include #include "root.h" // global ir state for current module struct IRState; extern IRState* gIR; -extern llvm::TargetData* gTargetData; +extern const llvm::TargetData* gTargetData; struct TypeFunction; struct TypeStruct; @@ -40,20 +41,28 @@ // represents a struct or class struct IRStruct { - typedef std::vector TypeVector; - typedef std::vector ConstantVector; - typedef std::vector FuncDeclVec; + struct Offset + { + VarDeclaration* var; + llvm::Constant* init; + + Offset(VarDeclaration* v, llvm::Constant* i) + : var(v), init(i) {} + }; + + typedef std::vector FuncDeclVector; + typedef std::multimap OffsetMap; public: IRStruct(); IRStruct(Type*); Type* type; - TypeVector fields; - ConstantVector inits; llvm::PATypeHolder recty; - FuncDeclVec funcs; + FuncDeclVector funcs; bool queueFuncs; + + OffsetMap offsets; }; // represents a finally block diff -r d7e764e62462 -r b706170e24a9 gen/statements.c --- a/gen/statements.c Mon Oct 29 03:28:12 2007 +0100 +++ b/gen/statements.c Wed Oct 31 03:11:32 2007 +0100 @@ -672,8 +672,14 @@ } else if (aggrtype->ty == Tarray) { - numiters = p->ir->CreateLoad(LLVM_DtoGEPi(val,0,0,"tmp",p->scopebb())); - val = p->ir->CreateLoad(LLVM_DtoGEPi(val,0,1,"tmp",p->scopebb())); + if (arr->type == elem::SLICE) { + numiters = arr->arg; + val = arr->mem; + } + else { + numiters = p->ir->CreateLoad(LLVM_DtoGEPi(val,0,0,"tmp",p->scopebb())); + val = p->ir->CreateLoad(LLVM_DtoGEPi(val,0,1,"tmp",p->scopebb())); + } } else { diff -r d7e764e62462 -r b706170e24a9 gen/toir.c --- a/gen/toir.c Mon Oct 29 03:28:12 2007 +0100 +++ b/gen/toir.c Wed Oct 31 03:11:32 2007 +0100 @@ -1449,17 +1449,27 @@ TypeStruct* vdt = (TypeStruct*)vdtype; assert(vdt->sym); e = new elem; - bool donormally = true; + const llvm::Type* llt = LLVM_DtoType(t); if (offset == 0) { - const llvm::Type* llt = LLVM_DtoType(t); e->mem = p->ir->CreateBitCast(llvalue, llt, "tmp"); } else { std::vector dst(1,0); - vdt->sym->offsetToIndex(tnext, offset, dst); + size_t fo = vdt->sym->offsetToIndex(tnext, offset, dst); llvm::Value* ptr = llvalue; assert(ptr); e->mem = LLVM_DtoGEP(ptr,dst,"tmp"); + if (e->mem->getType() != llt) { + e->mem = p->ir->CreateBitCast(e->mem, llt, "tmp"); + } + if (fo == (size_t)-1) { + size_t llt_sz = gTargetData->getTypeSize(llt->getContainedType(0)); + assert(offset % llt_sz == 0); + e->mem = new llvm::GetElementPtrInst(e->mem, LLVM_DtoConstUint(offset / llt_sz), "tmp", p->scopebb()); + } + else if (fo) { + e->mem = new llvm::GetElementPtrInst(e->mem, LLVM_DtoConstUint(fo), "tmp", p->scopebb()); + } } e->type = elem::VAL; e->field = true; @@ -1678,29 +1688,52 @@ llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); - unsigned n = elements->dim; - for (unsigned i=0; iscopebb()); - - Expression* vx = (Expression*)elements->data[i]; - if (vx != 0) { - p->exps.push_back(IRExp(NULL,vx,arrptr)); - elem* ve = vx->toElem(p); - p->exps.pop_back(); - - if (!ve->inplace) { - llvm::Value* val = ve->getValue(); - Logger::cout() << *val << " | " << *arrptr << '\n'; - - Type* vxtype = LLVM_DtoDType(vx->type); - LLVM_DtoAssign(vxtype, arrptr, val); + if (sd->isUnionDeclaration()) { + Logger::println("num elements = %d", elements->dim); + //assert(elements->dim == 1); + Expression* vx = (Expression*)elements->data[0]; + assert(vx); + + Type* vxtype = LLVM_DtoDType(vx->type); + const llvm::Type* llvxty = llvm::PointerType::get(LLVM_DtoType(vxtype)); + llvm::Value* arrptr = p->ir->CreateBitCast(sptr, llvxty, "tmp"); + + p->exps.push_back(IRExp(NULL,vx,arrptr)); + elem* ve = vx->toElem(p); + p->exps.pop_back(); + + if (!ve->inplace) { + llvm::Value* val = ve->getValue(); + Logger::cout() << *val << " | " << *arrptr << '\n'; + LLVM_DtoAssign(vxtype, arrptr, val); + } + delete ve; + } + else { + unsigned n = elements->dim; + for (unsigned i=0; iscopebb()); + + Expression* vx = (Expression*)elements->data[i]; + if (vx != 0) { + p->exps.push_back(IRExp(NULL,vx,arrptr)); + elem* ve = vx->toElem(p); + p->exps.pop_back(); + + if (!ve->inplace) { + llvm::Value* val = ve->getValue(); + Logger::cout() << *val << " | " << *arrptr << '\n'; + + Type* vxtype = LLVM_DtoDType(vx->type); + LLVM_DtoAssign(vxtype, arrptr, val); + } + delete ve; } - delete ve; - } - else { - assert(0); + else { + assert(0); + } } } @@ -1835,8 +1868,13 @@ else if (e1type->ty == Tsarray) { e->mem = LLVM_DtoGEP(v->mem,zero,lo->getValue(),"tmp",p->scopebb()); } - else - assert(0); + else if (e1type->ty == Tpointer) { + e->mem = new llvm::GetElementPtrInst(v->getValue(),lo->getValue(),"tmp",p->scopebb()); + } + else { + Logger::println("type = %s", e1type->toChars()); + assert(0); + } } elem* up = upr->toElem(p); @@ -2559,8 +2597,8 @@ elem* e = new elem; - llvm::Value* l = u->getValue(); - llvm::Value* r = v->getValue(); + llvm::Value* l = u->field ? u->mem : u->getValue(); + llvm::Value* r = v->field ? v->mem : v->getValue(); Type* t1 = LLVM_DtoDType(e1->type); @@ -2578,6 +2616,7 @@ if (t1->ty == Tpointer && v->type == elem::NUL && l->getType() != r->getType()) { r = llvm::ConstantPointerNull::get(llvm::cast(l->getType())); } + Logger::cout() << "l = " << *l << " r = " << *r << '\n'; e->val = new llvm::ICmpInst(pred, l, r, "tmp", p->scopebb()); } e->type = elem::VAL; diff -r d7e764e62462 -r b706170e24a9 gen/tollvm.c --- a/gen/tollvm.c Mon Oct 29 03:28:12 2007 +0100 +++ b/gen/tollvm.c Wed Oct 31 03:11:32 2007 +0100 @@ -17,15 +17,8 @@ bool LLVM_DtoIsPassedByRef(Type* type) { - TY t = type->ty; - if (t == Tstruct || t == Tarray || t == Tdelegate) - return true; - else if (t == Ttypedef) { - Type* bt = type->toBasetype(); - assert(bt); - return LLVM_DtoIsPassedByRef(bt); - } - return false; + TY t = LLVM_DtoDType(type)->ty; + return (t == Tstruct || t == Tarray || t == Tdelegate); } Type* LLVM_DtoDType(Type* t) @@ -530,12 +523,10 @@ assert(vd); Logger::println("vars[%d] = %s", i, vd->toChars()); - std::vector idxs; - si->ad->offsetToIndex(vdtype, vd->offset, idxs); - assert(idxs.size() == 1); - unsigned idx = idxs[0]; + llvm::Constant* v = 0; - llvm::Constant* v = 0; + assert(vd->llvmFieldIndex >= 0); + unsigned idx = vd->llvmFieldIndex; if (ExpInitializer* ex = ini->isExpInitializer()) { @@ -557,6 +548,7 @@ assert(v); inits[idx] = v; + Logger::cout() << "init[" << idx << "] = " << *v << '\n'; } // fill out nulls @@ -1271,8 +1263,10 @@ // on this stack if (fd == f) { llvm::Value* v = LLVM_DtoGEPi(vd->llvmValue,0,unsigned(vd->llvmNestedIndex),"tmp"); - if (vd->isParameter() && (vd->isRef() || vd->isOut())) + if (vd->isParameter() && (vd->isRef() || vd->isOut() || LLVM_DtoIsPassedByRef(vd->type))) { + Logger::cout() << "1267 loading: " << *v << '\n'; v = gIR->ir->CreateLoad(v,"tmp"); + } return v; } @@ -1293,8 +1287,10 @@ while (f) { if (fd == f) { llvm::Value* v = LLVM_DtoGEPi(ptr,0,vd->llvmNestedIndex,"tmp"); - if (vd->isParameter() && (vd->isRef() || vd->isOut())) + if (vd->isParameter() && (vd->isRef() || vd->isOut() || LLVM_DtoIsPassedByRef(vd->type))) { + Logger::cout() << "1291 loading: " << *v << '\n'; v = gIR->ir->CreateLoad(v,"tmp"); + } return v; } else { diff -r d7e764e62462 -r b706170e24a9 gen/toobj.c --- a/gen/toobj.c Mon Oct 29 03:28:12 2007 +0100 +++ b/gen/toobj.c Wed Oct 31 03:11:32 2007 +0100 @@ -65,7 +65,15 @@ ir.module->setTargetTriple(target_triple); ir.module->setDataLayout(global.params.data_layout); - gTargetData = new llvm::TargetData(ir.module); + // heavily inspired by tools/llc/llc.cpp:200-230 + const llvm::TargetMachineRegistry::Entry* targetEntry; + std::string targetError; + targetEntry = llvm::TargetMachineRegistry::getClosestStaticTargetForModule(*ir.module, targetError); + assert(targetEntry && "Failed to find a static target for module"); + std::auto_ptr targetPtr(targetEntry->CtorFn(*ir.module, "")); // TODO: replace "" with features + assert(targetPtr.get() && "Could not allocate target machine!"); + llvm::TargetMachine &targetMachine = *targetPtr.get(); + gTargetData = targetMachine.getTargetData(); // process module members for (int k=0; k < members->dim; k++) { @@ -74,7 +82,6 @@ dsym->toObjFile(); } - delete gTargetData; gTargetData = 0; // emit the llvm main function if necessary @@ -142,7 +149,7 @@ /* ================================================================== */ /// Returns the LLVM style index from a DMD style offset -void AggregateDeclaration::offsetToIndex(Type* t, unsigned os, std::vector& result) +size_t AggregateDeclaration::offsetToIndex(Type* t, unsigned os, std::vector& result) { Logger::println("checking for offset %u type %s:", os, t->toChars()); LOG_SCOPE; @@ -151,18 +158,19 @@ Type* vdtype = LLVM_DtoDType(vd->type); Logger::println("found %u type %s", vd->offset, vdtype->toChars()); if (os == vd->offset && vdtype == t) { - result.push_back(i); - return; + assert(vd->llvmFieldIndex >= 0); + result.push_back(vd->llvmFieldIndex); + return vd->llvmFieldIndexOffset; } else if (vdtype->ty == Tstruct && (vd->offset + vdtype->size()) > os) { TypeStruct* ts = (TypeStruct*)vdtype; StructDeclaration* sd = ts->sym; result.push_back(i); - sd->offsetToIndex(t, os - vd->offset, result); - return; + return sd->offsetToIndex(t, os - vd->offset, result); } } - assert(0 && "Offset not found in any aggregate field"); + //assert(0 && "Offset not found in any aggregate field"); + return (size_t)-1; } /* ================================================================== */ @@ -190,12 +198,13 @@ /// Returns the LLVM style index from a DMD style offset /// Handles class inheritance -void ClassDeclaration::offsetToIndex(Type* t, unsigned os, std::vector& result) +size_t ClassDeclaration::offsetToIndex(Type* t, unsigned os, std::vector& result) { unsigned idx = 0; unsigned r = LLVM_ClassOffsetToIndex(this, os, idx); assert(r != (unsigned)-1 && "Offset not found in any aggregate field"); result.push_back(r+1); // vtable is 0 + return 0; } /* ================================================================== */ @@ -224,14 +233,98 @@ dsym->toObjFile(); } - if (gIR->topstruct().fields.empty()) + Logger::println("doing struct fields"); + + llvm::StructType* structtype = 0; + std::vector fieldinits; + + if (gIR->topstruct().offsets.empty()) + { + std::vector fieldtypes; + Logger::println("has no fields"); + fieldtypes.push_back(llvm::Type::Int8Ty); + fieldinits.push_back(llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false)); + structtype = llvm::StructType::get(fieldtypes); + } + else { - gIR->topstruct().fields.push_back(llvm::Type::Int8Ty); - gIR->topstruct().inits.push_back(llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false)); + Logger::println("has fields"); + std::vector fieldtypes; + unsigned prevsize = (unsigned)-1; + unsigned lastoffset = (unsigned)-1; + const llvm::Type* fieldtype = NULL; + llvm::Constant* fieldinit = NULL; + size_t fieldpad = 0; + int idx = 0; + for (IRStruct::OffsetMap::iterator i=gIR->topstruct().offsets.begin(); i!=gIR->topstruct().offsets.end(); ++i) { + // first iteration + if (lastoffset == (unsigned)-1) { + lastoffset = i->first; + assert(lastoffset == 0); + fieldtype = LLVM_DtoType(i->second.var->type); + fieldinit = i->second.init; + prevsize = gTargetData->getTypeSize(fieldtype); + i->second.var->llvmFieldIndex = idx; + } + // colliding offset? + else if (lastoffset == i->first) { + const llvm::Type* t = LLVM_DtoType(i->second.var->type); + size_t s = gTargetData->getTypeSize(t); + if (s > prevsize) { + fieldpad = s - prevsize; + prevsize = s; + } + llvmHasUnions = true; + i->second.var->llvmFieldIndex = idx; + } + // intersecting offset? + else if (i->first < (lastoffset + prevsize)) { + const llvm::Type* t = LLVM_DtoType(i->second.var->type); + size_t s = gTargetData->getTypeSize(t); + assert((i->first + s) <= (lastoffset + prevsize)); // this holds because all types are aligned to their size + llvmHasUnions = true; + i->second.var->llvmFieldIndex = idx; + i->second.var->llvmFieldIndexOffset = (i->first - lastoffset) / s; + } + // fresh offset + else { + // commit the field + fieldtypes.push_back(fieldtype); + fieldinits.push_back(fieldinit); + if (fieldpad) { + // match up with below + std::vector vals(fieldpad, llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false)); + llvm::Constant* c = llvm::ConstantArray::get(llvm::ArrayType::get(llvm::Type::Int8Ty, fieldpad), vals); + fieldtypes.push_back(c->getType()); + fieldinits.push_back(c); + idx++; + } + + idx++; + + // start new + lastoffset = i->first; + fieldtype = LLVM_DtoType(i->second.var->type); + fieldinit = i->second.init; + prevsize = gTargetData->getTypeSize(fieldtype); + i->second.var->llvmFieldIndex = idx; + fieldpad = 0; + } + } + fieldtypes.push_back(fieldtype); + fieldinits.push_back(fieldinit); + if (fieldpad) { + // match up with above + std::vector vals(fieldpad, llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false)); + llvm::Constant* c = llvm::ConstantArray::get(llvm::ArrayType::get(llvm::Type::Int8Ty, fieldpad), vals); + fieldtypes.push_back(c->getType()); + fieldinits.push_back(c); + } + + Logger::println("creating struct type"); + structtype = llvm::StructType::get(fieldtypes); } - llvm::StructType* structtype = llvm::StructType::get(gIR->topstruct().fields); - // refine abstract types for stuff like: struct S{S* next;} if (gIR->topstruct().recty != 0) { @@ -254,18 +347,18 @@ // always generate the constant initalizer if (!zeroInit) { Logger::println("Not zero initialized"); - //assert(tk == gIR->topstruct().size()); + //assert(tk == gIR->gIR->topstruct()().size()); #ifndef LLVMD_NO_LOGGER - Logger::cout() << *structtype << '\n'; - for (size_t k=0; ktopstruct().inits.size(); ++k) { + Logger::cout() << "struct type: " << *structtype << '\n'; + for (size_t k=0; ktopstruct().inits[k]->getType() << '\n'; + Logger::cout() << *fieldinits[k]->getType() << '\n'; Logger::cout() << "Value:" << '\n'; - Logger::cout() << *gIR->topstruct().inits[k] << '\n'; + Logger::cout() << *fieldinits[k] << '\n'; } Logger::cout() << "Initializer printed" << '\n'; #endif - llvmInitZ = llvm::ConstantStruct::get(structtype,gIR->topstruct().inits); + llvmInitZ = llvm::ConstantStruct::get(structtype,fieldinits); } else { Logger::println("Zero initialized"); @@ -278,14 +371,15 @@ _init = llvmInitZ; } - std::string initname(mangle()); - initname.append("__initZ"); + std::string initname("_D"); + initname.append(mangle()); + initname.append("6__initZ"); llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType, true, _linkage, _init, initname, gIR->module); ts->llvmInit = initvar; // generate member function definitions gIR->topstruct().queueFuncs = false; - IRStruct::FuncDeclVec& mfs = gIR->topstruct().funcs; + IRStruct::FuncDeclVector& mfs = gIR->topstruct().funcs; size_t n = mfs.size(); for (size_t i=0; itoObjFile(); @@ -296,7 +390,7 @@ gIR->structs.pop_back(); // generate typeinfo - if (getModule() == gIR->dmodule) + if (getModule() == gIR->dmodule && llvmInternal != LLVMnotypeinfo) type->getTypeInfo(NULL); } @@ -341,8 +435,12 @@ // add vtable llvm::PATypeHolder pa = llvm::OpaqueType::get(); const llvm::Type* vtabty = llvm::PointerType::get(pa); - gIR->topstruct().fields.push_back(vtabty); - gIR->topstruct().inits.push_back(0); + + std::vector fieldtypes; + fieldtypes.push_back(vtabty); + + std::vector fieldinits; + fieldinits.push_back(0); // base classes first LLVM_AddBaseClassData(&baseclasses); @@ -353,7 +451,13 @@ dsym->toObjFile(); } - llvm::StructType* structtype = llvm::StructType::get(gIR->topstruct().fields); + // fill out fieldtypes/inits + for (IRStruct::OffsetMap::iterator i=gIR->topstruct().offsets.begin(); i!=gIR->topstruct().offsets.end(); ++i) { + fieldtypes.push_back(LLVM_DtoType(i->second.var->type)); + fieldinits.push_back(i->second.init); + } + + llvm::StructType* structtype = llvm::StructType::get(fieldtypes); // refine abstract types for stuff like: class C {C next;} if (gIR->topstruct().recty != 0) { @@ -441,9 +545,9 @@ // first field is always the vtable assert(svtblVar != 0); - gIR->topstruct().inits[0] = svtblVar; + fieldinits[0] = svtblVar; - llvmInitZ = _init = llvm::ConstantStruct::get(structtype,gIR->topstruct().inits); + llvmInitZ = _init = llvm::ConstantStruct::get(structtype,fieldinits); assert(_init); std::string initname("_D"); @@ -457,7 +561,7 @@ initvar->setInitializer(_init); // generate member functions gIR->topstruct().queueFuncs = false; - IRStruct::FuncDeclVec& mfs = gIR->topstruct().funcs; + IRStruct::FuncDeclVector& mfs = gIR->topstruct().funcs; size_t n = mfs.size(); for (size_t i=0; itoObjFile(); @@ -573,7 +677,6 @@ Type* t = LLVM_DtoDType(type); const llvm::Type* _type = LLVM_DtoType(t); - gIR->topstruct().fields.push_back(_type); llvm::Constant*_init = LLVM_DtoConstInitializer(t, init); assert(_init); @@ -610,7 +713,9 @@ assert(0); } } - gIR->topstruct().inits.push_back(_init); + + // add the field in the IRStruct + gIR->topstruct().offsets.insert(std::make_pair(offset, IRStruct::Offset(this,_init))); } Logger::println("VarDeclaration::toObjFile is done"); diff -r d7e764e62462 -r b706170e24a9 gen/typinf.c --- a/gen/typinf.c Mon Oct 29 03:28:12 2007 +0100 +++ b/gen/typinf.c Wed Oct 31 03:11:32 2007 +0100 @@ -324,7 +324,7 @@ // create the symbol llvm::Constant* tiInit = llvm::ConstantStruct::get(stype, sinits); - llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::InternalLinkage,tiInit,toChars(),gIR->module); + llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,tiInit,toChars(),gIR->module); llvmValue = gvar; } @@ -389,7 +389,7 @@ // create the symbol llvm::Constant* tiInit = llvm::ConstantStruct::get(stype, sinits); - llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::InternalLinkage,tiInit,toChars(),gIR->module); + llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,tiInit,toChars(),gIR->module); llvmValue = gvar; } @@ -421,7 +421,7 @@ // create the symbol llvm::Constant* tiInit = llvm::ConstantStruct::get(stype, sinits); - llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::InternalLinkage,tiInit,tid->toChars(),gIR->module); + llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,tiInit,tid->toChars(),gIR->module); tid->llvmValue = gvar; } @@ -545,6 +545,7 @@ // char[] name char *name = sd->toPrettyChars(); sinits.push_back(LLVM_DtoConstString(name)); + Logger::println("************** A"); assert(sinits.back()->getType() == stype->getElementType(1)); // void[] init @@ -606,6 +607,7 @@ } #endif + Logger::println("************** B"); const llvm::PointerType* ptty = llvm::cast(stype->getElementType(3)); s = search_function(sd, Id::tohash); @@ -633,6 +635,7 @@ fdx = s ? s->isFuncDeclaration() : NULL; for (int i = 0; i < 2; i++) { + Logger::println("************** C %d", i); ptty = llvm::cast(stype->getElementType(4+i)); if (fdx) { @@ -657,6 +660,7 @@ fdx = s ? s->isFuncDeclaration() : NULL; } + Logger::println("************** D"); ptty = llvm::cast(stype->getElementType(6)); s = search_function(sd, Id::tostring); fdx = s ? s->isFuncDeclaration() : NULL; @@ -684,144 +688,9 @@ // create the symbol llvm::Constant* tiInit = llvm::ConstantStruct::get(stype, sinits); - llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::InternalLinkage,tiInit,toChars(),gIR->module); + llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,tiInit,toChars(),gIR->module); llvmValue = gvar; - - /* - //printf("TypeInfoStructDeclaration::toDt() '%s'\n", toChars()); - - unsigned offset = Type::typeinfostruct->structsize; - - dtxoff(pdt, Type::typeinfostruct->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Struct - dtdword(pdt, 0); // monitor - - assert(tinfo->ty == Tstruct); - - TypeStruct *tc = (TypeStruct *)tinfo; - StructDeclaration *sd = tc->sym; - -// Put out: -// char[] name; -// void[] init; -// hash_t function(void*) xtoHash; -// int function(void*,void*) xopEquals; -// int function(void*,void*) xopCmp; -// char[] function(void*) xtoString; -// uint m_flags; -// -// name[] -// - - char *name = sd->toPrettyChars(); - size_t namelen = strlen(name); - dtdword(pdt, namelen); - //dtabytes(pdt, TYnptr, 0, namelen + 1, name); - dtxoff(pdt, toSymbol(), offset, TYnptr); - offset += namelen + 1; - - // void[] init; - dtdword(pdt, sd->structsize); // init.length - if (sd->zeroInit) - dtdword(pdt, 0); // NULL for 0 initialization - else - dtxoff(pdt, sd->toInitializer(), 0, TYnptr); // init.ptr - - FuncDeclaration *fd; - FuncDeclaration *fdx; - TypeFunction *tf; - Type *ta; - Dsymbol *s; - - static TypeFunction *tftohash; - static TypeFunction *tftostring; - - if (!tftohash) - { - Scope sc; - - tftohash = new TypeFunction(NULL, Type::thash_t, 0, LINKd); - tftohash = (TypeFunction *)tftohash->semantic(0, &sc); - - tftostring = new TypeFunction(NULL, Type::tchar->arrayOf(), 0, LINKd); - tftostring = (TypeFunction *)tftostring->semantic(0, &sc); - } - - TypeFunction *tfeqptr; - { - Scope sc; - Arguments *arguments = new Arguments; - Argument *arg = new Argument(STCin, tc->pointerTo(), NULL, NULL); - - arguments->push(arg); - tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd); - tfeqptr = (TypeFunction *)tfeqptr->semantic(0, &sc); - } - -#if 0 - TypeFunction *tfeq; - { - Scope sc; - Array *arguments = new Array; - Argument *arg = new Argument(In, tc, NULL, NULL); - - arguments->push(arg); - tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd); - tfeq = (TypeFunction *)tfeq->semantic(0, &sc); - } -#endif - - s = search_function(sd, Id::tohash); - fdx = s ? s->isFuncDeclaration() : NULL; - if (fdx) - { fd = fdx->overloadExactMatch(tftohash); - if (fd) - dtxoff(pdt, fd->toSymbol(), 0, TYnptr); - else - //fdx->error("must be declared as extern (D) uint toHash()"); - dtdword(pdt, 0); - } - else - dtdword(pdt, 0); - - s = search_function(sd, Id::eq); - fdx = s ? s->isFuncDeclaration() : NULL; - for (int i = 0; i < 2; i++) - { - if (fdx) - { fd = fdx->overloadExactMatch(tfeqptr); - if (fd) - dtxoff(pdt, fd->toSymbol(), 0, TYnptr); - else - //fdx->error("must be declared as extern (D) int %s(%s*)", fdx->toChars(), sd->toChars()); - dtdword(pdt, 0); - } - else - dtdword(pdt, 0); - - s = search_function(sd, Id::cmp); - fdx = s ? s->isFuncDeclaration() : NULL; - } - - s = search_function(sd, Id::tostring); - fdx = s ? s->isFuncDeclaration() : NULL; - if (fdx) - { fd = fdx->overloadExactMatch(tftostring); - if (fd) - dtxoff(pdt, fd->toSymbol(), 0, TYnptr); - else - //fdx->error("must be declared as extern (D) char[] toString()"); - dtdword(pdt, 0); - } - else - dtdword(pdt, 0); - - // uint m_flags; - dtdword(pdt, tc->hasPointers()); - - // name[] - dtnbytes(pdt, namelen + 1, name); - */ } /* ========================================================================= */ diff -r d7e764e62462 -r b706170e24a9 lphobos/internal/objectimpl.d --- a/lphobos/internal/objectimpl.d Mon Oct 29 03:28:12 2007 +0100 +++ b/lphobos/internal/objectimpl.d Wed Oct 31 03:11:32 2007 +0100 @@ -974,7 +974,7 @@ return h; } - int equals(void *p2, void *p1) + int equals(void *p1, void *p2) { int c; if (p1 == p2) diff -r d7e764e62462 -r b706170e24a9 test/bug41.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/bug41.d Wed Oct 31 03:11:32 2007 +0100 @@ -0,0 +1,10 @@ +module bug41; + +void main() +{ + char[] a = "hello world"; + char* ap = a.ptr; + size_t i = 5; + char[] b = ap[0..i]; + assert(b == "hello"); +} diff -r d7e764e62462 -r b706170e24a9 test/d.d --- a/test/d.d Mon Oct 29 03:28:12 2007 +0100 +++ b/test/d.d Wed Oct 31 03:11:32 2007 +0100 @@ -1,9 +1,8 @@ module d; -/* + void main() { int delegate() dg; - int i = dg(); struct S { @@ -19,17 +18,19 @@ S s; auto dg2 = &s.func; - i = dg2(); + int i = dg2(); + assert(i == 42); i = f(dg2, 1); + assert(i == 43); } int f(int delegate() dg, int i) { return dg() + i; } -*/ +/* struct S { int i; @@ -46,3 +47,4 @@ { auto dg = &s.square; } +*/ \ No newline at end of file diff -r d7e764e62462 -r b706170e24a9 test/foreach7.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/foreach7.d Wed Oct 31 03:11:32 2007 +0100 @@ -0,0 +1,12 @@ +module foreach7; + +void main() +{ + int[4] a = [1,2,3,4]; + int i; + foreach(v; a[0..3]) + { + i += v; + } + assert(i == 6); +} diff -r d7e764e62462 -r b706170e24a9 test/nested4.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/nested4.d Wed Oct 31 03:11:32 2007 +0100 @@ -0,0 +1,12 @@ +module nested4; + +void func(void delegate() dg) { + auto v = (){ + dg(); + }; +} + +void main() +{ + func({}); +} diff -r d7e764e62462 -r b706170e24a9 test/structs4.d --- a/test/structs4.d Mon Oct 29 03:28:12 2007 +0100 +++ b/test/structs4.d Wed Oct 31 03:11:32 2007 +0100 @@ -22,5 +22,5 @@ s.t.b = 4; s.t.u = U.init; s.t.u.c = 5; - {assert(s.t.u.c == 5);} + //{assert(s.t.u.c == 5);} } diff -r d7e764e62462 -r b706170e24a9 test/union1.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/union1.d Wed Oct 31 03:11:32 2007 +0100 @@ -0,0 +1,15 @@ +module union1; + +pragma(LLVM_internal, "notypeinfo") +union U +{ + float f; + int i; +} + +void main() +{ + float f = 2; + U u = U(f); + assert(u.i == *cast(int*)&f); +} diff -r d7e764e62462 -r b706170e24a9 test/union2.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/union2.d Wed Oct 31 03:11:32 2007 +0100 @@ -0,0 +1,17 @@ +module union2; + +pragma(LLVM_internal, "notypeinfo") +union U +{ + float f; + long l; +} + +U u; + +void main() +{ + assert(u.f !<>= 0); + uint* p = 1 + cast(uint*)&u.l; + assert(*p == 0); +} diff -r d7e764e62462 -r b706170e24a9 test/union3.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/union3.d Wed Oct 31 03:11:32 2007 +0100 @@ -0,0 +1,14 @@ +module union3; + +pragma(LLVM_internal, "notypeinfo") +union vec3 +{ + struct { float x,y,z; } + float[3] xyz; +} + +void main() +{ + vec3 v; + assert(&v.y is &v.xyz[1]); +}