Commit dc036f5b6f

Andrew Kelley <andrew@ziglang.org>
2021-05-16 06:00:15
codegen: implement const value rendering for ints <= 64 bits
1 parent 5769ed2
Changed files (5)
src/codegen/x86_64.zig
@@ -171,7 +171,7 @@ pub const Encoder = struct {
     /// This is because the helper functions will assume capacity
     /// in order to avoid bounds checking.
     pub fn init(code: *ArrayList(u8), maximum_inst_size: u8) !Self {
-        try code.ensureCapacity(code.items.len + maximum_inst_size);
+        try code.ensureUnusedCapacity(maximum_inst_size);
         return Self{ .code = code };
     }
 
src/link/Elf.zig
@@ -2196,6 +2196,12 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
     if (decl.val.tag() == .extern_fn) {
         return; // TODO Should we do more when front-end analyzed extern decl?
     }
+    if (decl.val.castTag(.variable)) |payload| {
+        const variable = payload.data;
+        if (variable.is_extern) {
+            return; // TODO Should we do more when front-end analyzed extern decl?
+        }
+    }
 
     var code_buffer = std.ArrayList(u8).init(self.base.allocator);
     defer code_buffer.deinit();
@@ -2287,9 +2293,10 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
     } else {
         // TODO implement .debug_info for global variables
     }
+    const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
     const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
         .ty = decl.ty,
-        .val = decl.val,
+        .val = decl_val,
     }, &code_buffer, .{
         .dwarf = .{
             .dbg_line = &dbg_line_buffer,
src/codegen.zig
@@ -212,20 +212,50 @@ pub fn generateSymbol(
         },
         .Int => {
             // TODO populate .debug_info for the integer
+            const endian = bin_file.options.target.cpu.arch.endian();
             const info = typed_value.ty.intInfo(bin_file.options.target);
-            if (info.bits == 8 and info.signedness == .unsigned) {
-                const x = typed_value.val.toUnsignedInt();
-                try code.append(@intCast(u8, x));
+            if (info.bits <= 8) {
+                const x = @intCast(u8, typed_value.val.toUnsignedInt());
+                try code.append(x);
                 return Result{ .appended = {} };
             }
-            return Result{
-                .fail = try ErrorMsg.create(
-                    bin_file.allocator,
-                    src_loc,
-                    "TODO implement generateSymbol for int type '{}'",
-                    .{typed_value.ty},
-                ),
-            };
+            if (info.bits > 64) {
+                return Result{
+                    .fail = try ErrorMsg.create(
+                        bin_file.allocator,
+                        src_loc,
+                        "TODO implement generateSymbol for big ints ('{}')",
+                        .{typed_value.ty},
+                    ),
+                };
+            }
+            switch (info.signedness) {
+                .unsigned => {
+                    if (info.bits <= 16) {
+                        const x = @intCast(u16, typed_value.val.toUnsignedInt());
+                        mem.writeInt(u16, try code.addManyAsArray(2), x, endian);
+                    } else if (info.bits <= 32) {
+                        const x = @intCast(u32, typed_value.val.toUnsignedInt());
+                        mem.writeInt(u32, try code.addManyAsArray(4), x, endian);
+                    } else {
+                        const x = typed_value.val.toUnsignedInt();
+                        mem.writeInt(u64, try code.addManyAsArray(8), x, endian);
+                    }
+                },
+                .signed => {
+                    if (info.bits <= 16) {
+                        const x = @intCast(i16, typed_value.val.toSignedInt());
+                        mem.writeInt(i16, try code.addManyAsArray(2), x, endian);
+                    } else if (info.bits <= 32) {
+                        const x = @intCast(i32, typed_value.val.toSignedInt());
+                        mem.writeInt(i32, try code.addManyAsArray(4), x, endian);
+                    } else {
+                        const x = typed_value.val.toSignedInt();
+                        mem.writeInt(i64, try code.addManyAsArray(8), x, endian);
+                    }
+                },
+            }
+            return Result{ .appended = {} };
         },
         else => |t| {
             return Result{
test/stage2/test.zig
@@ -1293,9 +1293,10 @@ pub fn addCases(ctx: *TestContext) !void {
             \\    _ = foo;
             \\}
             \\extern var foo: i32;
+            \\pub export fn _start() void {}
         , &[_][]const u8{":2:9: error: unable to resolve comptime value"});
         case.addError(
-            \\export fn entry() void {
+            \\pub export fn _start() void {
             \\    _ = foo;
             \\}
             \\extern var foo;
BRANCH_TODO
@@ -1,7 +1,5 @@
  * get stage2 tests passing
    - spu-ii test is saying "unimplemented" for some reason
-   - compile log test has wrong source loc
-   - extern variable has no type: TODO implement generateSymbol for int type 'i32'
  * modify stage2 tests so that only 1 uses _start and the rest use
    pub fn main
  * modify stage2 CBE tests so that only 1 uses pub export main and the