Introduce sequence points before store instructions to prevent loads from the
authorDavid Given <dg@cowlark.com>
Sat, 7 Jan 2017 12:17:39 +0000 (13:17 +0100)
committerDavid Given <dg@cowlark.com>
Sat, 7 Jan 2017 12:17:39 +0000 (13:17 +0100)
same address being delayed until after the store (at which point they'll return
the wrong value).

mach/proto/mcg/treebuilder.c

index 2ead527..5b2a1b9 100644 (file)
@@ -119,6 +119,25 @@ static struct ir* appendir(struct ir* ir)
     return ir;
 }
 
+static void sequence_point(void)
+{
+    int i;
+
+    /* Ensures that any partially-evaluated expressions on the stack are executed right
+     * now. This typically needs to happen before store operations, to prevents loads of
+     * the same address being delayed until after the store (at which point they'll
+     * return incorrect values).
+     */
+
+    assert(current_bb != NULL);
+
+    for (i=0; i<stackptr; i++)
+    {
+        struct ir* ir = stack[i];
+        array_appendu(&current_bb->irs, ir);
+    }
+}
+
 static void materialise_stack(void)
 {
     int i;
@@ -229,6 +248,8 @@ static struct ir* store(int size, struct ir* address, int offset, struct ir* val
 {
     int opcode;
 
+    sequence_point();
+
     if (size == 1)
     {
         opcode = IR_STOREB;
@@ -475,6 +496,7 @@ static void insn_simple(int opcode)
 
         case op_sim:
         {
+            sequence_point();
             appendir(
                 new_ir2(
                     (EM_wordsize == 2) ? IR_STORE : IR_STOREH, EM_wordsize,
@@ -1497,6 +1519,7 @@ static void insn_lvalue(int opcode, const char* label, arith offset)
             break;
 
         case op_ste:
+            sequence_point();
             appendir(
                 new_ir2(
                     IR_STORE, EM_wordsize,
@@ -1507,6 +1530,7 @@ static void insn_lvalue(int opcode, const char* label, arith offset)
             break;
 
         case op_sde:
+            sequence_point();
             appendir(
                 new_ir2(
                     IR_STORE, EM_wordsize*2,
@@ -1517,6 +1541,7 @@ static void insn_lvalue(int opcode, const char* label, arith offset)
             break;
 
         case op_zre:
+            sequence_point();
             appendir(
                 new_ir2(
                     IR_STORE, EM_wordsize,
@@ -1527,6 +1552,7 @@ static void insn_lvalue(int opcode, const char* label, arith offset)
             break;
                 
         case op_ine:
+            sequence_point();
             appendir(
                 new_ir2(
                     IR_STORE, EM_wordsize,
@@ -1544,6 +1570,7 @@ static void insn_lvalue(int opcode, const char* label, arith offset)
             break;
 
         case op_dee:
+            sequence_point();
             appendir(
                 new_ir2(
                     IR_STORE, EM_wordsize,