const char *alias;
} intrin_t;
-ht intrin_intrinsics() {
+static ht intrin_intrinsics(void) {
static ht intrinsics = NULL;
if (!intrinsics)
intrinsics = util_htnew(PARSER_HT_SIZE);
return intrinsics;
}
-void intrin_intrinsics_destroy() {
- util_htdel(intrin_intrinsics());
-}
-
#define INTRIN_VAL(VALUE, NAME, FUNC, STYPE, VTYPE) \
do { \
(VALUE) = ast_value_new ( \
vec_push(parser->globals, (ast_expression*)(VALUE)); \
} while (0)
-
-ast_expression *intrin_func (parser_t *parser, const char *name);
-
#define QC_M_E 2.71828182845905
-ast_expression *intrin_pow(parser_t *parser) {
+static ast_expression *intrin_func(parser_t *parser, const char *name);
+static ast_expression *intrin_pow (parser_t *parser) {
+ /*
+ * float pow(float x, float y) {
+ * float local = 1.0f;
+ * while (y > 0) {
+ * while (!(y & 1)) {
+ * y >>= 2;
+ * x *= x;
+ * }
+ * y--;
+ * local *= x;
+ * }
+ * return local;
+ * }
+ */
static ast_value *value = NULL;
if (!value) {
parser_ctx(parser),
INSTR_STORE_F,
(ast_expression*)local,
- (ast_expression*)parser_const_float_1(parser)
+ (ast_expression*)parser->fold->imm_float[1] /* 1 == 1.0f */
)
);
INSTR_STORE_F,
INSTR_MUL_F,
(ast_expression*)arg2,
- (ast_expression*)parser_const_float(parser, 0.25f)
+ (ast_expression*)fold_constgen_float(parser->fold, 0.25f)
)
);
parser_ctx(parser),
INSTR_AND,
(ast_expression*)arg2,
- (ast_expression*)parser_const_float_1(parser)
+ (ast_expression*)parser->fold->imm_float[1] /* 1 == 1.0f */
),
true, /* ! not */
NULL,
INSTR_STORE_F,
INSTR_SUB_F,
(ast_expression*)arg2,
- (ast_expression*)parser_const_float_1(parser)
+ (ast_expression*)parser->fold->imm_float[1] /* 1 == 1.0f */
)
);
/* local *= x */
parser_ctx(parser),
INSTR_GT,
(ast_expression*)arg2,
- (ast_expression*)parser_const_float_0(parser)
+ (ast_expression*)parser->fold->imm_float[0] /* 0 == 0.0f */
),
false,
NULL,
return (ast_expression*)value;
}
-ast_expression *intrin_mod(parser_t *parser) {
+static ast_expression *intrin_mod(parser_t *parser) {
+ /*
+ * float mod(float x, float y) {
+ * return x - y * floor(x / y);
+ * }
+ */
static ast_value *value = NULL;
if (!value) {
return (ast_expression*)value;
}
-ast_expression *intrin_exp(parser_t *parser) {
+static ast_expression *intrin_exp(parser_t *parser) {
/*
- * float __builtin_exp(float x) {
- * return __builtin_pow(QC_M_E, x);
+ * float exp(float x) {
+ * return pow(QC_M_E, x);
* }
*/
static ast_value *value = NULL;
INTRIN_VAL(value, "exp", func, "<float>", TYPE_FLOAT);
/* push arguments for params to call */
- vec_push(call->params, (ast_expression*)parser_const_float(parser, QC_M_E));
+ vec_push(call->params, (ast_expression*)fold_constgen_float(parser->fold, QC_M_E));
vec_push(call->params, (ast_expression*)arg1);
/* return pow(QC_M_E, x) */
return (ast_expression*)value;
}
+static ast_expression *intrin_isnan(parser_t *parser) {
+ /*
+ * float isnan(float x) {
+ * float local;
+ * local = x;
+ *
+ * return (x != local);
+ * }
+ */
+ 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_function *func = NULL;
+
+ INTRIN_VAL(value, "isnan", func, "<float>", TYPE_FLOAT);
+
+ vec_push(body->locals, local);
+ vec_push(body->exprs,
+ (ast_expression*)ast_store_new(
+ parser_ctx(parser),
+ INSTR_STORE_F,
+ (ast_expression*)local,
+ (ast_expression*)arg1
+ )
+ );
+
+ vec_push(body->exprs,
+ (ast_expression*)ast_return_new(
+ parser_ctx(parser),
+ (ast_expression*)ast_binary_new(
+ parser_ctx(parser),
+ INSTR_NE_F,
+ (ast_expression*)arg1,
+ (ast_expression*)local
+ )
+ )
+ );
+
+ vec_push(value->expression.params, arg1);
+
+ vec_push(func->blocks, body);
+
+ INTRIN_REG(func, value);
+ }
+
+ return (ast_expression*)value;
+}
+
static intrin_t intrinsics[] = {
- {&intrin_exp, "__builtin_exp", "exp"},
- {&intrin_mod, "__builtin_mod", "mod"},
- {&intrin_pow, "__builtin_pow", "pow"}
+ {&intrin_exp, "__builtin_exp", "exp"},
+ {&intrin_mod, "__builtin_mod", "mod"},
+ {&intrin_pow, "__builtin_pow", "pow"},
+ {&intrin_isnan, "__builtin_isnan", "isnan"}
};
-ast_expression *intrin_func(parser_t *parser, const char *name) {
+void intrin_intrinsics_destroy(parser_t *parser) {
+ /*size_t i;*/
+ (void)parser;
+ util_htdel(intrin_intrinsics());
+#if 0
+ for (i = 0; i < sizeof(intrinsics)/sizeof(intrin_t); i++)
+ ast_value_delete( (ast_value*) intrinsics[i].intrin(parser));
+#endif
+}
+
+
+static ast_expression *intrin_func(parser_t *parser, const char *name) {
static bool init = false;
size_t i = 0;
void *find;
/*
* jesus fucking christ, Blub design something less fucking
* impossible to use, like a ast_is_builtin(ast_expression *), also
- * use a hashtable :P
- */
+ * 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)
- return find;
+ return (ast_expression*)find;
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);
}