mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2025-03-11 03:13:06 +00:00
Made intrinsics seperate from the parser.
This commit is contained in:
parent
85ee52128c
commit
73d9aa29c4
5 changed files with 151 additions and 139 deletions
2
Makefile
2
Makefile
|
@ -150,7 +150,7 @@ stat.o: gmqcc.h opts.def
|
|||
test.o: gmqcc.h opts.def
|
||||
main.o: gmqcc.h opts.def lexer.h
|
||||
lexer.o: gmqcc.h opts.def lexer.h
|
||||
parser.o: parser.h gmqcc.h opts.def lexer.h ast.h ir.h intrin.h
|
||||
parser.o: parser.h gmqcc.h opts.def lexer.h ast.h ir.h
|
||||
code.o: gmqcc.h opts.def
|
||||
ast.o: gmqcc.h opts.def ast.h ir.h parser.h lexer.h
|
||||
ir.o: gmqcc.h opts.def ir.h
|
||||
|
|
|
@ -14,7 +14,7 @@ LDFLAGS +=
|
|||
LIBS += -lm
|
||||
|
||||
#objects
|
||||
OBJ_C = main.o lexer.o parser.o fs.o stat.o util.o code.o ast.o ir.o conout.o ftepp.o opts.o utf8.o correct.o fold.o
|
||||
OBJ_C = main.o lexer.o parser.o fs.o stat.o util.o code.o ast.o ir.o conout.o ftepp.o opts.o utf8.o correct.o fold.o intrin.o
|
||||
OBJ_P = util.o fs.o conout.o opts.o pak.o stat.o
|
||||
OBJ_T = test.o util.o opts.o conout.o fs.o stat.o
|
||||
OBJ_X = exec-standalone.o util.o opts.o conout.o fs.o stat.o
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "parser.h"
|
||||
|
||||
/*
|
||||
* Provides all the "intrinsics" / "builtins" for GMQCC. These can do
|
||||
|
@ -30,49 +32,34 @@
|
|||
* is entered when -fintrin is used (causing all existing builtins to
|
||||
* be ignored by the compiler and instead interface through here.
|
||||
*/
|
||||
typedef struct {
|
||||
ast_expression *(*intrin)(parser_t *);
|
||||
const char *name;
|
||||
const char *alias;
|
||||
} intrin_t;
|
||||
|
||||
static ht intrin_intrinsics(void) {
|
||||
static ht intrinsics = NULL;
|
||||
if (!intrinsics)
|
||||
intrinsics = util_htnew(PARSER_HT_SIZE);
|
||||
|
||||
return intrinsics;
|
||||
}
|
||||
|
||||
#define INTRIN_VAL(VALUE, NAME, FUNC, STYPE, VTYPE) \
|
||||
do { \
|
||||
(VALUE) = ast_value_new ( \
|
||||
parser_ctx(parser), \
|
||||
"__builtin_" NAME, \
|
||||
TYPE_FUNCTION \
|
||||
); \
|
||||
(VALUE)->expression.next = (ast_expression*)ast_value_new ( \
|
||||
parser_ctx(parser), \
|
||||
STYPE, \
|
||||
VTYPE \
|
||||
); \
|
||||
(FUNC) = ast_function_new ( \
|
||||
parser_ctx(parser), \
|
||||
"__builtin_" NAME, \
|
||||
(VALUE) \
|
||||
); \
|
||||
#define INTRIN_VAL(VALUE, NAME, FUNC, STYPE, VTYPE) \
|
||||
do { \
|
||||
(VALUE) = ast_value_new ( \
|
||||
parser_ctx(intrin->parser), \
|
||||
"__builtin_" NAME, \
|
||||
TYPE_FUNCTION \
|
||||
); \
|
||||
(VALUE)->expression.next = (ast_expression*)ast_value_new ( \
|
||||
parser_ctx(intrin->parser), \
|
||||
STYPE, \
|
||||
VTYPE \
|
||||
); \
|
||||
(FUNC) = ast_function_new ( \
|
||||
parser_ctx(intrin->parser), \
|
||||
"__builtin_" NAME, \
|
||||
(VALUE) \
|
||||
); \
|
||||
} while (0)
|
||||
|
||||
#define INTRIN_REG(FUNC, VALUE) \
|
||||
do { \
|
||||
vec_push(parser->functions, (FUNC)); \
|
||||
vec_push(parser->globals, (ast_expression*)(VALUE)); \
|
||||
#define INTRIN_REG(FUNC, VALUE) \
|
||||
do { \
|
||||
vec_push(intrin->parser->functions, (FUNC)); \
|
||||
vec_push(intrin->parser->globals, (ast_expression*)(VALUE)); \
|
||||
} while (0)
|
||||
|
||||
#define QC_M_E 2.71828182845905
|
||||
|
||||
static ast_expression *intrin_func(parser_t *parser, const char *name);
|
||||
static ast_expression *intrin_pow (parser_t *parser) {
|
||||
static ast_expression *intrin_pow (intrin_t *intrin) {
|
||||
/*
|
||||
* float pow(float x, float y) {
|
||||
* float local = 1.0f;
|
||||
|
@ -90,12 +77,12 @@ static ast_expression *intrin_pow (parser_t *parser) {
|
|||
static ast_value *value = NULL;
|
||||
|
||||
if (!value) {
|
||||
ast_value *arg1 = ast_value_new(parser_ctx(parser), "x", TYPE_FLOAT);
|
||||
ast_value *arg2 = ast_value_new(parser_ctx(parser), "y", TYPE_FLOAT);
|
||||
ast_value *local = ast_value_new(parser_ctx(parser), "local", TYPE_FLOAT);
|
||||
ast_block *body = ast_block_new(parser_ctx(parser));
|
||||
ast_block *l1b = ast_block_new(parser_ctx(parser)); /* loop 1 body */
|
||||
ast_block *l2b = ast_block_new(parser_ctx(parser)); /* looo 2 body */
|
||||
ast_value *arg1 = ast_value_new(parser_ctx(intrin->parser), "x", TYPE_FLOAT);
|
||||
ast_value *arg2 = ast_value_new(parser_ctx(intrin->parser), "y", TYPE_FLOAT);
|
||||
ast_value *local = ast_value_new(parser_ctx(intrin->parser), "local", TYPE_FLOAT);
|
||||
ast_block *body = ast_block_new(parser_ctx(intrin->parser));
|
||||
ast_block *l1b = ast_block_new(parser_ctx(intrin->parser)); /* loop 1 body */
|
||||
ast_block *l2b = ast_block_new(parser_ctx(intrin->parser)); /* loop 2 body */
|
||||
ast_loop *loop1 = NULL;
|
||||
ast_loop *loop2 = NULL;
|
||||
ast_function *func = NULL;
|
||||
|
@ -112,28 +99,28 @@ static ast_expression *intrin_pow (parser_t *parser) {
|
|||
/* assignment to local of value 1.0f */
|
||||
vec_push(body->exprs,
|
||||
(ast_expression*)ast_store_new (
|
||||
parser_ctx(parser),
|
||||
parser_ctx(intrin->parser),
|
||||
INSTR_STORE_F,
|
||||
(ast_expression*)local,
|
||||
(ast_expression*)parser->fold->imm_float[1] /* 1 == 1.0f */
|
||||
(ast_expression*)intrin->fold->imm_float[1] /* 1 == 1.0f */
|
||||
)
|
||||
);
|
||||
|
||||
/* y >>= 2 */
|
||||
vec_push(l2b->exprs,
|
||||
(ast_expression*)ast_binstore_new (
|
||||
parser_ctx(parser),
|
||||
parser_ctx(intrin->parser),
|
||||
INSTR_STORE_F,
|
||||
INSTR_MUL_F,
|
||||
(ast_expression*)arg2,
|
||||
(ast_expression*)fold_constgen_float(parser->fold, 0.25f)
|
||||
(ast_expression*)fold_constgen_float(intrin->parser->fold, 0.25f)
|
||||
)
|
||||
);
|
||||
|
||||
/* x *= x */
|
||||
vec_push(l2b->exprs,
|
||||
(ast_expression*)ast_binstore_new (
|
||||
parser_ctx(parser),
|
||||
parser_ctx(intrin->parser),
|
||||
INSTR_STORE_F,
|
||||
INSTR_MUL_F,
|
||||
(ast_expression*)arg1,
|
||||
|
@ -143,13 +130,13 @@ static ast_expression *intrin_pow (parser_t *parser) {
|
|||
|
||||
/* while (!(y&1)) */
|
||||
loop2 = ast_loop_new (
|
||||
parser_ctx(parser),
|
||||
parser_ctx(intrin->parser),
|
||||
NULL,
|
||||
(ast_expression*)ast_binary_new (
|
||||
parser_ctx(parser),
|
||||
parser_ctx(intrin->parser),
|
||||
INSTR_AND,
|
||||
(ast_expression*)arg2,
|
||||
(ast_expression*)parser->fold->imm_float[1] /* 1 == 1.0f */
|
||||
(ast_expression*)intrin->fold->imm_float[1] /* 1 == 1.0f */
|
||||
),
|
||||
true, /* ! not */
|
||||
NULL,
|
||||
|
@ -164,17 +151,17 @@ static ast_expression *intrin_pow (parser_t *parser) {
|
|||
/* y-- */
|
||||
vec_push(l1b->exprs,
|
||||
(ast_expression*)ast_binstore_new (
|
||||
parser_ctx(parser),
|
||||
parser_ctx(intrin->parser),
|
||||
INSTR_STORE_F,
|
||||
INSTR_SUB_F,
|
||||
(ast_expression*)arg2,
|
||||
(ast_expression*)parser->fold->imm_float[1] /* 1 == 1.0f */
|
||||
(ast_expression*)intrin->fold->imm_float[1] /* 1 == 1.0f */
|
||||
)
|
||||
);
|
||||
/* local *= x */
|
||||
vec_push(l1b->exprs,
|
||||
(ast_expression*)ast_binstore_new (
|
||||
parser_ctx(parser),
|
||||
parser_ctx(intrin->parser),
|
||||
INSTR_STORE_F,
|
||||
INSTR_MUL_F,
|
||||
(ast_expression*)local,
|
||||
|
@ -184,13 +171,13 @@ static ast_expression *intrin_pow (parser_t *parser) {
|
|||
|
||||
/* while (y > 0) */
|
||||
loop1 = ast_loop_new (
|
||||
parser_ctx(parser),
|
||||
parser_ctx(intrin->parser),
|
||||
NULL,
|
||||
(ast_expression*)ast_binary_new (
|
||||
parser_ctx(parser),
|
||||
parser_ctx(intrin->parser),
|
||||
INSTR_GT,
|
||||
(ast_expression*)arg2,
|
||||
(ast_expression*)parser->fold->imm_float[0] /* 0 == 0.0f */
|
||||
(ast_expression*)intrin->fold->imm_float[0] /* 0 == 0.0f */
|
||||
),
|
||||
false,
|
||||
NULL,
|
||||
|
@ -205,7 +192,7 @@ static ast_expression *intrin_pow (parser_t *parser) {
|
|||
/* return local; */
|
||||
vec_push(body->exprs,
|
||||
(ast_expression*)ast_return_new (
|
||||
parser_ctx(parser),
|
||||
parser_ctx(intrin->parser),
|
||||
(ast_expression*)local
|
||||
)
|
||||
);
|
||||
|
@ -219,7 +206,7 @@ static ast_expression *intrin_pow (parser_t *parser) {
|
|||
return (ast_expression*)value;
|
||||
}
|
||||
|
||||
static ast_expression *intrin_mod(parser_t *parser) {
|
||||
static ast_expression *intrin_mod(intrin_t *intrin) {
|
||||
/*
|
||||
* float mod(float x, float y) {
|
||||
* return x - y * floor(x / y);
|
||||
|
@ -228,10 +215,10 @@ static ast_expression *intrin_mod(parser_t *parser) {
|
|||
static ast_value *value = NULL;
|
||||
|
||||
if (!value) {
|
||||
ast_call *call = ast_call_new (parser_ctx(parser), intrin_func(parser, "floor"));
|
||||
ast_value *arg1 = ast_value_new(parser_ctx(parser), "x", TYPE_FLOAT);
|
||||
ast_value *arg2 = ast_value_new(parser_ctx(parser), "y", TYPE_FLOAT);
|
||||
ast_block *body = ast_block_new(parser_ctx(parser));
|
||||
ast_call *call = ast_call_new (parser_ctx(intrin->parser), intrin_func(intrin, "floor"));
|
||||
ast_value *arg1 = ast_value_new(parser_ctx(intrin->parser), "x", TYPE_FLOAT);
|
||||
ast_value *arg2 = ast_value_new(parser_ctx(intrin->parser), "y", TYPE_FLOAT);
|
||||
ast_block *body = ast_block_new(parser_ctx(intrin->parser));
|
||||
ast_function *func = NULL;
|
||||
|
||||
INTRIN_VAL(value, "mod", func, "<float>", TYPE_FLOAT);
|
||||
|
@ -239,7 +226,7 @@ static ast_expression *intrin_mod(parser_t *parser) {
|
|||
/* floor(x/y) */
|
||||
vec_push(call->params,
|
||||
(ast_expression*)ast_binary_new (
|
||||
parser_ctx(parser),
|
||||
parser_ctx(intrin->parser),
|
||||
INSTR_DIV_F,
|
||||
(ast_expression*)arg1,
|
||||
(ast_expression*)arg2
|
||||
|
@ -248,13 +235,13 @@ static ast_expression *intrin_mod(parser_t *parser) {
|
|||
|
||||
vec_push(body->exprs,
|
||||
(ast_expression*)ast_return_new(
|
||||
parser_ctx(parser),
|
||||
parser_ctx(intrin->parser),
|
||||
(ast_expression*)ast_binary_new(
|
||||
parser_ctx(parser),
|
||||
parser_ctx(intrin->parser),
|
||||
INSTR_SUB_F,
|
||||
(ast_expression*)arg1,
|
||||
(ast_expression*)ast_binary_new(
|
||||
parser_ctx(parser),
|
||||
parser_ctx(intrin->parser),
|
||||
INSTR_MUL_F,
|
||||
(ast_expression*)arg2,
|
||||
(ast_expression*)call
|
||||
|
@ -266,7 +253,7 @@ static ast_expression *intrin_mod(parser_t *parser) {
|
|||
vec_push(value->expression.params, arg1); /* float x (for param) */
|
||||
vec_push(value->expression.params, arg2); /* float y (for param) */
|
||||
|
||||
vec_push(func->blocks, body); /* {{{ body }}} */
|
||||
vec_push(func->blocks, body); /* {{{ body }}} */
|
||||
|
||||
INTRIN_REG(func, value);
|
||||
}
|
||||
|
@ -274,7 +261,7 @@ static ast_expression *intrin_mod(parser_t *parser) {
|
|||
return (ast_expression*)value;
|
||||
}
|
||||
|
||||
static ast_expression *intrin_exp(parser_t *parser) {
|
||||
static ast_expression *intrin_exp(intrin_t *intrin) {
|
||||
/*
|
||||
* float exp(float x) {
|
||||
* return pow(QC_M_E, x);
|
||||
|
@ -283,21 +270,21 @@ static ast_expression *intrin_exp(parser_t *parser) {
|
|||
static ast_value *value = NULL;
|
||||
|
||||
if (!value) {
|
||||
ast_call *call = ast_call_new (parser_ctx(parser), intrin_func(parser, "pow"));
|
||||
ast_value *arg1 = ast_value_new (parser_ctx(parser), "x", TYPE_FLOAT);
|
||||
ast_block *body = ast_block_new (parser_ctx(parser));
|
||||
ast_call *call = ast_call_new (parser_ctx(intrin->parser), intrin_func(intrin, "pow"));
|
||||
ast_value *arg1 = ast_value_new(parser_ctx(intrin->parser), "x", TYPE_FLOAT);
|
||||
ast_block *body = ast_block_new(parser_ctx(intrin->parser));
|
||||
ast_function *func = NULL;
|
||||
|
||||
INTRIN_VAL(value, "exp", func, "<float>", TYPE_FLOAT);
|
||||
|
||||
/* push arguments for params to call */
|
||||
vec_push(call->params, (ast_expression*)fold_constgen_float(parser->fold, QC_M_E));
|
||||
vec_push(call->params, (ast_expression*)fold_constgen_float(intrin->fold, QC_M_E));
|
||||
vec_push(call->params, (ast_expression*)arg1);
|
||||
|
||||
/* return pow(QC_M_E, x) */
|
||||
vec_push(body->exprs,
|
||||
(ast_expression*)ast_return_new(
|
||||
parser_ctx(parser),
|
||||
parser_ctx(intrin->parser),
|
||||
(ast_expression*)call
|
||||
)
|
||||
);
|
||||
|
@ -312,7 +299,7 @@ static ast_expression *intrin_exp(parser_t *parser) {
|
|||
return (ast_expression*)value;
|
||||
}
|
||||
|
||||
static ast_expression *intrin_isnan(parser_t *parser) {
|
||||
static ast_expression *intrin_isnan(intrin_t *intrin) {
|
||||
/*
|
||||
* float isnan(float x) {
|
||||
* float local;
|
||||
|
@ -324,9 +311,9 @@ static ast_expression *intrin_isnan(parser_t *parser) {
|
|||
static ast_value *value = NULL;
|
||||
|
||||
if (!value) {
|
||||
ast_value *arg1 = ast_value_new (parser_ctx(parser), "x", TYPE_FLOAT);
|
||||
ast_value *local = ast_value_new (parser_ctx(parser), "local", TYPE_FLOAT);
|
||||
ast_block *body = ast_block_new (parser_ctx(parser));
|
||||
ast_value *arg1 = ast_value_new(parser_ctx(intrin->parser), "x", TYPE_FLOAT);
|
||||
ast_value *local = ast_value_new(parser_ctx(intrin->parser), "local", TYPE_FLOAT);
|
||||
ast_block *body = ast_block_new(parser_ctx(intrin->parser));
|
||||
ast_function *func = NULL;
|
||||
|
||||
INTRIN_VAL(value, "isnan", func, "<float>", TYPE_FLOAT);
|
||||
|
@ -334,7 +321,7 @@ static ast_expression *intrin_isnan(parser_t *parser) {
|
|||
vec_push(body->locals, local);
|
||||
vec_push(body->exprs,
|
||||
(ast_expression*)ast_store_new(
|
||||
parser_ctx(parser),
|
||||
parser_ctx(intrin->parser),
|
||||
INSTR_STORE_F,
|
||||
(ast_expression*)local,
|
||||
(ast_expression*)arg1
|
||||
|
@ -343,9 +330,9 @@ static ast_expression *intrin_isnan(parser_t *parser) {
|
|||
|
||||
vec_push(body->exprs,
|
||||
(ast_expression*)ast_return_new(
|
||||
parser_ctx(parser),
|
||||
parser_ctx(intrin->parser),
|
||||
(ast_expression*)ast_binary_new(
|
||||
parser_ctx(parser),
|
||||
parser_ctx(intrin->parser),
|
||||
INSTR_NE_F,
|
||||
(ast_expression*)arg1,
|
||||
(ast_expression*)local
|
||||
|
@ -354,7 +341,6 @@ static ast_expression *intrin_isnan(parser_t *parser) {
|
|||
);
|
||||
|
||||
vec_push(value->expression.params, arg1);
|
||||
|
||||
vec_push(func->blocks, body);
|
||||
|
||||
INTRIN_REG(func, value);
|
||||
|
@ -362,13 +348,19 @@ static ast_expression *intrin_isnan(parser_t *parser) {
|
|||
|
||||
return (ast_expression*)value;
|
||||
}
|
||||
#undef INTRIN_REG
|
||||
#undef INTRIN_VAL
|
||||
|
||||
static ast_expression *intrin_debug_typestring(parser_t *parser) {
|
||||
(void)parser;
|
||||
/*
|
||||
* TODO: make static (and handle ast_type_string) here for the builtin
|
||||
* instead of in SYA parse close.
|
||||
*/
|
||||
ast_expression *intrin_debug_typestring(intrin_t *intrin) {
|
||||
(void)intrin;
|
||||
return (ast_expression*)0x1;
|
||||
}
|
||||
|
||||
static intrin_t intrinsics[] = {
|
||||
static const intrin_func_t intrinsics[] = {
|
||||
{&intrin_exp, "__builtin_exp", "exp"},
|
||||
{&intrin_mod, "__builtin_mod", "mod"},
|
||||
{&intrin_pow, "__builtin_pow", "pow"},
|
||||
|
@ -376,50 +368,48 @@ static intrin_t intrinsics[] = {
|
|||
{&intrin_debug_typestring, "__builtin_debug_typestring", ""}
|
||||
};
|
||||
|
||||
void intrin_intrinsics_destroy(parser_t *parser) {
|
||||
/*size_t i;*/
|
||||
(void)parser;
|
||||
util_htdel(intrin_intrinsics());
|
||||
static void intrin_error(intrin_t *intrin, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vcompile_error(intrin->parser->lex->tok.ctx, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/* exposed */
|
||||
intrin_t *intrin_init(parser_t *parser) {
|
||||
intrin_t *intrin = (intrin_t*)mem_a(sizeof(intrin_t));
|
||||
intrin->parser = parser;
|
||||
intrin->fold = parser->fold;
|
||||
intrin->intrinsics = NULL;
|
||||
|
||||
static ast_expression *intrin_func(parser_t *parser, const char *name) {
|
||||
static bool init = false;
|
||||
vec_append(intrin->intrinsics, sizeof(intrinsics)/sizeof(*intrinsics), intrinsics);
|
||||
|
||||
return intrin;
|
||||
}
|
||||
|
||||
void intrin_cleanup(intrin_t *intrin) {
|
||||
vec_free(intrin->intrinsics);
|
||||
mem_d(intrin);
|
||||
}
|
||||
|
||||
ast_expression *intrin_func(intrin_t *intrin, const char *name) {
|
||||
size_t i = 0;
|
||||
void *find;
|
||||
|
||||
/* register the intrinsics in the hashtable for O(1) lookup */
|
||||
if (!init) {
|
||||
for (i = 0; i < sizeof(intrinsics)/sizeof(*intrinsics); i++)
|
||||
util_htset(intrin_intrinsics(), intrinsics[i].name, &intrinsics[i]);
|
||||
|
||||
init = true; /* only once */
|
||||
}
|
||||
|
||||
/*
|
||||
* jesus fucking christ, Blub design something less fucking
|
||||
* impossible to use, like a ast_is_builtin(ast_expression *), also
|
||||
* use a hashtable :P
|
||||
*/
|
||||
if ((find = (void*)parser_find_global(parser, name)) && ((ast_value*)find)->expression.vtype == TYPE_FUNCTION)
|
||||
for (i = 0; i < vec_size(parser->functions); ++i)
|
||||
if (((ast_value*)find)->name && !strcmp(parser->functions[i]->name, ((ast_value*)find)->name) && parser->functions[i]->builtin < 0)
|
||||
/* try current first */
|
||||
if ((find = (void*)parser_find_global(intrin->parser, name)) && ((ast_value*)find)->expression.vtype == TYPE_FUNCTION)
|
||||
for (i = 0; i < vec_size(intrin->parser->functions); ++i)
|
||||
if (((ast_value*)find)->name && !strcmp(intrin->parser->functions[i]->name, ((ast_value*)find)->name) && intrin->parser->functions[i]->builtin < 0)
|
||||
return (ast_expression*)find;
|
||||
/* try name second */
|
||||
for (i = 0; i < vec_size(intrin->intrinsics); i++)
|
||||
if (!strcmp(intrin->intrinsics[i].name, name))
|
||||
return intrin->intrinsics[i].intrin(intrin);
|
||||
/* try alias third */
|
||||
for (i = 0; i < vec_size(intrin->intrinsics); i++)
|
||||
if (!strcmp(intrin->intrinsics[i].alias, name))
|
||||
return intrin->intrinsics[i].intrin(intrin);
|
||||
|
||||
if ((find = util_htget(intrin_intrinsics(), name))) {
|
||||
/* intrinsic is in table. This will "generate the function" so
|
||||
* to speak (if it's not already generated).
|
||||
*/
|
||||
return ((intrin_t*)find)->intrin(parser);
|
||||
}
|
||||
|
||||
/*
|
||||
* check aliases now to see if there is an implementation of it.
|
||||
*/
|
||||
for (i = 0; i < sizeof(intrinsics) / sizeof(*intrinsics); i++)
|
||||
if (!strcmp(intrinsics[i].alias, name))
|
||||
return intrinsics[i].intrin(parser);
|
||||
|
||||
parseerror(parser, "need function: `%s` compiler depends on it", name);
|
||||
intrin_error(intrin, "need function: `%s` compiler depends on it", name);
|
||||
return NULL;
|
||||
}
|
20
parser.c
20
parser.c
|
@ -109,7 +109,7 @@ static ast_expression* parser_find_label(parser_t *parser, const char *name)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static ast_expression* parser_find_global(parser_t *parser, const char *name)
|
||||
ast_expression* parser_find_global(parser_t *parser, const char *name)
|
||||
{
|
||||
ast_expression *var = (ast_expression*)util_htget(parser->aliases, parser_tokval(parser));
|
||||
if (var)
|
||||
|
@ -171,9 +171,6 @@ static ast_value* parser_find_typedef(parser_t *parser, const char *name, size_t
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* include intrinsics */
|
||||
#include "intrin.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
size_t etype; /* 0 = expression, others are operators */
|
||||
|
@ -608,7 +605,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
|||
return false;
|
||||
} else if (!(out = fold_op(parser->fold, op, exprs))) {
|
||||
/* generate a call to __builtin_mod */
|
||||
ast_expression *mod = intrin_func(parser, "mod");
|
||||
ast_expression *mod = intrin_func(parser->intrin, "mod");
|
||||
ast_call *call = NULL;
|
||||
if (!mod) return false; /* can return null for missing floor */
|
||||
|
||||
|
@ -810,7 +807,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
|||
}
|
||||
|
||||
if (!(out = fold_op(parser->fold, op, exprs))) {
|
||||
ast_call *gencall = ast_call_new(parser_ctx(parser), intrin_func(parser, "pow"));
|
||||
ast_call *gencall = ast_call_new(parser_ctx(parser), intrin_func(parser->intrin, "pow"));
|
||||
vec_push(gencall->params, exprs[0]);
|
||||
vec_push(gencall->params, exprs[1]);
|
||||
out = (ast_expression*)gencall;
|
||||
|
@ -1199,7 +1196,7 @@ static bool parser_close_call(parser_t *parser, shunt *sy)
|
|||
* TODO handle this at the intrinsic level with an ast_intrinsic
|
||||
* node and codegen.
|
||||
*/
|
||||
if ((fun = sy->out[fid].out) == intrin_debug_typestring(parser)) {
|
||||
if ((fun = sy->out[fid].out) == intrin_debug_typestring(parser->intrin)) {
|
||||
char ty[1024];
|
||||
if (fid+2 != vec_size(sy->out) ||
|
||||
vec_last(sy->out).block)
|
||||
|
@ -1561,7 +1558,7 @@ static bool parse_sya_operand(parser_t *parser, shunt *sy, bool with_labels)
|
|||
* use the identifier as is.
|
||||
*/
|
||||
if (!strncmp(parser_tokval(parser), "__builtin_", 10)) {
|
||||
var = intrin_func(parser, parser_tokval(parser));
|
||||
var = intrin_func(parser->intrin, parser_tokval(parser));
|
||||
}
|
||||
|
||||
if (!var) {
|
||||
|
@ -5868,7 +5865,8 @@ parser_t *parser_create()
|
|||
parser->reserved_version = NULL;
|
||||
}
|
||||
|
||||
parser->fold = fold_init(parser);
|
||||
parser->fold = fold_init (parser);
|
||||
parser->intrin = intrin_init(parser);
|
||||
return parser;
|
||||
}
|
||||
|
||||
|
@ -5986,9 +5984,9 @@ static void parser_remove_ast(parser_t *parser)
|
|||
if (parser->reserved_version)
|
||||
ast_value_delete(parser->reserved_version);
|
||||
|
||||
util_htdel(parser->aliases);
|
||||
intrin_intrinsics_destroy(parser);
|
||||
util_htdel(parser->aliases);
|
||||
fold_cleanup(parser->fold);
|
||||
intrin_cleanup(parser->intrin);
|
||||
}
|
||||
|
||||
void parser_cleanup(parser_t *parser)
|
||||
|
|
32
parser.h
32
parser.h
|
@ -27,6 +27,9 @@
|
|||
#include "lexer.h"
|
||||
#include "ast.h"
|
||||
|
||||
typedef struct intrin_s intrin_t;
|
||||
typedef struct parser_s parser_t;
|
||||
|
||||
typedef struct {
|
||||
struct parser_s *parser;
|
||||
ast_value **imm_float; /* vector<ast_value*> */
|
||||
|
@ -36,9 +39,21 @@ typedef struct {
|
|||
hash_table_t *imm_string_dotranslate; /* map<string, ast_value*> */
|
||||
} fold_t;
|
||||
|
||||
typedef struct {
|
||||
ast_expression *(*intrin)(intrin_t *);
|
||||
const char *name;
|
||||
const char *alias;
|
||||
} intrin_func_t;
|
||||
|
||||
struct intrin_s {
|
||||
intrin_func_t *intrinsics; /* vector<intrin_func_t> */
|
||||
parser_t *parser;
|
||||
fold_t *fold;
|
||||
};
|
||||
|
||||
#define parser_ctx(p) ((p)->lex->tok.ctx)
|
||||
|
||||
typedef struct parser_s {
|
||||
struct parser_s {
|
||||
lex_file *lex;
|
||||
int tok;
|
||||
|
||||
|
@ -98,11 +113,14 @@ typedef struct parser_s {
|
|||
/* collected information */
|
||||
size_t max_param_count;
|
||||
|
||||
fold_t *fold;
|
||||
} parser_t;
|
||||
fold_t *fold;
|
||||
intrin_t *intrin;
|
||||
};
|
||||
|
||||
|
||||
char *parser_strdup(const char *str);
|
||||
/* parser.c */
|
||||
char *parser_strdup (const char *str);
|
||||
ast_expression *parser_find_global(parser_t *parser, const char *name);
|
||||
|
||||
/* fold.c */
|
||||
fold_t *fold_init (parser_t *);
|
||||
|
@ -115,4 +133,10 @@ ast_expression *fold_op (fold_t *, const oper_info *, ast_expression
|
|||
|
||||
int fold_cond (ir_value *, ast_function *, ast_ifthen *);
|
||||
|
||||
/* intrin.c */
|
||||
intrin_t *intrin_init (parser_t *parser);
|
||||
void intrin_cleanup (intrin_t *intrin);
|
||||
ast_expression *intrin_func (intrin_t *intrin, const char *name);
|
||||
ast_expression *intrin_debug_typestring(intrin_t *intrin);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue