temp committing major c++ification

This commit is contained in:
Wolfgang Bumiller 2015-01-20 16:43:58 +01:00
parent 794396df79
commit f09c6a5d63
11 changed files with 592 additions and 776 deletions

47
ast.cpp
View file

@ -151,7 +151,7 @@ void ast_type_adopt_impl(ast_expression *self, const ast_expression *other)
}
}
static ast_expression* ast_shallow_type(lex_ctx_t ctx, int vtype)
static ast_expression* ast_shallow_type(lex_ctx_t ctx, qc_type vtype)
{
ast_instantiate(ast_expression, ctx, ast_expression_delete_full);
ast_expression_init(self, nullptr);
@ -318,7 +318,7 @@ void ast_type_to_string(ast_expression *e, char *buf, size_t bufsize)
}
static bool ast_value_codegen(ast_value *self, ast_function *func, bool lvalue, ir_value **out);
ast_value* ast_value_new(lex_ctx_t ctx, const char *name, int t)
ast_value* ast_value_new(lex_ctx_t ctx, const char *name, qc_type t)
{
ast_instantiate(ast_value, ctx, ast_value_delete);
ast_expression_init((ast_expression*)self,
@ -1407,7 +1407,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
size_t namelen;
ast_expression *elemtype;
int vtype;
qc_type vtype;
ast_value *array = (ast_value*)fieldtype;
if (!ast_istype(fieldtype, ast_value)) {
@ -1480,7 +1480,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
size_t namelen;
ast_expression *elemtype = self->next;
int vtype = elemtype->vtype;
qc_type vtype = elemtype->vtype;
if (self->flags & AST_FLAG_ARRAY_INIT && !self->count) {
compile_error(ast_ctx(self), "array `%s' has no size", self->name);
@ -1595,7 +1595,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
return true;
error: /* clean up */
if(v) ir_value_delete(v);
if (v) delete v;
return false;
}
@ -1622,7 +1622,7 @@ static bool ast_local_codegen(ast_value *self, ir_function *func, bool param)
size_t namelen;
ast_expression *elemtype = self->next;
int vtype = elemtype->vtype;
qc_type vtype = elemtype->vtype;
func->flags |= IR_FLAG_HAS_ARRAYS;
@ -1710,7 +1710,7 @@ static bool ast_local_codegen(ast_value *self, ir_function *func, bool param)
return true;
error: /* clean up */
ir_value_delete(v);
delete v;
return false;
}
@ -1729,7 +1729,7 @@ bool ast_generate_accessors(ast_value *self, ir_builder *ir)
compile_error(ast_ctx(self), "internal error: not all array values have been generated for `%s`", self->name);
return false;
}
if (self->ir_values[i]->life) {
if (!self->ir_values[i]->life.empty()) {
compile_error(ast_ctx(self), "internal error: function containing `%s` already generated", self->name);
return false;
}
@ -1756,9 +1756,8 @@ bool ast_generate_accessors(ast_value *self, ir_builder *ir)
return false;
}
}
for (i = 0; i < self->count; ++i) {
vec_free(self->ir_values[i]->life);
}
for (i = 0; i < self->count; ++i)
self->ir_values[i]->life.clear();
opts_set(opts.warn, WARN_USED_UNINITIALIZED, warn);
return true;
}
@ -1867,7 +1866,7 @@ bool ast_function_codegen(ast_function *self, ir_builder *ir)
}
else if (compile_warning(ast_ctx(self), WARN_MISSING_RETURN_VALUES,
"control reaches end of non-void function (`%s`) via %s",
self->name, self->curblock->label))
self->name, self->curblock->label.c_str()))
{
return false;
}
@ -2069,7 +2068,7 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va
size_t merge_id;
/* prepare end-block */
merge_id = vec_size(func->ir_func->blocks);
merge_id = func->ir_func->blocks.size();
merge = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "sce_merge"));
/* generate the left expression */
@ -2106,8 +2105,8 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va
if (!ir_block_create_jump(func->curblock, ast_ctx(self), merge))
return false;
vec_remove(func->ir_func->blocks, merge_id, 1);
vec_push(func->ir_func->blocks, merge);
func->ir_func->blocks.erase(func->ir_func->blocks.begin() + merge_id);
func->ir_func->blocks.emplace_back(merge);
func->curblock = merge;
phi = ir_block_create_phi(func->curblock, ast_ctx(self),
@ -2868,7 +2867,7 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
bpostcond = end_bpostcond = nullptr;
}
bout_id = vec_size(func->ir_func->blocks);
bout_id = func->ir_func->blocks.size();
bout = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "after_loop"));
if (!bout)
return false;
@ -3012,8 +3011,8 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
}
/* Move 'bout' to the end */
vec_remove(func->ir_func->blocks, bout_id, 1);
vec_push(func->ir_func->blocks, bout);
func->ir_func->blocks.erase(func->ir_func->blocks.begin() + bout_id);
func->ir_func->blocks.emplace_back(bout);
return true;
}
@ -3096,7 +3095,7 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va
return false;
}
bout_id = vec_size(func->ir_func->blocks);
bout_id = func->ir_func->blocks.size();
bout = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "after_switch"));
if (!bout)
return false;
@ -3124,7 +3123,7 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va
return false;
bcase = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "case"));
bnot_id = vec_size(func->ir_func->blocks);
bnot_id = func->ir_func->blocks.size();
bnot = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "not_case"));
if (!bcase || !bnot)
return false;
@ -3152,8 +3151,8 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va
/* enter the else and move it down */
func->curblock = bnot;
vec_remove(func->ir_func->blocks, bnot_id, 1);
vec_push(func->ir_func->blocks, bnot);
func->ir_func->blocks.erase(func->ir_func->blocks.begin() + bnot_id);
func->ir_func->blocks.emplace_back(bnot);
} else {
/* The default case */
/* Remember where to fall through from: */
@ -3210,8 +3209,8 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va
func->breakblocks.pop_back();
/* Move 'bout' to the end, it's nicer */
vec_remove(func->ir_func->blocks, bout_id, 1);
vec_push(func->ir_func->blocks, bout);
func->ir_func->blocks.erase(func->ir_func->blocks.begin() + bout_id);
func->ir_func->blocks.emplace_back(bout);
return true;
}

