ast conversion mostly finished

This commit is contained in:
Wolfgang Bumiller 2015-01-30 18:59:48 +01:00
parent 9335bc2f4f
commit 45236a644f
8 changed files with 2139 additions and 2223 deletions

1925
ast.cpp

File diff suppressed because it is too large Load diff

221
ast.h
View file

@ -95,10 +95,6 @@ enum {
#define ast_istype(x, t) ( (x)->m_node_type == (TYPE_##t) )
/* Node interface with common components
*/
typedef void ast_node_delete(ast_node*);
struct ast_node
{
ast_node() = delete;
@ -114,7 +110,7 @@ struct ast_node
bool m_keep_node;
bool m_side_effects;
void propagate_side_effects(ast_node *other) const;
void propagateSideEffects(ast_node *other) const;
};
#define ast_unref(x) do \
@ -127,15 +123,6 @@ struct ast_node
enum class ast_copy_type_t { value };
static const ast_copy_type_t ast_copy_type = ast_copy_type_t::value;
/* Expression interface
*
* Any expression or block returns an ir_value, and needs
* to know the current function.
*/
typedef bool ast_expression_codegen(ast_expression*,
ast_function*,
bool lvalue,
ir_value**);
/* TODO: the codegen function should take an output-type parameter
* indicating whether a variable, type, label etc. is expected, and
* an environment!
@ -151,13 +138,16 @@ struct ast_expression : ast_node {
ast_expression(lex_ctx_t ctx, int nodetype, qc_type vtype);
ast_expression(lex_ctx_t ctx, int nodetype);
~ast_expression();
ast_expression(ast_copy_type_t, int nodetype, const ast_expression&);
ast_expression(ast_copy_type_t, const ast_expression&);
ast_expression(ast_copy_type_t, lex_ctx_t ctx, const ast_expression&);
ast_expression(ast_copy_type_t, int nodetype, const ast_expression&);
ast_expression(ast_copy_type_t, int nodetype, lex_ctx_t ctx, const ast_expression&);
static ast_expression *shallow_type(lex_ctx_t ctx, qc_type vtype);
static ast_expression *shallowType(lex_ctx_t ctx, qc_type vtype);
bool compare_type(const ast_expression &other) const;
void adopt_type(const ast_expression &other);
bool compareType(const ast_expression &other) const;
void adoptType(const ast_expression &other);
qc_type m_vtype = TYPE_VOID;
ast_expression *m_next = nullptr;
@ -177,6 +167,8 @@ struct ast_expression : ast_node {
*/
ir_value *m_outl = nullptr;
ir_value *m_outr = nullptr;
virtual bool codegen(ast_function *current, bool lvalue, ir_value **out);
};
/* Value
@ -206,7 +198,13 @@ struct ast_value : ast_expression
ast_value(ast_copy_type_t, const ast_value&);
ast_value(ast_copy_type_t, const ast_value&, const std::string&);
void add_param(ast_value*);
bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
void addParam(ast_value*);
bool generateGlobal(ir_builder*, bool isfield);
bool generateLocal(ir_function*, bool param);
bool generateAccessors(ir_builder*);
std::string m_name;
std::string m_desc;
@ -229,18 +227,22 @@ struct ast_value : ast_expression
size_t m_uses = 0;
ir_value *m_ir_v = nullptr;
ir_value **m_ir_values = nullptr;
std::vector<ir_value*> m_ir_values;
size_t m_ir_value_count = 0;
/* ONLY for arrays in progs version up to 6 */
ast_value *m_setter = nullptr;
ast_value *m_getter = nullptr;
bool m_intrinsic = false; /* true if associated with intrinsic */
};
bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield);
private:
bool generateGlobalFunction(ir_builder*);
bool generateGlobalField(ir_builder*);
ir_value *prepareGlobalArray(ir_builder*);
bool setGlobalArray();
bool checkArray(const ast_value &array) const;
};
void ast_type_to_string(const ast_expression *e, char *buf, size_t bufsize);
@ -262,6 +264,8 @@ struct ast_binary : ast_expression
ast_binary(lex_ctx_t ctx, int op, ast_expression *l, ast_expression *r);
~ast_binary();
bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
int m_op;
ast_expression *m_left;
ast_expression *m_right;
@ -280,6 +284,8 @@ struct ast_binstore : ast_expression
ast_binstore(lex_ctx_t ctx, int storeop, int mathop, ast_expression *l, ast_expression *r);
~ast_binstore();
bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
int m_opstore;
int m_opbin;
ast_expression *m_dest;
@ -287,11 +293,6 @@ struct ast_binstore : ast_expression
/* for &~= which uses the destination in a binary in source we can use this */
bool m_keep_dest;
};
ast_binstore* ast_binstore_new(lex_ctx_t ctx,
int storeop,
int op,
ast_expression *left,
ast_expression *right);
/* Unary
*
@ -301,9 +302,14 @@ struct ast_unary : ast_expression
{
ast_unary() = delete;
~ast_unary();
static ast_unary* make(lex_ctx_t ctx, int op, ast_expression *expr);
bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
int m_op;
ast_expression *m_operand;
static ast_unary* make(lex_ctx_t ctx, int op, ast_expression *expr);
private:
ast_unary(lex_ctx_t ctx, int op, ast_expression *expr);
};
@ -319,6 +325,9 @@ struct ast_return : ast_expression
ast_return() = delete;
ast_return(lex_ctx_t ctx, ast_expression *expr);
~ast_return();
bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
ast_expression *m_operand;
};
@ -341,6 +350,9 @@ struct ast_entfield : ast_expression
ast_entfield(lex_ctx_t ctx, ast_expression *entity, ast_expression *field);
ast_entfield(lex_ctx_t ctx, ast_expression *entity, ast_expression *field, const ast_expression *outtype);
~ast_entfield();
bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
// The entity can come from an expression of course.
ast_expression *m_entity;
// As can the field, it just must result in a value of TYPE_FIELD
@ -357,6 +369,8 @@ struct ast_member : ast_expression
static ast_member *make(lex_ctx_t ctx, ast_expression *owner, unsigned int field, const std::string &name);
~ast_member();
bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
ast_expression *m_owner;
unsigned int m_field;
std::string m_name;
@ -381,6 +395,9 @@ struct ast_array_index : ast_expression
{
static ast_array_index* make(lex_ctx_t ctx, ast_expression *array, ast_expression *index);
~ast_array_index();
bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
ast_expression *m_array;
ast_expression *m_index;
private:
@ -396,6 +413,9 @@ struct ast_argpipe : ast_expression
{
ast_argpipe() = delete;
ast_argpipe(lex_ctx_t ctx, ast_expression *index);
bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
~ast_argpipe();
ast_expression *m_index;
};
@ -410,6 +430,9 @@ struct ast_store : ast_expression
ast_store() = delete;
ast_store(lex_ctx_t ctx, int op, ast_expression *d, ast_expression *s);
~ast_store();
bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
int m_op;
ast_expression *m_dest;
ast_expression *m_source;
@ -431,6 +454,9 @@ struct ast_ifthen : ast_expression
ast_ifthen() = delete;
ast_ifthen(lex_ctx_t ctx, ast_expression *cond, ast_expression *ontrue, ast_expression *onfalse);
~ast_ifthen();
bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
ast_expression *m_cond;
/* It's all just 'expressions', since an ast_block is one too. */
ast_expression *m_on_true;
@ -455,6 +481,9 @@ struct ast_ternary : ast_expression
ast_ternary() = delete;
ast_ternary(lex_ctx_t ctx, ast_expression *cond, ast_expression *ontrue, ast_expression *onfalse);
~ast_ternary();
bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
ast_expression *m_cond;
/* It's all just 'expressions', since an ast_block is one too. */
ast_expression *m_on_true;
@ -494,6 +523,9 @@ struct ast_loop : ast_expression
ast_expression *increment,
ast_expression *body);
~ast_loop();
bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
ast_expression *m_initexpr;
ast_expression *m_precond;
ast_expression *m_postcond;
@ -513,10 +545,16 @@ struct ast_loop : ast_expression
*/
struct ast_breakcont : ast_expression
{
ast_breakcont() = delete;
ast_breakcont(lex_ctx_t ctx, bool iscont, unsigned int levels);
~ast_breakcont();
bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
bool m_is_continue;
unsigned int m_levels;
};
ast_breakcont* ast_breakcont_new(lex_ctx_t ctx, bool iscont, unsigned int levels);
/* Switch Statements
*
@ -535,11 +573,16 @@ struct ast_switch_case {
struct ast_switch : ast_expression
{
ast_switch() = delete;
ast_switch(lex_ctx_t ctx, ast_expression *op);
~ast_switch();
bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
ast_expression *m_operand;
std::vector<ast_switch_case> m_cases;
};
ast_switch* ast_switch_new(lex_ctx_t ctx, ast_expression *op);
/* Label nodes
*
@ -547,15 +590,23 @@ ast_switch* ast_switch_new(lex_ctx_t ctx, ast_expression *op);
*/
struct ast_label : ast_expression
{
const char *m_name;
ast_label() = delete;
ast_label(lex_ctx_t ctx, const std::string &name, bool undefined);
~ast_label();
bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
std::string m_name;
ir_block *m_irblock;
std::vector<ast_goto*> m_gotos;
/* means it has not yet been defined */
bool m_undefined;
};
ast_label* ast_label_new(lex_ctx_t ctx, const char *name, bool undefined);
private:
void registerGoto(ast_goto*);
friend struct ast_goto;
};
/* GOTO nodes
*
@ -563,25 +614,34 @@ ast_label* ast_label_new(lex_ctx_t ctx, const char *name, bool undefined);
*/
struct ast_goto : ast_expression
{
const char *m_name;
ast_goto() = delete;
ast_goto(lex_ctx_t ctx, const std::string &name);
~ast_goto();
bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
void setLabel(ast_label*);
std::string m_name;
ast_label *m_target;
ir_block *m_irblock_from;
};
ast_goto* ast_goto_new(lex_ctx_t ctx, const char *name);
void ast_goto_set_label(ast_goto*, ast_label*);
/* STATE node
*
* For frame/think state updates: void foo() [framenum, nextthink] {}
*/
struct ast_state : ast_expression
{
ast_state() = delete;
ast_state(lex_ctx_t ctx, ast_expression *frame, ast_expression *think);
~ast_state();
bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
ast_expression *m_framenum;
ast_expression *m_nextthink;
};
ast_state* ast_state_new(lex_ctx_t ctx, ast_expression *frame, ast_expression *think);
void ast_state_delete(ast_state*);
/* CALL node
*
@ -595,29 +655,42 @@ void ast_state_delete(ast_state*);
*/
struct ast_call : ast_expression
{
ast_call() = delete;
static ast_call *make(lex_ctx_t, ast_expression*);
~ast_call();
bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
bool checkTypes(ast_expression *this_func_va_type) const;
ast_expression *m_func;
std::vector<ast_expression *> m_params;
ast_expression *m_va_count;
private:
ast_call(lex_ctx_t ctx, ast_expression *funcexpr);
bool checkVararg(ast_expression *va_type, ast_expression *exp_type) const;
};
ast_call* ast_call_new(lex_ctx_t ctx,
ast_expression *funcexpr);
bool ast_call_check_types(ast_call*, ast_expression *this_func_va_type);
/* Blocks
*
*/
struct ast_block : ast_expression
{
ast_block() = delete;
ast_block(lex_ctx_t ctx);
~ast_block();
bool codegen(ast_function *current, bool lvalue, ir_value **out) override;
std::vector<ast_value*> m_locals;
std::vector<ast_expression*> m_exprs;
std::vector<ast_expression*> m_collect;
};
ast_block* ast_block_new(lex_ctx_t ctx);
void ast_block_delete(ast_block*);
void ast_block_set_type(ast_block*, ast_expression *from);
void ast_block_collect(ast_block*, ast_expression*);
bool GMQCC_WARN ast_block_add_expr(ast_block*, ast_expression*);
void setType(const ast_expression &from);
bool GMQCC_WARN addExpr(ast_expression*);
void collect(ast_expression*);
};
/* Function
*
@ -628,49 +701,53 @@ bool GMQCC_WARN ast_block_add_expr(ast_block*, ast_expression*);
* neither functions inside functions, nor lambdas, and function
* pointers could just work with a name. However, this way could be
* more flexible, and adds no real complexity.
*
* The destructor will NOT delete the underlying ast_value
*
*/
struct ast_function : ast_node
{
ast_value *m_function_type;
const char *m_name;
ast_function() = delete;
static ast_function *make(lex_ctx_t ctx, const std::string &name, ast_value *vtype);
~ast_function();
int m_builtin;
const char* makeLabel(const char *prefix);
virtual bool generateFunction(ir_builder*);
ast_value *m_function_type = nullptr;
std::string m_name;
int m_builtin = 0;
/* list of used-up names for statics without the count suffix */
std::vector<char*> m_static_names;
std::vector<std::string> m_static_names;
/* number of static variables, by convention this includes the
* ones without the count-suffix - remember this when dealing
* with savegames. uint instead of size_t as %zu in printf is
* C99, so no windows support. */
unsigned int m_static_count;
unsigned int m_static_count = 0;
ir_function *m_ir_func;
ir_block *m_curblock;
ir_function *m_ir_func = nullptr;
ir_block *m_curblock = nullptr;
std::vector<ir_block*> m_breakblocks;
std::vector<ir_block*> m_continueblocks;
size_t m_labelcount;
size_t m_labelcount = 0;
/* in order for thread safety - for the optional
* channel abesed multithreading... keeping a buffer
* here to use in ast_function_label.
*/
char m_labelbuf[64];
std::vector<std::unique_ptr<ast_block>> m_blocks;
ast_value *m_varargs;
ast_value *m_argc;
ast_value *m_fixedparams;
ast_value *m_return_value;
};
ast_function* ast_function_new(lex_ctx_t ctx, const char *name, ast_value *vtype);
/* This will NOT delete the underlying ast_value */
void ast_function_delete(ast_function*);
/* For "optimized" builds this can just keep returning "foo"...
* or whatever...
*/
const char* ast_function_label(ast_function*, const char *prefix);
std::unique_ptr<ast_value> m_varargs;
std::unique_ptr<ast_value> m_argc;
ast_value *m_fixedparams = nullptr; // these use unref()
ast_value *m_return_value = nullptr;
bool ast_function_codegen(ast_function *self, ir_builder *builder);
bool ast_generate_accessors(ast_value *asvalue, ir_builder *ir);
private:
ast_function(lex_ctx_t ctx, const std::string &name, ast_value *vtype);
char m_labelbuf[64];
};
/*
* If the condition creates a situation where this becomes -1 size it means there are

View file

@ -176,7 +176,7 @@ void vcompile_error(lex_ctx_t ctx, const char *msg, va_list ap)
con_cvprintmsg(ctx, LVL_ERROR, "error", msg, ap);
}
void compile_error(lex_ctx_t ctx, const char *msg, ...)
void compile_error_(lex_ctx_t ctx, const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
@ -215,7 +215,7 @@ bool GMQCC_WARN vcompile_warning(lex_ctx_t ctx, int warntype, const char *fmt, v
return OPTS_WERROR(warntype) && OPTS_FLAG(BAIL_ON_WERROR);
}
bool GMQCC_WARN compile_warning(lex_ctx_t ctx, int warntype, const char *fmt, ...)
bool GMQCC_WARN compile_warning_(lex_ctx_t ctx, int warntype, const char *fmt, ...)
{
bool r;
va_list ap;

View file

@ -931,14 +931,14 @@ bool fold::generate(ir_builder *ir) {
// generate globals for immediate folded values
ast_value *cur;
for (auto &it : m_imm_float)
if (!ast_global_codegen((cur = it), ir, false)) goto err;
if (!(cur = it)->generateGlobal(ir, false)) goto err;
for (auto &it : m_imm_vector)
if (!ast_global_codegen((cur = it), ir, false)) goto err;
if (!(cur = it)->generateGlobal(ir, false)) goto err;
for (auto &it : m_imm_string)
if (!ast_global_codegen((cur = it), ir, false)) goto err;
if (!(cur = it)->generateGlobal(ir, false)) goto err;
return true;
err:
con_out("failed to generate global %s\n", cur->m_name);
con_out("failed to generate global %s\n", cur->m_name.c_str());
delete ir;
return false;
}
@ -960,7 +960,7 @@ ast_expression *fold::constgen_float(qcfloat_t value, bool inexact) {
if (!memcmp(&it->m_constval.vfloat, &value, sizeof(qcfloat_t)))
return (ast_expression*)it;
ast_value *out = ast_value_new(ctx(), "#IMMEDIATE", TYPE_FLOAT);
ast_value *out = new ast_value(ctx(), "#IMMEDIATE", TYPE_FLOAT);
out->m_cvq = CV_CONST;
out->m_hasvalue = true;
out->m_inexact = inexact;
@ -976,7 +976,7 @@ ast_expression *fold::constgen_vector(vec3_t value) {
if (vec3_cmp(it->m_constval.vvec, value))
return (ast_expression*)it;
ast_value *out = ast_value_new(ctx(), "#IMMEDIATE", TYPE_VECTOR);
ast_value *out = new ast_value(ctx(), "#IMMEDIATE", TYPE_VECTOR);
out->m_cvq = CV_CONST;
out->m_hasvalue = true;
out->m_constval.vvec = value;
@ -997,10 +997,10 @@ ast_expression *fold::constgen_string(const char *str, bool translate) {
if (translate) {
char name[32];
util_snprintf(name, sizeof(name), "dotranslate_%zu", m_parser->translated++);
out = ast_value_new(ctx(), name, TYPE_STRING);
out = new ast_value(ctx(), name, TYPE_STRING);
out->m_flags |= AST_FLAG_INCLUDE_DEF; /* def needs to be included for translatables */
} else {
out = ast_value_new(ctx(), "#IMMEDIATE", TYPE_STRING);
out = new ast_value(ctx(), "#IMMEDIATE", TYPE_STRING);
}
out->m_cvq = CV_CONST;
@ -1014,6 +1014,10 @@ ast_expression *fold::constgen_string(const char *str, bool translate) {
return (ast_expression*)out;
}
ast_expression *fold::constgen_string(const std::string &str, bool translate) {
return constgen_string(str.c_str(), translate);
}
typedef union {
void (*callback)(void);
sfloat_t (*binary)(sfloat_state_t *, sfloat_t, sfloat_t);
@ -1069,11 +1073,11 @@ ast_expression *fold::op_mul_vec(vec3_t vec, ast_value *sel, const char *set) {
if (!y && !z) {
ast_expression *out;
++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
out = (ast_expression*)ast_member_new(ctx(), (ast_expression*)sel, set[0]-'x', nullptr);
out = ast_member::make(ctx(), (ast_expression*)sel, set[0]-'x', nullptr);
out->m_keep_node = false;
((ast_member*)out)->m_rvalue = true;
if (x != -1.0f)
return (ast_expression*)ast_binary_new(ctx(), INSTR_MUL_F, constgen_float(x, false), out);
return new ast_binary(ctx(), INSTR_MUL_F, constgen_float(x, false), out);
}
return nullptr;
}
@ -1181,7 +1185,7 @@ ast_expression *fold::op_div(ast_value *a, ast_value *b) {
bool inexact = check_except_float(&sfloat_div, a, b);
return constgen_float(immvalue_float(a) / immvalue_float(b), inexact);
} else if (fold_can_1(b)) {
return (ast_expression*)ast_binary_new(
return new ast_binary(
ctx(),
INSTR_MUL_F,
(ast_expression*)a,
@ -1192,17 +1196,16 @@ ast_expression *fold::op_div(ast_value *a, ast_value *b) {
if (fold_can_2(a, b)) {
return constgen_vector(vec3_mulvf(ctx(), immvalue_vector(a), 1.0f / immvalue_float(b)));
} else {
return (ast_expression*)ast_binary_new(
return new ast_binary(
ctx(),
INSTR_MUL_VF,
(ast_expression*)a,
(fold_can_1(b))
? (ast_expression*)constgen_float(1.0f / immvalue_float(b), false)
: (ast_expression*)ast_binary_new(
ctx(),
INSTR_DIV_F,
(ast_expression*)m_imm_float[1],
(ast_expression*)b
: new ast_binary(ctx(),
INSTR_DIV_F,
(ast_expression*)m_imm_float[1],
(ast_expression*)b
)
);
}
@ -1600,12 +1603,11 @@ ast_expression *fold::binary(lex_ctx_t ctx, int op, ast_expression *left, ast_ex
ast_expression *ret = superfluous(left, right, op);
if (ret)
return ret;
return (ast_expression*)ast_binary_new(ctx, op, left, right);
return new ast_binary(ctx, op, left, right);
}
int fold::cond(ir_value *condval, ast_function *func, ast_ifthen *branch) {
if (isfloat(condval) && fold_can_1(condval) && OPTS_OPTIMIZATION(OPTIM_CONST_FOLD_DCE)) {
ast_expression_codegen *cgen;
ir_block *elide;
ir_value *dummy;
bool istrue = (immvalue_float(condval) != 0.0f && branch->m_on_true);
@ -1621,9 +1623,9 @@ int fold::cond(ir_value *condval, ast_function *func, ast_ifthen *branch) {
return true;
}
if (!(elide = ir_function_create_block(branch->m_context, func->m_ir_func, ast_function_label(func, ((istrue) ? "ontrue" : "onfalse")))))
if (!(elide = ir_function_create_block(branch->m_context, func->m_ir_func, func->makeLabel((istrue) ? "ontrue" : "onfalse"))))
return false;
if (!(*(cgen = path->m_codegen))((ast_expression*)path, func, false, &dummy))
if (!path->codegen(func, false, &dummy))
return false;
if (!ir_block_create_jump(func->m_curblock, branch->m_context, elide))
return false;

1
fold.h
View file

@ -32,6 +32,7 @@ struct fold {
ast_expression *constgen_float(qcfloat_t value, bool inexact);
ast_expression *constgen_vector(vec3_t value);
ast_expression *constgen_string(const char *str, bool translate);
ast_expression *constgen_string(const std::string &str, bool translate);
ast_value *imm_float(size_t index) const { return m_imm_float[index]; }
ast_value *imm_vector(size_t index) const { return m_imm_vector[index]; }

20
gmqcc.h
View file

@ -589,12 +589,28 @@ extern size_t compile_errors;
extern size_t compile_Werrors;
extern size_t compile_warnings;
void /********/ compile_error (lex_ctx_t ctx, /*LVL_ERROR*/ const char *msg, ...);
void /********/ compile_error_ (lex_ctx_t ctx, /*LVL_ERROR*/ const char *msg, ...);
void /********/ vcompile_error (lex_ctx_t ctx, /*LVL_ERROR*/ const char *msg, va_list ap);
bool GMQCC_WARN compile_warning (lex_ctx_t ctx, int warntype, const char *fmt, ...);
bool GMQCC_WARN compile_warning_(lex_ctx_t ctx, int warntype, const char *fmt, ...);
bool GMQCC_WARN vcompile_warning(lex_ctx_t ctx, int warntype, const char *fmt, va_list ap);
void compile_show_werrors(void);
template <typename T>
inline constexpr const T formatNormalize(const T argument) { return argument; }
inline const char *formatNormalize(const std::string &argument) {
return argument.c_str();
}
template<typename... Ts>
inline bool GMQCC_WARN compile_warning(lex_ctx_t ctx, int warntype, const char *fmt, const Ts&... ts) {
return compile_warning_(ctx, warntype, fmt, formatNormalize(ts)...);
}
template<typename... Ts>
inline void /********/ compile_error (lex_ctx_t ctx, /*LVL_ERROR*/ const char *msg, const Ts&... ts) {
return compile_error_(ctx, msg, formatNormalize(ts)...);
}
/* ir.c */
/* TODO: cleanup */
enum store_type {

1058
intrin.cpp

File diff suppressed because it is too large Load diff

1089
parser.cpp

File diff suppressed because it is too large Load diff