Sfoglia il codice sorgente

Fixed a rare issue that can occurs in register allocation. Unit test added.

Marco Bambini 8 anni fa
parent
commit
9231f9e1a7

+ 12 - 1
src/compiler/gravity_codegen.c

@@ -1223,7 +1223,7 @@ static void visit_unary_expr (gvisitor_t *self, gnode_unary_expr_t *node) {
 }
 
 static void visit_postfix_expr (gvisitor_t *self, gnode_postfix_expr_t *node) {
-	DEBUG_CODEGEN("visit_call_expr");
+	DEBUG_CODEGEN("visit_postfix_expr");
 
 	// node->list usually cannot be NULL, it is NULL only as a result of a static enum transformation (see semacheck2.c)
 	if (node->list == NULL) {
@@ -1462,6 +1462,17 @@ static void visit_postfix_expr (gvisitor_t *self, gnode_postfix_expr_t *node) {
 	marray_destroy(self_list);
 	ircode_pop_context(code);
 
+    // temp fix for not optimal register allocation algorithm generated code
+    uint32_t temp_register = ircode_register_first_temp_available(code);
+    if (temp_register < dest_register) {
+        // free dest register
+        ircode_register_pop(code);
+        // allocate a new register (that I am now sure does not have holes)
+        temp_register = ircode_register_push_temp(code);
+        ircode_add(code, MOVE, temp_register, dest_register, 0);
+        ircode_register_clear(code, dest_register);
+    }
+    
 	CODEGEN_COUNT_REGISTERS(n2);
 	CODEGEN_ASSERT_REGISTERS(n1, n2, (is_assignment) ? -1 : 1);
 

+ 12 - 1
src/compiler/gravity_ircode.c

@@ -95,7 +95,7 @@ static inst_t *inst_new (opcode_t op, uint32_t p1, uint32_t p2, uint32_t p3, opt
 	#if GRAVITY_OPCODE_DEBUG
 	if (tag == LABEL_TAG) {
 		DEBUG_OPCODE("LABEL %d", p1);
-	} else {
+	} else if (tag != PRAGMA_MOVE_OPTIMIZATION){
 		const char *op_name = opcode_name(op);
 
 		if (op == LOADI) {
@@ -475,6 +475,17 @@ uint32_t ircode_register_push (ircode_t *code, uint32_t nreg) {
 	return nreg;
 }
 
+uint32_t ircode_register_first_temp_available (ircode_t *code) {
+    for (uint32_t i=0; i<MAX_REGISTERS; ++i) {
+        if (code->state[i] == false) {
+            return i;
+        }
+    }
+    // 0 means no registers available
+    code->error = true;
+    return 0;
+}
+
 uint32_t ircode_register_push_temp (ircode_t *code) {
 	uint32_t value = ircode_register_new(code);
 	marray_push(uint32_t, code->registers, value);

+ 1 - 0
src/compiler/gravity_ircode.h

@@ -103,6 +103,7 @@ bool		ircode_register_istemp (ircode_t *code, uint32_t n);
 uint32_t	ircode_register_push_temp (ircode_t *code);
 uint32_t	ircode_register_push (ircode_t *code, uint32_t nreg);
 uint32_t	ircode_register_pop (ircode_t *code);
+uint32_t    ircode_register_first_temp_available (ircode_t *code);
 uint32_t	ircode_register_pop_context_protect (ircode_t *code, bool protect);
 bool		ircode_register_protect_outside_context (ircode_t *code, uint32_t nreg);
 void		ircode_register_protect_in_context (ircode_t *code, uint32_t nreg);

+ 2 - 2
src/shared/gravity_value.h

@@ -66,8 +66,8 @@
 extern "C" {
 #endif
 
-#define GRAVITY_VERSION						"0.3.5"     // git tag 0.3.5
-#define GRAVITY_VERSION_NUMBER				0x000305    // git push --tags
+#define GRAVITY_VERSION						"0.3.6"     // git tag 0.3.6
+#define GRAVITY_VERSION_NUMBER				0x000306    // git push --tags
 #define GRAVITY_BUILD_DATE					__DATE__
 
 #ifndef GRAVITY_ENABLE_DOUBLE

+ 1 - 1
test/fuzzy/heap.gravity

@@ -73,7 +73,7 @@ func main() {
 	var v8 = v4 * v1;			// 3,6,9 (18)
 	var v9 = v1 + 2;			// 3,4,5 (12)
 
-	// just trigger this code in order in order to trigger internal test
+	// just trigger this code in order to trigger internal test
 	var test = v9.String();
 	if (test != "[3,4,5]") return false;
 

+ 40 - 0
test/unittest/register_allocation.gravity

@@ -0,0 +1,40 @@
+#unittest {
+	name: "Sequential register allocation fix.";
+	result: "100°";
+};
+
+class foo {
+    private var _temp = 12;
+    var Temperature;
+    
+    var a {
+        set {
+            _temp = value;
+            var _temp_int = Int(_temp);
+            System.print("Hi");
+            self.Temperature.text = "\(_temp_int)°";
+        }
+    };
+    
+    class TClass {
+        var text;
+        func dump() {
+            System.print("\(text)");
+        }
+    }
+ 
+    func init() {
+        Temperature = TClass();
+        Temperature.text = "Hello World";
+    }
+}
+
+func main() {
+    var f = foo();
+    System.print("\(f.Temperature.text)");
+    
+    f.a = "100";
+    System.print("\(f.Temperature.text)");
+    
+    return f.Temperature.text;
+}