16
ast.h
View file

@ -145,7 +145,7 @@ struct ast_expression : ast_node {
ast_expression() {}
ast_expression_codegen *codegen;
int vtype;
qc_type vtype;
ast_expression *next;
/* arrays get a member-count */
size_t count;
@ -173,13 +173,13 @@ struct ast_expression : ast_node {
* is like creating a 'float foo', foo serving as the type's name.
*/
union basic_value_t {
qcfloat_t vfloat;
int vint;
vec3_t vvec;
const char *vstring;
int ventity;
qcfloat_t vfloat;
int vint;
vec3_t vvec;
const char *vstring;
int ventity;
ast_function *vfunc;
ast_value *vfield;
ast_value *vfield;
};
struct ast_value : ast_expression
@ -216,7 +216,7 @@ struct ast_value : ast_expression
bool intrinsic; /* true if associated with intrinsic */
};
ast_value* ast_value_new(lex_ctx_t ctx, const char *name, int qctype);
ast_value* ast_value_new(lex_ctx_t ctx, const char *name, qc_type qctype);
ast_value* ast_value_copy(const ast_value *self);
/* This will NOT delete an underlying ast_function */
void ast_value_delete(ast_value*);

View file

@ -939,7 +939,7 @@ bool fold::generate(ir_builder *ir) {
return true;
err:
con_out("failed to generate global %s\n", cur->name);
ir_builder_delete(ir);
delete ir;
return false;
}

View file

@ -1,6 +1,10 @@
#ifndef GMQCC_HDR
#define GMQCC_HDR
#include <vector>
#include <string>
#include <utility>
#include <memory>
using std::move;
#include <stdarg.h>
#include <stddef.h>
#include <stdlib.h>
@ -259,7 +263,7 @@ int util_getline(char **, size_t *, FILE *);
/* code.c */
/* Note: if you change the order, fix type_sizeof in ir.c */
enum {
enum qc_type {
TYPE_VOID ,
TYPE_STRING ,
TYPE_FLOAT ,
@ -589,7 +593,7 @@ void compile_show_werrors(void);
/* ir.c */
/* TODO: cleanup */
enum store_types {
enum store_type {
store_global,
store_local, /* local, assignable for now, should get promoted later */
store_param, /* parameters, they are locals with a fixed position */

View file

@ -8,7 +8,7 @@ lex_ctx_t intrin::ctx() const {
return parser_ctx(m_parser);
}
ast_function *intrin::value(ast_value **out, const char *name, qcint_t vtype) {
ast_function *intrin::value(ast_value **out, const char *name, qc_type vtype) {
ast_value *value = nullptr;
ast_function *func = nullptr;
char buffer[1024];

View file

@ -30,7 +30,7 @@ struct intrin {
protected:
lex_ctx_t ctx() const;
ast_function *value(ast_value **out, const char *name, qcint_t vtype);
ast_function *value(ast_value **out, const char *name, qc_type vtype);
void reg(ast_value *const value, ast_function *const func);
ast_expression *nullfunc();

1091
ir.cpp

File diff suppressed because it is too large Load diff

168
ir.h
View file

@ -36,12 +36,19 @@ enum {
};
struct ir_value {
char *name;
int vtype;
int store;
ir_value(std::string&& name, store_type storetype, qc_type vtype);
~ir_value();
void* operator new(std::size_t); // to use mem_a
void operator delete(void*); // to use mem_d
std::string name;
qc_type vtype;
store_type store;
lex_ctx_t context;
int fieldtype; // even the IR knows the subtype of a field
int outtype; // and the output type of a function
qc_type fieldtype; // even the IR knows the subtype of a field
qc_type outtype; // and the output type of a function
int cvq; // 'const' vs 'var' qualifier
ir_flag_t flags;
@ -51,12 +58,12 @@ struct ir_value {
// constant values
bool hasvalue;
union {
qcfloat_t vfloat;
int vint;
vec3_t vvec;
int32_t ivec[3];
char *vstring;
ir_value *vpointer;
qcfloat_t vfloat;
int vint;
vec3_t vvec;
int32_t ivec[3];
char *vstring;
ir_value *vpointer;
ir_function *vfunc;
} constval;
@ -76,7 +83,7 @@ struct ir_value {
bool locked; // temps living during a CALL must be locked
bool callparam;
ir_life_entry_t *life; // For the temp allocator
std::vector<ir_life_entry_t> life; // For the temp allocator
};
/*
@ -84,7 +91,6 @@ struct ir_value {
* if a result of an operation: the function should store
* it to remember to delete it / garbage collect it
*/
void ir_value_delete(ir_value*);
ir_value* ir_value_vector_member(ir_value*, unsigned int member);
bool GMQCC_WARN ir_value_set_float(ir_value*, float f);
bool GMQCC_WARN ir_value_set_func(ir_value*, int f);
@ -121,38 +127,44 @@ struct ir_instr {
/* block */
struct ir_block {
char *label;
lex_ctx_t context;
bool final; /* once a jump is added we're done */
void* operator new(std::size_t);
void operator delete(void*);
ir_instr **instr;
ir_block **entries;
ir_block **exits;
ir_block(ir_function *owner, const std::string& name);
~ir_block();
ir_function *owner;
std::string label;
lex_ctx_t context;
bool final = false; /* once a jump is added we're done */
ir_instr **instr = nullptr;
ir_block **entries = nullptr;
ir_block **exits = nullptr;
std::vector<ir_value *> living;
/* For the temp-allocation */
size_t entry_id;
size_t eid;
bool is_return;
size_t entry_id = 0;
size_t eid = 0;
bool is_return = false;
ir_function *owner;
bool generated;
size_t code_start;
bool generated = false;
size_t code_start = 0;
};
ir_value* ir_block_create_binop(ir_block*, lex_ctx_t, const char *label, int op, ir_value *left, ir_value *right);
ir_value* ir_block_create_unary(ir_block*, lex_ctx_t, const char *label, int op, ir_value *operand);
bool GMQCC_WARN ir_block_create_store_op(ir_block*, lex_ctx_t, int op, ir_value *target, ir_value *what);
bool GMQCC_WARN ir_block_create_storep(ir_block*, lex_ctx_t, ir_value *target, ir_value *what);
ir_value* ir_block_create_load_from_ent(ir_block*, lex_ctx_t, const char *label, ir_value *ent, ir_value *field, int outype);
ir_value* ir_block_create_load_from_ent(ir_block*, lex_ctx_t, const char *label, ir_value *ent, ir_value *field, qc_type outype);
ir_value* ir_block_create_fieldaddress(ir_block*, lex_ctx_t, const char *label, ir_value *entity, ir_value *field);
bool GMQCC_WARN ir_block_create_state_op(ir_block*, lex_ctx_t, ir_value *frame, ir_value *think);
/* This is to create an instruction of the form
* <outtype>%label := opcode a, b
*/
ir_instr* ir_block_create_phi(ir_block*, lex_ctx_t, const char *label, int vtype);
ir_instr* ir_block_create_phi(ir_block*, lex_ctx_t, const char *label, qc_type vtype);
ir_value* ir_phi_value(ir_instr*);
void ir_phi_add(ir_instr*, ir_block *b, ir_value *v);
ir_instr* ir_block_create_call(ir_block*, lex_ctx_t, const char *label, ir_value *func, bool noreturn);
@ -175,27 +187,36 @@ bool GMQCC_WARN ir_block_create_goto(ir_block*, lex_ctx_t, ir_block *to);
/* function */
struct ir_function {
char *name;
int outtype;
int *params;
ir_block **blocks;
ir_flag_t flags;
int builtin;
void* operator new(std::size_t);
void operator delete(void*);
ir_function(ir_builder *owner, qc_type returntype);
~ir_function();
ir_builder *owner;
std::string name;
qc_type outtype;
int *params = nullptr;
ir_flag_t flags = 0;
int builtin = 0;
std::vector<std::unique_ptr<ir_block>> blocks;
/*
* values generated from operations
* which might get optimized away, so anything
* in there needs to be deleted in the dtor.
*/
ir_value **values;
ir_value **locals; /* locally defined variables */
ir_value *value;
std::vector<std::unique_ptr<ir_value>> values;
std::vector<std::unique_ptr<ir_value>> locals; /* locally defined variables */
ir_value *value = nullptr;
size_t allocated_locals;
size_t globaltemps;
size_t allocated_locals = 0;
size_t globaltemps = 0;
ir_block* first;
ir_block* last;
ir_block* first = nullptr;
ir_block* last = nullptr;
lex_ctx_t context;
@ -206,19 +227,17 @@ struct ir_function {
*
* remember the ID:
*/
qcint_t code_function_def;
qcint_t code_function_def = -1;
/* for temp allocation */
size_t run_id;
ir_builder *owner;
size_t run_id = 0;
/* vararg support: */
size_t max_varargs;
size_t max_varargs = 0;
};
ir_value* ir_function_create_local(ir_function *self, const char *name, int vtype, bool param);
ir_value* ir_function_create_local(ir_function *self, const std::string& name, qc_type vtype, bool param);
bool GMQCC_WARN ir_function_finalize(ir_function*);
ir_block* ir_function_create_block(lex_ctx_t ctx, ir_function*, const char *label);
@ -227,33 +246,42 @@ ir_block* ir_function_create_block(lex_ctx_t ctx, ir_function*, const char
#define IR_MAX_VINSTR_TEMPS 1
struct ir_builder {
char *name;
ir_function **functions;
ir_value **globals;
ir_value **fields;
ir_value **const_floats; /* for reusing them in vector-splits, TODO: sort this or use a radix-tree */
void* operator new(std::size_t);
void operator delete(void*);
ir_builder(const std::string& modulename);
~ir_builder();
std::string name;
std::vector<std::unique_ptr<ir_function>> functions;
std::vector<std::unique_ptr<ir_value>> globals;
std::vector<std::unique_ptr<ir_value>> fields;
// for reusing them in vector-splits, TODO: sort this or use a radix-tree
std::vector<ir_value*> const_floats;
ht htfunctions;
ht htglobals;
ht htfields;
ir_value **extparams;
ir_value **extparam_protos;
std::vector<std::unique_ptr<ir_value>> extparams;
std::vector<std::unique_ptr<ir_value>> extparam_protos;
/* the highest func->allocated_locals */
size_t max_locals;
size_t max_globaltemps;
uint32_t first_common_local;
uint32_t first_common_globaltemp;
// the highest func->allocated_locals
size_t max_locals = 0;
size_t max_globaltemps = 0;
uint32_t first_common_local = 0;
uint32_t first_common_globaltemp = 0;
const char **filenames;
qcint_t *filestrings;
/* we cache the #IMMEDIATE string here */
qcint_t str_immediate;
/* there should just be this one nil */
std::vector<const char*> filenames;
std::vector<qcint_t> filestrings;
// we cache the #IMMEDIATE string here
qcint_t str_immediate = 0;
// there should just be this one nil
ir_value *nil;
ir_value *reserved_va_count;
ir_value *coverage_func;
ir_value *reserved_va_count = nullptr;
ir_value *coverage_func = nullptr;
/* some virtual instructions require temps, and their code is isolated
* so that we don't need to keep track of their liveness.
*/
@ -263,11 +291,9 @@ struct ir_builder {
code_t *code;
};
ir_builder* ir_builder_new(const char *modulename);
void ir_builder_delete(ir_builder*);
ir_function* ir_builder_create_function(ir_builder*, const char *name, int outtype);
ir_value* ir_builder_create_global(ir_builder*, const char *name, int vtype);
ir_value* ir_builder_create_field(ir_builder*, const char *name, int vtype);
ir_function* ir_builder_create_function(ir_builder*, const std::string& name, qc_type outtype);
ir_value* ir_builder_create_global(ir_builder*, const std::string& name, qc_type vtype);
ir_value* ir_builder_create_field(ir_builder*, const std::string& name, qc_type vtype);
ir_value* ir_builder_get_va_count(ir_builder*);
bool ir_builder_generate(ir_builder *self, const char *filename);
void ir_builder_dump(ir_builder*, int (*oprintf)(const char*, ...));

View file

@ -65,7 +65,7 @@ static void lex_token_new(lex_file *lex)
if (lex->tok.value)
vec_shrinkto(lex->tok.value, 0);
lex->tok.constval.t = 0;
lex->tok.constval.t = TYPE_VOID;
lex->tok.ctx.line = lex->sline;
lex->tok.ctx.file = lex->name;
lex->tok.ctx.column = lex->column;

View file

@ -9,7 +9,7 @@ struct token {
vec3_t v;
int i;
qcfloat_t f;
int t; /* type */
qc_type t; /* type */
} constval;
lex_ctx_t ctx;
};

View file

@ -6144,7 +6144,7 @@ static bool parser_set_coverage_func(parser_t *parser, ir_builder *ir) {
if (!func) {
if (OPTS_OPTION_BOOL(OPTION_COVERAGE)) {
con_out("coverage support requested but no coverage() builtin declared\n");
ir_builder_delete(ir);
delete ir;
return false;
}
return true;
@ -6157,7 +6157,7 @@ static bool parser_set_coverage_func(parser_t *parser, ir_builder *ir) {
char ty[1024];
ast_type_to_string(expr, ty, sizeof(ty));
con_out("invalid type for coverage(): %s\n", ty);
ir_builder_delete(ir);
delete ir;
return false;
}
@ -6175,7 +6175,7 @@ bool parser_finish(parser_t *parser, const char *output)
return false;
}
ir = ir_builder_new("gmqcc_out");
ir = new ir_builder("gmqcc_out");
if (!ir) {
con_out("failed to allocate builder\n");
return false;
@ -6190,7 +6190,7 @@ bool parser_finish(parser_t *parser, const char *output)
field->hasvalue = false;
if (!ast_global_codegen((ast_value*)field, ir, true)) {
con_out("failed to generate field %s\n", field->name);
ir_builder_delete(ir);
delete ir;
return false;
}
if (hasvalue) {
@ -6217,7 +6217,7 @@ bool parser_finish(parser_t *parser, const char *output)
}
if (!ast_global_codegen(asvalue, ir, false)) {
con_out("failed to generate global %s\n", asvalue->name);
ir_builder_delete(ir);
delete ir;
return false;
}
}
@ -6230,12 +6230,12 @@ bool parser_finish(parser_t *parser, const char *output)
f->varargs->count = parser->max_param_count - f->function_type->type_params.size();
if (!parser_create_array_setter_impl(parser, f->varargs)) {
con_out("failed to generate vararg setter for %s\n", f->name);
ir_builder_delete(ir);
delete ir;
return false;
}
if (!parser_create_array_getter_impl(parser, f->varargs)) {
con_out("failed to generate vararg getter for %s\n", f->name);
ir_builder_delete(ir);
delete ir;
return false;
}
} else {
@ -6267,7 +6267,7 @@ bool parser_finish(parser_t *parser, const char *output)
asvalue->name);
}
if (!ast_generate_accessors(asvalue, ir)) {
ir_builder_delete(ir);
delete ir;
return false;
}
}
@ -6278,7 +6278,7 @@ bool parser_finish(parser_t *parser, const char *output)
if (asvalue->vtype != TYPE_ARRAY)
continue;
if (!ast_generate_accessors(asvalue, ir)) {
ir_builder_delete(ir);
delete ir;
return false;
}
}
@ -6286,13 +6286,13 @@ bool parser_finish(parser_t *parser, const char *output)
!ast_global_codegen(parser->reserved_version, ir, false))
{
con_out("failed to generate reserved::version");
ir_builder_delete(ir);
delete ir;
return false;
}
for (auto &f : parser->functions) {
if (!ast_function_codegen(f, ir)) {
con_out("failed to generate function %s\n", f->name);
ir_builder_delete(ir);
delete ir;
return false;
}
}
@ -6304,7 +6304,7 @@ bool parser_finish(parser_t *parser, const char *output)
for (auto &it : parser->functions) {
if (!ir_function_finalize(it->ir_func)) {
con_out("failed to finalize function %s\n", it->name);
ir_builder_delete(ir);
delete ir;
return false;
}
}
@ -6322,10 +6322,10 @@ bool parser_finish(parser_t *parser, const char *output)
if (!ir_builder_generate(ir, output)) {
con_out("*** failed to generate output file\n");
ir_builder_delete(ir);
delete ir;
return false;
}
}
ir_builder_delete(ir);
delete ir;
return retval;
}