| ... | ... | @@ -3992,13 +3992,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 3992 | 3992 | // Due to incremental compilation, how function calls are generated depends |
| 3993 | 3993 | // on linking. |
| 3994 | 3994 | const mod = self.bin_file.options.module.?; |
| 3995 | | if (self.bin_file.cast(link.File.Elf)) |elf_file| { |
| 3996 | | if (self.air.value(callee)) |func_value| { |
| 3997 | | if (func_value.castTag(.function)) |func_payload| { |
| 3998 | | const func = func_payload.data; |
| 3995 | if (self.air.value(callee)) |func_value| { |
| 3996 | if (func_value.castTag(.function)) |func_payload| { |
| 3997 | 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 | 4001 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 4000 | 4002 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |
| 4001 | | const fn_owner_decl = mod.declPtr(func.owner_decl); |
| 4002 | 4003 | const got_addr = blk: { |
| 4003 | 4004 | const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?]; |
| 4004 | 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 | 4009 | .ops = Mir.Inst.Ops.encode(.{ .flags = 0b01 }), |
| 4009 | 4010 | .data = .{ .imm = @truncate(u32, got_addr) }, |
| 4010 | 4011 | }); |
| 4011 | | } else if (func_value.castTag(.extern_fn)) |_| { |
| 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); |
| 4012 | } else if (self.bin_file.cast(link.File.Coff)) |_| { |
| 4034 | 4013 | try self.genSetReg(Type.initTag(.usize), .rax, .{ |
| 4035 | 4014 | .linker_load = .{ |
| 4036 | 4015 | .type = .got, |
| ... | ... | @@ -4045,19 +4024,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4045 | 4024 | }), |
| 4046 | 4025 | .data = undefined, |
| 4047 | 4026 | }); |
| 4048 | | } else if (func_value.castTag(.extern_fn)) |func_payload| { |
| 4049 | | const extern_fn = func_payload.data; |
| 4050 | | const decl_name = mod.declPtr(extern_fn.owner_decl).name; |
| 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)); |
| 4027 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { |
| 4028 | try fn_owner_decl.link.macho.ensureInitialized(macho_file); |
| 4029 | const sym_index = fn_owner_decl.link.macho.getSymbolIndex().?; |
| 4058 | 4030 | try self.genSetReg(Type.initTag(.usize), .rax, .{ |
| 4059 | 4031 | .linker_load = .{ |
| 4060 | | .type = .import, |
| 4032 | .type = .got, |
| 4061 | 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 | 4041 | }), |
| 4070 | 4042 | .data = undefined, |
| 4071 | 4043 | }); |
| 4072 | | } else { |
| 4073 | | return self.fail("TODO implement calling bitcasted functions", .{}); |
| 4044 | } else if (self.bin_file.cast(link.File.Plan9)) |p9| { |
| 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 { |
| 4076 | | assert(ty.zigTypeTag() == .Pointer); |
| 4077 | | const mcv = try self.resolveInst(callee); |
| 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().?; |
| 4066 | |
| 4067 | if (self.bin_file.cast(link.File.Coff)) |coff_file| { |
| 4068 | const sym_index = try coff_file.getGlobalSymbol(mem.sliceTo(decl_name, 0)); |
| 4095 | 4069 | try self.genSetReg(Type.initTag(.usize), .rax, .{ |
| 4096 | 4070 | .linker_load = .{ |
| 4097 | | .type = .got, |
| 4071 | .type = .import, |
| 4098 | 4072 | .sym_index = sym_index, |
| 4099 | 4073 | }, |
| 4100 | 4074 | }); |
| 4101 | | // callq *%rax |
| 4102 | 4075 | _ = try self.addInst(.{ |
| 4103 | 4076 | .tag = .call, |
| 4104 | 4077 | .ops = Mir.Inst.Ops.encode(.{ |
| ... | ... | @@ -4107,15 +4080,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4107 | 4080 | }), |
| 4108 | 4081 | .data = undefined, |
| 4109 | 4082 | }); |
| 4110 | | } else if (func_value.castTag(.extern_fn)) |func_payload| { |
| 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 | | } |
| 4083 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { |
| 4119 | 4084 | const sym_index = try macho_file.getGlobalSymbol(mem.sliceTo(decl_name, 0)); |
| 4120 | 4085 | _ = try self.addInst(.{ |
| 4121 | 4086 | .tag = .call_extern, |
| ... | ... | @@ -4128,50 +4093,24 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4128 | 4093 | }, |
| 4129 | 4094 | }); |
| 4130 | 4095 | } else { |
| 4131 | | return self.fail("TODO implement calling bitcasted functions", .{}); |
| 4096 | return self.fail("TODO implement calling extern functions", .{}); |
| 4132 | 4097 | } |
| 4133 | 4098 | } else { |
| 4134 | | assert(ty.zigTypeTag() == .Pointer); |
| 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 | | }); |
| 4099 | return self.fail("TODO implement calling bitcasted functions", .{}); |
| 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 | 4115 | if (info.stack_byte_count > 0) { |
| 4177 | 4116 | // Readjust the stack |