if (!self) { \
return NULL; \
} \
- ast_node_init((ast_node*)self, ctx); \
+ ast_node_init((ast_node*)self, ctx, TYPE_##T); \
( (ast_node*)self )->node.destroy = (ast_node_delete*)destroyfn
/* It must not be possible to get here. */
}
/* Initialize main ast node aprts */
-static void ast_node_init(ast_node *self, lex_ctx ctx)
+static void ast_node_init(ast_node *self, lex_ctx ctx, int nodetype)
{
self->node.context = ctx;
self->node.destroy = &_ast_node_destroy;
self->node.keep = false;
+ self->node.nodetype = nodetype;
}
/* General expression initialization */
typedef struct ast_unary_s ast_unary;
typedef struct ast_return_s ast_return;
+enum {
+ TYPE_ast_node,
+ TYPE_ast_expression,
+ TYPE_ast_value,
+ TYPE_ast_function,
+ TYPE_ast_block,
+ TYPE_ast_binary,
+ TYPE_ast_store,
+ TYPE_ast_entfield,
+ TYPE_ast_ifthen,
+ TYPE_ast_ternary,
+ TYPE_ast_loop,
+ TYPE_ast_call,
+ TYPE_ast_unary,
+ TYPE_ast_return
+};
+
+#define ast_istype(x, t) ( ((ast_node_common*)x)->nodetype == (t) )
+
/* Node interface with common components
*/
typedef void ast_node_delete(ast_node*);
lex_ctx context;
/* I don't feel comfortable using keywords like 'delete' as names... */
ast_node_delete *destroy;
+ int nodetype;
/* keep: if a node contains this node, 'keep'
* prevents its dtor from destroying this node as well.
*/
VECTOR_MAKE(int, code_globals );
VECTOR_MAKE(char, code_chars );
+uint32_t code_entfields;
+
void code_init() {
prog_section_function empty_function = {0,0,0,0,0,0,0,{0}};
prog_section_statement empty_statement = {0,{0},{0},{0}};
code_chars_add ('\0');
code_functions_add (empty_function);
code_statements_add(empty_statement);
+
+ code_entfields = 0;
}
uint32_t code_genstring(const char *str)
code_statements_add(s3);
}
+qcint code_alloc_field (size_t qcsize)
+{
+ qcint pos = (qcint)code_entfields;
+ code_entfields += qcsize;
+ return pos;
+}
+
bool code_write(const char *filename) {
prog_header code_header;
FILE *fp = NULL;
code_header.strings.length = code_chars_elements;
code_header.version = 6;
code_header.crc16 = 0; /* TODO: */
- code_header.entfield = 0; /* TODO: */
+ code_header.entfield = code_entfields;
if (OPTS_FLAG(DARKPLACES_STRING_TABLE_BUG)) {
util_debug("GEN", "Patching stringtable for -fdarkplaces-stringtablebug\n");
while (N##_add(*++elements) != -1 && len--); \
return N##_elements; \
} \
- typedef char VECTOR_FILL(extra_semicolon_,__COUNTER__)
+ typedef char VECTOR_FILL(extra_semicolon_##N,__COUNTER__)
#define VECTOR_PROT(T,N) \
extern T* N##_data ; \
extern long N##_elements ; \
VECTOR_PROT(int, code_globals );
VECTOR_PROT(char, code_chars );
+typedef float qcfloat;
+typedef int32_t qcint;
+
/*
* code_write -- writes out the compiled file
* code_init -- prepares the code file
void code_init ();
uint32_t code_genstring (const char *string);
uint32_t code_cachedstring(const char *string);
+qcint code_alloc_field (size_t qcsize);
/*===================================================================*/
/*========================= assembler.c =============================*/
* Since we may want to support that as well, let's redefine
* float and int here.
*/
-typedef float qcfloat;
-typedef int32_t qcint;
-
typedef union {
qcint _int;
qcint string;
MEM_VECTOR_INIT(self, functions);
MEM_VECTOR_INIT(self, globals);
+ MEM_VECTOR_INIT(self, fields);
self->name = NULL;
if (!ir_builder_set_name(self, modulename)) {
mem_d(self);
}
MEM_VEC_FUNCTIONS(ir_builder, ir_value*, globals)
+MEM_VEC_FUNCTIONS(ir_builder, ir_value*, fields)
MEM_VEC_FUNCTIONS(ir_builder, ir_function*, functions)
void ir_builder_delete(ir_builder* self)
for (i = 0; i != self->globals_count; ++i) {
ir_value_delete(self->globals[i]);
}
- MEM_VECTOR_CLEAR(self, globals);
+ MEM_VECTOR_CLEAR(self, fields);
+ for (i = 0; i != self->fields_count; ++i) {
+ ir_value_delete(self->fields[i]);
+ }
+ MEM_VECTOR_CLEAR(self, fields);
mem_d(self);
}
return ve;
}
+ir_value* ir_builder_get_field(ir_builder *self, const char *name)
+{
+ size_t i;
+ for (i = 0; i < self->fields_count; ++i) {
+ if (!strcmp(self->fields[i]->name, name))
+ return self->fields[i];
+ }
+ return NULL;
+}
+
+
+ir_value* ir_builder_create_field(ir_builder *self, const char *name, int vtype)
+{
+ ir_value *ve = ir_builder_get_field(self, name);
+ if (ve) {
+ return NULL;
+ }
+
+ ve = ir_value_var(name, store_global, TYPE_FIELD);
+ ve->fieldtype = vtype;
+ if (!ir_builder_fields_add(self, ve)) {
+ ir_value_delete(ve);
+ return NULL;
+ }
+ return ve;
+}
+
/***********************************************************************
*IR Function
*/
ir_value* ir_block_create_fieldaddress(ir_block *self, const char *label, ir_value *ent, ir_value *field)
{
+ ir_value *v;
+
/* Support for various pointer types todo if so desired */
if (ent->vtype != TYPE_ENTITY)
return NULL;
if (field->vtype != TYPE_FIELD)
return NULL;
- return ir_block_create_general_instr(self, label, INSTR_ADDRESS, ent, field, TYPE_POINTER);
+ v = ir_block_create_general_instr(self, label, INSTR_ADDRESS, ent, field, TYPE_POINTER);
+ v->fieldtype = field->fieldtype;
+ return v;
}
ir_value* ir_block_create_load_from_ent(ir_block *self, const char *label, ir_value *ent, ir_value *field, int outype)
}
else
{
- prog_section_field fld;
-
- fld.name = global->code.name;
- fld.offset = code_fields_elements;
- fld.type = global->fieldtype;
-
- if (fld.type == TYPE_VOID) {
- printf("Field is missing a type: %s\n", global->name);
- return false;
- }
-
- if (code_fields_add(fld) < 0)
- return false;
-
- global->code.globaladdr = code_globals_add(fld.offset);
+ global->code.globaladdr = code_globals_add(0);
}
if (global->code.globaladdr < 0)
return false;
}
}
+static bool ir_builder_gen_field(ir_builder *self, ir_value *field)
+{
+ prog_section_def def;
+ prog_section_field fld;
+
+ def.type = field->vtype;
+ def.offset = code_globals_elements;
+ def.name = field->code.name = code_genstring(field->name);
+
+ if (code_defs_add(def) < 0)
+ return false;
+
+ fld.name = def.name;
+ fld.offset = code_fields_elements;
+ fld.type = field->fieldtype;
+
+ if (fld.type == TYPE_VOID) {
+ printf("field is missing a type: %s - don't know its size\n", field->name);
+ return false;
+ }
+
+ if (code_fields_add(fld) < 0)
+ return false;
+
+ if (!code_globals_add(code_alloc_field(type_sizeof[field->fieldtype])))
+ return false;
+
+ field->code.globaladdr = code_globals_add(fld.offset);
+ return field->code.globaladdr >= 0;
+}
+
bool ir_builder_generate(ir_builder *self, const char *filename)
{
size_t i;
code_init();
+ for (i = 0; i < self->fields_count; ++i)
+ {
+ if (!ir_builder_gen_field(self, self->fields[i])) {
+ return false;
+ }
+ }
+
for (i = 0; i < self->globals_count; ++i)
{
if (!ir_builder_gen_global(self, self->globals[i])) {
char *name;
MEM_VECTOR_MAKE(ir_function*, functions);
MEM_VECTOR_MAKE(ir_value*, globals);
+ MEM_VECTOR_MAKE(ir_value*, fields);
} ir_builder;
ir_builder* ir_builder_new(const char *modulename);
MEM_VECTOR_PROTO(ir_builder, ir_function*, functions);
MEM_VECTOR_PROTO(ir_builder, ir_value*, globals);
+MEM_VECTOR_PROTO(ir_builder, ir_value*, fields);
ir_function* ir_builder_get_function(ir_builder*, const char *fun);
ir_function* ir_builder_create_function(ir_builder*, const char *name, int outtype);
ir_value* ir_builder_get_global(ir_builder*, const char *fun);
ir_value* ir_builder_create_global(ir_builder*, const char *name, int vtype);
+ir_value* ir_builder_get_field(ir_builder*, const char *fun);
+ir_value* ir_builder_create_field(ir_builder*, const char *name, int vtype);
bool ir_builder_generate(ir_builder *self, const char *filename);
VECTOR_MAKE(ast_value*, globals);
VECTOR_MAKE(ast_function*, functions);
+uint32_t opts_flags[1 + (COUNT_FLAGS / 32)];
+uint32_t opts_warn [1 + (COUNT_WARNINGS / 32)];
+
+uint32_t opts_O = 1;
+const char *opts_output = "progs.dat";
+int opts_standard = COMPILER_GMQCC;
+bool opts_debug = false;
+bool opts_memchk = false;
+
#include "ast-macros.h"
int main()