diff --git a/release/include/terra/terra.h b/release/include/terra/terra.h index 01eed1b0f..a8e0aa865 100644 --- a/release/include/terra/terra.h +++ b/release/include/terra/terra.h @@ -1,6 +1,5 @@ /* See Copyright Notice in ../LICENSE.txt */ - #ifndef terra_h #define terra_h @@ -12,30 +11,28 @@ extern "C" { #include "lualib.h" #include "lauxlib.h" -int terra_init(lua_State * L); +int terra_init(lua_State *L); -typedef struct { /* default values are 0 */ +typedef struct { /* default values are 0 */ int verbose; /*-v, print more debugging info (can be 1 for some, 2 for more) */ int debug; /*-g, turn on debugging symbols and base pointers */ int usemcjit; - char* cmd_line_chunk; + char *cmd_line_chunk; } terra_Options; -int terra_initwithoptions(lua_State * L, terra_Options * options); +int terra_initwithoptions(lua_State *L, terra_Options *options); -int terra_load(lua_State *L,lua_Reader reader, void *data, const char *chunkname); -int terra_loadfile(lua_State * L, const char * file); -int terra_loadbuffer(lua_State * L, const char *buf, size_t size, const char *name); +int terra_load(lua_State *L, lua_Reader reader, void *data, const char *chunkname); +int terra_loadfile(lua_State *L, const char *file); +int terra_loadbuffer(lua_State *L, const char *buf, size_t size, const char *name); int terra_loadstring(lua_State *L, const char *s); void terra_llvmshutdown(); -#define terra_dofile(L, fn) \ - (terra_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) +#define terra_dofile(L, fn) (terra_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) -#define terra_dostring(L, s) \ - (terra_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) +#define terra_dostring(L, s) (terra_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) #if __cplusplus } /*extern C*/ #endif - + #endif diff --git a/src/llex.cpp b/src/llex.cpp index d3f2ab7ec..06889ad98 100644 --- a/src/llex.cpp +++ b/src/llex.cpp @@ -4,7 +4,6 @@ ** See Copyright Notice in lua.h */ - #include #include #include @@ -28,157 +27,148 @@ #include "treadnumber.h" extern "C" { - #include "lua.h" +#include "lua.h" } -int next(LexState * ls) { +int next(LexState *ls) { ls->current = zgetc(ls->z); - if(ls->current != EOZ) { + if (ls->current != EOZ) { ls->currentoffset++; - OutputBuffer_putc(&ls->output_buffer,ls->current == EOZ ? '\0' : ls->current); + OutputBuffer_putc(&ls->output_buffer, ls->current == EOZ ? '\0' : ls->current); } return ls->current; } -#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') - +#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') /* ORDER RESERVED */ -static const char *const luaX_tokens [] = { - "and", "break", "do", "else", "elseif", - "end", "false", "for", "function", "goto", "if", - "in", "local", "nil", "not", "or", "repeat", - "return", "then", "true", "until", "while", "terra", "var","struct","union","quote","import","defer","escape", - "..", "...", "==", ">=", "<=", "~=", "::", "->", "<<", ">>", "", - "", "", "", "" -}; - +static const char *const luaX_tokens[] = { + "and", "break", "do", "else", "elseif", "end", "false", + "for", "function", "goto", "if", "in", "local", "nil", + "not", "or", "repeat", "return", "then", "true", "until", + "while", "terra", "var", "struct", "union", "quote", "import", + "defer", "escape", "..", "...", "==", ">=", "<=", + "~=", "::", "->", "<<", ">>", "", "", + "", "", ""}; #define save_and_next(ls) (save(ls, ls->current), next(ls)) +static l_noret lexerror(LexState *ls, const char *msg, int token); -static l_noret lexerror (LexState *ls, const char *msg, int token); +static void save(LexState *ls, int c) { + Mbuffer *b = ls->buff; + if (luaZ_bufflen(b) + 1 > luaZ_sizebuffer(b)) { + size_t newsize; + if (luaZ_sizebuffer(b) >= MAX_SIZET / 2) + lexerror(ls, "lexical element too long", 0); + newsize = luaZ_sizebuffer(b) * 2; + luaZ_resizebuffer(ls->L, b, newsize); + } + b->buffer[luaZ_bufflen(b)++] = cast(char, c); +} +void luaX_init(terra_State *L) { + // initialize the base tstring_table that will hold reserved keywords + int stk = lua_gettop(L->L); + lua_newtable(L->L); + lua_pushlightuserdata(L->L, &L->tstring_table); + lua_pushvalue(L->L, -2); + lua_rawset(L->L, LUA_REGISTRYINDEX); -static void save (LexState *ls, int c) { - Mbuffer *b = ls->buff; - if (luaZ_bufflen(b) + 1 > luaZ_sizebuffer(b)) { - size_t newsize; - if (luaZ_sizebuffer(b) >= MAX_SIZET/2) - lexerror(ls, "lexical element too long", 0); - newsize = luaZ_sizebuffer(b) * 2; - luaZ_resizebuffer(ls->L, b, newsize); - } - b->buffer[luaZ_bufflen(b)++] = cast(char, c); -} + // stack is: + int i; + for (i = 0; i < NUM_RESERVED; i++) { + TString *ts = luaS_new(L, luaX_tokens[i]); + ts->reserved = cast_byte(i + 1); /* reserved word */ + } -void luaX_init (terra_State *L) { - //initialize the base tstring_table that will hold reserved keywords - int stk = lua_gettop(L->L); - lua_newtable(L->L); - lua_pushlightuserdata(L->L, &L->tstring_table); - lua_pushvalue(L->L, -2); - lua_rawset(L->L, LUA_REGISTRYINDEX); - - //stack is: - - int i; - for (i=0; ireserved = cast_byte(i+1); /* reserved word */ - } - - lua_pop(L->L,1); // - assert(stk == lua_gettop(L->L)); + lua_pop(L->L, 1); // + assert(stk == lua_gettop(L->L)); } -void luaX_pushtstringtable(terra_State * L) { +void luaX_pushtstringtable(terra_State *L) { int stk = lua_gettop(L->L); lua_pushlightuserdata(L->L, &L->tstring_table); - lua_pushvalue(L->L,-1); + lua_pushvalue(L->L, -1); lua_rawget(L->L, LUA_REGISTRYINDEX); assert(!lua_isnil(L->L, -1)); - - lua_newtable(L->L); //new tstring table - lua_newtable(L->L); //metatable to link to old table + + lua_newtable(L->L); // new tstring table + lua_newtable(L->L); // metatable to link to old table lua_pushvalue(L->L, -3); lua_setfield(L->L, -2, "__index"); lua_setmetatable(L->L, -2); - - lua_remove(L->L,-2); //stack is: - lua_rawset(L->L,LUA_REGISTRYINDEX); - + + lua_remove(L->L, + -2); // stack is: + lua_rawset(L->L, LUA_REGISTRYINDEX); + assert(stk == lua_gettop(L->L)); } -void luaX_poptstringtable(terra_State * L) { +void luaX_poptstringtable(terra_State *L) { int stk = lua_gettop(L->L); lua_pushlightuserdata(L->L, &L->tstring_table); - lua_pushvalue(L->L,-1); - + lua_pushvalue(L->L, -1); + lua_rawget(L->L, LUA_REGISTRYINDEX); lua_getmetatable(L->L, -1); lua_getfield(L->L, -1, "__index"); - lua_remove(L->L,-2); // - lua_remove(L->L,-2); // - - lua_rawset(L->L,LUA_REGISTRYINDEX); - assert(stk == lua_gettop(L->L)); + lua_remove(L->L, -2); // + lua_remove(L->L, -2); // + lua_rawset(L->L, LUA_REGISTRYINDEX); + assert(stk == lua_gettop(L->L)); } -const char * luaX_token2rawstr(LexState * ls, int token) { - if(token < FIRST_RESERVED) { +const char *luaX_token2rawstr(LexState *ls, int token) { + if (token < FIRST_RESERVED) { assert(token == cast(unsigned char, token)); - return luaS_cstringf(ls->LP,"%c",token); + return luaS_cstringf(ls->LP, "%c", token); } else { return luaX_tokens[token - FIRST_RESERVED]; } } -const char * luaX_token2str (LexState *ls, int token) { - if (token < FIRST_RESERVED) { - assert(token == cast(unsigned char, token)); - return (lisprint(token)) ? luaS_cstringf(ls->LP,LUA_QL("%c"), token) : - luaS_cstringf(ls->LP,"char(%d)"); - } - else { - const char *s = luaX_tokens[token - FIRST_RESERVED]; - return luaS_cstringf(ls->LP,LUA_QS,s); - } -} - - -static const char *txtToken (LexState *ls, int token) { - switch (token) { - case TK_NAME: - case TK_STRING: - case TK_NUMBER: - save(ls, '\0'); - return luaS_cstringf(ls->LP,LUA_QS,luaZ_buffer(ls->buff)); - case TK_SPECIAL: - save(ls, '\0'); - return luaS_cstringf(ls->LP, "%s", luaZ_buffer(ls->buff)); - default: - return luaX_token2str(ls, token); - } -} - -l_noret luaX_reporterror(LexState * ls, const char * err) { +const char *luaX_token2str(LexState *ls, int token) { + if (token < FIRST_RESERVED) { + assert(token == cast(unsigned char, token)); + return (lisprint(token)) ? luaS_cstringf(ls->LP, LUA_QL("%c"), token) + : luaS_cstringf(ls->LP, "char(%d)"); + } else { + const char *s = luaX_tokens[token - FIRST_RESERVED]; + return luaS_cstringf(ls->LP, LUA_QS, s); + } +} + +static const char *txtToken(LexState *ls, int token) { + switch (token) { + case TK_NAME: + case TK_STRING: + case TK_NUMBER: + save(ls, '\0'); + return luaS_cstringf(ls->LP, LUA_QS, luaZ_buffer(ls->buff)); + case TK_SPECIAL: + save(ls, '\0'); + return luaS_cstringf(ls->LP, "%s", luaZ_buffer(ls->buff)); + default: + return luaX_token2str(ls, token); + } +} + +l_noret luaX_reporterror(LexState *ls, const char *err) { lua_pushstring(ls->L, err); throw LUA_ERRSYNTAX; - abort(); //quiet warnings about noret + abort(); // quiet warnings about noret } -static l_noret lexerror (LexState *ls, const char * msg, int token) { - msg = luaS_cstringf(ls->LP,"%s:%d: %s", getstr(ls->source), ls->linenumber, msg); - if (token) - msg = luaS_cstringf(ls->LP,"%s near %s", msg, txtToken(ls, token)); - luaX_reporterror(ls,msg); +static l_noret lexerror(LexState *ls, const char *msg, int token) { + msg = luaS_cstringf(ls->LP, "%s:%d: %s", getstr(ls->source), ls->linenumber, msg); + if (token) msg = luaS_cstringf(ls->LP, "%s near %s", msg, txtToken(ls, token)); + luaX_reporterror(ls, msg); } - -l_noret luaX_syntaxerror (LexState *ls, const char *msg) { - lexerror(ls, msg, ls->t.token); +l_noret luaX_syntaxerror(LexState *ls, const char *msg) { + lexerror(ls, msg, ls->t.token); } /* @@ -186,127 +176,130 @@ l_noret luaX_syntaxerror (LexState *ls, const char *msg) { ** it will not be collected until the end of the function's compilation ** (by that time it should be anchored in function's prototype) */ -TString *luaX_newstring (LexState *ls, const char *str, size_t l) { - return luaS_newlstr(ls->LP, str, l); /* create new string */ +TString *luaX_newstring(LexState *ls, const char *str, size_t l) { + return luaS_newlstr(ls->LP, str, l); /* create new string */ } /* ** increment line number and skips newline sequence (any of ** \n, \r, \n\r, or \r\n) */ -static void inclinenumber (LexState *ls) { - int old = ls->current; - assert(currIsNewline(ls)); - next(ls); /* skip `\n' or `\r' */ - if (currIsNewline(ls) && ls->current != old) - next(ls); /* skip `\n\r' or `\r\n' */ - if (++ls->linenumber >= MAX_INT) - luaX_syntaxerror(ls, "chunk has too many lines"); -} - - -void luaX_setinput (terra_State *LP, LexState *ls, ZIO *z, TString * source, - int firstchar) { - ls->decpoint = '.'; - ls->LP = LP; - ls->current = firstchar; - ls->currentoffset = 0; - ls->lookahead.token = TK_EOS; /* no look-ahead token */ - ls->z = z; - ls->fs = NULL; - ls->linenumber = 1; - ls->lastline = 1; - ls->source = source; - ls->envn = luaS_new(LP,"");//luaS_new(L, LUA_ENV); /* create env name */ - ls->in_terra = 0; - ls->patchinfo.N = 0; - ls->patchinfo.space = 32; - ls->patchinfo.buffer = (char*)malloc(32); - if(firstchar != EOZ) - OutputBuffer_putc(&ls->output_buffer,firstchar); - luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ -} - -void luaX_patchbegin(LexState *ls, Token * begin_token) { - //save everything from the current token to the end of the output buffer in the patch buffer - OutputBuffer * ob = &ls->output_buffer; +static void inclinenumber(LexState *ls) { + int old = ls->current; + assert(currIsNewline(ls)); + next(ls); /* skip `\n' or `\r' */ + if (currIsNewline(ls) && ls->current != old) next(ls); /* skip `\n\r' or `\r\n' */ + if (++ls->linenumber >= MAX_INT) luaX_syntaxerror(ls, "chunk has too many lines"); +} + +void luaX_setinput(terra_State *LP, LexState *ls, ZIO *z, TString *source, + int firstchar) { + ls->decpoint = '.'; + ls->LP = LP; + ls->current = firstchar; + ls->currentoffset = 0; + ls->lookahead.token = TK_EOS; /* no look-ahead token */ + ls->z = z; + ls->fs = NULL; + ls->linenumber = 1; + ls->lastline = 1; + ls->source = source; + ls->envn = luaS_new( + LP, ""); // luaS_new(L, LUA_ENV); /* create env name */ + ls->in_terra = 0; + ls->patchinfo.N = 0; + ls->patchinfo.space = 32; + ls->patchinfo.buffer = (char *)malloc(32); + if (firstchar != EOZ) OutputBuffer_putc(&ls->output_buffer, firstchar); + luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ +} + +void luaX_patchbegin(LexState *ls, Token *begin_token) { + // save everything from the current token to the end of the output buffer in the patch + // buffer + OutputBuffer *ob = &ls->output_buffer; int n_bytes = ob->N - ls->t.seminfo.buffer_begin; - if(n_bytes > ls->patchinfo.space) { + if (n_bytes > ls->patchinfo.space) { int newsize = std::max(n_bytes, ls->patchinfo.space * 2); - ls->patchinfo.buffer = (char*) realloc(ls->patchinfo.buffer, newsize); + ls->patchinfo.buffer = (char *)realloc(ls->patchinfo.buffer, newsize); ls->patchinfo.space = newsize; } - memcpy(ls->patchinfo.buffer,ob->data + ls->t.seminfo.buffer_begin, n_bytes); + memcpy(ls->patchinfo.buffer, ob->data + ls->t.seminfo.buffer_begin, n_bytes); ls->patchinfo.N = n_bytes; - //ls->patchinfo.buffer[ls->patchinfo.N] = '\0'; - //printf("buffer is %s\n",ls->patchinfo.buffer); + // ls->patchinfo.buffer[ls->patchinfo.N] = '\0'; + // printf("buffer is %s\n",ls->patchinfo.buffer); - //reset the output buffer to the beginning of the begin_token + // reset the output buffer to the beginning of the begin_token ob->N = begin_token->seminfo.buffer_begin; - //retain the tokens leading whitespace for sanity... - while(1) { - switch(ob->data[ob->N]) { - case '\n': case '\r': - begin_token->seminfo.linebegin++; - /*fallthrough*/ - case ' ': case '\f': case '\t': case '\v': - begin_token->seminfo.buffer_begin++; - ob->N++; - break; - default: - goto loop_exit; + // retain the tokens leading whitespace for sanity... + while (1) { + switch (ob->data[ob->N]) { + case '\n': + case '\r': + begin_token->seminfo.linebegin++; + /*fallthrough*/ + case ' ': + case '\f': + case '\t': + case '\v': + begin_token->seminfo.buffer_begin++; + ob->N++; + break; + default: + goto loop_exit; } - } loop_exit: + } +loop_exit: return; - //code can now safely write to this buffer + // code can now safely write to this buffer } -void luaX_insertbeforecurrenttoken(LexState * ls, char c) { +void luaX_insertbeforecurrenttoken(LexState *ls, char c) { int sz = ls->output_buffer.N - ls->t.seminfo.buffer_begin; - //make sure the buffer has enough space and the right size + // make sure the buffer has enough space and the right size OutputBuffer_putc(&ls->output_buffer, c); - char * begin = ls->output_buffer.data + ls->t.seminfo.buffer_begin; - memmove(begin + 1, begin ,sz); + char *begin = ls->output_buffer.data + ls->t.seminfo.buffer_begin; + memmove(begin + 1, begin, sz); *begin = c; - //adjust offsets of current tokens + // adjust offsets of current tokens ls->t.seminfo.buffer_begin++; ls->lookahead.seminfo.buffer_begin++; } -void luaX_getoutput(LexState * ls, Token * begin_token, const char ** output, int * N) { - OutputBuffer * ob = &ls->output_buffer; - +void luaX_getoutput(LexState *ls, Token *begin_token, const char **output, int *N) { + OutputBuffer *ob = &ls->output_buffer; + int buffer_begin = ls->t.seminfo.buffer_begin; int n_bytes = buffer_begin - begin_token->seminfo.buffer_begin; *output = ob->data + begin_token->seminfo.buffer_begin; *N = n_bytes; } -const char * luaX_saveoutput(LexState * ls, Token * begin_token) { +const char *luaX_saveoutput(LexState *ls, Token *begin_token) { int n_bytes; - const char * output; - luaX_getoutput(ls,begin_token,&output,&n_bytes); - TString * tstring = luaS_newlstr(ls->LP, output, n_bytes); //save this to the string table, which gets collected when this function exits + const char *output; + luaX_getoutput(ls, begin_token, &output, &n_bytes); + TString *tstring = luaS_newlstr(ls->LP, output, + n_bytes); // save this to the string table, which + // gets collected when this function exits return getstr(tstring); } -void luaX_patchend(LexState *ls, Token * begin_token) { - //first we need to pad with newlines, until we reach the original line count - OutputBuffer * ob = &ls->output_buffer; - //count the number of newlines in the patched in data +void luaX_patchend(LexState *ls, Token *begin_token) { + // first we need to pad with newlines, until we reach the original line count + OutputBuffer *ob = &ls->output_buffer; + // count the number of newlines in the patched in data int nlines = 0; - for(int i = begin_token->seminfo.buffer_begin; i < ob->N; i++) { - if(ob->data[i] == '\n') - nlines++; + for (int i = begin_token->seminfo.buffer_begin; i < ob->N; i++) { + if (ob->data[i] == '\n') nlines++; } - - for(int line = begin_token->seminfo.linebegin + nlines; - line < ls->t.seminfo.linebegin; - line++) { - OutputBuffer_putc(ob,'\n'); + + for (int line = begin_token->seminfo.linebegin + nlines; + line < ls->t.seminfo.linebegin; line++) { + OutputBuffer_putc(ob, '\n'); } int offset = ob->N - ls->t.seminfo.buffer_begin; - //restore patch data - OutputBuffer_puts(ob,ls->patchinfo.N,ls->patchinfo.buffer); - //adjust to current tokens to have correct information + // restore patch data + OutputBuffer_puts(ob, ls->patchinfo.N, ls->patchinfo.buffer); + // adjust to current tokens to have correct information ls->t.seminfo.buffer_begin += offset; ls->lookahead.seminfo.buffer_begin += offset; } @@ -317,398 +310,456 @@ void luaX_patchend(LexState *ls, Token * begin_token) { ** ======================================================= */ - - -static int check_next (LexState *ls, const char *set) { - if (ls->current == '\0' || !strchr(set, ls->current)) - return 0; - save_and_next(ls); - return 1; +static int check_next(LexState *ls, const char *set) { + if (ls->current == '\0' || !strchr(set, ls->current)) return 0; + save_and_next(ls); + return 1; } /* LUA_NUMBER */ -static void read_numeral (LexState *ls, SemInfo *seminfo) { - assert(lisdigit(ls->current)); - bool hasdecpoint = false; - - int c, xp = 'e'; - assert(lisdigit(ls->current)); - if ((c = ls->current) == '0') { - save_and_next(ls); - if ((ls->current | 0x20) == 'x') xp = 'p'; - } - while (lislalnum(ls->current) || ls->current == '.' || - ((ls->current == '-' || ls->current == '+') && (c | 0x20) == xp)) { - if(ls->current == '.') - hasdecpoint = true; - c = ls->current; - save_and_next(ls); - } - save(ls, '\0'); - - /* string ends in 'f' but is not hexidecimal. - this means that we have a single precision float */ - bool issinglefloat = ls->in_terra && c == 'f' && xp != 'p'; - - if(issinglefloat) { - /* clear the 'f' so that treadnumber succeeds */ - ls->buff->buffer[luaZ_bufflen(ls->buff)-2] = '\0'; - } - - ReadNumber num; - if(treadnumber(ls->buff->buffer, &num, ls->in_terra && !issinglefloat)) - lexerror(ls, "malformed number", TK_NUMBER); - - /* Terra handles 2 things differently from LuaJIT: - 1. if the number had a decimal place, it is always a floating point number. In constrast, treadnumber will convert it to an int if it can be represented as an int. - 2. if the number ends in an 'f' and isn't a hexidecimal number, it is treated as a single-precision floating point number - */ - seminfo->flags = num.flags; - if(num.flags & F_ISINTEGER) { - seminfo->i = num.i; - seminfo->r = seminfo->i; - if(issinglefloat) { - seminfo->flags = 0; - } else if(hasdecpoint) { - seminfo->flags = F_IS8BYTES; +static void read_numeral(LexState *ls, SemInfo *seminfo) { + assert(lisdigit(ls->current)); + bool hasdecpoint = false; + + int c, xp = 'e'; + assert(lisdigit(ls->current)); + if ((c = ls->current) == '0') { + save_and_next(ls); + if ((ls->current | 0x20) == 'x') xp = 'p'; } - } else { - seminfo->r = num.d; - if (!issinglefloat) - seminfo->flags = F_IS8BYTES; - } - -} + while (lislalnum(ls->current) || ls->current == '.' || + ((ls->current == '-' || ls->current == '+') && (c | 0x20) == xp)) { + if (ls->current == '.') hasdecpoint = true; + c = ls->current; + save_and_next(ls); + } + save(ls, '\0'); + /* string ends in 'f' but is not hexidecimal. + this means that we have a single precision float */ + bool issinglefloat = ls->in_terra && c == 'f' && xp != 'p'; + + if (issinglefloat) { + /* clear the 'f' so that treadnumber succeeds */ + ls->buff->buffer[luaZ_bufflen(ls->buff) - 2] = '\0'; + } + + ReadNumber num; + if (treadnumber(ls->buff->buffer, &num, ls->in_terra && !issinglefloat)) + lexerror(ls, "malformed number", TK_NUMBER); + + /* Terra handles 2 things differently from LuaJIT: + 1. if the number had a decimal place, it is always a floating point number. In + constrast, treadnumber will convert it to an int if it can be represented as an + int. + 2. if the number ends in an 'f' and isn't a hexidecimal number, it is treated as a + single-precision floating point number + */ + seminfo->flags = num.flags; + if (num.flags & F_ISINTEGER) { + seminfo->i = num.i; + seminfo->r = seminfo->i; + if (issinglefloat) { + seminfo->flags = 0; + } else if (hasdecpoint) { + seminfo->flags = F_IS8BYTES; + } + } else { + seminfo->r = num.d; + if (!issinglefloat) seminfo->flags = F_IS8BYTES; + } +} /* ** skip a sequence '[=*[' or ']=*]' and return its number of '='s or ** -1 if sequence is malformed */ -static int skip_sep (LexState *ls) { - int count = 0; - int s = ls->current; - assert(s == '[' || s == ']'); - save_and_next(ls); - while (ls->current == '=') { +static int skip_sep(LexState *ls) { + int count = 0; + int s = ls->current; + assert(s == '[' || s == ']'); save_and_next(ls); - count++; - } - return (ls->current == s) ? count : (-count) - 1; -} - - -static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { - save_and_next(ls); /* skip 2nd `[' */ - if (currIsNewline(ls)) /* string starts with a newline? */ - inclinenumber(ls); /* skip it */ - for (;;) { - switch (ls->current) { - case EOZ: - lexerror(ls, (seminfo) ? "unfinished long string" : - "unfinished long comment", TK_EOS); - break; /* to avoid warnings */ - case ']': { - if (skip_sep(ls) == sep) { - save_and_next(ls); /* skip 2nd `]' */ - goto endloop; - } - break; - } - case '\n': case '\r': { - save(ls, '\n'); - inclinenumber(ls); - if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */ - break; - } - default: { - if (seminfo) save_and_next(ls); - else next(ls); - } + while (ls->current == '=') { + save_and_next(ls); + count++; } - } endloop: - if (seminfo) - seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep), - luaZ_bufflen(ls->buff) - 2*(2 + sep)); -} - - -static void escerror (LexState *ls, int *c, int n, const char *msg) { - int i; - luaZ_resetbuffer(ls->buff); /* prepare error message */ - save(ls, '\\'); - for (i = 0; i < n && c[i] != EOZ; i++) - save(ls, c[i]); - lexerror(ls, msg, TK_STRING); -} - - -static int readhexaesc (LexState *ls) { - int c[3], i; /* keep input for error message */ - int r = 0; /* result accumulator */ - c[0] = 'x'; /* for error message */ - for (i = 1; i < 3; i++) { /* read two hexa digits */ - c[i] = next(ls); - if (!lisxdigit(c[i])) - escerror(ls, c, i + 1, "hexadecimal digit expected"); - r = (r << 4) + luaO_hexavalue(c[i]); - } - return r; -} - - -static int readdecesc (LexState *ls) { - int c[3], i; - int r = 0; /* result accumulator */ - for (i = 0; i < 3 && lisdigit(ls->current); i++) { /* read up to 3 digits */ - c[i] = ls->current; - r = 10*r + c[i] - '0'; - next(ls); - } - if (r > UCHAR_MAX) - escerror(ls, c, i, "decimal escape too large"); - return r; -} - - -static void read_string (LexState *ls, int del, SemInfo *seminfo) { - save_and_next(ls); /* keep delimiter (for error messages) */ - while (ls->current != del) { - switch (ls->current) { - case EOZ: - lexerror(ls, "unfinished string", TK_EOS); - break; /* to avoid warnings */ - case '\n': - case '\r': - lexerror(ls, "unfinished string", TK_STRING); - break; /* to avoid warnings */ - case '\\': { /* escape sequences */ - int c; /* final character to be saved */ - next(ls); /* do not save the `\' */ + return (ls->current == s) ? count : (-count) - 1; +} + +static void read_long_string(LexState *ls, SemInfo *seminfo, int sep) { + save_and_next(ls); /* skip 2nd `[' */ + if (currIsNewline(ls)) /* string starts with a newline? */ + inclinenumber(ls); /* skip it */ + for (;;) { switch (ls->current) { - case 'a': c = '\a'; goto read_save; - case 'b': c = '\b'; goto read_save; - case 'f': c = '\f'; goto read_save; - case 'n': c = '\n'; goto read_save; - case 'r': c = '\r'; goto read_save; - case 't': c = '\t'; goto read_save; - case 'v': c = '\v'; goto read_save; - case 'x': c = readhexaesc(ls); goto read_save; - case '\n': case '\r': - inclinenumber(ls); c = '\n'; goto only_save; - case '\\': case '\"': case '\'': - c = ls->current; goto read_save; - case EOZ: goto no_save; /* will raise an error next loop */ - case 'z': { /* zap following span of spaces */ - next(ls); /* skip the 'z' */ - while (lisspace(ls->current)) { - if (currIsNewline(ls)) inclinenumber(ls); - else next(ls); + case EOZ: + lexerror(ls, + (seminfo) ? "unfinished long string" : "unfinished long comment", + TK_EOS); + break; /* to avoid warnings */ + case ']': { + if (skip_sep(ls) == sep) { + save_and_next(ls); /* skip 2nd `]' */ + goto endloop; + } + break; + } + case '\n': + case '\r': { + save(ls, '\n'); + inclinenumber(ls); + if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */ + break; + } + default: { + if (seminfo) + save_and_next(ls); + else + next(ls); } - goto no_save; - } - default: { - if (!lisdigit(ls->current)) - escerror(ls, &ls->current, 1, "invalid escape sequence"); - /* digital escape \ddd */ - c = readdecesc(ls); - goto only_save; - } } - read_save: next(ls); /* read next character */ - only_save: save(ls, c); /* save 'c' */ - no_save: break; - } - default: - save_and_next(ls); } - } - save_and_next(ls); /* skip delimiter */ - seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1, - luaZ_bufflen(ls->buff) - 2); -} - -static void dump_stack(lua_State * L, int elem) { - lua_pushvalue(L,elem); - lua_getfield(L,LUA_GLOBALSINDEX,"terra"); - lua_getfield(L,-1,"tree"); - lua_getfield(L,-1,"printraw"); - lua_pushvalue(L,-4); - lua_call(L, 1, 0); - - lua_pop(L,3); -} - -static int llex (LexState *ls, SemInfo *seminfo) { - (void) dump_stack; //suppress unused warning for debugging function - luaZ_resetbuffer(ls->buff); - seminfo->buffer_begin = ls->output_buffer.N - 1; //- 1 because we already recorded the first token - seminfo->linebegin = ls->linenumber; //no -1 because we haven't incremented line info for this token yet - for (;;) { - switch (ls->current) { - case '\n': case '\r': { /* line breaks */ - inclinenumber(ls); - break; - } - case ' ': case '\f': case '\t': case '\v': { /* spaces */ - next(ls); - break; - } - case '-': { /* '-' or '--' (comment) */ - next(ls); - if (ls->current == '>') { - next(ls); - return TK_FUNC_PTR; - } - if (ls->current != '-') return '-'; - /* else is a comment */ +endloop: + if (seminfo) + seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep), + luaZ_bufflen(ls->buff) - 2 * (2 + sep)); +} + +static void escerror(LexState *ls, int *c, int n, const char *msg) { + int i; + luaZ_resetbuffer(ls->buff); /* prepare error message */ + save(ls, '\\'); + for (i = 0; i < n && c[i] != EOZ; i++) save(ls, c[i]); + lexerror(ls, msg, TK_STRING); +} + +static int readhexaesc(LexState *ls) { + int c[3], i; /* keep input for error message */ + int r = 0; /* result accumulator */ + c[0] = 'x'; /* for error message */ + for (i = 1; i < 3; i++) { /* read two hexa digits */ + c[i] = next(ls); + if (!lisxdigit(c[i])) escerror(ls, c, i + 1, "hexadecimal digit expected"); + r = (r << 4) + luaO_hexavalue(c[i]); + } + return r; +} + +static int readdecesc(LexState *ls) { + int c[3], i; + int r = 0; /* result accumulator */ + for (i = 0; i < 3 && lisdigit(ls->current); i++) { /* read up to 3 digits */ + c[i] = ls->current; + r = 10 * r + c[i] - '0'; next(ls); - if (ls->current == '[') { /* long comment? */ - int sep = skip_sep(ls); - luaZ_resetbuffer(ls->buff); /* `skip_sep' may dirty the buffer */ - if (sep >= 0) { - read_long_string(ls, NULL, sep); /* skip long comment */ - luaZ_resetbuffer(ls->buff); /* previous call may dirty the buff. */ - break; - } - } - /* else short comment */ - while (!currIsNewline(ls) && ls->current != EOZ) - next(ls); /* skip until end of line (or end of file) */ - break; - } - case '[': { /* long string or simply '[' */ - int sep = skip_sep(ls); - if (sep >= 0) { - read_long_string(ls, seminfo, sep); - return TK_STRING; + } + if (r > UCHAR_MAX) escerror(ls, c, i, "decimal escape too large"); + return r; +} + +static void read_string(LexState *ls, int del, SemInfo *seminfo) { + save_and_next(ls); /* keep delimiter (for error messages) */ + while (ls->current != del) { + switch (ls->current) { + case EOZ: + lexerror(ls, "unfinished string", TK_EOS); + break; /* to avoid warnings */ + case '\n': + case '\r': + lexerror(ls, "unfinished string", TK_STRING); + break; /* to avoid warnings */ + case '\\': { /* escape sequences */ + int c; /* final character to be saved */ + next(ls); /* do not save the `\' */ + switch (ls->current) { + case 'a': + c = '\a'; + goto read_save; + case 'b': + c = '\b'; + goto read_save; + case 'f': + c = '\f'; + goto read_save; + case 'n': + c = '\n'; + goto read_save; + case 'r': + c = '\r'; + goto read_save; + case 't': + c = '\t'; + goto read_save; + case 'v': + c = '\v'; + goto read_save; + case 'x': + c = readhexaesc(ls); + goto read_save; + case '\n': + case '\r': + inclinenumber(ls); + c = '\n'; + goto only_save; + case '\\': + case '\"': + case '\'': + c = ls->current; + goto read_save; + case EOZ: + goto no_save; /* will raise an error next loop */ + case 'z': { /* zap following span of spaces */ + next(ls); /* skip the 'z' */ + while (lisspace(ls->current)) { + if (currIsNewline(ls)) + inclinenumber(ls); + else + next(ls); + } + goto no_save; + } + default: { + if (!lisdigit(ls->current)) + escerror(ls, &ls->current, 1, "invalid escape sequence"); + /* digital escape \ddd */ + c = readdecesc(ls); + goto only_save; + } + } + read_save: + next(ls); /* read next character */ + only_save: + save(ls, c); /* save 'c' */ + no_save: + break; + } + default: + save_and_next(ls); } - else if (sep == -1) return '['; - else lexerror(ls, "invalid long string delimiter", TK_STRING); - } - case '=': { - next(ls); - if (ls->current != '=') return '='; - else { next(ls); return TK_EQ; } - } - case '<': { - next(ls); - if (ls->current == '=') { next(ls); return TK_LE; } - else if(ls->current == '<') { next(ls); return TK_LSHIFT; } - else return '<'; - } - case '>': { - next(ls); - if (ls->current == '=') { next(ls); return TK_GE; } - else if(ls->current == '>') { next(ls); return TK_RSHIFT; } - else return '>'; - } - case '~': { - next(ls); - if (ls->current != '=') return '~'; - else { next(ls); return TK_NE; } - } - case ':': { - next(ls); - if (ls->current != ':') return ':'; - else { next(ls); return TK_DBCOLON; } - } - case '"': case '\'': { /* short literal strings */ - read_string(ls, ls->current, seminfo); - return TK_STRING; - } - case '.': { /* '.', '..', '...', or number */ - save_and_next(ls); - if (check_next(ls, ".")) { - if (check_next(ls, ".")) - return TK_DOTS; /* '...' */ - else return TK_CONCAT; /* '..' */ + } + save_and_next(ls); /* skip delimiter */ + seminfo->ts = + luaX_newstring(ls, luaZ_buffer(ls->buff) + 1, luaZ_bufflen(ls->buff) - 2); +} + +static void dump_stack(lua_State *L, int elem) { + lua_pushvalue(L, elem); + lua_getfield(L, LUA_GLOBALSINDEX, "terra"); + lua_getfield(L, -1, "tree"); + lua_getfield(L, -1, "printraw"); + lua_pushvalue(L, -4); + lua_call(L, 1, 0); + + lua_pop(L, 3); +} + +static int llex(LexState *ls, SemInfo *seminfo) { + (void)dump_stack; // suppress unused warning for debugging function + luaZ_resetbuffer(ls->buff); + seminfo->buffer_begin = + ls->output_buffer.N - 1; //- 1 because we already recorded the first token + seminfo->linebegin = ls->linenumber; // no -1 because we haven't incremented line + // info for this token yet + for (;;) { + switch (ls->current) { + case '\n': + case '\r': { /* line breaks */ + inclinenumber(ls); + break; + } + case ' ': + case '\f': + case '\t': + case '\v': { /* spaces */ + next(ls); + break; + } + case '-': { /* '-' or '--' (comment) */ + next(ls); + if (ls->current == '>') { + next(ls); + return TK_FUNC_PTR; + } + if (ls->current != '-') return '-'; + /* else is a comment */ + next(ls); + if (ls->current == '[') { /* long comment? */ + int sep = skip_sep(ls); + luaZ_resetbuffer(ls->buff); /* `skip_sep' may dirty the buffer */ + if (sep >= 0) { + read_long_string(ls, NULL, sep); /* skip long comment */ + luaZ_resetbuffer( + ls->buff); /* previous call may dirty the buff. */ + break; + } + } + /* else short comment */ + while (!currIsNewline(ls) && ls->current != EOZ) + next(ls); /* skip until end of line (or end of file) */ + break; + } + case '[': { /* long string or simply '[' */ + int sep = skip_sep(ls); + if (sep >= 0) { + read_long_string(ls, seminfo, sep); + return TK_STRING; + } else if (sep == -1) + return '['; + else + lexerror(ls, "invalid long string delimiter", TK_STRING); + } + case '=': { + next(ls); + if (ls->current != '=') + return '='; + else { + next(ls); + return TK_EQ; + } + } + case '<': { + next(ls); + if (ls->current == '=') { + next(ls); + return TK_LE; + } else if (ls->current == '<') { + next(ls); + return TK_LSHIFT; + } else + return '<'; + } + case '>': { + next(ls); + if (ls->current == '=') { + next(ls); + return TK_GE; + } else if (ls->current == '>') { + next(ls); + return TK_RSHIFT; + } else + return '>'; + } + case '~': { + next(ls); + if (ls->current != '=') + return '~'; + else { + next(ls); + return TK_NE; + } + } + case ':': { + next(ls); + if (ls->current != ':') + return ':'; + else { + next(ls); + return TK_DBCOLON; + } + } + case '"': + case '\'': { /* short literal strings */ + read_string(ls, ls->current, seminfo); + return TK_STRING; + } + case '.': { /* '.', '..', '...', or number */ + save_and_next(ls); + if (check_next(ls, ".")) { + if (check_next(ls, ".")) + return TK_DOTS; /* '...' */ + else + return TK_CONCAT; /* '..' */ + } else if (!lisdigit(ls->current)) + return '.'; + /* else go through */ + } + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + read_numeral(ls, seminfo); + return TK_NUMBER; + } + case EOZ: { + seminfo->buffer_begin = + ls->output_buffer.N; // EOS is not counted as a character, so we + // need to make sure the beginning of this + // token points to the end of the tokens + return TK_EOS; + } + default: { + if (lislalpha(ls->current)) { /* identifier or reserved word? */ + TString *ts; + do { + save_and_next(ls); + } while (lislalnum(ls->current)); + ts = luaX_newstring(ls, luaZ_buffer(ls->buff), + luaZ_bufflen(ls->buff)); + seminfo->ts = ts; + if (ts->reserved > 0) /* reserved word? */ + return ts->reserved - 1 + FIRST_RESERVED; + else { + if (ls->languageextensionsenabled) { + luaX_globalgetfield(ls, TA_ENTRY_POINT_TABLE, getstr(ts)); + int special = lua_istable(ls->L, -1); + lua_pop(ls->L, 1); /* remove lookup value */ + if (special) return TK_SPECIAL; + } + return TK_NAME; + } + } else { /* single-char tokens (+ - / ...) */ + int c = ls->current; + next(ls); + return c; + } + } } - else if (!lisdigit(ls->current)) return '.'; - /* else go through */ - } - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': { - read_numeral(ls, seminfo); - return TK_NUMBER; - } - case EOZ: { - seminfo->buffer_begin = ls->output_buffer.N; //EOS is not counted as a character, so we need to make sure the beginning of this token points to the end of the tokens - return TK_EOS; - } - default: { - if (lislalpha(ls->current)) { /* identifier or reserved word? */ - TString *ts; - do { - save_and_next(ls); - } while (lislalnum(ls->current)); - ts = luaX_newstring(ls, luaZ_buffer(ls->buff), - luaZ_bufflen(ls->buff)); - seminfo->ts = ts; - if (ts->reserved > 0) /* reserved word? */ - return ts->reserved - 1 + FIRST_RESERVED; - else { - if(ls->languageextensionsenabled) { - luaX_globalgetfield(ls, TA_ENTRY_POINT_TABLE, getstr(ts)); - int special = lua_istable(ls->L,-1); - lua_pop(ls->L,1); /* remove lookup value */ - if(special) - return TK_SPECIAL; - } - return TK_NAME; - } - } - else { /* single-char tokens (+ - / ...) */ - int c = ls->current; - next(ls); - return c; - } - } - } - } - } - - -void luaX_next (LexState *ls) { - ls->lastline = ls->linenumber; - if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */ - ls->t = ls->lookahead; /* use this one */ - ls->lookahead.token = TK_EOS; /* and discharge it */ - } - else - ls->t.token = llex(ls, &ls->t.seminfo); /* read next token */ -} - - -int luaX_lookahead (LexState *ls) { - assert(ls->lookahead.token == TK_EOS); - ls->lookahead.token = llex(ls, &ls->lookahead.seminfo); - return ls->lookahead.token; -} - -void luaX_globalpush(LexState * ls, TA_Globals k) { - lua_pushlightuserdata(ls->L,&ls->lextable); - lua_rawget(ls->L,LUA_REGISTRYINDEX); - lua_rawgeti(ls->L,-1,k); - lua_remove(ls->L,-2); /*remove lexstate table*/ -} -void luaX_globalgettable(LexState * ls, TA_Globals k) { - luaX_globalpush(ls, k); - lua_insert(ls->L,-2); - lua_gettable(ls->L,-2); - lua_remove(ls->L,-2); /*remove the global table*/ + } } -void luaX_globalgetfield(LexState * ls, TA_Globals k, const char * field) { - luaX_globalpush(ls,k); - lua_getfield(ls->L,-1,field); - lua_remove(ls->L,-2); + +void luaX_next(LexState *ls) { + ls->lastline = ls->linenumber; + if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */ + ls->t = ls->lookahead; /* use this one */ + ls->lookahead.token = TK_EOS; /* and discharge it */ + } else + ls->t.token = llex(ls, &ls->t.seminfo); /* read next token */ } -void luaX_globalset(LexState * ls, TA_Globals k) { - lua_pushlightuserdata(ls->L,&ls->lextable); - lua_rawget(ls->L,LUA_REGISTRYINDEX); - lua_insert(ls->L,-2); - lua_rawseti(ls->L,-2,k); - lua_pop(ls->L,1); + +int luaX_lookahead(LexState *ls) { + assert(ls->lookahead.token == TK_EOS); + ls->lookahead.token = llex(ls, &ls->lookahead.seminfo); + return ls->lookahead.token; } +void luaX_globalpush(LexState *ls, TA_Globals k) { + lua_pushlightuserdata(ls->L, &ls->lextable); + lua_rawget(ls->L, LUA_REGISTRYINDEX); + lua_rawgeti(ls->L, -1, k); + lua_remove(ls->L, -2); /*remove lexstate table*/ +} +void luaX_globalgettable(LexState *ls, TA_Globals k) { + luaX_globalpush(ls, k); + lua_insert(ls->L, -2); + lua_gettable(ls->L, -2); + lua_remove(ls->L, -2); /*remove the global table*/ +} +void luaX_globalgetfield(LexState *ls, TA_Globals k, const char *field) { + luaX_globalpush(ls, k); + lua_getfield(ls->L, -1, field); + lua_remove(ls->L, -2); +} +void luaX_globalset(LexState *ls, TA_Globals k) { + lua_pushlightuserdata(ls->L, &ls->lextable); + lua_rawget(ls->L, LUA_REGISTRYINDEX); + lua_insert(ls->L, -2); + lua_rawseti(ls->L, -2, k); + lua_pop(ls->L, 1); +} diff --git a/src/llex.h b/src/llex.h index a2ec908ec..ce7d7acb9 100644 --- a/src/llex.h +++ b/src/llex.h @@ -13,97 +13,133 @@ #include #include -#define FIRST_RESERVED 257 +#define FIRST_RESERVED 257 /* -* WARNING: if you change the order of this enumeration, -* grep "ORDER RESERVED" -*/ + * WARNING: if you change the order of this enumeration, + * grep "ORDER RESERVED" + */ enum RESERVED { - /* terminal symbols denoted by reserved words */ - TK_AND = FIRST_RESERVED, TK_BREAK, - TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, - TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, - TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, TK_TERRA, TK_VAR, TK_STRUCT, TK_UNION, TK_QUOTE, TK_IMPORT, TK_DEFER, TK_ESCAPE, /* WARNING: if you add a new last terminal, make sure to update NUM_RESERVED below to be the last terminal */ - /* other terminal symbols */ - TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_DBCOLON, TK_FUNC_PTR, TK_LSHIFT, TK_RSHIFT, TK_EOS, - TK_NUMBER, TK_NAME, TK_STRING, TK_SPECIAL + /* terminal symbols denoted by reserved words */ + TK_AND = FIRST_RESERVED, + TK_BREAK, + TK_DO, + TK_ELSE, + TK_ELSEIF, + TK_END, + TK_FALSE, + TK_FOR, + TK_FUNCTION, + TK_GOTO, + TK_IF, + TK_IN, + TK_LOCAL, + TK_NIL, + TK_NOT, + TK_OR, + TK_REPEAT, + TK_RETURN, + TK_THEN, + TK_TRUE, + TK_UNTIL, + TK_WHILE, + TK_TERRA, + TK_VAR, + TK_STRUCT, + TK_UNION, + TK_QUOTE, + TK_IMPORT, + TK_DEFER, + TK_ESCAPE, /* WARNING: if you add a new last terminal, make sure to update + NUM_RESERVED below to be the last terminal */ + /* other terminal symbols */ + TK_CONCAT, + TK_DOTS, + TK_EQ, + TK_GE, + TK_LE, + TK_NE, + TK_DBCOLON, + TK_FUNC_PTR, + TK_LSHIFT, + TK_RSHIFT, + TK_EOS, + TK_NUMBER, + TK_NAME, + TK_STRING, + TK_SPECIAL }; /* number of reserved words */ -#define NUM_RESERVED (cast(int, TK_ESCAPE-FIRST_RESERVED+1)) - +#define NUM_RESERVED (cast(int, TK_ESCAPE - FIRST_RESERVED + 1)) typedef struct { - union { - luaP_Number r; - TString * ts; - }; - int flags; //same as ReadNumber flags - uint64_t i; //integer value, for terra - int linebegin; //line on which we _started_ parsing this token - int buffer_begin; //position in buffer where we _started_ parsing this token -} SemInfo; /* semantics information */ - + union { + luaP_Number r; + TString *ts; + }; + int flags; // same as ReadNumber flags + uint64_t i; // integer value, for terra + int linebegin; // line on which we _started_ parsing this token + int buffer_begin; // position in buffer where we _started_ parsing this token +} SemInfo; /* semantics information */ typedef struct Token { - int token; - SemInfo seminfo; + int token; + SemInfo seminfo; } Token; - struct OutputBuffer { int N; int space; - char * data; + char *data; }; -static inline void OutputBuffer_init(OutputBuffer * buf) { +static inline void OutputBuffer_init(OutputBuffer *buf) { buf->N = 0; buf->space = 1024; - buf->data = (char*) malloc(buf->space); + buf->data = (char *)malloc(buf->space); } -static inline void OutputBuffer_free(OutputBuffer * buf) { +static inline void OutputBuffer_free(OutputBuffer *buf) { buf->N = 0; buf->space = 0; free(buf->data); buf->data = NULL; } -static inline void OutputBuffer_resize(OutputBuffer * buf, int newsize) { - buf->N = std::min(newsize,buf->N); +static inline void OutputBuffer_resize(OutputBuffer *buf, int newsize) { + buf->N = std::min(newsize, buf->N); buf->space = newsize; - buf->data = (char*) realloc(buf->data,newsize); + buf->data = (char *)realloc(buf->data, newsize); } -static inline void OutputBuffer_putc(OutputBuffer * buf, char c) { - if(buf->N == buf->space) - OutputBuffer_resize(buf,buf->space * 2); +static inline void OutputBuffer_putc(OutputBuffer *buf, char c) { + if (buf->N == buf->space) OutputBuffer_resize(buf, buf->space * 2); buf->data[buf->N] = c; buf->N++; } -static inline void OutputBuffer_rewind(OutputBuffer * buf, int size) { - buf->N -= std::min(buf->N,size); +static inline void OutputBuffer_rewind(OutputBuffer *buf, int size) { + buf->N -= std::min(buf->N, size); } -static inline void OutputBuffer_printf(OutputBuffer * buf,const char * fmt,...) { - if(buf->N == buf->space) { - OutputBuffer_resize(buf,buf->space * 2); +static inline void OutputBuffer_printf(OutputBuffer *buf, const char *fmt, ...) { + if (buf->N == buf->space) { + OutputBuffer_resize(buf, buf->space * 2); } - while(1) { + while (1) { va_list ap; - va_start(ap,fmt); + va_start(ap, fmt); int most_written = buf->space - buf->N; int n = vsnprintf(buf->data + buf->N, most_written, fmt, ap); - if(n > -1 && n < most_written) { + if (n > -1 && n < most_written) { buf->N += n; return; } OutputBuffer_resize(buf, buf->space * 2); } } -static inline void OutputBuffer_puts(OutputBuffer * buf, int N, const char * str) { - if(buf->N + N > buf->space) { - OutputBuffer_resize(buf,std::max(buf->space * 2,buf->N + N)); +static inline void OutputBuffer_puts(OutputBuffer *buf, int N, const char *str) { + if (buf->N + N > buf->space) { + OutputBuffer_resize(buf, std::max(buf->space * 2, buf->N + N)); } - memcpy(buf->data + buf->N,str,N); + memcpy(buf->data + buf->N, str, N); buf->N += N; } @@ -111,59 +147,58 @@ struct TerraCnt; /* state of the lexer plus state of the parser when shared by all functions */ typedef struct LexState { - int current; /* current character (charint) */ - int linenumber; /* input line counter */ - int lastline; /* line of last token `consumed' */ - int currentoffset; - Token t; /* current token */ - Token lookahead; /* look ahead token */ - struct FuncState *fs; /* current function (parser) */ - TerraCnt * terracnt; - lua_State *L; - int n_lua_objects; /*number of lua objects already in table of lua asts*/ - terra_State *LP; - ZIO *z; /* input stream */ - Mbuffer *buff; /* buffer for tokens */ - TString * source; /* current source name */ - TString * envn; /* environment variable name */ - char decpoint; /* locale decimal point */ - - int in_terra; - OutputBuffer output_buffer; - - struct { - char * buffer; - int N; - int space; - } patchinfo; //data to fix up output stream when we insert terra information - - int stacktop; /* top of lua stack when we start this function */ - int languageextensionsenabled; /* 0 if extensions are off */ - int rethrow; /* set to 1 when le_luaexpr needs to re-report an error message, used to suppress the duplicate - addition of context information */ - char lextable; /* &lextable is the registry key for lua state associated with the LexState object*/ + int current; /* current character (charint) */ + int linenumber; /* input line counter */ + int lastline; /* line of last token `consumed' */ + int currentoffset; + Token t; /* current token */ + Token lookahead; /* look ahead token */ + struct FuncState *fs; /* current function (parser) */ + TerraCnt *terracnt; + lua_State *L; + int n_lua_objects; /*number of lua objects already in table of lua asts*/ + terra_State *LP; + ZIO *z; /* input stream */ + Mbuffer *buff; /* buffer for tokens */ + TString *source; /* current source name */ + TString *envn; /* environment variable name */ + char decpoint; /* locale decimal point */ + + int in_terra; + OutputBuffer output_buffer; + + struct { + char *buffer; + int N; + int space; + } patchinfo; // data to fix up output stream when we insert terra information + + int stacktop; /* top of lua stack when we start this function */ + int languageextensionsenabled; /* 0 if extensions are off */ + int rethrow; /* set to 1 when le_luaexpr needs to re-report an error message, used to + suppress the duplicate addition of context information */ + char lextable; /* &lextable is the registry key for lua state associated with the + LexState object*/ } LexState; - -LUAI_FUNC void luaX_init (terra_State *L); -LUAI_FUNC void luaX_setinput (terra_State *L, LexState *ls, ZIO *z, - TString * source, int firstchar); -LUAI_FUNC TString * luaX_newstring (LexState *ls, const char *str, size_t l); -LUAI_FUNC void luaX_next (LexState *ls); -LUAI_FUNC int luaX_lookahead (LexState *ls); -LUAI_FUNC l_noret luaX_syntaxerror (LexState *ls, const char *s); -LUAI_FUNC const char * luaX_token2str (LexState *ls, int token); -LUAI_FUNC void luaX_patchbegin(LexState *ls, Token * begin_token); -LUAI_FUNC void luaX_patchend(LexState *ls, Token * begin_token); -LUAI_FUNC void luaX_insertbeforecurrenttoken(LexState * ls, char c); -const char * luaX_saveoutput(LexState * ls, Token * begin_token); -void luaX_getoutput(LexState * ls, Token * begin_token, const char ** output, int * N); -const char * luaX_token2rawstr(LexState * ls, int token); - -void luaX_pushtstringtable(terra_State * L); -void luaX_poptstringtable(terra_State * L); -l_noret luaX_reporterror(LexState * ls, const char * err); - +LUAI_FUNC void luaX_init(terra_State *L); +LUAI_FUNC void luaX_setinput(terra_State *L, LexState *ls, ZIO *z, TString *source, + int firstchar); +LUAI_FUNC TString *luaX_newstring(LexState *ls, const char *str, size_t l); +LUAI_FUNC void luaX_next(LexState *ls); +LUAI_FUNC int luaX_lookahead(LexState *ls); +LUAI_FUNC l_noret luaX_syntaxerror(LexState *ls, const char *s); +LUAI_FUNC const char *luaX_token2str(LexState *ls, int token); +LUAI_FUNC void luaX_patchbegin(LexState *ls, Token *begin_token); +LUAI_FUNC void luaX_patchend(LexState *ls, Token *begin_token); +LUAI_FUNC void luaX_insertbeforecurrenttoken(LexState *ls, char c); +const char *luaX_saveoutput(LexState *ls, Token *begin_token); +void luaX_getoutput(LexState *ls, Token *begin_token, const char **output, int *N); +const char *luaX_token2rawstr(LexState *ls, int token); + +void luaX_pushtstringtable(terra_State *L); +void luaX_poptstringtable(terra_State *L); +l_noret luaX_reporterror(LexState *ls, const char *err); enum TA_Globals { TA_TERRA_OBJECT = 1, @@ -174,10 +209,10 @@ enum TA_Globals { TA_TYPE_TABLE, TA_LAST_GLOBAL }; -//accessors for lua state assocated with the Terra lexer -void luaX_globalpush(LexState * ls, TA_Globals k); -void luaX_globalgettable(LexState * ls, TA_Globals k); -void luaX_globalgetfield(LexState * ls, TA_Globals k, const char * field); -void luaX_globalset(LexState * ls, TA_Globals k); +// accessors for lua state assocated with the Terra lexer +void luaX_globalpush(LexState *ls, TA_Globals k); +void luaX_globalgettable(LexState *ls, TA_Globals k); +void luaX_globalgetfield(LexState *ls, TA_Globals k, const char *field); +void luaX_globalset(LexState *ls, TA_Globals k); #endif diff --git a/src/llvmheaders.h b/src/llvmheaders.h index bb294ee26..08aeac52d 100644 --- a/src/llvmheaders.h +++ b/src/llvmheaders.h @@ -72,7 +72,7 @@ #include "llvmheaders_70.h" #else #error "unsupported LLVM version" -//for OSX code completion +// for OSX code completion #define LLVM_VERSION 60 #include "llvmheaders_60.h" #endif @@ -86,13 +86,13 @@ #endif #if LLVM_VERSION >= 36 -#define UNIQUEIFY(T,x) (std::unique_ptr(x)) +#define UNIQUEIFY(T, x) (std::unique_ptr(x)) #define FD_ERRTYPE std::error_code #define FD_ISERR(x) (x) #define FD_ERRSTR(x) ((x).message().c_str()) #define METADATA_ROOT_TYPE llvm::Metadata #else -#define UNIQUEIFY(T,x) (x) +#define UNIQUEIFY(T, x) (x) #define FD_ERRTYPE std::string #define FD_ISERR(x) (!(x).empty()) #define FD_ERRSTR(x) ((x).c_str()) @@ -100,20 +100,20 @@ #endif #if LLVM_VERSION >= 37 -using llvm::legacy::PassManager; using llvm::legacy::FunctionPassManager; +using llvm::legacy::PassManager; typedef llvm::raw_pwrite_stream emitobjfile_t; typedef llvm::DIFile* DIFileP; #else #define DEBUG_INFO_WORKING -using llvm::PassManager; using llvm::FunctionPassManager; +using llvm::PassManager; typedef llvm::raw_ostream emitobjfile_t; typedef llvm::DIFile DIFileP; #endif #if LLVM_VERSION >= 38 -inline void LLVMDisposeMessage(char *Message) { free(Message); } +inline void LLVMDisposeMessage(char* Message) { free(Message); } typedef llvm::legacy::PassManager PassManagerT; typedef llvm::legacy::FunctionPassManager FunctionPassManagerT; #else @@ -121,5 +121,4 @@ typedef PassManager PassManagerT; typedef FunctionPassManager FunctionPassManagerT; #endif - #endif diff --git a/src/llvmheaders_32.h b/src/llvmheaders_32.h index fb2d5547a..1a8669fb7 100644 --- a/src/llvmheaders_32.h +++ b/src/llvmheaders_32.h @@ -20,10 +20,9 @@ #include "clang/Rewrite/Core/Rewriter.h" #include "clang/Rewrite/Frontend/Rewriters.h" - #define LLVM_PATH_TYPE llvm::sys::Path #define RAW_FD_OSTREAM_NONE 0 #define RAW_FD_OSTREAM_BINARY raw_fd_ostream::F_Binary -#define HASFNATTR(attr) getFnAttributes().hasAttribute(Attributes :: attr) -#define ADDFNATTR(attr) addFnAttr(Attributes :: attr) +#define HASFNATTR(attr) getFnAttributes().hasAttribute(Attributes ::attr) +#define ADDFNATTR(attr) addFnAttr(Attributes ::attr) #define ATTRIBUTE Attributes diff --git a/src/llvmheaders_33.h b/src/llvmheaders_33.h index 6c2b8cbbf..d2716f586 100644 --- a/src/llvmheaders_33.h +++ b/src/llvmheaders_33.h @@ -20,10 +20,10 @@ #include "clang/Rewrite/Core/Rewriter.h" #include "clang/Rewrite/Frontend/Rewriters.h" - #define LLVM_PATH_TYPE llvm::sys::Path #define RAW_FD_OSTREAM_NONE 0 #define RAW_FD_OSTREAM_BINARY raw_fd_ostream::F_Binary -#define HASFNATTR(attr) getAttributes().hasAttribute(AttributeSet::FunctionIndex, Attribute :: attr) -#define ADDFNATTR(attr) addFnAttr(Attribute :: attr) +#define HASFNATTR(attr) \ + getAttributes().hasAttribute(AttributeSet::FunctionIndex, Attribute ::attr) +#define ADDFNATTR(attr) addFnAttr(Attribute ::attr) #define ATTRIBUTE Attributes \ No newline at end of file diff --git a/src/llvmheaders_34.h b/src/llvmheaders_34.h index c957b6835..ed68e1ed7 100644 --- a/src/llvmheaders_34.h +++ b/src/llvmheaders_34.h @@ -24,6 +24,7 @@ #define LLVM_PATH_TYPE std::string #define RAW_FD_OSTREAM_NONE sys::fs::F_None #define RAW_FD_OSTREAM_BINARY sys::fs::F_Binary -#define HASFNATTR(attr) getAttributes().hasAttribute(AttributeSet::FunctionIndex, Attribute :: attr) -#define ADDFNATTR(attr) addFnAttr(Attribute :: attr) +#define HASFNATTR(attr) \ + getAttributes().hasAttribute(AttributeSet::FunctionIndex, Attribute ::attr) +#define ADDFNATTR(attr) addFnAttr(Attribute ::attr) #define ATTRIBUTE Attributes \ No newline at end of file diff --git a/src/llvmheaders_35.h b/src/llvmheaders_35.h index c7c9da952..c1e0c55ab 100644 --- a/src/llvmheaders_35.h +++ b/src/llvmheaders_35.h @@ -20,10 +20,10 @@ #include "clang/Rewrite/Core/Rewriter.h" #include "clang/Rewrite/Frontend/Rewriters.h" - #define LLVM_PATH_TYPE std::string #define RAW_FD_OSTREAM_NONE sys::fs::F_None #define RAW_FD_OSTREAM_BINARY sys::fs::F_None -#define HASFNATTR(attr) getAttributes().hasAttribute(AttributeSet::FunctionIndex, Attribute :: attr) -#define ADDFNATTR(attr) addFnAttr(Attribute :: attr) +#define HASFNATTR(attr) \ + getAttributes().hasAttribute(AttributeSet::FunctionIndex, Attribute ::attr) +#define ADDFNATTR(attr) addFnAttr(Attribute ::attr) #define ATTRIBUTE Attributes \ No newline at end of file diff --git a/src/llvmheaders_36.h b/src/llvmheaders_36.h index 7d95112d2..c782778f5 100644 --- a/src/llvmheaders_36.h +++ b/src/llvmheaders_36.h @@ -23,6 +23,7 @@ #define LLVM_PATH_TYPE std::string #define RAW_FD_OSTREAM_NONE sys::fs::F_None #define RAW_FD_OSTREAM_BINARY sys::fs::F_None -#define HASFNATTR(attr) getAttributes().hasAttribute(AttributeSet::FunctionIndex, Attribute :: attr) -#define ADDFNATTR(attr) addFnAttr(Attribute :: attr) +#define HASFNATTR(attr) \ + getAttributes().hasAttribute(AttributeSet::FunctionIndex, Attribute ::attr) +#define ADDFNATTR(attr) addFnAttr(Attribute ::attr) #define ATTRIBUTE Attributes \ No newline at end of file diff --git a/src/llvmheaders_37.h b/src/llvmheaders_37.h index 03cc0ab1d..60b204a9b 100644 --- a/src/llvmheaders_37.h +++ b/src/llvmheaders_37.h @@ -25,6 +25,7 @@ #define LLVM_PATH_TYPE std::string #define RAW_FD_OSTREAM_NONE sys::fs::F_None #define RAW_FD_OSTREAM_BINARY sys::fs::F_None -#define HASFNATTR(attr) getAttributes().hasAttribute(AttributeSet::FunctionIndex, Attribute :: attr) -#define ADDFNATTR(attr) addFnAttr(Attribute :: attr) +#define HASFNATTR(attr) \ + getAttributes().hasAttribute(AttributeSet::FunctionIndex, Attribute ::attr) +#define ADDFNATTR(attr) addFnAttr(Attribute ::attr) #define ATTRIBUTE Attributes \ No newline at end of file diff --git a/src/llvmheaders_38.h b/src/llvmheaders_38.h index 03cc0ab1d..60b204a9b 100644 --- a/src/llvmheaders_38.h +++ b/src/llvmheaders_38.h @@ -25,6 +25,7 @@ #define LLVM_PATH_TYPE std::string #define RAW_FD_OSTREAM_NONE sys::fs::F_None #define RAW_FD_OSTREAM_BINARY sys::fs::F_None -#define HASFNATTR(attr) getAttributes().hasAttribute(AttributeSet::FunctionIndex, Attribute :: attr) -#define ADDFNATTR(attr) addFnAttr(Attribute :: attr) +#define HASFNATTR(attr) \ + getAttributes().hasAttribute(AttributeSet::FunctionIndex, Attribute ::attr) +#define ADDFNATTR(attr) addFnAttr(Attribute ::attr) #define ATTRIBUTE Attributes \ No newline at end of file diff --git a/src/llvmheaders_39.h b/src/llvmheaders_39.h index 03cc0ab1d..60b204a9b 100644 --- a/src/llvmheaders_39.h +++ b/src/llvmheaders_39.h @@ -25,6 +25,7 @@ #define LLVM_PATH_TYPE std::string #define RAW_FD_OSTREAM_NONE sys::fs::F_None #define RAW_FD_OSTREAM_BINARY sys::fs::F_None -#define HASFNATTR(attr) getAttributes().hasAttribute(AttributeSet::FunctionIndex, Attribute :: attr) -#define ADDFNATTR(attr) addFnAttr(Attribute :: attr) +#define HASFNATTR(attr) \ + getAttributes().hasAttribute(AttributeSet::FunctionIndex, Attribute ::attr) +#define ADDFNATTR(attr) addFnAttr(Attribute ::attr) #define ATTRIBUTE Attributes \ No newline at end of file diff --git a/src/llvmheaders_50.h b/src/llvmheaders_50.h index 9afd79a42..22d025b2d 100644 --- a/src/llvmheaders_50.h +++ b/src/llvmheaders_50.h @@ -27,6 +27,7 @@ #define LLVM_PATH_TYPE std::string #define RAW_FD_OSTREAM_NONE sys::fs::F_None #define RAW_FD_OSTREAM_BINARY sys::fs::F_None -#define HASFNATTR(attr) getAttributes().hasAttribute(AttributeSet::FunctionIndex, Attribute :: attr) -#define ADDFNATTR(attr) addFnAttr(Attribute :: attr) +#define HASFNATTR(attr) \ + getAttributes().hasAttribute(AttributeSet::FunctionIndex, Attribute ::attr) +#define ADDFNATTR(attr) addFnAttr(Attribute ::attr) #define ATTRIBUTE Attributes diff --git a/src/llvmheaders_60.h b/src/llvmheaders_60.h index 39f96e6ea..4f75a5d85 100644 --- a/src/llvmheaders_60.h +++ b/src/llvmheaders_60.h @@ -30,6 +30,7 @@ #define LLVM_PATH_TYPE std::string #define RAW_FD_OSTREAM_NONE sys::fs::F_None #define RAW_FD_OSTREAM_BINARY sys::fs::F_None -#define HASFNATTR(attr) getAttributes().hasAttribute(AttributeSet::FunctionIndex, Attribute :: attr) -#define ADDFNATTR(attr) addFnAttr(Attribute :: attr) +#define HASFNATTR(attr) \ + getAttributes().hasAttribute(AttributeSet::FunctionIndex, Attribute ::attr) +#define ADDFNATTR(attr) addFnAttr(Attribute ::attr) #define ATTRIBUTE Attributes diff --git a/src/llvmheaders_70.h b/src/llvmheaders_70.h index 39f96e6ea..4f75a5d85 100644 --- a/src/llvmheaders_70.h +++ b/src/llvmheaders_70.h @@ -30,6 +30,7 @@ #define LLVM_PATH_TYPE std::string #define RAW_FD_OSTREAM_NONE sys::fs::F_None #define RAW_FD_OSTREAM_BINARY sys::fs::F_None -#define HASFNATTR(attr) getAttributes().hasAttribute(AttributeSet::FunctionIndex, Attribute :: attr) -#define ADDFNATTR(attr) addFnAttr(Attribute :: attr) +#define HASFNATTR(attr) \ + getAttributes().hasAttribute(AttributeSet::FunctionIndex, Attribute ::attr) +#define ADDFNATTR(attr) addFnAttr(Attribute ::attr) #define ATTRIBUTE Attributes diff --git a/src/lobject.cpp b/src/lobject.cpp index 6f29e8497..ec18f1333 100644 --- a/src/lobject.cpp +++ b/src/lobject.cpp @@ -6,81 +6,78 @@ #include "lobject.h" #include "llex.h" -static int isneg (const char **s) { - if (**s == '-') { (*s)++; return 1; } - else if (**s == '+') (*s)++; - return 0; +static int isneg(const char **s) { + if (**s == '-') { + (*s)++; + return 1; + } else if (**s == '+') + (*s)++; + return 0; } - -int luaO_hexavalue (int c) { - if (lisdigit(c)) return c - '0'; - else return ltolower(c) - 'a' + 10; +int luaO_hexavalue(int c) { + if (lisdigit(c)) + return c - '0'; + else + return ltolower(c) - 'a' + 10; } -static luaP_Number readhexa (const char **s, luaP_Number r, int *count) { - for (; lisxdigit(cast_uchar(**s)); (*s)++) { /* read integer part */ - r = (r * 16.0) + cast_num(luaO_hexavalue(cast_uchar(**s))); - (*count)++; - } - return r; +static luaP_Number readhexa(const char **s, luaP_Number r, int *count) { + for (; lisxdigit(cast_uchar(**s)); (*s)++) { /* read integer part */ + r = (r * 16.0) + cast_num(luaO_hexavalue(cast_uchar(**s))); + (*count)++; + } + return r; } - /* ** convert an hexadecimal numeric string to a number, following ** C99 specification for 'strtod' */ -static luaP_Number luaP_strx2number (const char *s, char **endptr) { - luaP_Number r = 0.0; - int e = 0, i = 0; - int neg = 0; /* 1 if number is negative */ - *endptr = const_cast(cast(const char *, s)); /* nothing is valid yet */ - while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ - neg = isneg(&s); /* check signal */ - if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */ - return 0.0; /* invalid format (no '0x') */ - s += 2; /* skip '0x' */ - r = readhexa(&s, r, &i); /* read integer part */ - if (*s == '.') { - s++; /* skip dot */ - r = readhexa(&s, r, &e); /* read fractional part */ - } - if (i == 0 && e == 0) - return 0.0; /* invalid format (no digit) */ - e *= -4; /* each fractional digit divides value by 2^-4 */ - *endptr = const_cast(cast(const char *, s)); /* valid up to here */ - if (*s == 'p' || *s == 'P') { /* exponent part? */ - int exp1 = 0; - int neg1; - s++; /* skip 'p' */ - neg1 = isneg(&s); /* signal */ - if (!lisdigit(cast_uchar(*s))) - goto ret; /* must have at least one digit */ - while (lisdigit(cast_uchar(*s))) /* read exponent */ - exp1 = exp1 * 10 + *(s++) - '0'; - if (neg1) exp1 = -exp1; - e += exp1; - } - *endptr = const_cast(cast(const char *, s)); /* valid up to here */ - ret: - if (neg) r = -r; - return ldexp(r, e); +static luaP_Number luaP_strx2number(const char *s, char **endptr) { + luaP_Number r = 0.0; + int e = 0, i = 0; + int neg = 0; /* 1 if number is negative */ + *endptr = const_cast(cast(const char *, s)); /* nothing is valid yet */ + while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ + neg = isneg(&s); /* check signal */ + if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */ + return 0.0; /* invalid format (no '0x') */ + s += 2; /* skip '0x' */ + r = readhexa(&s, r, &i); /* read integer part */ + if (*s == '.') { + s++; /* skip dot */ + r = readhexa(&s, r, &e); /* read fractional part */ + } + if (i == 0 && e == 0) return 0.0; /* invalid format (no digit) */ + e *= -4; /* each fractional digit divides value by 2^-4 */ + *endptr = const_cast(cast(const char *, s)); /* valid up to here */ + if (*s == 'p' || *s == 'P') { /* exponent part? */ + int exp1 = 0; + int neg1; + s++; /* skip 'p' */ + neg1 = isneg(&s); /* signal */ + if (!lisdigit(cast_uchar(*s))) goto ret; /* must have at least one digit */ + while (lisdigit(cast_uchar(*s))) /* read exponent */ + exp1 = exp1 * 10 + *(s++) - '0'; + if (neg1) exp1 = -exp1; + e += exp1; + } + *endptr = const_cast(cast(const char *, s)); /* valid up to here */ +ret: + if (neg) r = -r; + return ldexp(r, e); } - - -int luaO_str2d (const char *s, size_t len, luaP_Number *result) { - char *endptr; - if (strpbrk(s, "nN")) /* reject 'inf' and 'nan' */ - return 0; - else if (strpbrk(s, "xX")) /* hexa? */ - *result = luaP_strx2number(s, &endptr); - else - *result = luaP_str2number(s, &endptr); - if (endptr == s) return 0; /* nothing recognized */ - while (lisspace(cast_uchar(*endptr))) endptr++; - return (endptr == s + len); /* OK if no trailing characters */ +int luaO_str2d(const char *s, size_t len, luaP_Number *result) { + char *endptr; + if (strpbrk(s, "nN")) /* reject 'inf' and 'nan' */ + return 0; + else if (strpbrk(s, "xX")) /* hexa? */ + *result = luaP_strx2number(s, &endptr); + else + *result = luaP_str2number(s, &endptr); + if (endptr == s) return 0; /* nothing recognized */ + while (lisspace(cast_uchar(*endptr))) endptr++; + return (endptr == s + len); /* OK if no trailing characters */ } - - diff --git a/src/lobject.h b/src/lobject.h index 8118bb717..6f5a4869f 100644 --- a/src/lobject.h +++ b/src/lobject.h @@ -13,25 +13,27 @@ ** systems, you can leave 'luaP_strx2number' undefined and Lua will ** provide its own implementation. */ -#define luaP_str2number(s,p) strtod((s), (p)) -int luaO_str2d (const char *s, size_t len, luaP_Number *result); -int luaO_hexavalue (int c); +#define luaP_str2number(s, p) strtod((s), (p)) +int luaO_str2d(const char *s, size_t len, luaP_Number *result); +int luaO_hexavalue(int c); /* ** `module' operation for hashing (size is always a power of 2) */ -#define lmod(s,size) \ - (check_exp((size&(size-1))==0, (cast(int, (s) & ((size)-1))))) +#define lmod(s, size) (check_exp((size & (size - 1)) == 0, (cast(int, (s) & ((size)-1))))) /* internal assertions for in-house debugging */ #if defined(luaP_assert) -#define check_exp(c,e) (luaP_assert(c), (e)) +#define check_exp(c, e) (luaP_assert(c), (e)) /* to avoid problems with conditions too long */ -#define luaP_longassert(c) { if (!(c)) luaP_assert(0); } +#define luaP_longassert(c) \ + { \ + if (!(c)) luaP_assert(0); \ + } #else -#define luaP_assert(c) ((void)0) -#define check_exp(c,e) (e) -#define luaP_longassert(c) ((void)0) +#define luaP_assert(c) ((void)0) +#define check_exp(c, e) (e) +#define luaP_longassert(c) ((void)0) #endif #endif diff --git a/src/lparser.cpp b/src/lparser.cpp index 124c9733a..edd4b50c3 100644 --- a/src/lparser.cpp +++ b/src/lparser.cpp @@ -4,7 +4,6 @@ ** See Copyright Notice in lua.h */ - #include #include #include @@ -32,93 +31,98 @@ #include "llvm/ADT/SmallSet.h" #include "treadnumber.h" -static void dump_stack(lua_State * L, int elem); - - -//helpers to ensure that the lua stack contains the right number of arguments after a call -#define RETURNS_N(x,n) do { \ - if(ls->in_terra) { \ - int begin = lua_gettop(ls->L); \ - (x); \ - int end = lua_gettop(ls->L); \ - if(begin + n != end) { \ - fprintf(stderr,"%s:%d: unmatched return\n",__FILE__,__LINE__); \ - luaX_syntaxerror(ls,"error"); \ - } \ - } else { \ - (x); \ - } \ -} while(0) - -#define RETURNS_1(x) RETURNS_N(x,1) -#define RETURNS_0(x) RETURNS_N(x,0) +static void dump_stack(lua_State *L, int elem); + +// helpers to ensure that the lua stack contains the right number of arguments after a +// call +#define RETURNS_N(x, n) \ + do { \ + if (ls->in_terra) { \ + int begin = lua_gettop(ls->L); \ + (x); \ + int end = lua_gettop(ls->L); \ + if (begin + n != end) { \ + fprintf(stderr, "%s:%d: unmatched return\n", __FILE__, __LINE__); \ + luaX_syntaxerror(ls, "error"); \ + } \ + } else { \ + (x); \ + } \ + } while (0) + +#define RETURNS_1(x) RETURNS_N(x, 1) +#define RETURNS_0(x) RETURNS_N(x, 0) /* maximum number of local variables per function (must be smaller than 250, due to the bytecode format) */ -#define MAXVARS 200 +#define MAXVARS 200 -#define hasmultret(k) ((k) == VCALL || (k) == VVARARG) +#define hasmultret(k) ((k) == VCALL || (k) == VVARARG) -typedef llvm::SmallSet StringSet; +typedef llvm::SmallSet StringSet; /* ** nodes for block list (list of active blocks) */ typedef struct BlockCnt { - struct BlockCnt *previous; /* chain */ - StringSet defined; - int isterra; /* does this scope describe a terra scope or a lua scope?*/ - int languageextensionsdefined; + struct BlockCnt *previous; /* chain */ + StringSet defined; + int isterra; /* does this scope describe a terra scope or a lua scope?*/ + int languageextensionsdefined; } BlockCnt; struct TerraCnt { - StringSet capturedlocals; /*list of all local variables that this terra block captures from the immediately enclosing lua block */ + StringSet capturedlocals; /*list of all local variables that this terra block captures + from the immediately enclosing lua block */ BlockCnt block; - TerraCnt * previous; + TerraCnt *previous; }; - -static int new_table(LexState * ls) { - if(ls->in_terra) { - //printf("(new table)\n"); +static int new_table(LexState *ls) { + if (ls->in_terra) { + // printf("(new table)\n"); lua_newtable(ls->L); return lua_gettop(ls->L); - } else return 0; + } else + return 0; } -static int new_list(LexState * ls) { - if(ls->in_terra) { - luaX_globalpush(ls,TA_NEWLIST); - lua_call(ls->L,0,1); +static int new_list(LexState *ls) { + if (ls->in_terra) { + luaX_globalpush(ls, TA_NEWLIST); + lua_call(ls->L, 0, 1); return lua_gettop(ls->L); - } else return 0; + } else + return 0; } -static int new_list_before(LexState * ls) { - if(ls->in_terra) { +static int new_list_before(LexState *ls) { + if (ls->in_terra) { int t = new_list(ls); - lua_insert(ls->L,-2); + lua_insert(ls->L, -2); return t - 1; - } else return 0; + } else + return 0; } -static void push_string_before(LexState * ls, const char * str) { - if(ls->in_terra) { - lua_pushstring(ls->L,str); - lua_insert(ls->L,-2); +static void push_string_before(LexState *ls, const char *str) { + if (ls->in_terra) { + lua_pushstring(ls->L, str); + lua_insert(ls->L, -2); } } -//this should eventually be optimized to use 'add_field' with tokens already on the stack -static void add_field(LexState * ls, int table, const char * field) { - if(ls->in_terra) { - table = (table < 0) ? (table + lua_gettop(ls->L) + 1) : table; //otherwise table is wrong once we modify the stack - //printf("consume field\n"); - - lua_setfield(ls->L,table,field); +// this should eventually be optimized to use 'add_field' with tokens already on the stack +static void add_field(LexState *ls, int table, const char *field) { + if (ls->in_terra) { + table = (table < 0) ? (table + lua_gettop(ls->L) + 1) + : table; // otherwise table is wrong once we modify the stack + // printf("consume field\n"); + + lua_setfield(ls->L, table, field); } } -static void push_string(LexState * ls, const char * str) { - if(ls->in_terra) { - //printf("push string: %s\n",str); - lua_pushstring(ls->L,str); +static void push_string(LexState *ls, const char *str) { + if (ls->in_terra) { + // printf("push string: %s\n",str); + lua_pushstring(ls->L, str); } } @@ -127,254 +131,248 @@ struct Position { int offset; }; -static Position getposition(LexState * ls) { - Position p = { ls->linenumber, ls->currentoffset - 1 }; +static Position getposition(LexState *ls) { + Position p = {ls->linenumber, ls->currentoffset - 1}; return p; } -static void table_setposition(LexState * ls, int t, Position p) { - lua_pushinteger(ls->L,p.linenumber); - lua_setfield(ls->L,t,"linenumber"); - lua_pushinteger(ls->L,p.offset); - lua_setfield(ls->L,t,"offset"); +static void table_setposition(LexState *ls, int t, Position p) { + lua_pushinteger(ls->L, p.linenumber); + lua_setfield(ls->L, t, "linenumber"); + lua_pushinteger(ls->L, p.offset); + lua_setfield(ls->L, t, "offset"); lua_pushstring(ls->L, getstr(ls->source)); - lua_setfield(ls->L,t, "filename"); + lua_setfield(ls->L, t, "filename"); } static int newobjecterror(lua_State *L) { - printf("newobjecterror: %s\n",lua_tostring(L,-1)); + printf("newobjecterror: %s\n", lua_tostring(L, -1)); exit(1); } -static int new_object(LexState * ls, const char * k, int N, Position * p) { - if(ls->in_terra) { +static int new_object(LexState *ls, const char *k, int N, Position *p) { + if (ls->in_terra) { luaX_globalgetfield(ls, TA_TYPE_TABLE, k); - lua_insert(ls->L,-(N+1)); - - lua_pushcfunction(ls->L,newobjecterror); - lua_insert(ls->L,-(N+2)); - - lua_pcall(ls->L,N,1,-(N+2)); - - table_setposition(ls, lua_gettop(ls->L) , *p); - - lua_remove(ls->L,-2); - + lua_insert(ls->L, -(N + 1)); + + lua_pushcfunction(ls->L, newobjecterror); + lua_insert(ls->L, -(N + 2)); + + lua_pcall(ls->L, N, 1, -(N + 2)); + + table_setposition(ls, lua_gettop(ls->L), *p); + + lua_remove(ls->L, -2); + return lua_gettop(ls->L); - } else return 0; + } else + return 0; } -static void add_index(LexState * ls, int table, int n) { - if(ls->in_terra) { - //printf("consume index\n"); - lua_pushinteger(ls->L,n); - lua_pushvalue(ls->L,-2); - lua_settable(ls->L,table); - lua_pop(ls->L,1); +static void add_index(LexState *ls, int table, int n) { + if (ls->in_terra) { + // printf("consume index\n"); + lua_pushinteger(ls->L, n); + lua_pushvalue(ls->L, -2); + lua_settable(ls->L, table); + lua_pop(ls->L, 1); } } -static int add_entry(LexState * ls, int table) { - if(ls->in_terra) { - int n = lua_objlen(ls->L,table); - add_index(ls,table,n+1); - return n+1; - } else return 0; +static int add_entry(LexState *ls, int table) { + if (ls->in_terra) { + int n = lua_objlen(ls->L, table); + add_index(ls, table, n + 1); + return n + 1; + } else + return 0; } -static void push_string(LexState * ls, TString * str) { - push_string(ls,getstr(str)); -} -static void push_boolean(LexState * ls, int b) { - if(ls->in_terra) { - //printf("push boolean\n"); - lua_pushboolean(ls->L,b); +static void push_string(LexState *ls, TString *str) { push_string(ls, getstr(str)); } +static void push_boolean(LexState *ls, int b) { + if (ls->in_terra) { + // printf("push boolean\n"); + lua_pushboolean(ls->L, b); } } -static void check_no_terra(LexState * ls, const char * thing) { - if(ls->in_terra) { - luaX_syntaxerror(ls,luaS_cstringf(ls->LP,"%s cannot be nested in terra functions.", thing)); +static void check_no_terra(LexState *ls, const char *thing) { + if (ls->in_terra) { + luaX_syntaxerror( + ls, + luaS_cstringf(ls->LP, "%s cannot be nested in terra functions.", thing)); } } -static void check_terra(LexState * ls, const char * thing) { - if(!ls->in_terra) { - luaX_syntaxerror(ls,luaS_cstringf(ls->LP,"%s cannot be used outside terra functions.", thing)); +static void check_terra(LexState *ls, const char *thing) { + if (!ls->in_terra) { + luaX_syntaxerror( + ls, luaS_cstringf(ls->LP, "%s cannot be used outside terra functions.", + thing)); } } /* ** prototypes for recursive non-terminal functions */ -static void statement (LexState *ls); -static void expr (LexState *ls); -static void terratype(LexState * ls); -static void luaexpr(LexState * ls); -static void embeddedcode(LexState * ls, int isterra, int isexp); -static void doquote(LexState * ls, int isexp); -static void languageextension(LexState * ls, int isstatement, int islocal); - -static void definevariable(LexState * ls, TString * varname) { +static void statement(LexState *ls); +static void expr(LexState *ls); +static void terratype(LexState *ls); +static void luaexpr(LexState *ls); +static void embeddedcode(LexState *ls, int isterra, int isexp); +static void doquote(LexState *ls, int isexp); +static void languageextension(LexState *ls, int isstatement, int islocal); + +static void definevariable(LexState *ls, TString *varname) { ls->fs->bl->defined.insert(varname); } -static void refvariable(LexState * ls, TString * varname) { - if(ls->terracnt == NULL) - return; /* no need to search for variables if we are not in a terra scope at all */ - //printf("searching %s\n",getstr(varname)); - TerraCnt * cur = NULL; - for(BlockCnt * bl = ls->fs->bl; bl != NULL; bl = bl->previous) { - //printf("ctx %d\n",bl->isterra); - if(bl->defined.count(varname)) { - if(cur && !bl->isterra) - cur->capturedlocals.insert(varname); - break; - } - if(bl->isterra && bl->previous && !bl->previous->isterra) { - cur = (cur) ? cur->previous : ls->terracnt; - assert(cur != NULL); +static void refvariable(LexState *ls, TString *varname) { + if (ls->terracnt == NULL) + return; /* no need to search for variables if we are not in a terra scope at all + */ + // printf("searching %s\n",getstr(varname)); + TerraCnt *cur = NULL; + for (BlockCnt *bl = ls->fs->bl; bl != NULL; bl = bl->previous) { + // printf("ctx %d\n",bl->isterra); + if (bl->defined.count(varname)) { + if (cur && !bl->isterra) cur->capturedlocals.insert(varname); + break; + } + if (bl->isterra && bl->previous && !bl->previous->isterra) { + cur = (cur) ? cur->previous : ls->terracnt; + assert(cur != NULL); + } } - } } -static l_noret error_expected (LexState *ls, int token) { - luaX_syntaxerror(ls, - luaS_cstringf(ls->LP, "%s expected", luaX_token2str(ls, token))); +static l_noret error_expected(LexState *ls, int token) { + luaX_syntaxerror(ls, luaS_cstringf(ls->LP, "%s expected", luaX_token2str(ls, token))); } - -static l_noret errorlimit (FuncState *fs, int limit, const char *what) { - terra_State *L = fs->ls->LP; - const char *msg; - int line = fs->f.linedefined; - const char *where = (line == 0) - ? "main function" - : luaS_cstringf(L, "function at line %d", line); - msg = luaS_cstringf(L, "too many %s (limit is %d) in %s", - what, limit, where); - luaX_syntaxerror(fs->ls, msg); +static l_noret errorlimit(FuncState *fs, int limit, const char *what) { + terra_State *L = fs->ls->LP; + const char *msg; + int line = fs->f.linedefined; + const char *where = + (line == 0) ? "main function" : luaS_cstringf(L, "function at line %d", line); + msg = luaS_cstringf(L, "too many %s (limit is %d) in %s", what, limit, where); + luaX_syntaxerror(fs->ls, msg); } - -static void checklimit (FuncState *fs, int v, int l, const char *what) { - if (v > l) errorlimit(fs, l, what); +static void checklimit(FuncState *fs, int v, int l, const char *what) { + if (v > l) errorlimit(fs, l, what); } - -static int testnext (LexState *ls, int c) { - if (ls->t.token == c) { - luaX_next(ls); - return 1; - } - else return 0; +static int testnext(LexState *ls, int c) { + if (ls->t.token == c) { + luaX_next(ls); + return 1; + } else + return 0; } - -static void check (LexState *ls, int c) { - if (ls->t.token != c) - error_expected(ls, c); +static void check(LexState *ls, int c) { + if (ls->t.token != c) error_expected(ls, c); } - -static void checknext (LexState *ls, int c) { - check(ls, c); - luaX_next(ls); +static void checknext(LexState *ls, int c) { + check(ls, c); + luaX_next(ls); } - -#define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); } - - - -static void check_match (LexState *ls, int what, int who, int where) { - if (!testnext(ls, what)) { - if (where == ls->linenumber) - error_expected(ls, what); - else { - luaX_syntaxerror(ls, luaS_cstringf(ls->LP, - "%s expected (to close %s at line %d)", - luaX_token2str(ls, what), luaX_token2str(ls, who), where)); +#define check_condition(ls, c, msg) \ + { \ + if (!(c)) luaX_syntaxerror(ls, msg); \ } - } -} - - -static TString *str_checkname (LexState *ls) { - TString *ts; - check(ls, TK_NAME); - ts = ls->t.seminfo.ts; - luaX_next(ls); - return ts; -} - -static void singlevar (LexState *ls) { - Position p = getposition(ls); - TString * varname = str_checkname(ls); - push_string(ls,varname); - new_object(ls,"var", 1,&p); - refvariable(ls, varname); -} - -//tries to parse a symbol "NAME | '['' lua expression '']'" -//returns true if a name was parsed and sets str to that name -//otherwise, str is not modified -static bool checksymbol(LexState * ls, TString ** str) { - Position p = getposition(ls); - int line = ls->linenumber; - if(ls->in_terra && testnext(ls,'[')) { - RETURNS_1(luaexpr(ls)); - new_object(ls,"escapedident",1,&p); - check_match(ls, ']', '[', line); - return false; - } - TString * nm = str_checkname(ls); - if(str) - *str = nm; - push_string(ls,nm); - new_object(ls,"namedident",1,&p); - return true; -} -static void enterlevel (LexState *ls) { - terra_State *L = ls->LP; - ++L->nCcalls; - checklimit(ls->fs, L->nCcalls, LUAI_MAXCCALLS, "C levels"); +static void check_match(LexState *ls, int what, int who, int where) { + if (!testnext(ls, what)) { + if (where == ls->linenumber) + error_expected(ls, what); + else { + luaX_syntaxerror( + ls, luaS_cstringf(ls->LP, "%s expected (to close %s at line %d)", + luaX_token2str(ls, what), luaX_token2str(ls, who), + where)); + } + } } -#define leavelevel(ls) ((ls)->LP->nCcalls--) - -static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isloop) { - bl->previous = fs->bl; - bl->isterra = fs->ls->in_terra; - bl->languageextensionsdefined = 0; - fs->bl = bl; - //printf("entering block %lld\n", (long long int)bl); - //printf("previous is %lld\n", (long long int)bl->previous); +static TString *str_checkname(LexState *ls) { + TString *ts; + check(ls, TK_NAME); + ts = ls->t.seminfo.ts; + luaX_next(ls); + return ts; } -static void leaveblock (FuncState *fs) { - BlockCnt *bl = fs->bl; - LexState *ls = fs->ls; - if(bl->languageextensionsdefined > 0) { - luaX_globalgetfield(ls, TA_TERRA_OBJECT, "unimportlanguages"); - luaX_globalpush(ls, TA_LANGUAGES_TABLE); - lua_pushnumber(ls->L, bl->languageextensionsdefined); - luaX_globalpush(ls, TA_ENTRY_POINT_TABLE); - lua_call(ls->L, 3, 0); - ls->languageextensionsenabled -= bl->languageextensionsdefined; - } - fs->bl = bl->previous; - //printf("leaving block %lld\n", (long long int)bl); - //printf("now is %lld\n", (long long int)fs->bl); - //for(int i = 0; i < bl->local_variables.size(); i++) { - // printf("v[%d] = %s\n",i,getstr(bl->local_variables[i])); - //} +static void singlevar(LexState *ls) { + Position p = getposition(ls); + TString *varname = str_checkname(ls); + push_string(ls, varname); + new_object(ls, "var", 1, &p); + refvariable(ls, varname); } -static void enterterra(LexState * ls, TerraCnt * current) { +// tries to parse a symbol "NAME | '['' lua expression '']'" +// returns true if a name was parsed and sets str to that name +// otherwise, str is not modified +static bool checksymbol(LexState *ls, TString **str) { + Position p = getposition(ls); + int line = ls->linenumber; + if (ls->in_terra && testnext(ls, '[')) { + RETURNS_1(luaexpr(ls)); + new_object(ls, "escapedident", 1, &p); + check_match(ls, ']', '[', line); + return false; + } + TString *nm = str_checkname(ls); + if (str) *str = nm; + push_string(ls, nm); + new_object(ls, "namedident", 1, &p); + return true; +} + +static void enterlevel(LexState *ls) { + terra_State *L = ls->LP; + ++L->nCcalls; + checklimit(ls->fs, L->nCcalls, LUAI_MAXCCALLS, "C levels"); +} + +#define leavelevel(ls) ((ls)->LP->nCcalls--) + +static void enterblock(FuncState *fs, BlockCnt *bl, lu_byte isloop) { + bl->previous = fs->bl; + bl->isterra = fs->ls->in_terra; + bl->languageextensionsdefined = 0; + fs->bl = bl; + // printf("entering block %lld\n", (long long int)bl); + // printf("previous is %lld\n", (long long int)bl->previous); +} + +static void leaveblock(FuncState *fs) { + BlockCnt *bl = fs->bl; + LexState *ls = fs->ls; + if (bl->languageextensionsdefined > 0) { + luaX_globalgetfield(ls, TA_TERRA_OBJECT, "unimportlanguages"); + luaX_globalpush(ls, TA_LANGUAGES_TABLE); + lua_pushnumber(ls->L, bl->languageextensionsdefined); + luaX_globalpush(ls, TA_ENTRY_POINT_TABLE); + lua_call(ls->L, 3, 0); + ls->languageextensionsenabled -= bl->languageextensionsdefined; + } + fs->bl = bl->previous; + // printf("leaving block %lld\n", (long long int)bl); + // printf("now is %lld\n", (long long int)fs->bl); + // for(int i = 0; i < bl->local_variables.size(); i++) { + // printf("v[%d] = %s\n",i,getstr(bl->local_variables[i])); + //} +} + +static void enterterra(LexState *ls, TerraCnt *current) { current->previous = ls->terracnt; ls->terracnt = current; ls->in_terra++; enterblock(ls->fs, ¤t->block, 0); } -static void leaveterra(LexState * ls) { +static void leaveterra(LexState *ls) { assert(ls->in_terra); assert(ls->terracnt); leaveblock(ls->fs); @@ -382,125 +380,124 @@ static void leaveterra(LexState * ls) { ls->in_terra--; } -static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { - fs->prev = ls->fs; /* linked list of funcstates */ - fs->bl = (fs->prev) ? ls->fs->bl : NULL; - fs->ls = ls; - ls->fs = fs; - fs->f.linedefined = 0; - fs->f.is_vararg = 0; - fs->f.source = ls->source; - enterblock(fs, bl, 0); +static void open_func(LexState *ls, FuncState *fs, BlockCnt *bl) { + fs->prev = ls->fs; /* linked list of funcstates */ + fs->bl = (fs->prev) ? ls->fs->bl : NULL; + fs->ls = ls; + ls->fs = fs; + fs->f.linedefined = 0; + fs->f.is_vararg = 0; + fs->f.source = ls->source; + enterblock(fs, bl, 0); } - -static void close_func (LexState *ls) { - FuncState *fs = ls->fs; - leaveblock(fs); - ls->fs = fs->prev; +static void close_func(LexState *ls) { + FuncState *fs = ls->fs; + leaveblock(fs); + ls->fs = fs->prev; } - /* ** opens the main function, which is a regular vararg function with an ** upvalue named LUA_ENV */ -static void open_mainfunc (LexState *ls, FuncState *fs, BlockCnt *bl) { - open_func(ls, fs, bl); - fs->f.is_vararg = 1; /* main function is always vararg */ +static void open_mainfunc(LexState *ls, FuncState *fs, BlockCnt *bl) { + open_func(ls, fs, bl); + fs->f.is_vararg = 1; /* main function is always vararg */ } -static void dump_stack(lua_State * L, int elem) { - lua_pushvalue(L,elem); - lua_getfield(L,LUA_GLOBALSINDEX,"terra"); - lua_getfield(L,-1,"tree"); - lua_getfield(L,-1,"printraw"); - lua_pushvalue(L,-4); +static void dump_stack(lua_State *L, int elem) { + lua_pushvalue(L, elem); + lua_getfield(L, LUA_GLOBALSINDEX, "terra"); + lua_getfield(L, -1, "tree"); + lua_getfield(L, -1, "printraw"); + lua_pushvalue(L, -4); lua_call(L, 1, 0); - - lua_pop(L,3); + + lua_pop(L, 3); } /*============================================================*/ /* GRAMMAR RULES */ /*============================================================*/ - /* ** check whether current token is in the follow set of a block. ** 'until' closes syntactical blocks, but do not close scope, ** so it handled in separate. */ -static int block_follow (LexState *ls, int withuntil) { - switch (ls->t.token) { - case TK_ELSE: case TK_ELSEIF: - case TK_END: case TK_EOS: case TK_IN: - return 1; - case TK_UNTIL: return withuntil; - default: return 0; - } -} - - -static void statlist (LexState *ls) { - /* statlist -> { stat [`;'] } */ - int tbl = new_list(ls); - while (!block_follow(ls, 1)) { - if (ls->t.token == TK_RETURN) { - statement(ls); - add_entry(ls,tbl); - return; /* 'return' must be last statement */ - } - if (ls->t.token == ';') { - luaX_next(ls); - } else { - statement(ls); - add_entry(ls,tbl); +static int block_follow(LexState *ls, int withuntil) { + switch (ls->t.token) { + case TK_ELSE: + case TK_ELSEIF: + case TK_END: + case TK_EOS: + case TK_IN: + return 1; + case TK_UNTIL: + return withuntil; + default: + return 0; + } +} + +static void statlist(LexState *ls) { + /* statlist -> { stat [`;'] } */ + int tbl = new_list(ls); + while (!block_follow(ls, 1)) { + if (ls->t.token == TK_RETURN) { + statement(ls); + add_entry(ls, tbl); + return; /* 'return' must be last statement */ + } + if (ls->t.token == ';') { + luaX_next(ls); + } else { + statement(ls); + add_entry(ls, tbl); + } } - } } -static void push_type(LexState * ls, const char * typ) { - if(ls->in_terra) { +static void push_type(LexState *ls, const char *typ) { + if (ls->in_terra) { luaX_globalgetfield(ls, TA_TERRA_OBJECT, "types"); - lua_getfield(ls->L,-1,typ); - lua_remove(ls->L,-2); //types object + lua_getfield(ls->L, -1, typ); + lua_remove(ls->L, -2); // types object } } -static void push_literal(LexState * ls, const char * typ) { - if(ls->in_terra) { - push_type(ls,typ); +static void push_literal(LexState *ls, const char *typ) { + if (ls->in_terra) { + push_type(ls, typ); Position p = getposition(ls); - new_object(ls,"literal",2,&p); + new_object(ls, "literal", 2, &p); } } -static void push_double(LexState * ls, double d) { - if(ls->in_terra) { - lua_pushnumber(ls->L,d); +static void push_double(LexState *ls, double d) { + if (ls->in_terra) { + lua_pushnumber(ls->L, d); } } -static void push_integer(LexState * ls, int64_t i) { - if(ls->in_terra) { - void * data = lua_newuserdata(ls->L,sizeof(int64_t)); - *(int64_t*)data = i; +static void push_integer(LexState *ls, int64_t i) { + if (ls->in_terra) { + void *data = lua_newuserdata(ls->L, sizeof(int64_t)); + *(int64_t *)data = i; } } -static void push_nil(LexState * ls) { - if(ls->in_terra) - lua_pushnil(ls->L); +static void push_nil(LexState *ls) { + if (ls->in_terra) lua_pushnil(ls->L); } -static void yindex (LexState *ls) { - /* index -> '[' expr ']' */ - luaX_next(ls); /* skip the '[' */ - - RETURNS_1(expr(ls)); - //luaK_exp2val(ls->fs, v); - checknext(ls, ']'); -} +static void yindex(LexState *ls) { + /* index -> '[' expr ']' */ + luaX_next(ls); /* skip the '[' */ + RETURNS_1(expr(ls)); + // luaK_exp2val(ls->fs, v); + checknext(ls, ']'); +} /* ** {====================================================================== @@ -508,149 +505,142 @@ static void yindex (LexState *ls) { ** ======================================================================= */ - struct ConsControl { - int nh; /* total number of `record' elements */ - int na; /* total number of array elements */ + int nh; /* total number of `record' elements */ + int na; /* total number of array elements */ }; +static void recfield(LexState *ls, struct ConsControl *cc) { + /* recfield -> (NAME | `['exp1`]') = exp1 */ + FuncState *fs = ls->fs; + Position pos = getposition(ls); + if (ls->t.token == TK_NAME) { + checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); + RETURNS_1(checksymbol(ls, NULL)); + } else { /* ls->t.token == '[' */ + if (!ls->in_terra) { + yindex(ls); + } else { + RETURNS_1(expr(ls)); + if (ls->t.token == '=') { + lua_getfield(ls->L, -1, "kind"); + lua_pushstring(ls->L, "luaexpression"); + if (!lua_equal(ls->L, -1, -2)) luaX_syntaxerror(ls, "unexpected symbol"); + lua_pop(ls->L, 2); // kind and luaexpression + new_object(ls, "escapedident", 1, &pos); + } else { + /* oops! this wasn't a recfield, but a listfield with an escape */ + new_object(ls, "listfield", 1, &pos); + return; + } + } + } + cc->nh++; + checknext(ls, '='); + RETURNS_1(expr(ls)); + new_object(ls, "recfield", 2, &pos); +} -static void recfield (LexState *ls, struct ConsControl *cc) { - /* recfield -> (NAME | `['exp1`]') = exp1 */ - FuncState *fs = ls->fs; - Position pos = getposition(ls); - if (ls->t.token == TK_NAME) { - checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); - RETURNS_1(checksymbol(ls, NULL)); - } else { /* ls->t.token == '[' */ - if(!ls->in_terra) { - yindex(ls); - } else { - RETURNS_1(expr(ls)); - if(ls->t.token == '=') { - lua_getfield(ls->L,-1, "kind"); - lua_pushstring(ls->L,"luaexpression"); - if(!lua_equal(ls->L,-1,-2)) - luaX_syntaxerror(ls, "unexpected symbol"); - lua_pop(ls->L,2); //kind and luaexpression - new_object(ls,"escapedident",1,&pos); - } else { - /* oops! this wasn't a recfield, but a listfield with an escape */ - new_object(ls,"listfield",1,&pos); - return; - } - } - } - cc->nh++; - checknext(ls, '='); - RETURNS_1(expr(ls)); - new_object(ls,"recfield",2,&pos); -} - -static void listfield (LexState *ls, struct ConsControl *cc) { - /* listfield -> exp */ - Position pos = getposition(ls); - RETURNS_1(expr(ls)); - new_object(ls,"listfield",1,&pos); - checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor"); - cc->na++; -} - - -static void field (LexState *ls, struct ConsControl *cc) { - /* field -> listfield | recfield */ - switch(ls->t.token) { - case TK_NAME: { /* may be 'listfield' or 'recfield' */ - if (luaX_lookahead(ls) != '=') /* expression? */ - listfield(ls, cc); - else - recfield(ls, cc); - break; - } - case '[': { - recfield(ls, cc); - break; - } - default: { - listfield(ls, cc); - break; - } - } -} - - -static void constructor (LexState *ls) { - /* constructor -> '{' [ field { sep field } [sep] ] '}' - sep -> ',' | ';' */ - int line = ls->linenumber; - struct ConsControl cc; - cc.na = cc.nh = 0; - Position pos = getposition(ls); - int records = new_list(ls); - checknext(ls, '{'); - do { - if (ls->t.token == '}') break; - RETURNS_1(field(ls, &cc)); - add_entry(ls,records); - } while (testnext(ls, ',') || testnext(ls, ';')); - check_match(ls, '}', '{', line); - new_object(ls,"constructoru",1,&pos); -} - -static void structfield (LexState *ls) { - Position p = getposition(ls); - push_string(ls,str_checkname(ls)); - checknext(ls, ':'); - RETURNS_1(terratype(ls)); - new_object(ls,"structentry",2,&p); -} - -static void structbody(LexState * ls) { +static void listfield(LexState *ls, struct ConsControl *cc) { + /* listfield -> exp */ + Position pos = getposition(ls); + RETURNS_1(expr(ls)); + new_object(ls, "listfield", 1, &pos); + checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor"); + cc->na++; +} + +static void field(LexState *ls, struct ConsControl *cc) { + /* field -> listfield | recfield */ + switch (ls->t.token) { + case TK_NAME: { /* may be 'listfield' or 'recfield' */ + if (luaX_lookahead(ls) != '=') /* expression? */ + listfield(ls, cc); + else + recfield(ls, cc); + break; + } + case '[': { + recfield(ls, cc); + break; + } + default: { + listfield(ls, cc); + break; + } + } +} + +static void constructor(LexState *ls) { + /* constructor -> '{' [ field { sep field } [sep] ] '}' + sep -> ',' | ';' */ + int line = ls->linenumber; + struct ConsControl cc; + cc.na = cc.nh = 0; + Position pos = getposition(ls); + int records = new_list(ls); + checknext(ls, '{'); + do { + if (ls->t.token == '}') break; + RETURNS_1(field(ls, &cc)); + add_entry(ls, records); + } while (testnext(ls, ',') || testnext(ls, ';')); + check_match(ls, '}', '{', line); + new_object(ls, "constructoru", 1, &pos); +} + +static void structfield(LexState *ls) { + Position p = getposition(ls); + push_string(ls, str_checkname(ls)); + checknext(ls, ':'); + RETURNS_1(terratype(ls)); + new_object(ls, "structentry", 2, &p); +} + +static void structbody(LexState *ls) { Position p = getposition(ls); int records = new_list(ls); - checknext(ls,'{'); - while(ls->t.token != '}') { - if(testnext(ls, TK_UNION)) - RETURNS_1(structbody(ls)); - else - RETURNS_1(structfield(ls)); - add_entry(ls,records); - if(ls->t.token == ',' || ls->t.token == ';') - luaX_next(ls); - } - check_match(ls,'}','{',p.linenumber); - new_object(ls,"structlist",1,&p); -} -static void structconstructor(LexState * ls) { + checknext(ls, '{'); + while (ls->t.token != '}') { + if (testnext(ls, TK_UNION)) + RETURNS_1(structbody(ls)); + else + RETURNS_1(structfield(ls)); + add_entry(ls, records); + if (ls->t.token == ',' || ls->t.token == ';') luaX_next(ls); + } + check_match(ls, '}', '{', p.linenumber); + new_object(ls, "structlist", 1, &p); +} +static void structconstructor(LexState *ls) { // already parsed 'struct' or 'struct' name. - //starting at '{' or '(' + // starting at '{' or '(' Position p = getposition(ls); - if(testnext(ls,'(')) { + if (testnext(ls, '(')) { RETURNS_1(luaexpr(ls)); - check_match(ls,')','(',p.linenumber); - } else push_nil(ls); + check_match(ls, ')', '(', p.linenumber); + } else + push_nil(ls); structbody(ls); - new_object(ls,"structdef",2,&p); + new_object(ls, "structdef", 2, &p); } struct Name { - std::vector data; //for patching the [local] terra a.b.c.d, and [local] var a.b.c.d sugar + std::vector data; // for patching the [local] terra a.b.c.d, and [local] + // var a.b.c.d sugar }; -static void Name_add(Name * name, TString * string) { - name->data.push_back(string); -} +static void Name_add(Name *name, TString *string) { name->data.push_back(string); } -static void Name_print(Name * name, LexState * ls) { +static void Name_print(Name *name, LexState *ls) { size_t N = name->data.size(); - for(size_t i = 0; i < N; i++) { - OutputBuffer_printf(&ls->output_buffer,"%s",getstr(name->data[i])); - if(i + 1 < N) - OutputBuffer_putc(&ls->output_buffer, '.'); + for (size_t i = 0; i < N; i++) { + OutputBuffer_printf(&ls->output_buffer, "%s", getstr(name->data[i])); + if (i + 1 < N) OutputBuffer_putc(&ls->output_buffer, '.'); } } -static void print_captured_locals(LexState * ls, TerraCnt * tc); +static void print_captured_locals(LexState *ls, TerraCnt *tc); /* print_stack not used anywhere right now - comment out to eliminate compiler warning */ @@ -663,159 +653,158 @@ static void print_stack(lua_State * L, int idx) { } #endif -//store the lua object on the top of the stack to to the _G.terra._trees table, returning its index in the table -static int store_value(LexState * ls) { +// store the lua object on the top of the stack to to the _G.terra._trees table, returning +// its index in the table +static int store_value(LexState *ls) { int i = 0; - if(ls->in_terra) { + if (ls->in_terra) { luaX_globalpush(ls, TA_FUNCTION_TABLE); - lua_insert(ls->L,-2); + lua_insert(ls->L, -2); i = add_entry(ls, lua_gettop(ls->L) - 1); - lua_pop(ls->L,1); /*remove function table*/ + lua_pop(ls->L, 1); /*remove function table*/ } return i; } -static void printtreesandnames(LexState * ls, std::vector * trees, std::vector * names) { - OutputBuffer_printf(&ls->output_buffer,"{"); - for(size_t i = 0; i < trees->size(); i++) { - OutputBuffer_printf(&ls->output_buffer,"_G.terra._trees[%d]",(*trees)[i]); - if (i + 1 < trees->size()) - OutputBuffer_putc(&ls->output_buffer,','); - } - OutputBuffer_printf(&ls->output_buffer,"},{"); - for(size_t i = 0; i < names->size(); i++) { - OutputBuffer_printf(&ls->output_buffer,"\"%s\"",getstr((*names)[i])); - if (i + 1 < names->size()) - OutputBuffer_putc(&ls->output_buffer,','); - } - OutputBuffer_printf(&ls->output_buffer,"}"); +static void printtreesandnames(LexState *ls, std::vector *trees, + std::vector *names) { + OutputBuffer_printf(&ls->output_buffer, "{"); + for (size_t i = 0; i < trees->size(); i++) { + OutputBuffer_printf(&ls->output_buffer, "_G.terra._trees[%d]", (*trees)[i]); + if (i + 1 < trees->size()) OutputBuffer_putc(&ls->output_buffer, ','); + } + OutputBuffer_printf(&ls->output_buffer, "},{"); + for (size_t i = 0; i < names->size(); i++) { + OutputBuffer_printf(&ls->output_buffer, "\"%s\"", getstr((*names)[i])); + if (i + 1 < names->size()) OutputBuffer_putc(&ls->output_buffer, ','); + } + OutputBuffer_printf(&ls->output_buffer, "}"); } /* }====================================================================== */ -static int vardecl(LexState *ls, int requiretype, TString ** vname) { +static int vardecl(LexState *ls, int requiretype, TString **vname) { Position p = getposition(ls); int wasstring = checksymbol(ls, vname); if (ls->in_terra && wasstring && (requiretype || ls->t.token == ':')) { checknext(ls, ':'); RETURNS_1(terratype(ls)); - } else push_nil(ls); - new_object(ls,"unevaluatedparam",2,&p); + } else + push_nil(ls); + new_object(ls, "unevaluatedparam", 2, &p); return wasstring; } -static void parlist (LexState *ls) { - /* parlist -> [ param { `,' param } ] */ - FuncState *fs = ls->fs; - Proto *f = &fs->f; - int tbl = new_list(ls); - f->is_vararg = 0; - std::vector vnames; - if (ls->t.token != ')') { /* is `parlist' not empty? */ - do { - switch (ls->t.token) { - case TK_NAME: case '[': { /* param -> NAME */ - TString * vname; - if(vardecl(ls, 1, &vname)) - vnames.push_back(vname); - add_entry(ls,tbl); - break; - } - case TK_DOTS: { /* param -> `...' */ - luaX_next(ls); - f->is_vararg = 1; - break; - } - default: luaX_syntaxerror(ls, " or " LUA_QL("...") " expected"); - } - } while (!f->is_vararg && testnext(ls, ',')); - } - for(size_t i = 0; i < vnames.size(); i++) - definevariable(ls, vnames[i]); -} -static void block (LexState *ls); - -static void body (LexState *ls, int ismethod, int line) { - /* body -> `(' parlist `)' block END */ - FuncState new_fs; - BlockCnt bl; - open_func(ls, &new_fs, &bl); - new_fs.f.linedefined = line; - Position p = getposition(ls); - checknext(ls, '('); - RETURNS_1(parlist(ls)); - if (ismethod) { - definevariable(ls, luaS_new(ls->LP,"self")); - } - push_boolean(ls,new_fs.f.is_vararg); - checknext(ls, ')'); - if(ls->in_terra && testnext(ls,':')) { - RETURNS_1(terratype(ls)); - } else push_nil(ls); - RETURNS_1(block(ls)); - new_fs.f.lastlinedefined = ls->linenumber; - check_match(ls, TK_END, TK_FUNCTION, line); - close_func(ls); - new_object(ls,"functiondefu",4,&p); -} - -static int explist (LexState *ls) { - /* explist -> expr { `,' expr } */ - int n = 1; /* at least one expression */ - int lst = new_list(ls); - expr(ls); - add_entry(ls,lst); - while (testnext(ls, ',')) { - //luaK_exp2nextreg(ls->fs, v); - expr(ls); - add_entry(ls,lst); - n++; - } - return n; +static void parlist(LexState *ls) { + /* parlist -> [ param { `,' param } ] */ + FuncState *fs = ls->fs; + Proto *f = &fs->f; + int tbl = new_list(ls); + f->is_vararg = 0; + std::vector vnames; + if (ls->t.token != ')') { /* is `parlist' not empty? */ + do { + switch (ls->t.token) { + case TK_NAME: + case '[': { /* param -> NAME */ + TString *vname; + if (vardecl(ls, 1, &vname)) vnames.push_back(vname); + add_entry(ls, tbl); + break; + } + case TK_DOTS: { /* param -> `...' */ + luaX_next(ls); + f->is_vararg = 1; + break; + } + default: + luaX_syntaxerror(ls, " or " LUA_QL("...") " expected"); + } + } while (!f->is_vararg && testnext(ls, ',')); + } + for (size_t i = 0; i < vnames.size(); i++) definevariable(ls, vnames[i]); } +static void block(LexState *ls); - -static void funcargs (LexState *ls, int line) { - switch (ls->t.token) { - case '(': { /* funcargs -> `(' [ explist ] `)' */ - luaX_next(ls); - if (ls->t.token == ')') { /* arg list is empty? */ - new_list(ls); //empty return list - } else { - RETURNS_1(explist(ls)); - } - check_match(ls, ')', '(', line); - break; - } - case '{': { /* funcargs -> constructor */ - int exps = new_list(ls); - RETURNS_1(constructor(ls)); - add_entry(ls,exps); - break; - } - case TK_STRING: { /* funcargs -> STRING */ - //codestring(ls, &args, ls->t.seminfo.ts); - int exps = new_list(ls); - push_string(ls,ls->t.seminfo.ts); - push_literal(ls,"rawstring"); - add_entry(ls,exps); - luaX_next(ls); /* must use `seminfo' before `next' */ - break; - } - case '`': case TK_QUOTE: { - int exps = new_list(ls); - doquote(ls,ls->t.token == '`'); - add_entry(ls, exps); - break; - } - default: { - luaX_syntaxerror(ls, "function arguments expected"); +static void body(LexState *ls, int ismethod, int line) { + /* body -> `(' parlist `)' block END */ + FuncState new_fs; + BlockCnt bl; + open_func(ls, &new_fs, &bl); + new_fs.f.linedefined = line; + Position p = getposition(ls); + checknext(ls, '('); + RETURNS_1(parlist(ls)); + if (ismethod) { + definevariable(ls, luaS_new(ls->LP, "self")); + } + push_boolean(ls, new_fs.f.is_vararg); + checknext(ls, ')'); + if (ls->in_terra && testnext(ls, ':')) { + RETURNS_1(terratype(ls)); + } else + push_nil(ls); + RETURNS_1(block(ls)); + new_fs.f.lastlinedefined = ls->linenumber; + check_match(ls, TK_END, TK_FUNCTION, line); + close_func(ls); + new_object(ls, "functiondefu", 4, &p); +} + +static int explist(LexState *ls) { + /* explist -> expr { `,' expr } */ + int n = 1; /* at least one expression */ + int lst = new_list(ls); + expr(ls); + add_entry(ls, lst); + while (testnext(ls, ',')) { + // luaK_exp2nextreg(ls->fs, v); + expr(ls); + add_entry(ls, lst); + n++; } - } + return n; } - - +static void funcargs(LexState *ls, int line) { + switch (ls->t.token) { + case '(': { /* funcargs -> `(' [ explist ] `)' */ + luaX_next(ls); + if (ls->t.token == ')') { /* arg list is empty? */ + new_list(ls); // empty return list + } else { + RETURNS_1(explist(ls)); + } + check_match(ls, ')', '(', line); + break; + } + case '{': { /* funcargs -> constructor */ + int exps = new_list(ls); + RETURNS_1(constructor(ls)); + add_entry(ls, exps); + break; + } + case TK_STRING: { /* funcargs -> STRING */ + // codestring(ls, &args, ls->t.seminfo.ts); + int exps = new_list(ls); + push_string(ls, ls->t.seminfo.ts); + push_literal(ls, "rawstring"); + add_entry(ls, exps); + luaX_next(ls); /* must use `seminfo' before `next' */ + break; + } + case '`': + case TK_QUOTE: { + int exps = new_list(ls); + doquote(ls, ls->t.token == '`'); + add_entry(ls, exps); + break; + } + default: { + luaX_syntaxerror(ls, "function arguments expected"); + } + } +} /* ** {====================================================================== @@ -823,37 +812,37 @@ static void funcargs (LexState *ls, int line) { ** ======================================================================= */ -static void prefixexp (LexState *ls) { - /* prefixexp -> NAME | '(' expr ')' */ - - switch (ls->t.token) { - case '(': { - int line = ls->linenumber; - luaX_next(ls); - RETURNS_1(expr(ls)); - check_match(ls, ')', '(', line); - return; - } - case '[': { - check_terra(ls, "escape"); - int line = ls->linenumber; - luaX_next(ls); - RETURNS_1(luaexpr(ls)); - check_match(ls, ']', '[', line); - return; - } - case TK_NAME: { - RETURNS_1(singlevar(ls)); - return; - } - default: { - luaX_syntaxerror(ls, "unexpected symbol"); - } - } -} - -static int issplitprimary(LexState * ls) { - if(ls->lastline != ls->linenumber) { +static void prefixexp(LexState *ls) { + /* prefixexp -> NAME | '(' expr ')' */ + + switch (ls->t.token) { + case '(': { + int line = ls->linenumber; + luaX_next(ls); + RETURNS_1(expr(ls)); + check_match(ls, ')', '(', line); + return; + } + case '[': { + check_terra(ls, "escape"); + int line = ls->linenumber; + luaX_next(ls); + RETURNS_1(luaexpr(ls)); + check_match(ls, ']', '[', line); + return; + } + case TK_NAME: { + RETURNS_1(singlevar(ls)); + return; + } + default: { + luaX_syntaxerror(ls, "unexpected symbol"); + } + } +} + +static int issplitprimary(LexState *ls) { + if (ls->lastline != ls->linenumber) { luaX_insertbeforecurrenttoken(ls, ';'); return 1; } else { @@ -861,131 +850,135 @@ static int issplitprimary(LexState * ls) { } } -static void primaryexp (LexState *ls) { - /* primaryexp -> - prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */ - int line = ls->linenumber; - RETURNS_1(prefixexp(ls)); - Position p = getposition(ls); - for (;;) { - switch (ls->t.token) { - case '.': { /* fieldsel */ - luaX_next(ls); - checksymbol(ls,NULL); - new_object(ls,"selectu",2,&p); - break; - } - case '[': { /* `[' exp1 `]' */ - if(issplitprimary(ls)) - return; - RETURNS_1(yindex(ls)); - new_object(ls,"index",2,&p); - break; - } - case ':': { /* `:' NAME funcargs */ - luaX_next(ls); - RETURNS_1(checksymbol(ls,NULL)); - RETURNS_1(funcargs(ls, line)); - new_object(ls,"method",3,&p); - break; - } - case '(': case '`': case TK_QUOTE: /* funcargs */ - if(issplitprimary(ls)) - return; - /* fallthrough */ - case TK_STRING: case '{': { - RETURNS_1(funcargs(ls, line)); - new_object(ls,"apply",2,&p); - break; - } - default: return; +static void primaryexp(LexState *ls) { + /* primaryexp -> + prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */ + int line = ls->linenumber; + RETURNS_1(prefixexp(ls)); + Position p = getposition(ls); + for (;;) { + switch (ls->t.token) { + case '.': { /* fieldsel */ + luaX_next(ls); + checksymbol(ls, NULL); + new_object(ls, "selectu", 2, &p); + break; + } + case '[': { /* `[' exp1 `]' */ + if (issplitprimary(ls)) return; + RETURNS_1(yindex(ls)); + new_object(ls, "index", 2, &p); + break; + } + case ':': { /* `:' NAME funcargs */ + luaX_next(ls); + RETURNS_1(checksymbol(ls, NULL)); + RETURNS_1(funcargs(ls, line)); + new_object(ls, "method", 3, &p); + break; + } + case '(': + case '`': + case TK_QUOTE: /* funcargs */ + if (issplitprimary(ls)) return; + /* fallthrough */ + case TK_STRING: + case '{': { + RETURNS_1(funcargs(ls, line)); + new_object(ls, "apply", 2, &p); + break; + } + default: + return; + } } - } } -//TODO: eventually we should record the set of possibly used symbols, and only quote the ones appearing in it -static void print_captured_locals(LexState * ls, TerraCnt * tc) { - OutputBuffer_printf(&ls->output_buffer,"function() return terra.makeenv({ "); +// TODO: eventually we should record the set of possibly used symbols, and only quote the +// ones appearing in it +static void print_captured_locals(LexState *ls, TerraCnt *tc) { + OutputBuffer_printf(&ls->output_buffer, "function() return terra.makeenv({ "); int in_terra = ls->in_terra; - ls->in_terra = 1; //force new_table, etc to do something, not the cleanest way to express this... + ls->in_terra = 1; // force new_table, etc to do something, not the cleanest way to + // express this... int tbl = new_table(ls); - for(StringSet::iterator i = tc->capturedlocals.begin(), end = tc->capturedlocals.end(); - i != end; - ++i) { - TString * iv = *i; - const char * str = getstr(iv); - lua_pushboolean(ls->L,true); - add_field(ls,tbl,str); - OutputBuffer_printf(&ls->output_buffer,"%s = %s;",str,str); + for (StringSet::iterator i = tc->capturedlocals.begin(), + end = tc->capturedlocals.end(); + i != end; ++i) { + TString *iv = *i; + const char *str = getstr(iv); + lua_pushboolean(ls->L, true); + add_field(ls, tbl, str); + OutputBuffer_printf(&ls->output_buffer, "%s = %s;", str, str); } int defined = store_value(ls); ls->in_terra = in_terra; - OutputBuffer_printf(&ls->output_buffer," },_G.terra._trees[%d],getfenv()) end",defined); + OutputBuffer_printf(&ls->output_buffer, " },_G.terra._trees[%d],getfenv()) end", + defined); } -static void doquote(LexState * ls, int isexp) { +static void doquote(LexState *ls, int isexp) { int isfullquote = ls->t.token == '`' || ls->t.token == TK_QUOTE; - + check_no_terra(ls, isexp ? "`" : "quote"); - + TerraCnt tc; enterterra(ls, &tc); Token begin = ls->t; int line = ls->linenumber; - if(isfullquote) - luaX_next(ls); //skip ` or quote - if(isexp) { + if (isfullquote) luaX_next(ls); // skip ` or quote + if (isexp) { RETURNS_1(expr(ls)); } else { - FuncState * fs = ls->fs; + FuncState *fs = ls->fs; BlockCnt bc; enterblock(fs, &bc, 0); Position p = getposition(ls); RETURNS_1(statlist(ls)); - if(isfullquote && testnext(ls, TK_IN)) { + if (isfullquote && testnext(ls, TK_IN)) { RETURNS_1(explist(ls)); } else { new_list(ls); } push_boolean(ls, true); - if(isfullquote) - check_match(ls, TK_END, TK_QUOTE, line); + if (isfullquote) check_match(ls, TK_END, TK_QUOTE, line); leaveblock(fs); - new_object(ls,"letin",3,&p); + new_object(ls, "letin", 3, &p); } - - luaX_patchbegin(ls,&begin); + + luaX_patchbegin(ls, &begin); int id = store_value(ls); - OutputBuffer_printf(&ls->output_buffer,"(terra.definequote(_G.terra._trees[%d],",id); - print_captured_locals(ls,&tc); - OutputBuffer_printf(&ls->output_buffer,"))"); - luaX_patchend(ls,&begin); + OutputBuffer_printf(&ls->output_buffer, "(terra.definequote(_G.terra._trees[%d],", + id); + print_captured_locals(ls, &tc); + OutputBuffer_printf(&ls->output_buffer, "))"); + luaX_patchend(ls, &begin); leaveterra(ls); } -//buf should be at least 128 chars -static void number_type(LexState * ls, int flags, char * buf) { - if(ls->in_terra) { - if(flags & F_ISINTEGER) { - const char * sign = (flags & F_ISUNSIGNED) ? "u" : ""; - const char * sz = (flags & F_IS8BYTES) ? "64" : ""; - sprintf(buf,"%sint%s",sign,sz); - } else { - sprintf(buf,"%s",(flags & F_IS8BYTES) ? "double" : "float"); - } +// buf should be at least 128 chars +static void number_type(LexState *ls, int flags, char *buf) { + if (ls->in_terra) { + if (flags & F_ISINTEGER) { + const char *sign = (flags & F_ISUNSIGNED) ? "u" : ""; + const char *sz = (flags & F_IS8BYTES) ? "64" : ""; + sprintf(buf, "%sint%s", sign, sz); + } else { + sprintf(buf, "%s", (flags & F_IS8BYTES) ? "double" : "float"); + } } } -static void blockescape(LexState * ls) { +static void blockescape(LexState *ls) { check_terra(ls, "escape"); int line = ls->linenumber; luaX_next(ls); - embeddedcode(ls,0,0); + embeddedcode(ls, 0, 0); check_match(ls, TK_END, TK_ESCAPE, line); } -static void bodyortype(LexState * ls, int ismethod) { - if(ls->t.token == '(') { +static void bodyortype(LexState *ls, int ismethod) { + if (ls->t.token == '(') { body(ls, ismethod, ls->linenumber); } else { checknext(ls, TK_DBCOLON); @@ -993,184 +986,235 @@ static void bodyortype(LexState * ls, int ismethod) { } } -static void simpleexp (LexState *ls) { - /* simpleexp -> NUMBER | STRING | NIL | TRUE | FALSE | ... | - constructor | FUNCTION body | primaryexp */ - switch (ls->t.token) { - case TK_NUMBER: { - char buf[128]; - int flags = ls->t.seminfo.flags; - number_type(ls, flags, &buf[0]); - if(flags & F_ISINTEGER) { - push_integer(ls,ls->t.seminfo.i); - push_literal(ls,buf); - sprintf(buf,"%" PRIu64,ls->t.seminfo.i); - push_string(ls,buf); - add_field(ls,-2,"stringvalue"); - - } else { - push_double(ls,ls->t.seminfo.r); - push_literal(ls, buf); - } - break; - } - case TK_STRING: { - push_string(ls,ls->t.seminfo.ts); - push_literal(ls,"rawstring"); - break; - } - case TK_NIL: { - if(ls->in_terra) - lua_pushnil(ls->L); - push_literal(ls,"niltype"); - break; - } - case TK_TRUE: { - //init_exp(v, VTRUE, 0); - push_boolean(ls,true); - push_literal(ls,"bool"); - break; - } - case TK_FALSE: { - push_boolean(ls,false); - push_literal(ls,"bool"); - break; - } - case TK_DOTS: { /* vararg */ - FuncState *fs = ls->fs; - check_condition(ls, fs->f.is_vararg, - "cannot use " LUA_QL("...") " outside a vararg function"); - break; - } - case '{': { /* constructor */ - constructor(ls); - return; - } - case '`': case TK_QUOTE: { /* quote expression */ - doquote(ls,ls->t.token == '`'); - return; - } - case TK_ESCAPE: { - blockescape(ls); - return; - } - case TK_FUNCTION: { - luaX_next(ls); - body(ls, 0, ls->linenumber); - return; - } - case TK_TERRA: { - check_no_terra(ls,"nested terra functions"); - - TerraCnt tc; - enterterra(ls, &tc); - Token begin = ls->t; - luaX_next(ls); - bodyortype(ls,0); - luaX_patchbegin(ls,&begin); - int id = store_value(ls); - OutputBuffer_printf(&ls->output_buffer,"terra.anonfunction(_G.terra._trees[%d],",id); - print_captured_locals(ls,&tc); - OutputBuffer_printf(&ls->output_buffer,")"); - luaX_patchend(ls,&begin); - leaveterra(ls); - return; - } - case TK_SPECIAL: { - languageextension(ls, 0, 0); - return; - } - case TK_STRUCT: { - check_no_terra(ls,"struct declarations"); - Token begin = ls->t; - - luaX_next(ls); //skip over struct, struct constructor expects it to be parsed already - - - TerraCnt tc; - enterterra(ls, &tc); - - structconstructor(ls); - int id = store_value(ls); - - luaX_patchbegin(ls,&begin); - OutputBuffer_printf(&ls->output_buffer,"terra.anonstruct(_G.terra._trees[%d],",id); - print_captured_locals(ls,&tc); - OutputBuffer_printf(&ls->output_buffer,")"); - luaX_patchend(ls,&begin); - - leaveterra(ls); - return; - } break; - default: { - primaryexp(ls); - return; - } - } - luaX_next(ls); +static void simpleexp(LexState *ls) { + /* simpleexp -> NUMBER | STRING | NIL | TRUE | FALSE | ... | + constructor | FUNCTION body | primaryexp */ + switch (ls->t.token) { + case TK_NUMBER: { + char buf[128]; + int flags = ls->t.seminfo.flags; + number_type(ls, flags, &buf[0]); + if (flags & F_ISINTEGER) { + push_integer(ls, ls->t.seminfo.i); + push_literal(ls, buf); + sprintf(buf, "%" PRIu64, ls->t.seminfo.i); + push_string(ls, buf); + add_field(ls, -2, "stringvalue"); + + } else { + push_double(ls, ls->t.seminfo.r); + push_literal(ls, buf); + } + break; + } + case TK_STRING: { + push_string(ls, ls->t.seminfo.ts); + push_literal(ls, "rawstring"); + break; + } + case TK_NIL: { + if (ls->in_terra) lua_pushnil(ls->L); + push_literal(ls, "niltype"); + break; + } + case TK_TRUE: { + // init_exp(v, VTRUE, 0); + push_boolean(ls, true); + push_literal(ls, "bool"); + break; + } + case TK_FALSE: { + push_boolean(ls, false); + push_literal(ls, "bool"); + break; + } + case TK_DOTS: { /* vararg */ + FuncState *fs = ls->fs; + check_condition(ls, fs->f.is_vararg, + "cannot use " LUA_QL("...") " outside a vararg function"); + break; + } + case '{': { /* constructor */ + constructor(ls); + return; + } + case '`': + case TK_QUOTE: { /* quote expression */ + doquote(ls, ls->t.token == '`'); + return; + } + case TK_ESCAPE: { + blockescape(ls); + return; + } + case TK_FUNCTION: { + luaX_next(ls); + body(ls, 0, ls->linenumber); + return; + } + case TK_TERRA: { + check_no_terra(ls, "nested terra functions"); + + TerraCnt tc; + enterterra(ls, &tc); + Token begin = ls->t; + luaX_next(ls); + bodyortype(ls, 0); + luaX_patchbegin(ls, &begin); + int id = store_value(ls); + OutputBuffer_printf(&ls->output_buffer, + "terra.anonfunction(_G.terra._trees[%d],", id); + print_captured_locals(ls, &tc); + OutputBuffer_printf(&ls->output_buffer, ")"); + luaX_patchend(ls, &begin); + leaveterra(ls); + return; + } + case TK_SPECIAL: { + languageextension(ls, 0, 0); + return; + } + case TK_STRUCT: { + check_no_terra(ls, "struct declarations"); + Token begin = ls->t; + + luaX_next(ls); // skip over struct, struct constructor expects it to be + // parsed already + + TerraCnt tc; + enterterra(ls, &tc); + + structconstructor(ls); + int id = store_value(ls); + + luaX_patchbegin(ls, &begin); + OutputBuffer_printf(&ls->output_buffer, + "terra.anonstruct(_G.terra._trees[%d],", id); + print_captured_locals(ls, &tc); + OutputBuffer_printf(&ls->output_buffer, ")"); + luaX_patchend(ls, &begin); + + leaveterra(ls); + return; + } break; + default: { + primaryexp(ls); + return; + } + } + luaX_next(ls); } /* ** grep "ORDER OPR" if you change these enums (ORDER OP) */ typedef enum BinOpr { - OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, - OPR_POW, OPR_CONCAT, - OPR_LSHIFT, OPR_RSHIFT, - OPR_EQ, OPR_LT, OPR_LE, - OPR_NE, OPR_GT, OPR_GE, - OPR_AND, OPR_OR, - OPR_FUNC_PTR, - OPR_NOBINOPR + OPR_ADD, + OPR_SUB, + OPR_MUL, + OPR_DIV, + OPR_MOD, + OPR_POW, + OPR_CONCAT, + OPR_LSHIFT, + OPR_RSHIFT, + OPR_EQ, + OPR_LT, + OPR_LE, + OPR_NE, + OPR_GT, + OPR_GE, + OPR_AND, + OPR_OR, + OPR_FUNC_PTR, + OPR_NOBINOPR } BinOpr; - -typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_DEREF, OPR_ADDR, OPR_NOUNOPR } UnOpr; - -static UnOpr getunopr (int op) { - switch (op) { - case TK_NOT: return OPR_NOT; - case '-': return OPR_MINUS; - case '#': return OPR_LEN; - case '&': return OPR_ADDR; - case '@': return OPR_DEREF; - default: return OPR_NOUNOPR; - } -} - - -static BinOpr getbinopr (int op) { - switch (op) { - case '+': return OPR_ADD; - case '-': return OPR_SUB; - case '*': return OPR_MUL; - case '/': return OPR_DIV; - case '%': return OPR_MOD; - case '^': return OPR_POW; - case TK_CONCAT: return OPR_CONCAT; - case TK_NE: return OPR_NE; - case TK_EQ: return OPR_EQ; - case '<': return OPR_LT; - case TK_LE: return OPR_LE; - case '>': return OPR_GT; - case TK_GE: return OPR_GE; - case TK_AND: return OPR_AND; - case TK_OR: return OPR_OR; - case TK_FUNC_PTR: return OPR_FUNC_PTR; - case TK_LSHIFT: return OPR_LSHIFT; - case TK_RSHIFT: return OPR_RSHIFT; - default: return OPR_NOBINOPR; - } -} -static void check_lua_operator(LexState * ls, int op) { - switch(op) { - case '@': case TK_LSHIFT: case TK_RSHIFT: - if(!ls->in_terra) - luaX_syntaxerror(ls,luaS_cstringf(ls->LP,"@, <<, and >> operators not supported in Lua code.")); +typedef enum UnOpr { + OPR_MINUS, + OPR_NOT, + OPR_LEN, + OPR_DEREF, + OPR_ADDR, + OPR_NOUNOPR +} UnOpr; + +static UnOpr getunopr(int op) { + switch (op) { + case TK_NOT: + return OPR_NOT; + case '-': + return OPR_MINUS; + case '#': + return OPR_LEN; + case '&': + return OPR_ADDR; + case '@': + return OPR_DEREF; + default: + return OPR_NOUNOPR; + } +} + +static BinOpr getbinopr(int op) { + switch (op) { + case '+': + return OPR_ADD; + case '-': + return OPR_SUB; + case '*': + return OPR_MUL; + case '/': + return OPR_DIV; + case '%': + return OPR_MOD; + case '^': + return OPR_POW; + case TK_CONCAT: + return OPR_CONCAT; + case TK_NE: + return OPR_NE; + case TK_EQ: + return OPR_EQ; + case '<': + return OPR_LT; + case TK_LE: + return OPR_LE; + case '>': + return OPR_GT; + case TK_GE: + return OPR_GE; + case TK_AND: + return OPR_AND; + case TK_OR: + return OPR_OR; + case TK_FUNC_PTR: + return OPR_FUNC_PTR; + case TK_LSHIFT: + return OPR_LSHIFT; + case TK_RSHIFT: + return OPR_RSHIFT; + default: + return OPR_NOBINOPR; + } +} +static void check_lua_operator(LexState *ls, int op) { + switch (op) { + case '@': + case TK_LSHIFT: + case TK_RSHIFT: + if (!ls->in_terra) + luaX_syntaxerror( + ls, + luaS_cstringf( + ls->LP, + "@, <<, and >> operators not supported in Lua code.")); break; case '#': - if(ls->in_terra) - luaX_syntaxerror(ls,luaS_cstringf(ls->LP,"# operator not supported in Terra code.")); + if (ls->in_terra) + luaX_syntaxerror( + ls, + luaS_cstringf(ls->LP, "# operator not supported in Terra code.")); break; default: break; @@ -1178,112 +1222,108 @@ static void check_lua_operator(LexState * ls, int op) { } static const struct { - lu_byte left; /* left priority for each binary operator */ - lu_byte right; /* right priority */ -} priority[] = { /* ORDER OPR */ - {7, 7}, {7, 7}, {8, 8}, {8, 8}, {8, 8}, /* `+' `-' `*' `/' `%' */ - {11, 10}, {6, 5}, /* ^, .. (right associative) */ - {4, 4}, {4, 4}, /* << >> */ - {3, 3}, {3, 3}, {3, 3}, /* ==, <, <= */ - {3, 3}, {3, 3}, {3, 3}, /* ~=, >, >= */ - {2, 2}, {1, 1}, /* and, or */ - {3,2} /* function pointer*/ + lu_byte left; /* left priority for each binary operator */ + lu_byte right; /* right priority */ +} priority[] = { + /* ORDER OPR */ + {7, 7}, {7, 7}, {8, 8}, {8, 8}, {8, 8}, /* `+' `-' `*' `/' `%' */ + {11, 10}, {6, 5}, /* ^, .. (right associative) */ + {4, 4}, {4, 4}, /* << >> */ + {3, 3}, {3, 3}, {3, 3}, /* ==, <, <= */ + {3, 3}, {3, 3}, {3, 3}, /* ~=, >, >= */ + {2, 2}, {1, 1}, /* and, or */ + {3, 2} /* function pointer*/ }; -#define UNARY_PRIORITY 9 /* priority for unary operators */ - +#define UNARY_PRIORITY 9 /* priority for unary operators */ /* ** subexpr -> (simpleexp | unop subexpr) { binop subexpr } ** where `binop' is any binary operator with a priority higher than `limit' */ -static BinOpr subexpr (LexState *ls, int limit) { - BinOpr op; - UnOpr uop; - enterlevel(ls); - uop = getunopr(ls->t.token); - check_lua_operator(ls,ls->t.token); - Token begintoken = ls->t; - - if (uop != OPR_NOUNOPR) { - Position p = getposition(ls); - push_string(ls,luaX_token2rawstr(ls,ls->t.token)); - luaX_next(ls); - Token beginexp = ls->t; - int exps = new_list(ls); - RETURNS_1(subexpr(ls, UNARY_PRIORITY)); - add_entry(ls,exps); - - if(uop == OPR_ADDR) { //desugar &a to terra.types.pointer(a) - const char * expstring = luaX_saveoutput(ls, &beginexp); - luaX_patchbegin(ls, &begintoken); - OutputBuffer_printf(&ls->output_buffer,"terra.types.pointer(%s)", expstring); - luaX_patchend(ls, &begintoken); - } - new_object(ls, "operator", 2, &p); - } - else RETURNS_1(simpleexp(ls)); - /* expand while operators have priorities higher than `limit' */ - - op = getbinopr(ls->t.token); - const char * lhs_string = NULL; - if(op == OPR_FUNC_PTR) { - lhs_string = luaX_saveoutput(ls,&begintoken); - //leading whitespace will be included before the token, so skip it here - while(isspace(*lhs_string)) - lhs_string++; - } - while (op != OPR_NOBINOPR && priority[op].left > limit) { - check_lua_operator(ls,ls->t.token); - BinOpr nextop; - int exps = new_list_before(ls); - add_entry(ls,exps); //add prefix to operator list - Position pos = getposition(ls); - - const char * token = luaX_token2rawstr(ls,ls->t.token); - luaX_next(ls); - Token beginrhs = ls->t; - /* read sub-expression with higher priority */ - RETURNS_1(nextop = subexpr(ls, priority[op].right)); - - if(lhs_string) { //desugar a -> b to terra.types.functype(a,b) - const char * rhs_string = luaX_saveoutput(ls,&beginrhs); - luaX_patchbegin(ls, &begintoken); - OutputBuffer_printf(&ls->output_buffer,"terra.types.funcpointer(%s,%s)",lhs_string,rhs_string); - luaX_patchend(ls,&begintoken); - lhs_string = NULL; - } - add_entry(ls,exps); - - push_string_before(ls,token); - - new_object(ls,"operator",2,&pos); - - op = nextop; - } - leavelevel(ls); - return op; /* return first untreated operator */ -} +static BinOpr subexpr(LexState *ls, int limit) { + BinOpr op; + UnOpr uop; + enterlevel(ls); + uop = getunopr(ls->t.token); + check_lua_operator(ls, ls->t.token); + Token begintoken = ls->t; + if (uop != OPR_NOUNOPR) { + Position p = getposition(ls); + push_string(ls, luaX_token2rawstr(ls, ls->t.token)); + luaX_next(ls); + Token beginexp = ls->t; + int exps = new_list(ls); + RETURNS_1(subexpr(ls, UNARY_PRIORITY)); + add_entry(ls, exps); -static void expr (LexState *ls) { - RETURNS_1(subexpr(ls, 0)); + if (uop == OPR_ADDR) { // desugar &a to terra.types.pointer(a) + const char *expstring = luaX_saveoutput(ls, &beginexp); + luaX_patchbegin(ls, &begintoken); + OutputBuffer_printf(&ls->output_buffer, "terra.types.pointer(%s)", expstring); + luaX_patchend(ls, &begintoken); + } + new_object(ls, "operator", 2, &p); + } else + RETURNS_1(simpleexp(ls)); + /* expand while operators have priorities higher than `limit' */ + + op = getbinopr(ls->t.token); + const char *lhs_string = NULL; + if (op == OPR_FUNC_PTR) { + lhs_string = luaX_saveoutput(ls, &begintoken); + // leading whitespace will be included before the token, so skip it here + while (isspace(*lhs_string)) lhs_string++; + } + while (op != OPR_NOBINOPR && priority[op].left > limit) { + check_lua_operator(ls, ls->t.token); + BinOpr nextop; + int exps = new_list_before(ls); + add_entry(ls, exps); // add prefix to operator list + Position pos = getposition(ls); + + const char *token = luaX_token2rawstr(ls, ls->t.token); + luaX_next(ls); + Token beginrhs = ls->t; + /* read sub-expression with higher priority */ + RETURNS_1(nextop = subexpr(ls, priority[op].right)); + + if (lhs_string) { // desugar a -> b to terra.types.functype(a,b) + const char *rhs_string = luaX_saveoutput(ls, &beginrhs); + luaX_patchbegin(ls, &begintoken); + OutputBuffer_printf(&ls->output_buffer, "terra.types.funcpointer(%s,%s)", + lhs_string, rhs_string); + luaX_patchend(ls, &begintoken); + lhs_string = NULL; + } + add_entry(ls, exps); + + push_string_before(ls, token); + + new_object(ls, "operator", 2, &pos); + + op = nextop; + } + leavelevel(ls); + return op; /* return first untreated operator */ } +static void expr(LexState *ls) { RETURNS_1(subexpr(ls, 0)); } struct ExprReaderData { int step; - const char * data; + const char *data; int N; }; -const char * expr_reader(lua_State * L, void * data, size_t * size) { - ExprReaderData * d = (ExprReaderData *) data; - if(d->step == 0) { - const char * ret = "return "; +const char *expr_reader(lua_State *L, void *data, size_t *size) { + ExprReaderData *d = (ExprReaderData *)data; + if (d->step == 0) { + const char *ret = "return "; *size = strlen(ret); d->step++; return ret; - } else if(d->step == 1) { + } else if (d->step == 1) { d->step++; *size = d->N; return d->data; @@ -1293,64 +1333,62 @@ const char * expr_reader(lua_State * L, void * data, size_t * size) { } } - -static void embeddedcode(LexState * ls, int isterra, int isexp) { +static void embeddedcode(LexState *ls, int isterra, int isexp) { assert(ls->in_terra); - - //terra types are lua expressions. - //to resolve them we stop processing terra code and start processing lua code - //we capture the string of lua code and then evaluate it later to get the actual type + + // terra types are lua expressions. + // to resolve them we stop processing terra code and start processing lua code + // we capture the string of lua code and then evaluate it later to get the actual type Position pos = getposition(ls); Token begintoken = ls->t; int in_terra = ls->in_terra; - + ls->in_terra = 0; - FuncState * fs = ls->fs; + FuncState *fs = ls->fs; BlockCnt bl; enterblock(ls->fs, &bl, 0); - - if(isterra) { - doquote(ls,isexp); - } else if(isexp) + + if (isterra) { + doquote(ls, isexp); + } else if (isexp) expr(ls); else statlist(ls); leaveblock(fs); ls->in_terra = in_terra; - + ExprReaderData data; - data.step = (isexp || isterra) ? 0 : 1; //is the string we captured an expression? it is if we captured a quote (terra.definequote(...)) or a lua expression + data.step = + (isexp || isterra) + ? 0 + : 1; // is the string we captured an expression? it is if we captured + // a quote (terra.definequote(...)) or a lua expression luaX_getoutput(ls, &begintoken, &data.data, &data.N); std::stringstream ss; ss << "@$terra$" << getstr(ls->source) << "$terra$" << begintoken.seminfo.linebegin; - if(lua_load(ls->L, expr_reader, &data, ss.str().c_str()) != 0) { - //we already parsed this buffer, so this should rarely cause an error - //we need to find the line number in the error string, add it to where we began this line, - //and then report the error with the correct line number - const char * error = luaL_checkstring(ls->L, -1); - while(*error != ':') - error++; - char * aftererror; - int lineoffset = strtol(error+1,&aftererror,10); - - luaX_reporterror(ls, luaS_cstringf(ls->LP,"%s:%d: %s\n",getstr(ls->source),begintoken.seminfo.linebegin + lineoffset - 1,aftererror+1)); - } - - push_boolean(ls, isexp); - new_object(ls,"luaexpression",2,&pos); -} + if (lua_load(ls->L, expr_reader, &data, ss.str().c_str()) != 0) { + // we already parsed this buffer, so this should rarely cause an error + // we need to find the line number in the error string, add it to where we began + // this line, and then report the error with the correct line number + const char *error = luaL_checkstring(ls->L, -1); + while (*error != ':') error++; + char *aftererror; + int lineoffset = strtol(error + 1, &aftererror, 10); -static void luaexpr(LexState * ls) { - embeddedcode(ls,0, 1); -} + luaX_reporterror(ls, luaS_cstringf(ls->LP, "%s:%d: %s\n", getstr(ls->source), + begintoken.seminfo.linebegin + lineoffset - 1, + aftererror + 1)); + } -static void terratype(LexState * ls) { - luaexpr(ls); + push_boolean(ls, isexp); + new_object(ls, "luaexpression", 2, &pos); } -/* }==================================================================== */ +static void luaexpr(LexState *ls) { embeddedcode(ls, 0, 1); } +static void terratype(LexState *ls) { luaexpr(ls); } +/* }==================================================================== */ /* ** {====================================================================== @@ -1358,347 +1396,343 @@ static void terratype(LexState * ls) { ** ======================================================================= */ +static void block(LexState *ls) { + /* block -> statlist */ + FuncState *fs = ls->fs; + BlockCnt bl; + Position p = getposition(ls); + + enterblock(fs, &bl, 0); + RETURNS_1(statlist(ls)); + leaveblock(fs); -static void block (LexState *ls) { - /* block -> statlist */ - FuncState *fs = ls->fs; - BlockCnt bl; - Position p = getposition(ls); - - enterblock(fs, &bl, 0); - RETURNS_1(statlist(ls)); - leaveblock(fs); - - new_object(ls,"block",1,&p); + new_object(ls, "block", 1, &p); } -static void lhsexp(LexState * ls) { - if(ls->t.token == '@') { +static void lhsexp(LexState *ls) { + if (ls->t.token == '@') { expr(ls); } else { primaryexp(ls); } } -static void assignment (LexState *ls, int nvars, int lhs) { - if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */ - RETURNS_1(lhsexp(ls)); - add_entry(ls,lhs); - checklimit(ls->fs, nvars + ls->LP->nCcalls, LUAI_MAXCCALLS, "C levels"); - RETURNS_0(assignment(ls, nvars+1,lhs)); - } else { /* assignment -> `=' explist */ - checknext(ls, '='); +static void assignment(LexState *ls, int nvars, int lhs) { + if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */ + RETURNS_1(lhsexp(ls)); + add_entry(ls, lhs); + checklimit(ls->fs, nvars + ls->LP->nCcalls, LUAI_MAXCCALLS, "C levels"); + RETURNS_0(assignment(ls, nvars + 1, lhs)); + } else { /* assignment -> `=' explist */ + checknext(ls, '='); + Position pos = getposition(ls); + RETURNS_1(explist(ls)); + new_object(ls, "assignment", 2, &pos); + } +} + +static void cond(LexState *ls) { + /* cond -> exp */ + RETURNS_1(expr(ls)); /* read condition */ +} + +static void gotostat(LexState *ls) { Position pos = getposition(ls); - RETURNS_1(explist(ls)); - new_object(ls,"assignment",2,&pos); - } -} - - -static void cond (LexState *ls) { - /* cond -> exp */ - RETURNS_1(expr(ls)); /* read condition */ -} - - -static void gotostat (LexState *ls) { - Position pos = getposition(ls); - if (testnext(ls, TK_GOTO)) { - checksymbol(ls,NULL); - new_object(ls,"gotostat",1,&pos); - } else { - new_object(ls,"breakstat",0,&pos); - luaX_next(ls); /* skip break */ - } - -} - -static void labelstat (LexState *ls) { - check_terra(ls,"goto labels"); - /* label -> '::' NAME '::' */ - Position pos = getposition(ls); - RETURNS_1(checksymbol(ls,NULL)); - checknext(ls, TK_DBCOLON); /* skip double colon */ - new_object(ls,"label",1,&pos); -} - - -static void whilestat (LexState *ls, int line) { - /* whilestat -> WHILE cond DO block END */ - FuncState *fs = ls->fs; - Position pos = getposition(ls); - BlockCnt bl; - luaX_next(ls); /* skip WHILE */ - RETURNS_1(cond(ls)); - enterblock(fs, &bl, 1); - checknext(ls, TK_DO); - RETURNS_1(block(ls)); - check_match(ls, TK_END, TK_WHILE, line); - leaveblock(fs); - new_object(ls,"whilestat",2,&pos); -} - - -static void repeatstat (LexState *ls, int line) { - /* repeatstat -> REPEAT block UNTIL cond */ - FuncState *fs = ls->fs; - BlockCnt bl1, bl2; - enterblock(fs, &bl1, 1); /* loop block */ - enterblock(fs, &bl2, 0); /* scope block */ - luaX_next(ls); /* skip REPEAT */ - int stmts = new_list(ls); - Position pos = getposition(ls); - - RETURNS_1(statlist(ls)); - check_match(ls, TK_UNTIL, TK_REPEAT, line); - RETURNS_1(cond(ls)); - - leaveblock(fs); /* finish scope */ - leaveblock(fs); /* finish loop */ - new_object(ls,"repeatstat",2,&pos); - add_entry(ls, stmts); - new_object(ls,"block",1,&pos); -} - -static void forbody (LexState *ls, int line, int isnum, BlockCnt * bl) { - /* forbody -> DO block */ - FuncState *fs = ls->fs; - checknext(ls, TK_DO); - enterblock(fs, bl, 0); /* scope for declared variables */ - RETURNS_1(block(ls)); - leaveblock(fs); /* end of scope for declared variables */ -} - -static void fornum (LexState *ls, TString *varname, Position * p) { - /* fornum -> NAME = exp1,exp1[,exp1] forbody */ - checknext(ls, '='); - RETURNS_1(expr(ls)); /* initial value */ - checknext(ls, ','); - RETURNS_1(expr(ls)); /* limit */ - if (testnext(ls, ',')) { - RETURNS_1(expr(ls)); /* optional step */ - } else { - push_nil(ls); - } - BlockCnt bl; - if(varname) - definevariable(ls, varname); - RETURNS_1(forbody(ls, p->linenumber, 1, &bl)); - new_object(ls,"fornumu",5,p); - int blk = new_list_before(ls); - add_entry(ls, blk); - new_object(ls, "block", 1, p); -} - - -static void forlist (LexState *ls, TString *indexname, Position * p) { - /* forlist -> NAME {,NAME} IN explist forbody */ - int vars = new_list_before(ls); - add_entry(ls,vars); - /* create declared variables */ - BlockCnt bl; - if(indexname) - definevariable(ls, indexname); - - while (testnext(ls, ',')) { - TString * name; - if(vardecl(ls, 0, &name)) - definevariable(ls,name); - add_entry(ls,vars); - } - checknext(ls, TK_IN); - int line = ls->linenumber; - if(ls->in_terra) - RETURNS_1(expr(ls)); - else - RETURNS_1(explist(ls)); - RETURNS_1(forbody(ls, line, 0, &bl)); - new_object(ls,"forlist",3,p); -} - -static void forstat (LexState *ls, Position * p) { - /* forstat -> FOR (fornum | forlist) END */ - FuncState *fs = ls->fs; - TString *varname = NULL; - BlockCnt bl; - enterblock(fs, &bl, 1); /* scope for loop and control variables */ - luaX_next(ls); /* skip `for' */ - - vardecl(ls, 0, &varname); - - switch (ls->t.token) { - case '=': RETURNS_0(fornum(ls, varname, p)); break; - case ',': case TK_IN: RETURNS_0(forlist(ls, varname,p)); break; - default: luaX_syntaxerror(ls, LUA_QL("=") " or " LUA_QL("in") " expected"); - } - check_match(ls, TK_END, TK_FOR, p->linenumber); - leaveblock(fs); /* loop scope (`break' jumps to this point) */ -} - -static void test_then_block (LexState *ls) { - /* test_then_block -> [IF | ELSEIF] cond THEN block */ - BlockCnt bl; - luaX_next(ls); /* skip IF or ELSEIF */ - Position p = getposition(ls); - RETURNS_1(cond(ls)); /* read condition */ - checknext(ls, TK_THEN); - RETURNS_1(block(ls)); - new_object(ls,"ifbranch",2,&p); -} - -static void ifstat (LexState *ls, int line) { - /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ - Position p = getposition(ls); - int branches = new_list(ls); - RETURNS_1(test_then_block(ls)); /* IF cond THEN block */ - add_entry(ls,branches); - while (ls->t.token == TK_ELSEIF) { - RETURNS_1(test_then_block(ls)); /* ELSEIF cond THEN block */ - add_entry(ls,branches); - } - if (testnext(ls, TK_ELSE)) { - RETURNS_1(block(ls)); /* `else' part */ - } else push_nil(ls); - check_match(ls, TK_END, TK_IF, line); - new_object(ls,"ifstat",2,&p); -} - -static void localfunc (LexState *ls) { - TString * name = str_checkname(ls); - definevariable(ls, name); - body(ls, 0, ls->linenumber); /* function created in next register */ - /* debug information will only see the variable after this point! */ - -} - -void print_name_list(LexState * ls, std::vector * definednames) { - for(size_t i = 0; i < definednames->size(); i++) { + if (testnext(ls, TK_GOTO)) { + checksymbol(ls, NULL); + new_object(ls, "gotostat", 1, &pos); + } else { + new_object(ls, "breakstat", 0, &pos); + luaX_next(ls); /* skip break */ + } +} + +static void labelstat(LexState *ls) { + check_terra(ls, "goto labels"); + /* label -> '::' NAME '::' */ + Position pos = getposition(ls); + RETURNS_1(checksymbol(ls, NULL)); + checknext(ls, TK_DBCOLON); /* skip double colon */ + new_object(ls, "label", 1, &pos); +} + +static void whilestat(LexState *ls, int line) { + /* whilestat -> WHILE cond DO block END */ + FuncState *fs = ls->fs; + Position pos = getposition(ls); + BlockCnt bl; + luaX_next(ls); /* skip WHILE */ + RETURNS_1(cond(ls)); + enterblock(fs, &bl, 1); + checknext(ls, TK_DO); + RETURNS_1(block(ls)); + check_match(ls, TK_END, TK_WHILE, line); + leaveblock(fs); + new_object(ls, "whilestat", 2, &pos); +} + +static void repeatstat(LexState *ls, int line) { + /* repeatstat -> REPEAT block UNTIL cond */ + FuncState *fs = ls->fs; + BlockCnt bl1, bl2; + enterblock(fs, &bl1, 1); /* loop block */ + enterblock(fs, &bl2, 0); /* scope block */ + luaX_next(ls); /* skip REPEAT */ + int stmts = new_list(ls); + Position pos = getposition(ls); + + RETURNS_1(statlist(ls)); + check_match(ls, TK_UNTIL, TK_REPEAT, line); + RETURNS_1(cond(ls)); + + leaveblock(fs); /* finish scope */ + leaveblock(fs); /* finish loop */ + new_object(ls, "repeatstat", 2, &pos); + add_entry(ls, stmts); + new_object(ls, "block", 1, &pos); +} + +static void forbody(LexState *ls, int line, int isnum, BlockCnt *bl) { + /* forbody -> DO block */ + FuncState *fs = ls->fs; + checknext(ls, TK_DO); + enterblock(fs, bl, 0); /* scope for declared variables */ + RETURNS_1(block(ls)); + leaveblock(fs); /* end of scope for declared variables */ +} + +static void fornum(LexState *ls, TString *varname, Position *p) { + /* fornum -> NAME = exp1,exp1[,exp1] forbody */ + checknext(ls, '='); + RETURNS_1(expr(ls)); /* initial value */ + checknext(ls, ','); + RETURNS_1(expr(ls)); /* limit */ + if (testnext(ls, ',')) { + RETURNS_1(expr(ls)); /* optional step */ + } else { + push_nil(ls); + } + BlockCnt bl; + if (varname) definevariable(ls, varname); + RETURNS_1(forbody(ls, p->linenumber, 1, &bl)); + new_object(ls, "fornumu", 5, p); + int blk = new_list_before(ls); + add_entry(ls, blk); + new_object(ls, "block", 1, p); +} + +static void forlist(LexState *ls, TString *indexname, Position *p) { + /* forlist -> NAME {,NAME} IN explist forbody */ + int vars = new_list_before(ls); + add_entry(ls, vars); + /* create declared variables */ + BlockCnt bl; + if (indexname) definevariable(ls, indexname); + + while (testnext(ls, ',')) { + TString *name; + if (vardecl(ls, 0, &name)) definevariable(ls, name); + add_entry(ls, vars); + } + checknext(ls, TK_IN); + int line = ls->linenumber; + if (ls->in_terra) + RETURNS_1(expr(ls)); + else + RETURNS_1(explist(ls)); + RETURNS_1(forbody(ls, line, 0, &bl)); + new_object(ls, "forlist", 3, p); +} + +static void forstat(LexState *ls, Position *p) { + /* forstat -> FOR (fornum | forlist) END */ + FuncState *fs = ls->fs; + TString *varname = NULL; + BlockCnt bl; + enterblock(fs, &bl, 1); /* scope for loop and control variables */ + luaX_next(ls); /* skip `for' */ + + vardecl(ls, 0, &varname); + + switch (ls->t.token) { + case '=': + RETURNS_0(fornum(ls, varname, p)); + break; + case ',': + case TK_IN: + RETURNS_0(forlist(ls, varname, p)); + break; + default: + luaX_syntaxerror(ls, LUA_QL("=") " or " LUA_QL("in") " expected"); + } + check_match(ls, TK_END, TK_FOR, p->linenumber); + leaveblock(fs); /* loop scope (`break' jumps to this point) */ +} + +static void test_then_block(LexState *ls) { + /* test_then_block -> [IF | ELSEIF] cond THEN block */ + BlockCnt bl; + luaX_next(ls); /* skip IF or ELSEIF */ + Position p = getposition(ls); + RETURNS_1(cond(ls)); /* read condition */ + checknext(ls, TK_THEN); + RETURNS_1(block(ls)); + new_object(ls, "ifbranch", 2, &p); +} + +static void ifstat(LexState *ls, int line) { + /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ + Position p = getposition(ls); + int branches = new_list(ls); + RETURNS_1(test_then_block(ls)); /* IF cond THEN block */ + add_entry(ls, branches); + while (ls->t.token == TK_ELSEIF) { + RETURNS_1(test_then_block(ls)); /* ELSEIF cond THEN block */ + add_entry(ls, branches); + } + if (testnext(ls, TK_ELSE)) { + RETURNS_1(block(ls)); /* `else' part */ + } else + push_nil(ls); + check_match(ls, TK_END, TK_IF, line); + new_object(ls, "ifstat", 2, &p); +} + +static void localfunc(LexState *ls) { + TString *name = str_checkname(ls); + definevariable(ls, name); + body(ls, 0, ls->linenumber); /* function created in next register */ + /* debug information will only see the variable after this point! */ +} + +void print_name_list(LexState *ls, std::vector *definednames) { + for (size_t i = 0; i < definednames->size(); i++) { Name_print(&(*definednames)[i], ls); - if(i + 1 < definednames->size()) - OutputBuffer_putc(&ls->output_buffer, ','); - } -} - -static void localstat (LexState *ls) { - /* stat -> LOCAL NAME {`,' NAME} [`=' explist] */ - Position p = getposition(ls); - int vars = new_list(ls); - std::vector declarednames; - do { - TString * vname; - if(vardecl(ls, 0, &vname)) - declarednames.push_back(vname); - add_entry(ls,vars); - } while (testnext(ls, ',')); - if (testnext(ls, '=')) { - push_boolean(ls,true); - RETURNS_1(explist(ls)); - } else { - push_boolean(ls,false); - new_list(ls); - } - for(size_t i = 0; i < declarednames.size(); i++) { - definevariable(ls, declarednames[i]); - } - new_object(ls,"defvar",3,&p); -} - -static int funcname (LexState *ls) { - /* funcname -> NAME {fieldsel} [`:' NAME] */ - int ismethod = 0; - TString * vname = str_checkname(ls); - refvariable(ls, vname); - while(testnext(ls,'.')) { - str_checkname(ls); - } - if (testnext(ls,':')) { - ismethod = 1; - str_checkname(ls); - } - return ismethod; -} - -static void dump(LexState * ls) { - lua_State * L = ls->L; + if (i + 1 < definednames->size()) OutputBuffer_putc(&ls->output_buffer, ','); + } +} + +static void localstat(LexState *ls) { + /* stat -> LOCAL NAME {`,' NAME} [`=' explist] */ + Position p = getposition(ls); + int vars = new_list(ls); + std::vector declarednames; + do { + TString *vname; + if (vardecl(ls, 0, &vname)) declarednames.push_back(vname); + add_entry(ls, vars); + } while (testnext(ls, ',')); + if (testnext(ls, '=')) { + push_boolean(ls, true); + RETURNS_1(explist(ls)); + } else { + push_boolean(ls, false); + new_list(ls); + } + for (size_t i = 0; i < declarednames.size(); i++) { + definevariable(ls, declarednames[i]); + } + new_object(ls, "defvar", 3, &p); +} + +static int funcname(LexState *ls) { + /* funcname -> NAME {fieldsel} [`:' NAME] */ + int ismethod = 0; + TString *vname = str_checkname(ls); + refvariable(ls, vname); + while (testnext(ls, '.')) { + str_checkname(ls); + } + if (testnext(ls, ':')) { + ismethod = 1; + str_checkname(ls); + } + return ismethod; +} + +static void dump(LexState *ls) { + lua_State *L = ls->L; printf("object is:\n"); int tree = lua_gettop(L); - lua_getfield(L,LUA_GLOBALSINDEX,"terra"); - lua_getfield(L,-1,"tree"); - lua_getfield(L,-1,"printraw"); + lua_getfield(L, LUA_GLOBALSINDEX, "terra"); + lua_getfield(L, -1, "tree"); + lua_getfield(L, -1, "printraw"); lua_pushvalue(L, tree); lua_call(L, 1, 0); - - lua_pop(L,2); -} + lua_pop(L, 2); +} -static void funcstat (LexState *ls, int line) { - /* funcstat -> FUNCTION funcname body */ - luaX_next(ls); /* skip FUNCTION */ - int ismethod = funcname(ls); - body(ls, ismethod, line); +static void funcstat(LexState *ls, int line) { + /* funcstat -> FUNCTION funcname body */ + luaX_next(ls); /* skip FUNCTION */ + int ismethod = funcname(ls); + body(ls, ismethod, line); } -static int terraname (LexState *ls, int islocal, int token, Name * name) { - /* funcname -> NAME {fieldsel} [`:' NAME] */ - int ismethod = 0; - - TString * vname = str_checkname(ls); - Name_add(name,vname); - - if(!islocal) { - while(testnext(ls,'.')) { - TString * vname = str_checkname(ls); - Name_add(name,vname); - } - if (TK_TERRA == token && testnext(ls,':')) { - ismethod = 1; - TString * vname = str_checkname(ls); - Name_add(name,vname); +static int terraname(LexState *ls, int islocal, int token, Name *name) { + /* funcname -> NAME {fieldsel} [`:' NAME] */ + int ismethod = 0; + + TString *vname = str_checkname(ls); + Name_add(name, vname); + + if (!islocal) { + while (testnext(ls, '.')) { + TString *vname = str_checkname(ls); + Name_add(name, vname); + } + if (TK_TERRA == token && testnext(ls, ':')) { + ismethod = 1; + TString *vname = str_checkname(ls); + Name_add(name, vname); + } } - } - - return ismethod; + + return ismethod; } struct TDefn { - char kind; //'f'unction 'm'ethod 's'truct - int treeid; //-1 indicates no tree + char kind; //'f'unction 'm'ethod 's'truct + int treeid; //-1 indicates no tree int islocal; }; -bool startsTerraStat(LexState * ls) { - if(ls->t.token == TK_TERRA || ls->t.token == TK_STRUCT) - return true; - if(ls->t.token == TK_LOCAL) { +bool startsTerraStat(LexState *ls) { + if (ls->t.token == TK_TERRA || ls->t.token == TK_STRUCT) return true; + if (ls->t.token == TK_LOCAL) { luaX_lookahead(ls); return ls->lookahead.token == TK_TERRA || ls->lookahead.token == TK_STRUCT; - } else return false; + } else + return false; } -static void terrastats(LexState * ls, bool emittedlocal) { +static void terrastats(LexState *ls, bool emittedlocal) { Token begin = ls->t; - + std::vector names; std::vector defs; size_t nlocals = 0; - + TerraCnt tc; - + enterterra(ls, &tc); - + bool islocal = emittedlocal; - for(int idx = 0; true; idx++) { + for (int idx = 0; true; idx++) { int token = ls->t.token; luaX_next(ls); /* consume starting token */ names.push_back(Name()); - Name * name = &names.back(); + Name *name = &names.back(); int ismethod = terraname(ls, islocal, token, name); - if(islocal) + if (islocal) nlocals++; else - refvariable(ls,name->data[0]); //non-local names are references because we look up old value - TDefn tdefn; tdefn.treeid = -1; tdefn.islocal = islocal; - switch(token) { + refvariable(ls, name->data[0]); // non-local names are references because we + // look up old value + TDefn tdefn; + tdefn.treeid = -1; + tdefn.islocal = islocal; + switch (token) { case TK_TERRA: { tdefn.kind = ismethod ? 'm' : 'f'; bodyortype(ls, ismethod); @@ -1706,526 +1740,533 @@ static void terrastats(LexState * ls, bool emittedlocal) { } break; case TK_STRUCT: { tdefn.kind = 's'; - if(ls->t.token == '{' || ls->t.token == '(') { + if (ls->t.token == '{' || ls->t.token == '(') { structconstructor(ls); tdefn.treeid = store_value(ls); } } break; } defs.push_back(tdefn); - if(!startsTerraStat(ls)) - break; + if (!startsTerraStat(ls)) break; islocal = testnext(ls, TK_LOCAL); } - + leaveterra(ls); - - luaX_patchbegin(ls,&begin); - - //print the new local names (if any) and define them in the local context - if(!emittedlocal && nlocals > 0) - OutputBuffer_printf(&ls->output_buffer, "local "); - for(size_t i = 0,emitted = 0; i < names.size(); i++) { - Name * name = &names[i]; - TString * firstname = name->data[0]; - if(defs[i].islocal) { + + luaX_patchbegin(ls, &begin); + + // print the new local names (if any) and define them in the local context + if (!emittedlocal && nlocals > 0) OutputBuffer_printf(&ls->output_buffer, "local "); + for (size_t i = 0, emitted = 0; i < names.size(); i++) { + Name *name = &names[i]; + TString *firstname = name->data[0]; + if (defs[i].islocal) { Name_print(name, ls); definevariable(ls, firstname); - tc.capturedlocals.insert(firstname); //capture these locals so that the constructor doesn't see old values - if(++emitted < nlocals) - OutputBuffer_putc(&ls->output_buffer, ','); + tc.capturedlocals.insert(firstname); // capture these locals so that the + // constructor doesn't see old values + if (++emitted < nlocals) OutputBuffer_putc(&ls->output_buffer, ','); } } - if(nlocals > 0) - OutputBuffer_putc(&ls->output_buffer, ';'); - + if (nlocals > 0) OutputBuffer_putc(&ls->output_buffer, ';'); + bool hasreturns = false; - for(size_t i = 0; i < names.size(); i++) { - if(names[i].data.size() == 1) { - if(hasreturns) OutputBuffer_putc(&ls->output_buffer, ','); - Name_print(&names[i],ls); + for (size_t i = 0; i < names.size(); i++) { + if (names[i].data.size() == 1) { + if (hasreturns) OutputBuffer_putc(&ls->output_buffer, ','); + Name_print(&names[i], ls); hasreturns = true; } } - if(hasreturns) - OutputBuffer_printf(&ls->output_buffer, " = "); + if (hasreturns) OutputBuffer_printf(&ls->output_buffer, " = "); OutputBuffer_printf(&ls->output_buffer, "terra.defineobjects(\""); - for(size_t i = 0; i < defs.size(); i++) + for (size_t i = 0; i < defs.size(); i++) OutputBuffer_putc(&ls->output_buffer, defs[i].kind); OutputBuffer_printf(&ls->output_buffer, "\","); print_captured_locals(ls, &tc); - for(size_t i = 0; i < defs.size(); i++) { - Name * name = &names[i]; + for (size_t i = 0; i < defs.size(); i++) { + Name *name = &names[i]; OutputBuffer_printf(&ls->output_buffer, ", \""); - Name_print(name,ls); - OutputBuffer_printf(&ls->output_buffer, "\", _G.terra._trees[%d]",defs[i].treeid); - } - OutputBuffer_putc(&ls->output_buffer,')'); - luaX_patchend(ls,&begin); -} - -static void exprstat (LexState *ls) { - /* stat -> func | assignment */ - RETURNS_1(lhsexp(ls)); - if(ls->t.token != '=' && ls->t.token != ',') { /* stat -> func */ - //nop - } else { /* stat -> assignment */ - int tbl = new_list_before(ls); //assignment list is put into a table - add_entry(ls,tbl); - RETURNS_0(assignment(ls, 1,tbl)); //assignment will replace this table with the actual assignment node - } -} - - -static void retstat (LexState *ls) { - /* stat -> RETURN [explist] [';'] */ - Position p = getposition(ls); - new_list(ls); //empty statements - if (block_follow(ls, 1) || ls->t.token == ';') { - new_list(ls); - } else { - RETURNS_1(explist(ls)); /* optional return values */ - } - push_boolean(ls, false); //has statements - testnext(ls, ';'); /* skip optional semicolon */ - new_object(ls, "letin", 3, &p); - new_object(ls,"returnstat",1,&p); -} - - -static void statement (LexState *ls) { - Position p = getposition(ls); - int line = p.linenumber; /* may be needed for error messages */ - - enterlevel(ls); - - switch (ls->t.token) { - case TK_IF: { /* stat -> ifstat */ - RETURNS_1(ifstat(ls, line)); - break; - } - case TK_WHILE: { /* stat -> whilestat */ - RETURNS_1(whilestat(ls, line)); - break; - } - case TK_DO: { /* stat -> DO block END */ - luaX_next(ls); /* skip DO */ - RETURNS_1(block(ls)); - check_match(ls, TK_END, TK_DO, line); - break; - } - case TK_FOR: { /* stat -> forstat */ - //TODO: AST - RETURNS_1(forstat(ls, &p)); - break; - } - case TK_REPEAT: { /* stat -> repeatstat */ - RETURNS_1(repeatstat(ls, line)); - break; - } - case TK_FUNCTION: { /* stat -> funcstat */ - check_no_terra(ls,"lua functions"); - funcstat(ls, line); - break; - } - case TK_TERRA: case TK_STRUCT: { - check_no_terra(ls, "terra declarations"); - terrastats(ls, false); - } break; - case TK_SPECIAL: { - check_no_terra(ls, "language extensions"); - languageextension(ls, 1, 0); - } break; - case TK_LOCAL: { /* stat -> localstat */ - luaX_next(ls); /* skip LOCAL */ - check_no_terra(ls,"local keywords"); - if (testnext(ls, TK_FUNCTION)) { /* local function? */ - localfunc(ls); - } else if(ls->t.token == TK_STRUCT || ls->t.token == TK_TERRA) { - terrastats(ls, true); - } else if(ls->t.token == TK_SPECIAL) { - languageextension(ls, 1, 1); - } else { - localstat(ls); - } - break; - } - case TK_VAR: { - check_terra(ls, "variables"); - luaX_next(ls); /* skip var */ - RETURNS_1(localstat(ls)); - break; - } - case TK_DBCOLON: { /* stat -> label */ - - luaX_next(ls); /* skip double colon */ - RETURNS_1(labelstat(ls)); - break; - } - case TK_RETURN: { /* stat -> retstat */ - luaX_next(ls); /* skip RETURN */ - RETURNS_1(retstat(ls)); - break; - } - case TK_BREAK: /* stat -> breakstat */ - case TK_GOTO: { /* stat -> 'goto' NAME */ - RETURNS_1(gotostat(ls)); - break; - } - case TK_IMPORT: { - check_no_terra(ls, "import statements"); - Token begin = ls->t; - luaX_next(ls); - check(ls,TK_STRING); - luaX_globalgetfield(ls, TA_TERRA_OBJECT, "importlanguage"); - luaX_globalpush(ls, TA_LANGUAGES_TABLE); - luaX_globalpush(ls, TA_ENTRY_POINT_TABLE); - lua_pushstring(ls->L, getstr(ls->t.seminfo.ts)); - ls->languageextensionsenabled++; - ls->fs->bl->languageextensionsdefined++; - - if(lua_pcall(ls->L, 3, 0, 0)) { - const char * str = luaL_checkstring(ls->L,-1); - luaX_reporterror(ls, str); - } - luaX_next(ls); /* skip string */ - luaX_patchbegin(ls, &begin); - OutputBuffer_printf(&ls->output_buffer, "do end"); - luaX_patchend(ls, &begin); - break; - } - case TK_DEFER: { - Position p = getposition(ls); - luaX_next(ls); - expr(ls); - new_object(ls,"defer",1,&p); - break; + Name_print(name, ls); + OutputBuffer_printf(&ls->output_buffer, "\", _G.terra._trees[%d]", + defs[i].treeid); } - case TK_ESCAPE: { - blockescape(ls); - break; + OutputBuffer_putc(&ls->output_buffer, ')'); + luaX_patchend(ls, &begin); +} + +static void exprstat(LexState *ls) { + /* stat -> func | assignment */ + RETURNS_1(lhsexp(ls)); + if (ls->t.token != '=' && ls->t.token != ',') { /* stat -> func */ + // nop + } else { /* stat -> assignment */ + int tbl = new_list_before(ls); // assignment list is put into a table + add_entry(ls, tbl); + RETURNS_0(assignment(ls, 1, tbl)); // assignment will replace this table with the + // actual assignment node } - /*otherwise, fallthrough to the normal error message.*/ - default: { /* stat -> func | assignment */ - RETURNS_1(exprstat(ls)); - break; +} + +static void retstat(LexState *ls) { + /* stat -> RETURN [explist] [';'] */ + Position p = getposition(ls); + new_list(ls); // empty statements + if (block_follow(ls, 1) || ls->t.token == ';') { + new_list(ls); + } else { + RETURNS_1(explist(ls)); /* optional return values */ } - } - leavelevel(ls); + push_boolean(ls, false); // has statements + testnext(ls, ';'); /* skip optional semicolon */ + new_object(ls, "letin", 3, &p); + new_object(ls, "returnstat", 1, &p); } -static void le_handleerror(LexState * ls) { - /* there was an error, it is on the top of the stack - we need to call lua's error handler to rethrow the error. */ - ls->rethrow = 1; /* prevent languageextension from adding the context again */ - lua_error(ls->L); /* does not return */ +static void statement(LexState *ls) { + Position p = getposition(ls); + int line = p.linenumber; /* may be needed for error messages */ + + enterlevel(ls); + + switch (ls->t.token) { + case TK_IF: { /* stat -> ifstat */ + RETURNS_1(ifstat(ls, line)); + break; + } + case TK_WHILE: { /* stat -> whilestat */ + RETURNS_1(whilestat(ls, line)); + break; + } + case TK_DO: { /* stat -> DO block END */ + luaX_next(ls); /* skip DO */ + RETURNS_1(block(ls)); + check_match(ls, TK_END, TK_DO, line); + break; + } + case TK_FOR: { /* stat -> forstat */ + // TODO: AST + RETURNS_1(forstat(ls, &p)); + break; + } + case TK_REPEAT: { /* stat -> repeatstat */ + RETURNS_1(repeatstat(ls, line)); + break; + } + case TK_FUNCTION: { /* stat -> funcstat */ + check_no_terra(ls, "lua functions"); + funcstat(ls, line); + break; + } + case TK_TERRA: + case TK_STRUCT: { + check_no_terra(ls, "terra declarations"); + terrastats(ls, false); + } break; + case TK_SPECIAL: { + check_no_terra(ls, "language extensions"); + languageextension(ls, 1, 0); + } break; + case TK_LOCAL: { /* stat -> localstat */ + luaX_next(ls); /* skip LOCAL */ + check_no_terra(ls, "local keywords"); + if (testnext(ls, TK_FUNCTION)) { /* local function? */ + localfunc(ls); + } else if (ls->t.token == TK_STRUCT || ls->t.token == TK_TERRA) { + terrastats(ls, true); + } else if (ls->t.token == TK_SPECIAL) { + languageextension(ls, 1, 1); + } else { + localstat(ls); + } + break; + } + case TK_VAR: { + check_terra(ls, "variables"); + luaX_next(ls); /* skip var */ + RETURNS_1(localstat(ls)); + break; + } + case TK_DBCOLON: { /* stat -> label */ + + luaX_next(ls); /* skip double colon */ + RETURNS_1(labelstat(ls)); + break; + } + case TK_RETURN: { /* stat -> retstat */ + luaX_next(ls); /* skip RETURN */ + RETURNS_1(retstat(ls)); + break; + } + case TK_BREAK: /* stat -> breakstat */ + case TK_GOTO: { /* stat -> 'goto' NAME */ + RETURNS_1(gotostat(ls)); + break; + } + case TK_IMPORT: { + check_no_terra(ls, "import statements"); + Token begin = ls->t; + luaX_next(ls); + check(ls, TK_STRING); + luaX_globalgetfield(ls, TA_TERRA_OBJECT, "importlanguage"); + luaX_globalpush(ls, TA_LANGUAGES_TABLE); + luaX_globalpush(ls, TA_ENTRY_POINT_TABLE); + lua_pushstring(ls->L, getstr(ls->t.seminfo.ts)); + ls->languageextensionsenabled++; + ls->fs->bl->languageextensionsdefined++; + + if (lua_pcall(ls->L, 3, 0, 0)) { + const char *str = luaL_checkstring(ls->L, -1); + luaX_reporterror(ls, str); + } + luaX_next(ls); /* skip string */ + luaX_patchbegin(ls, &begin); + OutputBuffer_printf(&ls->output_buffer, "do end"); + luaX_patchend(ls, &begin); + break; + } + case TK_DEFER: { + Position p = getposition(ls); + luaX_next(ls); + expr(ls); + new_object(ls, "defer", 1, &p); + break; + } + case TK_ESCAPE: { + blockescape(ls); + break; + } + /*otherwise, fallthrough to the normal error message.*/ + default: { /* stat -> func | assignment */ + RETURNS_1(exprstat(ls)); + break; + } + } + leavelevel(ls); +} + +static void le_handleerror(LexState *ls) { + /* there was an error, it is on the top of the stack + we need to call lua's error handler to rethrow the error. */ + ls->rethrow = 1; /* prevent languageextension from adding the context again */ + lua_error(ls->L); /* does not return */ } -static int le_next(lua_State * L) { - LexState * ls = const_cast((const LexState *) lua_topointer(L,lua_upvalueindex(1))); +static int le_next(lua_State *L) { + LexState *ls = const_cast( + (const LexState *)lua_topointer(L, lua_upvalueindex(1))); try { - luaX_next(ls); - } catch(...) { - le_handleerror(ls); + luaX_next(ls); + } catch (...) { + le_handleerror(ls); } return 0; } -static void converttokentolua(LexState * ls, Token * t) { +static void converttokentolua(LexState *ls, Token *t) { lua_newtable(ls->L); - switch(t->token) { - case TK_NAME: { - lua_getfield(ls->L,lua_upvalueindex(2),getstr(t->seminfo.ts)); - int iskeyword = !lua_isnil(ls->L,-1); - lua_pop(ls->L,1); - lua_pushstring(ls->L,getstr(t->seminfo.ts)); - if(!iskeyword) { - lua_setfield(ls->L,-2,"value"); - lua_pushstring(ls->L,""); - } - lua_setfield(ls->L,-2,"type"); - } break; - case TK_STRING: - lua_pushstring(ls->L,""); - lua_setfield(ls->L,-2,"type"); - lua_pushstring(ls->L,getstr(t->seminfo.ts)); - lua_setfield(ls->L,-2,"value"); - break; - case TK_NUMBER: { - char buf[128]; - lua_pushstring(ls->L,""); - lua_setfield(ls->L,-2,"type"); - int flags = t->seminfo.flags; - number_type(ls, flags, &buf[0]); - push_type(ls,buf); - lua_setfield(ls->L,-2,"valuetype"); - if (flags & F_IS8BYTES && flags & F_ISINTEGER) { - uint64_t * ip = (uint64_t*) lua_newuserdata(ls->L,sizeof(uint64_t)); - *ip = t->seminfo.i; - } else { - lua_pushnumber(ls->L,t->seminfo.r); - } - lua_setfield(ls->L,-2,"value"); - } break; - case TK_SPECIAL: - lua_pushstring(ls->L,getstr(t->seminfo.ts)); - lua_setfield(ls->L,-2,"type"); - break; - case TK_EOS: - lua_pushstring(ls->L,""); - lua_setfield(ls->L,-2,"type"); - break; - default: - lua_pushstring(ls->L,luaX_token2rawstr(ls,t->token)); - lua_setfield(ls->L,-2,"type"); - break; - } -} - -static int le_cur(lua_State * L) { - LexState * ls = const_cast((const LexState *) lua_topointer(L,lua_upvalueindex(1))); + switch (t->token) { + case TK_NAME: { + lua_getfield(ls->L, lua_upvalueindex(2), getstr(t->seminfo.ts)); + int iskeyword = !lua_isnil(ls->L, -1); + lua_pop(ls->L, 1); + lua_pushstring(ls->L, getstr(t->seminfo.ts)); + if (!iskeyword) { + lua_setfield(ls->L, -2, "value"); + lua_pushstring(ls->L, ""); + } + lua_setfield(ls->L, -2, "type"); + } break; + case TK_STRING: + lua_pushstring(ls->L, ""); + lua_setfield(ls->L, -2, "type"); + lua_pushstring(ls->L, getstr(t->seminfo.ts)); + lua_setfield(ls->L, -2, "value"); + break; + case TK_NUMBER: { + char buf[128]; + lua_pushstring(ls->L, ""); + lua_setfield(ls->L, -2, "type"); + int flags = t->seminfo.flags; + number_type(ls, flags, &buf[0]); + push_type(ls, buf); + lua_setfield(ls->L, -2, "valuetype"); + if (flags & F_IS8BYTES && flags & F_ISINTEGER) { + uint64_t *ip = (uint64_t *)lua_newuserdata(ls->L, sizeof(uint64_t)); + *ip = t->seminfo.i; + } else { + lua_pushnumber(ls->L, t->seminfo.r); + } + lua_setfield(ls->L, -2, "value"); + } break; + case TK_SPECIAL: + lua_pushstring(ls->L, getstr(t->seminfo.ts)); + lua_setfield(ls->L, -2, "type"); + break; + case TK_EOS: + lua_pushstring(ls->L, ""); + lua_setfield(ls->L, -2, "type"); + break; + default: + lua_pushstring(ls->L, luaX_token2rawstr(ls, t->token)); + lua_setfield(ls->L, -2, "type"); + break; + } +} + +static int le_cur(lua_State *L) { + LexState *ls = const_cast( + (const LexState *)lua_topointer(L, lua_upvalueindex(1))); converttokentolua(ls, &ls->t); Position p = getposition(ls); table_setposition(ls, lua_gettop(ls->L), p); return 1; } -static int le_lookahead(lua_State * L) { - LexState * ls = const_cast((const LexState *) lua_topointer(L,lua_upvalueindex(1))); +static int le_lookahead(lua_State *L) { + LexState *ls = const_cast( + (const LexState *)lua_topointer(L, lua_upvalueindex(1))); try { - luaX_lookahead(ls); - converttokentolua(ls, &ls->lookahead); - } catch(...) { - le_handleerror(ls); + luaX_lookahead(ls); + converttokentolua(ls, &ls->lookahead); + } catch (...) { + le_handleerror(ls); } return 1; } -static int le_embeddedcode(lua_State * L) { - LexState * ls = const_cast((const LexState *) lua_topointer(L,lua_upvalueindex(1))); - bool isterra = lua_toboolean(L,1); - bool isexp = lua_toboolean(L,2); - try { - embeddedcode(ls,isterra,isexp); - } catch(...) { - le_handleerror(ls); - } - lua_getfield(ls->L,-1,"expression"); - lua_remove(ls->L,-2); /* remove original object, we just want to return the function */ - return 1; +static int le_embeddedcode(lua_State *L) { + LexState *ls = const_cast( + (const LexState *)lua_topointer(L, lua_upvalueindex(1))); + bool isterra = lua_toboolean(L, 1); + bool isexp = lua_toboolean(L, 2); + try { + embeddedcode(ls, isterra, isexp); + } catch (...) { + le_handleerror(ls); + } + lua_getfield(ls->L, -1, "expression"); + lua_remove(ls->L, + -2); /* remove original object, we just want to return the function */ + return 1; } -static void languageextension(LexState * ls, int isstatement, int islocal) { - lua_State * L = ls->L; +static void languageextension(LexState *ls, int isstatement, int islocal) { + lua_State *L = ls->L; Token begin = ls->t; std::vector names; TerraCnt tc; - - enterterra(ls, &tc); //specifically to capture local variables, not for other reasons - + + enterterra(ls, &tc); // specifically to capture local variables, not for other + // reasons + int top = lua_gettop(L); - //setup call to the language - - luaX_globalgetfield(ls, TA_TERRA_OBJECT,"runlanguage"); + // setup call to the language + + luaX_globalgetfield(ls, TA_TERRA_OBJECT, "runlanguage"); luaX_globalgetfield(ls, TA_ENTRY_POINT_TABLE, getstr(ls->t.seminfo.ts)); - - lua_pushlightuserdata(ls->L,(void*)ls); - lua_getfield(ls->L,-2,"keywordtable"); - lua_pushcclosure(ls->L,le_cur,2); - - lua_pushlightuserdata(ls->L,(void*)ls); - lua_getfield(ls->L,-3,"keywordtable"); - lua_pushcclosure(ls->L,le_lookahead,2); - - lua_pushlightuserdata(ls->L,(void*)ls); - lua_pushcclosure(ls->L,le_next,1); - - lua_pushlightuserdata(ls->L,(void*)ls); - lua_pushcclosure(ls->L,le_embeddedcode,1); - - lua_pushstring(ls->L,getstr(ls->source)); - lua_pushboolean(ls->L,isstatement); - lua_pushboolean(ls->L,islocal); - - if(lua_pcall(ls->L,8,3,0)) { - const char * str = luaL_checkstring(ls->L,-1); - if(ls->rethrow) + + lua_pushlightuserdata(ls->L, (void *)ls); + lua_getfield(ls->L, -2, "keywordtable"); + lua_pushcclosure(ls->L, le_cur, 2); + + lua_pushlightuserdata(ls->L, (void *)ls); + lua_getfield(ls->L, -3, "keywordtable"); + lua_pushcclosure(ls->L, le_lookahead, 2); + + lua_pushlightuserdata(ls->L, (void *)ls); + lua_pushcclosure(ls->L, le_next, 1); + + lua_pushlightuserdata(ls->L, (void *)ls); + lua_pushcclosure(ls->L, le_embeddedcode, 1); + + lua_pushstring(ls->L, getstr(ls->source)); + lua_pushboolean(ls->L, isstatement); + lua_pushboolean(ls->L, islocal); + + if (lua_pcall(ls->L, 8, 3, 0)) { + const char *str = luaL_checkstring(ls->L, -1); + if (ls->rethrow) luaX_reporterror(ls, str); else /* add line information */ luaX_syntaxerror(ls, str); } - + /* register all references from user code */ lua_pushnil(L); - while (lua_next(L,-2) != 0) { + while (lua_next(L, -2) != 0) { size_t len; - const char * str = lua_tolstring(L,-1,&len); - refvariable(ls, luaS_newlstr(ls->LP,str,len)); - lua_pop(L,1); - } - - lua_pop(L,1); /* remove _references list */ - - //put names returned into names object - + const char *str = lua_tolstring(L, -1, &len); + refvariable(ls, luaS_newlstr(ls->LP, str, len)); + lua_pop(L, 1); + } + + lua_pop(L, 1); /* remove _references list */ + + // put names returned into names object + lua_pushnil(L); while (lua_next(L, -2) != 0) { names.push_back(Name()); lua_pushnil(L); - while(lua_next(L,-2) != 0) { + while (lua_next(L, -2) != 0) { size_t len; - const char * str = lua_tolstring(L,-1,&len); + const char *str = lua_tolstring(L, -1, &len); names.back().data.push_back(luaS_newlstr(ls->LP, str, len)); - lua_pop(L,1); + lua_pop(L, 1); } lua_pop(L, 1); } - lua_pop(L,1); /* no longer need names, top of stack is now the user's function */ - - //object on top of stack + lua_pop(L, 1); /* no longer need names, top of stack is now the user's function */ + + // object on top of stack int n = store_value(ls); - + leaveterra(ls); - - //patch the thing into place - - luaX_patchbegin(ls,&begin); - - if(isstatement && names.size() > 0) { + + // patch the thing into place + + luaX_patchbegin(ls, &begin); + + if (isstatement && names.size() > 0) { print_name_list(ls, &names); - if(islocal) { - for(size_t i = 0; i < names.size(); i++) { + if (islocal) { + for (size_t i = 0; i < names.size(); i++) { definevariable(ls, names[i].data[0]); } } - OutputBuffer_printf(&ls->output_buffer," = "); - } - - OutputBuffer_printf(&ls->output_buffer,"_G.terra._trees[%d](",n); - print_captured_locals(ls,&tc); - OutputBuffer_printf(&ls->output_buffer,")"); - luaX_patchend(ls,&begin); - + OutputBuffer_printf(&ls->output_buffer, " = "); + } + + OutputBuffer_printf(&ls->output_buffer, "_G.terra._trees[%d](", n); + print_captured_locals(ls, &tc); + OutputBuffer_printf(&ls->output_buffer, ")"); + luaX_patchend(ls, &begin); + assert(lua_gettop(L) == top); } /* }====================================================================== */ -static void cleanup(LexState * ls) { - luaX_poptstringtable(ls->LP); //we can forget all the non-reserved strings +static void cleanup(LexState *ls) { + luaX_poptstringtable(ls->LP); // we can forget all the non-reserved strings OutputBuffer_free(&ls->output_buffer); - if(ls->buff->buffer) { + if (ls->buff->buffer) { free(ls->buff->buffer); ls->buff->buffer = NULL; } free(ls->buff); ls->buff = NULL; - if(ls->patchinfo.buffer) { + if (ls->patchinfo.buffer) { free(ls->patchinfo.buffer); ls->patchinfo.buffer = NULL; ls->patchinfo.N = 0; ls->patchinfo.space = 0; } - - //clear the registry index entry for our state - lua_pushlightuserdata(ls->L,&ls->lextable); + + // clear the registry index entry for our state + lua_pushlightuserdata(ls->L, &ls->lextable); lua_pushnil(ls->L); - lua_rawset(ls->L,LUA_REGISTRYINDEX); -} - -int luaY_parser (terra_State *T, ZIO *z, - const char *name, int firstchar) { - (void)dump; //suppress warning for unused debugging functions - (void)dump_stack; - (void)printtreesandnames; - LexState lexstate; - FuncState funcstate; - //memset(&lexstate,0,sizeof(LexState)); - //memset(&funcstate,0,sizeof(FuncState)); - - Mbuffer * buff = (Mbuffer*) malloc(sizeof(Mbuffer)); - memset(buff,0,sizeof(Mbuffer)); - - luaX_pushtstringtable(T); - - BlockCnt bl; - bl.previous = NULL; - lua_State * L = T->L; - lexstate.L = L; - lexstate.in_terra = 0; - lexstate.terracnt = NULL; - TString *tname = (name[0] == '@') ? luaS_new(T, name + 1) : luaS_stringf(T,"[string \"%s\"]",name); - lexstate.buff = buff; - lexstate.n_lua_objects = 0; - lexstate.rethrow = 0; - OutputBuffer_init(&lexstate.output_buffer); - if(!lua_checkstack(L,1 + LUAI_MAXCCALLS)) { - abort(); - } - lexstate.stacktop = lua_gettop(L); - - - lua_pushlightuserdata(L,&lexstate.lextable); - lua_newtable(L); /* lua state for lexer */ - lua_rawset(L,LUA_REGISTRYINDEX); - - lua_getfield(L,LUA_GLOBALSINDEX,"terra"); //TA_TERRA_OBJECT - int to = lua_gettop(L); - - lua_pushvalue(L,-1); - luaX_globalset(&lexstate, TA_TERRA_OBJECT); - - lua_getfield(L,to,"_trees"); - luaX_globalset(&lexstate, TA_FUNCTION_TABLE); - - - lua_getfield(L,to,"irtypes"); - luaX_globalset(&lexstate, TA_TYPE_TABLE); - - lua_getfield(L,to,"newlist"); - luaX_globalset(&lexstate, TA_NEWLIST); - - lua_newtable(L); - luaX_globalset(&lexstate, TA_ENTRY_POINT_TABLE); - lua_newtable(L); - luaX_globalset(&lexstate, TA_LANGUAGES_TABLE); - lexstate.languageextensionsenabled = 0; - - lua_pop(L,1); /* remove gs and terra object from stack */ - - assert(lua_gettop(L) == lexstate.stacktop); - try { - luaX_setinput(T, &lexstate, z, tname, firstchar); - open_mainfunc(&lexstate, &funcstate, &bl); - luaX_next(&lexstate); /* read first token */ - statlist(&lexstate); /* main body */ - check(&lexstate, TK_EOS); - close_func(&lexstate); - assert(!funcstate.prev && !lexstate.fs); - } catch(int err) { - cleanup(&lexstate); - assert(lua_gettop(L) > lexstate.stacktop); - if(lua_gettop(L) > lexstate.stacktop + 1) { - lua_replace(L,lexstate.stacktop + 1); //put the error message at the new top of stack - lua_settop(L, lexstate.stacktop + 1); //reset the stack to just 1 above where it orignally (holding the error message) + lua_rawset(ls->L, LUA_REGISTRYINDEX); +} + +int luaY_parser(terra_State *T, ZIO *z, const char *name, int firstchar) { + (void)dump; // suppress warning for unused debugging functions + (void)dump_stack; + (void)printtreesandnames; + LexState lexstate; + FuncState funcstate; + // memset(&lexstate,0,sizeof(LexState)); + // memset(&funcstate,0,sizeof(FuncState)); + + Mbuffer *buff = (Mbuffer *)malloc(sizeof(Mbuffer)); + memset(buff, 0, sizeof(Mbuffer)); + + luaX_pushtstringtable(T); + + BlockCnt bl; + bl.previous = NULL; + lua_State *L = T->L; + lexstate.L = L; + lexstate.in_terra = 0; + lexstate.terracnt = NULL; + TString *tname = (name[0] == '@') ? luaS_new(T, name + 1) + : luaS_stringf(T, "[string \"%s\"]", name); + lexstate.buff = buff; + lexstate.n_lua_objects = 0; + lexstate.rethrow = 0; + OutputBuffer_init(&lexstate.output_buffer); + if (!lua_checkstack(L, 1 + LUAI_MAXCCALLS)) { + abort(); + } + lexstate.stacktop = lua_gettop(L); + + lua_pushlightuserdata(L, &lexstate.lextable); + lua_newtable(L); /* lua state for lexer */ + lua_rawset(L, LUA_REGISTRYINDEX); + + lua_getfield(L, LUA_GLOBALSINDEX, "terra"); // TA_TERRA_OBJECT + int to = lua_gettop(L); + + lua_pushvalue(L, -1); + luaX_globalset(&lexstate, TA_TERRA_OBJECT); + + lua_getfield(L, to, "_trees"); + luaX_globalset(&lexstate, TA_FUNCTION_TABLE); + + lua_getfield(L, to, "irtypes"); + luaX_globalset(&lexstate, TA_TYPE_TABLE); + + lua_getfield(L, to, "newlist"); + luaX_globalset(&lexstate, TA_NEWLIST); + + lua_newtable(L); + luaX_globalset(&lexstate, TA_ENTRY_POINT_TABLE); + lua_newtable(L); + luaX_globalset(&lexstate, TA_LANGUAGES_TABLE); + lexstate.languageextensionsenabled = 0; + + lua_pop(L, 1); /* remove gs and terra object from stack */ + + assert(lua_gettop(L) == lexstate.stacktop); + try { + luaX_setinput(T, &lexstate, z, tname, firstchar); + open_mainfunc(&lexstate, &funcstate, &bl); + luaX_next(&lexstate); /* read first token */ + statlist(&lexstate); /* main body */ + check(&lexstate, TK_EOS); + close_func(&lexstate); + assert(!funcstate.prev && !lexstate.fs); + } catch (int err) { + cleanup(&lexstate); + assert(lua_gettop(L) > lexstate.stacktop); + if (lua_gettop(L) > lexstate.stacktop + 1) { + lua_replace(L, lexstate.stacktop + + 1); // put the error message at the new top of stack + lua_settop(L, + lexstate.stacktop + 1); // reset the stack to just 1 above where + // it orignally (holding the error message) + } + assert(lua_gettop(L) == lexstate.stacktop + 1); + return err; + } + + assert(lua_gettop(L) == lexstate.stacktop); + + /* all scopes should be correctly finished */ + OutputBuffer_putc(&lexstate.output_buffer, '\0'); + VERBOSE_ONLY(T) { + printf("********* passing to lua " + "************\n%s\n*************************************\n", + lexstate.output_buffer.data); } - assert(lua_gettop(L) == lexstate.stacktop + 1); + // loadbuffer doesn't like null terminators, so rewind to before them + while (lexstate.output_buffer.data[lexstate.output_buffer.N - 1] == '\0' && + lexstate.output_buffer.N > 0) { + lexstate.output_buffer.N--; + } + + int err = luaL_loadbuffer(L, lexstate.output_buffer.data, lexstate.output_buffer.N, + name); + cleanup(&lexstate); + return err; - } - - assert(lua_gettop(L) == lexstate.stacktop); - - /* all scopes should be correctly finished */ - OutputBuffer_putc(&lexstate.output_buffer,'\0'); - VERBOSE_ONLY(T) { - printf("********* passing to lua ************\n%s\n*************************************\n",lexstate.output_buffer.data); - } - //loadbuffer doesn't like null terminators, so rewind to before them - while(lexstate.output_buffer.data[lexstate.output_buffer.N-1] == '\0' && lexstate.output_buffer.N > 0) { - lexstate.output_buffer.N--; - } - - int err = luaL_loadbuffer(L, lexstate.output_buffer.data, lexstate.output_buffer.N, name); - cleanup(&lexstate); - - return err; } - diff --git a/src/lparser.h b/src/lparser.h index 4f4beb2b0..a1fcfdcc6 100644 --- a/src/lparser.h +++ b/src/lparser.h @@ -16,25 +16,23 @@ */ /* control of blocks */ -struct BlockCnt; /* defined in lparser.c */ +struct BlockCnt; /* defined in lparser.c */ typedef struct Proto { int linedefined; int lastlinedefined; int is_vararg; - TString * source; + TString *source; } Proto; /* state needed to generate code for a given function */ typedef struct FuncState { - Proto f; /* current function header */ - struct FuncState *prev; /* enclosing function */ - struct LexState *ls; /* lexical state */ - struct BlockCnt *bl; /* chain of current blocks */ + Proto f; /* current function header */ + struct FuncState *prev; /* enclosing function */ + struct LexState *ls; /* lexical state */ + struct BlockCnt *bl; /* chain of current blocks */ } FuncState; - -LUAI_FUNC int luaY_parser (terra_State *T, ZIO *z, const char *name, int firstchar); - +LUAI_FUNC int luaY_parser(terra_State *T, ZIO *z, const char *name, int firstchar); #endif diff --git a/src/lutil.h b/src/lutil.h index a3567f3f5..e5f6cbf51 100644 --- a/src/lutil.h +++ b/src/lutil.h @@ -13,28 +13,23 @@ extern "C" { #include "lualib.h" } -#define cast(t, exp) ((t)(exp)) -#define cast_byte(i) cast(lu_byte, (i)) +#define cast(t, exp) ((t)(exp)) +#define cast_byte(i) cast(lu_byte, (i)) #define cast_num(i) cast(luaP_Number, (i)) #define cast_int(i) cast(int, (i)) -#define cast_uchar(i) cast(unsigned char, (i)) - +#define cast_uchar(i) cast(unsigned char, (i)) typedef double luaP_Number; typedef unsigned char lu_byte; typedef uint32_t lu_int32; -#define MAX_SIZET ((size_t)(~(size_t)0)-2) - +#define MAX_SIZET ((size_t)(~(size_t)0) - 2) typedef struct TString { - const char * string; - lu_byte reserved; + const char *string; + lu_byte reserved; } TString; - - - -typedef const char * (*luaP_Reader) (lua_State *L, void *ud, size_t *sz); +typedef const char *(*luaP_Reader)(lua_State *L, void *ud, size_t *sz); /* @@ LUAI_FUNC is a mark for all extern functions that are not to be @@ -50,29 +45,29 @@ typedef const char * (*luaP_Reader) (lua_State *L, void *ud, size_t *sz); ** give a warning about it. To avoid these warnings, change to the ** default definition. */ -#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ - defined(__ELF__) /* { */ -#define LUAI_FUNC __attribute__((visibility("hidden"))) extern -#define LUAI_DDEC LUAI_FUNC -#define LUAI_DDEF /* empty */ - -#else /* }{ */ -#define LUAI_FUNC extern -#define LUAI_DDEC extern -#define LUAI_DDEF /* empty */ -#endif /* } */ +#if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 302) && \ + defined(__ELF__) /* { */ +#define LUAI_FUNC __attribute__((visibility("hidden"))) extern +#define LUAI_DDEC LUAI_FUNC +#define LUAI_DDEF /* empty */ + +#else /* }{ */ +#define LUAI_FUNC extern +#define LUAI_DDEC extern +#define LUAI_DDEF /* empty */ +#endif /* } */ #if defined(__GNUC__) -#define l_noret void __attribute__((noreturn)) +#define l_noret void __attribute__((noreturn)) #elif defined(_MSC_VER) -#define l_noret void __declspec(noreturn) +#define l_noret void __declspec(noreturn) #else -#define l_noret void +#define l_noret void #endif /* minimum size for string buffer */ #if !defined(LUA_MINBUFFER) -#define LUA_MINBUFFER 32 +#define LUA_MINBUFFER 32 #endif /* @@ -80,10 +75,9 @@ typedef const char * (*luaP_Reader) (lua_State *L, void *ud, size_t *sz); @* of a function in debug information. ** CHANGE it if you want a different size. */ -#define LUA_IDSIZE 60 - +#define LUA_IDSIZE 60 -#define MAX_INT (INT_MAX-2) /* maximum value of an int (-2 for safety) */ +#define MAX_INT (INT_MAX - 2) /* maximum value of an int (-2 for safety) */ /* ** Marks the end of a patch list. It is an invalid value both as an absolute @@ -96,14 +90,14 @@ typedef const char * (*luaP_Reader) (lua_State *L, void *ud, size_t *sz); ** in a program. (Value must fit in an unsigned short int.) */ #if !defined(LUAI_MAXCCALLS) -#define LUAI_MAXCCALLS 200 +#define LUAI_MAXCCALLS 200 #endif /* @@ LUA_QL describes how error messages quote program elements. ** CHANGE it if you want a different appearance. */ -#define LUA_QL(x) "'" x "'" -#define LUA_QS LUA_QL("%s") +#define LUA_QL(x) "'" x "'" +#define LUA_QS LUA_QL("%s") #endif diff --git a/src/main.cpp b/src/main.cpp index 470c36b18..fbe870ad7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -19,105 +19,100 @@ #endif #include "terra.h" -static void doerror(lua_State * L) { - fprintf(stderr,"%s\n",luaL_checkstring(L,-1)); +static void doerror(lua_State *L) { + fprintf(stderr, "%s\n", luaL_checkstring(L, -1)); lua_close(L); terra_llvmshutdown(); exit(1); } -const char * progname = NULL; -static void dotty (lua_State *L); -void parse_args(lua_State * L, int argc, char ** argv, terra_Options * options, bool * interactive, int * begin_script); -static int getargs (lua_State *L, char **argv, int n); -static int docall (lua_State *L, int narg, int clear); +const char *progname = NULL; +static void dotty(lua_State *L); +void parse_args(lua_State *L, int argc, char **argv, terra_Options *options, + bool *interactive, int *begin_script); +static int getargs(lua_State *L, char **argv, int n); +static int docall(lua_State *L, int narg, int clear); -static void (*terratraceback)(void*); +static void (*terratraceback)(void *); #ifndef _WIN32 -void sigsegv(int sig, siginfo_t *info, void * uap) { - signal(sig,SIG_DFL); //reset signal to default, just in case traceback itself crashes - terratraceback(uap); //call terra's pretty traceback - raise(sig); //rethrow the signal to the default handler +void sigsegv(int sig, siginfo_t *info, void *uap) { + signal(sig, + SIG_DFL); // reset signal to default, just in case traceback itself crashes + terratraceback(uap); // call terra's pretty traceback + raise(sig); // rethrow the signal to the default handler } void registerhandler() { - struct sigaction sa; - sa.sa_flags = SA_RESETHAND | SA_SIGINFO; - sigemptyset(&sa.sa_mask); - sa.sa_sigaction = sigsegv; - sigaction(SIGSEGV, &sa, NULL); - sigaction(SIGILL, &sa, NULL); + struct sigaction sa; + sa.sa_flags = SA_RESETHAND | SA_SIGINFO; + sigemptyset(&sa.sa_mask); + sa.sa_sigaction = sigsegv; + sigaction(SIGSEGV, &sa, NULL); + sigaction(SIGILL, &sa, NULL); } #else -LONG WINAPI windowsexceptionhandler(EXCEPTION_POINTERS * ExceptionInfo) { - terratraceback(ExceptionInfo->ContextRecord); - return EXCEPTION_EXECUTE_HANDLER; -} -void registerhandler() { - SetUnhandledExceptionFilter(windowsexceptionhandler); +LONG WINAPI windowsexceptionhandler(EXCEPTION_POINTERS *ExceptionInfo) { + terratraceback(ExceptionInfo->ContextRecord); + return EXCEPTION_EXECUTE_HANDLER; } +void registerhandler() { SetUnhandledExceptionFilter(windowsexceptionhandler); } #endif -void setupcrashsignal(lua_State * L) { +void setupcrashsignal(lua_State *L) { lua_getglobal(L, "terralib"); lua_getfield(L, -1, "traceback"); - const void * tb = lua_topointer(L,-1); - if(!tb) - return; //debug not supported - terratraceback = *(void(* const *)(void*))tb; - registerhandler(); - lua_pop(L,2); + const void *tb = lua_topointer(L, -1); + if (!tb) return; // debug not supported + terratraceback = *(void (*const *)(void *))tb; + registerhandler(); + lua_pop(L, 2); } -static int luapanic (lua_State * L) { //so that we can set a debugger breakpoint and catch the error - printf("PANIC: unprotected error in call to Lua API (%s)\n",lua_tostring(L,-1)); +static int luapanic( + lua_State *L) { // so that we can set a debugger breakpoint and catch the error + printf("PANIC: unprotected error in call to Lua API (%s)\n", lua_tostring(L, -1)); exit(1); } -int main(int argc, char ** argv) { +int main(int argc, char **argv) { progname = argv[0]; - lua_State * L = luaL_newstate(); + lua_State *L = luaL_newstate(); luaL_openlibs(L); - lua_atpanic(L,luapanic); + lua_atpanic(L, luapanic); terra_Options options; memset(&options, 0, sizeof(terra_Options)); - + bool interactive = false; int scriptidx; - parse_args(L,argc,argv,&options,&interactive,&scriptidx); - - if(terra_initwithoptions(L, &options)) - doerror(L); - + parse_args(L, argc, argv, &options, &interactive, &scriptidx); + + if (terra_initwithoptions(L, &options)) doerror(L); + setupcrashsignal(L); - - if(options.cmd_line_chunk != NULL) { - if(terra_dostring(L,options.cmd_line_chunk)) - doerror(L); - free(options.cmd_line_chunk); + + if (options.cmd_line_chunk != NULL) { + if (terra_dostring(L, options.cmd_line_chunk)) doerror(L); + free(options.cmd_line_chunk); } - if(scriptidx < argc) { - int narg = getargs(L, argv, scriptidx); - lua_setglobal(L, "arg"); - const char * filename = argv[scriptidx]; - if(!strcmp(filename,"-")) - filename = NULL; - if(terra_loadfile(L,filename)) - doerror(L); - lua_insert(L, -(narg + 1)); - if(docall(L,narg,0)) - doerror(L); + if (scriptidx < argc) { + int narg = getargs(L, argv, scriptidx); + lua_setglobal(L, "arg"); + const char *filename = argv[scriptidx]; + if (!strcmp(filename, "-")) filename = NULL; + if (terra_loadfile(L, filename)) doerror(L); + lua_insert(L, -(narg + 1)); + if (docall(L, narg, 0)) doerror(L); } - - if(isatty(0) && (interactive || (scriptidx == argc && !options.cmd_line_chunk))) { + + if (isatty(0) && (interactive || (scriptidx == argc && !options.cmd_line_chunk))) { progname = NULL; dotty(L); } - + lua_close(L); terra_llvmshutdown(); - + return 0; } @@ -134,17 +129,16 @@ void usage() { " - Execute stdin instead of script and stop parsing options\n"); } -void parse_args(lua_State * L, int argc, char ** argv, terra_Options * options, bool * interactive, int * begin_script) { +void parse_args(lua_State *L, int argc, char **argv, terra_Options *options, + bool *interactive, int *begin_script) { int ch; - static struct option longopts[] = { - { "help", 0, NULL, 'h' }, - { "verbose", 0, NULL, 'v' }, - { "debugsymbols", 0, NULL, 'g' }, - { "interactive", 0, NULL, 'i' }, - { "mcjit", 0, NULL, 'm' }, - { "execute", required_argument, NULL, 'e' }, - { NULL, 0, NULL, 0 } - }; + static struct option longopts[] = {{"help", 0, NULL, 'h'}, + {"verbose", 0, NULL, 'v'}, + {"debugsymbols", 0, NULL, 'g'}, + {"interactive", 0, NULL, 'i'}, + {"mcjit", 0, NULL, 'm'}, + {"execute", required_argument, NULL, 'e'}, + {NULL, 0, NULL, 0}}; /* Parse commandline options */ opterr = 0; while ((ch = getopt_long(argc, argv, "+hvgime:p:", longopts, NULL)) != -1) { @@ -162,7 +156,7 @@ void parse_args(lua_State * L, int argc, char ** argv, terra_Options * options, options->usemcjit = 1; break; case 'e': - options->cmd_line_chunk = (char*)malloc(strlen(optarg) + 1); + options->cmd_line_chunk = (char *)malloc(strlen(optarg) + 1); strcpy(options->cmd_line_chunk, optarg); break; case ':': @@ -175,195 +169,199 @@ void parse_args(lua_State * L, int argc, char ** argv, terra_Options * options, } *begin_script = optind; } -//this stuff is from lua's lua.c repl implementation: +// this stuff is from lua's lua.c repl implementation: #ifndef _WIN32 #include "linenoise.h" -#define lua_readline(L,b,p) ((void)L, ((b)=linenoise(p)) != NULL) -#define lua_saveline(L,idx) \ - if (lua_strlen(L,idx) > 0) /* non-empty line? */ \ - linenoiseHistoryAdd(lua_tostring(L, idx)); /* add it to history */ -#define lua_freeline(L,b) ((void)L, free(b)) +#define lua_readline(L, b, p) ((void)L, ((b) = linenoise(p)) != NULL) +#define lua_saveline(L, idx) \ + if (lua_strlen(L, idx) > 0) /* non-empty line? */ \ + linenoiseHistoryAdd(lua_tostring(L, idx)); /* add it to history */ +#define lua_freeline(L, b) ((void)L, free(b)) #else -#define lua_readline(L,b,p) \ - ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \ - fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */ -#define lua_saveline(L,idx) { (void)L; (void)idx; } -#define lua_freeline(L,b) { (void)L; (void)b; } +#define lua_readline(L, b, p) \ + ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \ + fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */ +#define lua_saveline(L, idx) \ + { \ + (void)L; \ + (void)idx; \ + } +#define lua_freeline(L, b) \ + { \ + (void)L; \ + (void)b; \ + } #endif -static void l_message (const char *pname, const char *msg) { - if (pname) fprintf(stderr, "%s: ", pname); - fprintf(stderr, "%s\n", msg); - fflush(stderr); +static void l_message(const char *pname, const char *msg) { + if (pname) fprintf(stderr, "%s: ", pname); + fprintf(stderr, "%s\n", msg); + fflush(stderr); } -static int report (lua_State *L, int status) { - if (status && !lua_isnil(L, -1)) { - const char *msg = lua_tostring(L, -1); - if (msg == NULL) msg = "(error object is not a string)"; - l_message(progname, msg); - lua_pop(L, 1); - } - return status; +static int report(lua_State *L, int status) { + if (status && !lua_isnil(L, -1)) { + const char *msg = lua_tostring(L, -1); + if (msg == NULL) msg = "(error object is not a string)"; + l_message(progname, msg); + lua_pop(L, 1); + } + return status; } -static int incomplete (lua_State *L, int status) { - if (status == LUA_ERRSYNTAX) { - size_t lmsg; - const char *msg = lua_tolstring(L, -1, &lmsg); - const char *tp = msg + lmsg - (sizeof("''") - 1); - if (strstr(msg, "''") == tp) { - lua_pop(L, 1); - return 1; +static int incomplete(lua_State *L, int status) { + if (status == LUA_ERRSYNTAX) { + size_t lmsg; + const char *msg = lua_tolstring(L, -1, &lmsg); + const char *tp = msg + lmsg - (sizeof("''") - 1); + if (strstr(msg, "''") == tp) { + lua_pop(L, 1); + return 1; + } } - } - return 0; /* else... */ + return 0; /* else... */ } -static int getargs (lua_State *L, char **argv, int n) { - int narg; - int i; - int argc = 0; - while (argv[argc]) argc++; /* count total number of arguments */ - narg = argc - (n + 1); /* number of arguments to the script */ - luaL_checkstack(L, narg + 3, "too many arguments to script"); - for (i=n+1; i < argc; i++) - lua_pushstring(L, argv[i]); - lua_createtable(L, narg, n + 1); - for (i=0; i < argc; i++) { - lua_pushstring(L, argv[i]); - lua_rawseti(L, -2, i - n); - } - return narg; +static int getargs(lua_State *L, char **argv, int n) { + int narg; + int i; + int argc = 0; + while (argv[argc]) argc++; /* count total number of arguments */ + narg = argc - (n + 1); /* number of arguments to the script */ + luaL_checkstack(L, narg + 3, "too many arguments to script"); + for (i = n + 1; i < argc; i++) lua_pushstring(L, argv[i]); + lua_createtable(L, narg, n + 1); + for (i = 0; i < argc; i++) { + lua_pushstring(L, argv[i]); + lua_rawseti(L, -2, i - n); + } + return narg; } #define LUA_MAXINPUT 512 -#define LUA_PROMPT "> " +#define LUA_PROMPT "> " #define LUA_PROMPT2 ">> " -static const char *get_prompt (lua_State *L, int firstline) { - const char *p; - lua_getfield(L, LUA_GLOBALSINDEX, firstline ? "_PROMPT" : "_PROMPT2"); - p = lua_tostring(L, -1); - if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2); - lua_pop(L, 1); /* remove global */ - return p; +static const char *get_prompt(lua_State *L, int firstline) { + const char *p; + lua_getfield(L, LUA_GLOBALSINDEX, firstline ? "_PROMPT" : "_PROMPT2"); + p = lua_tostring(L, -1); + if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2); + lua_pop(L, 1); /* remove global */ + return p; } -static int pushline (lua_State *L, int firstline) { - char buffer[LUA_MAXINPUT]; - char *b = buffer; - size_t l; - const char *prmt = get_prompt(L, firstline); - if (lua_readline(L, b, prmt) == 0) - return 0; /* no input */ - l = strlen(b); - if (l > 0 && b[l-1] == '\n') /* line ends with newline? */ - b[l-1] = '\0'; /* remove it */ - if (firstline && b[0] == '=') /* first line starts with `=' ? */ - lua_pushfstring(L, "return %s", b+1); /* change it to `return' */ - else - lua_pushstring(L, b); - lua_saveline(L, -1); - lua_freeline(L, b); - return 1; +static int pushline(lua_State *L, int firstline) { + char buffer[LUA_MAXINPUT]; + char *b = buffer; + size_t l; + const char *prmt = get_prompt(L, firstline); + if (lua_readline(L, b, prmt) == 0) return 0; /* no input */ + l = strlen(b); + if (l > 0 && b[l - 1] == '\n') /* line ends with newline? */ + b[l - 1] = '\0'; /* remove it */ + if (firstline && b[0] == '=') /* first line starts with `=' ? */ + lua_pushfstring(L, "return %s", b + 1); /* change it to `return' */ + else + lua_pushstring(L, b); + lua_saveline(L, -1); + lua_freeline(L, b); + return 1; } -static int loadline (lua_State *L) { - int status; - lua_settop(L, 0); - if (!pushline(L, 1)) - return -1; /* no input */ - for (;;) { /* repeat until gets a complete line */ - status = terra_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "stdin"); - if (!incomplete(L, status)) break; /* cannot try to add lines? */ - if (!pushline(L, 0)) /* no more input? */ - return -1; - lua_pushliteral(L, "\n"); /* add a new line... */ - lua_insert(L, -2); /* ...between the two lines */ - lua_concat(L, 3); /* join them */ - } - lua_remove(L, 1); /* remove line */ - return status; +static int loadline(lua_State *L) { + int status; + lua_settop(L, 0); + if (!pushline(L, 1)) return -1; /* no input */ + for (;;) { /* repeat until gets a complete line */ + status = terra_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "stdin"); + if (!incomplete(L, status)) break; /* cannot try to add lines? */ + if (!pushline(L, 0)) /* no more input? */ + return -1; + lua_pushliteral(L, "\n"); /* add a new line... */ + lua_insert(L, -2); /* ...between the two lines */ + lua_concat(L, 3); /* join them */ + } + lua_remove(L, 1); /* remove line */ + return status; } -static int traceback (lua_State *L) { - if (!lua_isstring(L, 1)) /* 'message' not a string? */ - return 1; /* keep it intact */ - lua_getfield(L, LUA_GLOBALSINDEX, "debug"); - if (!lua_istable(L, -1)) { - lua_pop(L, 1); - return 1; - } - lua_getfield(L, -1, "traceback"); - if (!lua_isfunction(L, -1)) { - lua_pop(L, 2); +static int traceback(lua_State *L) { + if (!lua_isstring(L, 1)) /* 'message' not a string? */ + return 1; /* keep it intact */ + lua_getfield(L, LUA_GLOBALSINDEX, "debug"); + if (!lua_istable(L, -1)) { + lua_pop(L, 1); + return 1; + } + lua_getfield(L, -1, "traceback"); + if (!lua_isfunction(L, -1)) { + lua_pop(L, 2); + return 1; + } + lua_pushvalue(L, 1); /* pass error message */ + lua_pushinteger(L, 2); /* skip this function and traceback */ + lua_call(L, 2, 1); /* call debug.traceback */ return 1; - } - lua_pushvalue(L, 1); /* pass error message */ - lua_pushinteger(L, 2); /* skip this function and traceback */ - lua_call(L, 2, 1); /* call debug.traceback */ - return 1; } static lua_State *globalL = NULL; -static void lstop (lua_State *L, lua_Debug *ar) { - (void)ar; /* unused arg. */ - lua_sethook(L, NULL, 0, 0); - luaL_error(L, "interrupted!"); +static void lstop(lua_State *L, lua_Debug *ar) { + (void)ar; /* unused arg. */ + lua_sethook(L, NULL, 0, 0); + luaL_error(L, "interrupted!"); } -static void laction (int i) { - signal(i, SIG_DFL); /* if another SIGINT happens before lstop, - terminate process (default action) */ - lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); +static void laction(int i) { + signal(i, SIG_DFL); /* if another SIGINT happens before lstop, + terminate process (default action) */ + lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); } - -static int docall (lua_State *L, int narg, int clear) { - int status; - globalL = L; - int base = lua_gettop(L) - narg; /* function index */ - lua_pushcfunction(L, traceback); /* push traceback function */ - lua_insert(L, base); /* put it under chunk and args */ - signal(SIGINT, laction); - status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base); - signal(SIGINT, SIG_DFL); - lua_remove(L, base); /* remove traceback function */ - /* force a complete garbage collection in case of errors */ - if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0); - return status; +static int docall(lua_State *L, int narg, int clear) { + int status; + globalL = L; + int base = lua_gettop(L) - narg; /* function index */ + lua_pushcfunction(L, traceback); /* push traceback function */ + lua_insert(L, base); /* put it under chunk and args */ + signal(SIGINT, laction); + status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base); + signal(SIGINT, SIG_DFL); + lua_remove(L, base); /* remove traceback function */ + /* force a complete garbage collection in case of errors */ + if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0); + return status; } static void print_welcome() { printf("\n" "Terra -- A low-level counterpart to Lua\n" - "Release " TERRA_VERSION_STRING "\n" + "Release " TERRA_VERSION_STRING + "\n" "\n" "Stanford University\n" "zdevito@stanford.edu\n" "\n"); } -static void dotty (lua_State *L) { - int status; - print_welcome(); - while ((status = loadline(L)) != -1) { - if (status == 0) status = docall(L, 0, 0); - report(L,status); - if (status == 0 && lua_gettop(L) > 0) { /* any result to print? */ - lua_getglobal(L, "print"); - lua_insert(L, 1); - if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0) - lua_pushfstring(L, - "error calling " LUA_QL("print") " (%s)", - lua_tostring(L, -1)); - report(L,status); +static void dotty(lua_State *L) { + int status; + print_welcome(); + while ((status = loadline(L)) != -1) { + if (status == 0) status = docall(L, 0, 0); + report(L, status); + if (status == 0 && lua_gettop(L) > 0) { /* any result to print? */ + lua_getglobal(L, "print"); + lua_insert(L, 1); + if (lua_pcall(L, lua_gettop(L) - 1, 0, 0) != 0) + lua_pushfstring(L, "error calling " LUA_QL("print") " (%s)", + lua_tostring(L, -1)); + report(L, status); + } } - } - lua_settop(L, 0); /* clear stack */ - fputs("\n", stdout); - fflush(stdout); + lua_settop(L, 0); /* clear stack */ + fputs("\n", stdout); + fflush(stdout); } #if 0 diff --git a/src/tcompiler.cpp b/src/tcompiler.cpp index d7c6762c5..f3d0d53b2 100644 --- a/src/tcompiler.cpp +++ b/src/tcompiler.cpp @@ -25,7 +25,7 @@ extern "C" { #include #include "llvmheaders.h" -#include "tcompilerstate.h" //definition of terra_CompilerState which contains LLVM state +#include "tcompilerstate.h" //definition of terra_CompilerState which contains LLVM state #include "tobj.h" #include "tinline.h" #include "llvm/Support/ManagedStatic.h" @@ -42,28 +42,29 @@ extern "C" { using namespace llvm; - -#define TERRALIB_FUNCTIONS(_) \ - _(inittarget,1) \ - _(freetarget,0) \ - _(initcompilationunit,1) \ - _(compilationunitaddvalue,1) /*entry point from lua into compiler to generate LLVM for a function, other functions it calls may not yet exist*/\ - _(freecompilationunit,0) \ - _(jit,1) /*entry point from lua into compiler to actually invoke the JIT by calling getPointerToFunction*/\ - _(llvmsizeof,1) \ - _(disassemble,1) \ - _(pointertolightuserdata,0) /*because luajit ffi doesn't do this...*/\ - _(bindtoluaapi,0) \ - _(gcdebug,0) \ - _(saveobjimpl,1) \ - _(linklibraryimpl,1) \ - _(linkllvmimpl,1) \ - _(currenttimeinseconds,0) \ - _(isintegral,0) \ - _(dumpmodule,1) - - -#define DEF_LIBFUNCTION(nm,isclo) static int terra_##nm(lua_State * L); +#define TERRALIB_FUNCTIONS(_) \ + _(inittarget, 1) \ + _(freetarget, 0) \ + _(initcompilationunit, 1) \ + _(compilationunitaddvalue, \ + 1) /*entry point from lua into compiler to generate LLVM for a function, other \ + functions it calls may not yet exist*/ \ + _(freecompilationunit, 0) \ + _(jit, 1) /*entry point from lua into compiler to actually invoke the JIT by calling \ + getPointerToFunction*/ \ + _(llvmsizeof, 1) \ + _(disassemble, 1) \ + _(pointertolightuserdata, 0) /*because luajit ffi doesn't do this...*/ \ + _(bindtoluaapi, 0) \ + _(gcdebug, 0) \ + _(saveobjimpl, 1) \ + _(linklibraryimpl, 1) \ + _(linkllvmimpl, 1) \ + _(currenttimeinseconds, 0) \ + _(isintegral, 0) \ + _(dumpmodule, 1) + +#define DEF_LIBFUNCTION(nm, isclo) static int terra_##nm(lua_State *L); TERRALIB_FUNCTIONS(DEF_LIBFUNCTION) #undef DEF_LIBFUNCTION @@ -86,30 +87,28 @@ static llvm_shutdown_obj llvmshutdownobj; #endif struct DisassembleFunctionListener : public JITEventListener { - TerraCompilationUnit * CU; - terra_State * T; - DisassembleFunctionListener(TerraCompilationUnit * CU_) - : CU(CU_), T(CU_->T) {} - virtual void NotifyFunctionEmitted (const Function & f, void * data, size_t sz, const EmittedFunctionDetails & EFD) { - TerraFunctionInfo & fi = T->C->functioninfo[data]; + TerraCompilationUnit *CU; + terra_State *T; + DisassembleFunctionListener(TerraCompilationUnit *CU_) : CU(CU_), T(CU_->T) {} + virtual void NotifyFunctionEmitted(const Function &f, void *data, size_t sz, + const EmittedFunctionDetails &EFD) { + TerraFunctionInfo &fi = T->C->functioninfo[data]; fi.ctx = CU->TT->ctx; fi.name = f.getName(); fi.addr = data; fi.size = sz; - DEBUG_ONLY(T) { - fi.efd = EFD; - } + DEBUG_ONLY(T) { fi.efd = EFD; } } #if LLVM_VERSION >= 34 void InitializeDebugData(StringRef name, object::SymbolRef::Type type, uint64_t sz) { - if(type == object::SymbolRef::ST_Function) { - #if !defined(__arm__) && !defined(__linux__) && !defined(__FreeBSD__) + if (type == object::SymbolRef::ST_Function) { +#if !defined(__arm__) && !defined(__linux__) && !defined(__FreeBSD__) name = name.substr(1); - #endif - void * addr = (void*) CU->ee->getFunctionAddress(name); - if(addr) { +#endif + void *addr = (void *)CU->ee->getFunctionAddress(name); + if (addr) { assert(addr); - TerraFunctionInfo & fi = T->C->functioninfo[addr]; + TerraFunctionInfo &fi = T->C->functioninfo[addr]; fi.ctx = CU->TT->ctx; fi.name = name; fi.addr = addr; @@ -120,12 +119,12 @@ struct DisassembleFunctionListener : public JITEventListener { #endif #if LLVM_VERSION >= 34 && LLVM_VERSION <= 35 virtual void NotifyObjectEmitted(const ObjectImage &Obj) { - for(object::symbol_iterator I = Obj.begin_symbols(), E = Obj.end_symbols(); - I != E; -#if LLVM_VERSION <=34 - I.increment(err) + for (object::symbol_iterator I = Obj.begin_symbols(), E = Obj.end_symbols(); + I != E; +#if LLVM_VERSION <= 34 + I.increment(err) #else - ++I + ++I #endif ) { StringRef name; @@ -134,13 +133,14 @@ struct DisassembleFunctionListener : public JITEventListener { I->getName(name); I->getType(t); I->getSize(sz); - InitializeDebugData(name,t,sz); + InitializeDebugData(name, t, sz); } } #elif LLVM_VERSION == 36 - virtual void NotifyObjectEmitted(const object::ObjectFile &Obj, const RuntimeDyld::LoadedObjectInfo &L) { - for(auto I = Obj.symbol_begin(), E = Obj.symbol_end(); I != E; ++I) { - object::SymbolRef sym(I->getRawDataRefImpl(),&Obj); + virtual void NotifyObjectEmitted(const object::ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &L) { + for (auto I = Obj.symbol_begin(), E = Obj.symbol_end(); I != E; ++I) { + object::SymbolRef sym(I->getRawDataRefImpl(), &Obj); StringRef name; object::SymbolRef::Type t; uint64_t sz; @@ -151,33 +151,31 @@ struct DisassembleFunctionListener : public JITEventListener { } } #else - virtual void NotifyObjectEmitted(const object::ObjectFile &Obj, const RuntimeDyld::LoadedObjectInfo &L) { + virtual void NotifyObjectEmitted(const object::ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &L) { auto size_map = llvm::object::computeSymbolSizes(Obj); - for(auto & S : size_map) { + for (auto &S : size_map) { object::SymbolRef sym = S.first; #if LLVM_VERSION < 39 - InitializeDebugData(sym.getName().get(),sym.getType(),S.second); + InitializeDebugData(sym.getName().get(), sym.getType(), S.second); #else auto name = sym.getName(); auto type = sym.getType(); - if(name && type) - InitializeDebugData(name.get(),type.get(),S.second); + if (name && type) InitializeDebugData(name.get(), type.get(), S.second); #endif } } #endif }; - #if LLVM_VERSION > 40 class TerraSectionMemoryManager : public SectionMemoryManager { - - public: - +public: #if LLVM_VERSION > 50 - TerraSectionMemoryManager(TerraCompilationUnit * CU_in, MemoryMapper *MM = nullptr) : SectionMemoryManager(MM) { + TerraSectionMemoryManager(TerraCompilationUnit *CU_in, MemoryMapper *MM = nullptr) + : SectionMemoryManager(MM) { #else - TerraSectionMemoryManager(TerraCompilationUnit * CU_in) : SectionMemoryManager() { + TerraSectionMemoryManager(TerraCompilationUnit *CU_in) : SectionMemoryManager() { #endif CU = CU_in; } @@ -185,95 +183,97 @@ class TerraSectionMemoryManager : public SectionMemoryManager { TerraSectionMemoryManager(const TerraSectionMemoryManager &) = delete; void operator=(const TerraSectionMemoryManager &) = delete; - void notifyObjectLoaded (ExecutionEngine *EE, const object::ObjectFile &obj) override { + void notifyObjectLoaded(ExecutionEngine *EE, const object::ObjectFile &obj) override { auto size_map = llvm::object::computeSymbolSizes(obj); - for(auto & S : size_map) { + for (auto &S : size_map) { object::SymbolRef sym = S.first; auto name = sym.getName(); auto type = sym.getType(); - // printf("notify: %s %d %#010llx\n", cantFail(std::move(name)).data(), cantFail(std::move(type)), S.second); - if(name && type) - static_cast(CU->jiteventlistener)->InitializeDebugData(name.get(),type.get(),S.second); + // printf("notify: %s %d %#010llx\n", cantFail(std::move(name)).data(), + // cantFail(std::move(type)), S.second); + if (name && type) + static_cast(CU->jiteventlistener) + ->InitializeDebugData(name.get(), type.get(), S.second); } } - private: - - TerraCompilationUnit * CU; +private: + TerraCompilationUnit *CU; }; #endif static double CurrentTimeInSeconds() { #ifdef _WIN32 static uint64_t freq = 0; - if(freq == 0) { + if (freq == 0) { LARGE_INTEGER i; QueryPerformanceFrequency(&i); freq = i.QuadPart; } LARGE_INTEGER t; QueryPerformanceCounter(&t); - return t.QuadPart / (double) freq; + return t.QuadPart / (double)freq; #else struct timeval tv; gettimeofday(&tv, NULL); return tv.tv_sec + tv.tv_usec / 1000000.0; #endif } -static int terra_currenttimeinseconds(lua_State * L) { +static int terra_currenttimeinseconds(lua_State *L) { lua_pushnumber(L, CurrentTimeInSeconds()); return 1; } -static void AddLLVMOptions(int N,...) { +static void AddLLVMOptions(int N, ...) { va_list ap; va_start(ap, N); std::vector ops; ops.push_back("terra"); - for(int i = 0; i < N; i++) { - const char * arg = va_arg(ap, const char *); + for (int i = 0; i < N; i++) { + const char *arg = va_arg(ap, const char *); ops.push_back(arg); } - cl::ParseCommandLineOptions(N+1, &ops[0]); + cl::ParseCommandLineOptions(N + 1, &ops[0]); } -//useful for debugging GC problems. You can attach it to -static int terra_gcdebug(lua_State * L) { - lua_newuserdata(L,sizeof(void*)); - lua_getfield(L,LUA_GLOBALSINDEX,"terra"); - lua_getfield(L,-1,"llvm_gcdebugmetatable"); - lua_setmetatable(L,-3); - lua_pop(L,1); //the 'terra' table - lua_setfield(L,-2,"llvm_gcdebughandle"); +// useful for debugging GC problems. You can attach it to +static int terra_gcdebug(lua_State *L) { + lua_newuserdata(L, sizeof(void *)); + lua_getfield(L, LUA_GLOBALSINDEX, "terra"); + lua_getfield(L, -1, "llvm_gcdebugmetatable"); + lua_setmetatable(L, -3); + lua_pop(L, 1); // the 'terra' table + lua_setfield(L, -2, "llvm_gcdebughandle"); return 0; } -static void RegisterFunction(struct terra_State * T, const char * name, int isclo, lua_CFunction fn) { - if(isclo) { - lua_pushlightuserdata(T->L,(void*)T); - lua_pushcclosure(T->L,fn,1); +static void RegisterFunction(struct terra_State *T, const char *name, int isclo, + lua_CFunction fn) { + if (isclo) { + lua_pushlightuserdata(T->L, (void *)T); + lua_pushcclosure(T->L, fn, 1); } else { lua_pushcfunction(T->L, fn); } - lua_setfield(T->L,-2,name); + lua_setfield(T->L, -2, name); } static llvm::sys::Mutex terrainitlock; static int terrainitcount; -bool OneTimeInit(struct terra_State * T) { +bool OneTimeInit(struct terra_State *T) { bool success = true; - #if LLVM_VERSION <= 35 +#if LLVM_VERSION <= 35 terrainitlock.acquire(); - #else +#else terrainitlock.lock(); - #endif +#endif terrainitcount++; - if(terrainitcount == 1) { - #ifdef PRINT_LLVM_TIMING_STATS - AddLLVMOptions(1,"-time-passes"); - #endif + if (terrainitcount == 1) { +#ifdef PRINT_LLVM_TIMING_STATS + AddLLVMOptions(1, "-time-passes"); +#endif #ifndef __arm__ - AddLLVMOptions(1,"-x86-asm-syntax=intel"); + AddLLVMOptions(1, "-x86-asm-syntax=intel"); #endif InitializeAllTargets(); InitializeAllTargetInfos(); @@ -281,53 +281,53 @@ bool OneTimeInit(struct terra_State * T) { InitializeAllAsmParsers(); InitializeAllTargetMCs(); } else { - #if LLVM_VERSION <= 34 - if(!llvm_is_multithreaded()) { - if(!llvm_start_multithreaded()) { - terra_pusherror(T,"llvm failed to start multi-threading\n"); +#if LLVM_VERSION <= 34 + if (!llvm_is_multithreaded()) { + if (!llvm_start_multithreaded()) { + terra_pusherror(T, "llvm failed to start multi-threading\n"); success = false; } } - #endif //after 3.5, this isn't needed +#endif // after 3.5, this isn't needed } - #if LLVM_VERSION <= 35 +#if LLVM_VERSION <= 35 terrainitlock.release(); - #else +#else terrainitlock.unlock(); - #endif +#endif return success; } -//LLVM 3.1 doesn't enable avx even if it is present, we detect and force it here +// LLVM 3.1 doesn't enable avx even if it is present, we detect and force it here bool HostHasAVX() { StringMap Features; sys::getHostCPUFeatures(Features); return Features["avx"]; } -int terra_inittarget(lua_State * L) { - terra_State * T = terra_getstate(L, 1); - TerraTarget * TT = new TerraTarget(); +int terra_inittarget(lua_State *L) { + terra_State *T = terra_getstate(L, 1); + TerraTarget *TT = new TerraTarget(); TT->id = T->targets.size(); T->targets.push_back(TT); TT->nreferences = 2; - if(!lua_isnil(L, 1)) { - TT->Triple = lua_tostring(L,1); + if (!lua_isnil(L, 1)) { + TT->Triple = lua_tostring(L, 1); } else { - #if LLVM_VERSION >= 33 +#if LLVM_VERSION >= 33 TT->Triple = llvm::sys::getProcessTriple(); - #else +#else TT->Triple = llvm::sys::getDefaultTargetTriple(); - #endif +#endif } - if(!lua_isnil(L, 2)) - TT->CPU = lua_tostring(L,2); + if (!lua_isnil(L, 2)) + TT->CPU = lua_tostring(L, 2); else TT->CPU = llvm::sys::getHostCPUName(); - - if(!lua_isnil(L, 3)) - TT->Features = lua_tostring(L,3); + + if (!lua_isnil(L, 3)) + TT->Features = lua_tostring(L, 3); else { // LLVM 3.8 generates invalid AVX instructions on Skylake processors // detect that situation and force AVX off in that case @@ -336,7 +336,7 @@ int terra_inittarget(lua_State * L) { #else #if LLVM_VERSION == 38 std::string cpu_name = llvm::sys::getHostCPUName(); - if(cpu_name == "skylake") + if (cpu_name == "skylake") TT->Features = "-avx"; else TT->Features = HostHasAVX() ? "+avx" : ""; @@ -345,191 +345,193 @@ int terra_inittarget(lua_State * L) { #endif #endif } - + TargetOptions options; DEBUG_ONLY(T) { - #if LLVM_VERSION <= 36 +#if LLVM_VERSION <= 36 options.NoFramePointerElim = true; - #endif +#endif } - - if(lua_toboolean(L,4)) { //FloatABIHard boolean + + if (lua_toboolean(L, 4)) { // FloatABIHard boolean options.FloatABIType = FloatABI::Hard; } else { - #ifdef __arm__ - //force hard float since we currently onlly work on platforms that have it - options->FloatABIType = FloatABI::Hard; - #endif +#ifdef __arm__ + // force hard float since we currently onlly work on platforms that have it + options->FloatABIType = FloatABI::Hard; +#endif } - + TT->next_unused_id = 0; TT->ctx = new LLVMContext(); std::string err; const Target *TheTarget = TargetRegistry::lookupTarget(TT->Triple, err); - if(!TheTarget) { - luaL_error(L,"failed to initialize target for LLVM Triple: %s (%s)",TT->Triple.c_str(),err.c_str()); + if (!TheTarget) { + luaL_error(L, "failed to initialize target for LLVM Triple: %s (%s)", + TT->Triple.c_str(), err.c_str()); } - TT->tm = TheTarget->createTargetMachine(TT->Triple, TT->CPU, TT->Features, options, + TT->tm = TheTarget->createTargetMachine( + TT->Triple, TT->CPU, TT->Features, options, #if defined(__linux__) || defined(__unix__) || (LLVM_VERSION < 50) - Reloc::PIC_, + Reloc::PIC_, #else - Optional(), + Optional(), #endif #if defined(__powerpc64__) - // On PPC the small model is limited to 16bit offsets - CodeModel::Medium, + // On PPC the small model is limited to 16bit offsets + CodeModel::Medium, #else - // Use small model so that we can use signed 32bits offset in the function and GV tables - CodeModel::Small, + // Use small model so that we can use signed 32bits offset in the function and + // GV tables + CodeModel::Small, #endif - CodeGenOpt::Aggressive); - TT->external = new Module("external",*TT->ctx); + CodeGenOpt::Aggressive); + TT->external = new Module("external", *TT->ctx); TT->external->setTargetTriple(TT->Triple); lua_pushlightuserdata(L, TT); return 1; } -int terra_initcompilationunit(lua_State * L) { - terra_State * T = terra_getstate(L, 1); - TerraCompilationUnit * CU = new TerraCompilationUnit(); - TerraTarget * TT = (TerraTarget*)terra_tocdatapointer(L, 1); +int terra_initcompilationunit(lua_State *L) { + terra_State *T = terra_getstate(L, 1); + TerraCompilationUnit *CU = new TerraCompilationUnit(); + TerraTarget *TT = (TerraTarget *)terra_tocdatapointer(L, 1); CU->TT = TT; CU->TT->nreferences++; CU->nreferences = 1; CU->T = T; CU->C = T->C; CU->C->nreferences++; - CU->optimize = lua_toboolean(L,2); - - CU->M = new Module("terra",*TT->ctx); + CU->optimize = lua_toboolean(L, 2); + + CU->M = new Module("terra", *TT->ctx); CU->M->setTargetTriple(TT->Triple); - #if LLVM_VERSION >= 38 +#if LLVM_VERSION >= 38 CU->M->setDataLayout(TT->tm->createDataLayout()); - #elif LLVM_VERSION == 37 +#elif LLVM_VERSION == 37 CU->M->setDataLayout(*TT->tm->getDataLayout()); - #else +#else CU->M->setDataLayout(TT->tm->getDataLayout()); - #endif - - CU->mi = new ManualInliner(TT->tm,CU->M); +#endif + + CU->mi = new ManualInliner(TT->tm, CU->M); CU->fpm = new FunctionPassManagerT(CU->M); llvmutil_addtargetspecificpasses(CU->fpm, TT->tm); llvmutil_addoptimizationpasses(CU->fpm); - CU->fpm->doInitialization(); + CU->fpm->doInitialization(); lua_pushlightuserdata(L, CU); return 1; } -static void InitializeJIT(TerraCompilationUnit * CU) { - if(CU->ee) return; //already initialized - Module * topeemodule = (CU->T->options.usemcjit) ? new Module("terra",*CU->TT->ctx) : CU->M; +static void InitializeJIT(TerraCompilationUnit *CU) { + if (CU->ee) return; // already initialized + Module *topeemodule = + (CU->T->options.usemcjit) ? new Module("terra", *CU->TT->ctx) : CU->M; #ifdef _WIN32 - std::string MCJITTriple = CU->TT->Triple; - MCJITTriple.append("-elf"); //on windows we need to use an elf container because coff is not supported yet - topeemodule->setTargetTriple(MCJITTriple); + std::string MCJITTriple = CU->TT->Triple; + MCJITTriple.append("-elf"); // on windows we need to use an elf container because + // coff is not supported yet + topeemodule->setTargetTriple(MCJITTriple); #else topeemodule->setTargetTriple(CU->TT->Triple); #endif - + std::string err; std::vector mattrs; - if(!CU->TT->Features.empty()) - mattrs.push_back(CU->TT->Features); - EngineBuilder eb(UNIQUEIFY(Module,topeemodule)); + if (!CU->TT->Features.empty()) mattrs.push_back(CU->TT->Features); + EngineBuilder eb(UNIQUEIFY(Module, topeemodule)); eb.setErrorStr(&err) - .setMCPU(CU->TT->CPU) - .setMAttrs(mattrs) - .setEngineKind(EngineKind::JIT) + .setMCPU(CU->TT->CPU) + .setMAttrs(mattrs) + .setEngineKind(EngineKind::JIT) #ifdef TERRA_CAN_USE_OLD_JIT - .setAllocateGVsWithCode(false) - .setUseMCJIT(CU->T->options.usemcjit) + .setAllocateGVsWithCode(false) + .setUseMCJIT(CU->T->options.usemcjit) #endif - .setTargetOptions(CU->TT->tm->Options) + .setTargetOptions(CU->TT->tm->Options) #if LLVM_VERSION < 50 - .setOptLevel(CodeGenOpt::Aggressive); + .setOptLevel(CodeGenOpt::Aggressive); #else - .setOptLevel(CodeGenOpt::Aggressive) - .setMCJITMemoryManager(make_unique(CU)) - .setUseOrcMCJITReplacement(true); + .setOptLevel(CodeGenOpt::Aggressive) + .setMCJITMemoryManager(make_unique(CU)) + .setUseOrcMCJITReplacement(true); #endif CU->ee = eb.create(); - if (!CU->ee) - terra_reporterror(CU->T,"llvm: %s\n",err.c_str()); + if (!CU->ee) terra_reporterror(CU->T, "llvm: %s\n", err.c_str()); CU->jiteventlistener = new DisassembleFunctionListener(CU); #if LLVM_VERSION < 50 CU->ee->RegisterJITEventListener(CU->jiteventlistener); #endif } -int terra_compilerinit(struct terra_State * T) { - if(!OneTimeInit(T)) - return LUA_ERRRUN; - lua_getfield(T->L,LUA_GLOBALSINDEX,"terra"); - - #define REGISTER_FN(name,isclo) RegisterFunction(T,#name,isclo,terra_##name); +int terra_compilerinit(struct terra_State *T) { + if (!OneTimeInit(T)) return LUA_ERRRUN; + lua_getfield(T->L, LUA_GLOBALSINDEX, "terra"); + +#define REGISTER_FN(name, isclo) RegisterFunction(T, #name, isclo, terra_##name); TERRALIB_FUNCTIONS(REGISTER_FN) - #undef REGISTER_FN +#undef REGISTER_FN + + lua_pushnumber(T->L, LLVM_VERSION); + lua_setfield(T->L, -2, "llvmversion"); + + lua_pop(T->L, 1); // remove terra from stack - lua_pushnumber(T->L,LLVM_VERSION); - lua_setfield(T->L,-2, "llvmversion"); - - lua_pop(T->L,1); //remove terra from stack - T->C = new terra_CompilerState(); memset(T->C, 0, sizeof(terra_CompilerState)); T->C->nreferences = 1; #ifndef TERRA_CAN_USE_OLD_JIT - T->options.usemcjit = 1; //force mcjit use, since old JIT is no longer supported. + T->options.usemcjit = 1; // force mcjit use, since old JIT is no longer supported. #endif - if(T->options.usemcjit) { + if (T->options.usemcjit) { #ifndef TERRA_CAN_USE_MCJIT - terra_pusherror(T, "mcjit is not supported using LLVM %d",LLVM_VERSION); + terra_pusherror(T, "mcjit is not supported using LLVM %d", LLVM_VERSION); return LUA_ERRRUN; #endif } return 0; } -void freetarget(TerraTarget * TT) { +void freetarget(TerraTarget *TT) { assert(TT->nreferences > 0); - if(0 == --TT->nreferences) { + if (0 == --TT->nreferences) { delete TT->external; delete TT->tm; delete TT->ctx; delete TT; } } -int terra_freetarget(lua_State * L) { - freetarget((TerraTarget *) terra_tocdatapointer(L,1)); +int terra_freetarget(lua_State *L) { + freetarget((TerraTarget *)terra_tocdatapointer(L, 1)); return 0; } -static void freecompilationunit(TerraCompilationUnit * CU) { +static void freecompilationunit(TerraCompilationUnit *CU) { assert(CU->nreferences > 0); - if(0 == --CU->nreferences) { + if (0 == --CU->nreferences) { delete CU->mi; delete CU->fpm; - if(CU->ee) { + if (CU->ee) { CU->ee->UnregisterJITEventListener(CU->jiteventlistener); delete CU->jiteventlistener; delete CU->ee; } - if(CU->T->options.usemcjit || !CU->ee) //we own the module so we delete it + if (CU->T->options.usemcjit || !CU->ee) // we own the module so we delete it delete CU->M; freetarget(CU->TT); - terra_compilerfree(CU->C); //decrement reference count to compiler + terra_compilerfree(CU->C); // decrement reference count to compiler delete CU; } } -int terra_freecompilationunit(lua_State * L) { - freecompilationunit((TerraCompilationUnit *) terra_tocdatapointer(L,1)); +int terra_freecompilationunit(lua_State *L) { + freecompilationunit((TerraCompilationUnit *)terra_tocdatapointer(L, 1)); return 0; } -int terra_compilerfree(struct terra_CompilerState * C) { +int terra_compilerfree(struct terra_CompilerState *C) { assert(C->nreferences > 0); - if(0 == --C->nreferences) { - if(C->MB.base() != NULL) { + if (0 == --C->nreferences) { + if (C->MB.base() != NULL) { llvm::sys::Memory::releaseMappedMemory(C->MB); } C->functioninfo.clear(); @@ -538,54 +540,59 @@ int terra_compilerfree(struct terra_CompilerState * C) { return 0; } -static void GetStructEntries(Obj * typ, Obj * entries) { +static void GetStructEntries(Obj *typ, Obj *entries) { Obj layout; - if(!typ->obj("cachedlayout",&layout)) { + if (!typ->obj("cachedlayout", &layout)) { assert(!"typechecked failed to complete type needed by the compiler, this is a bug."); } - layout.obj("entries",entries); + layout.obj("entries", entries); } -struct TType { //contains llvm raw type pointer and any metadata about it we need - Type * type; +struct TType { // contains llvm raw type pointer and any metadata about it we need + Type *type; bool issigned; bool islogical; - bool incomplete; // does this aggregate type or its children include an incomplete struct + bool incomplete; // does this aggregate type or its children include an incomplete + // struct }; class Types { - TerraCompilationUnit * CU; - terra_State * T; - TType * GetIncomplete(Obj * typ) { - TType * t = NULL; - if(!LookupTypeCache(typ, &t)) { + TerraCompilationUnit *CU; + terra_State *T; + TType *GetIncomplete(Obj *typ) { + TType *t = NULL; + if (!LookupTypeCache(typ, &t)) { assert(t); - switch(typ->kind("kind")) { + switch (typ->kind("kind")) { case T_pointer: { Obj base; - typ->obj("type",&base); - Type * baset = (base.kind("kind") == T_functype) ? Type::getInt8Ty(*CU->TT->ctx) : GetIncomplete(&base)->type; - t->type = PointerType::get(baset,typ->number("addressspace")); + typ->obj("type", &base); + Type *baset = (base.kind("kind") == T_functype) + ? Type::getInt8Ty(*CU->TT->ctx) + : GetIncomplete(&base)->type; + t->type = PointerType::get(baset, typ->number("addressspace")); } break; case T_array: { Obj base; - typ->obj("type",&base); + typ->obj("type", &base); int N = typ->number("N"); - TType * baset = GetIncomplete(&base); + TType *baset = GetIncomplete(&base); t->type = ArrayType::get(baset->type, N); t->incomplete = baset->incomplete; } break; case T_struct: { - StructType * st = CreateStruct(typ); + StructType *st = CreateStruct(typ); t->type = st; t->incomplete = st->isOpaque(); } break; case T_vector: { Obj base; - typ->obj("type",&base); + typ->obj("type", &base); int N = typ->number("N"); - TType * ttype = GetIncomplete(&base); //vectors can only contain primitives, so the type must be complete - Type * baseType = ttype->type; + TType *ttype = + GetIncomplete(&base); // vectors can only contain primitives, + // so the type must be complete + Type *baseType = ttype->type; t->issigned = ttype->issigned; t->islogical = ttype->islogical; t->type = VectorType::get(baseType, N); @@ -600,19 +607,20 @@ class Types { t->type = Type::getInt8Ty(*CU->TT->ctx); } break; default: { - printf("kind = %d, %s\n",typ->kind("kind"),tkindtostr(typ->kind("kind"))); - terra_reporterror(T,"type not understood or not primitive\n"); + printf("kind = %d, %s\n", typ->kind("kind"), + tkindtostr(typ->kind("kind"))); + terra_reporterror(T, "type not understood or not primitive\n"); } break; } } assert(t && t->type); return t; } - void CreatePrimitiveType(Obj * typ, TType * t) { + void CreatePrimitiveType(Obj *typ, TType *t) { int bytes = typ->number("bytes"); - switch(typ->kind("type")) { + switch (typ->kind("type")) { case T_float: { - if(bytes == 4) { + if (bytes == 4) { t->type = Type::getFloatTy(*CU->TT->ctx); } else { assert(bytes == 8); @@ -621,45 +629,46 @@ class Types { } break; case T_integer: { t->issigned = typ->boolean("signed"); - t->type = Type::getIntNTy(*CU->TT->ctx,bytes * 8); + t->type = Type::getIntNTy(*CU->TT->ctx, bytes * 8); } break; case T_logical: { t->type = Type::getInt8Ty(*CU->TT->ctx); t->islogical = true; } break; default: { - printf("kind = %d, %s\n",typ->kind("kind"),tkindtostr(typ->kind("type"))); - terra_reporterror(T,"type not understood"); + printf("kind = %d, %s\n", typ->kind("kind"), + tkindtostr(typ->kind("type"))); + terra_reporterror(T, "type not understood"); } break; } } - Type * FunctionPointerType() { - return Type::getInt8PtrTy(*CU->TT->ctx); - } - bool LookupTypeCache(Obj * typ, TType ** t) { - *t = (TType*) CU->symbols->getud(typ); //try to look up the cached type - if(*t == NULL) { + Type *FunctionPointerType() { return Type::getInt8PtrTy(*CU->TT->ctx); } + bool LookupTypeCache(Obj *typ, TType **t) { + *t = (TType *)CU->symbols->getud(typ); // try to look up the cached type + if (*t == NULL) { CU->symbols->push(); typ->push(); - *t = (TType*) lua_newuserdata(T->L,sizeof(TType)); - lua_settable(T->L,-3); - lua_pop(T->L,1); - memset(*t,0,sizeof(TType)); + *t = (TType *)lua_newuserdata(T->L, sizeof(TType)); + lua_settable(T->L, -3); + lua_pop(T->L, 1); + memset(*t, 0, sizeof(TType)); assert(*t != NULL); return false; } return true; } - StructType * CreateStruct(Obj * typ) { - //check to see if it was initialized externally first - if(typ->boolean("llvm_definingfunction")) { - const char * name = typ->string("llvm_definingfunction"); + StructType *CreateStruct(Obj *typ) { + // check to see if it was initialized externally first + if (typ->boolean("llvm_definingfunction")) { + const char *name = typ->string("llvm_definingfunction"); size_t target_id = typ->number("llvm_definingtarget"); - TerraTarget * TT = T->targets[target_id]; + TerraTarget *TT = T->targets[target_id]; assert(TT); - Function * df = TT->external->getFunction(name); assert(df); + Function *df = TT->external->getFunction(name); + assert(df); int argpos = typ->number("llvm_argumentposition"); - StructType * st = cast(df->getFunctionType()->getParamType(argpos)->getPointerElementType()); + StructType *st = cast( + df->getFunctionType()->getParamType(argpos)->getPointerElementType()); assert(st); return st; } @@ -671,52 +680,57 @@ class Types { else return StructType::create(*CU->TT->ctx); } - bool beginsWith(const std::string & s, const std::string & prefix) { - return s.substr(0,prefix.size()) == prefix; + bool beginsWith(const std::string &s, const std::string &prefix) { + return s.substr(0, prefix.size()) == prefix; } - void LayoutStruct(StructType * st, Obj * typ) { + void LayoutStruct(StructType *st, Obj *typ) { Obj layout; - GetStructEntries(typ,&layout); + GetStructEntries(typ, &layout); int N = layout.size(); std::vector entry_types; - - unsigned unionAlign = 0; //minimum union alignment - Type * unionType = NULL; //type with the largest alignment constraint - size_t unionAlignSz = 0; //size of type with largest alignment contraint - size_t unionSz = 0; //allocation size of the largest member - - for(int i = 0; i < N; i++) { + + unsigned unionAlign = 0; // minimum union alignment + Type *unionType = NULL; // type with the largest alignment constraint + size_t unionAlignSz = 0; // size of type with largest alignment contraint + size_t unionSz = 0; // allocation size of the largest member + + for (int i = 0; i < N; i++) { Obj v; layout.objAt(i, &v); Obj vt; - v.obj("type",&vt); - - Type * fieldtype = Get(&vt)->type; + v.obj("type", &vt); + + Type *fieldtype = Get(&vt)->type; bool inunion = v.boolean("inunion"); - if(inunion) { + if (inunion) { unsigned align = CU->getDataLayout().getABITypeAlignment(fieldtype); - if(align >= unionAlign) { // orequal is to make sure we have a non-null type even if it is a 0-sized struct + if (align >= unionAlign) { // orequal is to make sure we have a non-null + // type even if it is a 0-sized struct unionAlign = align; unionType = fieldtype; unionAlignSz = CU->getDataLayout().getTypeAllocSize(fieldtype); } size_t allocSize = CU->getDataLayout().getTypeAllocSize(fieldtype); - if(allocSize > unionSz) - unionSz = allocSize; - - //check if this is the last member of the union, and if it is, add it to our struct + if (allocSize > unionSz) unionSz = allocSize; + + // check if this is the last member of the union, and if it is, add it to + // our struct Obj nextObj; - if(i + 1 < N) - layout.objAt(i+1,&nextObj); - if(i + 1 == N || nextObj.number("allocation") != v.number("allocation")) { + if (i + 1 < N) layout.objAt(i + 1, &nextObj); + if (i + 1 == N || + nextObj.number("allocation") != v.number("allocation")) { std::vector union_types; assert(unionType); union_types.push_back(unionType); - if(unionAlignSz < unionSz) { // the type with the largest alignment requirement is not the type with the largest size, pad this struct so that it will fit the largest type + if (unionAlignSz < + unionSz) { // the type with the largest alignment requirement is + // not the type with the largest size, pad this struct + // so that it will fit the largest type size_t diff = unionSz - unionAlignSz; - union_types.push_back(ArrayType::get(Type::getInt8Ty(*CU->TT->ctx),diff)); + union_types.push_back( + ArrayType::get(Type::getInt8Ty(*CU->TT->ctx), diff)); } - entry_types.push_back(StructType::get(*CU->TT->ctx,union_types)); + entry_types.push_back(StructType::get(*CU->TT->ctx, union_types)); unionAlign = 0; unionType = NULL; unionAlignSz = 0; @@ -733,78 +747,83 @@ class Types { printf("\nEnd Layout\n"); } } + public: - Types(TerraCompilationUnit * CU_) : CU(CU_), T(CU_->T) {} - TType * Get(Obj * typ) { - assert(typ->kind("kind") != T_functype); // Get should not be called on function directly, only function pointers - TType * t = GetIncomplete(typ); - if(t->incomplete) { + Types(TerraCompilationUnit *CU_) : CU(CU_), T(CU_->T) {} + TType *Get(Obj *typ) { + assert(typ->kind("kind") != T_functype); // Get should not be called on function + // directly, only function pointers + TType *t = GetIncomplete(typ); + if (t->incomplete) { assert(t->type->isAggregateType()); - switch(typ->kind("kind")) { + switch (typ->kind("kind")) { case T_struct: { LayoutStruct(cast(t->type), typ); } break; case T_array: { Obj base; - typ->obj("type",&base); - Get(&base); //force base type to be completed + typ->obj("type", &base); + Get(&base); // force base type to be completed } break; default: - terra_reporterror(T,"type marked incomplete is not an array or struct\n"); + terra_reporterror( + T, "type marked incomplete is not an array or struct\n"); } } t->incomplete = false; return t; } - bool IsUnitType(Obj * t) { + bool IsUnitType(Obj *t) { t->pushfield("isunit"); t->push(); - lua_call(T->L,1,1); - bool result = lua_toboolean(T->L,-1); - lua_pop(T->L,1); + lua_call(T->L, 1, 1); + bool result = lua_toboolean(T->L, -1); + lua_pop(T->L, 1); return result; } - void EnsureTypeIsComplete(Obj * typ) { - Get(typ); - } - void EnsurePointsToCompleteType(Obj * ptrTy) { - if(ptrTy->kind("kind") == T_pointer) { + void EnsureTypeIsComplete(Obj *typ) { Get(typ); } + void EnsurePointsToCompleteType(Obj *ptrTy) { + if (ptrTy->kind("kind") == T_pointer) { Obj objTy; - ptrTy->obj("type",&objTy); + ptrTy->obj("type", &objTy); EnsureTypeIsComplete(&objTy); - } //otherwise it is niltype and already complete + } // otherwise it is niltype and already complete } }; -//helper function to alloca at the beginning of function -static AllocaInst *CreateAlloca(IRBuilder<> * B, Type *Ty, Value *ArraySize = 0, const Twine &Name = "") { - BasicBlock * entry = &B->GetInsertBlock()->getParent()->getEntryBlock(); +// helper function to alloca at the beginning of function +static AllocaInst *CreateAlloca(IRBuilder<> *B, Type *Ty, Value *ArraySize = 0, + const Twine &Name = "") { + BasicBlock *entry = &B->GetInsertBlock()->getParent()->getEntryBlock(); IRBuilder<> TmpB(entry, - entry->begin()); //make sure alloca are at the beginning of the function - //this is needed because alloca's that do not dominate the - //function do weird things - return TmpB.CreateAlloca(Ty,ArraySize,Name); + entry->begin()); // make sure alloca are at the beginning of the + // function this is needed because alloca's that do + // not dominate the function do weird things + return TmpB.CreateAlloca(Ty, ArraySize, Name); } - -static Value * CreateConstGEP2_32(IRBuilder<> * B, Value *Ptr, unsigned Idx0, unsigned Idx1) { - #if LLVM_VERSION <= 36 - return B->CreateConstGEP2_32(Ptr,Idx0,Idx1); - #else - return B->CreateConstGEP2_32(Ptr->getType()->getPointerElementType(),Ptr,Idx0,Idx1); - #endif +static Value *CreateConstGEP2_32(IRBuilder<> *B, Value *Ptr, unsigned Idx0, + unsigned Idx1) { +#if LLVM_VERSION <= 36 + return B->CreateConstGEP2_32(Ptr, Idx0, Idx1); +#else + return B->CreateConstGEP2_32(Ptr->getType()->getPointerElementType(), Ptr, Idx0, + Idx1); +#endif } -//functions that handle the details of the x86_64 ABI (this really should be handled by LLVM...) +// functions that handle the details of the x86_64 ABI (this really should be handled by +// LLVM...) struct CCallingConv { - TerraCompilationUnit * CU; - terra_State * T; - lua_State * L; - terra_CompilerState * C; - Types * Ty; - - CCallingConv(TerraCompilationUnit * CU_, Types * Ty_) : CU(CU_), T(CU_->T), L(CU_->T->L), C(CU_->T->C), Ty(Ty_) {} - + TerraCompilationUnit *CU; + terra_State *T; + lua_State *L; + terra_CompilerState *C; + Types *Ty; + + CCallingConv(TerraCompilationUnit *CU_, Types *Ty_) + : CU(CU_), T(CU_->T), L(CU_->T->L), C(CU_->T->C), Ty(Ty_) {} + enum RegisterClass { C_NO_CLASS = 0, C_SSE_FLOAT = 1, @@ -812,87 +831,94 @@ struct CCallingConv { C_INTEGER = 3, C_MEMORY = 4 }; - + enum ArgumentKind { - C_PRIMITIVE, //passed without modifcation (i.e. any non-aggregate type) - C_AGGREGATE_REG, //aggregate passed through registers - C_AGGREGATE_MEM, //aggregate passed through memory + C_PRIMITIVE, // passed without modifcation (i.e. any non-aggregate type) + C_AGGREGATE_REG, // aggregate passed through registers + C_AGGREGATE_MEM, // aggregate passed through memory }; - + struct Argument { ArgumentKind kind; - TType * type; //orignal type for the object - Type * cctype; //if type == C_AGGREGATE_REG, this is a struct that holds a list of the values that goes into the registers - //if type == CC_PRIMITIVE, this is the struct that this type appear in the argument list and the type should be coerced to + TType *type; // orignal type for the object + Type *cctype; // if type == C_AGGREGATE_REG, this is a struct that holds a list + // of the values that goes into the registers if type == + // CC_PRIMITIVE, this is the struct that this type appear in the + // argument list and the type should be coerced to Argument() {} - Argument(ArgumentKind kind, TType * type, Type * cctype = NULL) { + Argument(ArgumentKind kind, TType *type, Type *cctype = NULL) { this->kind = kind; this->type = type; this->cctype = cctype ? cctype : type->type; } int GetNumberOfTypesInParamList() { - if(C_AGGREGATE_REG == this->kind) + if (C_AGGREGATE_REG == this->kind) return cast(this->cctype)->getNumElements(); return 1; } }; - + struct Classification { Argument returntype; std::vector paramtypes; - FunctionType * fntype; + FunctionType *fntype; }; - - RegisterClass Meet(RegisterClass a, RegisterClass b) { - return (a > b) ? a : b; - } - - void MergeValue(RegisterClass * classes, size_t offset, Obj * type) { - Type * t = Ty->Get(type)->type; + + RegisterClass Meet(RegisterClass a, RegisterClass b) { return (a > b) ? a : b; } + + void MergeValue(RegisterClass *classes, size_t offset, Obj *type) { + Type *t = Ty->Get(type)->type; int entry = offset / 8; - if(t->isVectorTy()) //we don't handle structures with vectors in them yet + if (t->isVectorTy()) // we don't handle structures with vectors in them yet classes[entry] = C_MEMORY; - else if(t->isFloatTy()) - classes[entry] = Meet(classes[entry],C_SSE_FLOAT); - else if(t->isDoubleTy()) - classes[entry] = Meet(classes[entry],C_SSE_DOUBLE); - else if(t->isIntegerTy() || t->isPointerTy()) - classes[entry] = Meet(classes[entry],C_INTEGER); - else if(t->isStructTy()) { - StructType * st = cast(Ty->Get(type)->type); + else if (t->isFloatTy()) + classes[entry] = Meet(classes[entry], C_SSE_FLOAT); + else if (t->isDoubleTy()) + classes[entry] = Meet(classes[entry], C_SSE_DOUBLE); + else if (t->isIntegerTy() || t->isPointerTy()) + classes[entry] = Meet(classes[entry], C_INTEGER); + else if (t->isStructTy()) { + StructType *st = cast(Ty->Get(type)->type); assert(!st->isOpaque()); - const StructLayout * sl = CU->getDataLayout().getStructLayout(st); + const StructLayout *sl = CU->getDataLayout().getStructLayout(st); Obj layout; - GetStructEntries(type,&layout); + GetStructEntries(type, &layout); int N = layout.size(); - for(int i = 0; i < N; i++) { + for (int i = 0; i < N; i++) { Obj entry; - layout.objAt(i,&entry); + layout.objAt(i, &entry); int allocation = entry.number("allocation"); size_t structoffset = sl->getElementOffset(allocation); Obj entrytype; - entry.obj("type",&entrytype); + entry.obj("type", &entrytype); MergeValue(classes, offset + structoffset, &entrytype); } - } else if(t->isArrayTy()) { - ArrayType * at = cast(Ty->Get(type)->type); + } else if (t->isArrayTy()) { + ArrayType *at = cast(Ty->Get(type)->type); size_t elemsize = CU->getDataLayout().getTypeAllocSize(at->getElementType()); size_t sz = at->getNumElements(); Obj elemtype; type->obj("type", &elemtype); - for(size_t i = 0; i < sz; i++) + for (size_t i = 0; i < sz; i++) MergeValue(classes, offset + i * elemsize, &elemtype); } else assert(!"unexpected value in classification"); } #ifndef _WIN32 - Type * TypeForClass(size_t size, RegisterClass clz) { - switch(clz) { - case C_SSE_FLOAT: case C_SSE_DOUBLE: - switch(size) { - case 4: return Type::getFloatTy(*CU->TT->ctx); - case 8: return (C_SSE_DOUBLE == clz) ? Type::getDoubleTy(*CU->TT->ctx) : VectorType::get(Type::getFloatTy(*CU->TT->ctx),2); - default: assert(!"unexpected size for floating point class"); + Type *TypeForClass(size_t size, RegisterClass clz) { + switch (clz) { + case C_SSE_FLOAT: + case C_SSE_DOUBLE: + switch (size) { + case 4: + return Type::getFloatTy(*CU->TT->ctx); + case 8: + return (C_SSE_DOUBLE == clz) + ? Type::getDoubleTy(*CU->TT->ctx) + : VectorType::get(Type::getFloatTy(*CU->TT->ctx), + 2); + default: + assert(!"unexpected size for floating point class"); } case C_INTEGER: assert(size <= 8); @@ -901,328 +927,337 @@ struct CCallingConv { assert(!"unexpected class"); } } - bool ValidAggregateSize(size_t sz) { - return sz <= 16; - } + bool ValidAggregateSize(size_t sz) { return sz <= 16; } #else - Type * TypeForClass(size_t size, RegisterClass clz) { + Type *TypeForClass(size_t size, RegisterClass clz) { assert(size <= 8); - return Type::getIntNTy(*CU->TT->ctx, size * 8); + return Type::getIntNTy(*CU->TT->ctx, size * 8); } bool ValidAggregateSize(size_t sz) { bool isPow2 = sz && !(sz & (sz - 1)); return sz <= 8 && isPow2; } #endif - - Argument ClassifyArgument(Obj * type, int * usedfloat, int * usedint) { - TType * t = Ty->Get(type); - - if(!t->type->isAggregateType()) { - if(t->type->isFloatingPointTy() || t->type->isVectorTy()) + + Argument ClassifyArgument(Obj *type, int *usedfloat, int *usedint) { + TType *t = Ty->Get(type); + + if (!t->type->isAggregateType()) { + if (t->type->isFloatingPointTy() || t->type->isVectorTy()) ++*usedfloat; else ++*usedint; bool usei1 = t->islogical && !t->type->isVectorTy(); - return Argument(C_PRIMITIVE,t,usei1 ? Type::getInt1Ty(*CU->TT->ctx) : NULL); + return Argument(C_PRIMITIVE, t, usei1 ? Type::getInt1Ty(*CU->TT->ctx) : NULL); } - + int sz = CU->getDataLayout().getTypeAllocSize(t->type); - if(!ValidAggregateSize(sz)) { - return Argument(C_AGGREGATE_MEM,t); + if (!ValidAggregateSize(sz)) { + return Argument(C_AGGREGATE_MEM, t); } - + RegisterClass classes[] = {C_NO_CLASS, C_NO_CLASS}; - - int sizes[] = { std::min(sz,8), std::max(0,sz - 8) }; + + int sizes[] = {std::min(sz, 8), std::max(0, sz - 8)}; MergeValue(classes, 0, type); - if(classes[0] == C_MEMORY || classes[1] == C_MEMORY) { - return Argument(C_AGGREGATE_MEM,t); + if (classes[0] == C_MEMORY || classes[1] == C_MEMORY) { + return Argument(C_AGGREGATE_MEM, t); } - int nfloat = (classes[0] == C_SSE_FLOAT || classes[0] == C_SSE_DOUBLE) + (classes[1] == C_SSE_FLOAT || classes[1] == C_SSE_DOUBLE); + int nfloat = (classes[0] == C_SSE_FLOAT || classes[0] == C_SSE_DOUBLE) + + (classes[1] == C_SSE_FLOAT || classes[1] == C_SSE_DOUBLE); int nint = (classes[0] == C_INTEGER) + (classes[1] == C_INTEGER); if (sz > 8 && (*usedfloat + nfloat > 8 || *usedint + nint > 6)) { - return Argument(C_AGGREGATE_MEM,t); + return Argument(C_AGGREGATE_MEM, t); } - + *usedfloat += nfloat; *usedint += nint; - - std::vector elements; - for(int i = 0; i < 2; i++) - if(sizes[i] > 0) - elements.push_back(TypeForClass(sizes[i], classes[i])); - - return Argument(C_AGGREGATE_REG,t, - StructType::get(*CU->TT->ctx,elements)); - } - void Classify(Obj * ftype, Obj * params, Classification * info) { + + std::vector elements; + for (int i = 0; i < 2; i++) + if (sizes[i] > 0) elements.push_back(TypeForClass(sizes[i], classes[i])); + + return Argument(C_AGGREGATE_REG, t, StructType::get(*CU->TT->ctx, elements)); + } + void Classify(Obj *ftype, Obj *params, Classification *info) { Obj returntype; - ftype->obj("returntype",&returntype); + ftype->obj("returntype", &returntype); int zero = 0; info->returntype = ClassifyArgument(&returntype, &zero, &zero); - - #ifdef _WIN32 - //windows classifies empty structs as pass by pointer, but we need a return value of unit (an empty tuple) - //to be translated to void. So if it is unit, force the return value to be void by overriding the normal - //classification decision - if(Ty->IsUnitType(&returntype)) { - info->returntype = Argument(C_AGGREGATE_REG,info->returntype.type,StructType::get(*CU->TT->ctx)); - } - #endif - + +#ifdef _WIN32 + // windows classifies empty structs as pass by pointer, but we need a return value + // of unit (an empty tuple) to be translated to void. So if it is unit, force the + // return value to be void by overriding the normal classification decision + if (Ty->IsUnitType(&returntype)) { + info->returntype = Argument(C_AGGREGATE_REG, info->returntype.type, + StructType::get(*CU->TT->ctx)); + } +#endif + int nfloat = 0; - int nint = info->returntype.kind == C_AGGREGATE_MEM ? 1 : 0; /*sret consumes RDI for the return value pointer so it counts towards the used integer registers*/ + int nint = info->returntype.kind == C_AGGREGATE_MEM + ? 1 + : 0; /*sret consumes RDI for the return value pointer so it + counts towards the used integer registers*/ int N = params->size(); - for(int i = 0; i < N; i++) { + for (int i = 0; i < N; i++) { Obj elem; - params->objAt(i,&elem); - info->paramtypes.push_back(ClassifyArgument(&elem,&nfloat,&nint)); + params->objAt(i, &elem); + info->paramtypes.push_back(ClassifyArgument(&elem, &nfloat, &nint)); } - info->fntype = CreateFunctionType(info,ftype->boolean("isvararg")); + info->fntype = CreateFunctionType(info, ftype->boolean("isvararg")); } - - Classification * ClassifyFunction(Obj * fntyp) { - Classification * info = (Classification*)CU->symbols->getud(fntyp); - if(!info) { - info = new Classification(); //TODO: fix leak + + Classification *ClassifyFunction(Obj *fntyp) { + Classification *info = (Classification *)CU->symbols->getud(fntyp); + if (!info) { + info = new Classification(); // TODO: fix leak Obj params; - fntyp->obj("parameters",¶ms); + fntyp->obj("parameters", ¶ms); Classify(fntyp, ¶ms, info); CU->symbols->setud(fntyp, info); } return info; } - - template - void addSRetAttr(FnOrCall * r, int idx) { - #if LLVM_VERSION == 32 - AttrBuilder builder; - builder.addAttribute(Attributes::StructRet); - builder.addAttribute(Attributes::NoAlias); - r->addAttribute(idx,Attributes::get(*C->ctx,builder)); - #else - r->addAttribute(idx,Attribute::StructRet); - r->addAttribute(idx,Attribute::NoAlias); - #endif - } - template - void addByValAttr(FnOrCall * r, int idx) { - #if LLVM_VERSION == 32 - AttrBuilder builder; - builder.addAttribute(Attributes::ByVal); - r->addAttribute(idx,Attributes::get(*C->ctx,builder)); - #else - r->addAttribute(idx,Attribute::ByVal); - #endif - } - template - void addExtAttrIfNeeded(TType * t, FnOrCall * r, int idx) { - if(!t->type->isIntegerTy() || t->type->getPrimitiveSizeInBits() >= 32) - return; - #if LLVM_VERSION == 32 - AttrBuilder builder; - builder.addAttribute(t->issigned ? Attributes::SExt : Attributes::ZExt); - r->addAttribute(idx,Attributes::get(*C->ctx,builder)); - #else - r->addAttribute(idx,t->issigned ? Attribute::SExt : Attribute::ZExt); - #endif - } - - template - void AttributeFnOrCall(FnOrCall * r, Classification * info) { + + template + void addSRetAttr(FnOrCall *r, int idx) { +#if LLVM_VERSION == 32 + AttrBuilder builder; + builder.addAttribute(Attributes::StructRet); + builder.addAttribute(Attributes::NoAlias); + r->addAttribute(idx, Attributes::get(*C->ctx, builder)); +#else + r->addAttribute(idx, Attribute::StructRet); + r->addAttribute(idx, Attribute::NoAlias); +#endif + } + template + void addByValAttr(FnOrCall *r, int idx) { +#if LLVM_VERSION == 32 + AttrBuilder builder; + builder.addAttribute(Attributes::ByVal); + r->addAttribute(idx, Attributes::get(*C->ctx, builder)); +#else + r->addAttribute(idx, Attribute::ByVal); +#endif + } + template + void addExtAttrIfNeeded(TType *t, FnOrCall *r, int idx) { + if (!t->type->isIntegerTy() || t->type->getPrimitiveSizeInBits() >= 32) return; +#if LLVM_VERSION == 32 + AttrBuilder builder; + builder.addAttribute(t->issigned ? Attributes::SExt : Attributes::ZExt); + r->addAttribute(idx, Attributes::get(*C->ctx, builder)); +#else + r->addAttribute(idx, t->issigned ? Attribute::SExt : Attribute::ZExt); +#endif + } + + template + void AttributeFnOrCall(FnOrCall *r, Classification *info) { addExtAttrIfNeeded(info->returntype.type, r, 0); int argidx = 1; - if(info->returntype.kind == C_AGGREGATE_MEM) { + if (info->returntype.kind == C_AGGREGATE_MEM) { addSRetAttr(r, argidx); argidx++; } - for(size_t i = 0; i < info->paramtypes.size(); i++) { - Argument * v = &info->paramtypes[i]; - if(v->kind == C_AGGREGATE_MEM) { - #ifndef _WIN32 + for (size_t i = 0; i < info->paramtypes.size(); i++) { + Argument *v = &info->paramtypes[i]; + if (v->kind == C_AGGREGATE_MEM) { +#ifndef _WIN32 addByValAttr(r, argidx); - #endif +#endif } addExtAttrIfNeeded(v->type, r, argidx); argidx += v->GetNumberOfTypesInParamList(); } } - - Value *emitStoreAgg(IRBuilder<> * B, Type *t1, Value* src, Value *addr_dst) { + + Value *emitStoreAgg(IRBuilder<> *B, Type *t1, Value *src, Value *addr_dst) { assert(t1->isAggregateType()); LoadInst *l = dyn_cast(src); if (t1->isStructTy() && l) { // create bitcasts of src and dest address - Value* addr_src = l->getOperand(0); - Type* t = Type::getInt8PtrTy(*CU->TT->ctx); + Value *addr_src = l->getOperand(0); + Type *t = Type::getInt8PtrTy(*CU->TT->ctx); addr_dst = B->CreateBitCast(addr_dst, t); addr_src = B->CreateBitCast(addr_src, t); // size of bytes to copy StructType *st = cast(t1); const StructLayout *sl = CU->getDataLayout().getStructLayout(st); uint64_t size = sl->getSizeInBytes(); - Value *size_v = ConstantInt::get(Type::getInt64Ty(*CU->TT->ctx),size); + Value *size_v = ConstantInt::get(Type::getInt64Ty(*CU->TT->ctx), size); // perform the copy #if LLVM_VERSION <= 60 - Value* m = B->CreateMemCpy(addr_dst, addr_src, size_v, sl->getAlignment()); + Value *m = B->CreateMemCpy(addr_dst, addr_src, size_v, sl->getAlignment()); #else - Value* m = B->CreateMemCpy(addr_dst, sl->getAlignment(), addr_src, sl->getAlignment(), size_v); + Value *m = B->CreateMemCpy(addr_dst, sl->getAlignment(), addr_src, + sl->getAlignment(), size_v); #endif return m; - } - else + } else return (B->CreateStore(src, addr_dst)); } - Function * CreateFunction(Module * M, Obj * ftype, const Twine & name) { - Classification * info = ClassifyFunction(ftype); - Function * fn = Function::Create(info->fntype, Function::InternalLinkage, name, M); - AttributeFnOrCall(fn,info); - #if LLVM_VERSION > 32 && defined(__arm__) - fn->addAttribute(llvm::AttributeSet::FunctionIndex, llvm::Attribute::NoUnwind); - #endif - #if LLVM_VERSION >= 37 - DEBUG_ONLY(T) { - fn->addFnAttr("no-frame-pointer-elim","true"); - } - #endif + Function *CreateFunction(Module *M, Obj *ftype, const Twine &name) { + Classification *info = ClassifyFunction(ftype); + Function *fn = Function::Create(info->fntype, Function::InternalLinkage, name, M); + AttributeFnOrCall(fn, info); +#if LLVM_VERSION > 32 && defined(__arm__) + fn->addAttribute(llvm::AttributeSet::FunctionIndex, llvm::Attribute::NoUnwind); +#endif +#if LLVM_VERSION >= 37 + DEBUG_ONLY(T) { fn->addFnAttr("no-frame-pointer-elim", "true"); } +#endif return fn; } - - PointerType * Ptr(Type * t) { - return PointerType::getUnqual(t); - } - Value * ConvertPrimitive(IRBuilder<> * B, Value * src, Type * dstType, bool issigned) { - if(!dstType->isIntegerTy()) - return src; + + PointerType *Ptr(Type *t) { return PointerType::getUnqual(t); } + Value *ConvertPrimitive(IRBuilder<> *B, Value *src, Type *dstType, bool issigned) { + if (!dstType->isIntegerTy()) return src; return B->CreateIntCast(src, dstType, issigned); } - void EmitEntry(IRBuilder<> * B, Obj * ftype, Function * func, std::vector * variables) { - Classification * info = ClassifyFunction(ftype); + void EmitEntry(IRBuilder<> *B, Obj *ftype, Function *func, + std::vector *variables) { + Classification *info = ClassifyFunction(ftype); assert(info->paramtypes.size() == variables->size()); Function::arg_iterator ai = func->arg_begin(); - if(info->returntype.kind == C_AGGREGATE_MEM) - ++ai; //first argument is the return structure, skip it when loading arguments - for(size_t i = 0; i < variables->size(); i++) { - Argument * p = &info->paramtypes[i]; - Value * v = (*variables)[i]; - switch(p->kind) { + if (info->returntype.kind == C_AGGREGATE_MEM) + ++ai; // first argument is the return structure, skip it when loading + // arguments + for (size_t i = 0; i < variables->size(); i++) { + Argument *p = &info->paramtypes[i]; + Value *v = (*variables)[i]; + switch (p->kind) { case C_PRIMITIVE: { - Value * a = ConvertPrimitive(B,&*ai,p->type->type,p->type->issigned); - B->CreateStore(a,v); + Value *a = + ConvertPrimitive(B, &*ai, p->type->type, p->type->issigned); + B->CreateStore(a, v); ++ai; } break; case C_AGGREGATE_MEM: - //TODO: check that LLVM optimizes this copy away + // TODO: check that LLVM optimizes this copy away emitStoreAgg(B, p->type->type, B->CreateLoad(&*ai), v); ++ai; break; case C_AGGREGATE_REG: { - Value * dest = B->CreateBitCast(v,Ptr(p->cctype)); + Value *dest = B->CreateBitCast(v, Ptr(p->cctype)); int N = p->GetNumberOfTypesInParamList(); - for(int j = 0; j < N; j++) { - B->CreateStore(&*ai,CreateConstGEP2_32(B,dest, 0, j)); + for (int j = 0; j < N; j++) { + B->CreateStore(&*ai, CreateConstGEP2_32(B, dest, 0, j)); ++ai; } } break; } } } - void EmitReturn(IRBuilder<> * B, Obj * ftype, Function * function, Value * result) { - Classification * info = ClassifyFunction(ftype); + void EmitReturn(IRBuilder<> *B, Obj *ftype, Function *function, Value *result) { + Classification *info = ClassifyFunction(ftype); ArgumentKind kind = info->returntype.kind; - - if(C_AGGREGATE_REG == kind && info->returntype.GetNumberOfTypesInParamList() == 0) { + + if (C_AGGREGATE_REG == kind && + info->returntype.GetNumberOfTypesInParamList() == 0) { B->CreateRetVoid(); - } else if(C_PRIMITIVE == kind) { - B->CreateRet(ConvertPrimitive(B,result,info->returntype.cctype,info->returntype.type->issigned)); - } else if(C_AGGREGATE_MEM == kind) { - emitStoreAgg(B, info->returntype.type->type,result,&*function->arg_begin()); + } else if (C_PRIMITIVE == kind) { + B->CreateRet(ConvertPrimitive(B, result, info->returntype.cctype, + info->returntype.type->issigned)); + } else if (C_AGGREGATE_MEM == kind) { + emitStoreAgg(B, info->returntype.type->type, result, &*function->arg_begin()); B->CreateRetVoid(); - } else if(C_AGGREGATE_REG == kind) { - Value * dest = CreateAlloca(B,info->returntype.type->type); - emitStoreAgg(B, info->returntype.type->type,result, dest); - Value * result = B->CreateBitCast(dest,Ptr(info->returntype.cctype)); - if(info->returntype.GetNumberOfTypesInParamList() == 1) - result = CreateConstGEP2_32(B,result, 0, 0); + } else if (C_AGGREGATE_REG == kind) { + Value *dest = CreateAlloca(B, info->returntype.type->type); + emitStoreAgg(B, info->returntype.type->type, result, dest); + Value *result = B->CreateBitCast(dest, Ptr(info->returntype.cctype)); + if (info->returntype.GetNumberOfTypesInParamList() == 1) + result = CreateConstGEP2_32(B, result, 0, 0); B->CreateRet(B->CreateLoad(result)); } else { assert(!"unhandled return value"); } } - - Value * EmitCall(IRBuilder<> * B, Obj * ftype, Obj * paramtypes, Value * callee, std::vector * actuals) { + + Value *EmitCall(IRBuilder<> *B, Obj *ftype, Obj *paramtypes, Value *callee, + std::vector *actuals) { Classification info; - Classify(ftype,paramtypes,&info); - - std::vector arguments; - - if(C_AGGREGATE_MEM == info.returntype.kind) { - arguments.push_back(CreateAlloca(B,info.returntype.type->type)); - } - - for(size_t i = 0; i < info.paramtypes.size(); i++) { - Argument * a = &info.paramtypes[i]; - Value * actual = (*actuals)[i]; - switch(a->kind) { + Classify(ftype, paramtypes, &info); + + std::vector arguments; + + if (C_AGGREGATE_MEM == info.returntype.kind) { + arguments.push_back(CreateAlloca(B, info.returntype.type->type)); + } + + for (size_t i = 0; i < info.paramtypes.size(); i++) { + Argument *a = &info.paramtypes[i]; + Value *actual = (*actuals)[i]; + switch (a->kind) { case C_PRIMITIVE: - arguments.push_back(ConvertPrimitive(B,actual,a->cctype,a->type->issigned)); + arguments.push_back( + ConvertPrimitive(B, actual, a->cctype, a->type->issigned)); break; case C_AGGREGATE_MEM: { - Value * scratch = CreateAlloca(B,a->type->type); + Value *scratch = CreateAlloca(B, a->type->type); emitStoreAgg(B, a->type->type, actual, scratch); arguments.push_back(scratch); } break; case C_AGGREGATE_REG: { - Value * scratch = CreateAlloca(B,a->type->type); + Value *scratch = CreateAlloca(B, a->type->type); emitStoreAgg(B, a->type->type, actual, scratch); - Value * casted = B->CreateBitCast(scratch,Ptr(a->cctype)); + Value *casted = B->CreateBitCast(scratch, Ptr(a->cctype)); int N = a->GetNumberOfTypesInParamList(); - for(int j = 0; j < N; j++) { - arguments.push_back(B->CreateLoad(CreateConstGEP2_32(B,casted,0,j))); + for (int j = 0; j < N; j++) { + arguments.push_back( + B->CreateLoad(CreateConstGEP2_32(B, casted, 0, j))); } } break; } - - } - - //emit call - //function pointers are stored as &int8 to avoid calling convension issues - //cast it back to the real pointer type right before calling it - callee = B->CreateBitCast(callee,Ptr(info.fntype)); - CallInst * call = B->CreateCall(callee, arguments); - //annotate call with byval and sret - AttributeFnOrCall(call,&info); - - //unstage results - if(C_PRIMITIVE == info.returntype.kind) { - return ConvertPrimitive(B,call,info.returntype.type->type,info.returntype.type->issigned); + } + + // emit call + // function pointers are stored as &int8 to avoid calling convension issues + // cast it back to the real pointer type right before calling it + callee = B->CreateBitCast(callee, Ptr(info.fntype)); + CallInst *call = B->CreateCall(callee, arguments); + // annotate call with byval and sret + AttributeFnOrCall(call, &info); + + // unstage results + if (C_PRIMITIVE == info.returntype.kind) { + return ConvertPrimitive(B, call, info.returntype.type->type, + info.returntype.type->issigned); } else { - Value * aggregate; - if(C_AGGREGATE_MEM == info.returntype.kind) { + Value *aggregate; + if (C_AGGREGATE_MEM == info.returntype.kind) { aggregate = arguments[0]; - } else { //C_AGGREGATE_REG - aggregate = CreateAlloca(B,info.returntype.type->type); - Value * casted = B->CreateBitCast(aggregate,Ptr(info.returntype.cctype)); - if(info.returntype.GetNumberOfTypesInParamList() == 1) - casted = CreateConstGEP2_32(B,casted, 0, 0); - if(info.returntype.GetNumberOfTypesInParamList() > 0) - B->CreateStore(call,casted); + } else { // C_AGGREGATE_REG + aggregate = CreateAlloca(B, info.returntype.type->type); + Value *casted = B->CreateBitCast(aggregate, Ptr(info.returntype.cctype)); + if (info.returntype.GetNumberOfTypesInParamList() == 1) + casted = CreateConstGEP2_32(B, casted, 0, 0); + if (info.returntype.GetNumberOfTypesInParamList() > 0) + B->CreateStore(call, casted); } return B->CreateLoad(aggregate); } } - FunctionType * CreateFunctionType(Classification * info, bool isvararg) { - std::vector arguments; - - Type * rt = NULL; - switch(info->returntype.kind) { + FunctionType *CreateFunctionType(Classification *info, bool isvararg) { + std::vector arguments; + + Type *rt = NULL; + switch (info->returntype.kind) { case C_AGGREGATE_REG: { - switch(info->returntype.GetNumberOfTypesInParamList()) { - case 0: rt = Type::getVoidTy(*CU->TT->ctx); break; - case 1: rt = cast(info->returntype.cctype)->getElementType(0); break; - default: rt = info->returntype.cctype; break; + switch (info->returntype.GetNumberOfTypesInParamList()) { + case 0: + rt = Type::getVoidTy(*CU->TT->ctx); + break; + case 1: + rt = cast(info->returntype.cctype)->getElementType(0); + break; + default: + rt = info->returntype.cctype; + break; } } break; case C_AGGREGATE_MEM: { @@ -1233,10 +1268,10 @@ struct CCallingConv { rt = info->returntype.cctype; } break; } - - for(size_t i = 0; i < info->paramtypes.size(); i++) { - Argument * a = &info->paramtypes[i]; - switch(a->kind) { + + for (size_t i = 0; i < info->paramtypes.size(); i++) { + Argument *a = &info->paramtypes[i]; + switch (a->kind) { case C_PRIMITIVE: { arguments.push_back(a->cctype); } break; @@ -1245,169 +1280,194 @@ struct CCallingConv { break; case C_AGGREGATE_REG: { int N = a->GetNumberOfTypesInParamList(); - for(int j = 0; j < N; j++) { - arguments.push_back(cast(a->cctype)->getElementType(j)); + for (int j = 0; j < N; j++) { + arguments.push_back( + cast(a->cctype)->getElementType(j)); } } break; } } - - return FunctionType::get(rt,arguments,isvararg); + + return FunctionType::get(rt, arguments, isvararg); } }; -static Constant * EmitConstantInitializer(TerraCompilationUnit * CU, Obj * v); +static Constant *EmitConstantInitializer(TerraCompilationUnit *CU, Obj *v); -static GlobalVariable * CreateGlobalVariable(TerraCompilationUnit * CU, Obj * global, const char * name) { +static GlobalVariable *CreateGlobalVariable(TerraCompilationUnit *CU, Obj *global, + const char *name) { Obj t; - global->obj("type",&t); - Type * typ = CU->Ty->Get(&t)->type; - - Constant * llvmconstant = global->boolean("extern") ? NULL : UndefValue::get(typ); + global->obj("type", &t); + Type *typ = CU->Ty->Get(&t)->type; + + Constant *llvmconstant = global->boolean("extern") ? NULL : UndefValue::get(typ); Obj constant; - if(global->obj("initializer",&constant)) { - llvmconstant = EmitConstantInitializer(CU,&constant); + if (global->obj("initializer", &constant)) { + llvmconstant = EmitConstantInitializer(CU, &constant); } int as = global->number("addressspace"); GlobalValue::LinkageTypes linkage = - (global->boolean("constant") && !global->boolean("extern")) - ? GlobalValue::InternalLinkage : GlobalValue::ExternalLinkage; - return new GlobalVariable(*CU->M, typ, global->boolean("constant"), linkage, llvmconstant, name, NULL, GlobalVariable::NotThreadLocal, as); + (global->boolean("constant") && !global->boolean("extern")) + ? GlobalValue::InternalLinkage + : GlobalValue::ExternalLinkage; + return new GlobalVariable(*CU->M, typ, global->boolean("constant"), linkage, + llvmconstant, name, NULL, GlobalVariable::NotThreadLocal, + as); } -static bool AlwaysShouldCopy(GlobalValue * G, void * data) { return true; } +static bool AlwaysShouldCopy(GlobalValue *G, void *data) { return true; } -static GlobalVariable * EmitGlobalVariable(TerraCompilationUnit * CU, Obj * global, const char * name) { - GlobalVariable * gv = (GlobalVariable*) CU->symbols->getud(global); +static GlobalVariable *EmitGlobalVariable(TerraCompilationUnit *CU, Obj *global, + const char *name) { + GlobalVariable *gv = (GlobalVariable *)CU->symbols->getud(global); if (gv == NULL) { - if(global->hasfield("name")) - name = global->string("name"); //globals given name overrides the alternate name given when the global is created - if(global->boolean("extern")) { + if (global->hasfield("name")) + name = global->string("name"); // globals given name overrides the alternate + // name given when the global is created + if (global->boolean("extern")) { gv = CU->M->getGlobalVariable(name); - if(!gv) { - GlobalValue * externglobal = CU->TT->external->getGlobalVariable(name); - if(externglobal) { - llvmutil_copyfrommodule(CU->M, CU->TT->external, &externglobal, 1, AlwaysShouldCopy, NULL); - gv = CU->M->getGlobalVariable(name); assert(gv); + if (!gv) { + GlobalValue *externglobal = CU->TT->external->getGlobalVariable(name); + if (externglobal) { + llvmutil_copyfrommodule(CU->M, CU->TT->external, &externglobal, 1, + AlwaysShouldCopy, NULL); + gv = CU->M->getGlobalVariable(name); + assert(gv); } } } - if(!gv) - gv = CreateGlobalVariable(CU,global,name); + if (!gv) gv = CreateGlobalVariable(CU, global, name); CU->symbols->setud(global, gv); } return gv; } const int COMPILATION_UNIT_POS = 1; -static int terra_deletefunction(lua_State * L); +static int terra_deletefunction(lua_State *L); -Function * EmitFunction(TerraCompilationUnit * CU, Obj * funcobj, TerraFunctionState * user); +Function *EmitFunction(TerraCompilationUnit *CU, Obj *funcobj, TerraFunctionState *user); -struct Locals { Obj cur; Locals * prev; }; //stack of local environment +struct Locals { + Obj cur; + Locals *prev; +}; // stack of local environment struct FunctionEmitter { - TerraCompilationUnit * CU; - terra_State * T; - lua_State * L; - terra_CompilerState * C; - Types * Ty; - CCallingConv * CC; - Module * M; - Obj * labels, * labeldepth; - Locals * locals; - - IRBuilder<> * B; - std::vector > breakpoints; //stack of basic blocks where a break statement should go - - #ifdef DEBUG_INFO_WORKING - DIBuilder * DB; + TerraCompilationUnit *CU; + terra_State *T; + lua_State *L; + terra_CompilerState *C; + Types *Ty; + CCallingConv *CC; + Module *M; + Obj *labels, *labeldepth; + Locals *locals; + + IRBuilder<> *B; + std::vector > + breakpoints; // stack of basic blocks where a break statement should go + +#ifdef DEBUG_INFO_WORKING + DIBuilder *DB; DISubprogram SP; - #endif - - StringMap filenamecache; //map from filename to lexical scope object representing file. - const char * customfilename; +#endif + + StringMap filenamecache; // map from filename to lexical scope object + // representing file. + const char *customfilename; int customlinenumber; - - Obj * funcobj; - TerraFunctionState * fstate; + + Obj *funcobj; + TerraFunctionState *fstate; std::vector deferred; - + Obj labeltbl; Locals basescope; - - FunctionEmitter(TerraCompilationUnit * CU_) : CU(CU_), T(CU_->T), L(CU_->T->L), C(CU_->T->C), Ty(CU_->Ty), CC(CU_->CC), M(CU_->M), locals(NULL) { + + FunctionEmitter(TerraCompilationUnit *CU_) + : CU(CU_), + T(CU_->T), + L(CU_->T->L), + C(CU_->T->C), + Ty(CU_->Ty), + CC(CU_->CC), + M(CU_->M), + locals(NULL) { B = new IRBuilder<>(*CU->TT->ctx); enterScope(&basescope); labels = newMap(&labeltbl); } - ~FunctionEmitter() { - delete B; - } - TerraFunctionState * emitFunction(Obj * funcobj_) { + ~FunctionEmitter() { delete B; } + TerraFunctionState *emitFunction(Obj *funcobj_) { funcobj = funcobj_; - fstate = lookupSymbol(CU->symbols,funcobj); - if(!fstate) { - fstate = (TerraFunctionState*) lua_newuserdata(L, sizeof(TerraFunctionState)); //map the declaration first so that recursive uses do not re-emit + fstate = lookupSymbol(CU->symbols, funcobj); + if (!fstate) { + fstate = (TerraFunctionState *)lua_newuserdata( + L, sizeof(TerraFunctionState)); // map the declaration first so that + // recursive uses do not re-emit memset(fstate, 0, sizeof(TerraFunctionState)); mapFunction(CU->symbols, funcobj); - const char * name = funcobj->string("name"); + const char *name = funcobj->string("name"); bool isextern = T_functionextern == funcobj->kind("kind"); - if (isextern) { //try to resolve function as imported C code + if (isextern) { // try to resolve function as imported C code fstate->func = M->getFunction(name); - if(!fstate->func) { - GlobalValue * externfunction = CU->TT->external->getFunction(name); - if(externfunction) { - llvmutil_copyfrommodule(CU->M, CU->TT->external, &externfunction, 1, AlwaysShouldCopy, NULL); - fstate->func = CU->M->getFunction(name); assert(fstate->func); + if (!fstate->func) { + GlobalValue *externfunction = CU->TT->external->getFunction(name); + if (externfunction) { + llvmutil_copyfrommodule(CU->M, CU->TT->external, &externfunction, + 1, AlwaysShouldCopy, NULL); + fstate->func = CU->M->getFunction(name); + assert(fstate->func); } } - if(fstate->func) - return fstate; + if (fstate->func) return fstate; } - + Obj ftype; - funcobj->obj("type",&ftype); - //function name is $+name so that it can't conflict with any symbols imported from the C namespace - fstate->func = CC->CreateFunction(M,&ftype, Twine(StringRef((isextern) ? "" : "$"),name)); + funcobj->obj("type", &ftype); + // function name is $+name so that it can't conflict with any symbols imported + // from the C namespace + fstate->func = CC->CreateFunction( + M, &ftype, Twine(StringRef((isextern) ? "" : "$"), name)); if (isextern) { // Set external linkage for extern functions. fstate->func->setLinkage(GlobalValue::ExternalLinkage); } - if(funcobj->hasfield("alwaysinline")) { - if(funcobj->boolean("alwaysinline")) { + if (funcobj->hasfield("alwaysinline")) { + if (funcobj->boolean("alwaysinline")) { fstate->func->ADDFNATTR(AlwaysInline); } else { fstate->func->ADDFNATTR(NoInline); } } - if(funcobj->hasfield("dontoptimize")) { - if(funcobj->boolean("dontoptimize")) { + if (funcobj->hasfield("dontoptimize")) { + if (funcobj->boolean("dontoptimize")) { fstate->func->ADDFNATTR(OptimizeNone); fstate->func->ADDFNATTR(NoInline); } } - if(funcobj->hasfield("noreturn")) { - if(funcobj->boolean("noreturn")) { + if (funcobj->hasfield("noreturn")) { + if (funcobj->boolean("noreturn")) { fstate->func->ADDFNATTR(NoReturn); } } - if(!isextern) { - if(CU->optimize) { + if (!isextern) { + if (CU->optimize) { fstate->index = CU->functioncount++; fstate->lowlink = fstate->index; fstate->onstack = true; CU->tooptimize->push_back(fstate); } emitBody(); - if(CU->optimize && fstate->lowlink == fstate->index) { //this is the end of a strongly connect component run optimizations on it - VERBOSE_ONLY(T) { - printf("optimizing scc containing: "); - } - TerraFunctionState * f; - std::vector scc; + if (CU->optimize && + fstate->lowlink == + fstate->index) { // this is the end of a strongly connect + // component run optimizations on it + VERBOSE_ONLY(T) { printf("optimizing scc containing: "); } + TerraFunctionState *f; + std::vector scc; do { f = CU->tooptimize->back(); CU->tooptimize->pop_back(); @@ -1415,192 +1475,196 @@ struct FunctionEmitter { f->onstack = false; VERBOSE_ONLY(T) { std::string s = f->func->getName(); - printf("%s%s",s.c_str(), (fstate == f) ? "\n" : " "); + printf("%s%s", s.c_str(), (fstate == f) ? "\n" : " "); } - } while(fstate != f); + } while (fstate != f); CU->mi->run(scc.begin(), scc.end()); - for(size_t i = 0; i < scc.size(); i++) { + for (size_t i = 0; i < scc.size(); i++) { VERBOSE_ONLY(T) { std::string s = scc[i]->getName(); - printf("optimizing %s\n",s.c_str()); + printf("optimizing %s\n", s.c_str()); } CU->fpm->run(*scc[i]); - VERBOSE_ONLY(T) { - TERRA_DUMP_FUNCTION(scc[i]); - } + VERBOSE_ONLY(T) { TERRA_DUMP_FUNCTION(scc[i]); } } } } - lua_getfield(L,COMPILATION_UNIT_POS,"collectfunctions"); - if(lua_toboolean(L,-1)) { //set a destructor on the TerraFunctionState object to clean up this function + lua_getfield(L, COMPILATION_UNIT_POS, "collectfunctions"); + if (lua_toboolean(L, -1)) { // set a destructor on the TerraFunctionState + // object to clean up this function CU->nreferences++; CU->symbols->push(); funcobj->push(); - lua_gettable(L, -2); //lookup userdata object that holds the TerraFunctionState for this function - lua_newtable(L); //setmetatable(ud,{ __gc = terra_deletefunction(llvm_cu) }) - lua_getfield(L,COMPILATION_UNIT_POS,"llvm_cu"); - lua_pushcclosure(L,terra_deletefunction,1); - lua_setfield(L,-2,"__gc"); - lua_setmetatable(L,-2); - lua_pop(L, 2); //userdata object and symbols talbe + lua_gettable(L, -2); // lookup userdata object that holds the + // TerraFunctionState for this function + lua_newtable( + L); // setmetatable(ud,{ __gc = terra_deletefunction(llvm_cu) }) + lua_getfield(L, COMPILATION_UNIT_POS, "llvm_cu"); + lua_pushcclosure(L, terra_deletefunction, 1); + lua_setfield(L, -2, "__gc"); + lua_setmetatable(L, -2); + lua_pop(L, 2); // userdata object and symbols talbe } - lua_pop(L,1); + lua_pop(L, 1); } return fstate; } - Constant * emitConstantExpression(Obj * exp) { + Constant *emitConstantExpression(Obj *exp) { TerraFunctionState state; fstate = &state; - fstate->func = Function::Create(FunctionType::get(typeOfValue(exp)->type, false), Function::ExternalLinkage, "constant", M); - BasicBlock * entry = BasicBlock::Create(*CU->TT->ctx,"entry",fstate->func); - initDebug(exp->string("filename"),exp->number("linenumber")); + fstate->func = Function::Create(FunctionType::get(typeOfValue(exp)->type, false), + Function::ExternalLinkage, "constant", M); + BasicBlock *entry = BasicBlock::Create(*CU->TT->ctx, "entry", fstate->func); + initDebug(exp->string("filename"), exp->number("linenumber")); setDebugPoint(exp); B->SetInsertPoint(entry); B->CreateRet(emitExp(exp)); endDebug(); CU->fpm->run(*fstate->func); - ReturnInst * term = cast(fstate->func->getEntryBlock().getTerminator()); - Constant * r = dyn_cast(term->getReturnValue()); assert(r || !"constant expression was not constant"); + ReturnInst *term = + cast(fstate->func->getEntryBlock().getTerminator()); + Constant *r = dyn_cast(term->getReturnValue()); + assert(r || !"constant expression was not constant"); fstate->func->eraseFromParent(); return r; } - Obj * newMap(Obj * buf) { + Obj *newMap(Obj *buf) { lua_newtable(L); CU->symbols->fromStack(buf); return buf; } void emitBody() { - - BasicBlock * entry = BasicBlock::Create(*CU->TT->ctx,"entry",fstate->func); + BasicBlock *entry = BasicBlock::Create(*CU->TT->ctx, "entry", fstate->func); B->SetInsertPoint(entry); - + Obj parameters; - initDebug(funcobj->string("filename"),funcobj->number("linenumber")); + initDebug(funcobj->string("filename"), funcobj->number("linenumber")); setDebugPoint(funcobj); - funcobj->obj("parameters",¶meters); - + funcobj->obj("parameters", ¶meters); + Obj ftype, labeldepthtbl; - funcobj->obj("type",&ftype); - funcobj->obj("labeldepths",&labeldepthtbl); + funcobj->obj("type", &ftype); + funcobj->obj("labeldepths", &labeldepthtbl); labeldepth = &labeldepthtbl; - + std::vector parametervars; emitExpressionList(¶meters, false, ¶metervars); - CC->EmitEntry(B,&ftype, fstate->func, ¶metervars); - + CC->EmitEntry(B, &ftype, fstate->func, ¶metervars); + Obj body; - funcobj->obj("body",&body); + funcobj->obj("body", &body); emitStmt(&body); - //if there no terminating return statment, we need to insert one - //if there was a Return, then this block is dead and will be cleaned up + // if there no terminating return statment, we need to insert one + // if there was a Return, then this block is dead and will be cleaned up emitReturnUndef(); assert(breakpoints.size() == 0); - - VERBOSE_ONLY(T) { - TERRA_DUMP_FUNCTION(fstate->func); - } + + VERBOSE_ONLY(T) { TERRA_DUMP_FUNCTION(fstate->func); } verifyFunction(*fstate->func); - + endDebug(); } - template - R* lookupSymbol(Obj * tbl, Obj * k) { - return (R*) tbl->getud(k); - } - void mapSymbol(Obj * tbl, Obj * k, void * v) { - tbl->setud(k,v); + template + R *lookupSymbol(Obj *tbl, Obj *k) { + return (R *)tbl->getud(k); } - void mapFunction(Obj * tbl, Obj * k) { //TerraFunctionState userdata is on top of stack + void mapSymbol(Obj *tbl, Obj *k, void *v) { tbl->setud(k, v); } + void mapFunction(Obj *tbl, Obj *k) { // TerraFunctionState userdata is on top of + // stack tbl->push(); k->push(); - lua_pushvalue(L,-3); - lua_settable(L,-3); - lua_pop(L,2); //table and original userdata object + lua_pushvalue(L, -3); + lua_settable(L, -3); + lua_pop(L, 2); // table and original userdata object } - TType * getType(Obj * v) { - return Ty->Get(v); - } - TType * typeOfValue(Obj * v) { + TType *getType(Obj *v) { return Ty->Get(v); } + TType *typeOfValue(Obj *v) { Obj t; - v->obj("type",&t); + v->obj("type", &t); return getType(&t); } - - AllocaInst * allocVar(Obj * v) { + + AllocaInst *allocVar(Obj *v) { Obj sym; - v->obj("symbol",&sym); - AllocaInst * a = CreateAlloca(B,typeOfValue(v)->type,0,v->string("name")); - mapSymbol(&locals->cur,&sym,a); + v->obj("symbol", &sym); + AllocaInst *a = CreateAlloca(B, typeOfValue(v)->type, 0, v->string("name")); + mapSymbol(&locals->cur, &sym, a); return a; } - - Value * emitAddressOf(Obj * exp) { - Value * v = emitExp(exp,false); - if(exp->boolean("lvalue")) - return v; - Value * addr = CreateAlloca(B,typeOfValue(exp)->type); - B->CreateStore(v,addr); + + Value *emitAddressOf(Obj *exp) { + Value *v = emitExp(exp, false); + if (exp->boolean("lvalue")) return v; + Value *addr = CreateAlloca(B, typeOfValue(exp)->type); + B->CreateStore(v, addr); return addr; } - - Value * emitUnary(Obj * exp, Obj * ao) { + + Value *emitUnary(Obj *exp, Obj *ao) { T_Kind kind = exp->kind("operator"); - if (T_addressof == kind) - return emitAddressOf(ao); - - TType * t = typeOfValue(exp); - Type * baseT = getPrimitiveType(t); - Value * a = emitExp(ao); - switch(kind) { + if (T_addressof == kind) return emitAddressOf(ao); + + TType *t = typeOfValue(exp); + Type *baseT = getPrimitiveType(t); + Value *a = emitExp(ao); + switch (kind) { case T_dereference: - return a; /* no-op, a is a pointer and lvalue is true for this expression */ + return a; /* no-op, a is a pointer and lvalue is true for this expression + */ break; case T_not: - if(t->islogical) - return B->CreateZExt(B->CreateICmpEQ(a, ConstantInt::get(t->type,0)), t->type); + if (t->islogical) + return B->CreateZExt(B->CreateICmpEQ(a, ConstantInt::get(t->type, 0)), + t->type); else return B->CreateNot(a); break; case T_sub: - if(baseT->isIntegerTy()) { + if (baseT->isIntegerTy()) { return B->CreateNeg(a); } else { return B->CreateFNeg(a); } break; default: - printf("NYI - unary %s\n",tkindtostr(kind)); + printf("NYI - unary %s\n", tkindtostr(kind)); abort(); break; } } - Value * emitCompare(T_Kind op, TType * t, Value * a, Value * b) { - Type * baseT = getPrimitiveType(t); -#define RETURN_OP(op,u) \ -if(baseT->isIntegerTy() || t->type->isPointerTy()) { \ - return B->CreateICmp(CmpInst::ICMP_##op,a,b); \ -} else { \ - return B->CreateFCmp(CmpInst::FCMP_##u##op,a,b); \ -} -#define RETURN_SOP(op,u) \ -if(baseT->isIntegerTy() || t->type->isPointerTy()) { \ - if(t->issigned) { \ - return B->CreateICmp(CmpInst::ICMP_S##op,a,b); \ - } else { \ - return B->CreateICmp(CmpInst::ICMP_U##op,a,b); \ - } \ -} else { \ - return B->CreateFCmp(CmpInst::FCMP_##u##op,a,b); \ -} - - switch(op) { - case T_ne: RETURN_OP(NE,U) break; - case T_eq: RETURN_OP(EQ,O) break; - case T_lt: RETURN_SOP(LT,O) break; - case T_gt: RETURN_SOP(GT,O) break; - case T_ge: RETURN_SOP(GE,O) break; - case T_le: RETURN_SOP(LE,O) break; - default: + Value *emitCompare(T_Kind op, TType *t, Value *a, Value *b) { + Type *baseT = getPrimitiveType(t); +#define RETURN_OP(op, u) \ + if (baseT->isIntegerTy() || t->type->isPointerTy()) { \ + return B->CreateICmp(CmpInst::ICMP_##op, a, b); \ + } else { \ + return B->CreateFCmp(CmpInst::FCMP_##u##op, a, b); \ + } +#define RETURN_SOP(op, u) \ + if (baseT->isIntegerTy() || t->type->isPointerTy()) { \ + if (t->issigned) { \ + return B->CreateICmp(CmpInst::ICMP_S##op, a, b); \ + } else { \ + return B->CreateICmp(CmpInst::ICMP_U##op, a, b); \ + } \ + } else { \ + return B->CreateFCmp(CmpInst::FCMP_##u##op, a, b); \ + } + + switch (op) { + case T_ne: + RETURN_OP(NE, U) break; + case T_eq: + RETURN_OP(EQ, O) break; + case T_lt: + RETURN_SOP(LT, O) break; + case T_gt: + RETURN_SOP(GT, O) break; + case T_ge: + RETURN_SOP(GE, O) break; + case T_le: + RETURN_SOP(LE, O) break; + default: assert(!"unknown op"); return NULL; break; @@ -1608,33 +1672,37 @@ if(baseT->isIntegerTy() || t->type->isPointerTy()) { \ #undef RETURN_OP #undef RETURN_SOP } - void emitBranchOnExpr(Obj * expr, BasicBlock * trueblock, BasicBlock * falseblock) { - //try to optimize the branching by looking into lazy logical expressions and simplifying them + void emitBranchOnExpr(Obj *expr, BasicBlock *trueblock, BasicBlock *falseblock) { + // try to optimize the branching by looking into lazy logical expressions and + // simplifying them T_Kind kind = expr->kind("kind"); - if(T_operator == kind) { + if (T_operator == kind) { T_Kind op = expr->kind("operator"); Obj operands; - expr->obj("operands",&operands); - Obj lhs; Obj rhs; - operands.objAt(0,&lhs); - operands.objAt(1,&rhs); - if(T_not == op) { + expr->obj("operands", &operands); + Obj lhs; + Obj rhs; + operands.objAt(0, &lhs); + operands.objAt(1, &rhs); + if (T_not == op) { emitBranchOnExpr(&lhs, falseblock, trueblock); return; } - if(T_and == op || T_or == op) { + if (T_and == op || T_or == op) { bool isand = T_and == op; - BasicBlock * condblock = createAndInsertBB((isand) ? "and.lhs.true" : "or.lhs.false"); - emitBranchOnExpr(&lhs, (isand) ? condblock : trueblock, (isand) ? falseblock : condblock); + BasicBlock *condblock = + createAndInsertBB((isand) ? "and.lhs.true" : "or.lhs.false"); + emitBranchOnExpr(&lhs, (isand) ? condblock : trueblock, + (isand) ? falseblock : condblock); setInsertBlock(condblock); emitBranchOnExpr(&rhs, trueblock, falseblock); return; } } - //if no optimizations applied just emit the naive branch + // if no optimizations applied just emit the naive branch B->CreateCondBr(emitCond(expr), trueblock, falseblock); } - Value * emitLazyLogical(TType * t, Obj * ao, Obj * bo, bool isAnd) { + Value *emitLazyLogical(TType *t, Obj *ao, Obj *bo, bool isAnd) { /* AND (isAnd == true) bool result; @@ -1653,22 +1721,22 @@ if(baseT->isIntegerTy() || t->type->isPointerTy()) { \ result = ; } */ - - BasicBlock * stmtB = createAndInsertBB((isAnd) ? "and.rhs" : "or.rhs"); - BasicBlock * mergeB = createAndInsertBB((isAnd) ? "and.end" : "or.end"); - + + BasicBlock *stmtB = createAndInsertBB((isAnd) ? "and.rhs" : "or.rhs"); + BasicBlock *mergeB = createAndInsertBB((isAnd) ? "and.end" : "or.end"); + emitBranchOnExpr(ao, (isAnd) ? stmtB : mergeB, (isAnd) ? mergeB : stmtB); - - Type * int1 = Type::getInt1Ty(*CU->TT->ctx); + + Type *int1 = Type::getInt1Ty(*CU->TT->ctx); setInsertBlock(mergeB); - PHINode * result = B->CreatePHI(int1, 2); - Value * literal = ConstantInt::get(int1, !isAnd); - for(pred_iterator it = pred_begin(mergeB), end = pred_end(mergeB); - it != end; ++it) - result->addIncoming(literal,*it); - + PHINode *result = B->CreatePHI(int1, 2); + Value *literal = ConstantInt::get(int1, !isAnd); + for (pred_iterator it = pred_begin(mergeB), end = pred_end(mergeB); it != end; + ++it) + result->addIncoming(literal, *it); + setInsertBlock(stmtB); - Value * b = emitCond(bo); + Value *b = emitCond(bo); stmtB = B->GetInsertBlock(); B->CreateBr(mergeB); followsBB(mergeB); @@ -1676,101 +1744,113 @@ if(baseT->isIntegerTy() || t->type->isPointerTy()) { \ result->addIncoming(b, stmtB); return B->CreateZExt(result, t->type); } - Value * emitIndex(TType * ftype, int tobits, Value * number) { + Value *emitIndex(TType *ftype, int tobits, Value *number) { TType ttype; - memset(&ttype,0,sizeof(ttype)); - ttype.type = Type::getIntNTy(*CU->TT->ctx,tobits); + memset(&ttype, 0, sizeof(ttype)); + ttype.type = Type::getIntNTy(*CU->TT->ctx, tobits); ttype.issigned = ftype->issigned; - return emitPrimitiveCast(ftype,&ttype,number); - } - Value * emitPointerArith(T_Kind kind, Value * pointer, TType * numTy, Value * number) { - number = emitIndex(numTy,64,number); - if(kind == T_add) { - return B->CreateGEP(pointer,number); - } else if(kind == T_sub) { - Value * numNeg = B->CreateNeg(number); - return B->CreateGEP(pointer,numNeg); + return emitPrimitiveCast(ftype, &ttype, number); + } + Value *emitPointerArith(T_Kind kind, Value *pointer, TType *numTy, Value *number) { + number = emitIndex(numTy, 64, number); + if (kind == T_add) { + return B->CreateGEP(pointer, number); + } else if (kind == T_sub) { + Value *numNeg = B->CreateNeg(number); + return B->CreateGEP(pointer, numNeg); } else { assert(!"unexpected pointer arith"); return NULL; } } - Value * emitPointerSub(TType * t, Value * a, Value * b) { - return B->CreatePtrDiff(a, b); - } - Value * emitBinary(Obj * exp, Obj * ao, Obj * bo) { - TType * t = typeOfValue(exp); + Value *emitPointerSub(TType *t, Value *a, Value *b) { return B->CreatePtrDiff(a, b); } + Value *emitBinary(Obj *exp, Obj *ao, Obj *bo) { + TType *t = typeOfValue(exp); T_Kind kind = exp->kind("operator"); - //check for lazy operators before evaluateing arguments - if(t->islogical && !t->type->isVectorTy()) { - switch(kind) { + // check for lazy operators before evaluateing arguments + if (t->islogical && !t->type->isVectorTy()) { + switch (kind) { case T_and: - return emitLazyLogical(t,ao,bo,true); + return emitLazyLogical(t, ao, bo, true); case T_or: - return emitLazyLogical(t,ao,bo,false); + return emitLazyLogical(t, ao, bo, false); default: break; } } - - //ok, we have eager operators, lets evalute the arguments then emit - Value * a = emitExp(ao); - Value * b = emitExp(bo); + + // ok, we have eager operators, lets evalute the arguments then emit + Value *a = emitExp(ao); + Value *b = emitExp(bo); Obj aot; - ao->obj("type",&aot); - TType * at = getType(&aot); - TType * bt = typeOfValue(bo); - //CC.EnsureTypeIsComplete(at) (not needed because typeOfValue(ao) ensure the type is complete) - - //check for pointer arithmetic first pointer arithmetic first - if(at->type->isPointerTy() && (kind == T_add || kind == T_sub)) { + ao->obj("type", &aot); + TType *at = getType(&aot); + TType *bt = typeOfValue(bo); + // CC.EnsureTypeIsComplete(at) (not needed because typeOfValue(ao) ensure the type + // is complete) + + // check for pointer arithmetic first pointer arithmetic first + if (at->type->isPointerTy() && (kind == T_add || kind == T_sub)) { Ty->EnsurePointsToCompleteType(&aot); - if(bt->type->isPointerTy()) { - return emitPointerSub(t,a,b); + if (bt->type->isPointerTy()) { + return emitPointerSub(t, a, b); } else { assert(bt->type->isIntegerTy()); return emitPointerArith(kind, a, bt, b); } } - - Type * baseT = getPrimitiveType(t); - -#define RETURN_OP(op) \ -if(baseT->isIntegerTy()) { \ - return B->Create##op(a,b); \ -} else { \ - return B->CreateF##op(a,b); \ -} -#define RETURN_SOP(op) \ -if(baseT->isIntegerTy()) { \ - if(t->issigned) { \ - return B->CreateS##op(a,b); \ - } else { \ - return B->CreateU##op(a,b); \ - } \ -} else { \ - return B->CreateF##op(a,b); \ -} - switch(kind) { - case T_add: RETURN_OP(Add) break; - case T_sub: RETURN_OP(Sub) break; - case T_mul: RETURN_OP(Mul) break; - case T_div: RETURN_SOP(Div) break; - case T_mod: RETURN_SOP(Rem) break; - case T_pow: return B->CreateXor(a, b); - case T_and: return B->CreateAnd(a,b); - case T_or: return B->CreateOr(a,b); - case T_ne: case T_eq: case T_lt: case T_gt: case T_ge: case T_le: { - Value * v = emitCompare(exp->kind("operator"),typeOfValue(ao),a,b); + + Type *baseT = getPrimitiveType(t); + +#define RETURN_OP(op) \ + if (baseT->isIntegerTy()) { \ + return B->Create##op(a, b); \ + } else { \ + return B->CreateF##op(a, b); \ + } +#define RETURN_SOP(op) \ + if (baseT->isIntegerTy()) { \ + if (t->issigned) { \ + return B->CreateS##op(a, b); \ + } else { \ + return B->CreateU##op(a, b); \ + } \ + } else { \ + return B->CreateF##op(a, b); \ + } + switch (kind) { + case T_add: + RETURN_OP(Add) break; + case T_sub: + RETURN_OP(Sub) break; + case T_mul: + RETURN_OP(Mul) break; + case T_div: + RETURN_SOP(Div) break; + case T_mod: + RETURN_SOP(Rem) break; + case T_pow: + return B->CreateXor(a, b); + case T_and: + return B->CreateAnd(a, b); + case T_or: + return B->CreateOr(a, b); + case T_ne: + case T_eq: + case T_lt: + case T_gt: + case T_ge: + case T_le: { + Value *v = emitCompare(exp->kind("operator"), typeOfValue(ao), a, b); return B->CreateZExt(v, t->type); } break; case T_lshift: return B->CreateShl(a, b); break; case T_rshift: - if(at->issigned) + if (at->issigned) return B->CreateAShr(a, b); else return B->CreateLShr(a, b); @@ -1781,173 +1861,178 @@ if(baseT->isIntegerTy()) { \ } #undef RETURN_OP #undef RETURN_SOP - // should not be reachable - every case above should either return or assert - return 0; + // should not be reachable - every case above should either return or assert + return 0; } - Value * emitArrayToPointer(Obj * exp) { - Value * v = emitAddressOf(exp); - return CreateConstGEP2_32(B,v,0,0); + Value *emitArrayToPointer(Obj *exp) { + Value *v = emitAddressOf(exp); + return CreateConstGEP2_32(B, v, 0, 0); } - Type * getPrimitiveType(TType * t) { - if(t->type->isVectorTy()) + Type *getPrimitiveType(TType *t) { + if (t->type->isVectorTy()) return cast(t->type)->getElementType(); else return t->type; } - Value * emitPrimitiveCast(TType * from, TType * to, Value * exp) { - - Type * fBase = getPrimitiveType(from); - Type * tBase = getPrimitiveType(to); - + Value *emitPrimitiveCast(TType *from, TType *to, Value *exp) { + Type *fBase = getPrimitiveType(from); + Type *tBase = getPrimitiveType(to); + int fsize = fBase->getPrimitiveSizeInBits(); int tsize = tBase->getPrimitiveSizeInBits(); - - if(fBase->isIntegerTy()) { - if(tBase->isIntegerTy()) { + + if (fBase->isIntegerTy()) { + if (tBase->isIntegerTy()) { return B->CreateIntCast(exp, to->type, from->issigned); - } else if(tBase->isFloatingPointTy()) { - if(from->issigned) { + } else if (tBase->isFloatingPointTy()) { + if (from->issigned) { return B->CreateSIToFP(exp, to->type); } else { return B->CreateUIToFP(exp, to->type); } - } else goto nyi; - } else if(fBase->isFloatingPointTy()) { - if(tBase->isIntegerTy()) { - if(to->issigned) { + } else + goto nyi; + } else if (fBase->isFloatingPointTy()) { + if (tBase->isIntegerTy()) { + if (to->issigned) { return B->CreateFPToSI(exp, to->type); } else { return B->CreateFPToUI(exp, to->type); } - } else if(tBase->isFloatingPointTy()) { - if(fsize < tsize) { + } else if (tBase->isFloatingPointTy()) { + if (fsize < tsize) { return B->CreateFPExt(exp, to->type); } else { return B->CreateFPTrunc(exp, to->type); } - } else goto nyi; - } else goto nyi; + } else + goto nyi; + } else + goto nyi; nyi: assert(!"NYI - casts"); return NULL; - } - Value * emitBroadcast(TType * fromT, TType * toT, Value * v) { - Value * result = UndefValue::get(toT->type); - VectorType * vt = cast(toT->type); - Type * integerType = Type::getInt32Ty(*CU->TT->ctx); - for(size_t i = 0; i < vt->getNumElements(); i++) + Value *emitBroadcast(TType *fromT, TType *toT, Value *v) { + Value *result = UndefValue::get(toT->type); + VectorType *vt = cast(toT->type); + Type *integerType = Type::getInt32Ty(*CU->TT->ctx); + for (size_t i = 0; i < vt->getNumElements(); i++) result = B->CreateInsertElement(result, v, ConstantInt::get(integerType, i)); return result; } - bool isPointerToFunction(Type * t) { + bool isPointerToFunction(Type *t) { return t->isPointerTy() && t->getPointerElementType()->isFunctionTy(); } - Value * emitStructSelect(Obj * structType, Value * structPtr, int index) { - + Value *emitStructSelect(Obj *structType, Value *structPtr, int index) { assert(structPtr->getType()->isPointerTy()); - PointerType * objTy = cast(structPtr->getType()); + PointerType *objTy = cast(structPtr->getType()); assert(objTy->getElementType()->isStructTy()); Ty->EnsureTypeIsComplete(structType); - + Obj layout; - GetStructEntries(structType,&layout); - + GetStructEntries(structType, &layout); + Obj entry; - layout.objAt(index,&entry); - + layout.objAt(index, &entry); + int allocindex = entry.number("allocation"); - - Value * addr = CreateConstGEP2_32(B,structPtr,0,allocindex); - //in three cases the type of the value in the struct does not match the expected type returned - //1. if it is a union then the llvm struct will have some buffer space to hold the object but + + Value *addr = CreateConstGEP2_32(B, structPtr, 0, allocindex); + // in three cases the type of the value in the struct does not match the expected + // type returned + // 1. if it is a union then the llvm struct will have some buffer space to hold + // the object but // the space may have a different type - //2. if the struct was imported from Clang and the value is a function pointer (Terra internal represents functions with i8* for simplicity) - //3. if the field was an anonymous C struct, so we don't know its name - //in all cases we simply bitcast cast the resulting pointer to the expected type + // 2. if the struct was imported from Clang and the value is a function pointer + // (Terra internal represents functions with i8* for simplicity) + // 3. if the field was an anonymous C struct, so we don't know its name + // in all cases we simply bitcast cast the resulting pointer to the expected type Obj entryType; - entry.obj("type",&entryType); - if (entry.boolean("inunion") || isPointerToFunction(addr->getType()->getPointerElementType())) { - Type * resultType = PointerType::getUnqual(getType(&entryType)->type); + entry.obj("type", &entryType); + if (entry.boolean("inunion") || + isPointerToFunction(addr->getType()->getPointerElementType())) { + Type *resultType = PointerType::getUnqual(getType(&entryType)->type); addr = B->CreateBitCast(addr, resultType); } - + return addr; } - Value *emitStore(Value* value, Value *addr, bool isVolatile, bool hasAlignment, int alignment) { - LoadInst *l = dyn_cast(&*value); - Type *t1 = value->getType(); - if (t1->isStructTy() && l) { - // create bitcasts of src and dest address - Type* t = Type::getInt8PtrTy(*CU->TT->ctx); - // addr_dst - Value *addr_dst = B->CreateBitCast(addr, t); - // addr_src - Value* addr_src = l->getOperand(0); - addr_src = B->CreateBitCast(addr_src, t); - // size of bytes to copy - StructType *st = cast(t1); - const StructLayout *sl = CU->getDataLayout().getStructLayout(st); - uint64_t size = sl->getSizeInBytes(); - Value *size_v = ConstantInt::get(Type::getInt64Ty(*CU->TT->ctx),size); - int al = hasAlignment ? alignment: sl->getAlignment(); - // perform the copy + Value *emitStore(Value *value, Value *addr, bool isVolatile, bool hasAlignment, + int alignment) { + LoadInst *l = dyn_cast(&*value); + Type *t1 = value->getType(); + if (t1->isStructTy() && l) { + // create bitcasts of src and dest address + Type *t = Type::getInt8PtrTy(*CU->TT->ctx); + // addr_dst + Value *addr_dst = B->CreateBitCast(addr, t); + // addr_src + Value *addr_src = l->getOperand(0); + addr_src = B->CreateBitCast(addr_src, t); + // size of bytes to copy + StructType *st = cast(t1); + const StructLayout *sl = CU->getDataLayout().getStructLayout(st); + uint64_t size = sl->getSizeInBytes(); + Value *size_v = ConstantInt::get(Type::getInt64Ty(*CU->TT->ctx), size); + int al = hasAlignment ? alignment : sl->getAlignment(); + // perform the copy #if LLVM_VERSION <= 60 - Value* m = B->CreateMemCpy(addr_dst, addr_src, size_v, al, isVolatile); + Value *m = B->CreateMemCpy(addr_dst, addr_src, size_v, al, isVolatile); #else - Value* m = B->CreateMemCpy(addr_dst, al, addr_src, sl->getAlignment(), size_v, isVolatile); -#endif - return m; - } - StoreInst *st = B->CreateStore(value, addr); - if (isVolatile) - st->setVolatile(true); - if (hasAlignment) - st->setAlignment(alignment); - return st; - } - - Value * emitIfElse(Obj * cond, Obj * a, Obj * b) { - Value * condExp = emitExp(cond); - Value * aExp = emitExp(a); - Value * bExp = emitExp(b); - condExp = emitCond(condExp); //convert to i1 + Value *m = B->CreateMemCpy(addr_dst, al, addr_src, sl->getAlignment(), size_v, + isVolatile); +#endif + return m; + } + StoreInst *st = B->CreateStore(value, addr); + if (isVolatile) st->setVolatile(true); + if (hasAlignment) st->setAlignment(alignment); + return st; + } + + Value *emitIfElse(Obj *cond, Obj *a, Obj *b) { + Value *condExp = emitExp(cond); + Value *aExp = emitExp(a); + Value *bExp = emitExp(b); + condExp = emitCond(condExp); // convert to i1 return B->CreateSelect(condExp, aExp, bExp); } - Value * emitExp(Obj * exp, bool loadlvalue = true) { - Value * raw = emitExpRaw(exp); - if(loadlvalue && exp->boolean("lvalue")) { + Value *emitExp(Obj *exp, bool loadlvalue = true) { + Value *raw = emitExpRaw(exp); + if (loadlvalue && exp->boolean("lvalue")) { Obj type; - exp->obj("type",&type); + exp->obj("type", &type); Ty->EnsureTypeIsComplete(&type); raw = B->CreateLoad(raw); } return raw; } - - Value * emitExpRaw(Obj * exp) { + + Value *emitExpRaw(Obj *exp) { setDebugPoint(exp); - switch(exp->kind("kind")) { - case T_var: { + switch (exp->kind("kind")) { + case T_var: { Obj sym; - exp->obj("symbol",&sym); - Value * v = NULL; - for(Locals * f = locals; v == NULL && f != NULL; f = f->prev) { - v = lookupSymbol(&f->cur,&sym); + exp->obj("symbol", &sym); + Value *v = NULL; + for (Locals *f = locals; v == NULL && f != NULL; f = f->prev) { + v = lookupSymbol(&f->cur, &sym); } assert(v); return v; } break; - case T_globalvalueref: { + case T_globalvalueref: { Obj global; - exp->obj("value",&global); - if(T_globalvariable == global.kind("kind")) { - return EmitGlobalVariable(CU,&global,exp->string("name")); + exp->obj("value", &global); + if (T_globalvariable == global.kind("kind")) { + return EmitGlobalVariable(CU, &global, exp->string("name")); } else { - //functions are represented with &int8 pointers to avoid - //calling convension issues, so cast the literal to this type now - return B->CreateBitCast(EmitFunction(CU, &global, fstate),typeOfValue(exp)->type); + // functions are represented with &int8 pointers to avoid + // calling convension issues, so cast the literal to this type now + return B->CreateBitCast(EmitFunction(CU, &global, fstate), + typeOfValue(exp)->type); } } break; case T_allocvar: { @@ -1956,47 +2041,46 @@ if(baseT->isIntegerTy()) { \ case T_letin: { Locals buf; enterScope(&buf); - Value * v = emitLetIn(exp); + Value *v = emitLetIn(exp); leaveScope(); return v; } break; case T_operator: { - Obj exps; - exp->obj("operands",&exps); + exp->obj("operands", &exps); int N = exps.size(); - if(N == 1) { + if (N == 1) { Obj a; - exps.objAt(0,&a); - return emitUnary(exp,&a); - } else if(N == 2) { - Obj a,b; - exps.objAt(0,&a); - exps.objAt(1,&b); - return emitBinary(exp,&a,&b); + exps.objAt(0, &a); + return emitUnary(exp, &a); + } else if (N == 2) { + Obj a, b; + exps.objAt(0, &a); + exps.objAt(1, &b); + return emitBinary(exp, &a, &b); } else { T_Kind op = exp->kind("operator"); - if(op == T_select) { - Obj a,b,c; - exps.objAt(0,&a); - exps.objAt(1,&b); - exps.objAt(2,&c); - return emitIfElse(&a,&b,&c); + if (op == T_select) { + Obj a, b, c; + exps.objAt(0, &a); + exps.objAt(1, &b); + exps.objAt(2, &c); + return emitIfElse(&a, &b, &c); } exp->dump(); assert(!"NYI - unimplemented operator?"); return NULL; } - switch(exp->kind("operator")) { + switch (exp->kind("operator")) { case T_add: { - TType * t = typeOfValue(exp); + TType *t = typeOfValue(exp); Obj exps; - - if(t->type->isFPOrFPVectorTy()) { - Obj a,b; - exps.objAt(0,&a); - exps.objAt(1,&b); - return B->CreateFAdd(emitExp(&a),emitExp(&b)); + + if (t->type->isFPOrFPVectorTy()) { + Obj a, b; + exps.objAt(0, &a); + exps.objAt(1, &b); + return B->CreateFAdd(emitExp(&a), emitExp(&b)); } else { assert(!"NYI - integer +"); } @@ -2005,70 +2089,71 @@ if(baseT->isIntegerTy()) { \ assert(!"NYI - op"); } break; } - + } break; case T_index: { Obj value; Obj idx; - exp->obj("value",&value); - exp->obj("index",&idx); - + exp->obj("value", &value); + exp->obj("index", &idx); + Obj aggTypeO; - value.obj("type",&aggTypeO); - TType * aggType = getType(&aggTypeO); - Value * valueExp = emitExp(&value); - Value * idxExp = emitExp(&idx); - - //if this is a vector index, emit an extractElement - if(aggType->type->isVectorTy()) { - idxExp = emitIndex(typeOfValue(&idx),32,idxExp); - Value * result = B->CreateExtractElement(valueExp, idxExp); + value.obj("type", &aggTypeO); + TType *aggType = getType(&aggTypeO); + Value *valueExp = emitExp(&value); + Value *idxExp = emitExp(&idx); + + // if this is a vector index, emit an extractElement + if (aggType->type->isVectorTy()) { + idxExp = emitIndex(typeOfValue(&idx), 32, idxExp); + Value *result = B->CreateExtractElement(valueExp, idxExp); return result; } else { - idxExp = emitIndex(typeOfValue(&idx),64,idxExp); - //otherwise we have a pointer access which will use a GEP instruction - std::vector idxs; + idxExp = emitIndex(typeOfValue(&idx), 64, idxExp); + // otherwise we have a pointer access which will use a GEP instruction + std::vector idxs; Ty->EnsurePointsToCompleteType(&aggTypeO); - Value * result = B->CreateGEP(valueExp, idxExp); - if(!exp->boolean("lvalue")) - result = B->CreateLoad(result); + Value *result = B->CreateGEP(valueExp, idxExp); + if (!exp->boolean("lvalue")) result = B->CreateLoad(result); return result; } } break; case T_literal: { Obj type; exp->obj("type", &type); - TType * t = getType(&type); - if(t->islogical) { - bool b = exp->boolean("value"); - return ConstantInt::get(t->type,b); - } else if(t->type->isIntegerTy()) { + TType *t = getType(&type); + if (t->islogical) { + bool b = exp->boolean("value"); + return ConstantInt::get(t->type, b); + } else if (t->type->isIntegerTy()) { uint64_t integer = exp->integer("value"); return ConstantInt::get(t->type, integer); - } else if(t->type->isFloatingPointTy()) { + } else if (t->type->isFloatingPointTy()) { double dbl = exp->number("value"); return ConstantFP::get(t->type, dbl); - } else if(t->type->isPointerTy()) { - PointerType * pt = cast(t->type); - if(type.kind("kind") == T_niltype) { + } else if (t->type->isPointerTy()) { + PointerType *pt = cast(t->type); + if (type.kind("kind") == T_niltype) { return ConstantPointerNull::get(pt); } - + Obj objType; - type.obj("type",&objType); - if(t->type->getPointerElementType()->isIntegerTy(8)) { + type.obj("type", &objType); + if (t->type->getPointerElementType()->isIntegerTy(8)) { Obj stringvalue; - exp->obj("value",&stringvalue); - Value * str = lookupSymbol(CU->symbols, &stringvalue); - if(!str) { + exp->obj("value", &stringvalue); + Value *str = lookupSymbol(CU->symbols, &stringvalue); + if (!str) { exp->pushfield("value"); size_t len; - const char * rawstr = lua_tolstring(L,-1,&len); - str = B->CreateGlobalString(StringRef(rawstr,len),"$string"); //needs a name to make mcjit work in 3.5 - lua_pop(L,1); + const char *rawstr = lua_tolstring(L, -1, &len); + str = B->CreateGlobalString( + StringRef(rawstr, len), + "$string"); // needs a name to make mcjit work in 3.5 + lua_pop(L, 1); mapSymbol(CU->symbols, &stringvalue, str); } - return B->CreateBitCast(str, pt); + return B->CreateBitCast(str, pt); } else { assert(!"NYI - pointer literal"); } @@ -2078,196 +2163,207 @@ if(baseT->isIntegerTy()) { \ } } break; case T_constant: { - TType * typ = typeOfValue(exp); + TType *typ = typeOfValue(exp); Obj value; exp->pushfield("value"); - const void * data = lua_topointer(L,-1); + const void *data = lua_topointer(L, -1); assert(data); size_t size = CU->getDataLayout().getTypeAllocSize(typ->type); - Value * r; - if(typ->type->isIntegerTy()) { + Value *r; + if (typ->type->isIntegerTy()) { uint64_t integer = 0; - memcpy(&integer,data,size); //note: assuming little endian, there is probably a better way to do this + memcpy(&integer, data, size); // note: assuming little endian, there + // is probably a better way to do this r = ConstantInt::get(typ->type, integer); - } else if(typ->type->isFloatTy()) { - r = ConstantFP::get(typ->type, *(const float*)data); - } else if(typ->type->isDoubleTy()) { - r = ConstantFP::get(typ->type, *(const double*)data); - } else if(typ->type->isPointerTy()) { - Constant * ptrint = ConstantInt::get(CU->getDataLayout().getIntPtrType(*CU->TT->ctx), *(const intptr_t*)data); + } else if (typ->type->isFloatTy()) { + r = ConstantFP::get(typ->type, *(const float *)data); + } else if (typ->type->isDoubleTy()) { + r = ConstantFP::get(typ->type, *(const double *)data); + } else if (typ->type->isPointerTy()) { + Constant *ptrint = ConstantInt::get( + CU->getDataLayout().getIntPtrType(*CU->TT->ctx), + *(const intptr_t *)data); r = ConstantExpr::getIntToPtr(ptrint, typ->type); } else { TERRA_DUMP_TYPE(typ->type); assert(!"NYI - constant load\n"); } - lua_pop(L,1); // remove pointer + lua_pop(L, 1); // remove pointer return r; } break; case T_apply: { - return emitCall(exp,false); + return emitCall(exp, false); } break; case T_structcast: { - Obj expression,structvariable,to; - exp->obj("expression",&expression); - //allocate memory to hold input variable + Obj expression, structvariable, to; + exp->obj("expression", &expression); + // allocate memory to hold input variable exp->obj("structvariable", &structvariable); - exp->obj("type",&to); - TType * toT = getType(&to); - Value * sv = allocVar(&structvariable); - B->CreateStore(emitExp(&expression),sv); - - //allocate temporary to hold output variable - //type must be complete before we try to allocate space for it - //this is enforced by the callers + exp->obj("type", &to); + TType *toT = getType(&to); + Value *sv = allocVar(&structvariable); + B->CreateStore(emitExp(&expression), sv); + + // allocate temporary to hold output variable + // type must be complete before we try to allocate space for it + // this is enforced by the callers assert(!toT->incomplete); - Value * output = CreateAlloca(B,toT->type); - + Value *output = CreateAlloca(B, toT->type); + Obj entries; - exp->obj("entries",&entries); + exp->obj("entries", &entries); int N = entries.size(); - - for(int i = 0; i < N; i++) { + + for (int i = 0; i < N; i++) { Obj entry; - entries.objAt(i,&entry); + entries.objAt(i, &entry); Obj value; entry.obj("value", &value); int idx = entry.number("index"); - Value * oe = emitStructSelect(&to,output,idx); - Value * in = emitExp(&value); //these expressions will select from the structvariable and perform any casts necessary - B->CreateStore(in,oe); + Value *oe = emitStructSelect(&to, output, idx); + Value *in = emitExp( + &value); // these expressions will select from the + // structvariable and perform any casts necessary + B->CreateStore(in, oe); } return B->CreateLoad(output); } break; case T_cast: { Obj a; - Obj to,from; - exp->obj("expression",&a); - exp->obj("to",&to); - a.obj("type",&from); - TType * fromT = getType(&from); - TType * toT = getType(&to); - if(fromT->type->isArrayTy()) { + Obj to, from; + exp->obj("expression", &a); + exp->obj("to", &to); + a.obj("type", &from); + TType *fromT = getType(&from); + TType *toT = getType(&to); + if (fromT->type->isArrayTy()) { return emitArrayToPointer(&a); } - Value * v = emitExp(&a); - if(fromT->type->isPointerTy()) { - if(toT->type->isPointerTy()) { + Value *v = emitExp(&a); + if (fromT->type->isPointerTy()) { + if (toT->type->isPointerTy()) { return B->CreateBitCast(v, toT->type); } else { assert(toT->type->isIntegerTy()); return B->CreatePtrToInt(v, toT->type); } - } else if(toT->type->isPointerTy()) { + } else if (toT->type->isPointerTy()) { assert(fromT->type->isIntegerTy()); return B->CreateIntToPtr(v, toT->type); - } else if(toT->type->isVectorTy()) { - if(fromT->type->isVectorTy()) - return emitPrimitiveCast(fromT,toT,v); + } else if (toT->type->isVectorTy()) { + if (fromT->type->isVectorTy()) + return emitPrimitiveCast(fromT, toT, v); else return emitBroadcast(fromT, toT, v); } else { - return emitPrimitiveCast(fromT,toT,v); + return emitPrimitiveCast(fromT, toT, v); } } break; case T_sizeof: { Obj typ; - exp->obj("oftype",&typ); - TType * tt = getType(&typ); - return ConstantInt::get(Type::getInt64Ty(*CU->TT->ctx),CU->getDataLayout().getTypeAllocSize(tt->type)); - } break; + exp->obj("oftype", &typ); + TType *tt = getType(&typ); + return ConstantInt::get(Type::getInt64Ty(*CU->TT->ctx), + CU->getDataLayout().getTypeAllocSize(tt->type)); + } break; case T_select: { - Obj obj,typ; - exp->obj("value",&obj); + Obj obj, typ; + exp->obj("value", &obj); /*TType * vt =*/typeOfValue(&obj); - - obj.obj("type",&typ); + + obj.obj("type", &typ); int offset = exp->number("index"); - - Value * v = emitAddressOf(&obj); - Value * result = emitStructSelect(&typ,v,offset); - if(!exp->boolean("lvalue")) - result = B->CreateLoad(result); + + Value *v = emitAddressOf(&obj); + Value *result = emitStructSelect(&typ, v, offset); + if (!exp->boolean("lvalue")) result = B->CreateLoad(result); return result; } break; - case T_constructor: case T_arrayconstructor: { + case T_constructor: + case T_arrayconstructor: { Obj expressions; - exp->obj("expressions",&expressions); - return emitConstructor(exp,&expressions); + exp->obj("expressions", &expressions); + return emitConstructor(exp, &expressions); } break; case T_vectorconstructor: { Obj expressions; - exp->obj("expressions",&expressions); + exp->obj("expressions", &expressions); std::vector values; - emitExpressionList(&expressions,true,&values); - TType * vecType = typeOfValue(exp); - Value * vec = UndefValue::get(vecType->type); - Type * intType = Type::getInt32Ty(*CU->TT->ctx); - for(size_t i = 0; i < values.size(); i++) { - vec = B->CreateInsertElement(vec, values[i], ConstantInt::get(intType, i)); + emitExpressionList(&expressions, true, &values); + TType *vecType = typeOfValue(exp); + Value *vec = UndefValue::get(vecType->type); + Type *intType = Type::getInt32Ty(*CU->TT->ctx); + for (size_t i = 0; i < values.size(); i++) { + vec = B->CreateInsertElement(vec, values[i], + ConstantInt::get(intType, i)); } return vec; } break; case T_inlineasm: { Obj arguments; - exp->obj("arguments",&arguments); + exp->obj("arguments", &arguments); std::vector values; - emitExpressionList(&arguments,true,&values); + emitExpressionList(&arguments, true, &values); Obj typ; - exp->obj("type",&typ); + exp->obj("type", &typ); bool isvoid = Ty->IsUnitType(&typ); - Type * ttype = getType(&typ)->type; - Type * rtype = (isvoid) ? Type::getVoidTy(*CU->TT->ctx) : ttype; - std::vector ptypes; - for(size_t i = 0; i < values.size(); i++) + Type *ttype = getType(&typ)->type; + Type *rtype = (isvoid) ? Type::getVoidTy(*CU->TT->ctx) : ttype; + std::vector ptypes; + for (size_t i = 0; i < values.size(); i++) ptypes.push_back(values[i]->getType()); - Value * fn = InlineAsm::get(FunctionType::get(rtype, ptypes, false),exp->string("asm"),exp->string("constraints"),exp->boolean("volatile")); - Value * call = B->CreateCall(fn,values); + Value *fn = InlineAsm::get(FunctionType::get(rtype, ptypes, false), + exp->string("asm"), exp->string("constraints"), + exp->boolean("volatile")); + Value *call = B->CreateCall(fn, values); return (isvoid) ? UndefValue::get(ttype) : call; } break; case T_attrload: { - Obj addr,type,attr; - exp->obj("type",&type); - exp->obj("address",&addr); - exp->obj("attrs",&attr); + Obj addr, type, attr; + exp->obj("type", &type); + exp->obj("address", &addr); + exp->obj("attrs", &attr); Ty->EnsureTypeIsComplete(&type); - LoadInst * l = B->CreateLoad(emitExp(&addr)); - if(attr.hasfield("alignment")) { + LoadInst *l = B->CreateLoad(emitExp(&addr)); + if (attr.hasfield("alignment")) { int alignment = attr.number("alignment"); l->setAlignment(alignment); } - if(attr.boolean("nontemporal")) { - #if LLVM_VERSION <= 35 + if (attr.boolean("nontemporal")) { +#if LLVM_VERSION <= 35 auto list = ConstantInt::get(Type::getInt32Ty(*CU->TT->ctx), 1); - #else - auto list = ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(*CU->TT->ctx), 1)); - #endif +#else + auto list = ConstantAsMetadata::get( + ConstantInt::get(Type::getInt32Ty(*CU->TT->ctx), 1)); +#endif l->setMetadata("nontemporal", MDNode::get(*CU->TT->ctx, list)); } l->setVolatile(attr.boolean("isvolatile")); return l; } break; case T_attrstore: { - Obj addr,attr,value; - exp->obj("address",&addr); - exp->obj("attrs",&attr); - exp->obj("value",&value); - Value * addrexp = emitExp(&addr); - Value * valueexp = emitExp(&value); + Obj addr, attr, value; + exp->obj("address", &addr); + exp->obj("attrs", &attr); + exp->obj("value", &value); + Value *addrexp = emitExp(&addr); + Value *valueexp = emitExp(&value); bool isvolatile = attr.boolean("isvolatile"); bool hasalignment = attr.hasfield("alignment"); - int alignment=0; - if (hasalignment) - alignment = attr.number("alignment"); - Value *s = emitStore(valueexp, addrexp, isvolatile, hasalignment, alignment); - StoreInst * store = dyn_cast(s); + int alignment = 0; + if (hasalignment) alignment = attr.number("alignment"); + Value *s = + emitStore(valueexp, addrexp, isvolatile, hasalignment, alignment); + StoreInst *store = dyn_cast(s); if (store && attr.boolean("nontemporal")) { - #if LLVM_VERSION <= 35 +#if LLVM_VERSION <= 35 auto list = ConstantInt::get(Type::getInt32Ty(*CU->TT->ctx), 1); - #else - auto list = ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(*CU->TT->ctx), 1)); - #endif +#else + auto list = ConstantAsMetadata::get( + ConstantInt::get(Type::getInt32Ty(*CU->TT->ctx), 1)); +#endif store->setMetadata("nontemporal", MDNode::get(*CU->TT->ctx, list)); - } + } return Constant::getNullValue(typeOfValue(exp)->type); } break; case T_debuginfo: { @@ -2280,93 +2376,89 @@ if(baseT->isIntegerTy()) { \ assert(!"NYI - exp"); } break; } - // should not be reachable - every case above should either return or assert - return 0; - } - BasicBlock * createAndInsertBB(StringRef name) { - return BasicBlock::Create(*CU->TT->ctx, name,fstate->func); + // should not be reachable - every case above should either return or assert + return 0; } - void followsBB(BasicBlock * b) { - b->moveAfter(B->GetInsertBlock()); + BasicBlock *createAndInsertBB(StringRef name) { + return BasicBlock::Create(*CU->TT->ctx, name, fstate->func); } - Value * emitCond(Obj * cond) { - return emitCond(emitExp(cond)); - } - Value * emitCond(Value * cond) { - Type * resultType = Type::getInt1Ty(*CU->TT->ctx); - if(cond->getType()->isVectorTy()) { - VectorType * vt = cast(cond->getType()); - resultType = VectorType::get(resultType,vt->getNumElements()); + void followsBB(BasicBlock *b) { b->moveAfter(B->GetInsertBlock()); } + Value *emitCond(Obj *cond) { return emitCond(emitExp(cond)); } + Value *emitCond(Value *cond) { + Type *resultType = Type::getInt1Ty(*CU->TT->ctx); + if (cond->getType()->isVectorTy()) { + VectorType *vt = cast(cond->getType()); + resultType = VectorType::get(resultType, vt->getNumElements()); } return B->CreateTrunc(cond, resultType); } - void emitIfBranch(Obj * ifbranch, BasicBlock * footer) { - Obj cond,body; + void emitIfBranch(Obj *ifbranch, BasicBlock *footer) { + Obj cond, body; ifbranch->obj("condition", &cond); - ifbranch->obj("body",&body); - BasicBlock * thenBB = createAndInsertBB("then"); - BasicBlock * continueif = createAndInsertBB("else"); + ifbranch->obj("body", &body); + BasicBlock *thenBB = createAndInsertBB("then"); + BasicBlock *continueif = createAndInsertBB("else"); emitBranchOnExpr(&cond, thenBB, continueif); - + setInsertBlock(thenBB); - + emitStmt(&body); B->CreateBr(footer); followsBB(continueif); setInsertBlock(continueif); - } - + #ifdef DEBUG_INFO_WORKING - DIFileP createDebugInfoForFile(const char * filename) { - //checking the existence of a file once per function can be expensive, - //so only do it if debug mode is set to slow compile anyway. - //In the future, we can cache across functions calls if needed - if(T->options.debug > 1 && llvm::sys::fs::exists(filename)) { + DIFileP createDebugInfoForFile(const char *filename) { + // checking the existence of a file once per function can be expensive, + // so only do it if debug mode is set to slow compile anyway. + // In the future, we can cache across functions calls if needed + if (T->options.debug > 1 && llvm::sys::fs::exists(filename)) { SmallString<256> filepath = StringRef(filename); llvm::sys::fs::make_absolute(filepath); - return DB->createFile(llvm::sys::path::filename(filepath),llvm::sys::path::parent_path(filepath)); + return DB->createFile(llvm::sys::path::filename(filepath), + llvm::sys::path::parent_path(filepath)); } else { - return DB->createFile(filename,"."); + return DB->createFile(filename, "."); } } - MDNode * debugScopeForFile(const char * filename) { - StringMap::iterator it = filenamecache.find(filename); - if(it != filenamecache.end()) - return it->second; - MDNode * block = DB->createLexicalBlockFile(SP, createDebugInfoForFile(filename)); + MDNode *debugScopeForFile(const char *filename) { + StringMap::iterator it = filenamecache.find(filename); + if (it != filenamecache.end()) return it->second; + MDNode *block = DB->createLexicalBlockFile(SP, createDebugInfoForFile(filename)); filenamecache[filename] = block; return block; } - void initDebug(const char * filename, int lineno) { + void initDebug(const char *filename, int lineno) { customfilename = NULL; customlinenumber = 0; DEBUG_ONLY(T) { DB = new DIBuilder(*M); - + DIFileP file = createDebugInfoForFile(filename); - #if LLVM_VERSION >= 34 +#if LLVM_VERSION >= 34 DICompileUnit CU = - #endif - DB->createCompileUnit(1, "compilationunit", ".", "terra", true, "", 0); - #if LLVM_VERSION >= 36 - auto TA = DB->getOrCreateTypeArray(ArrayRef()); - #else - auto TA = DB->getOrCreateArray(ArrayRef()); - #endif +#endif + DB->createCompileUnit(1, "compilationunit", ".", "terra", true, "", + 0); +#if LLVM_VERSION >= 36 + auto TA = DB->getOrCreateTypeArray(ArrayRef()); +#else + auto TA = DB->getOrCreateArray(ArrayRef()); +#endif SP = DB->createFunction( - #if LLVM_VERSION >= 34 - CU, - #else - (DIDescriptor)DB->getCU(), - #endif - fstate->func->getName(), fstate->func->getName(), file, lineno, - DB->createSubroutineType(file, TA), - false, true, 0,0, true, fstate->func); - - if(!M->getModuleFlagsMetadata()) { - M->addModuleFlag(llvm::Module::Warning, "Dwarf Version",2); - M->addModuleFlag(llvm::Module::Warning, "Debug Info Version",1); +#if LLVM_VERSION >= 34 + CU, +#else + (DIDescriptor)DB->getCU(), +#endif + fstate->func->getName(), fstate->func->getName(), file, lineno, + DB->createSubroutineType(file, TA), false, true, 0, 0, true, + fstate->func); + + if (!M->getModuleFlagsMetadata()) { + M->addModuleFlag(llvm::Module::Warning, "Dwarf Version", 2); + M->addModuleFlag(llvm::Module::Warning, "Debug Info Version", 1); } filenamecache[filename] = SP; } @@ -2377,128 +2469,127 @@ if(baseT->isIntegerTy()) { \ delete DB; } } - void setDebugPoint(Obj * obj) { + void setDebugPoint(Obj *obj) { DEBUG_ONLY(T) { - MDNode * scope = debugScopeForFile(customfilename ? customfilename : obj->string("filename")); - B->SetCurrentDebugLocation(DebugLoc::get(customfilename ? customlinenumber : obj->number("linenumber"), 0, scope)); + MDNode *scope = debugScopeForFile(customfilename ? customfilename + : obj->string("filename")); + B->SetCurrentDebugLocation(DebugLoc::get( + customfilename ? customlinenumber : obj->number("linenumber"), 0, + scope)); } } #else - void initDebug(const char * filename, int lineno) {} + void initDebug(const char *filename, int lineno) {} void endDebug() {} - void setDebugPoint(Obj * obj) {} + void setDebugPoint(Obj *obj) {} #endif - void setInsertBlock(BasicBlock * bb) { - B->SetInsertPoint(bb); - } - void pushBreakpoint(BasicBlock * exit) { - breakpoints.push_back(std::make_pair(exit,deferred.size())); - } - void popBreakpoint() { - breakpoints.pop_back(); - } - BasicBlock * getOrCreateBlockForLabel(Obj * stmt, int * depth) { - Obj ident,lbl; - stmt->obj("label",&ident); - ident.obj("value",&lbl); - BasicBlock * bb = lookupSymbol(labels, &lbl); - if(!bb) { + void setInsertBlock(BasicBlock *bb) { B->SetInsertPoint(bb); } + void pushBreakpoint(BasicBlock *exit) { + breakpoints.push_back(std::make_pair(exit, deferred.size())); + } + void popBreakpoint() { breakpoints.pop_back(); } + BasicBlock *getOrCreateBlockForLabel(Obj *stmt, int *depth) { + Obj ident, lbl; + stmt->obj("label", &ident); + ident.obj("value", &lbl); + BasicBlock *bb = lookupSymbol(labels, &lbl); + if (!bb) { bb = createAndInsertBB(lbl.asstring("value")); mapSymbol(labels, &lbl, bb); } labeldepth->push(); lbl.push(); - lua_gettable(L,-2); - *depth = luaL_checknumber(L,-1); - lua_pop(L,2); + lua_gettable(L, -2); + *depth = luaL_checknumber(L, -1); + lua_pop(L, 2); return bb; } - Value * emitCall(Obj * call, bool defer) { + Value *emitCall(Obj *call, bool defer) { Obj paramlist; Obj paramtypes; Obj func; - - call->obj("arguments",¶mlist); - paramlist.pushfield("map"); //call arguments:map("type") to get paramtypes + + call->obj("arguments", ¶mlist); + paramlist.pushfield("map"); // call arguments:map("type") to get paramtypes paramlist.push(); - lua_pushstring(L,"type"); - lua_call(L,2,1); + lua_pushstring(L, "type"); + lua_call(L, 2, 1); paramlist.fromStack(¶mtypes); - - call->obj("value",&func); - - Value * fn = emitExp(&func); - + + call->obj("value", &func); + + Value *fn = emitExp(&func); + Obj fnptrtyp; - func.obj("type",&fnptrtyp); + func.obj("type", &fnptrtyp); Obj fntyp; - fnptrtyp.obj("type",&fntyp); - - std::vector actuals; - emitExpressionList(¶mlist,true,&actuals); - BasicBlock * cur = B->GetInsertBlock(); - if(defer) { - BasicBlock * bb = createAndInsertBB("defer"); + fnptrtyp.obj("type", &fntyp); + + std::vector actuals; + emitExpressionList(¶mlist, true, &actuals); + BasicBlock *cur = B->GetInsertBlock(); + if (defer) { + BasicBlock *bb = createAndInsertBB("defer"); setInsertBlock(bb); deferred.push_back(bb); } - Value * r = CC->EmitCall(B,&fntyp,¶mtypes, fn, &actuals); - setInsertBlock(cur); //defer may have changed it + Value *r = CC->EmitCall(B, &fntyp, ¶mtypes, fn, &actuals); + setInsertBlock(cur); // defer may have changed it return r; } - + void emitReturnUndef() { - Type * rt = fstate->func->getReturnType(); - if(rt->isVoidTy()) { + Type *rt = fstate->func->getReturnType(); + if (rt->isVoidTy()) { B->CreateRetVoid(); } else { B->CreateRet(UndefValue::get(rt)); } } - void emitExpressionList(Obj * exps, bool loadlvalue, std::vector * results) { + void emitExpressionList(Obj *exps, bool loadlvalue, std::vector *results) { int N = exps->size(); - for(int i = 0; i < N; i++) { + for (int i = 0; i < N; i++) { Obj exp; exps->objAt(i, &exp); - results->push_back(emitExp(&exp,loadlvalue)); + results->push_back(emitExp(&exp, loadlvalue)); } } - Value * emitConstructor(Obj * exp, Obj * expressions) { - Value * result = CreateAlloca(B,typeOfValue(exp)->type); + Value *emitConstructor(Obj *exp, Obj *expressions) { + Value *result = CreateAlloca(B, typeOfValue(exp)->type); std::vector values; - emitExpressionList(expressions,true,&values); - for(size_t i = 0; i < values.size(); i++) { - Value * addr = CreateConstGEP2_32(B,result,0,i); - B->CreateStore(values[i],addr); + emitExpressionList(expressions, true, &values); + for (size_t i = 0; i < values.size(); i++) { + Value *addr = CreateConstGEP2_32(B, result, 0, i); + B->CreateStore(values[i], addr); } return B->CreateLoad(result); } - void emitStmtList(Obj * stmts) { + void emitStmtList(Obj *stmts) { int NS = stmts->size(); - for(int i = 0; i < NS; i++) { + for (int i = 0; i < NS; i++) { Obj s; - stmts->objAt(i,&s); + stmts->objAt(i, &s); emitStmt(&s); } } - Value * emitLetIn(Obj * letin) { - Obj stmts,exps; - letin->obj("statements",&stmts); + Value *emitLetIn(Obj *letin) { + Obj stmts, exps; + letin->obj("statements", &stmts); emitStmtList(&stmts); - letin->obj("expressions",&exps); + letin->obj("expressions", &exps); if (exps.size() == 1) { Obj exp; - exps.objAt(0,&exp); - return emitExp(&exp,false); + exps.objAt(0, &exp); + return emitExp(&exp, false); } return emitConstructor(letin, &exps); } void startDeadCode() { - BasicBlock * bb = createAndInsertBB("dead"); + BasicBlock *bb = createAndInsertBB("dead"); setInsertBlock(bb); } - BasicBlock * copyBlock(BasicBlock * BB) { + BasicBlock *copyBlock(BasicBlock *BB) { ValueToValueMapTy VMap; BasicBlock *NewBB = CloneBasicBlock(BB, VMap, "", fstate->func); for (BasicBlock::iterator II = NewBB->begin(), IE = NewBB->end(); II != IE; ++II) @@ -2508,28 +2599,30 @@ if(baseT->isIntegerTy()) { \ #else RF_IgnoreMissingLocals #endif - ); + ); return NewBB; } - //emit an exit path that includes the most recent num deferred statements - //this is used by gotos,returns, and breaks. unlike scope ends it copies the dtor stack + // emit an exit path that includes the most recent num deferred statements + // this is used by gotos,returns, and breaks. unlike scope ends it copies the dtor + // stack void emitDeferred(size_t num) { - for(size_t i = 0; i < num; i++) { - BasicBlock * bb = deferred[deferred.size() - 1 - i]; + for (size_t i = 0; i < num; i++) { + BasicBlock *bb = deferred[deferred.size() - 1 - i]; bb = copyBlock(bb); B->CreateBr(bb); setInsertBlock(bb); } } - //unwind deferred and remove them from dtor stack, no need to copy the BB, since this is its last use + // unwind deferred and remove them from dtor stack, no need to copy the BB, since this + // is its last use void unwindDeferred(size_t to) { - for(; deferred.size() > to; deferred.pop_back()) { - BasicBlock * bb = deferred.back(); + for (; deferred.size() > to; deferred.pop_back()) { + BasicBlock *bb = deferred.back(); B->CreateBr(bb); setInsertBlock(bb); } } - void enterScope(Locals * buf) { + void enterScope(Locals *buf) { buf->prev = locals; newMap(&buf->cur); locals = buf; @@ -2538,33 +2631,34 @@ if(baseT->isIntegerTy()) { \ assert(locals); locals = locals->prev; } - void emitStmt(Obj * stmt) { + void emitStmt(Obj *stmt) { setDebugPoint(stmt); T_Kind kind = stmt->kind("kind"); - switch(kind) { + switch (kind) { case T_block: { Locals buf; enterScope(&buf); size_t N = deferred.size(); Obj stmts; - stmt->obj("statements",&stmts); + stmt->obj("statements", &stmts); emitStmtList(&stmts); unwindDeferred(N); leaveScope(); } break; case T_returnstat: { Obj exp; - stmt->obj("expression",&exp); - Value * result = emitExp(&exp);; + stmt->obj("expression", &exp); + Value *result = emitExp(&exp); + ; Obj ftype; - funcobj->obj("type",&ftype); + funcobj->obj("type", &ftype); emitDeferred(deferred.size()); - CC->EmitReturn(B,&ftype,fstate->func,result); + CC->EmitReturn(B, &ftype, fstate->func, result); startDeadCode(); } break; case T_label: { int depth; - BasicBlock * bb = getOrCreateBlockForLabel(stmt,&depth); + BasicBlock *bb = getOrCreateBlockForLabel(stmt, &depth); assert((size_t)depth == deferred.size()); B->CreateBr(bb); followsBB(bb); @@ -2572,7 +2666,7 @@ if(baseT->isIntegerTy()) { \ } break; case T_gotostat: { int depth; - BasicBlock * bb = getOrCreateBlockForLabel(stmt,&depth); + BasicBlock *bb = getOrCreateBlockForLabel(stmt, &depth); assert(deferred.size() >= (size_t)depth); emitDeferred(deferred.size() - depth); B->CreateBr(bb); @@ -2587,99 +2681,100 @@ if(baseT->isIntegerTy()) { \ startDeadCode(); } break; case T_whilestat: { - Obj cond,body; - stmt->obj("condition",&cond); - stmt->obj("body",&body); - BasicBlock * condBB = createAndInsertBB("condition"); - + Obj cond, body; + stmt->obj("condition", &cond); + stmt->obj("body", &body); + BasicBlock *condBB = createAndInsertBB("condition"); + B->CreateBr(condBB); setInsertBlock(condBB); - - BasicBlock * loopBody = createAndInsertBB("whilebody"); - BasicBlock * merge = createAndInsertBB("merge"); - + + BasicBlock *loopBody = createAndInsertBB("whilebody"); + BasicBlock *merge = createAndInsertBB("merge"); + pushBreakpoint(merge); - + emitBranchOnExpr(&cond, loopBody, merge); setInsertBlock(loopBody); emitStmt(&body); - - + B->CreateBr(condBB); - + followsBB(merge); setInsertBlock(merge); popBreakpoint(); - + } break; case T_fornum: { - Obj initial,step,limit,variable,body; - stmt->obj("initial",&initial); - bool hasstep = stmt->obj("step",&step); - stmt->obj("limit",&limit); - stmt->obj("variable",&variable); - stmt->obj("body",&body); - TType * t = typeOfValue(&variable); - Value * initialv = emitExp(&initial); - Value * limitv = emitExp(&limit); - Value * stepv = (hasstep) ? emitExp(&step) : ConstantInt::get(t->type,1); - Value * vp = emitExp(&variable,false); - Value * zero = ConstantInt::get(t->type,0); + Obj initial, step, limit, variable, body; + stmt->obj("initial", &initial); + bool hasstep = stmt->obj("step", &step); + stmt->obj("limit", &limit); + stmt->obj("variable", &variable); + stmt->obj("body", &body); + TType *t = typeOfValue(&variable); + Value *initialv = emitExp(&initial); + Value *limitv = emitExp(&limit); + Value *stepv = (hasstep) ? emitExp(&step) : ConstantInt::get(t->type, 1); + Value *vp = emitExp(&variable, false); + Value *zero = ConstantInt::get(t->type, 0); B->CreateStore(initialv, vp); - BasicBlock * cond = createAndInsertBB("forcond"); + BasicBlock *cond = createAndInsertBB("forcond"); B->CreateBr(cond); setInsertBlock(cond); - Value * v = B->CreateLoad(vp); - Value * c = B->CreateOr(B->CreateAnd(emitCompare(T_lt,t, v, limitv), emitCompare(T_gt,t,stepv,zero)), - B->CreateAnd(emitCompare(T_gt,t, v, limitv), emitCompare(T_le,t,stepv,zero))); - BasicBlock * loopBody = createAndInsertBB("forbody"); - BasicBlock * merge = createAndInsertBB("merge"); + Value *v = B->CreateLoad(vp); + Value *c = B->CreateOr(B->CreateAnd(emitCompare(T_lt, t, v, limitv), + emitCompare(T_gt, t, stepv, zero)), + B->CreateAnd(emitCompare(T_gt, t, v, limitv), + emitCompare(T_le, t, stepv, zero))); + BasicBlock *loopBody = createAndInsertBB("forbody"); + BasicBlock *merge = createAndInsertBB("merge"); pushBreakpoint(merge); - B->CreateCondBr(c,loopBody,merge); + B->CreateCondBr(c, loopBody, merge); setInsertBlock(loopBody); emitStmt(&body); - B->CreateStore(B->CreateAdd(v, stepv),vp); + B->CreateStore(B->CreateAdd(v, stepv), vp); B->CreateBr(cond); followsBB(merge); setInsertBlock(merge); - + popBreakpoint(); } break; case T_ifstat: { Obj branches; - stmt->obj("branches",&branches); + stmt->obj("branches", &branches); int N = branches.size(); - BasicBlock * footer = createAndInsertBB("merge"); - for(int i = 0; i < N; i++) { + BasicBlock *footer = createAndInsertBB("merge"); + for (int i = 0; i < N; i++) { Obj branch; - branches.objAt(i,&branch); - emitIfBranch(&branch,footer); + branches.objAt(i, &branch); + emitIfBranch(&branch, footer); } Obj orelse; - if(stmt->obj("orelse",&orelse)) - emitStmt(&orelse); + if (stmt->obj("orelse", &orelse)) emitStmt(&orelse); B->CreateBr(footer); followsBB(footer); setInsertBlock(footer); } break; case T_repeatstat: { - Obj cond,statements; - stmt->obj("condition",&cond); - stmt->obj("statements",&statements); - - BasicBlock * loopBody = createAndInsertBB("repeatbody"); - BasicBlock * merge = createAndInsertBB("merge"); - + Obj cond, statements; + stmt->obj("condition", &cond); + stmt->obj("statements", &statements); + + BasicBlock *loopBody = createAndInsertBB("repeatbody"); + BasicBlock *merge = createAndInsertBB("merge"); + pushBreakpoint(merge); - + B->CreateBr(loopBody); setInsertBlock(loopBody); size_t N = deferred.size(); emitStmtList(&statements); - if(N < deferred.size()) { //because the body and the conditional are in the same block scope - //we need special handling for deferred - //along the back edge of the loop we must emit the deferred blocks - BasicBlock * backedge = createAndInsertBB("repeatdeferred"); + if (N < deferred.size()) { // because the body and the conditional are in + // the same block scope we need special + // handling for deferred along the back edge of + // the loop we must emit the deferred blocks + BasicBlock *backedge = createAndInsertBB("repeatdeferred"); setInsertBlock(backedge); emitDeferred(deferred.size() - N); B->CreateBr(loopBody); @@ -2690,168 +2785,186 @@ if(baseT->isIntegerTy()) { \ followsBB(merge); setInsertBlock(merge); unwindDeferred(N); - + popBreakpoint(); } break; case T_assignment: { std::vector rhsexps; Obj rhss; - stmt->obj("rhs",&rhss); - emitExpressionList(&rhss,true,&rhsexps); + stmt->obj("rhs", &rhss); + emitExpressionList(&rhss, true, &rhsexps); Obj lhss; - stmt->obj("lhs",&lhss); + stmt->obj("lhs", &lhss); int N = lhss.size(); - for(int i = 0; i < N; i++) { + for (int i = 0; i < N; i++) { Obj lhs; - lhss.objAt(i,&lhs); - if(lhs.kind("kind") == T_setter) { - Obj rhsvar,setter; - lhs.obj("rhs",&rhsvar); - lhs.obj("setter",&setter); - Value * rhsvarV = emitExp(&rhsvar,false); - B->CreateStore(rhsexps[i],rhsvarV); + lhss.objAt(i, &lhs); + if (lhs.kind("kind") == T_setter) { + Obj rhsvar, setter; + lhs.obj("rhs", &rhsvar); + lhs.obj("setter", &setter); + Value *rhsvarV = emitExp(&rhsvar, false); + B->CreateStore(rhsexps[i], rhsvarV); emitExp(&setter); } else { - emitStore(rhsexps[i],emitExp(&lhs,false), /* isVolatile */ false, /*hasAlignment*/ false, 0); + emitStore(rhsexps[i], emitExp(&lhs, false), + /* isVolatile */ false, /*hasAlignment*/ false, 0); } } } break; case T_defer: { Obj expression; - stmt->obj("expression",&expression); + stmt->obj("expression", &expression); emitCall(&expression, true); } break; default: { - emitExp(stmt,false); + emitExp(stmt, false); } break; } } }; -static Constant * EmitConstantInitializer(TerraCompilationUnit * CU, Obj * v) { +static Constant *EmitConstantInitializer(TerraCompilationUnit *CU, Obj *v) { FunctionEmitter fe(CU); return fe.emitConstantExpression(v); } -Function * EmitFunction(TerraCompilationUnit * CU, Obj * funcdecl, TerraFunctionState * user) { +Function *EmitFunction(TerraCompilationUnit *CU, Obj *funcdecl, + TerraFunctionState *user) { Obj funcdefn; funcdecl->obj("definition", &funcdefn); FunctionEmitter fe(CU); - TerraFunctionState * result = fe.emitFunction(&funcdefn); - if(user && result->onstack) - user->lowlink = std::min(user->lowlink,result->lowlink); // Tarjan's scc algorithm + TerraFunctionState *result = fe.emitFunction(&funcdefn); + if (user && result->onstack) + user->lowlink = + std::min(user->lowlink, result->lowlink); // Tarjan's scc algorithm return result->func; } -static int terra_compilationunitaddvalue(lua_State * L) { //entry point into compiler from lua code - terra_State * T = terra_getstate(L, 1); - GlobalValue * gv; - //create lua table to hold object references anchored on stack +static int terra_compilationunitaddvalue( + lua_State *L) { // entry point into compiler from lua code + terra_State *T = terra_getstate(L, 1); + GlobalValue *gv; + // create lua table to hold object references anchored on stack int ref_table = lobj_newreftable(T->L); { - Obj cu,globals,value; - lua_pushvalue(L,COMPILATION_UNIT_POS); //the compilation unit - cu.initFromStack(L,ref_table); + Obj cu, globals, value; + lua_pushvalue(L, COMPILATION_UNIT_POS); // the compilation unit + cu.initFromStack(L, ref_table); cu.obj("symbols", &globals); - const char * modulename = (lua_isnil(L,2)) ? NULL : lua_tostring(L,2); - lua_pushvalue(L,3); //the function definition + const char *modulename = (lua_isnil(L, 2)) ? NULL : lua_tostring(L, 2); + lua_pushvalue(L, 3); // the function definition cu.fromStack(&value); - TerraCompilationUnit * CU = (TerraCompilationUnit*) cu.cd("llvm_cu"); assert(CU); - + TerraCompilationUnit *CU = (TerraCompilationUnit *)cu.cd("llvm_cu"); + assert(CU); + Types Ty(CU); - CCallingConv CC(CU,&Ty); + CCallingConv CC(CU, &Ty); std::vector tooptimize; - CU->Ty = &Ty; CU->CC = &CC; CU->symbols = &globals; CU->tooptimize = &tooptimize; - if(value.kind("kind") == T_globalvariable) { - gv = EmitGlobalVariable(CU,&value,"anon"); + CU->Ty = &Ty; + CU->CC = &CC; + CU->symbols = &globals; + CU->tooptimize = &tooptimize; + if (value.kind("kind") == T_globalvariable) { + gv = EmitGlobalVariable(CU, &value, "anon"); } else { - gv = EmitFunction(CU,&value,NULL); - } - gv->setLinkage(GlobalValue::ExternalLinkage); // User explicitly exported this function. - CU->Ty = NULL; CU->CC = NULL; CU->symbols = NULL; CU->tooptimize = NULL; - if(modulename) { - if(GlobalValue * gv2 = CU->M->getNamedValue(modulename)) - gv2->setName(Twine(StringRef(modulename),"_renamed")); //rename anything else that has this name - gv->setName(modulename); //and set our function to this name - assert(gv->getName() == modulename); //make sure it worked + gv = EmitFunction(CU, &value, NULL); } - //cleanup -- ensure we left the stack the way we started + gv->setLinkage( + GlobalValue::ExternalLinkage); // User explicitly exported this function. + CU->Ty = NULL; + CU->CC = NULL; + CU->symbols = NULL; + CU->tooptimize = NULL; + if (modulename) { + if (GlobalValue *gv2 = CU->M->getNamedValue(modulename)) + gv2->setName( + Twine(StringRef(modulename), + "_renamed")); // rename anything else that has this name + gv->setName(modulename); // and set our function to this name + assert(gv->getName() == modulename); // make sure it worked + } + // cleanup -- ensure we left the stack the way we started assert(lua_gettop(T->L) == ref_table); - } //scope to ensure that all Obj held in the compiler are destroyed before we pop the reference table off the stack - lobj_removereftable(T->L,ref_table); - lua_pushlightuserdata(L,gv); + } // scope to ensure that all Obj held in the compiler are destroyed before we pop + // the reference table off the stack + lobj_removereftable(T->L, ref_table); + lua_pushlightuserdata(L, gv); return 1; } -static int terra_llvmsizeof(lua_State * L) { - terra_State * T = terra_getstate(L, 1); +static int terra_llvmsizeof(lua_State *L) { + terra_State *T = terra_getstate(L, 1); int ref_table = lobj_newreftable(L); - TType * llvmtyp; TerraCompilationUnit * CU; + TType *llvmtyp; + TerraCompilationUnit *CU; { - Obj cu,typ,globals; - lua_pushvalue(L,1); - cu.initFromStack(L,ref_table); - lua_pushvalue(L,2); - typ.initFromStack(L,ref_table); - cu.obj("symbols",&globals); - CU = (TerraCompilationUnit*)cu.cd("llvm_cu"); + Obj cu, typ, globals; + lua_pushvalue(L, 1); + cu.initFromStack(L, ref_table); + lua_pushvalue(L, 2); + typ.initFromStack(L, ref_table); + cu.obj("symbols", &globals); + CU = (TerraCompilationUnit *)cu.cd("llvm_cu"); CU->symbols = &globals; llvmtyp = Types(CU).Get(&typ); CU->symbols = NULL; } lobj_removereftable(T->L, ref_table); - lua_pushnumber(T->L,CU->getDataLayout().getTypeAllocSize(llvmtyp->type)); + lua_pushnumber(T->L, CU->getDataLayout().getTypeAllocSize(llvmtyp->type)); return 1; } #ifdef TERRA_CAN_USE_MCJIT -static void * GetGlobalValueAddress(TerraCompilationUnit * CU, StringRef Name) { - if(CU->T->options.debug > 1) +static void *GetGlobalValueAddress(TerraCompilationUnit *CU, StringRef Name) { + if (CU->T->options.debug > 1) return sys::DynamicLibrary::SearchForAddressOfSymbol(Name); - return (void*)CU->ee->getGlobalValueAddress(Name); + return (void *)CU->ee->getGlobalValueAddress(Name); } -static bool MCJITShouldCopy(GlobalValue * G, void * data) { - TerraCompilationUnit * CU = (TerraCompilationUnit*) data; - if(dyn_cast(G) != NULL || dyn_cast(G) != NULL) - return 0 == GetGlobalValueAddress(CU,G->getName()); +static bool MCJITShouldCopy(GlobalValue *G, void *data) { + TerraCompilationUnit *CU = (TerraCompilationUnit *)data; + if (dyn_cast(G) != NULL || dyn_cast(G) != NULL) + return 0 == GetGlobalValueAddress(CU, G->getName()); return true; } #endif -static bool SaveSharedObject(TerraCompilationUnit * CU, Module * M, std::vector * args, const char * filename); +static bool SaveSharedObject(TerraCompilationUnit *CU, Module *M, + std::vector *args, const char *filename); -static void * JITGlobalValue(TerraCompilationUnit * CU, GlobalValue * gv) { +static void *JITGlobalValue(TerraCompilationUnit *CU, GlobalValue *gv) { InitializeJIT(CU); - ExecutionEngine * ee = CU->ee; + ExecutionEngine *ee = CU->ee; if (CU->T->options.usemcjit) { #ifdef TERRA_CAN_USE_MCJIT - if(gv->isDeclaration()) { + if (gv->isDeclaration()) { StringRef name = gv->getName(); - if(name.startswith("\01")) //remove asm renaming tag before looking for symbol + if (name.startswith( + "\01")) // remove asm renaming tag before looking for symbol name = name.substr(1); return ee->getPointerToNamedFunction(name); } - void * ptr = GetGlobalValueAddress(CU,gv->getName()); - if(ptr) { + void *ptr = GetGlobalValueAddress(CU, gv->getName()); + if (ptr) { return ptr; } llvm::ValueToValueMapTy VMap; - Module * m = llvmutil_extractmodulewithproperties(gv->getName(), gv->getParent(), &gv, 1, MCJITShouldCopy,CU, VMap); - - if(CU->T->options.debug > 1) { + Module *m = llvmutil_extractmodulewithproperties( + gv->getName(), gv->getParent(), &gv, 1, MCJITShouldCopy, CU, VMap); + + if (CU->T->options.debug > 1) { llvm::SmallString<256> tmpname; - llvmutil_createtemporaryfile("terra","so",tmpname); - if(SaveSharedObject(CU, m, NULL, tmpname.c_str())) - lua_error(CU->T->L); + llvmutil_createtemporaryfile("terra", "so", tmpname); + if (SaveSharedObject(CU, m, NULL, tmpname.c_str())) lua_error(CU->T->L); sys::DynamicLibrary::LoadLibraryPermanently(tmpname.c_str()); - void * result = sys::DynamicLibrary::SearchForAddressOfSymbol(gv->getName()); + void *result = sys::DynamicLibrary::SearchForAddressOfSymbol(gv->getName()); assert(result); return result; } - ee->addModule(UNIQUEIFY(Module,m)); - return (void*) ee->getGlobalValueAddress(gv->getName()); + ee->addModule(UNIQUEIFY(Module, m)); + return (void *)ee->getGlobalValueAddress(gv->getName()); #else return NULL; #endif @@ -2860,37 +2973,38 @@ static void * JITGlobalValue(TerraCompilationUnit * CU, GlobalValue * gv) { } } -static int terra_jit(lua_State * L) { +static int terra_jit(lua_State *L) { terra_getstate(L, 1); - TerraCompilationUnit * CU = (TerraCompilationUnit*) terra_tocdatapointer(L,1); - GlobalValue * gv = (GlobalValue*) lua_touserdata(L,2); + TerraCompilationUnit *CU = (TerraCompilationUnit *)terra_tocdatapointer(L, 1); + GlobalValue *gv = (GlobalValue *)lua_touserdata(L, 2); double begin = CurrentTimeInSeconds(); - void * ptr = JITGlobalValue(CU,gv); + void *ptr = JITGlobalValue(CU, gv); double t = CurrentTimeInSeconds() - begin; - lua_pushlightuserdata(L,ptr); - lua_pushnumber(L,t); + lua_pushlightuserdata(L, ptr); + lua_pushnumber(L, t); return 2; } -static int terra_deletefunction(lua_State * L) { - TerraCompilationUnit * CU = (TerraCompilationUnit*) terra_tocdatapointer(L,lua_upvalueindex(1)); - TerraFunctionState * fstate = (TerraFunctionState*) lua_touserdata(L,-1); +static int terra_deletefunction(lua_State *L) { + TerraCompilationUnit *CU = + (TerraCompilationUnit *)terra_tocdatapointer(L, lua_upvalueindex(1)); + TerraFunctionState *fstate = (TerraFunctionState *)lua_touserdata(L, -1); assert(fstate); - Function * func = fstate->func; + Function *func = fstate->func; assert(func); VERBOSE_ONLY(CU->T) { - printf("deleting function: %s\n",func->getName().str().c_str()); + printf("deleting function: %s\n", func->getName().str().c_str()); } - //MCJIT can't free individual functions, so we need to leak the generated code + // MCJIT can't free individual functions, so we need to leak the generated code #ifdef TERRA_CAN_USE_OLD_JIT - if(!CU->T->options.usemcjit && CU->ee->getPointerToGlobalIfAvailable(func)) { - VERBOSE_ONLY(CU->T) { - printf("... and deleting generated code\n"); - } + if (!CU->T->options.usemcjit && CU->ee->getPointerToGlobalIfAvailable(func)) { + VERBOSE_ONLY(CU->T) { printf("... and deleting generated code\n"); } CU->ee->freeMachineCodeForFunction(func); } #endif - if(!func->use_empty() || CU->T->options.usemcjit) { //for MCJIT, we need to keep the declaration so another function doesn't get the same name + if (!func->use_empty() || + CU->T->options.usemcjit) { // for MCJIT, we need to keep the declaration so + // another function doesn't get the same name VERBOSE_ONLY(CU->T) { printf("... uses not empty, removing body but keeping declaration.\n"); } @@ -2898,214 +3012,217 @@ static int terra_deletefunction(lua_State * L) { } else { CU->mi->eraseFunction(func); } - VERBOSE_ONLY(CU->T) { - printf("... finish delete.\n"); - } + VERBOSE_ONLY(CU->T) { printf("... finish delete.\n"); } fstate->func = NULL; freecompilationunit(CU); return 0; } -static int terra_disassemble(lua_State * L) { - terra_State * T = terra_getstate(L, 1); - Function * fn = (Function*) lua_touserdata(L,1); assert(fn); - void * addr = lua_touserdata(L,2); assert(fn); +static int terra_disassemble(lua_State *L) { + terra_State *T = terra_getstate(L, 1); + Function *fn = (Function *)lua_touserdata(L, 1); + assert(fn); + void *addr = lua_touserdata(L, 2); + assert(fn); TERRA_DUMP_FUNCTION(fn); - if(T->C->functioninfo.count(addr)) { - TerraFunctionInfo & fi = T->C->functioninfo[addr]; - printf("assembly for function at address %p\n",addr); - llvmutil_disassemblefunction(fi.addr, fi.size,0); + if (T->C->functioninfo.count(addr)) { + TerraFunctionInfo &fi = T->C->functioninfo[addr]; + printf("assembly for function at address %p\n", addr); + llvmutil_disassemblefunction(fi.addr, fi.size, 0); } return 0; } -static bool FindLinker(terra_State * T, LLVM_PATH_TYPE * linker, const char* target) { +static bool FindLinker(terra_State *T, LLVM_PATH_TYPE *linker, const char *target) { #ifndef _WIN32 - #if LLVM_VERSION >= 36 - *linker = *sys::findProgramByName("gcc"); - return *linker == ""; - #elif LLVM_VERSION >= 34 - *linker = sys::FindProgramByName("gcc"); - return *linker == ""; - #else - *linker = sys::Program::FindProgramByName("gcc"); - return linker->isEmpty(); - #endif +#if LLVM_VERSION >= 36 + *linker = *sys::findProgramByName("gcc"); + return *linker == ""; +#elif LLVM_VERSION >= 34 + *linker = sys::FindProgramByName("gcc"); + return *linker == ""; +#else + *linker = sys::Program::FindProgramByName("gcc"); + return linker->isEmpty(); +#endif #else - lua_getfield(T->L, LUA_GLOBALSINDEX, "terra"); - lua_getfield(T->L, -1, "getvclinker"); - lua_pushstring(T->L, target); - lua_call(T->L, 1, 3); - *linker = LLVM_PATH_TYPE(lua_tostring(T->L,-3)); - const char * vclib = lua_tostring(T->L,-2); - const char * vcpath = lua_tostring(T->L,-1); - _putenv(vclib); - _putenv(vcpath); - lua_pop(T->L,4); - return false; + lua_getfield(T->L, LUA_GLOBALSINDEX, "terra"); + lua_getfield(T->L, -1, "getvclinker"); + lua_pushstring(T->L, target); + lua_call(T->L, 1, 3); + *linker = LLVM_PATH_TYPE(lua_tostring(T->L, -3)); + const char *vclib = lua_tostring(T->L, -2); + const char *vcpath = lua_tostring(T->L, -1); + _putenv(vclib); + _putenv(vcpath); + lua_pop(T->L, 4); + return false; #endif } -static bool SaveAndLink(TerraCompilationUnit * CU, Module * M, std::vector * linkargs, const char * filename) { +static bool SaveAndLink(TerraCompilationUnit *CU, Module *M, + std::vector *linkargs, const char *filename) { llvm::SmallString<256> tmpname; - llvmutil_createtemporaryfile("terra","o", tmpname); - const char * tmpnamebuf = tmpname.c_str(); + llvmutil_createtemporaryfile("terra", "o", tmpname); + const char *tmpnamebuf = tmpname.c_str(); FD_ERRTYPE err; - raw_fd_ostream tmp(tmpnamebuf,err,RAW_FD_OSTREAM_BINARY); - if(FD_ISERR(err)) { - terra_pusherror(CU->T,"llvm: %s",FD_ERRSTR(err)); + raw_fd_ostream tmp(tmpnamebuf, err, RAW_FD_OSTREAM_BINARY); + if (FD_ISERR(err)) { + terra_pusherror(CU->T, "llvm: %s", FD_ERRSTR(err)); unlink(tmpnamebuf); return true; } - if(llvmutil_emitobjfile(M,CU->TT->tm,true,tmp)) { - terra_pusherror(CU->T,"llvm: llvmutil_emitobjfile"); + if (llvmutil_emitobjfile(M, CU->TT->tm, true, tmp)) { + terra_pusherror(CU->T, "llvm: llvmutil_emitobjfile"); unlink(tmpnamebuf); return true; } - tmp.close(); + tmp.close(); LLVM_PATH_TYPE linker; std::string arch(CU->TT->Triple); arch.erase(arch.find_first_of('-')); - if(FindLinker(CU->T,&linker, arch.c_str())) { + if (FindLinker(CU->T, &linker, arch.c_str())) { unlink(tmpnamebuf); - terra_pusherror(CU->T,"llvm: failed to find linker"); + terra_pusherror(CU->T, "llvm: failed to find linker"); return true; } std::vector cmd; cmd.push_back(linker.c_str()); cmd.push_back(tmpnamebuf); - if(linkargs) - cmd.insert(cmd.end(),linkargs->begin(),linkargs->end()); - + if (linkargs) cmd.insert(cmd.end(), linkargs->begin(), linkargs->end()); + #ifndef _WIN32 cmd.push_back("-o"); cmd.push_back(filename); #else - cmd.push_back("-defaultlib:msvcrt"); - cmd.push_back("-nologo"); - llvm::SmallString<256> fileout("-out:"); - fileout.append(filename); - cmd.push_back(fileout.c_str()); -#endif - - cmd.push_back(NULL); + cmd.push_back("-defaultlib:msvcrt"); + cmd.push_back("-nologo"); + llvm::SmallString<256> fileout("-out:"); + fileout.append(filename); + cmd.push_back(fileout.c_str()); +#endif + + cmd.push_back(NULL); std::string errstr; - if(llvmutil_executeandwait(linker,&cmd[0],&errstr)) { + if (llvmutil_executeandwait(linker, &cmd[0], &errstr)) { unlink(tmpnamebuf); unlink(filename); - terra_pusherror(CU->T,"llvm: %s\n",errstr.c_str()); + terra_pusherror(CU->T, "llvm: %s\n", errstr.c_str()); return true; } return false; } -static bool SaveObject(TerraCompilationUnit * CU, Module * M, const std::string & filekind, emitobjfile_t & dest) { - if(filekind == "object" || filekind == "asm") { - if(llvmutil_emitobjfile(M,CU->TT->tm,filekind == "object",dest)) { - terra_pusherror(CU->T,"llvm: llvmutil_emitobjfile"); +static bool SaveObject(TerraCompilationUnit *CU, Module *M, const std::string &filekind, + emitobjfile_t &dest) { + if (filekind == "object" || filekind == "asm") { + if (llvmutil_emitobjfile(M, CU->TT->tm, filekind == "object", dest)) { + terra_pusherror(CU->T, "llvm: llvmutil_emitobjfile"); return true; } - } else if(filekind == "bitcode") { + } else if (filekind == "bitcode") { #if LLVM_VERSION < 70 - llvm::WriteBitcodeToFile(M,dest); + llvm::WriteBitcodeToFile(M, dest); #else llvm::WriteBitcodeToFile(*M, dest); #endif - } else if(filekind == "llvmir") { + } else if (filekind == "llvmir") { dest << *M; } return false; } -static bool SaveSharedObject(TerraCompilationUnit * CU, Module * M, std::vector * args, const char * filename) { +static bool SaveSharedObject(TerraCompilationUnit *CU, Module *M, + std::vector *args, const char *filename) { std::vector cmd; #ifdef __APPLE__ - cmd.push_back("-g"); + cmd.push_back("-g"); cmd.push_back("-dynamiclib"); cmd.push_back("-single_module"); cmd.push_back("-undefined"); cmd.push_back("dynamic_lookup"); - cmd.push_back("-fPIC"); + cmd.push_back("-fPIC"); #elif _WIN32 - cmd.push_back("-dll"); + cmd.push_back("-dll"); #else - cmd.push_back("-g"); + cmd.push_back("-g"); cmd.push_back("-shared"); cmd.push_back("-Wl,-export-dynamic"); #ifndef __FreeBSD__ cmd.push_back("-ldl"); #endif - cmd.push_back("-fPIC"); + cmd.push_back("-fPIC"); #endif - if(args) - cmd.insert(cmd.end(),args->begin(),args->end()); - return SaveAndLink(CU,M,&cmd,filename); + if (args) cmd.insert(cmd.end(), args->begin(), args->end()); + return SaveAndLink(CU, M, &cmd, filename); } -static int terra_saveobjimpl(lua_State * L) { - terra_State * T = terra_getstate(L, 1); - - const char * filename = lua_tostring(L, 1); //NULL means write to memory - std::string filekind = lua_tostring(L,2); +static int terra_saveobjimpl(lua_State *L) { + terra_State *T = terra_getstate(L, 1); + + const char *filename = lua_tostring(L, 1); // NULL means write to memory + std::string filekind = lua_tostring(L, 2); int argument_index = 4; - bool optimize = lua_toboolean(L,5); + bool optimize = lua_toboolean(L, 5); - lua_getfield(L,3,"llvm_cu"); - TerraCompilationUnit * CU = (TerraCompilationUnit*) terra_tocdatapointer(L,-1); assert(CU); + lua_getfield(L, 3, "llvm_cu"); + TerraCompilationUnit *CU = (TerraCompilationUnit *)terra_tocdatapointer(L, -1); + assert(CU); if (optimize) { - llvmutil_optimizemodule(CU->M,CU->TT->tm); + llvmutil_optimizemodule(CU->M, CU->TT->tm); } - //TODO: interialize the non-exported functions? + // TODO: interialize the non-exported functions? std::vector args; - int nargs = lua_objlen(L,argument_index); - for(int i = 1; i <= nargs; i++) { - lua_rawgeti(L,argument_index,i); - args.push_back(luaL_checkstring(L,-1)); - lua_pop(L,1); + int nargs = lua_objlen(L, argument_index); + for (int i = 1; i <= nargs; i++) { + lua_rawgeti(L, argument_index, i); + args.push_back(luaL_checkstring(L, -1)); + lua_pop(L, 1); } - + bool result = false; int N = 0; - + if (filekind == "executable") { - result = SaveAndLink(CU,CU->M,&args,filename); + result = SaveAndLink(CU, CU->M, &args, filename); } else if (filekind == "sharedlibrary") { - result = SaveSharedObject(CU,CU->M,&args,filename); - } else { - if(filename != NULL) { + result = SaveSharedObject(CU, CU->M, &args, filename); + } else { + if (filename != NULL) { FD_ERRTYPE err; - raw_fd_ostream dest(filename, err, (filekind == "llvmir") ? RAW_FD_OSTREAM_NONE : RAW_FD_OSTREAM_BINARY); + raw_fd_ostream dest( + filename, err, + (filekind == "llvmir") ? RAW_FD_OSTREAM_NONE : RAW_FD_OSTREAM_BINARY); if (FD_ISERR(err)) { terra_pusherror(T, "llvm: %s", FD_ERRSTR(err)); result = true; } else { - result = SaveObject(CU,CU->M,filekind, dest); + result = SaveObject(CU, CU->M, filekind, dest); } } else { - SmallVector mem; - { //ensure stream is finished before we add the memory to lua + SmallVector mem; + { // ensure stream is finished before we add the memory to lua raw_svector_ostream dest(mem); - result = SaveObject(CU,CU->M,filekind,dest); + result = SaveObject(CU, CU->M, filekind, dest); } N = 1; - lua_pushlstring(L,&mem[0],mem.size()); + lua_pushlstring(L, &mem[0], mem.size()); } } - if(result) - lua_error(CU->T->L); - + if (result) lua_error(CU->T->L); + return N; } -static int terra_pointertolightuserdata(lua_State * L) { +static int terra_pointertolightuserdata(lua_State *L) { lua_pushlightuserdata(L, terra_tocdatapointer(L, -1)); return 1; } -static int terra_bindtoluaapi(lua_State * L) { +static int terra_bindtoluaapi(lua_State *L) { int N = lua_gettop(L); assert(N >= 1); - void * const * fn = (void * const *) lua_topointer(L,1); + void *const *fn = (void *const *)lua_topointer(L, 1); assert(fn); - lua_pushcclosure(L, (lua_CFunction) *fn, N - 1); + lua_pushcclosure(L, (lua_CFunction)*fn, N - 1); return 1; } #ifdef _WIN32 @@ -3113,114 +3230,120 @@ static int terra_bindtoluaapi(lua_State * L) { #else #define ISFINITE(v) std::isfinite(v) #endif -static int terra_isintegral(lua_State * L) { - double v = luaL_checknumber(L,-1); - bool integral = ISFINITE(v) && (double)(int)v == v; - lua_pushboolean(L,integral); +static int terra_isintegral(lua_State *L) { + double v = luaL_checknumber(L, -1); + bool integral = ISFINITE(v) && (double)(int)v == v; + lua_pushboolean(L, integral); return 1; } -static int terra_linklibraryimpl(lua_State * L) { - terra_State * T = terra_getstate(L, 1); +static int terra_linklibraryimpl(lua_State *L) { + terra_State *T = terra_getstate(L, 1); std::string Err; - if(sys::DynamicLibrary::LoadLibraryPermanently(luaL_checkstring(L, 1),&Err)) { + if (sys::DynamicLibrary::LoadLibraryPermanently(luaL_checkstring(L, 1), &Err)) { terra_reporterror(T, "llvm: %s\n", Err.c_str()); } return 0; } -static int terra_linkllvmimpl(lua_State * L) { - terra_State * T = terra_getstate(L, 1); (void)T; +static int terra_linkllvmimpl(lua_State *L) { + terra_State *T = terra_getstate(L, 1); + (void)T; std::string Err; - TerraTarget * TT = (TerraTarget*) terra_tocdatapointer(L,1); + TerraTarget *TT = (TerraTarget *)terra_tocdatapointer(L, 1); size_t length; - const char * filename = lua_tolstring(L,2,&length); + const char *filename = lua_tolstring(L, 2, &length); bool fromstring = lua_toboolean(L, 3); #if LLVM_VERSION <= 34 OwningPtr mb; - error_code ec = MemoryBuffer::getFile(filename,mb); - if(ec) + error_code ec = MemoryBuffer::getFile(filename, mb); + if (ec) terra_reporterror(CU->T, "linkllvm(%s): %s\n", filename, ec.message().c_str()); - Module * m = ParseBitcodeFile(mb.get(), *T->C->ctx,&Err); - if(!m) - terra_reporterror(CU->T, "linkllvm(%s): %s\n", filename, Err.c_str()); + Module *m = ParseBitcodeFile(mb.get(), *T->C->ctx, &Err); + if (!m) terra_reporterror(CU->T, "linkllvm(%s): %s\n", filename, Err.c_str()); #else ErrorOr > mb = std::error_code(); - if(fromstring) { - std::unique_ptr mbcontents(MemoryBuffer::getMemBuffer(StringRef(filename,length),"",false)); + if (fromstring) { + std::unique_ptr mbcontents( + MemoryBuffer::getMemBuffer(StringRef(filename, length), "", false)); mb = std::move(mbcontents); } else { mb = MemoryBuffer::getFile(filename); } - if(!mb) { - if(fromstring) + if (!mb) { + if (fromstring) terra_reporterror(T, "linkllvm: %s\n", mb.getError().message().c_str()); - else - terra_reporterror(T, "linkllvm(%s): %s\n", filename, mb.getError().message().c_str()); - } - #if LLVM_VERSION == 36 - ErrorOr mm = parseBitcodeFile(mb.get()->getMemBufferRef(),*TT->ctx); - #elif LLVM_VERSION >= 50 - Expected> mm = parseBitcodeFile(mb.get()->getMemBufferRef(),*TT->ctx); - #elif LLVM_VERSION >= 37 - ErrorOr> mm = parseBitcodeFile(mb.get()->getMemBufferRef(),*TT->ctx); - #else - ErrorOr mm = parseBitcodeFile(mb.get().get(),*TT->ctx); - #endif - if(!mm) { - if(fromstring) { - #if LLVM_VERSION >= 50 - std::string Msg; - raw_string_ostream S((Msg)); - logAllUnhandledErrors(mm.takeError(), S, ""); - S.flush(); - terra_reporterror(T, "linkllvm: %s\n", S.str().c_str()); - #else - terra_reporterror(T, "linkllvm: %s\n", mm.getError().message().c_str()); - #endif + else + terra_reporterror(T, "linkllvm(%s): %s\n", filename, + mb.getError().message().c_str()); + } +#if LLVM_VERSION == 36 + ErrorOr mm = parseBitcodeFile(mb.get()->getMemBufferRef(), *TT->ctx); +#elif LLVM_VERSION >= 50 + Expected > mm = + parseBitcodeFile(mb.get()->getMemBufferRef(), *TT->ctx); +#elif LLVM_VERSION >= 37 + ErrorOr > mm = + parseBitcodeFile(mb.get()->getMemBufferRef(), *TT->ctx); +#else + ErrorOr mm = parseBitcodeFile(mb.get().get(), *TT->ctx); +#endif + if (!mm) { + if (fromstring) { +#if LLVM_VERSION >= 50 + std::string Msg; + raw_string_ostream S((Msg)); + logAllUnhandledErrors(mm.takeError(), S, ""); + S.flush(); + terra_reporterror(T, "linkllvm: %s\n", S.str().c_str()); +#else + terra_reporterror(T, "linkllvm: %s\n", mm.getError().message().c_str()); +#endif } else { - #if LLVM_VERSION >= 50 +#if LLVM_VERSION >= 50 std::string Msg; raw_string_ostream S((Msg)); logAllUnhandledErrors(mm.takeError(), S, ""); S.flush(); terra_reporterror(T, "linkllvm(%s): %s\n", filename, S.str().c_str()); - #else - terra_reporterror(T, "linkllvm(%s): %s\n", filename, mm.getError().message().c_str()); - #endif +#else + terra_reporterror(T, "linkllvm(%s): %s\n", filename, + mm.getError().message().c_str()); +#endif } } - #if LLVM_VERSION >= 37 - Module * M = mm.get().release(); - #else - Module * M = mm.get(); - #endif +#if LLVM_VERSION >= 37 + Module *M = mm.get().release(); +#else + Module *M = mm.get(); +#endif #endif M->setTargetTriple(TT->Triple); #if LLVM_VERSION < 39 - char * err; - if(LLVMLinkModules(llvm::wrap(TT->external), llvm::wrap(M), LLVMLinkerDestroySource, &err)) { - if(fromstring) - terra_pusherror(T, "linker reported error: %s",err); - else - terra_pusherror(T, "linker(%s) reported error: %s",filename,err); + char *err; + if (LLVMLinkModules(llvm::wrap(TT->external), llvm::wrap(M), LLVMLinkerDestroySource, + &err)) { + if (fromstring) + terra_pusherror(T, "linker reported error: %s", err); + else + terra_pusherror(T, "linker(%s) reported error: %s", filename, err); LLVMDisposeMessage(err); lua_error(T->L); } #else - if(LLVMLinkModules2(llvm::wrap(TT->external), llvm::wrap(M))) { - if(fromstring) + if (LLVMLinkModules2(llvm::wrap(TT->external), llvm::wrap(M))) { + if (fromstring) terra_pusherror(T, "linker reported error"); - else - terra_pusherror(T, "linker reported error on %s",filename); + else + terra_pusherror(T, "linker reported error on %s", filename); lua_error(T->L); } #endif return 0; } -static int terra_dumpmodule(lua_State * L) { - terra_State * T = terra_getstate(L, 1); (void)T; - TerraCompilationUnit * CU = (TerraCompilationUnit*) terra_tocdatapointer(L,1); - if(CU) - TERRA_DUMP_MODULE(CU->M); +static int terra_dumpmodule(lua_State *L) { + terra_State *T = terra_getstate(L, 1); + (void)T; + TerraCompilationUnit *CU = (TerraCompilationUnit *)terra_tocdatapointer(L, 1); + if (CU) TERRA_DUMP_MODULE(CU->M); return 0; } diff --git a/src/tcompiler.h b/src/tcompiler.h index 2476226cd..00296d800 100644 --- a/src/tcompiler.h +++ b/src/tcompiler.h @@ -4,8 +4,8 @@ struct terra_State; struct terra_CompilerState; struct TerraTarget; -int terra_compilerinit(struct terra_State * T); -int terra_compilerfree(struct terra_CompilerState * T); -void freetarget(TerraTarget * TT); +int terra_compilerinit(struct terra_State* T); +int terra_compilerfree(struct terra_CompilerState* T); +void freetarget(TerraTarget* TT); #endif \ No newline at end of file diff --git a/src/tcompilerstate.h b/src/tcompilerstate.h index 857fe8d2a..7f680d925 100644 --- a/src/tcompilerstate.h +++ b/src/tcompilerstate.h @@ -4,60 +4,76 @@ #include "llvmheaders.h" #include "tinline.h" - struct TerraFunctionInfo { - llvm::LLVMContext * ctx; + llvm::LLVMContext *ctx; std::string name; - void * addr; + void *addr; size_t size; llvm::JITEvent_EmittedFunctionDetails efd; }; -class Types; struct CCallingConv; struct Obj; +class Types; +struct CCallingConv; +struct Obj; struct TerraTarget { - TerraTarget() : nreferences(0), tm(NULL), ctx(NULL), external(NULL), next_unused_id(0) {} + TerraTarget() + : nreferences(0), tm(NULL), ctx(NULL), external(NULL), next_unused_id(0) {} int nreferences; - std::string Triple,CPU,Features; - llvm::TargetMachine * tm; - llvm::LLVMContext * ctx; - llvm::Module * external; //module that holds IR for externally included things (from includec or linkllvm) - size_t next_unused_id; //for creating names for dummy functions + std::string Triple, CPU, Features; + llvm::TargetMachine *tm; + llvm::LLVMContext *ctx; + llvm::Module *external; // module that holds IR for externally included things (from + // includec or linkllvm) + size_t next_unused_id; // for creating names for dummy functions size_t id; }; -struct TerraFunctionState { //compilation state - llvm::Function * func; - int index,lowlink; //for Tarjan's scc algorithm +struct TerraFunctionState { // compilation state + llvm::Function *func; + int index, lowlink; // for Tarjan's scc algorithm bool onstack; }; struct TerraCompilationUnit { - TerraCompilationUnit() : nreferences(0), optimize(false), T(NULL), C(NULL), M(NULL), mi(NULL), fpm(NULL), ee(NULL),jiteventlistener(NULL), Ty(NULL), CC(NULL), symbols(NULL), functioncount(0) {} + TerraCompilationUnit() + : nreferences(0), + optimize(false), + T(NULL), + C(NULL), + M(NULL), + mi(NULL), + fpm(NULL), + ee(NULL), + jiteventlistener(NULL), + Ty(NULL), + CC(NULL), + symbols(NULL), + functioncount(0) {} int nreferences; - //configuration + // configuration bool optimize; - + // LLVM state used in compiltion unit - terra_State * T; - terra_CompilerState * C; - TerraTarget * TT; - llvm::Module * M; - ManualInliner * mi; - FunctionPassManager * fpm; - llvm::ExecutionEngine * ee; - llvm::JITEventListener * jiteventlistener; //for reporting debug info + terra_State *T; + terra_CompilerState *C; + TerraTarget *TT; + llvm::Module *M; + ManualInliner *mi; + FunctionPassManager *fpm; + llvm::ExecutionEngine *ee; + llvm::JITEventListener *jiteventlistener; // for reporting debug info // Temporary storage for objects that exist only during emitting functions - Types * Ty; - CCallingConv * CC; - Obj * symbols; - int functioncount; // for assigning unique indexes to functions; - std::vector* tooptimize; - const llvm::DataLayout & getDataLayout() { - #if LLVM_VERSION <= 35 + Types *Ty; + CCallingConv *CC; + Obj *symbols; + int functioncount; // for assigning unique indexes to functions; + std::vector *tooptimize; + const llvm::DataLayout &getDataLayout() { +#if LLVM_VERSION <= 35 return *M->getDataLayout(); - #else +#else return M->getDataLayout(); - #endif +#endif } }; diff --git a/src/tcuda.cpp b/src/tcuda.cpp index 3b73c7c46..d2095202e 100644 --- a/src/tcuda.cpp +++ b/src/tcuda.cpp @@ -26,91 +26,95 @@ extern "C" { #include #endif - -#define CUDA_DO2(err,str,...) do { \ - int e = err; \ - if(e != CUDA_SUCCESS) { \ - terra_reporterror(T,"%s:%d: %s cuda reported error %d" str,__FILE__,__LINE__,#err,e,__VA_ARGS__); \ - } \ -} while(0) - -#define CUDA_DO(err) CUDA_DO2(err,"%s","") - -#define CUDA_SYM(_) \ - _(nvvmAddModuleToProgram) \ - _(nvvmCompileProgram) \ - _(nvvmCreateProgram) \ - _(nvvmGetCompiledResult) \ +#define CUDA_DO2(err, str, ...) \ + do { \ + int e = err; \ + if (e != CUDA_SUCCESS) { \ + terra_reporterror(T, "%s:%d: %s cuda reported error %d" str, __FILE__, \ + __LINE__, #err, e, __VA_ARGS__); \ + } \ + } while (0) + +#define CUDA_DO(err) CUDA_DO2(err, "%s", "") + +#define CUDA_SYM(_) \ + _(nvvmAddModuleToProgram) \ + _(nvvmCompileProgram) \ + _(nvvmCreateProgram) \ + _(nvvmGetCompiledResult) \ _(nvvmGetCompiledResultSize) \ - _(nvvmGetProgramLog) \ - _(nvvmGetProgramLogSize) \ + _(nvvmGetProgramLog) \ + _(nvvmGetProgramLogSize) \ _(nvvmVersion) struct terra_CUDAState { int initialized; - #define INIT_SYM(x) decltype(&::x) x; +#define INIT_SYM(x) decltype(&::x) x; CUDA_SYM(INIT_SYM) - #undef INIT_SYM +#undef INIT_SYM }; -void initializeNVVMState(terra_State * T) { +void initializeNVVMState(terra_State *T) { if (!T->cuda->initialized) { - //dynamically assign all of our symbols - #define INIT_SYM(x) \ - T->cuda->x = (decltype(&x)) llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(#x); \ - assert(T->cuda->x); - CUDA_SYM(INIT_SYM) - #undef INIT_SYM +// dynamically assign all of our symbols +#define INIT_SYM(x) \ + T->cuda->x = (decltype(&x))llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(#x); \ + assert(T->cuda->x); + CUDA_SYM(INIT_SYM) +#undef INIT_SYM T->cuda->initialized = 1; } } -static void annotateKernel(terra_State * T, llvm::Module * M, llvm::Function * kernel, const char * name, int value) { - llvm::LLVMContext & ctx = M->getContext(); +static void annotateKernel(terra_State *T, llvm::Module *M, llvm::Function *kernel, + const char *name, int value) { + llvm::LLVMContext &ctx = M->getContext(); std::vector vals; - llvm::NamedMDNode * annot = M->getOrInsertNamedMetadata("nvvm.annotations"); - llvm::MDString * str = llvm::MDString::get(ctx, name); - #if LLVM_VERSION <= 35 + llvm::NamedMDNode *annot = M->getOrInsertNamedMetadata("nvvm.annotations"); + llvm::MDString *str = llvm::MDString::get(ctx, name); +#if LLVM_VERSION <= 35 vals.push_back(kernel); vals.push_back(str); vals.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(ctx), value)); - #else +#else vals.push_back(llvm::ValueAsMetadata::get(kernel)); vals.push_back(str); - vals.push_back(llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(llvm::Type::getInt32Ty(ctx), value))); - #endif - llvm::MDNode * node = llvm::MDNode::get(ctx, vals); + vals.push_back(llvm::ConstantAsMetadata::get( + llvm::ConstantInt::get(llvm::Type::getInt32Ty(ctx), value))); +#endif + llvm::MDNode *node = llvm::MDNode::get(ctx, vals); annot->addOperand(node); } -static const char * cudadatalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64"; +static const char *cudadatalayout = + "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-" + "v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64"; #if LLVM_VERSION <= 38 class RemoveAttr : public llvm::InstVisitor { public: - void visitCallInst(llvm::CallInst & I) { - I.setAttributes(llvm::AttributeSet()); - } + void visitCallInst(llvm::CallInst &I) { I.setAttributes(llvm::AttributeSet()); } }; #endif -void moduleToPTX(terra_State * T, llvm::Module * M, int major, int minor, std::string * buf, const char * libdevice) { - +void moduleToPTX(terra_State *T, llvm::Module *M, int major, int minor, std::string *buf, + const char *libdevice) { #if LLVM_VERSION <= 38 - for(llvm::Module::iterator it = M->begin(), end = M->end(); it != end; ++it) { - it->setAttributes(llvm::AttributeSet()); //remove annotations because syntax doesn't match + for (llvm::Module::iterator it = M->begin(), end = M->end(); it != end; ++it) { + it->setAttributes( + llvm::AttributeSet()); // remove annotations because syntax doesn't match RemoveAttr A; - A.visit(&*it); //remove annotations on CallInsts as well. + A.visit(&*it); // remove annotations on CallInsts as well. } #endif - int nmajor,nminor; - CUDA_DO(T->cuda->nvvmVersion(&nmajor,&nminor)); - int nversion = nmajor*10 + nminor; - if(nversion >= 12) + int nmajor, nminor; + CUDA_DO(T->cuda->nvvmVersion(&nmajor, &nminor)); + int nversion = nmajor * 10 + nminor; + if (nversion >= 12) M->setTargetTriple("nvptx64-nvidia-cuda"); else - M->setTargetTriple(""); //clear these because nvvm doesn't like them - M->setDataLayout(""); //nvvm doesn't like data layout either + M->setTargetTriple(""); // clear these because nvvm doesn't like them + M->setDataLayout(""); // nvvm doesn't like data layout either std::stringstream device; device << "-arch=compute_" << major << minor; @@ -120,14 +124,14 @@ void moduleToPTX(terra_State * T, llvm::Module * M, int major, int minor, std::s std::string llvmir; { llvm::raw_string_ostream output(llvmir); - #if LLVM_VERSION >= 38 +#if LLVM_VERSION >= 38 M->setDataLayout(cudadatalayout); llvm::WriteBitcodeToFile(M, output); - #else +#else llvm::formatted_raw_ostream foutput(output); foutput << "target datalayout = \"" << cudadatalayout << "\";\n"; foutput << *M; - #endif +#endif } nvvmProgram prog; @@ -135,27 +139,29 @@ void moduleToPTX(terra_State * T, llvm::Module * M, int major, int minor, std::s // Add libdevice module first if (libdevice != NULL) { - std::ifstream libdeviceFile(libdevice); - std::stringstream sstr; - sstr << libdeviceFile.rdbuf(); - std::string libdeviceStr = sstr.str(); - size_t libdeviceModSize = libdeviceStr.size(); - const char* libdeviceMod = libdeviceStr.data(); - CUDA_DO(T->cuda->nvvmAddModuleToProgram(prog, libdeviceMod, libdeviceModSize, "libdevice")); + std::ifstream libdeviceFile(libdevice); + std::stringstream sstr; + sstr << libdeviceFile.rdbuf(); + std::string libdeviceStr = sstr.str(); + size_t libdeviceModSize = libdeviceStr.size(); + const char *libdeviceMod = libdeviceStr.data(); + CUDA_DO(T->cuda->nvvmAddModuleToProgram(prog, libdeviceMod, libdeviceModSize, + "libdevice")); } - CUDA_DO(T->cuda->nvvmAddModuleToProgram(prog, llvmir.data(), llvmir.size(), M->getModuleIdentifier().c_str())); + CUDA_DO(T->cuda->nvvmAddModuleToProgram(prog, llvmir.data(), llvmir.size(), + M->getModuleIdentifier().c_str())); int numOptions = 1; - const char * options[] = { deviceopt.c_str() }; + const char *options[] = {deviceopt.c_str()}; size_t size; int err = T->cuda->nvvmCompileProgram(prog, numOptions, options); if (err != CUDA_SUCCESS) { - CUDA_DO(T->cuda->nvvmGetProgramLogSize(prog,&size)); + CUDA_DO(T->cuda->nvvmGetProgramLogSize(prog, &size)); buf->resize(size); CUDA_DO(T->cuda->nvvmGetProgramLog(prog, &(*buf)[0])); - terra_reporterror(T,"%s:%d: nvvm error reported (%d)\n %s\n",__FILE__,__LINE__,err,buf->c_str()); - + terra_reporterror(T, "%s:%d: nvvm error reported (%d)\n %s\n", __FILE__, __LINE__, + err, buf->c_str()); } CUDA_DO(T->cuda->nvvmGetCompiledResultSize(prog, &size)); buf->resize(size); @@ -180,7 +186,8 @@ void moduleToPTX(terra_State * T, llvm::Module * M, int major, int minor, std::s llvm::SmallString<2048> ErrMsg; auto MB = llvm::MemoryBuffer::getFile(libdevice); - auto E_LDEVICE = llvm::parseBitcodeFile(MB->get()->getMemBufferRef(), M->getContext()); + auto E_LDEVICE = + llvm::parseBitcodeFile(MB->get()->getMemBufferRef(), M->getContext()); if (auto Err = E_LDEVICE.takeError()) { llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "[CUDA Error] "); @@ -189,10 +196,10 @@ void moduleToPTX(terra_State * T, llvm::Module * M, int major, int minor, std::s auto &LDEVICE = *E_LDEVICE; - llvm::TargetOptions opt; auto RM = llvm::Optional(); - auto TargetMachine = Target->createTargetMachine("nvptx64-nvidia-cuda", cpuopt, Features, opt, RM); + auto TargetMachine = + Target->createTargetMachine("nvptx64-nvidia-cuda", cpuopt, Features, opt, RM); LDEVICE->setTargetTriple("nvptx64-nvidia-cuda"); LDEVICE->setDataLayout(TargetMachine->createDataLayout()); @@ -216,17 +223,17 @@ void moduleToPTX(terra_State * T, llvm::Module * M, int major, int minor, std::s PMB.populateModulePassManager(PM); - #if LLVM_VERSION >= 70 +#if LLVM_VERSION >= 70 if (TargetMachine->addPassesToEmitFile(PM, str_dest, nullptr, FileType)) { llvm::errs() << "TargetMachine can't emit a file of this type\n"; return; } - #else +#else if (TargetMachine->addPassesToEmitFile(PM, str_dest, FileType)) { llvm::errs() << "TargetMachine can't emit a file of this type\n"; return; } - #endif +#endif PM.run(*M); buf->resize(dest.size()); @@ -241,106 +248,109 @@ void moduleToPTX(terra_State * T, llvm::Module * M, int major, int minor, std::s #endif } -//cuda doesn't like llvm generic names, so we replace non-identifier symbols here +// cuda doesn't like llvm generic names, so we replace non-identifier symbols here static std::string sanitizeName(std::string name) { std::string s; llvm::raw_string_ostream out(s); - for(size_t i = 0; i < name.size(); i++) { + for (size_t i = 0; i < name.size(); i++) { char c = name[i]; - if(isalnum(c) || c == '_') + if (isalnum(c) || c == '_') out << c; else - out << "_$" << (int) c << "_"; + out << "_$" << (int)c << "_"; } out.flush(); return s; } - -int terra_toptx(lua_State * L) { - terra_State * T = terra_getstate(L, 1); +int terra_toptx(lua_State *L) { + terra_State *T = terra_getstate(L, 1); initializeNVVMState(T); - lua_getfield(L,1,"llvm_cu"); - TerraCompilationUnit * CU = (TerraCompilationUnit*) terra_tocdatapointer(L,-1); - llvm::Module * M = CU->M; + lua_getfield(L, 1, "llvm_cu"); + TerraCompilationUnit *CU = (TerraCompilationUnit *)terra_tocdatapointer(L, -1); + llvm::Module *M = CU->M; int annotations = 2; - int dumpmodule = lua_toboolean(L,3); - int version = lua_tonumber(L,4); + int dumpmodule = lua_toboolean(L, 3); + int version = lua_tonumber(L, 4); int major = version / 10; int minor = version % 10; - const char * libdevice = lua_tostring(L,5); - - int N = lua_objlen(L,annotations); - for(int i = 0; i < N; i++) { - lua_rawgeti(L,annotations,i+1); // {kernel,annotation,value} - lua_rawgeti(L,-1,1); //kernel name - lua_rawgeti(L,-2,2); // annotation name - lua_rawgeti(L,-3,3); // annotation value - const char * kernelname = luaL_checkstring(L,-3); - const char * annotationname = luaL_checkstring(L,-2); - int annotationvalue = luaL_checkint(L,-1); - llvm::Function * kernel = M->getFunction(kernelname); + const char *libdevice = lua_tostring(L, 5); + + int N = lua_objlen(L, annotations); + for (int i = 0; i < N; i++) { + lua_rawgeti(L, annotations, i + 1); // {kernel,annotation,value} + lua_rawgeti(L, -1, 1); // kernel name + lua_rawgeti(L, -2, 2); // annotation name + lua_rawgeti(L, -3, 3); // annotation value + const char *kernelname = luaL_checkstring(L, -3); + const char *annotationname = luaL_checkstring(L, -2); + int annotationvalue = luaL_checkint(L, -1); + llvm::Function *kernel = M->getFunction(kernelname); assert(kernel); - annotateKernel(T,M,kernel,annotationname,annotationvalue); - lua_pop(L,4); //annotation table and 3 values in it + annotateKernel(T, M, kernel, annotationname, annotationvalue); + lua_pop(L, 4); // annotation table and 3 values in it } - //sanitize names - for(llvm::Module::iterator it = M->begin(), end = M->end(); it != end; ++it) { - const char * prefix = "cudart:"; + // sanitize names + for (llvm::Module::iterator it = M->begin(), end = M->end(); it != end; ++it) { + const char *prefix = "cudart:"; size_t prefixsize = strlen(prefix); std::string name = it->getName(); - if(name.size() >= prefixsize && name.substr(0,prefixsize) == prefix) { + if (name.size() >= prefixsize && name.substr(0, prefixsize) == prefix) { std::string shortname = name.substr(prefixsize); it->setName(shortname); - } if(!it->isDeclaration()) { + } + if (!it->isDeclaration()) { it->setName(sanitizeName(it->getName())); } } - for(llvm::Module::global_iterator it = M->global_begin(), end = M->global_end(); it != end; ++it) { + for (llvm::Module::global_iterator it = M->global_begin(), end = M->global_end(); + it != end; ++it) { it->setName(sanitizeName(it->getName())); } std::string ptx; - moduleToPTX(T,M,major,minor,&ptx,libdevice); - if(dumpmodule) { - fprintf(stderr,"CUDA Module:\n"); - #if LLVM_VERSION < 38 + moduleToPTX(T, M, major, minor, &ptx, libdevice); + if (dumpmodule) { + fprintf(stderr, "CUDA Module:\n"); +#if LLVM_VERSION < 38 M->dump(); - #else +#else M->print(llvm::errs(), nullptr); - #endif - fprintf(stderr,"Generated PTX:\n%s\n",ptx.c_str()); +#endif + fprintf(stderr, "Generated PTX:\n%s\n", ptx.c_str()); } - lua_pushstring(L,ptx.c_str()); + lua_pushstring(L, ptx.c_str()); return 1; } -int terra_cudainit(struct terra_State * T) { - lua_getfield(T->L,LUA_GLOBALSINDEX,"terra"); - lua_getfield(T->L,-1,"cudalibpaths"); - lua_getfield(T->L,-1,"nvvm"); - const char * libnvvmpath = lua_tostring(T->L,-1); - lua_pop(T->L,2); //path and cudalibpaths - if(llvm::sys::DynamicLibrary::LoadLibraryPermanently(libnvvmpath)) { +int terra_cudainit(struct terra_State *T) { + lua_getfield(T->L, LUA_GLOBALSINDEX, "terra"); + lua_getfield(T->L, -1, "cudalibpaths"); + lua_getfield(T->L, -1, "nvvm"); + const char *libnvvmpath = lua_tostring(T->L, -1); + lua_pop(T->L, 2); // path and cudalibpaths + if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(libnvvmpath)) { llvm::SmallString<256> err; err.append("failed to load libnvvm at: "); err.append(libnvvmpath); - lua_pushstring(T->L,err.c_str()); - lua_setfield(T->L,-2,"cudaloaderror"); - lua_pop(T->L,1); //terralib - return 0; //couldn't find the libnvvm library, do not load cudalib.lua + lua_pushstring(T->L, err.c_str()); + lua_setfield(T->L, -2, "cudaloaderror"); + lua_pop(T->L, 1); // terralib + return 0; // couldn't find the libnvvm library, do not load cudalib.lua } - T->cuda = (terra_CUDAState*) malloc(sizeof(terra_CUDAState)); - T->cuda->initialized = 0; /* actual CUDA initalization is done on first call to terra_cudacompile */ - /* this function just registers all the Lua state associated with CUDA */ - - lua_pushlightuserdata(T->L,(void*)T); - lua_pushcclosure(T->L,terra_toptx,1); - lua_setfield(T->L,-2,"toptximpl"); - lua_pop(T->L,1); //terralib - int err = terra_loadandrunbytecodes(T->L, (const unsigned char *)luaJIT_BC_cudalib,luaJIT_BC_cudalib_SIZE, "cudalib.lua"); - if(err) { + T->cuda = (terra_CUDAState *)malloc(sizeof(terra_CUDAState)); + T->cuda->initialized = + 0; /* actual CUDA initalization is done on first call to terra_cudacompile */ + /* this function just registers all the Lua state associated with CUDA */ + + lua_pushlightuserdata(T->L, (void *)T); + lua_pushcclosure(T->L, terra_toptx, 1); + lua_setfield(T->L, -2, "toptximpl"); + lua_pop(T->L, 1); // terralib + int err = terra_loadandrunbytecodes(T->L, (const unsigned char *)luaJIT_BC_cudalib, + luaJIT_BC_cudalib_SIZE, "cudalib.lua"); + if (err) { return err; } return 0; @@ -348,12 +358,10 @@ int terra_cudainit(struct terra_State * T) { #else /* cuda disabled, just do nothing */ -int terra_cudainit(struct terra_State * T) { - return 0; -} +int terra_cudainit(struct terra_State* T) { return 0; } #endif -int terra_cudafree(struct terra_State * T) { - //currently nothing to clean up +int terra_cudafree(struct terra_State *T) { + // currently nothing to clean up return 0; } diff --git a/src/tcuda.h b/src/tcuda.h index 29811060a..b95c283e9 100644 --- a/src/tcuda.h +++ b/src/tcuda.h @@ -2,7 +2,7 @@ #define tcuda_h struct terra_State; -int terra_cudainit(struct terra_State * T); -int terra_cudafree(struct terra_State * T); +int terra_cudainit(struct terra_State* T); +int terra_cudafree(struct terra_State* T); #endif \ No newline at end of file diff --git a/src/tcwrapper.cpp b/src/tcwrapper.cpp index bc2ef7b9c..a71d05afb 100644 --- a/src/tcwrapper.cpp +++ b/src/tcwrapper.cpp @@ -27,11 +27,10 @@ extern "C" { using namespace clang; - -static void CreateTableWithName(Obj * parent, const char * name, Obj * result) { - lua_State * L = parent->getState(); +static void CreateTableWithName(Obj *parent, const char *name, Obj *result) { + lua_State *L = parent->getState(); lua_newtable(L); - result->initFromStack(L,parent->getRefTable()); + result->initFromStack(L, parent->getRefTable()); result->push(); parent->setfield(name); } @@ -39,322 +38,323 @@ static void CreateTableWithName(Obj * parent, const char * name, Obj * result) { const int TARGET_POS = 1; const int HEADERPROVIDER_POS = 4; -// part of the setup is adapted from: http://eli.thegreenplace.net/2012/06/08/basic-source-to-source-transformation-with-clang/ +// part of the setup is adapted from: +// http://eli.thegreenplace.net/2012/06/08/basic-source-to-source-transformation-with-clang/ // By implementing RecursiveASTVisitor, we can specify which AST nodes // we're interested in by overriding relevant methods. -class IncludeCVisitor : public RecursiveASTVisitor -{ +class IncludeCVisitor : public RecursiveASTVisitor { public: - IncludeCVisitor(Obj * res, TerraTarget * TT_, const std::string & livenessfunction_) - : resulttable(res), - L(res->getState()), - ref_table(res->getRefTable()), - TT(TT_), - livenessfunction(livenessfunction_) { - - //create tables for errors messages, general namespace, and the tagged namespace - InitTable(&error_table,"errors"); - InitTable(&general,"general"); - InitTable(&tagged,"tagged"); + IncludeCVisitor(Obj *res, TerraTarget *TT_, const std::string &livenessfunction_) + : resulttable(res), + L(res->getState()), + ref_table(res->getRefTable()), + TT(TT_), + livenessfunction(livenessfunction_) { + // create tables for errors messages, general namespace, and the tagged namespace + InitTable(&error_table, "errors"); + InitTable(&general, "general"); + InitTable(&tagged, "tagged"); } - void InitTable(Obj * tbl, const char * name) { + void InitTable(Obj *tbl, const char *name) { CreateTableWithName(resulttable, name, tbl); } - - void InitType(const char * name, Obj * tt) { + + void InitType(const char *name, Obj *tt) { PushTypeField(name); - tt->initFromStack(L,ref_table); + tt->initFromStack(L, ref_table); } - - void PushTypeField(const char * name) { + + void PushTypeField(const char *name) { lua_getfield(L, LUA_GLOBALSINDEX, "terra"); lua_getfield(L, -1, "types"); lua_getfield(L, -1, name); - lua_remove(L,-2); - lua_remove(L,-2); + lua_remove(L, -2); + lua_remove(L, -2); } - - bool ImportError(const std::string & msg) { + + bool ImportError(const std::string &msg) { error_message = msg; return false; } - - bool GetFields( RecordDecl * rd, Obj * entries) { - - //check the fields of this struct, if any one of them is not understandable, then this struct becomes 'opaque' - //that is, we insert the type, and link it to its llvm type, so it can be used in terra code - //but none of its fields are exposed (since we don't understand the layout) + + bool GetFields(RecordDecl *rd, Obj *entries) { + // check the fields of this struct, if any one of them is not understandable, then + // this struct becomes 'opaque' that is, we insert the type, and link it to its + // llvm type, so it can be used in terra code but none of its fields are exposed + // (since we don't understand the layout) bool opaque = false; int anonname = 0; - for(RecordDecl::field_iterator it = rd->field_begin(), end = rd->field_end(); it != end; ++it) { + for (RecordDecl::field_iterator it = rd->field_begin(), end = rd->field_end(); + it != end; ++it) { DeclarationName declname = it->getDeclName(); - - if(it->isBitField() || (!it->isAnonymousStructOrUnion() && !declname)) { + + if (it->isBitField() || (!it->isAnonymousStructOrUnion() && !declname)) { opaque = true; continue; } std::string declstr; - if(it->isAnonymousStructOrUnion()) { + if (it->isAnonymousStructOrUnion()) { char buf[32]; - sprintf(buf,"_%d",anonname++); + sprintf(buf, "_%d", anonname++); declstr = buf; } else { declstr = declname.getAsString(); } QualType FT = it->getType(); Obj fobj; - if(!GetType(FT,&fobj)) { + if (!GetType(FT, &fobj)) { opaque = true; continue; } lua_newtable(L); fobj.push(); - lua_setfield(L,-2,"type"); - lua_pushstring(L,declstr.c_str()); - lua_setfield(L,-2,"field"); + lua_setfield(L, -2, "type"); + lua_pushstring(L, declstr.c_str()); + lua_setfield(L, -2, "field"); entries->addentry(); } return !opaque; - } size_t RegisterRecordType(QualType T) { outputtypes.push_back(Context->getPointerType(T)); - assert(outputtypes.size() < 65536 && "fixme: clang limits number of arguments to 65536"); + assert(outputtypes.size() < 65536 && + "fixme: clang limits number of arguments to 65536"); return outputtypes.size() - 1; } - bool GetRecordTypeFromDecl(RecordDecl * rd, Obj * tt) { - if(rd->isStruct() || rd->isUnion()) { + bool GetRecordTypeFromDecl(RecordDecl *rd, Obj *tt) { + if (rd->isStruct() || rd->isUnion()) { std::string name = rd->getName(); - Obj * thenamespace = &tagged; - if(name == "") { - TypedefNameDecl * decl = rd->getTypedefNameForAnonDecl(); - if(decl) { + Obj *thenamespace = &tagged; + if (name == "") { + TypedefNameDecl *decl = rd->getTypedefNameForAnonDecl(); + if (decl) { thenamespace = &general; name = decl->getName(); } } - //if name == "" then we have an anonymous struct - if(!thenamespace->obj(name.c_str(),tt)) { - lua_getfield(L,TARGET_POS,"getorcreatecstruct"); - lua_pushvalue(L,TARGET_POS); + // if name == "" then we have an anonymous struct + if (!thenamespace->obj(name.c_str(), tt)) { + lua_getfield(L, TARGET_POS, "getorcreatecstruct"); + lua_pushvalue(L, TARGET_POS); lua_pushstring(L, name.c_str()); lua_pushboolean(L, thenamespace == &tagged); - lua_call(L,3,1); - tt->initFromStack(L,ref_table); - if(!tt->boolean("llvm_definingfunction")) { + lua_call(L, 3, 1); + tt->initFromStack(L, ref_table); + if (!tt->boolean("llvm_definingfunction")) { size_t argpos = RegisterRecordType(Context->getRecordType(rd)); - lua_pushstring(L,livenessfunction.c_str()); + lua_pushstring(L, livenessfunction.c_str()); tt->setfield("llvm_definingfunction"); - lua_pushinteger(L,TT->id); + lua_pushinteger(L, TT->id); tt->setfield("llvm_definingtarget"); - lua_pushinteger(L,argpos); + lua_pushinteger(L, argpos); tt->setfield("llvm_argumentposition"); } - if(name != "") { //do not remember a name for an anonymous struct + if (name != "") { // do not remember a name for an anonymous struct tt->push(); - thenamespace->setfield(name.c_str()); //register the type + thenamespace->setfield(name.c_str()); // register the type } } - - if(tt->boolean("undefined") && rd->getDefinition() != NULL) { + + if (tt->boolean("undefined") && rd->getDefinition() != NULL) { tt->clearfield("undefined"); - RecordDecl * defn = rd->getDefinition(); + RecordDecl *defn = rd->getDefinition(); Obj entries; tt->newlist(&entries); - if(GetFields(defn, &entries)) { - if(!defn->isUnion()) { - //structtype.entries = {entry1, entry2, ... } + if (GetFields(defn, &entries)) { + if (!defn->isUnion()) { + // structtype.entries = {entry1, entry2, ... } entries.push(); tt->setfield("entries"); } else { - //add as a union: - //structtype.entries = { {entry1,entry2,...} } + // add as a union: + // structtype.entries = { {entry1,entry2,...} } Obj allentries; - tt->obj("entries",&allentries); + tt->obj("entries", &allentries); entries.push(); allentries.addentry(); } tt->pushfield("complete"); tt->push(); - lua_call(L,1,0); + lua_call(L, 1, 0); } } - + return true; } else { return ImportError("non-struct record types are not supported"); } } - bool GetType(QualType T, Obj * tt) { - + bool GetType(QualType T, Obj *tt) { T = Context->getCanonicalType(T); const Type *Ty = T.getTypePtr(); - + switch (Ty->getTypeClass()) { - case Type::Record: { - const RecordType *RT = dyn_cast(Ty); - RecordDecl * rd = RT->getDecl(); - return GetRecordTypeFromDecl(rd, tt); - } break; //TODO - case Type::Builtin: - switch (cast(Ty)->getKind()) { - case BuiltinType::Void: - InitType("opaque",tt); - return true; - case BuiltinType::Bool: - InitType("bool",tt); - return true; - case BuiltinType::Char_S: - case BuiltinType::Char_U: - case BuiltinType::SChar: - case BuiltinType::UChar: - case BuiltinType::Short: - case BuiltinType::UShort: - case BuiltinType::Int: - case BuiltinType::UInt: - case BuiltinType::Long: - case BuiltinType::ULong: - case BuiltinType::LongLong: - case BuiltinType::ULongLong: - case BuiltinType::WChar_S: - case BuiltinType::WChar_U: - case BuiltinType::Char16: - case BuiltinType::Char32: { - std::stringstream ss; - if (Ty->isUnsignedIntegerType()) - ss << "u"; - ss << "int"; - int sz = Context->getTypeSize(T); - ss << sz; - InitType(ss.str().c_str(),tt); - return true; - } - case BuiltinType::Half: - break; - case BuiltinType::Float: - InitType("float",tt); - return true; - case BuiltinType::Double: - InitType("double",tt); - return true; - case BuiltinType::LongDouble: - case BuiltinType::NullPtr: - case BuiltinType::UInt128: - default: + case Type::Record: { + const RecordType *RT = dyn_cast(Ty); + RecordDecl *rd = RT->getDecl(); + return GetRecordTypeFromDecl(rd, tt); + } break; // TODO + case Type::Builtin: + switch (cast(Ty)->getKind()) { + case BuiltinType::Void: + InitType("opaque", tt); + return true; + case BuiltinType::Bool: + InitType("bool", tt); + return true; + case BuiltinType::Char_S: + case BuiltinType::Char_U: + case BuiltinType::SChar: + case BuiltinType::UChar: + case BuiltinType::Short: + case BuiltinType::UShort: + case BuiltinType::Int: + case BuiltinType::UInt: + case BuiltinType::Long: + case BuiltinType::ULong: + case BuiltinType::LongLong: + case BuiltinType::ULongLong: + case BuiltinType::WChar_S: + case BuiltinType::WChar_U: + case BuiltinType::Char16: + case BuiltinType::Char32: { + std::stringstream ss; + if (Ty->isUnsignedIntegerType()) ss << "u"; + ss << "int"; + int sz = Context->getTypeSize(T); + ss << sz; + InitType(ss.str().c_str(), tt); + return true; + } + case BuiltinType::Half: + break; + case BuiltinType::Float: + InitType("float", tt); + return true; + case BuiltinType::Double: + InitType("double", tt); + return true; + case BuiltinType::LongDouble: + case BuiltinType::NullPtr: + case BuiltinType::UInt128: + default: + break; + } + case Type::Complex: + case Type::LValueReference: + case Type::RValueReference: break; - } - case Type::Complex: - case Type::LValueReference: - case Type::RValueReference: - break; - case Type::Pointer: { - const PointerType *PTy = cast(Ty); - QualType ETy = PTy->getPointeeType(); - Obj t2; - if(!GetType(ETy,&t2)) { - return false; - } - PushTypeField("pointer"); - t2.push(); - lua_call(L,1,1); - tt->initFromStack(L, ref_table); - return true; - } - - case Type::VariableArray: - case Type::IncompleteArray: - break; - case Type::ConstantArray: { - Obj at; - const ConstantArrayType *ATy = cast(Ty); - int sz = ATy->getSize().getZExtValue(); - if(GetType(ATy->getElementType(),&at)) { - PushTypeField("array"); - at.push(); - lua_pushinteger(L, sz); - lua_call(L,2,1); - tt->initFromStack(L,ref_table); + case Type::Pointer: { + const PointerType *PTy = cast(Ty); + QualType ETy = PTy->getPointeeType(); + Obj t2; + if (!GetType(ETy, &t2)) { + return false; + } + PushTypeField("pointer"); + t2.push(); + lua_call(L, 1, 1); + tt->initFromStack(L, ref_table); return true; - } else { - return false; } - } break; - case Type::ExtVector: - case Type::Vector: { - //printf("making a vector!\n"); + + case Type::VariableArray: + case Type::IncompleteArray: + break; + case Type::ConstantArray: { + Obj at; + const ConstantArrayType *ATy = cast(Ty); + int sz = ATy->getSize().getZExtValue(); + if (GetType(ATy->getElementType(), &at)) { + PushTypeField("array"); + at.push(); + lua_pushinteger(L, sz); + lua_call(L, 2, 1); + tt->initFromStack(L, ref_table); + return true; + } else { + return false; + } + } break; + case Type::ExtVector: + case Type::Vector: { + // printf("making a vector!\n"); const VectorType *VT = cast(T); Obj at; - if(GetType(VT->getElementType(),&at)) { + if (GetType(VT->getElementType(), &at)) { int n = VT->getNumElements(); PushTypeField("vector"); at.push(); - lua_pushinteger(L,n); - lua_call(L,2,1); + lua_pushinteger(L, n); + lua_call(L, 2, 1); tt->initFromStack(L, ref_table); return true; } else { return false; } - } break; - case Type::FunctionNoProto: /* fallthrough */ - case Type::FunctionProto: { + } break; + case Type::FunctionNoProto: /* fallthrough */ + case Type::FunctionProto: { const FunctionType *FT = cast(Ty); - return FT && GetFuncType(FT,tt); - } - case Type::ObjCObject: - case Type::ObjCInterface: - case Type::ObjCObjectPointer: - case Type::Enum: - InitType("uint32",tt); - return true; - case Type::BlockPointer: - case Type::MemberPointer: - case Type::Atomic: - default: - break; + return FT && GetFuncType(FT, tt); + } + case Type::ObjCObject: + case Type::ObjCInterface: + case Type::ObjCObjectPointer: + case Type::Enum: + InitType("uint32", tt); + return true; + case Type::BlockPointer: + case Type::MemberPointer: + case Type::Atomic: + default: + break; } std::stringstream ss; - ss << "type not understood: " << T.getAsString().c_str() << " " << Ty->getTypeClass(); + ss << "type not understood: " << T.getAsString().c_str() << " " + << Ty->getTypeClass(); return ImportError(ss.str().c_str()); } - void SetErrorReport(const char * field) { - lua_pushstring(L,error_message.c_str()); + void SetErrorReport(const char *field) { + lua_pushstring(L, error_message.c_str()); error_table.setfield(field); } - CStyleCastExpr* CreateCast(QualType Ty, CastKind Kind, Expr *E) { - TypeSourceInfo *TInfo = Context->getTrivialTypeSourceInfo(Ty, SourceLocation()); - return CStyleCastExpr::Create(*Context, Ty, VK_RValue, Kind, E, 0, TInfo, - SourceLocation(), SourceLocation()); + CStyleCastExpr *CreateCast(QualType Ty, CastKind Kind, Expr *E) { + TypeSourceInfo *TInfo = Context->getTrivialTypeSourceInfo(Ty, SourceLocation()); + return CStyleCastExpr::Create(*Context, Ty, VK_RValue, Kind, E, 0, TInfo, + SourceLocation(), SourceLocation()); } - IntegerLiteral * LiteralZero() { + IntegerLiteral *LiteralZero() { unsigned IntSize = static_cast(Context->getTypeSize(Context->IntTy)); - return IntegerLiteral::Create(*Context, llvm::APInt(IntSize, 0), Context->IntTy, SourceLocation()); + return IntegerLiteral::Create(*Context, llvm::APInt(IntSize, 0), Context->IntTy, + SourceLocation()); } - DeclRefExpr * GetDeclReference(ValueDecl * vd) { - DeclRefExpr *DR = DeclRefExpr::Create(*Context, NestedNameSpecifierLoc(),SourceLocation(),vd, false, SourceLocation(), - vd->getType(), - VK_LValue); + DeclRefExpr *GetDeclReference(ValueDecl *vd) { + DeclRefExpr *DR = DeclRefExpr::Create(*Context, NestedNameSpecifierLoc(), + SourceLocation(), vd, false, + SourceLocation(), vd->getType(), VK_LValue); return DR; } - void KeepLive(ValueDecl * vd) { - Expr * castexp = CreateCast(Context->VoidTy, clang::CK_ToVoid, GetDeclReference(vd)); + void KeepLive(ValueDecl *vd) { + Expr *castexp = + CreateCast(Context->VoidTy, clang::CK_ToVoid, GetDeclReference(vd)); outputstmts.push_back(castexp); } - bool VisitTypedefDecl(TypedefDecl * TD) { + bool VisitTypedefDecl(TypedefDecl *TD) { bool isCanonical = (TD == TD->getCanonicalDecl()); - #if LLVM_VERSION >= 36 && defined(_WIN32) - // Starting with LLVM 3.6, clang initializes "size_t" as an implicit declaration - // when being compatible with MSVC. - if (!isCanonical && TD->getName().str() == "size_t") { - isCanonical = (TD->getPreviousDecl() == TD->getCanonicalDecl()); - } - #endif - if(isCanonical && TD->getDeclContext()->getDeclKind() == Decl::TranslationUnit) { +#if LLVM_VERSION >= 36 && defined(_WIN32) + // Starting with LLVM 3.6, clang initializes "size_t" as an implicit declaration + // when being compatible with MSVC. + if (!isCanonical && TD->getName().str() == "size_t") { + isCanonical = (TD->getPreviousDecl() == TD->getCanonicalDecl()); + } +#endif + if (isCanonical && TD->getDeclContext()->getDeclKind() == Decl::TranslationUnit) { llvm::StringRef name = TD->getName(); QualType QT = Context->getCanonicalType(TD->getUnderlyingType()); Obj typ; - if(GetType(QT,&typ)) { + if (GetType(QT, &typ)) { typ.push(); general.setfield(name.str().c_str()); } else { @@ -363,171 +363,187 @@ class IncludeCVisitor : public RecursiveASTVisitor } return true; } - bool TraverseRecordDecl(RecordDecl * rd) { - if(rd->getDeclContext()->getDeclKind() == Decl::TranslationUnit) { + bool TraverseRecordDecl(RecordDecl *rd) { + if (rd->getDeclContext()->getDeclKind() == Decl::TranslationUnit) { Obj type; GetRecordTypeFromDecl(rd, &type); } return true; } - bool VisitEnumConstantDecl(EnumConstantDecl * E) { + bool VisitEnumConstantDecl(EnumConstantDecl *E) { int64_t v = E->getInitVal().getSExtValue(); llvm::StringRef name = E->getName(); - lua_pushnumber(L,(double)v); //I _think_ enums by spec must fit in an int, so they will fit in a double + lua_pushnumber(L, (double)v); // I _think_ enums by spec must fit in an int, so + // they will fit in a double general.setfield(name.str().c_str()); return true; } - bool GetFuncType(const FunctionType * f, Obj * typ) { - Obj returntype,parameters; + bool GetFuncType(const FunctionType *f, Obj *typ) { + Obj returntype, parameters; resulttable->newlist(¶meters); - - bool valid = true; //decisions about whether this function can be exported or not are delayed until we have seen all the potential problems - #if LLVM_VERSION <= 34 + + bool valid = + true; // decisions about whether this function can be exported or not are + // delayed until we have seen all the potential problems +#if LLVM_VERSION <= 34 QualType RT = f->getResultType(); - #else +#else QualType RT = f->getReturnType(); - #endif - if(RT->isVoidType()) { +#endif + if (RT->isVoidType()) { PushTypeField("unit"); returntype.initFromStack(L, ref_table); } else { - if(!GetType(RT,&returntype)) - valid = false; + if (!GetType(RT, &returntype)) valid = false; } - - - const FunctionProtoType * proto = f->getAs(); - //proto is null if the function was declared without an argument list (e.g. void foo() and not void foo(void)) - //we don't support old-style C parameter lists, we just treat them as empty - if(proto) { - #if LLVM_VERSION >= 35 - for(size_t i = 0; i < proto->getNumParams(); i++) { + + const FunctionProtoType *proto = f->getAs(); + // proto is null if the function was declared without an argument list (e.g. void + // foo() and not void foo(void)) we don't support old-style C parameter lists, we + // just treat them as empty + if (proto) { +#if LLVM_VERSION >= 35 + for (size_t i = 0; i < proto->getNumParams(); i++) { QualType PT = proto->getParamType(i); - #else - for(size_t i = 0; i < proto->getNumArgs(); i++) { +#else + for (size_t i = 0; i < proto->getNumArgs(); i++) { QualType PT = proto->getArgType(i); - #endif +#endif Obj pt; - if(!GetType(PT,&pt)) { - valid = false; //keep going with attempting to parse type to make sure we see all the reasons why we cannot support this function - } else if(valid) { + if (!GetType(PT, &pt)) { + valid = false; // keep going with attempting to parse type to make + // sure we see all the reasons why we cannot support + // this function + } else if (valid) { pt.push(); parameters.addentry(); } } } - - if(valid) { + + if (valid) { PushTypeField("functype"); parameters.push(); returntype.push(); lua_pushboolean(L, proto ? proto->isVariadic() : false); lua_call(L, 3, 1); - typ->initFromStack(L,ref_table); + typ->initFromStack(L, ref_table); } - + return valid; } bool TraverseFunctionDecl(FunctionDecl *f) { - // Function name + // Function name DeclarationName DeclName = f->getNameInfo().getName(); std::string FuncName = DeclName.getAsString(); - const FunctionType * fntyp = f->getType()->getAs(); - - if(!fntyp) - return true; - - if(f->getStorageClass() == clang::SC_Static) { + const FunctionType *fntyp = f->getType()->getAs(); + + if (!fntyp) return true; + + if (f->getStorageClass() == clang::SC_Static) { ImportError("cannot import static functions."); SetErrorReport(FuncName.c_str()); return true; } - + Obj typ; - if(!GetFuncType(fntyp,&typ)) { + if (!GetFuncType(fntyp, &typ)) { SetErrorReport(FuncName.c_str()); return true; } std::string InternalName = FuncName; // Avoid mangle on LLVM 6 and macOS - AsmLabelAttr * asmlabel = f->getAttr(); - if(asmlabel) { - #if !((LLVM_VERSION > 50) && __APPLE__) + AsmLabelAttr *asmlabel = f->getAttr(); + if (asmlabel) { +#if !((LLVM_VERSION > 50) && __APPLE__) InternalName = asmlabel->getLabel(); - #if !defined(__linux__) && !defined(__FreeBSD__) - //In OSX and Windows LLVM mangles assembler labels by adding a '\01' prefix - InternalName.insert(InternalName.begin(), '\01'); - #endif - #else +#if !defined(__linux__) && !defined(__FreeBSD__) + // In OSX and Windows LLVM mangles assembler labels by adding a '\01' prefix + InternalName.insert(InternalName.begin(), '\01'); +#endif +#else std::string label = asmlabel->getLabel(); - if(!((label[0] == '_') && (label.substr(1) == InternalName))) { + if (!((label[0] == '_') && (label.substr(1) == InternalName))) { InternalName = asmlabel->getLabel(); InternalName.insert(InternalName.begin(), '\01'); } - #endif +#endif // Uncomment for mangling issue debugging // llvm::errs() << "[mangle] " << FuncName << "=" << InternalName << "\n"; } - CreateFunction(FuncName,InternalName,&typ); - - KeepLive(f);//make sure this function is live in codegen by creating a dummy reference to it (void) is to suppress unused warnings - + CreateFunction(FuncName, InternalName, &typ); + + KeepLive(f); // make sure this function is live in codegen by creating a dummy + // reference to it (void) is to suppress unused warnings + return true; } - void CreateFunction(const std::string & name, const std::string & internalname, Obj * typ) { - if(!general.hasfield(name.c_str())) { + void CreateFunction(const std::string &name, const std::string &internalname, + Obj *typ) { + if (!general.hasfield(name.c_str())) { lua_getfield(L, LUA_GLOBALSINDEX, "terra"); lua_getfield(L, -1, "externfunction"); - lua_remove(L,-2); //terra table + lua_remove(L, -2); // terra table lua_pushstring(L, internalname.c_str()); typ->push(); lua_call(L, 2, 1); general.setfield(name.c_str()); } } - void SetContext(ASTContext * ctx) { - Context = ctx; - } - FunctionDecl * GetLivenessFunction() { - IdentifierInfo & II = Context->Idents.get(livenessfunction); + void SetContext(ASTContext *ctx) { Context = ctx; } + FunctionDecl *GetLivenessFunction() { + IdentifierInfo &II = Context->Idents.get(livenessfunction); DeclarationName N = Context->DeclarationNames.getIdentifier(&II); - #if LLVM_VERSION >= 33 - QualType T = Context->getFunctionType(Context->VoidTy, outputtypes, FunctionProtoType::ExtProtoInfo()); - #else - QualType T = Context->getFunctionType(Context->VoidTy, &outputtypes[0],outputtypes.size(), FunctionProtoType::ExtProtoInfo()); - #endif - FunctionDecl * F = FunctionDecl::Create(*Context, Context->getTranslationUnitDecl(), SourceLocation(), SourceLocation(), N,T, 0, SC_Extern); - +#if LLVM_VERSION >= 33 + QualType T = Context->getFunctionType(Context->VoidTy, outputtypes, + FunctionProtoType::ExtProtoInfo()); +#else + QualType T = Context->getFunctionType(Context->VoidTy, &outputtypes[0], + outputtypes.size(), + FunctionProtoType::ExtProtoInfo()); +#endif + FunctionDecl *F = FunctionDecl::Create( + *Context, Context->getTranslationUnitDecl(), SourceLocation(), + SourceLocation(), N, T, 0, SC_Extern); + std::vector params; - for(size_t i = 0; i < outputtypes.size(); i++) { - params.push_back(ParmVarDecl::Create(*Context, F, SourceLocation(), SourceLocation(), 0, outputtypes[i], /*TInfo=*/0, SC_None, - #if LLVM_VERSION <= 32 - SC_None, - #endif - 0)); + for (size_t i = 0; i < outputtypes.size(); i++) { + params.push_back(ParmVarDecl::Create(*Context, F, SourceLocation(), + SourceLocation(), 0, outputtypes[i], + /*TInfo=*/0, SC_None, +#if LLVM_VERSION <= 32 + SC_None, +#endif + 0)); } F->setParams(params); - #if LLVM_VERSION >= 60 - CompoundStmt * stmts = CompoundStmt::Create(*Context, outputstmts, SourceLocation(), SourceLocation()); - #elif LLVM_VERSION >= 33 - CompoundStmt * stmts = new (*Context) CompoundStmt(*Context, outputstmts, SourceLocation(), SourceLocation()); - #else - CompoundStmt * stmts = new (*Context) CompoundStmt(*Context, &outputstmts[0], outputstmts.size(), SourceLocation(), SourceLocation()); - #endif +#if LLVM_VERSION >= 60 + CompoundStmt *stmts = CompoundStmt::Create(*Context, outputstmts, + SourceLocation(), SourceLocation()); +#elif LLVM_VERSION >= 33 + CompoundStmt *stmts = new (*Context) + CompoundStmt(*Context, outputstmts, SourceLocation(), SourceLocation()); +#else + CompoundStmt *stmts = + new (*Context) CompoundStmt(*Context, &outputstmts[0], outputstmts.size(), + SourceLocation(), SourceLocation()); +#endif F->setBody(stmts); return F; } bool TraverseVarDecl(VarDecl *v) { - if(!(v->isFileVarDecl() && (v->hasExternalStorage() || v->getStorageClass() == clang::SC_None))) //is this a non-static global variable? + if (!(v->isFileVarDecl() && + (v->hasExternalStorage() || + v->getStorageClass() == + clang::SC_None))) // is this a non-static global variable? return true; - + QualType t = v->getType(); Obj typ; - if(!GetType(t, &typ)) - return true; + if (!GetType(t, &typ)) return true; std::string name = v->getNameAsString(); CreateExternGlobal(name, &typ); @@ -535,108 +551,134 @@ class IncludeCVisitor : public RecursiveASTVisitor return true; } - void CreateExternGlobal(const std::string & name, Obj * typ) { - if(!general.hasfield(name.c_str())) { + void CreateExternGlobal(const std::string &name, Obj *typ) { + if (!general.hasfield(name.c_str())) { lua_getfield(L, LUA_GLOBALSINDEX, "terra"); lua_getfield(L, -1, "global"); - lua_remove(L, -2); //terra table + lua_remove(L, -2); // terra table typ->push(); - lua_pushnil(L); //no initializer + lua_pushnil(L); // no initializer lua_pushstring(L, name.c_str()); - lua_pushboolean(L,true); + lua_pushboolean(L, true); lua_call(L, 4, 1); general.setfield(name.c_str()); } } - private: - std::vector outputstmts; + +private: + std::vector outputstmts; std::vector outputtypes; - Obj * resulttable; //holds table returned to lua includes "functions", "types", and "errors" - lua_State * L; + Obj *resulttable; // holds table returned to lua includes "functions", "types", and + // "errors" + lua_State *L; int ref_table; - ASTContext * Context; - Obj error_table; //name -> related error message - Obj general; //name -> function or type in the general namespace - Obj tagged; //name -> type in the tagged namespace (e.g. struct Foo) + ASTContext *Context; + Obj error_table; // name -> related error message + Obj general; // name -> function or type in the general namespace + Obj tagged; // name -> type in the tagged namespace (e.g. struct Foo) std::string error_message; - TerraTarget * TT; + TerraTarget *TT; std::string livenessfunction; }; class CodeGenProxy : public ASTConsumer { public: - CodeGenProxy(CodeGenerator * CG_, Obj * result, TerraTarget * TT, const std::string & livenessfunction) - : CG(CG_), Visitor(result,TT,livenessfunction) {} - CodeGenerator * CG; - IncludeCVisitor Visitor; - virtual ~CodeGenProxy() {} - virtual void Initialize(ASTContext &Context) { - Visitor.SetContext(&Context); - CG->Initialize(Context); - } - virtual bool HandleTopLevelDecl(DeclGroupRef D) { - for (DeclGroupRef::iterator b = D.begin(), e = D.end(); - b != e; ++b) + CodeGenProxy(CodeGenerator *CG_, Obj *result, TerraTarget *TT, + const std::string &livenessfunction) + : CG(CG_), Visitor(result, TT, livenessfunction) {} + CodeGenerator *CG; + IncludeCVisitor Visitor; + virtual ~CodeGenProxy() {} + virtual void Initialize(ASTContext &Context) { + Visitor.SetContext(&Context); + CG->Initialize(Context); + } + virtual bool HandleTopLevelDecl(DeclGroupRef D) { + for (DeclGroupRef::iterator b = D.begin(), e = D.end(); b != e; ++b) Visitor.TraverseDecl(*b); - return CG->HandleTopLevelDecl(D); - } - virtual void HandleInterestingDecl(DeclGroupRef D) { CG->HandleInterestingDecl(D); } - virtual void HandleTranslationUnit(ASTContext &Ctx) { - Decl * Decl = Visitor.GetLivenessFunction(); - DeclGroupRef R = DeclGroupRef::Create(Ctx, &Decl, 1); - CG->HandleTopLevelDecl(R); - CG->HandleTranslationUnit(Ctx); - } - virtual void HandleTagDeclDefinition(TagDecl *D) { CG->HandleTagDeclDefinition(D); } - virtual void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) { CG->HandleCXXImplicitFunctionInstantiation(D); } - virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) { CG->HandleTopLevelDeclInObjCContainer(D); } - virtual void CompleteTentativeDefinition(VarDecl *D) { CG->CompleteTentativeDefinition(D); } - virtual void HandleCXXStaticMemberVarInstantiation(VarDecl *D) { CG->HandleCXXStaticMemberVarInstantiation(D); } - #if LLVM_VERSION >= 37 - virtual void HandleVTable(CXXRecordDecl *RD) { CG->HandleVTable(RD); } - #else - virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) { CG->HandleVTable(RD, DefinitionRequired); } - #endif - virtual ASTMutationListener *GetASTMutationListener() { return CG->GetASTMutationListener(); } - virtual ASTDeserializationListener *GetASTDeserializationListener() { return CG->GetASTDeserializationListener(); } - virtual void PrintStats() { CG->PrintStats(); } + return CG->HandleTopLevelDecl(D); + } + virtual void HandleInterestingDecl(DeclGroupRef D) { CG->HandleInterestingDecl(D); } + virtual void HandleTranslationUnit(ASTContext &Ctx) { + Decl *Decl = Visitor.GetLivenessFunction(); + DeclGroupRef R = DeclGroupRef::Create(Ctx, &Decl, 1); + CG->HandleTopLevelDecl(R); + CG->HandleTranslationUnit(Ctx); + } + virtual void HandleTagDeclDefinition(TagDecl *D) { CG->HandleTagDeclDefinition(D); } + virtual void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) { + CG->HandleCXXImplicitFunctionInstantiation(D); + } + virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) { + CG->HandleTopLevelDeclInObjCContainer(D); + } + virtual void CompleteTentativeDefinition(VarDecl *D) { + CG->CompleteTentativeDefinition(D); + } + virtual void HandleCXXStaticMemberVarInstantiation(VarDecl *D) { + CG->HandleCXXStaticMemberVarInstantiation(D); + } +#if LLVM_VERSION >= 37 + virtual void HandleVTable(CXXRecordDecl *RD) { CG->HandleVTable(RD); } +#else + virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) { + CG->HandleVTable(RD, DefinitionRequired); + } +#endif + virtual ASTMutationListener *GetASTMutationListener() { + return CG->GetASTMutationListener(); + } + virtual ASTDeserializationListener *GetASTDeserializationListener() { + return CG->GetASTDeserializationListener(); + } + virtual void PrintStats() { CG->PrintStats(); } #if LLVM_VERSION == 32 - virtual void HandleImplicitImportDecl(ImportDecl *D) { CG->HandleImplicitImportDecl(D); } - virtual PPMutationListener *GetPPMutationListener() { return CG->GetPPMutationListener(); } + virtual void HandleImplicitImportDecl(ImportDecl *D) { + CG->HandleImplicitImportDecl(D); + } + virtual PPMutationListener *GetPPMutationListener() { + return CG->GetPPMutationListener(); + } #elif LLVM_VERSION >= 33 - virtual void HandleImplicitImportDecl(ImportDecl *D) { CG->HandleImplicitImportDecl(D); } - virtual bool shouldSkipFunctionBody(Decl *D) { return CG->shouldSkipFunctionBody(D); } + virtual void HandleImplicitImportDecl(ImportDecl *D) { + CG->HandleImplicitImportDecl(D); + } + virtual bool shouldSkipFunctionBody(Decl *D) { return CG->shouldSkipFunctionBody(D); } #endif - }; class LuaProvidedFile : public clang::vfs::File { private: - std::string Name; - clang::vfs::Status Status; - StringRef Buffer; + std::string Name; + clang::vfs::Status Status; + StringRef Buffer; + public: - LuaProvidedFile(const std::string & Name_, const clang::vfs::Status & Status_, const StringRef & Buffer_) : Name(Name_), Status(Status_), Buffer(Buffer_) {} - virtual ~LuaProvidedFile() override {} - virtual llvm::ErrorOr status() override { return Status; } + LuaProvidedFile(const std::string &Name_, const clang::vfs::Status &Status_, + const StringRef &Buffer_) + : Name(Name_), Status(Status_), Buffer(Buffer_) {} + virtual ~LuaProvidedFile() override {} + virtual llvm::ErrorOr status() override { return Status; } #if LLVM_VERSION >= 36 - virtual llvm::ErrorOr > - getBuffer(const Twine &Name, int64_t FileSize, - bool RequiresNullTerminator, bool IsVolatile) override { - return llvm::MemoryBuffer::getMemBuffer(Buffer,"",RequiresNullTerminator); - } + virtual llvm::ErrorOr > getBuffer( + const Twine &Name, int64_t FileSize, bool RequiresNullTerminator, + bool IsVolatile) override { + return llvm::MemoryBuffer::getMemBuffer(Buffer, "", RequiresNullTerminator); + } #else - virtual std::error_code - getBuffer(const Twine &Name, std::unique_ptr &Result, int64_t FileSize, - bool RequiresNullTerminator, bool IsVolatile) override { - Result.reset(llvm::MemoryBuffer::getMemBuffer(Buffer,"",RequiresNullTerminator)); + virtual std::error_code getBuffer(const Twine &Name, + std::unique_ptr &Result, + int64_t FileSize, bool RequiresNullTerminator, + bool IsVolatile) override { + Result.reset( + llvm::MemoryBuffer::getMemBuffer(Buffer, "", RequiresNullTerminator)); return std::error_code(); - } + } #endif - virtual std::error_code close() override { return std::error_code(); } + virtual std::error_code close() override { return std::error_code(); } #if LLVM_VERSION <= 37 - virtual void setName(StringRef Name_) override { Name = Name_; } + virtual void setName(StringRef Name_) override { Name = Name_; } #endif }; @@ -644,7 +686,7 @@ class LuaProvidedFile : public clang::vfs::File { static llvm::sys::TimeValue ZeroTime() { #if LLVM_VERSION >= 36 return llvm::sys::TimeValue::ZeroTime(); -#else +#else return llvm::sys::TimeValue::ZeroTime; #endif } @@ -655,126 +697,141 @@ static llvm::sys::TimePoint<> ZeroTime() { #endif class LuaOverlayFileSystem : public clang::vfs::FileSystem { private: - IntrusiveRefCntPtr RFS; - lua_State * L; + IntrusiveRefCntPtr RFS; + lua_State *L; + public: - LuaOverlayFileSystem(lua_State * L_) : RFS(vfs::getRealFileSystem()), L(L_) {} - - bool GetFile(const llvm::Twine &Path, clang::vfs::Status * status, StringRef * contents) { - lua_pushvalue(L, HEADERPROVIDER_POS); - lua_pushstring(L, Path.str().c_str()); - lua_call(L,1,1); - if(!lua_istable(L, -1)) { - lua_pop(L,1); - return false; + LuaOverlayFileSystem(lua_State *L_) : RFS(vfs::getRealFileSystem()), L(L_) {} + + bool GetFile(const llvm::Twine &Path, clang::vfs::Status *status, + StringRef *contents) { + lua_pushvalue(L, HEADERPROVIDER_POS); + lua_pushstring(L, Path.str().c_str()); + lua_call(L, 1, 1); + if (!lua_istable(L, -1)) { + lua_pop(L, 1); + return false; + } + llvm::sys::fs::file_type filetype = llvm::sys::fs::file_type::directory_file; + int64_t size = 0; + lua_getfield(L, -1, "kind"); + const char *kind = lua_tostring(L, -1); + if (strcmp(kind, "file") == 0) { + filetype = llvm::sys::fs::file_type::regular_file; + lua_getfield(L, -2, "contents"); + const char *data = (const char *)lua_touserdata(L, -1); + if (!data) { + data = lua_tostring(L, -1); + } + if (!data) { + lua_pop(L, 3); // pop table,kind,contents + return false; + } + lua_getfield(L, -3, "size"); + size = (lua_isnumber(L, -1)) ? lua_tonumber(L, -1) : ::strlen(data); + *contents = StringRef(data, size); + lua_pop(L, 2); // pop contents, size + } + *status = clang::vfs::Status(Path.str(), +#if LLVM_VERSION <= 37 + "", +#endif + clang::vfs::getNextVirtualUniqueID(), ZeroTime(), 0, + 0, size, filetype, llvm::sys::fs::all_all); + lua_pop(L, 2); // pop table, kind + return true; } - llvm::sys::fs::file_type filetype = llvm::sys::fs::file_type::directory_file; - int64_t size = 0; - lua_getfield(L, -1, "kind"); - const char * kind = lua_tostring(L, -1); - if(strcmp(kind,"file") == 0) { - filetype = llvm::sys::fs::file_type::regular_file; - lua_getfield(L,-2,"contents"); - const char * data = (const char*)lua_touserdata(L,-1); - if(!data) { - data = lua_tostring(L,-1); + virtual ~LuaOverlayFileSystem() {} + + virtual llvm::ErrorOr status(const llvm::Twine &Path) override { + static const std::error_code noSuchFileErr = + std::make_error_code(std::errc::no_such_file_or_directory); + llvm::ErrorOr RealStatus = RFS->status(Path); + if (RealStatus || RealStatus.getError() != noSuchFileErr) return RealStatus; + clang::vfs::Status Status; + StringRef Buffer; + if (GetFile(Path, &Status, &Buffer)) { + return Status; } - if(!data) { - lua_pop(L,3); //pop table,kind,contents - return false; + return llvm::errc::no_such_file_or_directory; + } +#if LLVM_VERSION <= 35 + virtual std::error_code openFileForRead( + const llvm::Twine &Path, std::unique_ptr &Result) override { + std::error_code ec = RFS->openFileForRead(Path, Result); + if (!ec || ec != llvm::errc::no_such_file_or_directory) return ec; + clang::vfs::Status Status; + StringRef Buffer; + if (GetFile(Path, &Status, &Buffer)) { + Result.reset(new LuaProvidedFile(Path.str(), Status, Buffer)); + return std::error_code(); } - lua_getfield(L,-3,"size"); - size = (lua_isnumber(L,-1)) ? lua_tonumber(L,-1) : ::strlen(data); - *contents = StringRef(data,size); - lua_pop(L,2); //pop contents, size + return llvm::errc::no_such_file_or_directory; } - *status = clang::vfs::Status(Path.str(), - #if LLVM_VERSION <= 37 - "", - #endif - clang::vfs::getNextVirtualUniqueID(), ZeroTime(), 0, 0, size, filetype, llvm::sys::fs::all_all); - lua_pop(L, 2); //pop table, kind - return true; - } - virtual ~LuaOverlayFileSystem() {} - - virtual llvm::ErrorOr status(const llvm::Twine &Path) override { - static const std::error_code noSuchFileErr = std::make_error_code(std::errc::no_such_file_or_directory); - llvm::ErrorOr RealStatus = RFS->status(Path); - if (RealStatus || RealStatus.getError() != noSuchFileErr) - return RealStatus; - clang::vfs::Status Status; - StringRef Buffer; - if (GetFile(Path,&Status,&Buffer)) { - return Status; +#else + virtual llvm::ErrorOr > openFileForRead( + const llvm::Twine &Path) override { + llvm::ErrorOr > ec = RFS->openFileForRead(Path); + if (ec || ec.getError() != llvm::errc::no_such_file_or_directory) return ec; + clang::vfs::Status Status; + StringRef Buffer; + if (GetFile(Path, &Status, &Buffer)) { + return std::unique_ptr( + new LuaProvidedFile(Path.str(), Status, Buffer)); + } + return llvm::errc::no_such_file_or_directory; } - return llvm::errc::no_such_file_or_directory; - } - #if LLVM_VERSION <= 35 - virtual std::error_code - openFileForRead(const llvm::Twine &Path, std::unique_ptr &Result) override { - std::error_code ec = RFS->openFileForRead(Path,Result); - if(!ec || ec != llvm::errc::no_such_file_or_directory) - return ec; - clang::vfs::Status Status; - StringRef Buffer; - if (GetFile(Path,&Status,&Buffer)) { - Result.reset(new LuaProvidedFile(Path.str(),Status,Buffer)); - return std::error_code(); +#endif + virtual clang::vfs::directory_iterator dir_begin(const llvm::Twine &Dir, + std::error_code &EC) override { + printf("BUGBUG: unexpected call to directory iterator in C header include. " + "report this a bug on github.com/zdevito/terra"); // as far as I can tell + // this isn't used by the + // things we are using, + // so I am leaving it + // unfinished until this + // changes. + return RFS->dir_begin(Dir, EC); } - return llvm::errc::no_such_file_or_directory; - } - #else - virtual llvm::ErrorOr> openFileForRead(const llvm::Twine &Path) override { - llvm::ErrorOr > ec = RFS->openFileForRead(Path); - if(ec || ec.getError() != llvm::errc::no_such_file_or_directory) - return ec; - clang::vfs::Status Status; - StringRef Buffer; - if (GetFile(Path,&Status,&Buffer)) { - return std::unique_ptr(new LuaProvidedFile(Path.str(),Status,Buffer)); +#if LLVM_VERSION >= 38 + llvm::ErrorOr getCurrentWorkingDirectory() const override { + return std::string("cwd"); } - return llvm::errc::no_such_file_or_directory; - } - #endif - virtual clang::vfs::directory_iterator dir_begin(const llvm::Twine &Dir, - std::error_code &EC) override { - printf("BUGBUG: unexpected call to directory iterator in C header include. report this a bug on github.com/zdevito/terra"); //as far as I can tell this isn't used by the things we are using, so I am leaving it unfinished until this changes. - return RFS->dir_begin(Dir,EC); - } - #if LLVM_VERSION >= 38 - llvm::ErrorOr getCurrentWorkingDirectory() const override { return std::string("cwd"); } - std::error_code setCurrentWorkingDirectory(const Twine &Path) override { return std::error_code(); } - #endif + std::error_code setCurrentWorkingDirectory(const Twine &Path) override { + return std::error_code(); + } +#endif }; - -static void initializeclang(terra_State * T, llvm::MemoryBuffer * membuffer, const char ** argbegin, const char ** argend, CompilerInstance * TheCompInst) { - // CompilerInstance will hold the instance of the Clang compiler for us, - // managing the various objects needed to run the compiler. - #if LLVM_VERSION <= 32 +static void initializeclang(terra_State *T, llvm::MemoryBuffer *membuffer, + const char **argbegin, const char **argend, + CompilerInstance *TheCompInst) { +// CompilerInstance will hold the instance of the Clang compiler for us, +// managing the various objects needed to run the compiler. +#if LLVM_VERSION <= 32 TheCompInst->createDiagnostics(0, 0); - #else +#else TheCompInst->createDiagnostics(); - #endif - - CompilerInvocation::CreateFromArgs(TheCompInst->getInvocation(), argbegin, argend, TheCompInst->getDiagnostics()); - //need to recreate the diagnostics engine so that it actually listens to warning flags like -Wno-deprecated - //this cannot go before CreateFromArgs - #if LLVM_VERSION <= 32 +#endif + + CompilerInvocation::CreateFromArgs(TheCompInst->getInvocation(), argbegin, argend, + TheCompInst->getDiagnostics()); +// need to recreate the diagnostics engine so that it actually listens to warning flags +// like -Wno-deprecated this cannot go before CreateFromArgs +#if LLVM_VERSION <= 32 TheCompInst->createDiagnostics(argbegin - argend, argbegin); - TargetOptions & to = TheCompInst->getTargetOpts(); - #elif LLVM_VERSION <= 34 + TargetOptions &to = TheCompInst->getTargetOpts(); +#elif LLVM_VERSION <= 34 TheCompInst->createDiagnostics(); - TargetOptions * to = &TheCompInst->getTargetOpts(); - #else + TargetOptions *to = &TheCompInst->getTargetOpts(); +#else TheCompInst->createDiagnostics(); std::shared_ptr to(new TargetOptions(TheCompInst->getTargetOpts())); - #endif - +#endif + TargetInfo *TI = TargetInfo::CreateTargetInfo(TheCompInst->getDiagnostics(), to); TheCompInst->setTarget(TI); - + llvm::IntrusiveRefCntPtr FS = new LuaOverlayFileSystem(T->L); TheCompInst->setVirtualFileSystem(FS); TheCompInst->createFileManager(); @@ -782,191 +839,202 @@ static void initializeclang(terra_State * T, llvm::MemoryBuffer * membuffer, con TheCompInst->createSourceManager(FileMgr); SourceManager &SourceMgr = TheCompInst->getSourceManager(); TheCompInst->createPreprocessor( - #if LLVM_VERSION >= 35 - TU_Complete - #endif +#if LLVM_VERSION >= 35 + TU_Complete +#endif ); TheCompInst->createASTContext(); // Set the main file handled by the source manager to the input file. #if LLVM_VERSION <= 34 SourceMgr.createMainFileIDForMemBuffer(membuffer); -#else - SourceMgr.setMainFileID(SourceMgr.createFileID(UNIQUEIFY(llvm::MemoryBuffer,membuffer))); +#else + SourceMgr.setMainFileID( + SourceMgr.createFileID(UNIQUEIFY(llvm::MemoryBuffer, membuffer))); #endif - TheCompInst->getDiagnosticClient().BeginSourceFile(TheCompInst->getLangOpts(),&TheCompInst->getPreprocessor()); + TheCompInst->getDiagnosticClient().BeginSourceFile(TheCompInst->getLangOpts(), + &TheCompInst->getPreprocessor()); Preprocessor &PP = TheCompInst->getPreprocessor(); - #if LLVM_VERSION <= 37 - PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(), - PP.getLangOpts()); - #else - PP.getBuiltinInfo().initializeBuiltins(PP.getIdentifierTable(), - PP.getLangOpts()); - #endif +#if LLVM_VERSION <= 37 + PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(), PP.getLangOpts()); +#else + PP.getBuiltinInfo().initializeBuiltins(PP.getIdentifierTable(), PP.getLangOpts()); +#endif } #if LLVM_VERSION >= 33 -static void AddMacro(terra_State * T, Preprocessor & PP, const IdentifierInfo * II, MacroDirective * MD, Obj * table) { - if(!II->hasMacroDefinition()) - return; - MacroInfo * MI = MD->getMacroInfo(); - if(MI->isFunctionLike()) - return; +static void AddMacro(terra_State *T, Preprocessor &PP, const IdentifierInfo *II, + MacroDirective *MD, Obj *table) { + if (!II->hasMacroDefinition()) return; + MacroInfo *MI = MD->getMacroInfo(); + if (MI->isFunctionLike()) return; bool negate = false; - const Token * Tok; - if(MI->getNumTokens() == 2 && MI->getReplacementToken(0).is(clang::tok::minus)) { + const Token *Tok; + if (MI->getNumTokens() == 2 && MI->getReplacementToken(0).is(clang::tok::minus)) { negate = true; Tok = &MI->getReplacementToken(1); - } else if(MI->getNumTokens() == 1) { + } else if (MI->getNumTokens() == 1) { Tok = &MI->getReplacementToken(0); } else { return; } - - if(Tok->isNot(clang::tok::numeric_constant)) - return; - + + if (Tok->isNot(clang::tok::numeric_constant)) return; + SmallString<64> IntegerBuffer; bool NumberInvalid = false; StringRef Spelling = PP.getSpelling(*Tok, IntegerBuffer, &NumberInvalid); NumericLiteralParser Literal(Spelling, Tok->getLocation(), PP); - if(Literal.hadError) - return; + if (Literal.hadError) return; double V; - if(Literal.isFloatingLiteral()) { + if (Literal.isFloatingLiteral()) { llvm::APFloat Result(0.0); Literal.GetFloatValue(Result); V = Result.convertToDouble(); } else { - llvm::APInt Result(64,0); + llvm::APInt Result(64, 0); Literal.GetIntegerValue(Result); int64_t i = Result.getSExtValue(); - if((int64_t)(double)i != i) - return; //right now we ignore things that are not representable in Lua's number type - //eventually we should use LuaJITs ctype support to hold the larger numbers + if ((int64_t)(double)i != i) + return; // right now we ignore things that are not representable in Lua's + // number type eventually we should use LuaJITs ctype support to hold + // the larger numbers V = i; } - if(negate) - V = -V; - lua_pushnumber(T->L,V); + if (negate) V = -V; + lua_pushnumber(T->L, V); table->setfield(II->getName().str().c_str()); } #endif -static void optimizemodule(TerraTarget * TT, llvm::Module * M) { - //cleanup after clang. - //in some cases clang will mark stuff AvailableExternally (e.g. atoi on linux) - //the linker will then delete it because it is not used. - //switching it to WeakODR means that the linker will keep it even if it is not used - std::vector usedArray; - - for(llvm::Module::iterator it = M->begin(), end = M->end(); - it != end; - ++it) { - llvm::Function * fn = &*it; - if(fn->hasAvailableExternallyLinkage()) { +static void optimizemodule(TerraTarget *TT, llvm::Module *M) { + // cleanup after clang. + // in some cases clang will mark stuff AvailableExternally (e.g. atoi on linux) + // the linker will then delete it because it is not used. + // switching it to WeakODR means that the linker will keep it even if it is not used + std::vector usedArray; + + for (llvm::Module::iterator it = M->begin(), end = M->end(); it != end; ++it) { + llvm::Function *fn = &*it; + if (fn->hasAvailableExternallyLinkage()) { fn->setLinkage(llvm::GlobalValue::WeakODRLinkage); } - #ifdef _WIN32 // On windows, the optimizer will delete LinkOnce functions that are unused +#ifdef _WIN32 // On windows, the optimizer will delete LinkOnce functions that are unused usedArray.push_back(fn); - #endif - #if LLVM_VERSION >= 35 - if(fn->hasDLLImportStorageClass()) //clear dll import linkage because it messes up the jit on window +#endif +#if LLVM_VERSION >= 35 + if (fn->hasDLLImportStorageClass()) // clear dll import linkage because it messes + // up the jit on window fn->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass); - #else - if(fn->hasDLLImportLinkage()) //clear dll import linkage because it messes up the jit on window +#else + if (fn->hasDLLImportLinkage()) // clear dll import linkage because it messes up + // the jit on window fn->setLinkage(llvm::GlobalValue::ExternalLinkage); - #endif +#endif } - if(usedArray.size() > 0) { - auto* i8PtrType = llvm::Type::getInt8PtrTy(M->getContext()); - for(auto& elem : usedArray) - elem = llvm::ConstantExpr::getBitCast(elem, i8PtrType); + if (usedArray.size() > 0) { + auto *i8PtrType = llvm::Type::getInt8PtrTy(M->getContext()); + for (auto &elem : usedArray) + elem = llvm::ConstantExpr::getBitCast(elem, i8PtrType); - auto* arrayType = llvm::ArrayType::get(i8PtrType, usedArray.size()); - auto* llvmUsed = new llvm::GlobalVariable(*M, arrayType, false, llvm::GlobalValue::AppendingLinkage, - llvm::ConstantArray::get(arrayType, usedArray), "llvm.used"); - llvmUsed->setSection("llvm.metadata"); + auto *arrayType = llvm::ArrayType::get(i8PtrType, usedArray.size()); + auto *llvmUsed = new llvm::GlobalVariable( + *M, arrayType, false, llvm::GlobalValue::AppendingLinkage, + llvm::ConstantArray::get(arrayType, usedArray), "llvm.used"); + llvmUsed->setSection("llvm.metadata"); } - M->setTargetTriple(TT->Triple); //suppress warning that occur due to unmatched os versions + M->setTargetTriple( + TT->Triple); // suppress warning that occur due to unmatched os versions PassManager opt; llvmutil_addtargetspecificpasses(&opt, TT->tm); opt.add(llvm::createFunctionInliningPass()); llvmutil_addoptimizationpasses(&opt); opt.run(*M); } -static int dofile(terra_State * T, TerraTarget * TT, const char * code, const char ** argbegin, const char ** argend, Obj * result) { +static int dofile(terra_State *T, TerraTarget *TT, const char *code, + const char **argbegin, const char **argend, Obj *result) { // CompilerInstance will hold the instance of the Clang compiler for us, // managing the various objects needed to run the compiler. CompilerInstance TheCompInst; - - #if LLVM_VERSION >=36 - llvm::MemoryBuffer * membuffer = llvm::MemoryBuffer::getMemBuffer(code, "").release(); - #else - llvm::MemoryBuffer * membuffer = llvm::MemoryBuffer::getMemBuffer(code, ""); - #endif - - initializeclang(T,membuffer, argbegin, argend, &TheCompInst); - - #if LLVM_VERSION <= 32 - CodeGenerator * codegen = CreateLLVMCodeGen(TheCompInst.getDiagnostics(), "mymodule", TheCompInst.getCodeGenOpts(), *TT->ctx ); - #elif LLVM_VERSION <= 36 - CodeGenerator * codegen = CreateLLVMCodeGen(TheCompInst.getDiagnostics(), "mymodule", TheCompInst.getCodeGenOpts(), TheCompInst.getTargetOpts(), *TT->ctx ); - #else - CodeGenerator * codegen = CreateLLVMCodeGen(TheCompInst.getDiagnostics(), "mymodule", TheCompInst.getHeaderSearchOpts(), TheCompInst.getPreprocessorOpts(), TheCompInst.getCodeGenOpts(), *TT->ctx ); - #endif - + +#if LLVM_VERSION >= 36 + llvm::MemoryBuffer *membuffer = + llvm::MemoryBuffer::getMemBuffer(code, "").release(); +#else + llvm::MemoryBuffer *membuffer = llvm::MemoryBuffer::getMemBuffer(code, ""); +#endif + + initializeclang(T, membuffer, argbegin, argend, &TheCompInst); + +#if LLVM_VERSION <= 32 + CodeGenerator *codegen = CreateLLVMCodeGen(TheCompInst.getDiagnostics(), "mymodule", + TheCompInst.getCodeGenOpts(), *TT->ctx); +#elif LLVM_VERSION <= 36 + CodeGenerator *codegen = CreateLLVMCodeGen(TheCompInst.getDiagnostics(), "mymodule", + TheCompInst.getCodeGenOpts(), + TheCompInst.getTargetOpts(), *TT->ctx); +#else + CodeGenerator *codegen = CreateLLVMCodeGen( + TheCompInst.getDiagnostics(), "mymodule", TheCompInst.getHeaderSearchOpts(), + TheCompInst.getPreprocessorOpts(), TheCompInst.getCodeGenOpts(), *TT->ctx); +#endif + std::stringstream ss; ss << "__makeeverythinginclanglive_"; ss << TT->next_unused_id++; std::string livenessfunction = ss.str(); - #if LLVM_VERSION < 37 - //CodeGenProxy codegenproxy(codegen,result,livenessfunction); - TheCompInst.setASTConsumer(new CodeGenProxy(codegen,result,TT,livenessfunction)); - #else - TheCompInst.setASTConsumer(std::unique_ptr(new CodeGenProxy(codegen,result,TT,livenessfunction))); - #endif - - TheCompInst.createSema(clang::TU_Complete,NULL); - - ParseAST(TheCompInst.getSema(),false,false); - +#if LLVM_VERSION < 37 + // CodeGenProxy codegenproxy(codegen,result,livenessfunction); + TheCompInst.setASTConsumer(new CodeGenProxy(codegen, result, TT, livenessfunction)); +#else + TheCompInst.setASTConsumer(std::unique_ptr( + new CodeGenProxy(codegen, result, TT, livenessfunction))); +#endif + + TheCompInst.createSema(clang::TU_Complete, NULL); + + ParseAST(TheCompInst.getSema(), false, false); + Obj macros; CreateTableWithName(result, "macros", ¯os); - - #if LLVM_VERSION >= 33 - Preprocessor & PP = TheCompInst.getPreprocessor(); - //adjust PP so that it no longer reports errors, which could happen while trying to parse numbers here + +#if LLVM_VERSION >= 33 + Preprocessor &PP = TheCompInst.getPreprocessor(); + // adjust PP so that it no longer reports errors, which could happen while trying to + // parse numbers here PP.getDiagnostics().setClient(new IgnoringDiagConsumer(), true); - for(Preprocessor::macro_iterator it = PP.macro_begin(false),end = PP.macro_end(false); it != end; ++it) { - const IdentifierInfo * II = it->first; - #if LLVM_VERSION <= 36 - MacroDirective * MD = it->second; - #else - MacroDirective * MD = it->second.getLatest(); - #endif - AddMacro(T,PP,II,MD,¯os); + for (Preprocessor::macro_iterator it = PP.macro_begin(false), + end = PP.macro_end(false); + it != end; ++it) { + const IdentifierInfo *II = it->first; +#if LLVM_VERSION <= 36 + MacroDirective *MD = it->second; +#else + MacroDirective *MD = it->second.getLatest(); +#endif + AddMacro(T, PP, II, MD, ¯os); } - #endif - - llvm::Module * M = codegen->ReleaseModule(); +#endif + + llvm::Module *M = codegen->ReleaseModule(); delete codegen; - if(!M) { - terra_reporterror(T,"compilation of included c code failed\n"); + if (!M) { + terra_reporterror(T, "compilation of included c code failed\n"); } - optimizemodule(TT,M); + optimizemodule(TT, M); #if LLVM_VERSION < 39 - char * err; - if(LLVMLinkModules(llvm::wrap(TT->external), llvm::wrap(M), LLVMLinkerDestroySource, &err)) { - terra_pusherror(T, "linker reported error: %s",err); + char *err; + if (LLVMLinkModules(llvm::wrap(TT->external), llvm::wrap(M), LLVMLinkerDestroySource, + &err)) { + terra_pusherror(T, "linker reported error: %s", err); LLVMDisposeMessage(err); lua_error(T->L); } #else - if(LLVMLinkModules2(llvm::wrap(TT->external), llvm::wrap(M))) { + if (LLVMLinkModules2(llvm::wrap(TT->external), llvm::wrap(M))) { terra_pusherror(T, "linker reported error"); lua_error(T->L); } @@ -974,11 +1042,12 @@ static int dofile(terra_State * T, TerraTarget * TT, const char * code, const ch return 0; } -int include_c(lua_State * L) { - terra_State * T = terra_getstate(L, 1); (void) T; +int include_c(lua_State *L) { + terra_State *T = terra_getstate(L, 1); + (void)T; lua_getfield(L, TARGET_POS, "llvm_target"); - TerraTarget * TT = (TerraTarget*)terra_tocdatapointer(L,-1); - const char * code = luaL_checkstring(L, 2); + TerraTarget *TT = (TerraTarget *)terra_tocdatapointer(L, -1); + const char *code = luaL_checkstring(L, 2); int N = lua_objlen(L, 3); std::vector args; @@ -986,9 +1055,9 @@ int include_c(lua_State * L) { args.push_back(TT->Triple.c_str()); args.push_back("-target-cpu"); args.push_back(TT->CPU.c_str()); - if(!TT->Features.empty()) { - args.push_back("-target-feature"); - args.push_back(TT->Features.c_str()); + if (!TT->Features.empty()) { + args.push_back("-target-feature"); + args.push_back(TT->Features.c_str()); } #ifdef _WIN32 @@ -997,53 +1066,53 @@ int include_c(lua_State * L) { #define __stringify(x) #x #define __indirect(x) __stringify(x) args.push_back("-fms-compatibility-version=" __indirect(_MSC_VER)); - args.push_back("-Wno-ignored-attributes"); + args.push_back("-Wno-ignored-attributes"); #endif - const char ** cpaths = clang_paths; + const char **cpaths = clang_paths; // On windows, insert clang paths first, so that we include from the right version of VS. #ifdef _WIN32 - while(*cpaths) { + while (*cpaths) { args.push_back(*cpaths); cpaths++; } - for(int i = 0; i < N; i++) { - lua_rawgeti(L, 3, i+1); - args.push_back(luaL_checkstring(L,-1)); - lua_pop(L,1); + for (int i = 0; i < N; i++) { + lua_rawgeti(L, 3, i + 1); + args.push_back(luaL_checkstring(L, -1)); + lua_pop(L, 1); } #else - for(int i = 0; i < N; i++) { - lua_rawgeti(L, 3, i+1); - args.push_back(luaL_checkstring(L,-1)); - lua_pop(L,1); + for (int i = 0; i < N; i++) { + lua_rawgeti(L, 3, i + 1); + args.push_back(luaL_checkstring(L, -1)); + lua_pop(L, 1); } - while(*cpaths) { + while (*cpaths) { args.push_back(*cpaths); cpaths++; } #endif - lua_newtable(L); //return a table of loaded functions + lua_newtable(L); // return a table of loaded functions int ref_table = lobj_newreftable(L); { Obj result; lua_pushvalue(L, -2); result.initFromStack(L, ref_table); - - dofile(T,TT,code,&args[0],&args[args.size()],&result); + + dofile(T, TT, code, &args[0], &args[args.size()], &result); } - + lobj_removereftable(L, ref_table); return 1; } -void terra_cwrapperinit(terra_State * T) { - lua_getfield(T->L,LUA_GLOBALSINDEX,"terra"); - - lua_pushlightuserdata(T->L,(void*)T); - lua_pushcclosure(T->L,include_c,1); - lua_setfield(T->L,-2,"registercfile"); - - lua_pop(T->L,-1); //terra object +void terra_cwrapperinit(terra_State *T) { + lua_getfield(T->L, LUA_GLOBALSINDEX, "terra"); + + lua_pushlightuserdata(T->L, (void *)T); + lua_pushcclosure(T->L, include_c, 1); + lua_setfield(T->L, -2, "registercfile"); + + lua_pop(T->L, -1); // terra object } diff --git a/src/tcwrapper.h b/src/tcwrapper.h index def2b9bd4..614d2ad8c 100644 --- a/src/tcwrapper.h +++ b/src/tcwrapper.h @@ -2,6 +2,6 @@ #define t_cwrapper_h #include "terrastate.h" -void terra_cwrapperinit(terra_State * T); +void terra_cwrapperinit(terra_State* T); #endif \ No newline at end of file diff --git a/src/tdebug.cpp b/src/tdebug.cpp index 065b61f62..beb1f1fe7 100644 --- a/src/tdebug.cpp +++ b/src/tdebug.cpp @@ -19,7 +19,6 @@ #include #endif - using namespace llvm; #ifdef DEBUG_INFO_WORKING @@ -27,35 +26,42 @@ static bool pointisbeforeinstruction(uintptr_t point, uintptr_t inst, bool isNex return point < inst || (!isNextInst && point == inst); } #endif -static bool stacktrace_findline(terra_CompilerState * C, const TerraFunctionInfo * fi, uintptr_t ip, bool isNextInstr, StringRef * file, size_t * lineno) { - #ifdef DEBUG_INFO_WORKING - const std::vector & LineStarts = fi->efd.LineStarts; +static bool stacktrace_findline(terra_CompilerState *C, const TerraFunctionInfo *fi, + uintptr_t ip, bool isNextInstr, StringRef *file, + size_t *lineno) { +#ifdef DEBUG_INFO_WORKING + const std::vector &LineStarts = + fi->efd.LineStarts; size_t i; - for(i = 0; i + 1 < LineStarts.size() && pointisbeforeinstruction(LineStarts[i + 1].Address, ip, isNextInstr); i++) { - //printf("\nscanning for %p, %s:%d %p\n",(void*)ip,DIFile(LineStarts[i].Loc.getScope(*C->ctx)).getFilename().data(),(int)LineStarts[i].Loc.getLine(),(void*)LineStarts[i].Address); + for (i = 0; i + 1 < LineStarts.size() && + pointisbeforeinstruction(LineStarts[i + 1].Address, ip, isNextInstr); + i++) { + // printf("\nscanning for %p, %s:%d + // %p\n",(void*)ip,DIFile(LineStarts[i].Loc.getScope(*C->ctx)).getFilename().data(),(int)LineStarts[i].Loc.getLine(),(void*)LineStarts[i].Address); } - - if(i < LineStarts.size()) { - if(lineno) - *lineno = LineStarts[i].Loc.getLine(); - if(file) - *file = DIFile(LineStarts[i].Loc.getScope(*fi->ctx)).getFilename(); + + if (i < LineStarts.size()) { + if (lineno) *lineno = LineStarts[i].Loc.getLine(); + if (file) *file = DIFile(LineStarts[i].Loc.getScope(*fi->ctx)).getFilename(); return true; } else { return false; } - #else +#else return false; - #endif +#endif } -static bool stacktrace_findsymbol(terra_CompilerState * C, uintptr_t ip, const TerraFunctionInfo ** rfi) { - for(llvm::DenseMap::iterator it = C->functioninfo.begin(), end = C->functioninfo.end(); - it != end; ++it) { - const TerraFunctionInfo & fi = it->second; - uintptr_t fstart = (uintptr_t) fi.addr; +static bool stacktrace_findsymbol(terra_CompilerState *C, uintptr_t ip, + const TerraFunctionInfo **rfi) { + for (llvm::DenseMap::iterator + it = C->functioninfo.begin(), + end = C->functioninfo.end(); + it != end; ++it) { + const TerraFunctionInfo &fi = it->second; + uintptr_t fstart = (uintptr_t)fi.addr; uintptr_t fend = fstart + fi.size; - if(fstart <= ip && ip < fend) { + if (fstart <= ip && ip < fend) { *rfi = &fi; return true; } @@ -64,33 +70,34 @@ static bool stacktrace_findsymbol(terra_CompilerState * C, uintptr_t ip, const T } struct Frame { - Frame * next; - void * addr; + Frame *next; + void *addr; }; #ifndef _WIN32 __attribute__((noinline)) #else __declspec(noinline) #endif -static int terra_backtrace(void ** frames, int maxN, void * rip, void * rbp) { - if(maxN > 0) - frames[0] = rip; - Frame * frame = (Frame*) rbp; - if(!frame) return 1; +static int +terra_backtrace(void **frames, int maxN, void *rip, void *rbp) { + if (maxN > 0) frames[0] = rip; + Frame *frame = (Frame *)rbp; + if (!frame) return 1; int i; #ifndef _WIN32 int fds[2]; pipe(fds); #endif - //successful write to a pipe checks that we can read - //Frame's memory. Otherwise we might segfault if rbp holds junk. - for(i = 1; i < maxN && + // successful write to a pipe checks that we can read + // Frame's memory. Otherwise we might segfault if rbp holds junk. + for (i = 1; i < maxN && #ifndef _WIN32 - write(fds[1],frame,sizeof(Frame)) != -1 && + write(fds[1], frame, sizeof(Frame)) != -1 && #else - !IsBadReadPtr(frame, sizeof(Frame)) && + !IsBadReadPtr(frame, sizeof(Frame)) && #endif - frame->addr && frame->next; i++) { + frame->addr && frame->next; + i++) { frames[i] = frame->addr; frame = frame->next; } @@ -101,34 +108,34 @@ static int terra_backtrace(void ** frames, int maxN, void * rip, void * rbp) { return i; } -static void stacktrace_printsourceline(const char * filename, size_t lineno) { - FILE * file = fopen(filename,"r"); - if(!file) - return; +static void stacktrace_printsourceline(const char *filename, size_t lineno) { + FILE *file = fopen(filename, "r"); + if (!file) return; int c = fgetc(file); - for(size_t i = 1; i < lineno && c != EOF;) { - if(c == '\n') - i++; + for (size_t i = 1; i < lineno && c != EOF;) { + if (c == '\n') i++; c = fgetc(file); } printf(" "); - while(c != EOF && c != '\n') { - fputc(c,stdout); + while (c != EOF && c != '\n') { + fputc(c, stdout); c = fgetc(file); } - fputc('\n',stdout); + fputc('\n', stdout); fclose(file); } -static bool printfunctioninfo(terra_CompilerState * C, uintptr_t ip, bool isNextInst, int i) { - const TerraFunctionInfo * fi; - if(stacktrace_findsymbol(C,ip,&fi)) { - uintptr_t fstart = (uintptr_t) fi->addr; - printf("%-3d %-35s 0x%016" PRIxPTR " %s + %d ",i,"terra (JIT)",ip,fi->name.c_str(),(int)(ip - fstart)); +static bool printfunctioninfo(terra_CompilerState *C, uintptr_t ip, bool isNextInst, + int i) { + const TerraFunctionInfo *fi; + if (stacktrace_findsymbol(C, ip, &fi)) { + uintptr_t fstart = (uintptr_t)fi->addr; + printf("%-3d %-35s 0x%016" PRIxPTR " %s + %d ", i, "terra (JIT)", ip, + fi->name.c_str(), (int)(ip - fstart)); StringRef filename; size_t lineno; - if(stacktrace_findline(C, fi, ip,isNextInst, &filename, &lineno)) { - printf("(%s:%d)\n",filename.data(),(int)lineno); + if (stacktrace_findline(C, fi, ip, isNextInst, &filename, &lineno)) { + printf("(%s:%d)\n", filename.data(), (int)lineno); stacktrace_printsourceline(filename.data(), lineno); } else { printf("\n"); @@ -138,69 +145,72 @@ static bool printfunctioninfo(terra_CompilerState * C, uintptr_t ip, bool isNext return false; } -static void printstacktrace(void * uap, void * data) { - terra_CompilerState * C = (terra_CompilerState*) data; +static void printstacktrace(void *uap, void *data) { + terra_CompilerState *C = (terra_CompilerState *)data; const int maxN = 128; - void * frames[maxN]; - void * rip; - void * rbp; + void *frames[maxN]; + void *rip; + void *rbp; #ifndef _WIN32 - if(uap == NULL) { + if (uap == NULL) { rip = __builtin_return_address(0); rbp = __builtin_frame_address(1); } else { - ucontext_t * uc = (ucontext_t*) uap; + ucontext_t *uc = (ucontext_t *)uap; #ifdef __linux__ - rip = (void*) uc->uc_mcontext.gregs[REG_RIP]; - rbp = (void*) uc->uc_mcontext.gregs[REG_RBP]; + rip = (void *)uc->uc_mcontext.gregs[REG_RIP]; + rbp = (void *)uc->uc_mcontext.gregs[REG_RBP]; #else #ifdef __FreeBSD__ - rip = (void*)uc->uc_mcontext.mc_rip; - rbp = (void*)uc->uc_mcontext.mc_rbp; + rip = (void *)uc->uc_mcontext.mc_rip; + rbp = (void *)uc->uc_mcontext.mc_rbp; #else - rip = (void*)uc->uc_mcontext->__ss.__rip; - rbp = (void*)uc->uc_mcontext->__ss.__rbp; + rip = (void *)uc->uc_mcontext->__ss.__rip; + rbp = (void *)uc->uc_mcontext->__ss.__rbp; #endif #endif } #else - if (uap == NULL) { - CONTEXT cur_context; - RtlCaptureContext(&cur_context); - rbp = (void*)cur_context.Rbp; - rip = _ReturnAddress(); - } - else { - CONTEXT * context = (CONTEXT*)uap; - rip = (void*)context->Rip; - rbp = (void*)context->Rbp; - } + if (uap == NULL) { + CONTEXT cur_context; + RtlCaptureContext(&cur_context); + rbp = (void *)cur_context.Rbp; + rip = _ReturnAddress(); + } else { + CONTEXT *context = (CONTEXT *)uap; + rip = (void *)context->Rip; + rbp = (void *)context->Rbp; + } #endif - int N = terra_backtrace(frames, maxN,rip,rbp); + int N = terra_backtrace(frames, maxN, rip, rbp); #ifndef _WIN32 - char ** symbols = backtrace_symbols(frames, N); + char **symbols = backtrace_symbols(frames, N); #else - HANDLE process = GetCurrentProcess(); - SymInitialize(process, NULL, true); + HANDLE process = GetCurrentProcess(); + SymInitialize(process, NULL, true); #endif - for(int i = 0 ; i < N; i++) { - bool isNextInst = i > 0 || uap == NULL; //unless this is the first entry in suspended context then the address is really a pointer to the _next_ instruction - uintptr_t ip = (uintptr_t) frames[i]; - if(!printfunctioninfo(C, ip, isNextInst,i)) { + for (int i = 0; i < N; i++) { + bool isNextInst = + i > 0 || + uap == NULL; // unless this is the first entry in suspended context then + // the address is really a pointer to the _next_ instruction + uintptr_t ip = (uintptr_t)frames[i]; + if (!printfunctioninfo(C, ip, isNextInst, i)) { #ifndef _WIN32 - printf("%s\n",symbols[i]); + printf("%s\n", symbols[i]); #else - char buf[256 + sizeof(SYMBOL_INFO)]; - SYMBOL_INFO * symbol = (SYMBOL_INFO*)buf; - symbol->MaxNameLen = 255; - symbol->SizeOfStruct = sizeof(SYMBOL_INFO); - if (SymFromAddr(process, ip, 0, symbol)) - printf("%-3d %-35s 0x%016" PRIxPTR " %s + %d\n", i, "C", ip, symbol->Name, (int)(ip - (uintptr_t)symbol->Address)); - else - printf("%-3d %-35s 0x%016" PRIxPTR "\n", i, "unknown", ip); + char buf[256 + sizeof(SYMBOL_INFO)]; + SYMBOL_INFO *symbol = (SYMBOL_INFO *)buf; + symbol->MaxNameLen = 255; + symbol->SizeOfStruct = sizeof(SYMBOL_INFO); + if (SymFromAddr(process, ip, 0, symbol)) + printf("%-3d %-35s 0x%016" PRIxPTR " %s + %d\n", i, "C", ip, symbol->Name, + (int)(ip - (uintptr_t)symbol->Address)); + else + printf("%-3d %-35s 0x%016" PRIxPTR "\n", i, "unknown", ip); #endif } } @@ -210,93 +220,95 @@ static void printstacktrace(void * uap, void * data) { } struct SymbolInfo { - const void * addr; - size_t size; - const char * name; - size_t namelength; + const void *addr; + size_t size; + const char *name; + size_t namelength; }; -static bool terra_lookupsymbol(void * ip, SymbolInfo * r, terra_CompilerState * C) { - const TerraFunctionInfo * fi; - if(!stacktrace_findsymbol(C, (uintptr_t)ip, &fi)) - return false; +static bool terra_lookupsymbol(void *ip, SymbolInfo *r, terra_CompilerState *C) { + const TerraFunctionInfo *fi; + if (!stacktrace_findsymbol(C, (uintptr_t)ip, &fi)) return false; r->addr = fi->addr; - r->size = fi->size; - r->name = fi->name.c_str(); - r->namelength = fi->name.length(); - return true; + r->size = fi->size; + r->name = fi->name.c_str(); + r->namelength = fi->name.length(); + return true; } - struct LineInfo { - const char * name; - size_t namelength; - size_t linenum; + const char *name; + size_t namelength; + size_t linenum; }; -static bool terra_lookupline(void * fnaddr, void * ip, LineInfo * r ,terra_CompilerState * C) { - if(C->functioninfo.count(fnaddr) == 0) - return false; - const TerraFunctionInfo & fi = C->functioninfo[fnaddr]; +static bool terra_lookupline(void *fnaddr, void *ip, LineInfo *r, + terra_CompilerState *C) { + if (C->functioninfo.count(fnaddr) == 0) return false; + const TerraFunctionInfo &fi = C->functioninfo[fnaddr]; StringRef sr; - if(!stacktrace_findline(C, &fi, (uintptr_t)ip, false, &sr, &r->linenum)) + if (!stacktrace_findline(C, &fi, (uintptr_t)ip, false, &sr, &r->linenum)) return false; - r->name = sr.data(); - r->namelength = sr.size(); + r->name = sr.data(); + r->namelength = sr.size(); return true; } #define CLOSURE_MAX_SIZE 64 -static void * createclosure(uint8_t * buf, void * fn, int nargs, void ** env, int nenv) { +static void *createclosure(uint8_t *buf, void *fn, int nargs, void **env, int nenv) { assert(nargs <= 4); assert(*env); - uint8_t * code = buf; -#define ENCODE_MOV(reg,imm) do { \ - *code++ = 0x48 | ((reg) >> 3);\ - *code++ = 0xb8 | ((reg) & 7); \ - void * data = (imm); \ - memcpy(code,&data, 8); \ - code += 8; \ -} while(0); + uint8_t *code = buf; +#define ENCODE_MOV(reg, imm) \ + do { \ + *code++ = 0x48 | ((reg) >> 3); \ + *code++ = 0xb8 | ((reg)&7); \ + void *data = (imm); \ + memcpy(code, &data, 8); \ + code += 8; \ + } while (0); #ifndef _WIN32 - const uint8_t regnums[] = {7,6,2,1 /*,8,9*/}; + const uint8_t regnums[] = {7, 6, 2, 1 /*,8,9*/}; #else - const uint8_t regnums[] = {1,2,8,9}; + const uint8_t regnums[] = {1, 2, 8, 9}; #endif - ENCODE_MOV(0,fn); /* mov rax, fn */ - for(int i = nargs - nenv; i < nargs; i++) - ENCODE_MOV(regnums[i],*env++); + ENCODE_MOV(0, fn); /* mov rax, fn */ + for (int i = nargs - nenv; i < nargs; i++) ENCODE_MOV(regnums[i], *env++); *code++ = 0xff; /* jmp rax */ *code++ = 0xe0; - return (void*) buf; + return (void *)buf; #undef ENCODE_MOV } -int terra_debuginit(struct terra_State * T) { - +int terra_debuginit(struct terra_State *T) { std::error_code ec; - T->C->MB = llvm::sys::Memory::allocateMappedMemory(CLOSURE_MAX_SIZE*3, NULL, llvm::sys::Memory::MF_READ|llvm::sys::Memory::MF_WRITE|llvm::sys::Memory::MF_EXEC, ec); - - void * stacktracefn = createclosure((uint8_t*)T->C->MB.base(),(void*)printstacktrace,2,(void**)&T->C,1); - void * lookupsymbol = createclosure((uint8_t*)T->C->MB.base()+CLOSURE_MAX_SIZE,(void*)terra_lookupsymbol,3,(void**)&T->C,1); - void * lookupline = createclosure((uint8_t*)T->C->MB.base()+2*CLOSURE_MAX_SIZE,(void*)terra_lookupline,4,(void**)&T->C,1); - - lua_getfield(T->L,LUA_GLOBALSINDEX,"terra"); + T->C->MB = llvm::sys::Memory::allocateMappedMemory( + CLOSURE_MAX_SIZE * 3, NULL, + llvm::sys::Memory::MF_READ | llvm::sys::Memory::MF_WRITE | + llvm::sys::Memory::MF_EXEC, + ec); + + void *stacktracefn = createclosure((uint8_t *)T->C->MB.base(), + (void *)printstacktrace, 2, (void **)&T->C, 1); + void *lookupsymbol = createclosure((uint8_t *)T->C->MB.base() + CLOSURE_MAX_SIZE, + (void *)terra_lookupsymbol, 3, (void **)&T->C, 1); + void *lookupline = createclosure((uint8_t *)T->C->MB.base() + 2 * CLOSURE_MAX_SIZE, + (void *)terra_lookupline, 4, (void **)&T->C, 1); + + lua_getfield(T->L, LUA_GLOBALSINDEX, "terra"); lua_getfield(T->L, -1, "initdebugfns"); - lua_pushlightuserdata(T->L, (void*)stacktracefn); - lua_pushlightuserdata(T->L, (void*)terra_backtrace); - lua_pushlightuserdata(T->L, (void*)lookupsymbol); - lua_pushlightuserdata(T->L, (void*)lookupline); - lua_pushlightuserdata(T->L, (void*)llvmutil_disassemblefunction); + lua_pushlightuserdata(T->L, (void *)stacktracefn); + lua_pushlightuserdata(T->L, (void *)terra_backtrace); + lua_pushlightuserdata(T->L, (void *)lookupsymbol); + lua_pushlightuserdata(T->L, (void *)lookupline); + lua_pushlightuserdata(T->L, (void *)llvmutil_disassemblefunction); lua_call(T->L, 5, 0); - lua_pop(T->L,1); /* terra table */ - return 0; + lua_pop(T->L, 1); /* terra table */ + return 0; } #else /* it arm code just don't include debug interface for now */ -int terra_debuginit(struct terra_State * T) { - return 0; -} +int terra_debuginit(struct terra_State* T) { return 0; } #endif diff --git a/src/tdebug.h b/src/tdebug.h index 9a9b608db..446bd512e 100644 --- a/src/tdebug.h +++ b/src/tdebug.h @@ -2,8 +2,10 @@ #define _tdebug_h struct terra_State; -namespace llvm { class JITMemoryManager; } +namespace llvm { +class JITMemoryManager; +} -int terra_debuginit(struct terra_State * T); +int terra_debuginit(struct terra_State* T); #endif \ No newline at end of file diff --git a/src/terra.cpp b/src/terra.cpp index 34975e88e..79b2eb987 100644 --- a/src/terra.cpp +++ b/src/terra.cpp @@ -35,168 +35,169 @@ _COM_SMARTPTR_TYPEDEF(ISetupInstance, __uuidof(ISetupInstance)); _COM_SMARTPTR_TYPEDEF(ISetupInstance2, __uuidof(ISetupInstance2)); #endif -static char * vstringf(const char * fmt, va_list ap) { +static char *vstringf(const char *fmt, va_list ap) { int N = 128; - char * buf = (char*) malloc(N); - while(1) { + char *buf = (char *)malloc(N); + while (1) { va_list cp; - #ifdef _WIN32 +#ifdef _WIN32 cp = ap; - #else - va_copy(cp,ap); - #endif +#else + va_copy(cp, ap); +#endif int n = vsnprintf(buf, N, fmt, cp); - if(n > -1 && n < N) { + if (n > -1 && n < N) { return buf; } - if(n > -1) + if (n > -1) N = n + 1; else N *= 2; free(buf); - buf = (char*) malloc(N); + buf = (char *)malloc(N); } } -void terra_vpusherror(terra_State * T, const char * fmt, va_list ap) { - char * buf = vstringf(fmt,ap); +void terra_vpusherror(terra_State *T, const char *fmt, va_list ap) { + char *buf = vstringf(fmt, ap); lua_pushstring(T->L, buf); free(buf); } -void terra_pusherror(terra_State * T, const char * fmt, ...) { +void terra_pusherror(terra_State *T, const char *fmt, ...) { va_list ap; - va_start(ap,fmt); - terra_vpusherror(T,fmt,ap); + va_start(ap, fmt); + terra_vpusherror(T, fmt, ap); va_end(ap); } -void terra_reporterror(terra_State * T, const char * fmt, ...) { +void terra_reporterror(terra_State *T, const char *fmt, ...) { va_list ap; - va_start(ap,fmt); - terra_vpusherror(T,fmt,ap); + va_start(ap, fmt); + terra_vpusherror(T, fmt, ap); va_end(ap); lua_error(T->L); } -terra_State * terra_getstate(lua_State * L, int upvalue) { - terra_State * T = const_cast((const terra_State *) lua_topointer(L,lua_upvalueindex(upvalue))); +terra_State *terra_getstate(lua_State *L, int upvalue) { + terra_State *T = const_cast( + (const terra_State *)lua_topointer(L, lua_upvalueindex(upvalue))); assert(T); T->L = L; return T; } -static terra_State * getterra(lua_State * L) { - lua_getfield(L,LUA_GLOBALSINDEX,"terra"); - lua_getfield(L,-1,"__terrastate"); - terra_State * T = (terra_State *) lua_touserdata(L, -1); +static terra_State *getterra(lua_State *L) { + lua_getfield(L, LUA_GLOBALSINDEX, "terra"); + lua_getfield(L, -1, "__terrastate"); + terra_State *T = (terra_State *)lua_touserdata(L, -1); T->L = L; - lua_pop(L,2); + lua_pop(L, 2); return T; } -//implementations of lua functions load, loadfile, loadstring +// implementations of lua functions load, loadfile, loadstring static const char *reader_luaload(lua_State *L, void *ud, size_t *size) { size_t fnvalue = (size_t)ud; - lua_pushvalue(L,fnvalue); - lua_call(L,0,1); - if(lua_isnil(L,-1)) { - lua_pop(L,1); + lua_pushvalue(L, fnvalue); + lua_call(L, 0, 1); + if (lua_isnil(L, -1)) { + lua_pop(L, 1); return NULL; } - const char * str = lua_tolstring(L,-1,size); - lua_pop(L,1); + const char *str = lua_tolstring(L, -1, size); + lua_pop(L, 1); return str; } -int terra_luaload(lua_State * L) { - const char * chunkname = "=(load)"; +int terra_luaload(lua_State *L) { + const char *chunkname = "=(load)"; size_t fnvalue; - if(lua_gettop(L) == 2) { - chunkname = luaL_checkstring(L,-1); + if (lua_gettop(L) == 2) { + chunkname = luaL_checkstring(L, -1); fnvalue = lua_gettop(L) - 1; } else { fnvalue = lua_gettop(L); } - if(terra_load(L,reader_luaload,(void*)fnvalue,chunkname)) { + if (terra_load(L, reader_luaload, (void *)fnvalue, chunkname)) { lua_pushnil(L); - lua_pushvalue(L,-2); - lua_remove(L,-3); + lua_pushvalue(L, -2); + lua_remove(L, -3); return 2; } return 1; } -int terra_lualoadfile(lua_State * L) { - const char * file = NULL; - if(lua_gettop(L) > 0) - file = luaL_checkstring(L,-1); - if(terra_loadfile(L,file)) { +int terra_lualoadfile(lua_State *L) { + const char *file = NULL; + if (lua_gettop(L) > 0) file = luaL_checkstring(L, -1); + if (terra_loadfile(L, file)) { lua_pushnil(L); - lua_pushvalue(L,-2); - lua_remove(L,-3); + lua_pushvalue(L, -2); + lua_remove(L, -3); return 2; } return 1; } -int terra_lualoadstring(lua_State * L) { - const char * string = luaL_checkstring(L,-1); - if(terra_loadstring(L,string)) { +int terra_lualoadstring(lua_State *L) { + const char *string = luaL_checkstring(L, -1); + if (terra_loadstring(L, string)) { lua_pushnil(L); - lua_pushvalue(L,-2); - lua_remove(L,-3); + lua_pushvalue(L, -2); + lua_remove(L, -3); return 2; } return 1; } -//defines bytecodes for included lua source +// defines bytecodes for included lua source #include "terralib.h" #include "strict.h" #include "asdl.h" #include "terralist.h" -int terra_loadandrunbytecodes(lua_State * L, const unsigned char * bytecodes, size_t size, const char * name) { - return luaL_loadbuffer(L, (const char *)bytecodes, size, name) - || lua_pcall(L,0,LUA_MULTRET,0); +int terra_loadandrunbytecodes(lua_State *L, const unsigned char *bytecodes, size_t size, + const char *name) { + return luaL_loadbuffer(L, (const char *)bytecodes, size, name) || + lua_pcall(L, 0, LUA_MULTRET, 0); } #define abs_index(L, i) \ - ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : lua_gettop(L) + (i) + 1) - -void terra_ongc(lua_State * L, int idx, lua_CFunction gcfn) { - idx = abs_index(L,idx); + ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : lua_gettop(L) + (i) + 1) + +void terra_ongc(lua_State *L, int idx, lua_CFunction gcfn) { + idx = abs_index(L, idx); lua_newtable(L); lua_pushcfunction(L, gcfn); lua_setfield(L, -2, "__gc"); lua_setmetatable(L, idx); } -static int terra_free(lua_State * L); +static int terra_free(lua_State *L); #ifndef _WIN32 -static bool pushterrahome(lua_State * L) { +static bool pushterrahome(lua_State *L) { Dl_info info; - if (dladdr((void*)terra_init, &info) != 0) { + if (dladdr((void *)terra_init, &info) != 0) { #ifdef __linux__ Dl_info infomain; - void * lmain = dlsym(NULL,"main"); - if (dladdr(lmain,&infomain) != 0) { - if (infomain.dli_fbase == info.dli_fbase) { - //statically compiled on linux, we need to find the executable directly. - char exe_path[PATH_MAX]; - ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path)); - if(len > 0) { - lua_pushstring(L, dirname(dirname(exe_path))); - return true; + void *lmain = dlsym(NULL, "main"); + if (dladdr(lmain, &infomain) != 0) { + if (infomain.dli_fbase == info.dli_fbase) { + // statically compiled on linux, we need to find the executable directly. + char exe_path[PATH_MAX]; + ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path)); + if (len > 0) { + lua_pushstring(L, dirname(dirname(exe_path))); + return true; + } } } - } #endif - if (info.dli_fname) { - char * full = realpath(info.dli_fname, NULL); - lua_pushstring(L, dirname(dirname(full))); //TODO: dirname not reentrant + if (info.dli_fname) { + char *full = realpath(info.dli_fname, NULL); + lua_pushstring(L, dirname(dirname(full))); // TODO: dirname not reentrant free(full); return true; } @@ -205,8 +206,8 @@ static bool pushterrahome(lua_State * L) { } #else -static bool pushterrahome(lua_State * L) { - //based on approach that clang uses as well +static bool pushterrahome(lua_State *L) { + // based on approach that clang uses as well MEMORY_BASIC_INFORMATION mbi; char path[MAX_PATH]; VirtualQuery((void *)terra_init, &mbi, sizeof(mbi)); @@ -217,234 +218,219 @@ static bool pushterrahome(lua_State * L) { return true; } -// On windows, gets the value of a given registry key in HKEY_LOCAL_MACHINE, or returns nil otherwise. -static int query_reg_value(lua_State* L) -{ - if(lua_gettop(L) != 2) - lua_pushnil(L); - else - { - auto key = luaL_checkstring(L, 1); - auto value = luaL_checkstring(L, 2); - - HKEY pkey; - if(!key || !value || RegOpenKeyExA(HKEY_LOCAL_MACHINE, key, 0, KEY_QUERY_VALUE | KEY_WOW64_32KEY | KEY_ENUMERATE_SUB_KEYS, &pkey) != S_OK) - lua_pushnil(L); - else - { - DWORD type = 0; - DWORD sz = 0; - LSTATUS r = RegQueryValueExA(pkey, value, 0, &type, 0, &sz); - if(r != S_OK) +// On windows, gets the value of a given registry key in HKEY_LOCAL_MACHINE, or returns +// nil otherwise. +static int query_reg_value(lua_State *L) { + if (lua_gettop(L) != 2) lua_pushnil(L); - else - { - BYTE* data = (BYTE*)malloc(sz + 1); - r = RegQueryValueExA(pkey, value, 0, &type, data, &sz); - data[sz] = 0; - if(!data || r != S_OK) - lua_pushnil(L); - else - { - switch(type) - { - case REG_BINARY: - lua_pushlstring(L, (const char*)data, sz); - break; - case REG_DWORD: - lua_pushinteger(L, *(int32_t*)data); - break; - case REG_QWORD: - lua_pushinteger(L, *(int64_t*)data); // This doesn't really work but we attempt it anyway - break; - case REG_EXPAND_SZ: { - sz = ExpandEnvironmentStringsA((const char*)data, 0, 0); - char* buf = (char*)malloc(sz); - ExpandEnvironmentStringsA((const char*)data, buf, sz); - lua_pushstring(L, (const char*)buf); - free(buf); - } break; - case REG_MULTI_SZ: - case REG_SZ: - lua_pushstring(L, (const char*)data); - break; - } - } - if(data) - free(data); - } + else { + auto key = luaL_checkstring(L, 1); + auto value = luaL_checkstring(L, 2); + + HKEY pkey; + if (!key || !value || + RegOpenKeyExA(HKEY_LOCAL_MACHINE, key, 0, + KEY_QUERY_VALUE | KEY_WOW64_32KEY | KEY_ENUMERATE_SUB_KEYS, + &pkey) != S_OK) + lua_pushnil(L); + else { + DWORD type = 0; + DWORD sz = 0; + LSTATUS r = RegQueryValueExA(pkey, value, 0, &type, 0, &sz); + if (r != S_OK) + lua_pushnil(L); + else { + BYTE *data = (BYTE *)malloc(sz + 1); + r = RegQueryValueExA(pkey, value, 0, &type, data, &sz); + data[sz] = 0; + if (!data || r != S_OK) + lua_pushnil(L); + else { + switch (type) { + case REG_BINARY: + lua_pushlstring(L, (const char *)data, sz); + break; + case REG_DWORD: + lua_pushinteger(L, *(int32_t *)data); + break; + case REG_QWORD: + lua_pushinteger( + L, *(int64_t *)data); // This doesn't really work but + // we attempt it anyway + break; + case REG_EXPAND_SZ: { + sz = ExpandEnvironmentStringsA((const char *)data, 0, 0); + char *buf = (char *)malloc(sz); + ExpandEnvironmentStringsA((const char *)data, buf, sz); + lua_pushstring(L, (const char *)buf); + free(buf); + } break; + case REG_MULTI_SZ: + case REG_SZ: + lua_pushstring(L, (const char *)data); + break; + } + } + if (data) free(data); + } - RegCloseKey(pkey); + RegCloseKey(pkey); + } } - } - return 1; + return 1; } -struct InitializeCOMRAII -{ - InitializeCOMRAII() { ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); } - ~InitializeCOMRAII() { ::CoUninitialize(); } +struct InitializeCOMRAII { + InitializeCOMRAII() { ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); } + ~InitializeCOMRAII() { ::CoUninitialize(); } }; // Based on clang's MSVC.cpp file -static bool findVCToolChainViaSetupConfig(lua_State* L) -{ - InitializeCOMRAII com; - HRESULT HR; - - ISetupConfigurationPtr Query; - HR = Query.CreateInstance(__uuidof(SetupConfiguration)); - if(FAILED(HR)) - return false; - - IEnumSetupInstancesPtr EnumInstances; - HR = ISetupConfiguration2Ptr(Query)->EnumAllInstances(&EnumInstances); - if(FAILED(HR)) - return false; - - ISetupInstancePtr Instance; - HR = EnumInstances->Next(1, &Instance, nullptr); - if(HR != S_OK) - return false; - - ISetupInstancePtr NewestInstance; - uint64_t NewestVersionNum = 0; - do - { - bstr_t VersionString; - uint64_t VersionNum; - HR = Instance->GetInstallationVersion(VersionString.GetAddress()); - if(FAILED(HR)) - continue; - HR = ISetupHelperPtr(Query)->ParseVersion(VersionString, &VersionNum); - if(FAILED(HR)) - continue; - if(!NewestVersionNum || (VersionNum > NewestVersionNum)) - { - NewestInstance = Instance; - NewestVersionNum = VersionNum; - } - } while((HR = EnumInstances->Next(1, &Instance, nullptr)) == S_OK); - - if(!NewestInstance) - return false; - - bstr_t VCPathWide; - HR = NewestInstance->ResolvePath(L"VC", VCPathWide.GetAddress()); - if(FAILED(HR)) - return false; - - std::wstring ToolsVersionFilePath(VCPathWide); - ToolsVersionFilePath += L"\\Auxiliary\\Build\\Microsoft.VCToolsVersion.default.txt"; - - FILE* f = nullptr; - auto open_result = _wfopen_s(&f, ToolsVersionFilePath.c_str(), L"rt"); - if(open_result != 0 || !f) - return false; - fseek(f, 0, SEEK_END); - size_t tools_file_size = ftell(f); - fseek(f, 0, SEEK_SET); - std::string version; - version.resize(tools_file_size); - auto retval = fgets((char*)version.data(), version.size(), f); - fclose(f); - - if(!retval) - return false; - - while(!version.back()) // strip trailing null terminators so whitespace removal works - version.pop_back(); - version.erase(version.find_last_not_of(" \n\r\t\v") + 1); - - std::string ToolchainPath; - ToolchainPath.resize(WideCharToMultiByte(CP_UTF8, 0, VCPathWide, VCPathWide.length(), 0, 0, NULL, NULL)); - ToolchainPath.resize(WideCharToMultiByte(CP_UTF8, 0, VCPathWide, VCPathWide.length(), (char*)ToolchainPath.data(), ToolchainPath.capacity(), NULL, NULL)); - ToolchainPath += "\\Tools\\MSVC\\"; - ToolchainPath += version; - lua_pushstring(L, ToolchainPath.c_str()); - return true; +static bool findVCToolChainViaSetupConfig(lua_State *L) { + InitializeCOMRAII com; + HRESULT HR; + + ISetupConfigurationPtr Query; + HR = Query.CreateInstance(__uuidof(SetupConfiguration)); + if (FAILED(HR)) return false; + + IEnumSetupInstancesPtr EnumInstances; + HR = ISetupConfiguration2Ptr(Query)->EnumAllInstances(&EnumInstances); + if (FAILED(HR)) return false; + + ISetupInstancePtr Instance; + HR = EnumInstances->Next(1, &Instance, nullptr); + if (HR != S_OK) return false; + + ISetupInstancePtr NewestInstance; + uint64_t NewestVersionNum = 0; + do { + bstr_t VersionString; + uint64_t VersionNum; + HR = Instance->GetInstallationVersion(VersionString.GetAddress()); + if (FAILED(HR)) continue; + HR = ISetupHelperPtr(Query)->ParseVersion(VersionString, &VersionNum); + if (FAILED(HR)) continue; + if (!NewestVersionNum || (VersionNum > NewestVersionNum)) { + NewestInstance = Instance; + NewestVersionNum = VersionNum; + } + } while ((HR = EnumInstances->Next(1, &Instance, nullptr)) == S_OK); + + if (!NewestInstance) return false; + + bstr_t VCPathWide; + HR = NewestInstance->ResolvePath(L"VC", VCPathWide.GetAddress()); + if (FAILED(HR)) return false; + + std::wstring ToolsVersionFilePath(VCPathWide); + ToolsVersionFilePath += L"\\Auxiliary\\Build\\Microsoft.VCToolsVersion.default.txt"; + + FILE *f = nullptr; + auto open_result = _wfopen_s(&f, ToolsVersionFilePath.c_str(), L"rt"); + if (open_result != 0 || !f) return false; + fseek(f, 0, SEEK_END); + size_t tools_file_size = ftell(f); + fseek(f, 0, SEEK_SET); + std::string version; + version.resize(tools_file_size); + auto retval = fgets((char *)version.data(), version.size(), f); + fclose(f); + + if (!retval) return false; + + while (!version.back()) // strip trailing null terminators so whitespace removal + // works + version.pop_back(); + version.erase(version.find_last_not_of(" \n\r\t\v") + 1); + + std::string ToolchainPath; + ToolchainPath.resize(WideCharToMultiByte(CP_UTF8, 0, VCPathWide, VCPathWide.length(), + 0, 0, NULL, NULL)); + ToolchainPath.resize(WideCharToMultiByte(CP_UTF8, 0, VCPathWide, VCPathWide.length(), + (char *)ToolchainPath.data(), + ToolchainPath.capacity(), NULL, NULL)); + ToolchainPath += "\\Tools\\MSVC\\"; + ToolchainPath += version; + lua_pushstring(L, ToolchainPath.c_str()); + return true; } -static int find_visual_studio_toolchain(lua_State* L) -{ - if(!findVCToolChainViaSetupConfig(L)) - lua_pushnil(L); - return 1; +static int find_visual_studio_toolchain(lua_State *L) { + if (!findVCToolChainViaSetupConfig(L)) lua_pushnil(L); + return 1; } -static int list_subdirectories(lua_State* L) -{ - if(lua_gettop(L) != 1) - lua_pushnil(L); - else - { - std::string path = luaL_checkstring(L, 1); - if(path.back() != '\\') - path += '\\'; - path += '*'; - - WIN32_FIND_DATAA find_data; - auto handle = FindFirstFileA(path.c_str(), &find_data); - if(handle == INVALID_HANDLE_VALUE) - lua_pushnil(L); - else - { - lua_newtable(L); - int i = 0; - BOOL success = TRUE; - while(success) - { - if((find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (find_data.cFileName[0] != '.')) - { - lua_pushnumber(L, ++i); // Make sure we start at 1 - lua_pushstring(L, find_data.cFileName); - lua_settable(L, -3); - } - - success = FindNextFileA(handle, &find_data); - } +static int list_subdirectories(lua_State *L) { + if (lua_gettop(L) != 1) + lua_pushnil(L); + else { + std::string path = luaL_checkstring(L, 1); + if (path.back() != '\\') path += '\\'; + path += '*'; + + WIN32_FIND_DATAA find_data; + auto handle = FindFirstFileA(path.c_str(), &find_data); + if (handle == INVALID_HANDLE_VALUE) + lua_pushnil(L); + else { + lua_newtable(L); + int i = 0; + BOOL success = TRUE; + while (success) { + if ((find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && + (find_data.cFileName[0] != '.')) { + lua_pushnumber(L, ++i); // Make sure we start at 1 + lua_pushstring(L, find_data.cFileName); + lua_settable(L, -3); + } + + success = FindNextFileA(handle, &find_data); + } - FindClose(handle); + FindClose(handle); + } } - } - return 1; + return 1; } #endif -static void setterrahome(lua_State * L) { +static void setterrahome(lua_State *L) { lua_getfield(L, LUA_GLOBALSINDEX, "terra"); - if (pushterrahome(L)) - lua_setfield(L, -2, "terrahome"); + if (pushterrahome(L)) lua_setfield(L, -2, "terrahome"); lua_pop(L, 1); } -int terra_init(lua_State * L) { +int terra_init(lua_State *L) { terra_Options options; - memset(&options,0, sizeof(terra_Options)); + memset(&options, 0, sizeof(terra_Options)); return terra_initwithoptions(L, &options); } -int terra_initwithoptions(lua_State * L, terra_Options * options) { - terra_State * T = (terra_State*) lua_newuserdata(L, sizeof(terra_State)); +int terra_initwithoptions(lua_State *L, terra_Options *options) { + terra_State *T = (terra_State *)lua_newuserdata(L, sizeof(terra_State)); terra_ongc(L, -1, terra_free); assert(T); - memset(T,0,sizeof(terra_State)); //some of lua stuff expects pointers to be null on entry + memset(T, 0, sizeof(terra_State)); // some of lua stuff expects pointers to be null + // on entry T->options = *options; #ifdef __arm__ - T->options.usemcjit = true; //force MCJIT since old JIT is partially broken on ARM + T->options.usemcjit = true; // force MCJIT since old JIT is partially broken on ARM #endif T->numlivefunctions = 1; T->L = L; - assert (T->L); + assert(T->L); lua_newtable(T->L); lua_insert(L, -2); - lua_setfield(L, -2, "__terrastate"); //reference to our T object, so that we can load it from the lua state on other API calls - - lua_setfield(T->L,LUA_GLOBALSINDEX,"terra"); //create global terra object - terra_kindsinit(T); //initialize lua mapping from T_Kind to/from string - setterrahome(T->L); //find the location of support files such as the clang resource directory - + lua_setfield(L, -2, "__terrastate"); // reference to our T object, so that we can + // load it from the lua state on other API calls + + lua_setfield(T->L, LUA_GLOBALSINDEX, "terra"); // create global terra object + terra_kindsinit(T); // initialize lua mapping from T_Kind to/from string + setterrahome(T->L); // find the location of support files such as the clang resource + // directory + int err = terra_compilerinit(T); - if(err) { + if (err) { return err; } @@ -457,176 +443,171 @@ int terra_initwithoptions(lua_State * L, terra_Options * options) { lua_setfield(T->L, -2, "findvisualstudiotoolchain"); lua_pushcfunction(T->L, list_subdirectories); lua_setfield(T->L, -2, "listsubdirectories"); - lua_pop(T->L, 1); //'terra' global + lua_pop(T->L, 1); //'terra' global #endif - err = terra_loadandrunbytecodes(T->L,(const unsigned char*)luaJIT_BC_strict,luaJIT_BC_strict_SIZE, "strict.lua") - || terra_loadandrunbytecodes(T->L,(const unsigned char*)luaJIT_BC_terralist,luaJIT_BC_terralist_SIZE, "terralist.lua") - || terra_loadandrunbytecodes(T->L,(const unsigned char*)luaJIT_BC_asdl,luaJIT_BC_asdl_SIZE, "asdl.lua") + err = terra_loadandrunbytecodes(T->L, (const unsigned char *)luaJIT_BC_strict, + luaJIT_BC_strict_SIZE, "strict.lua") || + terra_loadandrunbytecodes(T->L, (const unsigned char *)luaJIT_BC_terralist, + luaJIT_BC_terralist_SIZE, "terralist.lua") || + terra_loadandrunbytecodes(T->L, (const unsigned char *)luaJIT_BC_asdl, + luaJIT_BC_asdl_SIZE, "asdl.lua") #ifndef TERRA_EXTERNAL_TERRALIB - || terra_loadandrunbytecodes(T->L,(const unsigned char*)luaJIT_BC_terralib,luaJIT_BC_terralib_SIZE, "terralib.lua"); + || terra_loadandrunbytecodes(T->L, (const unsigned char *)luaJIT_BC_terralib, + luaJIT_BC_terralib_SIZE, "terralib.lua"); #else // make it possible to quickly iterate in terralib.lua when developing - || luaL_loadfile(T->L,TERRA_EXTERNAL_TERRALIB) - || lua_pcall(L,0,LUA_MULTRET,0); + || luaL_loadfile(T->L, TERRA_EXTERNAL_TERRALIB) || + lua_pcall(L, 0, LUA_MULTRET, 0); #endif - if(err) { + if (err) { return err; } - + terra_cwrapperinit(T); - - lua_getfield(T->L,LUA_GLOBALSINDEX,"terra"); - - lua_pushcfunction(T->L,terra_luaload); - lua_setfield(T->L,-2,"load"); - lua_pushcfunction(T->L,terra_lualoadstring); - lua_setfield(T->L,-2,"loadstring"); - lua_pushcfunction(T->L,terra_lualoadfile); - lua_setfield(T->L,-2,"loadfile"); - - lua_pushstring(T->L,TERRA_VERSION_STRING); - lua_setfield(T->L,-2,"version"); + + lua_getfield(T->L, LUA_GLOBALSINDEX, "terra"); + + lua_pushcfunction(T->L, terra_luaload); + lua_setfield(T->L, -2, "load"); + lua_pushcfunction(T->L, terra_lualoadstring); + lua_setfield(T->L, -2, "loadstring"); + lua_pushcfunction(T->L, terra_lualoadfile); + lua_setfield(T->L, -2, "loadfile"); + + lua_pushstring(T->L, TERRA_VERSION_STRING); + lua_setfield(T->L, -2, "version"); lua_newtable(T->L); - lua_setfield(T->L,-2,"_trees"); //to hold parser generated trees - + lua_setfield(T->L, -2, "_trees"); // to hold parser generated trees + lua_pushinteger(L, T->options.verbose); lua_setfield(L, -2, "isverbose"); lua_pushinteger(L, T->options.debug); lua_setfield(L, -2, "isdebug"); - - terra_registerinternalizedfiles(L,-1); - lua_pop(T->L,1); //'terra' global - + + terra_registerinternalizedfiles(L, -1); + lua_pop(T->L, 1); //'terra' global + luaX_init(T); terra_debuginit(T); err = terra_cudainit(T); /* if cuda is not enabled, this does nothing */ - if(err) { + if (err) { return err; } - return 0; + return 0; } -//Called when the lua state object is free'd during lua_close -static int terra_free(lua_State * L) { - terra_State * T = (terra_State *) lua_touserdata(L, -1); +// Called when the lua state object is free'd during lua_close +static int terra_free(lua_State *L) { + terra_State *T = (terra_State *)lua_touserdata(L, -1); assert(T); terra_cudafree(T); terra_compilerfree(T->C); - for (TerraTarget * TT : T->targets) { + for (TerraTarget *TT : T->targets) { freetarget(TT); } return 0; } struct FileInfo { - FILE * file; + FILE *file; char buf[512]; }; -int terra_load(lua_State *L,lua_Reader reader, void *data, const char *chunkname) { +int terra_load(lua_State *L, lua_Reader reader, void *data, const char *chunkname) { int st = lua_gettop(L); - terra_State * T = getterra(L); + terra_State *T = getterra(L); Zio zio; - luaZ_init(T,&zio,reader,data); - int r = luaY_parser(T,&zio,chunkname,zgetc(&zio)); + luaZ_init(T, &zio, reader, data); + int r = luaY_parser(T, &zio, chunkname, zgetc(&zio)); assert(lua_gettop(L) == st + 1); return r; } - -//these helper functions are from the LuaJIT implementation for loadfile and loadstring: +// these helper functions are from the LuaJIT implementation for loadfile and loadstring: #define TERRA_BUFFERSIZE 512 typedef struct FileReaderCtx { - FILE *fp; - char buf[TERRA_BUFFERSIZE]; + FILE *fp; + char buf[TERRA_BUFFERSIZE]; } FileReaderCtx; -static const char *reader_file(lua_State *L, void *ud, size_t *size) -{ - FileReaderCtx *ctx = (FileReaderCtx *)ud; - if (feof(ctx->fp)) return NULL; - *size = fread(ctx->buf, 1, sizeof(ctx->buf), ctx->fp); - return *size > 0 ? ctx->buf : NULL; +static const char *reader_file(lua_State *L, void *ud, size_t *size) { + FileReaderCtx *ctx = (FileReaderCtx *)ud; + if (feof(ctx->fp)) return NULL; + *size = fread(ctx->buf, 1, sizeof(ctx->buf), ctx->fp); + return *size > 0 ? ctx->buf : NULL; } typedef struct StringReaderCtx { - const char *str; - size_t size; + const char *str; + size_t size; } StringReaderCtx; -static const char *reader_string(lua_State *L, void *ud, size_t *size) -{ - StringReaderCtx *ctx = (StringReaderCtx *)ud; - if (ctx->size == 0) return NULL; - *size = ctx->size; - ctx->size = 0; - return ctx->str; +static const char *reader_string(lua_State *L, void *ud, size_t *size) { + StringReaderCtx *ctx = (StringReaderCtx *)ud; + if (ctx->size == 0) return NULL; + *size = ctx->size; + ctx->size = 0; + return ctx->str; } -//end helper functions +// end helper functions -int terra_loadfile(lua_State * L, const char * file) { +int terra_loadfile(lua_State *L, const char *file) { FileReaderCtx ctx; - ctx.fp = file ? fopen(file,"r") : stdin; - if(!ctx.fp) { - terra_State * T = getterra(L); - terra_pusherror(T,"failed to open file '%s'",file); - return LUA_ERRFILE; + ctx.fp = file ? fopen(file, "r") : stdin; + if (!ctx.fp) { + terra_State *T = getterra(L); + terra_pusherror(T, "failed to open file '%s'", file); + return LUA_ERRFILE; } - /*peek to see if we have a POSIX comment '#', which we repect on the first like for #! */ + /*peek to see if we have a POSIX comment '#', which we repect on the first like for #! + */ int c = fgetc(ctx.fp); - ungetc(c,ctx.fp); - if(c == '#') { /* skip the POSIX comment */ + ungetc(c, ctx.fp); + if (c == '#') { /* skip the POSIX comment */ do { - c = fgetc(ctx.fp); - } while(c != '\n' && c != EOF); - if(c == '\n') - ungetc(c,ctx.fp); /* keep line count accurate */ + c = fgetc(ctx.fp); + } while (c != '\n' && c != EOF); + if (c == '\n') ungetc(c, ctx.fp); /* keep line count accurate */ } - if(file) { - char * name = (char *) malloc(strlen(file) + 2); - sprintf(name,"@%s",file); - int r = terra_load(L,reader_file,&ctx,name); + if (file) { + char *name = (char *)malloc(strlen(file) + 2); + sprintf(name, "@%s", file); + int r = terra_load(L, reader_file, &ctx, name); free(name); fclose(ctx.fp); return r; } else { - return terra_load(L,reader_file,&ctx,"@=stdin"); + return terra_load(L, reader_file, &ctx, "@=stdin"); } } -int terra_loadbuffer(lua_State * L, const char *buf, size_t size, const char *name) { +int terra_loadbuffer(lua_State *L, const char *buf, size_t size, const char *name) { StringReaderCtx ctx; ctx.str = buf; ctx.size = size; - return terra_load(L,reader_string,&ctx,name); + return terra_load(L, reader_string, &ctx, name); } int terra_loadstring(lua_State *L, const char *s) { - return terra_loadbuffer(L, s, strlen(s), ""); + return terra_loadbuffer(L, s, strlen(s), ""); } namespace llvm { - void llvm_shutdown(); +void llvm_shutdown(); } -void terra_llvmshutdown() { - llvm::llvm_shutdown(); -} -//for require -extern "C" int luaopen_terra(lua_State * L) { +void terra_llvmshutdown() { llvm::llvm_shutdown(); } +// for require +extern "C" int luaopen_terra(lua_State *L) { terra_Options options; - memset(&options,0, sizeof(terra_Options)); - if(!lua_isnil(L,1)) - options.verbose = lua_tonumber(L,1); - if(!lua_isnil(L,2)) - options.debug = lua_tonumber(L,2); - if(!lua_isnil(L,3)) - options.usemcjit = lua_tonumber(L,3); - if(terra_initwithoptions(L,&options)) - lua_error(L); + memset(&options, 0, sizeof(terra_Options)); + if (!lua_isnil(L, 1)) options.verbose = lua_tonumber(L, 1); + if (!lua_isnil(L, 2)) options.debug = lua_tonumber(L, 2); + if (!lua_isnil(L, 3)) options.usemcjit = lua_tonumber(L, 3); + if (terra_initwithoptions(L, &options)) lua_error(L); return 0; } diff --git a/src/terrastate.h b/src/terrastate.h index 85f987ad7..2464f31e5 100644 --- a/src/terrastate.h +++ b/src/terrastate.h @@ -13,33 +13,36 @@ struct terra_CUDAState; struct TerraTarget; typedef struct terra_State { - struct lua_State * L; - struct terra_CompilerState * C; - struct terra_CUDAState * cuda; + struct lua_State *L; + struct terra_CompilerState *C; + struct terra_CUDAState *cuda; terra_Options options; std::vector targets; -//for parser + // for parser int nCcalls; - char tstring_table; //&tstring_table is used as the key into the lua registry that maps strings in Lua to TString objects for the parser - size_t numlivefunctions; //number of terra functions that are live in the system, + 1 if terra_free has not been called - //used to track when it is safe to delete the terra_State object. + char tstring_table; //&tstring_table is used as the key into the lua registry that + //maps strings in Lua to TString objects for the parser + size_t numlivefunctions; // number of terra functions that are live in the system, + + // 1 if terra_free has not been called used to track when it + // is safe to delete the terra_State object. } terra_State; -//call this whenevern terra code is running within a lua call. -//this will be like calling 'error' from lua, and return the installed handler -void terra_reporterror(terra_State * T, const char * fmt, ...); - -//call this when terra code is running outside of lua (e.g. in terra_init, or terra_dofile) -//it will push the error message to the lua stack -//the call is then responsibly for propagating the error to the caller of the terra function -void terra_pusherror(terra_State * T, const char * fmt, ...); -void terra_vpusherror(terra_State * T, const char * fmt, va_list ap); -int terra_loadandrunbytecodes(lua_State * L, const unsigned char * bytecodes, size_t size, const char * name); -terra_State * terra_getstate(lua_State * L, int closureindex); -#define VERBOSE_ONLY(T) if((T)->options.verbose != 0) -#define DEBUG_ONLY(T) if((T)->options.debug != 0) - -//definition in tclanginternalizedheaders.cpp -void terra_registerinternalizedfiles(lua_State * L, int terratable); +// call this whenevern terra code is running within a lua call. +// this will be like calling 'error' from lua, and return the installed handler +void terra_reporterror(terra_State *T, const char *fmt, ...); + +// call this when terra code is running outside of lua (e.g. in terra_init, or +// terra_dofile) it will push the error message to the lua stack the call is then +// responsibly for propagating the error to the caller of the terra function +void terra_pusherror(terra_State *T, const char *fmt, ...); +void terra_vpusherror(terra_State *T, const char *fmt, va_list ap); +int terra_loadandrunbytecodes(lua_State *L, const unsigned char *bytecodes, size_t size, + const char *name); +terra_State *terra_getstate(lua_State *L, int closureindex); +#define VERBOSE_ONLY(T) if ((T)->options.verbose != 0) +#define DEBUG_ONLY(T) if ((T)->options.debug != 0) + +// definition in tclanginternalizedheaders.cpp +void terra_registerinternalizedfiles(lua_State *L, int terratable); #endif diff --git a/src/tinline.cpp b/src/tinline.cpp index 446890ab5..d27b637ca 100644 --- a/src/tinline.cpp +++ b/src/tinline.cpp @@ -1,7 +1,7 @@ #ifdef TERRA_LLVM_HEADERS_HAVE_NDEBUG -//somewhere in LLVM's header files they define an object differently -//if NDEBUG is on, causing CallGraph functions to crash. -//we compile this file with a matching NDEBUG setting to get around this +// somewhere in LLVM's header files they define an object differently +// if NDEBUG is on, causing CallGraph functions to crash. +// we compile this file with a matching NDEBUG setting to get around this #define NDEBUG #endif #include "llvmheaders.h" @@ -9,85 +9,87 @@ using namespace llvm; -ManualInliner::ManualInliner(TargetMachine * TM, Module * m) { - //Trick the Module-at-a-time inliner into running on a single SCC - //First we run it on the (currently empty) module to initialize - //the inlining pass with the Analysis passes it needs. - #if LLVM_VERSION <= 35 - DataLayout * TD = new DataLayout(*TM->getDataLayout()); - #endif - - #if LLVM_VERSION <= 34 +ManualInliner::ManualInliner(TargetMachine *TM, Module *m) { +// Trick the Module-at-a-time inliner into running on a single SCC +// First we run it on the (currently empty) module to initialize +// the inlining pass with the Analysis passes it needs. +#if LLVM_VERSION <= 35 + DataLayout *TD = new DataLayout(*TM->getDataLayout()); +#endif + +#if LLVM_VERSION <= 34 PM.add(TD); - #elif LLVM_VERSION <= 35 +#elif LLVM_VERSION <= 35 PM.add(new DataLayoutPass(*TD)); - #elif LLVM_VERSION <= 36 +#elif LLVM_VERSION <= 36 PM.add(new DataLayoutPass()); - #else +#else PM.add(createTargetTransformInfoWrapperPass(TM->getTargetIRAnalysis())); - #endif - - #if LLVM_VERSION >= 33 && LLVM_VERSION <= 36 +#endif + +#if LLVM_VERSION >= 33 && LLVM_VERSION <= 36 TM->addAnalysisPasses(PM); - #endif - SI = (CallGraphSCCPass*) createFunctionInliningPass(); +#endif + SI = (CallGraphSCCPass *)createFunctionInliningPass(); PM.add(SI); PM.run(*m); - //save the call graph so we can keep it up to date - #if LLVM_VERSION <= 34 +// save the call graph so we can keep it up to date +#if LLVM_VERSION <= 34 CG = &SI->getAnalysis(); - #else - CallGraphWrapperPass & CGW = SI->getAnalysis(); - CGW.runOnModule(*m); //force it to realloc the CG +#else + CallGraphWrapperPass &CGW = SI->getAnalysis(); + CGW.runOnModule(*m); // force it to realloc the CG CG = &CGW.getCallGraph(); assert(CG); - #endif +#endif } -//Inliner handles erasing functions since it also maintains a copy of the callgraph -//that needs to be kept up to date with the functions in the module -void ManualInliner::eraseFunction(Function * F) { - CallGraphNode * n = CG->getOrInsertFunction(F); +// Inliner handles erasing functions since it also maintains a copy of the callgraph +// that needs to be kept up to date with the functions in the module +void ManualInliner::eraseFunction(Function *F) { + CallGraphNode *n = CG->getOrInsertFunction(F); n->removeAllCalledFunctions(); CG->removeFunctionFromModule(n); delete F; } -void ManualInliner::run(std::vector::iterator fbegin, std::vector::iterator fend) { - std::vector nodes; - //the inliner requires an up to date callgraph, so we add the functions in the SCC - //to the callgraph. If needed, we can do this during function creation to make it faster - for(std::vector::iterator fp = fbegin; fp != fend; ++fp){ - Function * F = *fp; - CallGraphNode * n = CG->getOrInsertFunction(F); +void ManualInliner::run(std::vector::iterator fbegin, + std::vector::iterator fend) { + std::vector nodes; + // the inliner requires an up to date callgraph, so we add the functions in the SCC + // to the callgraph. If needed, we can do this during function creation to make it + // faster + for (std::vector::iterator fp = fbegin; fp != fend; ++fp) { + Function *F = *fp; + CallGraphNode *n = CG->getOrInsertFunction(F); for (Function::iterator BB = F->begin(), BBE = F->end(); BB != BBE; ++BB) - for (BasicBlock::iterator II = BB->begin(), IE = BB->end(); II != IE; ++II) { - CallSite CS(cast(II)); - if (CS) { - const Function *Callee = CS.getCalledFunction(); - if (Callee && !Callee->isIntrinsic()) { - CallGraphNode * n2 = CG->getOrInsertFunction(Callee); - n->addCalledFunction(CS,n2); - } + for (BasicBlock::iterator II = BB->begin(), IE = BB->end(); II != IE; ++II) { + CallSite CS(cast(II)); + if (CS) { + const Function *Callee = CS.getCalledFunction(); + if (Callee && !Callee->isIntrinsic()) { + CallGraphNode *n2 = CG->getOrInsertFunction(Callee); + n->addCalledFunction(CS, n2); + } + } } - } nodes.push_back(n); } - //create a fake SCC node and manually run the inliner pass on it. + // create a fake SCC node and manually run the inliner pass on it. #if LLVM_VERSION < 39 CallGraphSCC SCC(NULL); #else - CallGraphSCC SCC(*CG,NULL); + CallGraphSCC SCC(*CG, NULL); #endif #if LLVM_VERSION >= 50 SCC.initialize(ArrayRef(nodes)); #else - SCC.initialize(&nodes[0], &nodes[0]+nodes.size()); + SCC.initialize(&nodes[0], &nodes[0] + nodes.size()); #endif SI->runOnSCC(SCC); - //We optimize the function now, which will invalidate the call graph, - //removing called functions makes sure that further inlining passes don't attempt to add invalid callsites as inlining candidates - for(std::vector::iterator fp = fbegin; fp != fend; ++fp){ + // We optimize the function now, which will invalidate the call graph, + // removing called functions makes sure that further inlining passes don't attempt to + // add invalid callsites as inlining candidates + for (std::vector::iterator fp = fbegin; fp != fend; ++fp) { CG->getOrInsertFunction(*fp)->removeAllCalledFunctions(); } - } diff --git a/src/tinline.h b/src/tinline.h index 66c434a6a..89c736db2 100644 --- a/src/tinline.h +++ b/src/tinline.h @@ -4,13 +4,15 @@ #include "llvmheaders.h" class ManualInliner { - llvm::CallGraphSCCPass * SI; - llvm::CallGraph * CG; + llvm::CallGraphSCCPass *SI; + llvm::CallGraph *CG; PassManager PM; + public: - ManualInliner(llvm::TargetMachine * tm, llvm::Module * m); - void run(std::vector::iterator fbegin, std::vector::iterator fend); - void eraseFunction(llvm::Function * f); + ManualInliner(llvm::TargetMachine *tm, llvm::Module *m); + void run(std::vector::iterator fbegin, + std::vector::iterator fend); + void eraseFunction(llvm::Function *f); }; #endif diff --git a/src/tinternalizedfiles.cpp b/src/tinternalizedfiles.cpp index 6e558ad70..198270da6 100644 --- a/src/tinternalizedfiles.cpp +++ b/src/tinternalizedfiles.cpp @@ -1,12 +1,12 @@ -//auto-generate files that defines the data for the internalized headers +// auto-generate files that defines the data for the internalized headers #include "stdint.h" #include "internalizedfiles.h" #include "terra.h" -void terra_registerinternalizedfiles(lua_State * L, int terratable) { - lua_getfield(L,terratable,"registerinternalizedfiles"); - lua_pushlightuserdata(L,&headerfile_names[0]); - lua_pushlightuserdata(L,&headerfile_contents[0]); - lua_pushlightuserdata(L,&headerfile_sizes[0]); - lua_call(L,3,0); +void terra_registerinternalizedfiles(lua_State* L, int terratable) { + lua_getfield(L, terratable, "registerinternalizedfiles"); + lua_pushlightuserdata(L, &headerfile_names[0]); + lua_pushlightuserdata(L, &headerfile_contents[0]); + lua_pushlightuserdata(L, &headerfile_sizes[0]); + lua_call(L, 3, 0); } \ No newline at end of file diff --git a/src/tkind.cpp b/src/tkind.cpp index 9b204011a..b5f94dae5 100644 --- a/src/tkind.cpp +++ b/src/tkind.cpp @@ -6,24 +6,22 @@ extern "C" { #include "lua.h" } -static const char * kindtostr[] = { -#define T_KIND_STRING(a,str) str, - T_KIND_LIST(T_KIND_STRING) - NULL -}; -const char * tkindtostr(T_Kind k) { +static const char* kindtostr[] = { +#define T_KIND_STRING(a, str) str, + T_KIND_LIST(T_KIND_STRING) NULL}; +const char* tkindtostr(T_Kind k) { assert(k < T_NUM_KINDS); return kindtostr[k]; } -void terra_kindsinit(terra_State * T) { - lua_State * L = T->L; - lua_getfield(L,LUA_GLOBALSINDEX,"terra"); +void terra_kindsinit(terra_State* T) { + lua_State* L = T->L; + lua_getfield(L, LUA_GLOBALSINDEX, "terra"); lua_newtable(L); - for(int i = 0; i < T_NUM_KINDS; i++) { - lua_pushnumber(L,i); - lua_setfield(L,-2,tkindtostr((T_Kind) i)); + for (int i = 0; i < T_NUM_KINDS; i++) { + lua_pushnumber(L, i); + lua_setfield(L, -2, tkindtostr((T_Kind)i)); } - lua_setfield(L,-2,"kinds"); - lua_pop(L,1); //terra object + lua_setfield(L, -2, "kinds"); + lua_pop(L, 1); // terra object } \ No newline at end of file diff --git a/src/tkind.h b/src/tkind.h index b534d2896..0f823872a 100644 --- a/src/tkind.h +++ b/src/tkind.h @@ -2,84 +2,83 @@ #define t_kind_h struct terra_State; -//a list of strings that the C++ code in tcompiler.cpp needs to examine for code emission -//a table terra.kinds maps these strings to enum values that are defined here. +// a list of strings that the C++ code in tcompiler.cpp needs to examine for code emission +// a table terra.kinds maps these strings to enum values that are defined here. -#define T_KIND_LIST(_) \ -_(add, "+") \ -_(addressof,"&") \ -_(allocvar, "allocvar") \ -_(and,"and") \ -_(apply,"apply") \ -_(array, "array") \ -_(arrayconstructor,"arrayconstructor") \ -_(assignment,"assignment") \ -_(attrload,"attrload") \ -_(attrstore,"attrstore") \ -_(block,"block") \ -_(breakstat,"breakstat") \ -_(cast,"cast") \ -_(constant,"constant") \ -_(constructor,"constructor") \ -_(debuginfo,"debuginfo") \ -_(defer, "defer") \ -_(dereference,"@") \ -_(div, "/") \ -_(eq,"==") \ -_(float,"float") \ -_(fornum,"fornum") \ -_(functype,"functype") \ -_(ge,">=") \ -_(globalvalueref, "globalvalueref") \ -_(gotostat,"gotostat") \ -_(gt,">") \ -_(ifstat,"ifstat") \ -_(index,"index") \ -_(inlineasm,"inlineasm") \ -_(integer,"integer") \ -_(label,"label") \ -_(le,"<=") \ -_(letin,"letin") \ -_(literal,"literal") \ -_(logical,"logical") \ -_(lshift, "<<") \ -_(lt,"<") \ -_(mod, "%") \ -_(mul, "*") \ -_(ne,"~=") \ -_(niltype, "niltype") \ -_(not,"not") \ -_(opaque, "opaque") \ -_(operator,"operator") \ -_(or, "or") \ -_(pointer,"pointer") \ -_(pow, "^") \ -_(primitive,"primitive") \ -_(repeatstat,"repeatstat") \ -_(returnstat,"returnstat") \ -_(rshift, ">>") \ -_(select,"select") \ -_(setter,"setter") \ -_(sizeof, "sizeof") \ -_(struct, "struct") \ -_(structcast, "structcast") \ -_(sub, "-") \ -_(var,"var") \ -_(vector, "vector") \ -_(vectorconstructor,"vectorconstructor") \ -_(whilestat,"whilestat") \ -_(globalvariable,"globalvariable") \ -_(terrafunction,"terrafunction") \ -_(functiondef, "functiondef") \ -_(functionextern, "functionextern") +#define T_KIND_LIST(_) \ + _(add, "+") \ + _(addressof, "&") \ + _(allocvar, "allocvar") \ + _(and, "and") \ + _(apply, "apply") \ + _(array, "array") \ + _(arrayconstructor, "arrayconstructor") \ + _(assignment, "assignment") \ + _(attrload, "attrload") \ + _(attrstore, "attrstore") \ + _(block, "block") \ + _(breakstat, "breakstat") \ + _(cast, "cast") \ + _(constant, "constant") \ + _(constructor, "constructor") \ + _(debuginfo, "debuginfo") \ + _(defer, "defer") \ + _(dereference, "@") \ + _(div, "/") \ + _(eq, "==") \ + _(float, "float") \ + _(fornum, "fornum") \ + _(functype, "functype") \ + _(ge, ">=") \ + _(globalvalueref, "globalvalueref") \ + _(gotostat, "gotostat") \ + _(gt, ">") \ + _(ifstat, "ifstat") \ + _(index, "index") \ + _(inlineasm, "inlineasm") \ + _(integer, "integer") \ + _(label, "label") \ + _(le, "<=") \ + _(letin, "letin") \ + _(literal, "literal") \ + _(logical, "logical") \ + _(lshift, "<<") \ + _(lt, "<") \ + _(mod, "%") \ + _(mul, "*") \ + _(ne, "~=") \ + _(niltype, "niltype") \ + _(not, "not") \ + _(opaque, "opaque") \ + _(operator, "operator") \ + _(or, "or") \ + _(pointer, "pointer") \ + _(pow, "^") \ + _(primitive, "primitive") \ + _(repeatstat, "repeatstat") \ + _(returnstat, "returnstat") \ + _(rshift, ">>") \ + _(select, "select") \ + _(setter, "setter") \ + _(sizeof, "sizeof") \ + _(struct, "struct") \ + _(structcast, "structcast") \ + _(sub, "-") \ + _(var, "var") \ + _(vector, "vector") \ + _(vectorconstructor, "vectorconstructor") \ + _(whilestat, "whilestat") \ + _(globalvariable, "globalvariable") \ + _(terrafunction, "terrafunction") \ + _(functiondef, "functiondef") \ + _(functionextern, "functionextern") enum T_Kind { - #define T_KIND_ENUM(a,str) T_##a, - T_KIND_LIST(T_KIND_ENUM) - T_NUM_KINDS +#define T_KIND_ENUM(a, str) T_##a, + T_KIND_LIST(T_KIND_ENUM) T_NUM_KINDS }; -const char * tkindtostr(T_Kind k); -void terra_kindsinit(terra_State * T); +const char* tkindtostr(T_Kind k); +void terra_kindsinit(terra_State* T); #endif \ No newline at end of file diff --git a/src/tllvmutil.cpp b/src/tllvmutil.cpp index beb7c6f4b..4723811e5 100644 --- a/src/tllvmutil.cpp +++ b/src/tllvmutil.cpp @@ -32,17 +32,17 @@ using namespace llvm; -void llvmutil_addtargetspecificpasses(PassManagerBase * fpm, TargetMachine * TM) { +void llvmutil_addtargetspecificpasses(PassManagerBase *fpm, TargetMachine *TM) { assert(TM && fpm); #if LLVM_VERSION >= 37 TargetLibraryInfoImpl TLII(TM->getTargetTriple()); fpm->add(new TargetLibraryInfoWrapperPass(TLII)); #else - TargetLibraryInfo * TLI = new TargetLibraryInfo(Triple(TM->getTargetTriple())); + TargetLibraryInfo *TLI = new TargetLibraryInfo(Triple(TM->getTargetTriple())); fpm->add(TLI); #endif #if LLVM_VERSION <= 35 - DataLayout * TD = new DataLayout(*TM->getDataLayout()); + DataLayout *TD = new DataLayout(*TM->getDataLayout()); #endif #if LLVM_VERSION <= 34 fpm->add(TD); @@ -53,7 +53,7 @@ void llvmutil_addtargetspecificpasses(PassManagerBase * fpm, TargetMachine * TM) #else fpm->add(createTargetTransformInfoWrapperPass(TM->getTargetIRAnalysis())); #endif - + #if LLVM_VERSION == 32 fpm->add(new TargetTransformInfo(TM->getScalarTargetTransformInfo(), TM->getVectorTargetTransformInfo())); @@ -64,14 +64,15 @@ void llvmutil_addtargetspecificpasses(PassManagerBase * fpm, TargetMachine * TM) class PassManagerWrapper : public PassManagerBase { public: - PassManagerBase * PM; - PassManagerWrapper(PassManagerBase * PM_) : PM(PM_) {} + PassManagerBase *PM; + PassManagerWrapper(PassManagerBase *PM_) : PM(PM_) {} virtual void add(Pass *P) { - if(P->getPotentialPassManagerType() > PMT_CallGraphPassManager || P->getAsImmutablePass() != NULL) + if (P->getPotentialPassManagerType() > PMT_CallGraphPassManager || + P->getAsImmutablePass() != NULL) PM->add(P); } }; -void llvmutil_addoptimizationpasses(PassManagerBase * fpm) { +void llvmutil_addoptimizationpasses(PassManagerBase *fpm) { PassManagerBuilder PMB; PMB.OptLevel = 3; PMB.SizeLevel = 0; @@ -89,23 +90,23 @@ void llvmutil_addoptimizationpasses(PassManagerBase * fpm) { #if LLVM_VERSION < 50 struct SimpleMemoryObject : public MemoryObject { - uint64_t getBase() const { return 0; } - uint64_t getExtent() const { return ~0ULL; } - int readByte(uint64_t Addr, uint8_t *Byte) const { - *Byte = *(uint8_t*)Addr; - return 0; - } + uint64_t getBase() const { return 0; } + uint64_t getExtent() const { return ~0ULL; } + int readByte(uint64_t Addr, uint8_t *Byte) const { + *Byte = *(uint8_t *)Addr; + return 0; + } }; #endif -void llvmutil_disassemblefunction(void * data, size_t numBytes, size_t numInst) { +void llvmutil_disassemblefunction(void *data, size_t numBytes, size_t numInst) { InitializeNativeTargetDisassembler(); std::string Error; #if LLVM_VERSION >= 33 std::string TripleName = llvm::sys::getProcessTriple(); #else std::string TripleName = llvm::sys::getDefaultTargetTriple(); -#endif +#endif std::string CPU = llvm::sys::getHostCPUName(); const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error); @@ -122,13 +123,13 @@ void llvmutil_disassemblefunction(void * data, size_t numBytes, size_t numInst) assert(MRI && "Unable to create target register info!"); std::string FeaturesStr; - const MCSubtargetInfo *STI = TheTarget->createMCSubtargetInfo(TripleName, CPU, - FeaturesStr); + const MCSubtargetInfo *STI = + TheTarget->createMCSubtargetInfo(TripleName, CPU, FeaturesStr); assert(STI && "Unable to create subtarget info!"); #if LLVM_VERSION >= 35 - MCContext Ctx(MAI,MRI, NULL); - MCDisassembler *DisAsm = TheTarget->createMCDisassembler(*STI,Ctx); + MCContext Ctx(MAI, MRI, NULL); + MCDisassembler *DisAsm = TheTarget->createMCDisassembler(*STI, Ctx); #else MCDisassembler *DisAsm = TheTarget->createMCDisassembler(*STI); #endif @@ -136,74 +137,84 @@ void llvmutil_disassemblefunction(void * data, size_t numBytes, size_t numInst) int AsmPrinterVariant = MAI->getAssemblerDialect(); MCInstPrinter *IP = TheTarget->createMCInstPrinter( - #if LLVM_VERSION >= 37 - Triple(TripleName), - #endif - AsmPrinterVariant, - *MAI, *MII, *MRI - #if LLVM_VERSION <= 36 - , *STI - #endif - ); +#if LLVM_VERSION >= 37 + Triple(TripleName), +#endif + AsmPrinterVariant, *MAI, *MII, *MRI +#if LLVM_VERSION <= 36 + , + *STI +#endif + ); assert(IP && "Unable to create instruction printer!"); - #if LLVM_VERSION < 36 +#if LLVM_VERSION < 36 SimpleMemoryObject SMO; - #else - ArrayRef Bytes((uint8_t*)data,numBytes); - #endif - +#else + ArrayRef Bytes((uint8_t *)data, numBytes); +#endif + uint64_t addr = (uint64_t)data; uint64_t Size; fflush(stdout); raw_fd_ostream Out(fileno(stdout), false); - for(size_t i = 0, b = 0; b < numBytes || i < numInst; i++, b += Size) { + for (size_t i = 0, b = 0; b < numBytes || i < numInst; i++, b += Size) { MCInst Inst; - #if LLVM_VERSION >= 36 - MCDisassembler::DecodeStatus S = DisAsm->getInstruction(Inst, Size, Bytes.slice(b),addr + b, nulls(), Out); - #else - MCDisassembler::DecodeStatus S = DisAsm->getInstruction(Inst, Size, SMO,addr + b, nulls(), Out); - #endif - if(MCDisassembler::Fail == S || MCDisassembler::SoftFail == S) - break; - Out << (void*) ((uintptr_t)data + b) << "(+" << b << ")" << ":\t"; - IP->printInst(&Inst,Out,"" - #if LLVM_VERSION >= 37 - , *STI - #endif +#if LLVM_VERSION >= 36 + MCDisassembler::DecodeStatus S = DisAsm->getInstruction( + Inst, Size, Bytes.slice(b), addr + b, nulls(), Out); +#else + MCDisassembler::DecodeStatus S = + DisAsm->getInstruction(Inst, Size, SMO, addr + b, nulls(), Out); +#endif + if (MCDisassembler::Fail == S || MCDisassembler::SoftFail == S) break; + Out << (void *)((uintptr_t)data + b) << "(+" << b << ")" + << ":\t"; + IP->printInst(&Inst, Out, "" +#if LLVM_VERSION >= 37 + , + *STI +#endif ); Out << "\n"; } Out.flush(); - delete MAI; delete MRI; delete STI; delete MII; delete DisAsm; delete IP; + delete MAI; + delete MRI; + delete STI; + delete MII; + delete DisAsm; + delete IP; } -//adapted from LLVM's C interface "LLVMTargetMachineEmitToFile" -bool llvmutil_emitobjfile(Module * Mod, TargetMachine * TM, bool outputobjectfile, emitobjfile_t & dest) { - +// adapted from LLVM's C interface "LLVMTargetMachineEmitToFile" +bool llvmutil_emitobjfile(Module *Mod, TargetMachine *TM, bool outputobjectfile, + emitobjfile_t &dest) { PassManagerT pass; llvmutil_addtargetspecificpasses(&pass, TM); - - TargetMachine::CodeGenFileType ft = outputobjectfile? TargetMachine::CGFT_ObjectFile : TargetMachine::CGFT_AssemblyFile; - - #if LLVM_VERSION <= 36 + + TargetMachine::CodeGenFileType ft = outputobjectfile + ? TargetMachine::CGFT_ObjectFile + : TargetMachine::CGFT_AssemblyFile; + +#if LLVM_VERSION <= 36 formatted_raw_ostream destf(dest); - #else - emitobjfile_t & destf = dest; - #endif +#else + emitobjfile_t &destf = dest; +#endif - #if LLVM_VERSION >= 70 +#if LLVM_VERSION >= 70 if (TM->addPassesToEmitFile(pass, destf, nullptr, ft)) { return true; } - #else +#else if (TM->addPassesToEmitFile(pass, destf, ft)) { return true; } - #endif +#endif pass.run(*Mod); - + destf.flush(); dest.flush(); @@ -213,118 +224,131 @@ bool llvmutil_emitobjfile(Module * Mod, TargetMachine * TM, bool outputobjectfil #if LLVM_VERSION >= 34 struct CopyConnectedComponent : public ValueMaterializer { - Module * dest; - Module * src; + Module *dest; + Module *src; llvmutil_Property copyGlobal; - void * data; - ValueToValueMapTy & VMap; - - CopyConnectedComponent(Module * dest_, Module * src_, llvmutil_Property copyGlobal_, void * data_, ValueToValueMapTy & VMap_) - : dest(dest_), src(src_), copyGlobal(copyGlobal_), data(data_), VMap(VMap_) {} - bool needsFreshlyNamedConstant(GlobalVariable * GV, GlobalVariable * newGV) { - if(GV->isConstant() && GV->hasPrivateLinkage() && + void *data; + ValueToValueMapTy &VMap; + + CopyConnectedComponent(Module *dest_, Module *src_, llvmutil_Property copyGlobal_, + void *data_, ValueToValueMapTy &VMap_) + : dest(dest_), src(src_), copyGlobal(copyGlobal_), data(data_), VMap(VMap_) {} + bool needsFreshlyNamedConstant(GlobalVariable *GV, GlobalVariable *newGV) { + if (GV->isConstant() && GV->hasPrivateLinkage() && #if LLVM_VERSION < 39 - GV->hasUnnamedAddr() + GV->hasUnnamedAddr() #else - GV->hasAtLeastLocalUnnamedAddr() + GV->hasAtLeastLocalUnnamedAddr() #endif - ) { //this is a candidate constant - return !newGV->isConstant() || newGV->getInitializer() != GV->getInitializer(); //it is not equal to its target + ) { // this is a candidate constant + return !newGV->isConstant() || + newGV->getInitializer() != + GV->getInitializer(); // it is not equal to its target } return false; } - #if LLVM_VERSION == 38 - virtual Value * materializeDeclFor(Value * V) { - #elif LLVM_VERSION < 38 - virtual Value * materializeValueFor(Value * V) { - #else - virtual Value * materialize(Value * V) { - #endif - if(Function * fn = dyn_cast(V)) { +#if LLVM_VERSION == 38 + virtual Value *materializeDeclFor(Value *V) { +#elif LLVM_VERSION < 38 + virtual Value *materializeValueFor(Value *V) { +#else + virtual Value *materialize(Value *V) { +#endif + if (Function *fn = dyn_cast(V)) { assert(fn->getParent() == src); - Function * newfn = dest->getFunction(fn->getName()); - if(!newfn) { - newfn = Function::Create(fn->getFunctionType(),fn->getLinkage(), fn->getName(),dest); + Function *newfn = dest->getFunction(fn->getName()); + if (!newfn) { + newfn = Function::Create(fn->getFunctionType(), fn->getLinkage(), + fn->getName(), dest); newfn->copyAttributesFrom(fn); } - if(!fn->isDeclaration() && newfn->isDeclaration() && copyGlobal(fn,data)) { - for(Function::arg_iterator II = newfn->arg_begin(), I = fn->arg_begin(), E = fn->arg_end(); I != E; ++I, ++II) { + if (!fn->isDeclaration() && newfn->isDeclaration() && copyGlobal(fn, data)) { + for (Function::arg_iterator II = newfn->arg_begin(), I = fn->arg_begin(), + E = fn->arg_end(); + I != E; ++I, ++II) { II->setName(I->getName()); VMap[&*I] = &*II; } VMap[fn] = newfn; - SmallVector Returns; + SmallVector Returns; CloneFunctionInto(newfn, fn, VMap, true, Returns, "", NULL, NULL, this); - }else{ + } else { newfn->setLinkage(GlobalValue::ExternalLinkage); } return newfn; - } else if(GlobalVariable * GV = dyn_cast(V)) { - GlobalVariable * newGV = dest->getGlobalVariable(GV->getName(),true); - if(!newGV || needsFreshlyNamedConstant(GV,newGV)) { - newGV = new GlobalVariable(*dest,GV->getType()->getElementType(),GV->isConstant(),GV->getLinkage(),NULL,GV->getName(),NULL,GlobalVariable::NotThreadLocal,GV->getType()->getAddressSpace()); + } else if (GlobalVariable *GV = dyn_cast(V)) { + GlobalVariable *newGV = dest->getGlobalVariable(GV->getName(), true); + if (!newGV || needsFreshlyNamedConstant(GV, newGV)) { + newGV = new GlobalVariable( + *dest, GV->getType()->getElementType(), GV->isConstant(), + GV->getLinkage(), NULL, GV->getName(), NULL, + GlobalVariable::NotThreadLocal, GV->getType()->getAddressSpace()); newGV->copyAttributesFrom(GV); - if(!GV->isDeclaration()) { - if(!copyGlobal(GV,data)) { + if (!GV->isDeclaration()) { + if (!copyGlobal(GV, data)) { newGV->setLinkage(GlobalValue::ExternalLinkage); - } else if(GV->hasInitializer()) { - Value * C = MapValue(GV->getInitializer(),VMap,RF_None,NULL,this); + } else if (GV->hasInitializer()) { + Value *C = + MapValue(GV->getInitializer(), VMap, RF_None, NULL, this); newGV->setInitializer(cast(C)); } } } return newGV; - } else return materializeValueForMetadata(V); + } else + return materializeValueForMetadata(V); } #ifdef DEBUG_INFO_WORKING - DIBuilder * DI; + DIBuilder *DI; DICompileUnit NCU; void CopyDebugMetadata() { DI = NULL; - if(NamedMDNode * NMD = src->getNamedMetadata("llvm.module.flags")) { - NamedMDNode * New = dest->getOrInsertNamedMetadata(NMD->getName()); + if (NamedMDNode *NMD = src->getNamedMetadata("llvm.module.flags")) { + NamedMDNode *New = dest->getOrInsertNamedMetadata(NMD->getName()); for (unsigned i = 0; i < NMD->getNumOperands(); i++) { - #if LLVM_VERSION <= 35 +#if LLVM_VERSION <= 35 New->addOperand(MapValue(NMD->getOperand(i), VMap)); - #else +#else New->addOperand(MapMetadata(NMD->getOperand(i), VMap)); - #endif +#endif } } - if(NamedMDNode * CUN = src->getNamedMetadata("llvm.dbg.cu")) { + if (NamedMDNode *CUN = src->getNamedMetadata("llvm.dbg.cu")) { DI = new DIBuilder(*dest); - + DICompileUnit CU(CUN->getOperand(0)); - NCU = DI->createCompileUnit(CU.getLanguage(), CU.getFilename(), CU.getDirectory(), CU.getProducer(), CU.isOptimized(), CU.getFlags(), CU.getRunTimeVersion()); + NCU = DI->createCompileUnit(CU.getLanguage(), CU.getFilename(), + CU.getDirectory(), CU.getProducer(), + CU.isOptimized(), CU.getFlags(), + CU.getRunTimeVersion()); } } - Value * materializeValueForMetadata(Value * V) { - #if LLVM_VERSION <= 35 - if(MDNode * MD = dyn_cast(V)) { + Value *materializeValueForMetadata(Value *V) { +#if LLVM_VERSION <= 35 + if (MDNode *MD = dyn_cast(V)) { DISubprogram SP(MD); - if(DI != NULL && SP.isSubprogram()) { - #else - if(auto * MDV = dyn_cast(V)) { - Metadata * MDraw = MDV->getMetadata(); - MDNode * MD = dyn_cast(MDraw); + if (DI != NULL && SP.isSubprogram()) { +#else + if (auto *MDV = dyn_cast(V)) { + Metadata *MDraw = MDV->getMetadata(); + MDNode *MD = dyn_cast(MDraw); DISubprogram SP(MD); - if(MD != NULL && DI != NULL && SP.isSubprogram()) { - #endif - - - if(Function * OF = SP.getFunction()) { - Function * F = cast(MapValue(OF,VMap,RF_None,NULL,this)); - DISubprogram NSP = DI->createFunction(SP.getContext(), SP.getName(), SP.getLinkageName(), - DI->createFile(SP.getFilename(),SP.getDirectory()), - SP.getLineNumber(), SP.getType(), - SP.isLocalToUnit(), SP.isDefinition(), - SP.getScopeLineNumber(),SP.getFlags(),SP.isOptimized(), - F); - #if LLVM_VERSION <= 35 + if (MD != NULL && DI != NULL && SP.isSubprogram()) { +#endif + + if (Function *OF = SP.getFunction()) { + Function *F = cast(MapValue(OF, VMap, RF_None, NULL, this)); + DISubprogram NSP = DI->createFunction( + SP.getContext(), SP.getName(), SP.getLinkageName(), + DI->createFile(SP.getFilename(), SP.getDirectory()), + SP.getLineNumber(), SP.getType(), SP.isLocalToUnit(), + SP.isDefinition(), SP.getScopeLineNumber(), SP.getFlags(), + SP.isOptimized(), F); +#if LLVM_VERSION <= 35 return NSP; - #else - return MetadataAsValue::get(dest->getContext(),NSP); - #endif +#else + return MetadataAsValue::get(dest->getContext(), NSP); +#endif } /* fallthrough */ } @@ -333,47 +357,47 @@ struct CopyConnectedComponent : public ValueMaterializer { return NULL; } void finalize() { - if(DI) { + if (DI) { DI->finalize(); delete DI; } } #else void CopyDebugMetadata() {} - Value * materializeValueForMetadata(Value * V) { return NULL; } + Value *materializeValueForMetadata(Value *V) { return NULL; } void finalize() {} #endif - }; -llvm::Module * llvmutil_extractmodulewithproperties(llvm::StringRef DestName, llvm::Module * Src, llvm::GlobalValue ** gvs, size_t N, llvmutil_Property copyGlobal, void * data, llvm::ValueToValueMapTy & VMap) { - Module * Dest = new Module(DestName,Src->getContext()); +llvm::Module *llvmutil_extractmodulewithproperties( + llvm::StringRef DestName, llvm::Module *Src, llvm::GlobalValue **gvs, size_t N, + llvmutil_Property copyGlobal, void *data, llvm::ValueToValueMapTy &VMap) { + Module *Dest = new Module(DestName, Src->getContext()); Dest->setTargetTriple(Src->getTargetTriple()); - CopyConnectedComponent cp(Dest,Src,copyGlobal,data,VMap); + CopyConnectedComponent cp(Dest, Src, copyGlobal, data, VMap); cp.CopyDebugMetadata(); - for(size_t i = 0; i < N; i++) - MapValue(gvs[i],VMap,RF_None,NULL,&cp); + for (size_t i = 0; i < N; i++) MapValue(gvs[i], VMap, RF_None, NULL, &cp); cp.finalize(); return Dest; } -void llvmutil_copyfrommodule(llvm::Module * Dest, llvm::Module * Src, llvm::GlobalValue ** gvs, size_t N, llvmutil_Property copyGlobal, void * data) { +void llvmutil_copyfrommodule(llvm::Module *Dest, llvm::Module *Src, + llvm::GlobalValue **gvs, size_t N, + llvmutil_Property copyGlobal, void *data) { llvm::ValueToValueMapTy VMap; - CopyConnectedComponent cp(Dest,Src,copyGlobal,data,VMap); - for(size_t i = 0; i < N; i++) - MapValue(gvs[i],VMap,RF_None,NULL,&cp); + CopyConnectedComponent cp(Dest, Src, copyGlobal, data, VMap); + for (size_t i = 0; i < N; i++) MapValue(gvs[i], VMap, RF_None, NULL, &cp); } #endif - - -void llvmutil_optimizemodule(Module * M, TargetMachine * TM) { +void llvmutil_optimizemodule(Module *M, TargetMachine *TM) { PassManagerT MPM; llvmutil_addtargetspecificpasses(&MPM, TM); - MPM.add(createVerifierPass()); //make sure we haven't messed stuff up yet - MPM.add(createGlobalDCEPass()); //run this early since anything not in the table of exported functions is still in this module - //this will remove dead functions - + MPM.add(createVerifierPass()); // make sure we haven't messed stuff up yet + MPM.add(createGlobalDCEPass()); // run this early since anything not in the table of + // exported functions is still in this module this + // will remove dead functions + PassManagerBuilder PMB; PMB.OptLevel = 3; PMB.SizeLevel = 0; @@ -394,45 +418,51 @@ void llvmutil_optimizemodule(Module * M, TargetMachine * TM) { } #if LLVM_VERSION >= 34 -error_code llvmutil_createtemporaryfile(const Twine &Prefix, StringRef Suffix, SmallVectorImpl &ResultPath) { return sys::fs::createTemporaryFile(Prefix,Suffix,ResultPath); } +error_code llvmutil_createtemporaryfile(const Twine &Prefix, StringRef Suffix, + SmallVectorImpl &ResultPath) { + return sys::fs::createTemporaryFile(Prefix, Suffix, ResultPath); +} #else -error_code llvmutil_createtemporaryfile(const Twine &Prefix, StringRef Suffix, SmallVectorImpl &ResultPath) { +error_code llvmutil_createtemporaryfile(const Twine &Prefix, StringRef Suffix, + SmallVectorImpl &ResultPath) { llvm::sys::Path P("/tmp"); P.appendComponent(Prefix.str()); P.appendSuffix(Suffix); - P.makeUnique(false,NULL); + P.makeUnique(false, NULL); StringRef str = P.str(); - ResultPath.append(str.begin(),str.end()); + ResultPath.append(str.begin(), str.end()); return error_code(); } #endif -int llvmutil_executeandwait(LLVM_PATH_TYPE program, const char ** args, std::string * err) { +int llvmutil_executeandwait(LLVM_PATH_TYPE program, const char **args, std::string *err) { #if LLVM_VERSION >= 34 bool executionFailed = false; - #if LLVM_VERSION >= 70 - llvm::sys::ProcessInfo Info = llvm::sys::ExecuteNoWait(program, llvm::toStringRefArray(args), llvm::None, {}, 0, err, &executionFailed); - #else - llvm::sys::ProcessInfo Info = llvm::sys::ExecuteNoWait(program,args,nullptr,{},0,err,&executionFailed); - #endif - if(executionFailed) +#if LLVM_VERSION >= 70 + llvm::sys::ProcessInfo Info = + llvm::sys::ExecuteNoWait(program, llvm::toStringRefArray(args), llvm::None, + {}, 0, err, &executionFailed); +#else + llvm::sys::ProcessInfo Info = llvm::sys::ExecuteNoWait(program, args, nullptr, {}, 0, + err, &executionFailed); +#endif + if (executionFailed) return -1; +#ifndef _WIN32 + // WAR for llvm bug (http://llvm.org/bugs/show_bug.cgi?id=18869) + pid_t pid; + int status; + do { + pid = waitpid(Info.Pid, &status, 0); + } while (pid == -1 && errno == EINTR); + if (pid == -1) { + *err = strerror(errno); return -1; - #ifndef _WIN32 - //WAR for llvm bug (http://llvm.org/bugs/show_bug.cgi?id=18869) - pid_t pid; - int status; - do { - pid = waitpid(Info.Pid,&status,0); - } while(pid == -1 && errno == EINTR); - if(pid == -1) { - *err = strerror(errno); - return -1; - } else { - return WEXITSTATUS(status); - } - #else - return llvm::sys::Wait(Info, 0, true, err).ReturnCode; - #endif + } else { + return WEXITSTATUS(status); + } +#else + return llvm::sys::Wait(Info, 0, true, err).ReturnCode; +#endif #else return sys::Program::ExecuteAndWait(program, args, 0, 0, 0, 0, err); #endif diff --git a/src/tllvmutil.h b/src/tllvmutil.h index c3fd235fc..c2a798b7e 100644 --- a/src/tllvmutil.h +++ b/src/tllvmutil.h @@ -3,22 +3,29 @@ #include "llvmheaders.h" -void llvmutil_addtargetspecificpasses(llvm::PassManagerBase * fpm, llvm::TargetMachine * tm); -void llvmutil_addoptimizationpasses(llvm::PassManagerBase * fpm); -extern "C" void llvmutil_disassemblefunction(void * data, size_t sz, size_t inst); -bool llvmutil_emitobjfile(llvm::Module * Mod, llvm::TargetMachine * TM, bool outputobjectfile, emitobjfile_t & dest); +void llvmutil_addtargetspecificpasses(llvm::PassManagerBase *fpm, + llvm::TargetMachine *tm); +void llvmutil_addoptimizationpasses(llvm::PassManagerBase *fpm); +extern "C" void llvmutil_disassemblefunction(void *data, size_t sz, size_t inst); +bool llvmutil_emitobjfile(llvm::Module *Mod, llvm::TargetMachine *TM, + bool outputobjectfile, emitobjfile_t &dest); #if LLVM_VERSION >= 33 -typedef bool (*llvmutil_Property)(llvm::GlobalValue *,void*); -llvm::Module * llvmutil_extractmodulewithproperties(llvm::StringRef DestName, llvm::Module * Src, llvm::GlobalValue ** gvs, size_t N, llvmutil_Property copyGlobal, void * data, llvm::ValueToValueMapTy & VMap); -void llvmutil_copyfrommodule(llvm::Module * Dest, llvm::Module * Src, llvm::GlobalValue ** gvs, size_t N, llvmutil_Property copyGlobal, void * data); +typedef bool (*llvmutil_Property)(llvm::GlobalValue *, void *); +llvm::Module *llvmutil_extractmodulewithproperties( + llvm::StringRef DestName, llvm::Module *Src, llvm::GlobalValue **gvs, size_t N, + llvmutil_Property copyGlobal, void *data, llvm::ValueToValueMapTy &VMap); +void llvmutil_copyfrommodule(llvm::Module *Dest, llvm::Module *Src, + llvm::GlobalValue **gvs, size_t N, + llvmutil_Property copyGlobal, void *data); #endif -void llvmutil_optimizemodule(llvm::Module * M, llvm::TargetMachine * TM); +void llvmutil_optimizemodule(llvm::Module *M, llvm::TargetMachine *TM); #if LLVM_VERSION >= 35 using std::error_code; #else using llvm::error_code; #endif -error_code llvmutil_createtemporaryfile(const llvm::Twine &Prefix, llvm::StringRef Suffix, llvm::SmallVectorImpl &ResultPath); -int llvmutil_executeandwait(LLVM_PATH_TYPE program, const char ** args, std::string * err); +error_code llvmutil_createtemporaryfile(const llvm::Twine &Prefix, llvm::StringRef Suffix, + llvm::SmallVectorImpl &ResultPath); +int llvmutil_executeandwait(LLVM_PATH_TYPE program, const char **args, std::string *err); #endif \ No newline at end of file diff --git a/src/tobj.h b/src/tobj.h index c12344228..942917fe3 100644 --- a/src/tobj.h +++ b/src/tobj.h @@ -8,227 +8,222 @@ extern "C" { } #include "tkind.h" -//helper function to handle cdata objects passed to C using legacy API -static inline void * terra_tocdatapointer(lua_State * L, int idx) { - if(10 != lua_type(L,idx)) return NULL; //not a cdata, 10 is from LuaJIT sources since it is not exposed in the normal API - //argument is a 'cdata'. - //calling topointer on it will return a pointer to the cdata payload - void * const * cdata = (void * const *) lua_topointer(L,idx); - if(!cdata) return NULL; +// helper function to handle cdata objects passed to C using legacy API +static inline void *terra_tocdatapointer(lua_State *L, int idx) { + if (10 != lua_type(L, idx)) + return NULL; // not a cdata, 10 is from LuaJIT sources since it is not exposed in + // the normal API + // argument is a 'cdata'. + // calling topointer on it will return a pointer to the cdata payload + void *const *cdata = (void *const *)lua_topointer(L, idx); + if (!cdata) return NULL; return *cdata; } -//object to hold reference to lua object and help extract information +// object to hold reference to lua object and help extract information struct Obj { Obj() { - ref = LUA_NOREF; L = NULL; + ref = LUA_NOREF; + L = NULL; } - void initFromStack(lua_State * L, int ref_table) { + void initFromStack(lua_State *L, int ref_table) { freeref(); this->L = L; this->ref_table = ref_table; - assert(!lua_isnil(this->L,-1)); - this->ref = luaL_ref(this->L,this->ref_table); - } - ~Obj() { - freeref(); + assert(!lua_isnil(this->L, -1)); + this->ref = luaL_ref(this->L, this->ref_table); } + ~Obj() { freeref(); } int size() { push(); - int i = lua_objlen(L,-1); + int i = lua_objlen(L, -1); pop(); return i; } - bool objAt(int i, Obj * r) { + bool objAt(int i, Obj *r) { push(); - lua_rawgeti(L,-1,i+1); //stick to 0-based indexing in C code... - if(lua_isnil(L,-1)) { + lua_rawgeti(L, -1, i + 1); // stick to 0-based indexing in C code... + if (lua_isnil(L, -1)) { pop(2); return false; } - r->initFromStack(L,ref_table); + r->initFromStack(L, ref_table); pop(); return true; } - double number(const char * field) { + double number(const char *field) { push(); - lua_getfield(L,-1,field); - double r = lua_tonumber(L,-1); + lua_getfield(L, -1, field); + double r = lua_tonumber(L, -1); pop(2); return r; } - uint64_t integer(const char * field) { + uint64_t integer(const char *field) { push(); - lua_getfield(L,-1,field); - const void * ud = lua_touserdata(L,-1); + lua_getfield(L, -1, field); + const void *ud = lua_touserdata(L, -1); pop(2); - uint64_t i = *(const uint64_t*)ud; + uint64_t i = *(const uint64_t *)ud; return i; } - bool boolean(const char * field) { + bool boolean(const char *field) { push(); - lua_getfield(L,-1,field); - bool v = lua_toboolean(L,-1); + lua_getfield(L, -1, field); + bool v = lua_toboolean(L, -1); pop(2); return v; } - const char * string(const char * field) { + const char *string(const char *field) { push(); - lua_getfield(L,-1,field); - const char * r = luaL_checkstring(L,-1); + lua_getfield(L, -1, field); + const char *r = luaL_checkstring(L, -1); pop(2); return r; } - const char * asstring(const char * field) { + const char *asstring(const char *field) { push(); lua_getfield(L, LUA_GLOBALSINDEX, "tostring"); - lua_getfield(L,-2,field); - lua_call(L,1,1); - const char * r = luaL_checkstring(L,-1); + lua_getfield(L, -2, field); + lua_call(L, 1, 1); + const char *r = luaL_checkstring(L, -1); pop(2); return r; } - bool obj(const char * field, Obj * r) { + bool obj(const char *field, Obj *r) { push(); - lua_getfield(L,-1,field); - if(lua_isnil(L,-1)) { + lua_getfield(L, -1, field); + if (lua_isnil(L, -1)) { pop(2); return false; } else { - r->initFromStack(L,ref_table); + r->initFromStack(L, ref_table); pop(); return true; } } - void * ud(const char * field) { + void *ud(const char *field) { push(); - lua_getfield(L,-1,field); - void * u = lua_touserdata(L,-1); + lua_getfield(L, -1, field); + void *u = lua_touserdata(L, -1); pop(2); return u; } - void * cd(const char * field) { + void *cd(const char *field) { push(); - lua_getfield(L,-1,field); - void * u = terra_tocdatapointer(L,-1); + lua_getfield(L, -1, field); + void *u = terra_tocdatapointer(L, -1); pop(2); return u; } - void pushfield(const char * field) { + void pushfield(const char *field) { push(); - lua_getfield(L,-1,field); - lua_remove(L,-2); + lua_getfield(L, -1, field); + lua_remove(L, -2); } - bool hasfield(const char * field) { + bool hasfield(const char *field) { push(); - lua_getfield(L,-1,field); - bool isNil = lua_isnil(L,-1); + lua_getfield(L, -1, field); + bool isNil = lua_isnil(L, -1); pop(2); return !isNil; } void push() { - //fprintf(stderr,"getting %d %d\n",ref_table,ref); + // fprintf(stderr,"getting %d %d\n",ref_table,ref); assert(lua_gettop(L) >= ref_table); - lua_rawgeti(L,ref_table,ref); + lua_rawgeti(L, ref_table, ref); } - T_Kind kind(const char * field) { + T_Kind kind(const char *field) { push(); - lua_getfield(L,LUA_GLOBALSINDEX,"terra"); - lua_getfield(L,-1,"kinds"); - lua_getfield(L,-3,field); - lua_gettable(L,-2); - int k = luaL_checkint(L,-1); + lua_getfield(L, LUA_GLOBALSINDEX, "terra"); + lua_getfield(L, -1, "kinds"); + lua_getfield(L, -3, field); + lua_gettable(L, -2); + int k = luaL_checkint(L, -1); pop(4); - return (T_Kind) k; + return (T_Kind)k; } - void setfield(const char * key) { //sets field to value on top of the stack and pops it off - assert(!lua_isnil(L,-1)); + void setfield( + const char *key) { // sets field to value on top of the stack and pops it off + assert(!lua_isnil(L, -1)); push(); - lua_pushvalue(L,-2); - lua_setfield(L,-2,key); + lua_pushvalue(L, -2); + lua_setfield(L, -2, key); pop(2); } - void clearfield(const char * key) { + void clearfield(const char *key) { push(); lua_pushnil(L); - lua_setfield(L,-2,key); + lua_setfield(L, -2, key); pop(1); } void addentry() { int s = size(); push(); lua_pushvalue(L, -2); - lua_rawseti(L, -2, s+1); + lua_rawseti(L, -2, s + 1); pop(2); } - void setud(Obj * k,void * ud) { + void setud(Obj *k, void *ud) { push(); k->push(); - lua_pushlightuserdata(L,ud); - lua_settable(L,-3); + lua_pushlightuserdata(L, ud); + lua_settable(L, -3); pop(1); } - void * getud(Obj * k) { + void *getud(Obj *k) { push(); k->push(); - lua_gettable(L,-2); - void * r = lua_touserdata(L,-1); + lua_gettable(L, -2); + void *r = lua_touserdata(L, -1); pop(2); return r; } void dump() { - lua_getfield(L,LUA_GLOBALSINDEX,"terra"); - lua_getfield(L,-1,"printraw"); + lua_getfield(L, LUA_GLOBALSINDEX, "terra"); + lua_getfield(L, -1, "printraw"); push(); lua_call(L, 1, 0); - - lua_pop(L,1); + + lua_pop(L, 1); } void print() { - lua_getfield(L,LUA_GLOBALSINDEX,"print"); + lua_getfield(L, LUA_GLOBALSINDEX, "print"); push(); - lua_call(L,1,0); + lua_call(L, 1, 0); } - void newlist(Obj * lst) { - lua_getfield(L,LUA_GLOBALSINDEX,"terra"); - lua_getfield(L,-1,"newlist"); - lua_remove(L,-2); + void newlist(Obj *lst) { + lua_getfield(L, LUA_GLOBALSINDEX, "terra"); + lua_getfield(L, -1, "newlist"); + lua_remove(L, -2); lua_call(L, 0, 1); lst->initFromStack(L, ref_table); } - void fromStack(Obj * o) { - o->initFromStack(L, ref_table); - } - lua_State * getState() { - return L; - } - int getRefTable() { - return ref_table; - } + void fromStack(Obj *o) { o->initFromStack(L, ref_table); } + lua_State *getState() { return L; } + int getRefTable() { return ref_table; } + private: void freeref() { - if(ref != LUA_NOREF) { - luaL_unref(L,ref_table,ref); + if (ref != LUA_NOREF) { + luaL_unref(L, ref_table, ref); L = NULL; ref = LUA_NOREF; } } - void pop(int n = 1) { - lua_pop(L,n); - } + void pop(int n = 1) { lua_pop(L, n); } int ref; int ref_table; - lua_State * L; + lua_State *L; }; -static inline int lobj_newreftable(lua_State * L) { +static inline int lobj_newreftable(lua_State *L) { lua_newtable(L); return lua_gettop(L); } -static inline void lobj_removereftable(lua_State * L, int ref_table) { +static inline void lobj_removereftable(lua_State *L, int ref_table) { assert(lua_gettop(L) == ref_table); - lua_pop(L,1); //remove the reference table from stack + lua_pop(L, 1); // remove the reference table from stack } #endif diff --git a/src/treadnumber.c b/src/treadnumber.c index c0f32a2bb..d117271c7 100644 --- a/src/treadnumber.c +++ b/src/treadnumber.c @@ -4,22 +4,23 @@ #include "lj_strscan.h" -int treadnumber(const char * buf, ReadNumber * result, int cstylesuffixes) { +int treadnumber(const char* buf, ReadNumber* result, int cstylesuffixes) { TLJ_TValue o; StrScanFmt fmt; int opt = STRSCAN_OPT_TOINT | STRSCAN_OPT_LL; - if(cstylesuffixes) + if (cstylesuffixes) opt |= STRSCAN_OPT_C; else opt |= STRSCAN_OPT_IMAG; - + fmt = terra_lj_strscan_scan((const uint8_t*)buf, &o, opt); result->flags = 0; - switch(fmt) { + switch (fmt) { case STRSCAN_ERROR: return 1; case STRSCAN_IMAG: - /* terra doesn't have imag numbers, so allowimag will be false for terra code */ + /* terra doesn't have imag numbers, so allowimag will be false for terra code + */ break; case STRSCAN_NUM: result->d = o.n; diff --git a/src/treadnumber.h b/src/treadnumber.h index de43a1bb9..209e5eecf 100644 --- a/src/treadnumber.h +++ b/src/treadnumber.h @@ -2,7 +2,7 @@ #define _treadnumber_h /* wrapper around LuaJIT's read number parsing code - used in the lexer so that we match LuaJIT's number format as closely as possible + used in the lexer so that we match LuaJIT's number format as closely as possible NYI - negative numbers, since '-' is treated as a unary minus we only ever encounter positive numbers, readnumber will not handle negatives correctly */ @@ -19,14 +19,14 @@ typedef enum { F_IS8BYTES = 4, } ReadNumberFlags; -typedef struct { +typedef struct { union { uint64_t i; double d; }; int flags; } ReadNumber; -int treadnumber(const char * buf, ReadNumber * result, int cstylesuffixes); +int treadnumber(const char* buf, ReadNumber* result, int cstylesuffixes); #ifdef __cplusplus } /* extern "C" */ diff --git a/tests/benchmarks/timing.h b/tests/benchmarks/timing.h index a51ec2db7..dd9db74dc 100644 --- a/tests/benchmarks/timing.h +++ b/tests/benchmarks/timing.h @@ -2,7 +2,7 @@ #include double current_time() { - struct timeval v; - gettimeofday(&v, NULL); - return v.tv_sec + v.tv_usec / 1000000.0; + struct timeval v; + gettimeofday(&v, NULL); + return v.tv_sec + v.tv_usec / 1000000.0; } diff --git a/tests/mytest.h b/tests/mytest.h index 71222b393..ad915f667 100644 --- a/tests/mytest.h +++ b/tests/mytest.h @@ -1,13 +1,22 @@ #include -int myfoobarthing(int a, double b, int c,int * d) { - FILE * foo = fopen("what","r"); - printf("my foobar thing is alive %d %f %d\n",a,b,c); +int myfoobarthing(int a, double b, int c, int* d) { + FILE* foo = fopen("what", "r"); + printf("my foobar thing is alive %d %f %d\n", a, b, c); *d = 8; return 7; } int myotherthing(int a, int b) { return a + b; } int myfnptr(int (*foobar)(void)) { return foobar(); } -typedef struct MyStruct { int a; double b; } MyStruct; -typedef struct MyStruct2 { int a; union { int b; int c; }; } MyStruct2; \ No newline at end of file +typedef struct MyStruct { + int a; + double b; +} MyStruct; +typedef struct MyStruct2 { + int a; + union { + int b; + int c; + }; +} MyStruct2; \ No newline at end of file