mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-11 18:33:14 +01:00
[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...
This commit is contained in:
249
demos/qd.d
249
demos/qd.d
@@ -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 @@ void main() {
|
||||
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 @@ extern(C) {
|
||||
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 @@ struct rgb {
|
||||
}
|
||||
}
|
||||
|
||||
void putpixel(SDL_Surface *surf, int x, int y, rgb c) {
|
||||
if ( (x<0) || (y<0) || (x!<surf.w) || (y!<surf.h) ) return;
|
||||
putpixel32(surf, x, y, [c.values[0], c.values[1], c.values[2], 0]);
|
||||
void putpixel(int x, int y, ubyte[4] col) {
|
||||
if ( (x<0) || (y<0) || (x!<display.w) || (y!<display.h) ) return;
|
||||
putpixel32(x, y, col);
|
||||
}
|
||||
|
||||
void hline(int x, int y, int w, rgb r) {
|
||||
hline(x, y, w, SDL_MapRGBA(display.format, r.values[0], r.values[1], r.values[2], 0));
|
||||
}
|
||||
void hline(int x, int y, int w, uint c) {
|
||||
if ( (y<0) || (y!<display.h) ) return;
|
||||
if (x<0) { w+=x; x=0; }
|
||||
if (w<0) return;
|
||||
if ( (x+w) !<display.w) w=display.w-x-1;
|
||||
auto cur = cast(uint *)display.pixels + y*display.pitch/4 + x;
|
||||
foreach (ref value; cur[0..w+1]) value=c;
|
||||
}
|
||||
|
||||
const rgb White={[255, 255, 255]};
|
||||
@@ -92,6 +164,9 @@ const rgb Black={[0, 0, 0]};
|
||||
const rgb Red={[255, 0, 0]};
|
||||
const rgb Green={[0, 255, 0]};
|
||||
const rgb Blue={[0, 0, 255]};
|
||||
const rgb Yellow={[255, 255, 0]};
|
||||
const rgb Cyan={[0, 255, 255]};
|
||||
const rgb Purple={[255, 0, 255]};
|
||||
rgb color=White;
|
||||
rgb back=Black;
|
||||
|
||||
@@ -123,33 +198,57 @@ box_rgb Box(rgb r) { return cast(box_rgb) r; }
|
||||
box_rgb Box() { return cast(box_rgb) color; }
|
||||
alias Back Fill;
|
||||
|
||||
bool doFlip=true;
|
||||
void flip() { SDL_Flip(display); }
|
||||
void flip(bool target) { doFlip=target; }
|
||||
scope class groupDraws {
|
||||
bool wasOn;
|
||||
this() { wasOn=doFlip; flip=false; }
|
||||
~this() { if (wasOn) { flip=true; flip; } }
|
||||
}
|
||||
|
||||
void execParams(T...)(T params) {
|
||||
const int col=select!(rgb, T);
|
||||
static if (col != -1) color=params[col];
|
||||
const int bcol=select!(back_rgb, T);
|
||||
static if (bcol != -1) back=cast(rgb) params[bcol];
|
||||
const int col=select!(rgb, T);
|
||||
static if (col != -1) color=params[col];
|
||||
else static if (bcol != -1) color=back;
|
||||
const int boxcol=select!(box_rgb, T);
|
||||
static if (boxcol != -1) color=cast(rgb) params[boxcol];
|
||||
}
|
||||
|
||||
void tintfill(int x1, int y1, int x2, int y2, rgb color) {
|
||||
SDL_LockSurface(display);
|
||||
scope(exit) { SDL_UnlockSurface(display); if (doFlip) flip; }
|
||||
ubyte[4] c;
|
||||
for (int x=x1; x<x2; ++x) {
|
||||
for (int y=y1; y<y2; ++y) {
|
||||
getpixel32(x, y, &c);
|
||||
c[0]=cast(ubyte)(c[0]*178+color.r*77)>>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 @@ void bresenham(bool countUp=true, bool steep=false)(int x0, int y0, int x1, int
|
||||
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 @@ void line(T...)(int x0, int y0, int x1, int y1, T p) {
|
||||
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 @@ void line(T...)(int x0, int y0, int x1, int y1, T p) {
|
||||
}
|
||||
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 @@ template circle_bresenham_pass(bool first) {
|
||||
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 @@ template circle_bresenham_pass(bool first) {
|
||||
";
|
||||
}
|
||||
|
||||
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 @@ struct floodfill_node {
|
||||
|
||||
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 @@ void paint(T...)(int x, int y, T t) {
|
||||
if (e>=0) do e--; while (e>=0 && check(pget(e, y)));
|
||||
//SDL_Flip(display);
|
||||
for (int i=e+1; i<w; ++i) {
|
||||
putpixel(display, i, y, color);
|
||||
putpixel32(i, y, color.values);
|
||||
if (y && check(pget(i, y-1)) && ((i==w-1)||!check(pget(i+1, y-1)))) queue ~= node(i, y-1);
|
||||
if ((y < display.h-1) && check(pget(i, y+1)) && ((i==w-1)||!check(pget(i+1, y+1)))) queue ~= node(i, y+1);
|
||||
}
|
||||
@@ -309,8 +417,55 @@ void paint(T...)(int x, int y, T t) {
|
||||
}
|
||||
}
|
||||
|
||||
void screen(size_t w, size_t h) {
|
||||
display = SDL_SetVideoMode(w, h, 32, SDL_SWSURFACE);
|
||||
struct screen {
|
||||
static {
|
||||
void opCall(size_t w, size_t h) {
|
||||
display = SDL_SetVideoMode(w, h, 32, SDL_SWSURFACE | SDL_DOUBLEBUF);
|
||||
}
|
||||
int width() { return display.w; }
|
||||
int height() { return display.h; }
|
||||
}
|
||||
}
|
||||
|
||||
void cls() { line(0, 0, display.w-1, display.h-1, Fill=Black); }
|
||||
|
||||
void cls(rgb fill=Black) { line(0, 0, display.w-1, display.h-1, Fill=fill); }
|
||||
|
||||
void events(void delegate(int, bool) key=null, void delegate(int, int, ubyte, bool) mouse=null) {
|
||||
SDL_Event evt;
|
||||
while (SDL_PollEvent(&evt)) {
|
||||
switch (evt.type) {
|
||||
case SDL_EventType.MouseMotion:
|
||||
with (evt.motion) if (mouse) mouse(x, y, 0, false);
|
||||
break;
|
||||
case SDL_EventType.MouseButtonDown:
|
||||
with (evt.button) if (mouse) mouse(x, y, button, true);
|
||||
break;
|
||||
case SDL_EventType.MouseButtonUp:
|
||||
with (evt.button) if (mouse) mouse(x, y, button, false);
|
||||
break;
|
||||
case SDL_EventType.KeyDown:
|
||||
if (key) key(evt.key.keysym.sym, true);
|
||||
case SDL_EventType.KeyUp:
|
||||
if (key) key(evt.key.keysym.sym, false);
|
||||
break;
|
||||
case SDL_EventType.Quit:
|
||||
throw new Error("Quit");
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void events(void delegate(int) key, void delegate(int, int, ubyte, bool) mouse=null) {
|
||||
events((int a, bool b) {
|
||||
if (b) key(a);
|
||||
}, mouse);
|
||||
}
|
||||
|
||||
void events(void delegate(int) key, void delegate(int, int) mouse) {
|
||||
events(key, (int x, int y, ubyte b, bool p) { mouse(x, y); });
|
||||
}
|
||||
|
||||
void events(void delegate(int, bool) key, void delegate(int, int) mouse) {
|
||||
events(key, (int x, int y, ubyte b, bool p) { mouse(x, y); });
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
#include "dsymbol.h"
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
struct Identifier;
|
||||
struct Type;
|
||||
@@ -101,7 +103,8 @@ struct AggregateDeclaration : ScopeDsymbol
|
||||
llvm::Constant* llvmVtbl;
|
||||
llvm::ConstantStruct* llvmConstVtbl;
|
||||
llvm::Constant* llvmInitZ;
|
||||
virtual void offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result); // converts a DMD field offsets to LLVM struct index vector
|
||||
bool llvmHasUnions;
|
||||
virtual size_t offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result); // converts a DMD field offsets to LLVM struct index vector
|
||||
|
||||
AggregateDeclaration *isAggregateDeclaration() { return this; }
|
||||
};
|
||||
@@ -237,7 +240,7 @@ struct ClassDeclaration : AggregateDeclaration
|
||||
|
||||
Symbol *vtblsym;
|
||||
|
||||
virtual void offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result);
|
||||
virtual size_t offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result);
|
||||
|
||||
ClassDeclaration *isClassDeclaration() { return (ClassDeclaration *)this; }
|
||||
};
|
||||
|
||||
15
dmd/attrib.c
15
dmd/attrib.c
@@ -887,13 +887,17 @@ void PragmaDeclaration::semantic(Scope *sc)
|
||||
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 @@ void PragmaDeclaration::semantic(Scope *sc)
|
||||
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 @@ void PragmaDeclaration::semantic(Scope *sc)
|
||||
}
|
||||
break;
|
||||
|
||||
case LLVMnotypeinfo:
|
||||
s->llvmInternal = llvm_internal;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0 && "invalid LLVM_internal pragma got through :/");
|
||||
}
|
||||
|
||||
@@ -550,6 +550,8 @@ VarDeclaration::VarDeclaration(Loc loc, Type *type, Identifier *id, Initializer
|
||||
canassign = 0;
|
||||
value = NULL;
|
||||
llvmNestedIndex = -1;
|
||||
llvmFieldIndex = -1;
|
||||
llvmFieldIndexOffset = 0;
|
||||
}
|
||||
|
||||
Dsymbol *VarDeclaration::syntaxCopy(Dsymbol *s)
|
||||
|
||||
@@ -260,6 +260,8 @@ struct VarDeclaration : Declaration
|
||||
|
||||
// LLVMDC
|
||||
int llvmNestedIndex;
|
||||
int llvmFieldIndex;
|
||||
size_t llvmFieldIndexOffset;
|
||||
};
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
@@ -50,6 +50,7 @@ AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
|
||||
llvmConstVtbl = NULL;
|
||||
llvmInitZ = NULL;
|
||||
llvmInProgress = false;
|
||||
llvmHasUnions = false;
|
||||
}
|
||||
|
||||
enum PROT AggregateDeclaration::prot()
|
||||
|
||||
@@ -7,5 +7,6 @@ enum
|
||||
LLVMbind,
|
||||
LLVMva_arg,
|
||||
LLVMva_start,
|
||||
LLVMva_intrinsic
|
||||
LLVMva_intrinsic,
|
||||
LLVMnotypeinfo
|
||||
};
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "tollvm.h"
|
||||
|
||||
IRState* gIR = 0;
|
||||
llvm::TargetData* gTargetData = 0;
|
||||
const llvm::TargetData* gTargetData = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
IRScope::IRScope()
|
||||
|
||||
@@ -4,13 +4,14 @@
|
||||
#include <stack>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <map>
|
||||
|
||||
#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 @@ struct IRScope
|
||||
// represents a struct or class
|
||||
struct IRStruct
|
||||
{
|
||||
typedef std::vector<const llvm::Type*> TypeVector;
|
||||
typedef std::vector<llvm::Constant*> ConstantVector;
|
||||
typedef std::vector<FuncDeclaration*> FuncDeclVec;
|
||||
struct Offset
|
||||
{
|
||||
VarDeclaration* var;
|
||||
llvm::Constant* init;
|
||||
|
||||
Offset(VarDeclaration* v, llvm::Constant* i)
|
||||
: var(v), init(i) {}
|
||||
};
|
||||
|
||||
typedef std::vector<FuncDeclaration*> FuncDeclVector;
|
||||
typedef std::multimap<unsigned, Offset> 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
|
||||
|
||||
@@ -672,8 +672,14 @@ void ForeachStatement::toIR(IRState* p)
|
||||
}
|
||||
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
|
||||
{
|
||||
|
||||
91
gen/toir.c
91
gen/toir.c
@@ -1449,17 +1449,27 @@ elem* SymOffExp::toElem(IRState* p)
|
||||
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<unsigned> 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 @@ elem* StructLiteralExp::toElem(IRState* p)
|
||||
|
||||
llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
|
||||
|
||||
unsigned n = elements->dim;
|
||||
for (unsigned i=0; i<n; ++i)
|
||||
{
|
||||
llvm::Value* offset = llvm::ConstantInt::get(llvm::Type::Int32Ty, i, false);
|
||||
llvm::Value* arrptr = LLVM_DtoGEP(sptr,zero,offset,"tmp",p->scopebb());
|
||||
if (sd->isUnionDeclaration()) {
|
||||
Logger::println("num elements = %d", elements->dim);
|
||||
//assert(elements->dim == 1);
|
||||
Expression* vx = (Expression*)elements->data[0];
|
||||
assert(vx);
|
||||
|
||||
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();
|
||||
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");
|
||||
|
||||
if (!ve->inplace) {
|
||||
llvm::Value* val = ve->getValue();
|
||||
Logger::cout() << *val << " | " << *arrptr << '\n';
|
||||
p->exps.push_back(IRExp(NULL,vx,arrptr));
|
||||
elem* ve = vx->toElem(p);
|
||||
p->exps.pop_back();
|
||||
|
||||
Type* vxtype = LLVM_DtoDType(vx->type);
|
||||
LLVM_DtoAssign(vxtype, arrptr, val);
|
||||
}
|
||||
delete ve;
|
||||
if (!ve->inplace) {
|
||||
llvm::Value* val = ve->getValue();
|
||||
Logger::cout() << *val << " | " << *arrptr << '\n';
|
||||
LLVM_DtoAssign(vxtype, arrptr, val);
|
||||
}
|
||||
else {
|
||||
assert(0);
|
||||
delete ve;
|
||||
}
|
||||
else {
|
||||
unsigned n = elements->dim;
|
||||
for (unsigned i=0; i<n; ++i)
|
||||
{
|
||||
llvm::Value* offset = llvm::ConstantInt::get(llvm::Type::Int32Ty, i, false);
|
||||
llvm::Value* arrptr = LLVM_DtoGEP(sptr,zero,offset,"tmp",p->scopebb());
|
||||
|
||||
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;
|
||||
}
|
||||
else {
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1835,8 +1868,13 @@ elem* SliceExp::toElem(IRState* p)
|
||||
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* IdentityExp::toElem(IRState* p)
|
||||
|
||||
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 @@ elem* IdentityExp::toElem(IRState* p)
|
||||
if (t1->ty == Tpointer && v->type == elem::NUL && l->getType() != r->getType()) {
|
||||
r = llvm::ConstantPointerNull::get(llvm::cast<llvm::PointerType>(l->getType()));
|
||||
}
|
||||
Logger::cout() << "l = " << *l << " r = " << *r << '\n';
|
||||
e->val = new llvm::ICmpInst(pred, l, r, "tmp", p->scopebb());
|
||||
}
|
||||
e->type = elem::VAL;
|
||||
|
||||
28
gen/tollvm.c
28
gen/tollvm.c
@@ -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,13 +523,11 @@ llvm::Constant* LLVM_DtoConstStructInitializer(StructInitializer* si)
|
||||
assert(vd);
|
||||
Logger::println("vars[%d] = %s", i, vd->toChars());
|
||||
|
||||
std::vector<unsigned> idxs;
|
||||
si->ad->offsetToIndex(vdtype, vd->offset, idxs);
|
||||
assert(idxs.size() == 1);
|
||||
unsigned idx = idxs[0];
|
||||
|
||||
llvm::Constant* v = 0;
|
||||
|
||||
assert(vd->llvmFieldIndex >= 0);
|
||||
unsigned idx = vd->llvmFieldIndex;
|
||||
|
||||
if (ExpInitializer* ex = ini->isExpInitializer())
|
||||
{
|
||||
v = ex->exp->toConstElem(gIR);
|
||||
@@ -557,6 +548,7 @@ llvm::Constant* LLVM_DtoConstStructInitializer(StructInitializer* si)
|
||||
assert(v);
|
||||
|
||||
inits[idx] = v;
|
||||
Logger::cout() << "init[" << idx << "] = " << *v << '\n';
|
||||
}
|
||||
|
||||
// fill out nulls
|
||||
@@ -1271,8 +1263,10 @@ llvm::Value* LLVM_DtoNestedVariable(VarDeclaration* vd)
|
||||
// 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 @@ llvm::Value* LLVM_DtoNestedVariable(VarDeclaration* vd)
|
||||
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 {
|
||||
|
||||
171
gen/toobj.c
171
gen/toobj.c
@@ -65,7 +65,15 @@ Module::genobjfile()
|
||||
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<llvm::TargetMachine> 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 @@ Module::genobjfile()
|
||||
dsym->toObjFile();
|
||||
}
|
||||
|
||||
delete gTargetData;
|
||||
gTargetData = 0;
|
||||
|
||||
// emit the llvm main function if necessary
|
||||
@@ -142,7 +149,7 @@ void Declaration::toObjFile()
|
||||
/* ================================================================== */
|
||||
|
||||
/// Returns the LLVM style index from a DMD style offset
|
||||
void AggregateDeclaration::offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result)
|
||||
size_t AggregateDeclaration::offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result)
|
||||
{
|
||||
Logger::println("checking for offset %u type %s:", os, t->toChars());
|
||||
LOG_SCOPE;
|
||||
@@ -151,18 +158,19 @@ void AggregateDeclaration::offsetToIndex(Type* t, unsigned os, std::vector<unsig
|
||||
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 @@ static unsigned LLVM_ClassOffsetToIndex(ClassDeclaration* cd, unsigned os, unsig
|
||||
|
||||
/// Returns the LLVM style index from a DMD style offset
|
||||
/// Handles class inheritance
|
||||
void ClassDeclaration::offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result)
|
||||
size_t ClassDeclaration::offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& 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,13 +233,97 @@ void StructDeclaration::toObjFile()
|
||||
dsym->toObjFile();
|
||||
}
|
||||
|
||||
if (gIR->topstruct().fields.empty())
|
||||
{
|
||||
gIR->topstruct().fields.push_back(llvm::Type::Int8Ty);
|
||||
gIR->topstruct().inits.push_back(llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false));
|
||||
}
|
||||
Logger::println("doing struct fields");
|
||||
|
||||
llvm::StructType* structtype = llvm::StructType::get(gIR->topstruct().fields);
|
||||
llvm::StructType* structtype = 0;
|
||||
std::vector<llvm::Constant*> fieldinits;
|
||||
|
||||
if (gIR->topstruct().offsets.empty())
|
||||
{
|
||||
std::vector<const llvm::Type*> 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
|
||||
{
|
||||
Logger::println("has fields");
|
||||
std::vector<const llvm::Type*> 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<llvm::Constant*> 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<llvm::Constant*> 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);
|
||||
}
|
||||
|
||||
// refine abstract types for stuff like: struct S{S* next;}
|
||||
if (gIR->topstruct().recty != 0)
|
||||
@@ -254,18 +347,18 @@ void StructDeclaration::toObjFile()
|
||||
// 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; k<gIR->topstruct().inits.size(); ++k) {
|
||||
Logger::cout() << "struct type: " << *structtype << '\n';
|
||||
for (size_t k=0; k<fieldinits.size(); ++k) {
|
||||
Logger::cout() << "Type:" << '\n';
|
||||
Logger::cout() << *gIR->topstruct().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 @@ void StructDeclaration::toObjFile()
|
||||
_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; i<n; ++i) {
|
||||
mfs[i]->toObjFile();
|
||||
@@ -296,7 +390,7 @@ void StructDeclaration::toObjFile()
|
||||
gIR->structs.pop_back();
|
||||
|
||||
// generate typeinfo
|
||||
if (getModule() == gIR->dmodule)
|
||||
if (getModule() == gIR->dmodule && llvmInternal != LLVMnotypeinfo)
|
||||
type->getTypeInfo(NULL);
|
||||
}
|
||||
|
||||
@@ -341,8 +435,12 @@ void ClassDeclaration::toObjFile()
|
||||
// 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<const llvm::Type*> fieldtypes;
|
||||
fieldtypes.push_back(vtabty);
|
||||
|
||||
std::vector<llvm::Constant*> fieldinits;
|
||||
fieldinits.push_back(0);
|
||||
|
||||
// base classes first
|
||||
LLVM_AddBaseClassData(&baseclasses);
|
||||
@@ -353,7 +451,13 @@ void ClassDeclaration::toObjFile()
|
||||
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 @@ void ClassDeclaration::toObjFile()
|
||||
|
||||
// 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 @@ void ClassDeclaration::toObjFile()
|
||||
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; i<n; ++i) {
|
||||
mfs[i]->toObjFile();
|
||||
@@ -573,7 +677,6 @@ void VarDeclaration::toObjFile()
|
||||
|
||||
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 @@ void VarDeclaration::toObjFile()
|
||||
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");
|
||||
|
||||
147
gen/typinf.c
147
gen/typinf.c
@@ -324,7 +324,7 @@ void TypeInfoTypedefDeclaration::toDt(dt_t **pdt)
|
||||
|
||||
// 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 @@ void TypeInfoEnumDeclaration::toDt(dt_t **pdt)
|
||||
|
||||
// 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 @@ static llvm::Constant* LLVM_D_Create_TypeInfoBase(Type* basetype, TypeInfoDeclar
|
||||
|
||||
// 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 @@ void TypeInfoStructDeclaration::toDt(dt_t **pdt)
|
||||
// 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 @@ void TypeInfoStructDeclaration::toDt(dt_t **pdt)
|
||||
}
|
||||
#endif
|
||||
|
||||
Logger::println("************** B");
|
||||
const llvm::PointerType* ptty = llvm::cast<llvm::PointerType>(stype->getElementType(3));
|
||||
|
||||
s = search_function(sd, Id::tohash);
|
||||
@@ -633,6 +635,7 @@ void TypeInfoStructDeclaration::toDt(dt_t **pdt)
|
||||
fdx = s ? s->isFuncDeclaration() : NULL;
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
Logger::println("************** C %d", i);
|
||||
ptty = llvm::cast<llvm::PointerType>(stype->getElementType(4+i));
|
||||
if (fdx)
|
||||
{
|
||||
@@ -657,6 +660,7 @@ void TypeInfoStructDeclaration::toDt(dt_t **pdt)
|
||||
fdx = s ? s->isFuncDeclaration() : NULL;
|
||||
}
|
||||
|
||||
Logger::println("************** D");
|
||||
ptty = llvm::cast<llvm::PointerType>(stype->getElementType(6));
|
||||
s = search_function(sd, Id::tostring);
|
||||
fdx = s ? s->isFuncDeclaration() : NULL;
|
||||
@@ -684,144 +688,9 @@ void TypeInfoStructDeclaration::toDt(dt_t **pdt)
|
||||
|
||||
// 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);
|
||||
*/
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
@@ -974,7 +974,7 @@ class TypeInfo_Struct : TypeInfo
|
||||
return h;
|
||||
}
|
||||
|
||||
int equals(void *p2, void *p1)
|
||||
int equals(void *p1, void *p2)
|
||||
{ int c;
|
||||
|
||||
if (p1 == p2)
|
||||
|
||||
10
test/bug41.d
Normal file
10
test/bug41.d
Normal file
@@ -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");
|
||||
}
|
||||
10
test/d.d
10
test/d.d
@@ -1,9 +1,8 @@
|
||||
module d;
|
||||
/*
|
||||
|
||||
void main()
|
||||
{
|
||||
int delegate() dg;
|
||||
int i = dg();
|
||||
|
||||
struct S
|
||||
{
|
||||
@@ -19,17 +18,19 @@ void main()
|
||||
|
||||
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 @@ void main()
|
||||
{
|
||||
auto dg = &s.square;
|
||||
}
|
||||
*/
|
||||
12
test/foreach7.d
Normal file
12
test/foreach7.d
Normal file
@@ -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);
|
||||
}
|
||||
12
test/nested4.d
Normal file
12
test/nested4.d
Normal file
@@ -0,0 +1,12 @@
|
||||
module nested4;
|
||||
|
||||
void func(void delegate() dg) {
|
||||
auto v = (){
|
||||
dg();
|
||||
};
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
func({});
|
||||
}
|
||||
@@ -22,5 +22,5 @@ void main()
|
||||
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);}
|
||||
}
|
||||
|
||||
15
test/union1.d
Normal file
15
test/union1.d
Normal file
@@ -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);
|
||||
}
|
||||
17
test/union2.d
Normal file
17
test/union2.d
Normal file
@@ -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);
|
||||
}
|
||||
14
test/union3.d
Normal file
14
test/union3.d
Normal file
@@ -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]);
|
||||
}
|
||||
Reference in New Issue
Block a user