@@ -142,7 +142,8 @@ const MCValue = union(enum) {
142
142
/// The value is in memory but requires a linker relocation fixup:
143
143
/// * got - the value is referenced indirectly via GOT entry index (the linker emits a got-type reloc)
144
144
/// * direct - the value is referenced directly via symbol index index (the linker emits a displacement reloc)
145
- linker_load : struct { @"type" : enum { got , direct }, sym_index : u32 },
145
+ /// * import - the value is referenced indirectly via import entry index (the linker emits an import-type reloc)
146
+ linker_load : struct { @"type" : enum { got , direct , import }, sym_index : u32 },
146
147
/// The value is one of the stack variables.
147
148
///
148
149
/// If the type is a pointer, it means the pointer address is in
@@ -1117,13 +1118,11 @@ fn truncRegister(
1117
1118
});
1118
1119
},
1119
1120
32 , 64 = > {
1120
- assert (dest_reg .size () == operand_reg .size ());
1121
-
1122
1121
_ = try self .addInst (.{
1123
1122
.tag = .mov_register ,
1124
1123
.data = .{ .rr = .{
1125
- .rd = dest_reg ,
1126
- .rn = operand_reg ,
1124
+ .rd = if ( int_bits == 32 ) dest_reg . toW () else dest_reg . toX () ,
1125
+ .rn = if ( int_bits == 32 ) operand_reg . toW () else operand_reg . toX () ,
1127
1126
} },
1128
1127
});
1129
1128
},
@@ -3719,14 +3718,21 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
3719
3718
const tag : Mir.Inst.Tag = switch (load_struct .@"type" ) {
3720
3719
.got = > .load_memory_ptr_got ,
3721
3720
.direct = > .load_memory_ptr_direct ,
3721
+ .import = > unreachable ,
3722
3722
};
3723
3723
const mod = self .bin_file .options .module .? ;
3724
+ const owner_decl = mod .declPtr (self .mod_fn .owner_decl );
3725
+ const atom_index = switch (self .bin_file .tag ) {
3726
+ .macho = > owner_decl .link .macho .sym_index ,
3727
+ .coff = > owner_decl .link .coff .sym_index ,
3728
+ else = > unreachable , // unsupported target format
3729
+ };
3724
3730
_ = try self .addInst (.{
3725
3731
.tag = tag ,
3726
3732
.data = .{
3727
3733
.payload = try self .addExtra (Mir.LoadMemoryPie {
3728
3734
.register = @enumToInt (src_reg ),
3729
- .atom_index = mod . declPtr ( self . mod_fn . owner_decl ). link . macho . sym_index ,
3735
+ .atom_index = atom_index ,
3730
3736
.sym_index = load_struct .sym_index ,
3731
3737
}),
3732
3738
},
@@ -4057,6 +4063,45 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
4057
4063
} else {
4058
4064
return self .fail ("TODO implement calling bitcasted functions" , .{});
4059
4065
}
4066
+ } else if (self .bin_file .cast (link .File .Coff )) | coff_file | {
4067
+ if (func_value .castTag (.function )) | func_payload | {
4068
+ const func = func_payload .data ;
4069
+ const fn_owner_decl = mod .declPtr (func .owner_decl );
4070
+ try self .genSetReg (Type .initTag (.u64 ), .x30 , .{
4071
+ .linker_load = .{
4072
+ .@"type" = .got ,
4073
+ .sym_index = fn_owner_decl .link .coff .sym_index ,
4074
+ },
4075
+ });
4076
+ // blr x30
4077
+ _ = try self .addInst (.{
4078
+ .tag = .blr ,
4079
+ .data = .{ .reg = .x30 },
4080
+ });
4081
+ } else if (func_value .castTag (.extern_fn )) | func_payload | {
4082
+ const extern_fn = func_payload .data ;
4083
+ const decl_name = mod .declPtr (extern_fn .owner_decl ).name ;
4084
+ if (extern_fn .lib_name ) | lib_name | {
4085
+ log .debug ("TODO enforce that '{s}' is expected in '{s}' library" , .{
4086
+ decl_name ,
4087
+ lib_name ,
4088
+ });
4089
+ }
4090
+ const sym_index = try coff_file .getGlobalSymbol (mem .sliceTo (decl_name , 0 ));
4091
+ try self .genSetReg (Type .initTag (.u64 ), .x30 , .{
4092
+ .linker_load = .{
4093
+ .@"type" = .import ,
4094
+ .sym_index = sym_index ,
4095
+ },
4096
+ });
4097
+ // blr x30
4098
+ _ = try self .addInst (.{
4099
+ .tag = .blr ,
4100
+ .data = .{ .reg = .x30 },
4101
+ });
4102
+ } else {
4103
+ return self .fail ("TODO implement calling bitcasted functions" , .{});
4104
+ }
4060
4105
} else if (self .bin_file .cast (link .File .Plan9 )) | p9 | {
4061
4106
if (func_value .castTag (.function )) | func_payload | {
4062
4107
try p9 .seeDecl (func_payload .data .owner_decl );
@@ -4077,8 +4122,6 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
4077
4122
} else {
4078
4123
return self .fail ("TODO implement calling bitcasted functions" , .{});
4079
4124
}
4080
- } else if (self .bin_file .cast (link .File .Coff )) | _ | {
4081
- return self .fail ("TODO implement calling in COFF for {}" , .{self .target .cpu .arch });
4082
4125
} else unreachable ;
4083
4126
} else {
4084
4127
assert (ty .zigTypeTag () == .Pointer );
@@ -5161,14 +5204,21 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
5161
5204
const tag : Mir.Inst.Tag = switch (load_struct .@"type" ) {
5162
5205
.got = > .load_memory_ptr_got ,
5163
5206
.direct = > .load_memory_ptr_direct ,
5207
+ .import = > unreachable ,
5164
5208
};
5165
5209
const mod = self .bin_file .options .module .? ;
5210
+ const owner_decl = mod .declPtr (self .mod_fn .owner_decl );
5211
+ const atom_index = switch (self .bin_file .tag ) {
5212
+ .macho = > owner_decl .link .macho .sym_index ,
5213
+ .coff = > owner_decl .link .coff .sym_index ,
5214
+ else = > unreachable , // unsupported target format
5215
+ };
5166
5216
_ = try self .addInst (.{
5167
5217
.tag = tag ,
5168
5218
.data = .{
5169
5219
.payload = try self .addExtra (Mir.LoadMemoryPie {
5170
5220
.register = @enumToInt (src_reg ),
5171
- .atom_index = mod . declPtr ( self . mod_fn . owner_decl ). link . macho . sym_index ,
5221
+ .atom_index = atom_index ,
5172
5222
.sym_index = load_struct .sym_index ,
5173
5223
}),
5174
5224
},
@@ -5268,14 +5318,21 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
5268
5318
const tag : Mir.Inst.Tag = switch (load_struct .@"type" ) {
5269
5319
.got = > .load_memory_got ,
5270
5320
.direct = > .load_memory_direct ,
5321
+ .import = > .load_memory_import ,
5271
5322
};
5272
5323
const mod = self .bin_file .options .module .? ;
5324
+ const owner_decl = mod .declPtr (self .mod_fn .owner_decl );
5325
+ const atom_index = switch (self .bin_file .tag ) {
5326
+ .macho = > owner_decl .link .macho .sym_index ,
5327
+ .coff = > owner_decl .link .coff .sym_index ,
5328
+ else = > unreachable , // unsupported target format
5329
+ };
5273
5330
_ = try self .addInst (.{
5274
5331
.tag = tag ,
5275
5332
.data = .{
5276
5333
.payload = try self .addExtra (Mir.LoadMemoryPie {
5277
5334
.register = @enumToInt (reg ),
5278
- .atom_index = mod . declPtr ( self . mod_fn . owner_decl ). link . macho . sym_index ,
5335
+ .atom_index = atom_index ,
5279
5336
.sym_index = load_struct .sym_index ,
5280
5337
}),
5281
5338
},
@@ -5455,14 +5512,21 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
5455
5512
const tag : Mir.Inst.Tag = switch (load_struct .@"type" ) {
5456
5513
.got = > .load_memory_ptr_got ,
5457
5514
.direct = > .load_memory_ptr_direct ,
5515
+ .import = > unreachable ,
5458
5516
};
5459
5517
const mod = self .bin_file .options .module .? ;
5518
+ const owner_decl = mod .declPtr (self .mod_fn .owner_decl );
5519
+ const atom_index = switch (self .bin_file .tag ) {
5520
+ .macho = > owner_decl .link .macho .sym_index ,
5521
+ .coff = > owner_decl .link .coff .sym_index ,
5522
+ else = > unreachable , // unsupported target format
5523
+ };
5460
5524
_ = try self .addInst (.{
5461
5525
.tag = tag ,
5462
5526
.data = .{
5463
5527
.payload = try self .addExtra (Mir.LoadMemoryPie {
5464
5528
.register = @enumToInt (src_reg ),
5465
- .atom_index = mod . declPtr ( self . mod_fn . owner_decl ). link . macho . sym_index ,
5529
+ .atom_index = atom_index ,
5466
5530
.sym_index = load_struct .sym_index ,
5467
5531
}),
5468
5532
},
@@ -5775,7 +5839,13 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne
5775
5839
.sym_index = decl .link .macho .sym_index ,
5776
5840
} };
5777
5841
} else if (self .bin_file .cast (link .File .Coff )) | _ | {
5778
- return self .fail ("TODO codegen COFF const Decl pointer" , .{});
5842
+ // Because COFF is PIE-always-on, we defer memory address resolution until
5843
+ // the linker has enough info to perform relocations.
5844
+ assert (decl .link .coff .sym_index != 0 );
5845
+ return MCValue { .linker_load = .{
5846
+ .@"type" = .got ,
5847
+ .sym_index = decl .link .coff .sym_index ,
5848
+ } };
5779
5849
} else if (self .bin_file .cast (link .File .Plan9 )) | p9 | {
5780
5850
try p9 .seeDecl (decl_index );
5781
5851
const got_addr = p9 .bases .data + decl .link .plan9 .got_index .? * ptr_bytes ;
@@ -5799,7 +5869,10 @@ fn lowerUnnamedConst(self: *Self, tv: TypedValue) InnerError!MCValue {
5799
5869
.sym_index = local_sym_index ,
5800
5870
} };
5801
5871
} else if (self .bin_file .cast (link .File .Coff )) | _ | {
5802
- return self .fail ("TODO lower unnamed const in COFF" , .{});
5872
+ return MCValue { .linker_load = .{
5873
+ .@"type" = .direct ,
5874
+ .sym_index = local_sym_index ,
5875
+ } };
5803
5876
} else if (self .bin_file .cast (link .File .Plan9 )) | _ | {
5804
5877
return self .fail ("TODO lower unnamed const in Plan9" , .{});
5805
5878
} else {
0 commit comments