X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=ast.c;h=94b254cc91f5a3ad3931fe81d9654e1d738f4047;hb=8ce331b563e413f7d1c17bbe6bccc48657cfab90;hp=81e1c121231e16bbb9bdde2c92cf72ec642fda1b;hpb=b0a07695344c805381fdca64aac229ee98725130;p=xonotic%2Fgmqcc.git diff --git a/ast.c b/ast.c index 81e1c12..94b254c 100644 --- a/ast.c +++ b/ast.c @@ -21,7 +21,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#include #include #include @@ -1208,6 +1207,63 @@ bool ast_value_codegen(ast_value *self, ast_function *func, bool lvalue, ir_valu return true; } +static bool ast_global_array_set(ast_value *self) +{ + size_t count = vec_size(self->initlist); + size_t i; + + if (count > self->expression.count) { + compile_error(ast_ctx(self), "too many elements in initializer"); + count = self->expression.count; + } + else if (count < self->expression.count) { + /* add this? + compile_warning(ast_ctx(self), "not all elements are initialized"); + */ + } + + for (i = 0; i != count; ++i) { + switch (self->expression.next->vtype) { + case TYPE_FLOAT: + if (!ir_value_set_float(self->ir_values[i], self->initlist[i].vfloat)) + return false; + break; + case TYPE_VECTOR: + if (!ir_value_set_vector(self->ir_values[i], self->initlist[i].vvec)) + return false; + break; + case TYPE_STRING: + if (!ir_value_set_string(self->ir_values[i], self->initlist[i].vstring)) + return false; + break; + case TYPE_ARRAY: + /* we don't support them in any other place yet either */ + compile_error(ast_ctx(self), "TODO: nested arrays"); + return false; + case TYPE_FUNCTION: + /* this requiers a bit more work - similar to the fields I suppose */ + compile_error(ast_ctx(self), "global of type function not properly generated"); + return false; + case TYPE_FIELD: + if (!self->initlist[i].vfield) { + compile_error(ast_ctx(self), "field constant without vfield set"); + return false; + } + if (!self->initlist[i].vfield->ir_v) { + compile_error(ast_ctx(self), "field constant generated before its field"); + return false; + } + if (!ir_value_set_field(self->ir_values[i], self->initlist[i].vfield->ir_v)) + return false; + break; + default: + compile_error(ast_ctx(self), "TODO: global constant type %i", self->expression.vtype); + break; + } + } + return true; +} + bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield) { ir_value *v = NULL; @@ -1317,6 +1373,11 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield) ast_expression *elemtype = self->expression.next; int vtype = elemtype->vtype; + if (self->expression.flags & AST_FLAG_ARRAY_INIT && !self->expression.count) { + compile_error(ast_ctx(self), "array `%s' has no size", self->name); + return false; + } + /* same as with field arrays */ if (!self->expression.count || self->expression.count > OPTS_OPTION_U32(OPTION_MAX_ARRAY_SIZE)) compile_error(ast_ctx(self), "Invalid array of size %lu", (unsigned long)self->expression.count); @@ -1368,6 +1429,13 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield) v->context = ast_ctx(self); } + /* link us to the ir_value */ + v->cvq = self->cvq; + self->ir_v = v; + if (self->expression.flags & AST_FLAG_INCLUDE_DEF) + self->ir_v->flags |= IR_FLAG_INCLUDE_DEF; + + /* initialize */ if (self->hasvalue) { switch (self->expression.vtype) { @@ -1384,7 +1452,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield) goto error; break; case TYPE_ARRAY: - compile_error(ast_ctx(self), "TODO: global constant array"); + ast_global_array_set(self); break; case TYPE_FUNCTION: compile_error(ast_ctx(self), "global of type function not properly generated"); @@ -1409,12 +1477,6 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield) break; } } - - /* link us to the ir_value */ - v->cvq = self->cvq; - self->ir_v = v; - if (self->expression.flags & AST_FLAG_INCLUDE_DEF) - self->ir_v->flags |= IR_FLAG_INCLUDE_DEF; return true; error: /* clean up */