Skip to content

wrong var->offset calculation on emit_code() #13

@AoiMoe

Description

@AoiMoe
void emit_code(Function *fn) {
  // Assign an offset from RBP to each local variable.
  int off = 0;
  for (int i = 0; i < fn->lvars->len; i++) {
    Var *var = fn->lvars->data[i];
    off += var->ty->size;
    off = roundup(off, var->ty->align);  // (*)
    var->offset = -off;
  }
...

At the point (*), var->ty->ailgn may be 0. In such case, roundup() returns 0 regardless of off value and it causes the accumulation of the offset to break.

An example of the fix:

diff --git a/gen_x86.c b/gen_x86.c
index 5453e01..5aa2989 100644
--- a/gen_x86.c
+++ b/gen_x86.c
@@ -184,7 +184,8 @@ void emit_code(Function *fn) {
   for (int i = 0; i < fn->lvars->len; i++) {
     Var *var = fn->lvars->data[i];
     off += var->ty->size;
-    off = roundup(off, var->ty->align);
+    if (var->ty->ty != FUNC)
+      off = roundup(off, var->ty->align);
     var->offset = -off;
   }
 
diff --git a/util.c b/util.c
index a4d30d0..7bf0c5b 100644
--- a/util.c
+++ b/util.c
@@ -129,6 +129,7 @@ char *sb_get(StringBuilder *sb) {
 }
 
 int roundup(int x, int align) {
+  assert(align != 0);
   return (x + align - 1) & ~(align - 1);
 }
 

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions