From da07fd5ca46228d7f6478bd41a28f201c1e4e73c Mon Sep 17 00:00:00 2001 From: David Gonzalez Martin Date: Fri, 10 Nov 2023 09:42:54 -0600 Subject: [PATCH] implement lea for globals and argument tweaks --- src/backend/x86_64.zig | 160 +++++++++++++++++++++++++++-------------- 1 file changed, 107 insertions(+), 53 deletions(-) diff --git a/src/backend/x86_64.zig b/src/backend/x86_64.zig index 7bdda85..d185795 100644 --- a/src/backend/x86_64.zig +++ b/src/backend/x86_64.zig @@ -2137,59 +2137,67 @@ pub const MIR = struct { switch (ir_instruction.*) { .ret => |ir_ret_index| { const ir_ret = mir.ir.returns.get(ir_ret_index); - const value_type = resolveType(getIrType(mir.ir, ir_ret.instruction)); - const source_register = try instruction_selection.getRegisterForValue(mir, ir_ret.instruction); + switch (ir_ret.instruction.invalid) { + true => { + const ret = try mir.buildInstruction(instruction_selection, .ret, &.{}); + try instruction_selection.instruction_cache.append(mir.allocator, ret); + }, + false => { + const value_type = resolveType(getIrType(mir.ir, ir_ret.instruction)); + const source_register = try instruction_selection.getRegisterForValue(mir, ir_ret.instruction); - const register_class = register_classes.get(value_type); + const register_class = register_classes.get(value_type); - const physical_register = Register{ - .index = .{ - .physical = switch (register_class) { - .gp32 => .eax, - .gp64 => .rax, + const physical_register = Register{ + .index = .{ + .physical = switch (register_class) { + .gp32 => .eax, + .gp64 => .rax, + else => unreachable, + }, + }, + }; + const operand_id: Operand.Id = switch (register_class) { + .gp32 => .gp32, + .gp64 => .gp64, else => unreachable, - }, - }, - }; - const operand_id: Operand.Id = switch (register_class) { - .gp32 => .gp32, - .gp64 => .gp64, - else => unreachable, - }; + }; - const copy = try mir.buildInstruction(instruction_selection, .copy, &.{ - Operand{ - .id = operand_id, - .u = .{ - .register = physical_register, - }, - .flags = .{ - .type = .def, - }, - }, - Operand{ - .id = operand_id, - .u = .{ - .register = source_register, - }, - .flags = .{}, - }, - }); + const copy = try mir.buildInstruction(instruction_selection, .copy, &.{ + Operand{ + .id = operand_id, + .u = .{ + .register = physical_register, + }, + .flags = .{ + .type = .def, + }, + }, + Operand{ + .id = operand_id, + .u = .{ + .register = source_register, + }, + .flags = .{}, + }, + }); - try instruction_selection.instruction_cache.append(mir.allocator, copy); + try instruction_selection.instruction_cache.append(mir.allocator, copy); - const ret = try mir.buildInstruction(instruction_selection, .ret, &.{ - Operand{ - .id = operand_id, - .u = .{ - .register = physical_register, - }, - .flags = .{ - .implicit = true, - }, + const ret = try mir.buildInstruction(instruction_selection, .ret, &.{ + Operand{ + .id = operand_id, + .u = .{ + .register = physical_register, + }, + .flags = .{ + .implicit = true, + }, + }, + }); + try instruction_selection.instruction_cache.append(mir.allocator, ret); }, - }); - try instruction_selection.instruction_cache.append(mir.allocator, ret); + } }, .load_integer => try instruction_selection.materializeInteger(mir, ir_instruction_index), .@"unreachable" => try instruction_selection.instruction_cache.append(mir.allocator, try mir.buildInstruction(instruction_selection, .ud2, &.{})), @@ -2238,6 +2246,7 @@ pub const MIR = struct { const last_block_instruction = mir.ir.instructions.get(ir_block.instructions.items[ir_block.instructions.items.len - 1]); break :blk switch (last_block_instruction.*) { .@"unreachable" => false, + .ret => true, else => |t| @panic(@tagName(t)), }; }, @@ -2468,12 +2477,16 @@ pub const MIR = struct { }, .call => |ir_call_index| { const ir_call = mir.ir.calls.get(ir_call_index); - for (ir_call.arguments, 0..) |ir_argument_index, index| { + var argument_index = ir_call.arguments.len; + while (argument_index > 0) { + argument_index -= 1; + + const ir_argument_index = ir_call.arguments[argument_index]; // print("index: {}", .{index}); const source_register = try instruction_selection.getRegisterForValue(mir, ir_argument_index); const source_value_type = resolveType(getIrType(mir.ir, ir_argument_index)); const source_register_class = register_classes.get(source_value_type); - const argument_register = calling_convention.argument_registers.get(source_register_class)[index]; + const argument_register = calling_convention.argument_registers.get(source_register_class)[argument_index]; // print("Argument register: {}", .{argument_register}); const destination_register = Register{ @@ -2487,6 +2500,7 @@ pub const MIR = struct { .gp64 => .gp64, else => unreachable, }; + const source_operand = Operand{ .id = operand_id, .u = .{ @@ -2494,6 +2508,7 @@ pub const MIR = struct { }, .flags = .{}, }; + const destination_operand = Operand{ .id = operand_id, .u = .{ @@ -2577,6 +2592,39 @@ pub const MIR = struct { }, } }, + .load_string_literal => |ir_load_string_literal_index| { + const virtual_register = try instruction_selection.getRegisterForValue(mir, ir_instruction_index); + const virtual_operand = Operand{ + .id = .gp64, + .u = .{ + .register = virtual_register, + }, + .flags = .{ .type = .def }, + }; + const source_operand = Operand{ + .id = .lea64mem, + .u = .{ + .lea64mem = .{ + .gp64 = null, + .scale = 1, + .scale_reg = null, + .displacement = Operand.PCRelative{ + .string_literal = ir_load_string_literal_index, + }, + }, + }, + .flags = .{}, + }; + + const lea = try mir.buildInstruction(instruction_selection, .lea64r, &.{ + virtual_operand, + source_operand, + }); + + try instruction_selection.instruction_cache.append(mir.allocator, lea); + + try instruction_selection.updateValueMap(mir.allocator, ir_instruction_index, virtual_register, false); + }, else => |t| @panic(@tagName(t)), } @@ -4070,11 +4118,17 @@ pub const MIR = struct { { if (instruction != .copy) { const descriptor = instruction_descriptors.getPtrConst(instruction); - if (descriptor.operands.len != operands.len) unreachable; - for (descriptor.operands, operands) |descriptor_operand, operand| { - switch (descriptor_operand.id) { - .unknown => {}, - else => if (descriptor_operand.id != operand.id) unreachable, + if (descriptor.operands.len == operands.len) { + for (descriptor.operands, operands) |descriptor_operand, operand| { + switch (descriptor_operand.id) { + .unknown => {}, + else => if (descriptor_operand.id != operand.id) unreachable, + } + } + } else { + switch (instruction) { + .ret => {}, + else => unreachable, } } }