From 8fe63d504226d5b181e627361e997a160dee4908 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 12 Jul 2020 23:04:00 -0700 Subject: stage2: peer type resolution with noreturn --- src-self-hosted/Module.zig | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'src-self-hosted/Module.zig') diff --git a/src-self-hosted/Module.zig b/src-self-hosted/Module.zig index 3f5a833680..bb8eca5ccf 100644 --- a/src-self-hosted/Module.zig +++ b/src-self-hosted/Module.zig @@ -3518,9 +3518,26 @@ fn makeIntType(self: *Module, scope: *Scope, signed: bool, bits: u16) !Type { fn resolvePeerTypes(self: *Module, scope: *Scope, instructions: []*Inst) !Type { if (instructions.len == 0) return Type.initTag(.noreturn); + if (instructions.len == 1) return instructions[0].ty; - return self.fail(scope, instructions[0].src, "TODO peer type resolution", .{}); + + var prev_inst = instructions[0]; + for (instructions[1..]) |next_inst| { + if (next_inst.ty.eql(prev_inst.ty)) + continue; + if (next_inst.ty.zigTypeTag() == .NoReturn) + continue; + if (prev_inst.ty.zigTypeTag() == .NoReturn) { + prev_inst = next_inst; + continue; + } + + // TODO error notes pointing out each type + return self.fail(scope, next_inst.src, "incompatible types: '{}' and '{}'", .{ prev_inst.ty, next_inst.ty }); + } + + return prev_inst.ty; } fn coerce(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*Inst { -- cgit v1.2.3 From 25b1c00c72b51ef9e011867b3fc4f37b3e216223 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 12 Jul 2020 23:50:25 -0700 Subject: stage2: add implicit return void where applicable --- src-self-hosted/Module.zig | 10 ++++++++-- src-self-hosted/ir.zig | 30 ------------------------------ src-self-hosted/type.zig | 4 ++++ src-self-hosted/zir.zig | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 58 insertions(+), 32 deletions(-) (limited to 'src-self-hosted/Module.zig') diff --git a/src-self-hosted/Module.zig b/src-self-hosted/Module.zig index bb8eca5ccf..03307ab96d 100644 --- a/src-self-hosted/Module.zig +++ b/src-self-hosted/Module.zig @@ -1210,6 +1210,12 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { try self.astGenBlock(&gen_scope.base, body_block); + const last_inst = gen_scope.instructions.items[gen_scope.instructions.items.len - 1]; + if (!last_inst.tag.isNoReturn()) { + const src = tree.token_locs[body_block.rbrace].start; + _ = try self.addZIRInst(&gen_scope.base, src, zir.Inst.ReturnVoid, .{}, .{}); + } + const fn_zir = try gen_scope_arena.allocator.create(Fn.ZIR); fn_zir.* = .{ .body = .{ @@ -2686,7 +2692,7 @@ fn analyzeInstBlock(self: *Module, scope: *Scope, inst: *zir.Inst.Block) InnerEr // Blocks must terminate with noreturn instruction. assert(child_block.instructions.items.len != 0); - assert(child_block.instructions.items[child_block.instructions.items.len - 1].tag.isNoReturn()); + assert(child_block.instructions.items[child_block.instructions.items.len - 1].ty.isNoReturn()); // Need to set the type and emit the Block instruction. This allows machine code generation // to emit a jump instruction to after the block when it encounters the break. @@ -3271,7 +3277,7 @@ fn analyzeInstCondBr(self: *Module, scope: *Scope, inst: *zir.Inst.CondBr) Inner defer false_block.instructions.deinit(self.gpa); try self.analyzeBody(&false_block.base, inst.positionals.false_body); - return self.addNewInstArgs(parent_block, inst.base.src, Type.initTag(.void), Inst.CondBr, Inst.Args(Inst.CondBr){ + return self.addNewInstArgs(parent_block, inst.base.src, Type.initTag(.noreturn), Inst.CondBr, Inst.Args(Inst.CondBr){ .condition = cond, .true_body = .{ .instructions = try scope.arena().dupe(*Inst, true_block.instructions.items) }, .false_body = .{ .instructions = try scope.arena().dupe(*Inst, false_block.instructions.items) }, diff --git a/src-self-hosted/ir.zig b/src-self-hosted/ir.zig index 094b877b53..74da3430a7 100644 --- a/src-self-hosted/ir.zig +++ b/src-self-hosted/ir.zig @@ -60,36 +60,6 @@ pub const Inst = struct { retvoid, sub, unreach, - - /// Returns whether the instruction is one of the control flow "noreturn" types. - /// Function calls do not count. When ZIR is generated, the compiler automatically - /// emits an `Unreach` after a function call with the `noreturn` return type. - pub fn isNoReturn(tag: Tag) bool { - return switch (tag) { - .add, - .arg, - .assembly, - .bitcast, - .block, - .breakpoint, - .call, - .cmp, - .constant, - .isnonnull, - .isnull, - .ptrtoint, - .sub, - => false, - - .br, - .brvoid, - .condbr, - .ret, - .retvoid, - .unreach, - => true, - }; - } }; pub fn cast(base: *Inst, comptime T: type) ?*T { diff --git a/src-self-hosted/type.zig b/src-self-hosted/type.zig index c0d88b1414..512dd631a7 100644 --- a/src-self-hosted/type.zig +++ b/src-self-hosted/type.zig @@ -468,6 +468,10 @@ pub const Type = extern union { }; } + pub fn isNoReturn(self: Type) bool { + return self.zigTypeTag() == .NoReturn; + } + /// Asserts that hasCodeGenBits() is true. pub fn abiAlignment(self: Type, target: Target) u32 { return switch (self.tag()) { diff --git a/src-self-hosted/zir.zig b/src-self-hosted/zir.zig index 8faf248636..0dfbdd20a0 100644 --- a/src-self-hosted/zir.zig +++ b/src-self-hosted/zir.zig @@ -81,6 +81,52 @@ pub const Inst = struct { condbr, isnull, isnonnull, + + /// Returns whether the instruction is one of the control flow "noreturn" types. + /// Function calls do not count. + pub fn isNoReturn(tag: Tag) bool { + return switch (tag) { + .arg, + .block, + .breakpoint, + .call, + .@"const", + .declref, + .declref_str, + .declval, + .declval_in_module, + .str, + .int, + .inttype, + .ptrtoint, + .fieldptr, + .deref, + .as, + .@"asm", + .@"fn", + .fntype, + .@"export", + .primitive, + .intcast, + .bitcast, + .elemptr, + .add, + .sub, + .cmp, + .isnull, + .isnonnull, + => false, + + .condbr, + .@"unreachable", + .@"return", + .returnvoid, + .@"break", + .breakvoid, + .compileerror, + => true, + }; + } }; pub fn TagToType(tag: Tag) type { -- cgit v1.2.3 From 08154c0deb653e016d6eb285c85094048eeded89 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 13 Jul 2020 00:28:11 -0700 Subject: stage2: add retvoid support to CBE --- src-self-hosted/Module.zig | 5 +- src-self-hosted/cgen.zig | 205 ----------------------------------------- src-self-hosted/codegen/c.zig | 206 ++++++++++++++++++++++++++++++++++++++++++ src-self-hosted/link.zig | 4 +- test/stage2/cbe.zig | 1 + 5 files changed, 212 insertions(+), 209 deletions(-) delete mode 100644 src-self-hosted/cgen.zig create mode 100644 src-self-hosted/codegen/c.zig (limited to 'src-self-hosted/Module.zig') diff --git a/src-self-hosted/Module.zig b/src-self-hosted/Module.zig index 03307ab96d..975158c477 100644 --- a/src-self-hosted/Module.zig +++ b/src-self-hosted/Module.zig @@ -1210,8 +1210,9 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { try self.astGenBlock(&gen_scope.base, body_block); - const last_inst = gen_scope.instructions.items[gen_scope.instructions.items.len - 1]; - if (!last_inst.tag.isNoReturn()) { + if (!fn_type.fnReturnType().isNoReturn() and (gen_scope.instructions.items.len == 0 or + !gen_scope.instructions.items[gen_scope.instructions.items.len - 1].tag.isNoReturn())) + { const src = tree.token_locs[body_block.rbrace].start; _ = try self.addZIRInst(&gen_scope.base, src, zir.Inst.ReturnVoid, .{}, .{}); } diff --git a/src-self-hosted/cgen.zig b/src-self-hosted/cgen.zig deleted file mode 100644 index 91dc4a81a4..0000000000 --- a/src-self-hosted/cgen.zig +++ /dev/null @@ -1,205 +0,0 @@ -const link = @import("link.zig"); -const Module = @import("Module.zig"); - -const std = @import("std"); - -const Inst = @import("ir.zig").Inst; -const Value = @import("value.zig").Value; -const Type = @import("type.zig").Type; - -const C = link.File.C; -const Decl = Module.Decl; -const mem = std.mem; - -/// Maps a name from Zig source to C. This will always give the same output for -/// any given input. -fn map(allocator: *std.mem.Allocator, name: []const u8) ![]const u8 { - return allocator.dupe(u8, name); -} - -fn renderType(file: *C, writer: std.ArrayList(u8).Writer, T: Type, src: usize) !void { - if (T.tag() == .usize) { - file.need_stddef = true; - try writer.writeAll("size_t"); - } else { - switch (T.zigTypeTag()) { - .NoReturn => { - file.need_noreturn = true; - try writer.writeAll("noreturn void"); - }, - .Void => try writer.writeAll("void"), - .Int => { - if (T.tag() == .u8) { - file.need_stdint = true; - try writer.writeAll("uint8_t"); - } else { - return file.fail(src, "TODO implement int types", .{}); - } - }, - else => |e| return file.fail(src, "TODO implement type {}", .{e}), - } - } -} - -fn renderFunctionSignature(file: *C, writer: std.ArrayList(u8).Writer, decl: *Decl) !void { - const tv = decl.typed_value.most_recent.typed_value; - try renderType(file, writer, tv.ty.fnReturnType(), decl.src()); - const name = try map(file.allocator, mem.spanZ(decl.name)); - defer file.allocator.free(name); - try writer.print(" {}(", .{name}); - if (tv.ty.fnParamLen() == 0) - try writer.writeAll("void)") - else - return file.fail(decl.src(), "TODO implement parameters", .{}); -} - -pub fn generate(file: *C, decl: *Decl) !void { - switch (decl.typed_value.most_recent.typed_value.ty.zigTypeTag()) { - .Fn => try genFn(file, decl), - .Array => try genArray(file, decl), - else => |e| return file.fail(decl.src(), "TODO {}", .{e}), - } -} - -fn genArray(file: *C, decl: *Decl) !void { - const tv = decl.typed_value.most_recent.typed_value; - // TODO: prevent inline asm constants from being emitted - const name = try map(file.allocator, mem.span(decl.name)); - defer file.allocator.free(name); - if (tv.val.cast(Value.Payload.Bytes)) |payload| - if (tv.ty.arraySentinel()) |sentinel| - if (sentinel.toUnsignedInt() == 0) - try file.constants.writer().print("const char *const {} = \"{}\";\n", .{ name, payload.data }) - else - return file.fail(decl.src(), "TODO byte arrays with non-zero sentinels", .{}) - else - return file.fail(decl.src(), "TODO byte arrays without sentinels", .{}) - else - return file.fail(decl.src(), "TODO non-byte arrays", .{}); -} - -fn genFn(file: *C, decl: *Decl) !void { - const writer = file.main.writer(); - const tv = decl.typed_value.most_recent.typed_value; - - try renderFunctionSignature(file, writer, decl); - - try writer.writeAll(" {"); - - const func: *Module.Fn = tv.val.cast(Value.Payload.Function).?.func; - const instructions = func.analysis.success.instructions; - if (instructions.len > 0) { - for (instructions) |inst| { - try writer.writeAll("\n\t"); - switch (inst.tag) { - .assembly => try genAsm(file, inst.cast(Inst.Assembly).?, decl), - .call => try genCall(file, inst.cast(Inst.Call).?, decl), - .ret => try genRet(file, inst.cast(Inst.Ret).?, decl, tv.ty.fnReturnType()), - else => |e| return file.fail(decl.src(), "TODO {}", .{e}), - } - } - try writer.writeAll("\n"); - } - - try writer.writeAll("}\n\n"); -} - -fn genRet(file: *C, inst: *Inst.Ret, decl: *Decl, expected_return_type: Type) !void { - const writer = file.main.writer(); - const ret_value = inst.args.operand; - const value = ret_value.value().?; - if (expected_return_type.eql(ret_value.ty)) - return file.fail(decl.src(), "TODO return {}", .{expected_return_type}) - else if (expected_return_type.isInt() and ret_value.ty.tag() == .comptime_int) - if (value.intFitsInType(expected_return_type, file.options.target)) - if (expected_return_type.intInfo(file.options.target).bits <= 64) - try writer.print("return {};", .{value.toUnsignedInt()}) - else - return file.fail(decl.src(), "TODO return ints > 64 bits", .{}) - else - return file.fail(decl.src(), "comptime int {} does not fit in {}", .{ value.toUnsignedInt(), expected_return_type }) - else - return file.fail(decl.src(), "return type mismatch: expected {}, found {}", .{ expected_return_type, ret_value.ty }); -} - -fn genCall(file: *C, inst: *Inst.Call, decl: *Decl) !void { - const writer = file.main.writer(); - const header = file.header.writer(); - if (inst.args.func.cast(Inst.Constant)) |func_inst| { - if (func_inst.val.cast(Value.Payload.Function)) |func_val| { - const target = func_val.func.owner_decl; - const target_ty = target.typed_value.most_recent.typed_value.ty; - const ret_ty = target_ty.fnReturnType().tag(); - if (target_ty.fnReturnType().hasCodeGenBits() and inst.base.isUnused()) { - try writer.print("(void)", .{}); - } - const tname = mem.spanZ(target.name); - if (file.called.get(tname) == null) { - try file.called.put(tname, void{}); - try renderFunctionSignature(file, header, target); - try header.writeAll(";\n"); - } - try writer.print("{}();", .{tname}); - } else { - return file.fail(decl.src(), "TODO non-function call target?", .{}); - } - if (inst.args.args.len != 0) { - return file.fail(decl.src(), "TODO function arguments", .{}); - } - } else { - return file.fail(decl.src(), "TODO non-constant call inst?", .{}); - } -} - -fn genAsm(file: *C, inst: *Inst.Assembly, decl: *Decl) !void { - const as = inst.args; - const writer = file.main.writer(); - for (as.inputs) |i, index| { - if (i[0] == '{' and i[i.len - 1] == '}') { - const reg = i[1 .. i.len - 1]; - const arg = as.args[index]; - if (arg.cast(Inst.Constant)) |c| { - if (c.val.tag() == .int_u64) { - try writer.writeAll("register "); - try renderType(file, writer, arg.ty, decl.src()); - try writer.print(" {}_constant __asm__(\"{}\") = {};\n\t", .{ reg, reg, c.val.toUnsignedInt() }); - } else { - return file.fail(decl.src(), "TODO inline asm {} args", .{c.val.tag()}); - } - } else { - return file.fail(decl.src(), "TODO non-constant inline asm args", .{}); - } - } else { - return file.fail(decl.src(), "TODO non-explicit inline asm regs", .{}); - } - } - try writer.print("__asm {} (\"{}\"", .{ if (as.is_volatile) @as([]const u8, "volatile") else "", as.asm_source }); - if (as.output) |o| { - return file.fail(decl.src(), "TODO inline asm output", .{}); - } - if (as.inputs.len > 0) { - if (as.output == null) { - try writer.writeAll(" :"); - } - try writer.writeAll(": "); - for (as.inputs) |i, index| { - if (i[0] == '{' and i[i.len - 1] == '}') { - const reg = i[1 .. i.len - 1]; - const arg = as.args[index]; - if (index > 0) { - try writer.writeAll(", "); - } - if (arg.cast(Inst.Constant)) |c| { - try writer.print("\"\"({}_constant)", .{reg}); - } else { - // This is blocked by the earlier test - unreachable; - } - } else { - // This is blocked by the earlier test - unreachable; - } - } - } - try writer.writeAll(");"); -} diff --git a/src-self-hosted/codegen/c.zig b/src-self-hosted/codegen/c.zig new file mode 100644 index 0000000000..ebc4ff7e1a --- /dev/null +++ b/src-self-hosted/codegen/c.zig @@ -0,0 +1,206 @@ +const std = @import("std"); + +const link = @import("../link.zig"); +const Module = @import("../Module.zig"); + +const Inst = @import("../ir.zig").Inst; +const Value = @import("../value.zig").Value; +const Type = @import("../type.zig").Type; + +const C = link.File.C; +const Decl = Module.Decl; +const mem = std.mem; + +/// Maps a name from Zig source to C. This will always give the same output for +/// any given input. +fn map(allocator: *std.mem.Allocator, name: []const u8) ![]const u8 { + return allocator.dupe(u8, name); +} + +fn renderType(file: *C, writer: std.ArrayList(u8).Writer, T: Type, src: usize) !void { + if (T.tag() == .usize) { + file.need_stddef = true; + try writer.writeAll("size_t"); + } else { + switch (T.zigTypeTag()) { + .NoReturn => { + file.need_noreturn = true; + try writer.writeAll("noreturn void"); + }, + .Void => try writer.writeAll("void"), + .Int => { + if (T.tag() == .u8) { + file.need_stdint = true; + try writer.writeAll("uint8_t"); + } else { + return file.fail(src, "TODO implement int types", .{}); + } + }, + else => |e| return file.fail(src, "TODO implement type {}", .{e}), + } + } +} + +fn renderFunctionSignature(file: *C, writer: std.ArrayList(u8).Writer, decl: *Decl) !void { + const tv = decl.typed_value.most_recent.typed_value; + try renderType(file, writer, tv.ty.fnReturnType(), decl.src()); + const name = try map(file.allocator, mem.spanZ(decl.name)); + defer file.allocator.free(name); + try writer.print(" {}(", .{name}); + if (tv.ty.fnParamLen() == 0) + try writer.writeAll("void)") + else + return file.fail(decl.src(), "TODO implement parameters", .{}); +} + +pub fn generate(file: *C, decl: *Decl) !void { + switch (decl.typed_value.most_recent.typed_value.ty.zigTypeTag()) { + .Fn => try genFn(file, decl), + .Array => try genArray(file, decl), + else => |e| return file.fail(decl.src(), "TODO {}", .{e}), + } +} + +fn genArray(file: *C, decl: *Decl) !void { + const tv = decl.typed_value.most_recent.typed_value; + // TODO: prevent inline asm constants from being emitted + const name = try map(file.allocator, mem.span(decl.name)); + defer file.allocator.free(name); + if (tv.val.cast(Value.Payload.Bytes)) |payload| + if (tv.ty.arraySentinel()) |sentinel| + if (sentinel.toUnsignedInt() == 0) + try file.constants.writer().print("const char *const {} = \"{}\";\n", .{ name, payload.data }) + else + return file.fail(decl.src(), "TODO byte arrays with non-zero sentinels", .{}) + else + return file.fail(decl.src(), "TODO byte arrays without sentinels", .{}) + else + return file.fail(decl.src(), "TODO non-byte arrays", .{}); +} + +fn genFn(file: *C, decl: *Decl) !void { + const writer = file.main.writer(); + const tv = decl.typed_value.most_recent.typed_value; + + try renderFunctionSignature(file, writer, decl); + + try writer.writeAll(" {"); + + const func: *Module.Fn = tv.val.cast(Value.Payload.Function).?.func; + const instructions = func.analysis.success.instructions; + if (instructions.len > 0) { + for (instructions) |inst| { + try writer.writeAll("\n\t"); + switch (inst.tag) { + .assembly => try genAsm(file, inst.cast(Inst.Assembly).?, decl), + .call => try genCall(file, inst.cast(Inst.Call).?, decl), + .ret => try genRet(file, inst.cast(Inst.Ret).?, decl, tv.ty.fnReturnType()), + .retvoid => try file.main.writer().print("return;", .{}), + else => |e| return file.fail(decl.src(), "TODO implement C codegen for {}", .{e}), + } + } + try writer.writeAll("\n"); + } + + try writer.writeAll("}\n\n"); +} + +fn genRet(file: *C, inst: *Inst.Ret, decl: *Decl, expected_return_type: Type) !void { + const writer = file.main.writer(); + const ret_value = inst.args.operand; + const value = ret_value.value().?; + if (expected_return_type.eql(ret_value.ty)) + return file.fail(decl.src(), "TODO return {}", .{expected_return_type}) + else if (expected_return_type.isInt() and ret_value.ty.tag() == .comptime_int) + if (value.intFitsInType(expected_return_type, file.options.target)) + if (expected_return_type.intInfo(file.options.target).bits <= 64) + try writer.print("return {};", .{value.toUnsignedInt()}) + else + return file.fail(decl.src(), "TODO return ints > 64 bits", .{}) + else + return file.fail(decl.src(), "comptime int {} does not fit in {}", .{ value.toUnsignedInt(), expected_return_type }) + else + return file.fail(decl.src(), "return type mismatch: expected {}, found {}", .{ expected_return_type, ret_value.ty }); +} + +fn genCall(file: *C, inst: *Inst.Call, decl: *Decl) !void { + const writer = file.main.writer(); + const header = file.header.writer(); + if (inst.args.func.cast(Inst.Constant)) |func_inst| { + if (func_inst.val.cast(Value.Payload.Function)) |func_val| { + const target = func_val.func.owner_decl; + const target_ty = target.typed_value.most_recent.typed_value.ty; + const ret_ty = target_ty.fnReturnType().tag(); + if (target_ty.fnReturnType().hasCodeGenBits() and inst.base.isUnused()) { + try writer.print("(void)", .{}); + } + const tname = mem.spanZ(target.name); + if (file.called.get(tname) == null) { + try file.called.put(tname, void{}); + try renderFunctionSignature(file, header, target); + try header.writeAll(";\n"); + } + try writer.print("{}();", .{tname}); + } else { + return file.fail(decl.src(), "TODO non-function call target?", .{}); + } + if (inst.args.args.len != 0) { + return file.fail(decl.src(), "TODO function arguments", .{}); + } + } else { + return file.fail(decl.src(), "TODO non-constant call inst?", .{}); + } +} + +fn genAsm(file: *C, inst: *Inst.Assembly, decl: *Decl) !void { + const as = inst.args; + const writer = file.main.writer(); + for (as.inputs) |i, index| { + if (i[0] == '{' and i[i.len - 1] == '}') { + const reg = i[1 .. i.len - 1]; + const arg = as.args[index]; + if (arg.cast(Inst.Constant)) |c| { + if (c.val.tag() == .int_u64) { + try writer.writeAll("register "); + try renderType(file, writer, arg.ty, decl.src()); + try writer.print(" {}_constant __asm__(\"{}\") = {};\n\t", .{ reg, reg, c.val.toUnsignedInt() }); + } else { + return file.fail(decl.src(), "TODO inline asm {} args", .{c.val.tag()}); + } + } else { + return file.fail(decl.src(), "TODO non-constant inline asm args", .{}); + } + } else { + return file.fail(decl.src(), "TODO non-explicit inline asm regs", .{}); + } + } + try writer.print("__asm {} (\"{}\"", .{ if (as.is_volatile) @as([]const u8, "volatile") else "", as.asm_source }); + if (as.output) |o| { + return file.fail(decl.src(), "TODO inline asm output", .{}); + } + if (as.inputs.len > 0) { + if (as.output == null) { + try writer.writeAll(" :"); + } + try writer.writeAll(": "); + for (as.inputs) |i, index| { + if (i[0] == '{' and i[i.len - 1] == '}') { + const reg = i[1 .. i.len - 1]; + const arg = as.args[index]; + if (index > 0) { + try writer.writeAll(", "); + } + if (arg.cast(Inst.Constant)) |c| { + try writer.print("\"\"({}_constant)", .{reg}); + } else { + // This is blocked by the earlier test + unreachable; + } + } else { + // This is blocked by the earlier test + unreachable; + } + } + } + try writer.writeAll(");"); +} diff --git a/src-self-hosted/link.zig b/src-self-hosted/link.zig index 64328d4df5..776f6de31c 100644 --- a/src-self-hosted/link.zig +++ b/src-self-hosted/link.zig @@ -7,7 +7,7 @@ const Module = @import("Module.zig"); const fs = std.fs; const elf = std.elf; const codegen = @import("codegen.zig"); -const cgen = @import("cgen.zig"); +const c_codegen = @import("codegen/c.zig"); const default_entry_addr = 0x8000000; @@ -259,7 +259,7 @@ pub const File = struct { } pub fn updateDecl(self: *File.C, module: *Module, decl: *Module.Decl) !void { - cgen.generate(self, decl) catch |err| { + c_codegen.generate(self, decl) catch |err| { if (err == error.CGenFailure) { try module.failed_decls.put(module.gpa, decl, self.error_msg); } diff --git a/test/stage2/cbe.zig b/test/stage2/cbe.zig index e642489b01..e817029b83 100644 --- a/test/stage2/cbe.zig +++ b/test/stage2/cbe.zig @@ -62,6 +62,7 @@ pub fn addCases(ctx: *TestContext) !void { \\ register size_t rax_constant __asm__("rax") = 231; \\ register size_t rdi_constant __asm__("rdi") = 0; \\ __asm volatile ("syscall" :: ""(rax_constant), ""(rdi_constant)); + \\ return; \\} \\ ); -- cgit v1.2.3