| ... | @@ -3992,13 +3992,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -3992,13 +3992,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 3992 | // Due to incremental compilation, how function calls are generated depends | 3992 | // Due to incremental compilation, how function calls are generated depends |
| 3993 | // on linking. | 3993 | // on linking. |
| 3994 | const mod = self.bin_file.options.module.?; | 3994 | const mod = self.bin_file.options.module.?; |
| 3995 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { | 3995 | if (self.air.value(callee)) |func_value| { |
| 3996 | if (self.air.value(callee)) |func_value| { | 3996 | if (func_value.castTag(.function)) |func_payload| { |
| 3997 | if (func_value.castTag(.function)) |func_payload| { | 3997 | const func = func_payload.data; |
| 3998 | const func = func_payload.data; | 3998 | const fn_owner_decl = mod.declPtr(func.owner_decl); |
| | 3999 | |
| | 4000 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { |
| 3999 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); | 4001 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 4000 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); | 4002 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |
| 4001 | const fn_owner_decl = mod.declPtr(func.owner_decl); | | |
| 4002 | const got_addr = blk: { | 4003 | const got_addr = blk: { |
| 4003 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; | 4004 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; |
| 4004 | break :blk @intCast(u32, got.p_vaddr + fn_owner_decl.link.elf.offset_table_index * ptr_bytes); | 4005 | break :blk @intCast(u32, got.p_vaddr + fn_owner_decl.link.elf.offset_table_index * ptr_bytes); |
| ... | @@ -4008,29 +4009,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -4008,29 +4009,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4008 | .ops = Mir.Inst.Ops.encode(.{ .flags = 0b01 }), | 4009 | .ops = Mir.Inst.Ops.encode(.{ .flags = 0b01 }), |
| 4009 | .data = .{ .imm = @truncate(u32, got_addr) }, | 4010 | .data = .{ .imm = @truncate(u32, got_addr) }, |
| 4010 | }); | 4011 | }); |
| 4011 | } else if (func_value.castTag(.extern_fn)) |_| { | 4012 | } else if (self.bin_file.cast(link.File.Coff)) |_| { |
| 4012 | return self.fail("TODO implement calling extern functions", .{}); | | |
| 4013 | } else { | | |
| 4014 | return self.fail("TODO implement calling bitcasted functions", .{}); | | |
| 4015 | } | | |
| 4016 | } else { | | |
| 4017 | assert(ty.zigTypeTag() == .Pointer); | | |
| 4018 | const mcv = try self.resolveInst(callee); | | |
| 4019 | try self.genSetReg(Type.initTag(.usize), .rax, mcv); | | |
| 4020 | _ = try self.addInst(.{ | | |
| 4021 | .tag = .call, | | |
| 4022 | .ops = Mir.Inst.Ops.encode(.{ | | |
| 4023 | .reg1 = .rax, | | |
| 4024 | .flags = 0b01, | | |
| 4025 | }), | | |
| 4026 | .data = undefined, | | |
| 4027 | }); | | |
| 4028 | } | | |
| 4029 | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| { | | |
| 4030 | if (self.air.value(callee)) |func_value| { | | |
| 4031 | if (func_value.castTag(.function)) |func_payload| { | | |
| 4032 | const func = func_payload.data; | | |
| 4033 | const fn_owner_decl = mod.declPtr(func.owner_decl); | | |
| 4034 | try self.genSetReg(Type.initTag(.usize), .rax, .{ | 4013 | try self.genSetReg(Type.initTag(.usize), .rax, .{ |
| 4035 | .linker_load = .{ | 4014 | .linker_load = .{ |
| 4036 | .type = .got, | 4015 | .type = .got, |
| ... | @@ -4045,19 +4024,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -4045,19 +4024,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4045 | }), | 4024 | }), |
| 4046 | .data = undefined, | 4025 | .data = undefined, |
| 4047 | }); | 4026 | }); |
| 4048 | } else if (func_value.castTag(.extern_fn)) |func_payload| { | 4027 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { |
| 4049 | const extern_fn = func_payload.data; | 4028 | try fn_owner_decl.link.macho.ensureInitialized(macho_file); |
| 4050 | const decl_name = mod.declPtr(extern_fn.owner_decl).name; | 4029 | const sym_index = fn_owner_decl.link.macho.getSymbolIndex().?; |
| 4051 | if (extern_fn.lib_name) |lib_name| { | | |
| 4052 | log.debug("TODO enforce that '{s}' is expected in '{s}' library", .{ | | |
| 4053 | decl_name, | | |
| 4054 | lib_name, | | |
| 4055 | }); | | |
| 4056 | } | | |
| 4057 | const sym_index = try coff_file.getGlobalSymbol(mem.sliceTo(decl_name, 0)); | | |
| 4058 | try self.genSetReg(Type.initTag(.usize), .rax, .{ | 4030 | try self.genSetReg(Type.initTag(.usize), .rax, .{ |
| 4059 | .linker_load = .{ | 4031 | .linker_load = .{ |
| 4060 | .type = .import, | 4032 | .type = .got, |
| 4061 | .sym_index = sym_index, | 4033 | .sym_index = sym_index, |
| 4062 | }, | 4034 | }, |
| 4063 | }); | 4035 | }); |
| ... | @@ -4069,36 +4041,37 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -4069,36 +4041,37 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4069 | }), | 4041 | }), |
| 4070 | .data = undefined, | 4042 | .data = undefined, |
| 4071 | }); | 4043 | }); |
| 4072 | } else { | 4044 | } else if (self.bin_file.cast(link.File.Plan9)) |p9| { |
| 4073 | return self.fail("TODO implement calling bitcasted functions", .{}); | 4045 | try p9.seeDecl(func.owner_decl); |
| | 4046 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| | 4047 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |
| | 4048 | const got_addr = p9.bases.data; |
| | 4049 | const got_index = fn_owner_decl.link.plan9.got_index.?; |
| | 4050 | const fn_got_addr = got_addr + got_index * ptr_bytes; |
| | 4051 | _ = try self.addInst(.{ |
| | 4052 | .tag = .call, |
| | 4053 | .ops = Mir.Inst.Ops.encode(.{ .flags = 0b01 }), |
| | 4054 | .data = .{ .imm = @intCast(u32, fn_got_addr) }, |
| | 4055 | }); |
| | 4056 | } else unreachable; |
| | 4057 | } else if (func_value.castTag(.extern_fn)) |func_payload| { |
| | 4058 | const extern_fn = func_payload.data; |
| | 4059 | const decl_name = mod.declPtr(extern_fn.owner_decl).name; |
| | 4060 | if (extern_fn.lib_name) |lib_name| { |
| | 4061 | log.debug("TODO enforce that '{s}' is expected in '{s}' library", .{ |
| | 4062 | decl_name, |
| | 4063 | lib_name, |
| | 4064 | }); |
| 4074 | } | 4065 | } |
| 4075 | } else { | 4066 | |
| 4076 | assert(ty.zigTypeTag() == .Pointer); | 4067 | if (self.bin_file.cast(link.File.Coff)) |coff_file| { |
| 4077 | const mcv = try self.resolveInst(callee); | 4068 | const sym_index = try coff_file.getGlobalSymbol(mem.sliceTo(decl_name, 0)); |
| 4078 | try self.genSetReg(Type.initTag(.usize), .rax, mcv); | | |
| 4079 | _ = try self.addInst(.{ | | |
| 4080 | .tag = .call, | | |
| 4081 | .ops = Mir.Inst.Ops.encode(.{ | | |
| 4082 | .reg1 = .rax, | | |
| 4083 | .flags = 0b01, | | |
| 4084 | }), | | |
| 4085 | .data = undefined, | | |
| 4086 | }); | | |
| 4087 | } | | |
| 4088 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { | | |
| 4089 | if (self.air.value(callee)) |func_value| { | | |
| 4090 | if (func_value.castTag(.function)) |func_payload| { | | |
| 4091 | const func = func_payload.data; | | |
| 4092 | const fn_owner_decl = mod.declPtr(func.owner_decl); | | |
| 4093 | try fn_owner_decl.link.macho.ensureInitialized(macho_file); | | |
| 4094 | const sym_index = fn_owner_decl.link.macho.getSymbolIndex().?; | | |
| 4095 | try self.genSetReg(Type.initTag(.usize), .rax, .{ | 4069 | try self.genSetReg(Type.initTag(.usize), .rax, .{ |
| 4096 | .linker_load = .{ | 4070 | .linker_load = .{ |
| 4097 | .type = .got, | 4071 | .type = .import, |
| 4098 | .sym_index = sym_index, | 4072 | .sym_index = sym_index, |
| 4099 | }, | 4073 | }, |
| 4100 | }); | 4074 | }); |
| 4101 | // callq *%rax | | |
| 4102 | _ = try self.addInst(.{ | 4075 | _ = try self.addInst(.{ |
| 4103 | .tag = .call, | 4076 | .tag = .call, |
| 4104 | .ops = Mir.Inst.Ops.encode(.{ | 4077 | .ops = Mir.Inst.Ops.encode(.{ |
| ... | @@ -4107,15 +4080,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -4107,15 +4080,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4107 | }), | 4080 | }), |
| 4108 | .data = undefined, | 4081 | .data = undefined, |
| 4109 | }); | 4082 | }); |
| 4110 | } else if (func_value.castTag(.extern_fn)) |func_payload| { | 4083 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { |
| 4111 | const extern_fn = func_payload.data; | | |
| 4112 | const decl_name = mod.declPtr(extern_fn.owner_decl).name; | | |
| 4113 | if (extern_fn.lib_name) |lib_name| { | | |
| 4114 | log.debug("TODO enforce that '{s}' is expected in '{s}' library", .{ | | |
| 4115 | decl_name, | | |
| 4116 | lib_name, | | |
| 4117 | }); | | |
| 4118 | } | | |
| 4119 | const sym_index = try macho_file.getGlobalSymbol(mem.sliceTo(decl_name, 0)); | 4084 | const sym_index = try macho_file.getGlobalSymbol(mem.sliceTo(decl_name, 0)); |
| 4120 | _ = try self.addInst(.{ | 4085 | _ = try self.addInst(.{ |
| 4121 | .tag = .call_extern, | 4086 | .tag = .call_extern, |
| ... | @@ -4128,50 +4093,24 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -4128,50 +4093,24 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4128 | }, | 4093 | }, |
| 4129 | }); | 4094 | }); |
| 4130 | } else { | 4095 | } else { |
| 4131 | return self.fail("TODO implement calling bitcasted functions", .{}); | 4096 | return self.fail("TODO implement calling extern functions", .{}); |
| 4132 | } | 4097 | } |
| 4133 | } else { | 4098 | } else { |
| 4134 | assert(ty.zigTypeTag() == .Pointer); | 4099 | return self.fail("TODO implement calling bitcasted functions", .{}); |
| 4135 | const mcv = try self.resolveInst(callee); | | |
| 4136 | try self.genSetReg(Type.initTag(.usize), .rax, mcv); | | |
| 4137 | _ = try self.addInst(.{ | | |
| 4138 | .tag = .call, | | |
| 4139 | .ops = Mir.Inst.Ops.encode(.{ | | |
| 4140 | .reg1 = .rax, | | |
| 4141 | .flags = 0b01, | | |
| 4142 | }), | | |
| 4143 | .data = undefined, | | |
| 4144 | }); | | |
| 4145 | } | | |
| 4146 | } else if (self.bin_file.cast(link.File.Plan9)) |p9| { | | |
| 4147 | if (self.air.value(callee)) |func_value| { | | |
| 4148 | if (func_value.castTag(.function)) |func_payload| { | | |
| 4149 | try p9.seeDecl(func_payload.data.owner_decl); | | |
| 4150 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); | | |
| 4151 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); | | |
| 4152 | const got_addr = p9.bases.data; | | |
| 4153 | const got_index = mod.declPtr(func_payload.data.owner_decl).link.plan9.got_index.?; | | |
| 4154 | const fn_got_addr = got_addr + got_index * ptr_bytes; | | |
| 4155 | _ = try self.addInst(.{ | | |
| 4156 | .tag = .call, | | |
| 4157 | .ops = Mir.Inst.Ops.encode(.{ .flags = 0b01 }), | | |
| 4158 | .data = .{ .imm = @intCast(u32, fn_got_addr) }, | | |
| 4159 | }); | | |
| 4160 | } else return self.fail("TODO implement calling extern fn on plan9", .{}); | | |
| 4161 | } else { | | |
| 4162 | assert(ty.zigTypeTag() == .Pointer); | | |
| 4163 | const mcv = try self.resolveInst(callee); | | |
| 4164 | try self.genSetReg(Type.initTag(.usize), .rax, mcv); | | |
| 4165 | _ = try self.addInst(.{ | | |
| 4166 | .tag = .call, | | |
| 4167 | .ops = Mir.Inst.Ops.encode(.{ | | |
| 4168 | .reg1 = .rax, | | |
| 4169 | .flags = 0b01, | | |
| 4170 | }), | | |
| 4171 | .data = undefined, | | |
| 4172 | }); | | |
| 4173 | } | 4100 | } |
| 4174 | } else unreachable; | 4101 | } else { |
| | 4102 | assert(ty.zigTypeTag() == .Pointer); |
| | 4103 | const mcv = try self.resolveInst(callee); |
| | 4104 | try self.genSetReg(Type.initTag(.usize), .rax, mcv); |
| | 4105 | _ = try self.addInst(.{ |
| | 4106 | .tag = .call, |
| | 4107 | .ops = Mir.Inst.Ops.encode(.{ |
| | 4108 | .reg1 = .rax, |
| | 4109 | .flags = 0b01, |
| | 4110 | }), |
| | 4111 | .data = undefined, |
| | 4112 | }); |
| | 4113 | } |
| 4175 | | 4114 | |
| 4176 | if (info.stack_byte_count > 0) { | 4115 | if (info.stack_byte_count > 0) { |
| 4177 | // Readjust the stack | 4116 | // Readjust the stack |