mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2025-02-20 18:32:01 +00:00
Merge branch 'master' into blub/bc3
This commit is contained in:
commit
ae251d3914
7 changed files with 131 additions and 24 deletions
5
ast.c
5
ast.c
|
@ -32,7 +32,7 @@
|
|||
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. */
|
||||
|
@ -43,11 +43,12 @@ static GMQCC_NORETURN void _ast_node_destroy(ast_node *self)
|
|||
}
|
||||
|
||||
/* 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 */
|
||||
|
|
20
ast.h
20
ast.h
|
@ -44,6 +44,25 @@ typedef struct ast_call_s ast_call;
|
|||
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*);
|
||||
|
@ -52,6 +71,7 @@ typedef struct
|
|||
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.
|
||||
*/
|
||||
|
|
13
code.c
13
code.c
|
@ -63,6 +63,8 @@ VECTOR_MAKE(prog_section_function, code_functions );
|
|||
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}};
|
||||
|
@ -82,6 +84,8 @@ void code_init() {
|
|||
code_chars_add ('\0');
|
||||
code_functions_add (empty_function);
|
||||
code_statements_add(empty_statement);
|
||||
|
||||
code_entfields = 0;
|
||||
}
|
||||
|
||||
uint32_t code_genstring(const char *str)
|
||||
|
@ -152,6 +156,13 @@ void code_test() {
|
|||
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;
|
||||
|
@ -173,7 +184,7 @@ bool code_write(const char *filename) {
|
|||
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");
|
||||
|
|
9
gmqcc.h
9
gmqcc.h
|
@ -253,7 +253,7 @@ uint32_t util_crc32(const char *, int, register const short);
|
|||
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 ; \
|
||||
|
@ -516,6 +516,9 @@ VECTOR_PROT(prog_section_function, code_functions );
|
|||
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
|
||||
|
@ -524,6 +527,7 @@ bool code_write (const char *filename);
|
|||
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 =============================*/
|
||||
|
@ -834,9 +838,6 @@ typedef struct {
|
|||
* 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;
|
||||
|
|
95
ir.c
95
ir.c
|
@ -115,6 +115,7 @@ ir_builder* ir_builder_new(const char *modulename)
|
|||
|
||||
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);
|
||||
|
@ -130,6 +131,7 @@ ir_builder* ir_builder_new(const char *modulename)
|
|||
}
|
||||
|
||||
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)
|
||||
|
@ -143,7 +145,11 @@ 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);
|
||||
}
|
||||
|
||||
|
@ -224,6 +230,33 @@ ir_value* ir_builder_create_global(ir_builder *self, const char *name, int vtype
|
|||
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
|
||||
*/
|
||||
|
@ -1284,6 +1317,8 @@ on_error:
|
|||
|
||||
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;
|
||||
|
@ -1291,7 +1326,9 @@ ir_value* ir_block_create_fieldaddress(ir_block *self, const char *label, ir_val
|
|||
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)
|
||||
|
@ -2105,21 +2142,7 @@ static bool gen_global_field(ir_value *global)
|
|||
}
|
||||
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;
|
||||
|
@ -2553,12 +2576,50 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global)
|
|||
}
|
||||
}
|
||||
|
||||
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])) {
|
||||
|
|
4
ir.h
4
ir.h
|
@ -290,6 +290,7 @@ typedef struct ir_builder_s
|
|||
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);
|
||||
|
@ -299,12 +300,15 @@ bool ir_builder_set_name(ir_builder *self, const char *name);
|
|||
|
||||
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);
|
||||
|
||||
|
|
|
@ -12,6 +12,15 @@
|
|||
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()
|
||||
|
|
Loading…
Reference in a new issue