]> git.xonotic.org Git - xonotic/gmqcc.git/commitdiff
ast_return
authorWolfgang Bumiller <wolfgang.linux@bumiller.com>
Thu, 26 Jul 2012 19:18:39 +0000 (21:18 +0200)
committerWolfgang Bumiller <wolfgang.linux@bumiller.com>
Thu, 26 Jul 2012 19:18:39 +0000 (21:18 +0200)
ast.c
ast.h

diff --git a/ast.c b/ast.c
index 70bc0374fa8c883df19d6ae6d6aea29491376e6a..56db3f94f872b678930e934ea9ca679c20bd4b25 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -200,6 +200,24 @@ void ast_unary_delete(ast_unary *self)
     mem_d(self);
 }
 
+ast_return* ast_return_new(lex_ctx ctx, int op,
+                         ast_expression *expr)
+{
+    ast_instantiate(ast_return, ctx, ast_return_delete);
+    ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_return_codegen);
+
+    self->operand = expr;
+
+    return self;
+}
+
+void ast_return_delete(ast_return *self)
+{
+    ast_unref(self->operand);
+    ast_expression_delete((ast_expression*)self);
+    mem_d(self);
+}
+
 ast_entfield* ast_entfield_new(lex_ctx ctx, ast_expression *entity, ast_expression *field)
 {
     const ast_expression *outtype;
@@ -785,7 +803,7 @@ bool ast_unary_codegen(ast_unary *self, ast_function *func, bool lvalue, ir_valu
     if (!(*cgen)((ast_expression*)(self->operand), func, false, &operand))
         return false;
 
-    *out = ir_block_create_unary(func->curblock, ast_function_label(func, "bin"),
+    *out = ir_block_create_unary(func->curblock, ast_function_label(func, "unary"),
                                  self->op, operand);
     if (!*out)
         return false;
@@ -793,6 +811,27 @@ bool ast_unary_codegen(ast_unary *self, ast_function *func, bool lvalue, ir_valu
     return true;
 }
 
+bool ast_return_codegen(ast_return *self, ast_function *func, bool lvalue, ir_value **out)
+{
+    ast_expression_codegen *cgen;
+    ir_value *operand;
+
+    /* In the context of a return operation, we can disregard
+     * the lvalue flag.
+     */
+    (void)lvalue;
+
+    cgen = self->operand->expression.codegen;
+    /* lvalue! */
+    if (!(*cgen)((ast_expression*)(self->operand), func, false, &operand))
+        return false;
+
+    if (!ir_block_create_return(func->curblock, operand))
+        return false;
+
+    return true;
+}
+
 bool ast_entfield_codegen(ast_entfield *self, ast_function *func, bool lvalue, ir_value **out)
 {
     ast_expression_codegen *cgen;
diff --git a/ast.h b/ast.h
index 663099d4efa46dbe73b81f2c85cd11b6af47a5ff..86bb18379f277ca1710e8856f1655ef510d40cc3 100644 (file)
--- a/ast.h
+++ b/ast.h
@@ -168,6 +168,24 @@ void ast_unary_delete(ast_unary*);
 
 bool ast_unary_codegen(ast_unary*, ast_function*, bool lvalue, ir_value**);
 
+/* Return
+ *
+ * Make sure 'return' only happens at the end of a block, otherwise the IR
+ * will refuse to create further instructions.
+ * This should be honored by the parser.
+ */
+struct ast_return_s
+{
+    ast_expression_common expression;
+    ast_expression *operand;
+};
+ast_return* ast_return_new(lex_ctx    ctx,
+                           int        op,
+                           ast_expression *expr);
+void ast_return_delete(ast_return*);
+
+bool ast_return_codegen(ast_return*, ast_function*, bool lvalue, ir_value**);
+
 /* Entity-field
  *
  * This must do 2 things: