authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-07-04 13:56:17-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-07-27 14:44:41-04:00
logf2f770fdd3818d1ec14e51ce752aca5beb08e150
treedcf49a573dde69f7978527e2a80627152cca3fd8
parent703baa4cd662e55ba39ea14ae2f30209e7ff023b

llvm: implement c abi for x86


9 files changed, 315 insertions(+), 33 deletions(-)

lib/std/Target.zig+3-6
...@@ -1797,6 +1797,7 @@ pub const Cpu = struct {...@@ -1797,6 +1797,7 @@ pub const Cpu = struct {
17971797
1798 .x86_sysv,1798 .x86_sysv,
1799 .x86_win,1799 .x86_win,
1800 .x86_mingw,
1800 .x86_stdcall,1801 .x86_stdcall,
1801 .x86_fastcall,1802 .x86_fastcall,
1802 .x86_thiscall,1803 .x86_thiscall,
...@@ -3664,18 +3665,14 @@ pub fn cMaxIntAlignment(target: *const Target) u16 {...@@ -3664,18 +3665,14 @@ pub fn cMaxIntAlignment(target: *const Target) u16 {
3664pub fn cCallingConvention(target: *const Target) ?std.builtin.CallingConvention {3665pub fn cCallingConvention(target: *const Target) ?std.builtin.CallingConvention {
3665 return switch (target.cpu.arch) {3666 return switch (target.cpu.arch) {
3666 .x86_64 => switch (target.os.tag) {3667 .x86_64 => switch (target.os.tag) {
3667 .windows,3668 .windows, .uefi => .{ .x86_64_win = .{} },
3668 .uefi,
3669 => .{ .x86_64_win = .{} },
3670 else => switch (target.abi) {3669 else => switch (target.abi) {
3671 .gnux32, .muslx32, .x32 => .{ .x86_64_x32 = .{} },3670 .gnux32, .muslx32, .x32 => .{ .x86_64_x32 = .{} },
3672 else => .{ .x86_64_sysv = .{} },3671 else => .{ .x86_64_sysv = .{} },
3673 },3672 },
3674 },3673 },
3675 .x86 => switch (target.os.tag) {3674 .x86 => switch (target.os.tag) {
3676 .windows,3675 .windows, .uefi => if (target.isMinGW()) .{ .x86_mingw = .{} } else .{ .x86_win = .{} },
3677 .uefi,
3678 => .{ .x86_win = .{} },
3679 else => .{ .x86_sysv = .{} },3676 else => .{ .x86_sysv = .{} },
3680 },3677 },
3681 .x86_16 => .{ .x86_16_cdecl = .{} },3678 .x86_16 => .{ .x86_16_cdecl = .{} },
lib/std/lang.zig+1
...@@ -214,6 +214,7 @@ pub const CallingConvention = union(enum(u8)) {...@@ -214,6 +214,7 @@ pub const CallingConvention = union(enum(u8)) {
214 // Calling conventions for the `x86` architecture.214 // Calling conventions for the `x86` architecture.
215 x86_sysv: X86RegparmOptions,215 x86_sysv: X86RegparmOptions,
216 x86_win: X86RegparmOptions,216 x86_win: X86RegparmOptions,
217 x86_mingw: X86RegparmOptions,
217 x86_stdcall: X86RegparmOptions,218 x86_stdcall: X86RegparmOptions,
218 x86_fastcall: CommonOptions,219 x86_fastcall: CommonOptions,
219 x86_thiscall: CommonOptions,220 x86_thiscall: CommonOptions,
src/Sema.zig+1
...@@ -8501,6 +8501,7 @@ const calling_conventions_supporting_var_args = [_]std.lang.CallingConvention.Ta...@@ -8501,6 +8501,7 @@ const calling_conventions_supporting_var_args = [_]std.lang.CallingConvention.Ta
8501 .x86_64_win,8501 .x86_64_win,
8502 .x86_sysv,8502 .x86_sysv,
8503 .x86_win,8503 .x86_win,
8504 .x86_mingw,
8504 .aarch64_aapcs,8505 .aarch64_aapcs,
8505 .aarch64_aapcs_darwin,8506 .aarch64_aapcs_darwin,
8506 .aarch64_aapcs_win,8507 .aarch64_aapcs_win,
src/Zcu.zig+2
...@@ -4644,6 +4644,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum)...@@ -4644,6 +4644,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum)
46444644
4645 .x86_sysv,4645 .x86_sysv,
4646 .x86_win,4646 .x86_win,
4647 .x86_mingw,
4647 .x86_stdcall,4648 .x86_stdcall,
4648 => |opts| opts.incoming_stack_alignment == null and opts.register_params == 0,4649 => |opts| opts.incoming_stack_alignment == null and opts.register_params == 0,
46494650
...@@ -4678,6 +4679,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum)...@@ -4678,6 +4679,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum)
4678 .stage2_x86 => switch (cc) {4679 .stage2_x86 => switch (cc) {
4679 .x86_sysv,4680 .x86_sysv,
4680 .x86_win,4681 .x86_win,
4682 .x86_mingw,
4681 => |opts| opts.incoming_stack_alignment == null and opts.register_params == 0,4683 => |opts| opts.incoming_stack_alignment == null and opts.register_params == 0,
4682 .naked => true,4684 .naked => true,
4683 else => false,4685 else => false,
src/codegen.zig+195
...@@ -1124,6 +1124,201 @@ pub fn fieldOffset(ptr_agg_ty: Type, ptr_field_ty: Type, field_index: u32, zcu:...@@ -1124,6 +1124,201 @@ pub fn fieldOffset(ptr_agg_ty: Type, ptr_field_ty: Type, field_index: u32, zcu:
1124 };1124 };
1125}1125}
11261126
1127pub const FlattenedItem = struct { offset: u64, type: ?Type };
1128pub fn flattenType(items_buf: []FlattenedItem, ty: Type, zcu: *Zcu, opts: struct {
1129 offset: u64 = 0,
1130 allow_arrays: bool = true,
1131 fn increaseOffset(opts: @This(), offset: u64) @This() {
1132 return .{
1133 .offset = opts.offset + offset,
1134 .allow_arrays = opts.allow_arrays,
1135 };
1136 }
1137}) ?[]FlattenedItem {
1138 const ip = &zcu.intern_pool;
1139 switch (ip.indexToKey(ty.toIntern())) {
1140 .int_type => |int_type| {
1141 if (int_type.bits == 0) return items_buf[0..0];
1142 if (items_buf.len < 1) return null;
1143 const items = items_buf[0..1];
1144 items.* = .{.{ .offset = opts.offset, .type = ty }};
1145 return items;
1146 },
1147 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
1148 .one, .many, .c => {
1149 if (items_buf.len < 1) return null;
1150 const items = items_buf[0..1];
1151 items.* = .{.{ .offset = opts.offset, .type = ty }};
1152 return items;
1153 },
1154 .slice => {
1155 if (items_buf.len < 2) return null;
1156 const items = items_buf[0..2];
1157 const ptr_field_ty = ty.slicePtrFieldType(zcu);
1158 items.* = .{
1159 .{ .offset = opts.offset, .type = ptr_field_ty },
1160 .{ .offset = opts.offset + ptr_field_ty.abiSize(zcu), .type = .usize },
1161 };
1162 return items;
1163 },
1164 },
1165 .array_type => |array_type| {
1166 const len = array_type.lenIncludingSentinel();
1167 if (len == 0) return items_buf[0..0];
1168 const elem_ty: Type = .fromInterned(array_type.child);
1169 const elem_items = flattenType(items_buf, elem_ty, zcu, opts) orelse return null;
1170 if (elem_items.len == 0) return items_buf[0..0];
1171 if (!opts.allow_arrays) return null;
1172 const items_len, const items_overflow = @mulWithOverflow(elem_items.len, len);
1173 if (items_overflow != 0 or items_buf.len < items_len) return null;
1174 var items_index = elem_items.len;
1175 const elem_size = elem_ty.abiSize(zcu);
1176 var elem_offset: u64 = elem_size;
1177 while (items_index != items_len) : ({
1178 items_index += elem_items.len;
1179 elem_offset += elem_size;
1180 }) for (items_buf[items_index..][0..elem_items.len], elem_items) |*item, elem_item| {
1181 item.* = .{ .offset = elem_offset + elem_item.offset, .type = elem_item.type };
1182 };
1183 return items_buf[0..@intCast(items_len)];
1184 },
1185 .vector_type => |vector_type| {
1186 if (vector_type.len == 0) return items_buf[0..0];
1187 if (items_buf.len < 1) return null;
1188 const items = items_buf[0..1];
1189 items.* = .{.{ .offset = opts.offset, .type = ty }};
1190 return items;
1191 },
1192 .opt_type, .error_union_type => return null,
1193 .simple_type => |simple_type| switch (simple_type) {
1194 .f16,
1195 .f32,
1196 .f64,
1197 .f80,
1198 .f128,
1199 .usize,
1200 .isize,
1201 .c_char,
1202 .c_short,
1203 .c_ushort,
1204 .c_int,
1205 .c_uint,
1206 .c_long,
1207 .c_ulong,
1208 .c_longlong,
1209 .c_ulonglong,
1210 .c_longdouble,
1211 .bool,
1212 .anyerror,
1213 => {
1214 if (items_buf.len < 1) return null;
1215 const items = items_buf[0..1];
1216 items.* = .{.{ .offset = opts.offset, .type = ty }};
1217 return items;
1218 },
1219 .anyopaque, .noreturn => return null,
1220 .void,
1221 .type,
1222 .comptime_int,
1223 .comptime_float,
1224 .null,
1225 .undefined,
1226 .enum_literal,
1227 => return items_buf[0..0],
1228 .adhoc_inferred_error_set, .generic_poison => unreachable,
1229 },
1230 .struct_type => {
1231 const loaded_struct = ip.loadStructType(ty.toIntern());
1232 switch (loaded_struct.layout) {
1233 .auto, .@"extern" => {},
1234 .@"packed" => return flattenType(items_buf, .fromInterned(
1235 loaded_struct.packed_backing_int_type,
1236 ), zcu, opts),
1237 }
1238 var items_len: usize = 0;
1239 var offset: u64 = 0;
1240 var field_it = loaded_struct.iterateRuntimeOrder(ip);
1241 while (field_it.next()) |field_index| {
1242 const field_ty: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]);
1243 const field_offset = loaded_struct.field_offsets.get(ip)[field_index];
1244 if (field_offset - offset > 0 and
1245 (items_len == 0 or items_buf[items_len - 1].type != null))
1246 {
1247 if (items_len == items_buf.len) return null;
1248 items_buf[items_len] = .{ .offset = offset, .type = null };
1249 items_len += 1;
1250 }
1251 items_len += (flattenType(items_buf[items_len..], field_ty, zcu, opts.increaseOffset(
1252 field_offset,
1253 )) orelse return null).len;
1254 offset = field_offset + field_ty.abiSize(zcu);
1255 }
1256 if (ty.abiSize(zcu) - offset > 0 and
1257 (items_len == 0 or items_buf[items_len - 1].type != null))
1258 {
1259 if (items_len == items_buf.len) return null;
1260 items_buf[items_len] = .{ .offset = offset, .type = null };
1261 items_len += 1;
1262 }
1263 return items_buf[0..items_len];
1264 },
1265 .tuple_type => |tuple_type| {
1266 if (items_buf.len < tuple_type.types.len) return null;
1267 var items_len: usize = 0;
1268 var offset: u64 = 0;
1269 for (tuple_type.types.get(ip)) |field_ty_ip| {
1270 const field_ty: Type = .fromInterned(field_ty_ip);
1271 offset = field_ty.abiAlignment(zcu).forward(offset);
1272 items_len += (flattenType(items_buf[items_len..], field_ty, zcu, opts.increaseOffset(
1273 offset,
1274 )) orelse return null).len;
1275 offset += field_ty.abiSize(zcu);
1276 }
1277 return items_buf[0..items_len];
1278 },
1279 .union_type => {
1280 const loaded_union = ip.loadUnionType(ty.toIntern());
1281 return switch (loaded_union.layout) {
1282 .auto, .@"extern" => return null,
1283 .@"packed" => return flattenType(items_buf, .fromInterned(
1284 loaded_union.packed_backing_int_type,
1285 ), zcu, opts),
1286 };
1287 },
1288 .opaque_type, .spirv_type, .func_type => return null,
1289 .enum_type => return flattenType(items_buf, .fromInterned(
1290 ip.loadEnumType(ty.toIntern()).int_tag_type,
1291 ), zcu, opts),
1292 .error_set_type, .inferred_error_set_type => {
1293 if (items_buf.len < 1) return null;
1294 const items = items_buf[0..1];
1295 items.* = .{.{ .offset = opts.offset, .type = ty }};
1296 return items;
1297 },
1298 .anyframe_type,
1299 // values, not types
1300 .undef,
1301 .simple_value,
1302 .@"extern",
1303 .func,
1304 .int,
1305 .err,
1306 .error_union,
1307 .enum_literal,
1308 .enum_tag,
1309 .float,
1310 .ptr,
1311 .slice,
1312 .opt,
1313 .aggregate,
1314 .un,
1315 .bitpack,
1316 // memoization, not types
1317 .memoized_call,
1318 => unreachable,
1319 }
1320}
1321
1127test {1322test {
1128 _ = aarch64;1323 _ = aarch64;
1129}1324}
src/codegen/c.zig+1-1
...@@ -7289,7 +7289,7 @@ fn toCallingConvention(cc: std.lang.CallingConvention, zcu: *Zcu) ?[]const u8 {...@@ -7289,7 +7289,7 @@ fn toCallingConvention(cc: std.lang.CallingConvention, zcu: *Zcu) ?[]const u8 {
7289 .x86_16_cdecl => "cdecl",7289 .x86_16_cdecl => "cdecl",
7290 .x86_16_regparmcall => "regparmcall",7290 .x86_16_regparmcall => "regparmcall",
7291 .x86_64_sysv, .x86_sysv => "sysv_abi",7291 .x86_64_sysv, .x86_sysv => "sysv_abi",
7292 .x86_64_win, .x86_win => "ms_abi",7292 .x86_64_win, .x86_win, .x86_mingw => "ms_abi",
7293 .x86_16_stdcall, .x86_stdcall => "stdcall",7293 .x86_16_stdcall, .x86_stdcall => "stdcall",
7294 .x86_fastcall => "fastcall",7294 .x86_fastcall => "fastcall",
7295 .x86_thiscall => "thiscall",7295 .x86_thiscall => "thiscall",
src/codegen/llvm.zig+13-5
...@@ -4235,19 +4235,26 @@ pub const Object = struct {...@@ -4235,19 +4235,26 @@ pub const Object = struct {
4235 };4235 };
4236 }4236 }
42374237
4238 pub const Byval = struct { alignment: InternPool.Alignment = .none };
4238 pub fn addByRefParamAttrs(4239 pub fn addByRefParamAttrs(
4239 o: *Object,4240 o: *Object,
4240 attributes: *Builder.FunctionAttributes.Wip,4241 attributes: *Builder.FunctionAttributes.Wip,
4241 llvm_arg_i: u32,4242 llvm_arg_i: u32,
4242 byval: bool,4243 maybe_byval: ?Byval,
4243 param_ty: Type,4244 param_ty: Type,
4244 ) Allocator.Error!void {4245 ) Allocator.Error!void {
4245 const llvm_param_ty = try o.lowerType(param_ty, .in_memory);4246 const llvm_param_ty = try o.lowerType(param_ty, .in_memory);
4246 const alignment = param_ty.abiAlignment(o.zcu).toLlvm();
4247 try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
4248 try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder);4247 try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder);
4249 try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = .wrap(alignment) }, &o.builder);4248 try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder);
4250 if (byval) try attributes.addParamAttr(llvm_arg_i, .{ .byval = llvm_param_ty }, &o.builder);4249 try attributes.addParamAttr(llvm_arg_i, .noundef, &o.builder);
4250 const alignment = if (maybe_byval) |byval| alignment: {
4251 try attributes.addParamAttr(llvm_arg_i, .{ .byval = llvm_param_ty }, &o.builder);
4252 break :alignment byval.alignment;
4253 } else .none;
4254 try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = .wrap(switch (alignment) {
4255 .none => param_ty.abiAlignment(o.zcu),
4256 else => alignment,
4257 }.toLlvm()) }, &o.builder);
4251 }4258 }
42524259
4253 pub fn getErrorNameTable(o: *Object) Allocator.Error!Builder.Variable.Index {4260 pub fn getErrorNameTable(o: *Object) Allocator.Error!Builder.Variable.Index {
...@@ -4598,6 +4605,7 @@ pub fn toLlvmCallConvTag(cc_tag: std.lang.CallingConvention.Tag, target: *const...@@ -4598,6 +4605,7 @@ pub fn toLlvmCallConvTag(cc_tag: std.lang.CallingConvention.Tag, target: *const
4598 .x86_16_interrupt,4605 .x86_16_interrupt,
4599 .x86_sysv,4606 .x86_sysv,
4600 .x86_win,4607 .x86_win,
4608 .x86_mingw,
4601 .x86_thiscall_mingw,4609 .x86_thiscall_mingw,
4602 .x86_64_x32,4610 .x86_64_x32,
4603 .aarch64_aapcs,4611 .aarch64_aapcs,
src/codegen/llvm/FuncGen.zig+98-19
...@@ -218,7 +218,7 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void {...@@ -218,7 +218,7 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void {
218 switch (lowering) {218 switch (lowering) {
219 .no_bits => continue,219 .no_bits => continue,
220 .byval => {220 .byval => {
221 assert(!it.byval_attr);221 assert(it.byval_attr == null);
222 const param_index = it.zig_index - 1;222 const param_index = it.zig_index - 1;
223 const param_ty: Type = .fromInterned(param_types[param_index]);223 const param_ty: Type = .fromInterned(param_types[param_index]);
224 const param = fg.wip.arg(it.llvm_index - 1);224 const param = fg.wip.arg(it.llvm_index - 1);
...@@ -237,15 +237,16 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void {...@@ -237,15 +237,16 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void {
237 .byref, .byref_mut => {237 .byref, .byref_mut => {
238 const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]);238 const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]);
239 const param = fg.wip.arg(it.llvm_index - 1);239 const param = fg.wip.arg(it.llvm_index - 1);
240 const alignment = if (it.byval_attr) |byval_attr| byval_attr.alignment else .none;
240241
241 if (isByRef(param_ty, zcu)) {242 if (alignment == .none and isByRef(param_ty, zcu)) {
242 args.appendAssumeCapacity(param);243 args.appendAssumeCapacity(param);
243 } else {244 } else {
244 args.appendAssumeCapacity(try fg.load(param, .none, param_ty, .normal));245 args.appendAssumeCapacity(try fg.load(param, alignment, param_ty, .normal));
245 }246 }
246 },247 },
247 .abi_sized_int => {248 .abi_sized_int => {
248 assert(!it.byval_attr);249 assert(it.byval_attr == null);
249 const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]);250 const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]);
250 const param = fg.wip.arg(it.llvm_index - 1);251 const param = fg.wip.arg(it.llvm_index - 1);
251252
...@@ -260,7 +261,7 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void {...@@ -260,7 +261,7 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void {
260 }261 }
261 },262 },
262 .slice => {263 .slice => {
263 assert(!it.byval_attr);264 assert(it.byval_attr == null);
264 const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]);265 const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]);
265 assert(!isByRef(param_ty, zcu));266 assert(!isByRef(param_ty, zcu));
266 const slice_val = try fg.wip.buildAggregate(267 const slice_val = try fg.wip.buildAggregate(
...@@ -271,7 +272,7 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void {...@@ -271,7 +272,7 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void {
271 args.appendAssumeCapacity(slice_val);272 args.appendAssumeCapacity(slice_val);
272 },273 },
273 .multiple_llvm_types => {274 .multiple_llvm_types => {
274 assert(!it.byval_attr);275 assert(it.byval_attr == null);
275 const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]);276 const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]);
276 const param_alignment = param_ty.abiAlignment(zcu);277 const param_alignment = param_ty.abiAlignment(zcu);
277 const llvm_ty = try o.builder.arrayType(it.offsets_buffer[it.types_len], .i8);278 const llvm_ty = try o.builder.arrayType(it.offsets_buffer[it.types_len], .i8);
...@@ -963,7 +964,7 @@ fn buildCall(...@@ -963,7 +964,7 @@ fn buildCall(
963 => continue,964 => continue,
964965
965 .slice => {966 .slice => {
966 assert(!it.byval_attr);967 assert(it.byval_attr == null);
967 const param_ty = Type.fromInterned(fn_info.param_types[it.zig_index - 1]);968 const param_ty = Type.fromInterned(fn_info.param_types[it.zig_index - 1]);
968 const ptr_info = param_ty.ptrInfo(zcu);969 const ptr_info = param_ty.ptrInfo(zcu);
969 const llvm_arg_i = it.llvm_index - 2;970 const llvm_arg_i = it.llvm_index - 2;
...@@ -6913,7 +6914,7 @@ const ParamTypeIterator = struct {...@@ -6913,7 +6914,7 @@ const ParamTypeIterator = struct {
6913 types_len: u32,6914 types_len: u32,
6914 types_buffer: [8]Builder.Type,6915 types_buffer: [8]Builder.Type,
6915 offsets_buffer: [9]u64,6916 offsets_buffer: [9]u64,
6916 byval_attr: bool,6917 byval_attr: ?Object.Byval,
69176918
6918 const Lowering = union(enum) {6919 const Lowering = union(enum) {
6919 no_bits,6920 no_bits,
...@@ -6931,7 +6932,7 @@ const ParamTypeIterator = struct {...@@ -6931,7 +6932,7 @@ const ParamTypeIterator = struct {
6931 pub fn next(it: *ParamTypeIterator) Allocator.Error!?Lowering {6932 pub fn next(it: *ParamTypeIterator) Allocator.Error!?Lowering {
6932 if (it.zig_index >= it.param_types.len) return null;6933 if (it.zig_index >= it.param_types.len) return null;
6933 const ty = it.param_types[it.zig_index];6934 const ty = it.param_types[it.zig_index];
6934 it.byval_attr = false;6935 it.byval_attr = null;
6935 return nextInner(it, Type.fromInterned(ty));6936 return nextInner(it, Type.fromInterned(ty));
6936 }6937 }
69376938
...@@ -7008,7 +7009,7 @@ const ParamTypeIterator = struct {...@@ -7008,7 +7009,7 @@ const ParamTypeIterator = struct {
7008 it.llvm_index += 1;7009 it.llvm_index += 1;
7009 switch (arm_c_abi.classifyType(ty, zcu, .arg)) {7010 switch (arm_c_abi.classifyType(ty, zcu, .arg)) {
7010 .memory => {7011 .memory => {
7011 it.byval_attr = true;7012 it.byval_attr = .{};
7012 return .byref;7013 return .byref;
7013 },7014 },
7014 .byval => return .byval,7015 .byval => return .byval,
...@@ -7086,7 +7087,7 @@ const ParamTypeIterator = struct {...@@ -7086,7 +7087,7 @@ const ParamTypeIterator = struct {
7086 it.llvm_index += 1;7087 it.llvm_index += 1;
7087 switch (mips_c_abi.classifyType(ty, zcu, .arg)) {7088 switch (mips_c_abi.classifyType(ty, zcu, .arg)) {
7088 .memory => {7089 .memory => {
7089 it.byval_attr = true;7090 it.byval_attr = .{};
7090 return .byref;7091 return .byref;
7091 },7092 },
7092 .byval => return .byval,7093 .byval => return .byval,
...@@ -7158,15 +7159,15 @@ const ParamTypeIterator = struct {...@@ -7158,15 +7159,15 @@ const ParamTypeIterator = struct {
7158 it.types_buffer[0..1].* = .{try it.object.lowerType(scalar_ty, .as_value)};7159 it.types_buffer[0..1].* = .{try it.object.lowerType(scalar_ty, .as_value)};
7159 it.offsets_buffer[0..2].* = .{ 0, scalar_ty.abiSize(zcu) };7160 it.offsets_buffer[0..2].* = .{ 0, scalar_ty.abiSize(zcu) };
7160 it.types_len = 1;7161 it.types_len = 1;
7161 it.llvm_index += 1;
7162 it.zig_index += 1;7162 it.zig_index += 1;
7163 it.llvm_index += 1;
7163 return .multiple_llvm_types;7164 return .multiple_llvm_types;
7164 }7165 }
7165 },7166 },
7166 .indirect => {7167 .indirect => {
7167 it.zig_index += 1;7168 it.zig_index += 1;
7168 it.llvm_index += 1;7169 it.llvm_index += 1;
7169 it.byval_attr = true;7170 it.byval_attr = .{};
7170 return .byref;7171 return .byref;
7171 },7172 },
7172 },7173 },
...@@ -7177,9 +7178,55 @@ const ParamTypeIterator = struct {...@@ -7177,9 +7178,55 @@ const ParamTypeIterator = struct {
7177 if (isScalar(zcu, ty)) {7178 if (isScalar(zcu, ty)) {
7178 return .byval;7179 return .byval;
7179 } else {7180 } else {
7180 it.byval_attr = true;7181 it.byval_attr = .{};
7182 return .byref;
7183 }
7184 },
7185 .x86_sysv, .x86_win, .x86_mingw => {
7186 if (isByRef(ty, zcu)) {
7187 var items_buf: [1]codegen.FlattenedItem = undefined;
7188 if (codegen.flattenType(&items_buf, ty, zcu, .{
7189 .allow_arrays = false,
7190 })) |items| one_float: {
7191 if (items.len != 1 or items[0].offset != 0) break :one_float;
7192 const item_ty = items[0].type orelse break :one_float;
7193 if (!item_ty.isRuntimeFloat()) break :one_float;
7194 it.types_buffer[0..1].*, it.offsets_buffer[0..2].* =
7195 switch (item_ty.floatBits(zcu.getTarget())) {
7196 else => unreachable,
7197 32 => .{ .{.float}, .{ 0, 4 } },
7198 64 => .{ .{.double}, .{ 0, 8 } },
7199 16, 80, 128 => break :one_float,
7200 };
7201 it.types_len = 1;
7202 it.zig_index += 1;
7203 it.llvm_index += 1;
7204 return .multiple_llvm_types;
7205 }
7206 it.zig_index += 1;
7207 it.llvm_index += 1;
7208 it.byval_attr = .{ .alignment = .@"4" };
7181 return .byref;7209 return .byref;
7182 }7210 }
7211 if (ty.isAbiInt(zcu)) switch (ty.intInfo(zcu).bits) {
7212 else => unreachable,
7213 8, 16, 32, 64 => {
7214 it.zig_index += 1;
7215 it.llvm_index += 1;
7216 return .byval;
7217 },
7218 128 => {
7219 it.types_buffer[0..2].* = .{ .i64, .i64 };
7220 it.offsets_buffer[0..3].* = .{ 0, 8, 16 };
7221 it.types_len = 2;
7222 it.zig_index += 1;
7223 it.llvm_index += 2;
7224 return .multiple_llvm_types;
7225 },
7226 };
7227 it.zig_index += 1;
7228 it.llvm_index += 1;
7229 return .byval;
7183 },7230 },
7184 .x86_64_sysv, .x86_64_x32 => return try it.next_x86_64_sysv(ty),7231 .x86_64_sysv, .x86_64_x32 => return try it.next_x86_64_sysv(ty),
7185 .x86_64_win => return it.next_x86_64_win(ty),7232 .x86_64_win => return it.next_x86_64_win(ty),
...@@ -7277,7 +7324,7 @@ const ParamTypeIterator = struct {...@@ -7277,7 +7324,7 @@ const ParamTypeIterator = struct {
7277 .x87 => {7324 .x87 => {
7278 it.zig_index += 1;7325 it.zig_index += 1;
7279 it.llvm_index += 1;7326 it.llvm_index += 1;
7280 it.byval_attr = true;7327 it.byval_attr = .{};
7281 return .byref;7328 return .byref;
7282 },7329 },
7283 .x87up => unreachable,7330 .x87up => unreachable,
...@@ -7285,7 +7332,7 @@ const ParamTypeIterator = struct {...@@ -7285,7 +7332,7 @@ const ParamTypeIterator = struct {
7285 .memory => {7332 .memory => {
7286 it.zig_index += 1;7333 it.zig_index += 1;
7287 it.llvm_index += 1;7334 it.llvm_index += 1;
7288 it.byval_attr = true;7335 it.byval_attr = .{};
7289 return .byref;7336 return .byref;
7290 },7337 },
7291 .win_i128 => unreachable, // windows only7338 .win_i128 => unreachable, // windows only
...@@ -7306,7 +7353,7 @@ const ParamTypeIterator = struct {...@@ -7306,7 +7353,7 @@ const ParamTypeIterator = struct {
7306 if (it.llvm_index + classes_len > 6) {7353 if (it.llvm_index + classes_len > 6) {
7307 it.zig_index += 1;7354 it.zig_index += 1;
7308 it.llvm_index += 1;7355 it.llvm_index += 1;
7309 it.byval_attr = true;7356 it.byval_attr = .{};
7310 return .byref;7357 return .byref;
7311 }7358 }
7312 } else if (!isByRef(ty, zcu)) {7359 } else if (!isByRef(ty, zcu)) {
...@@ -7340,7 +7387,7 @@ pub fn iterateParamTypes(...@@ -7340,7 +7387,7 @@ pub fn iterateParamTypes(
7340 .types_len = undefined,7387 .types_len = undefined,
7341 .types_buffer = undefined,7388 .types_buffer = undefined,
7342 .offsets_buffer = undefined,7389 .offsets_buffer = undefined,
7343 .byval_attr = false,7390 .byval_attr = null,
7344 };7391 };
7345}7392}
73467393
...@@ -7466,7 +7513,39 @@ pub fn fnReturnStrat(o: *Object, cc: std.lang.CallingConvention, ret_ty: Type) A...@@ -7466,7 +7513,39 @@ pub fn fnReturnStrat(o: *Object, cc: std.lang.CallingConvention, ret_ty: Type) A
7466 return .by_val;7513 return .by_val;
7467 } else .sret,7514 } else .sret,
7468 .x86_fastcall => fnReturnStrat_x86_fastcall(o, zcu, ret_ty),7515 .x86_fastcall => fnReturnStrat_x86_fastcall(o, zcu, ret_ty),
7469 .x86_sysv, .x86_win => if (isByRef(ret_ty, zcu)) .sret else .by_val,7516 .x86_sysv, .x86_win, .x86_mingw => if (isByRef(ret_ty, zcu)) {
7517 switch (cc) {
7518 else => unreachable,
7519 .x86_sysv => return .sret,
7520 .x86_win => {},
7521 .x86_mingw => {
7522 var items_buf: [1]codegen.FlattenedItem = undefined;
7523 if (codegen.flattenType(&items_buf, ret_ty, zcu, .{})) |items| one_float: {
7524 if (items.len != 1 or items[0].offset != 0) break :one_float;
7525 const item_ty = items[0].type orelse break :one_float;
7526 if (!item_ty.isRuntimeFloat()) break :one_float;
7527 return .{ .mem_cast = switch (item_ty.floatBits(zcu.getTarget())) {
7528 else => unreachable,
7529 16 => .half,
7530 32 => .float,
7531 64 => .double,
7532 80, 128 => break :one_float,
7533 } };
7534 }
7535 },
7536 }
7537 return switch (ret_ty.abiSize(zcu)) {
7538 0 => .void,
7539 1 => .{ .mem_cast = .i8 },
7540 2 => .{ .mem_cast = .i16 },
7541 4 => .{ .mem_cast = .i32 },
7542 8 => .{ .mem_cast = .i64 },
7543 else => .sret,
7544 };
7545 } else if (ret_ty.isAbiInt(zcu) and ret_ty.intInfo(zcu).bits > 64)
7546 .sret
7547 else
7548 .by_val,
7470 .x86_64_sysv, .x86_64_x32 => fnReturnStrat_x86_64_sysv(o, ret_ty),7549 .x86_64_sysv, .x86_64_x32 => fnReturnStrat_x86_64_sysv(o, ret_ty),
7471 .x86_64_win => fnReturnStrat_x86_64_win(o, ret_ty),7550 .x86_64_win => fnReturnStrat_x86_64_win(o, ret_ty),
7472 // TODO investigate other callconvs7551 // TODO investigate other callconvs
src/link/Dwarf.zig+1-2
...@@ -4151,8 +4151,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co...@@ -4151,8 +4151,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co
4151 .x86_64_regcall_v3_sysv => .LLVM_X86RegCall,4151 .x86_64_regcall_v3_sysv => .LLVM_X86RegCall,
4152 .x86_64_regcall_v4_win => .LLVM_X86RegCall,4152 .x86_64_regcall_v4_win => .LLVM_X86RegCall,
4153 .x86_64_vectorcall => .LLVM_vectorcall,4153 .x86_64_vectorcall => .LLVM_vectorcall,
4154 .x86_sysv => .normal,4154 .x86_sysv, .x86_win, .x86_mingw => .normal,
4155 .x86_win => .normal,
4156 .x86_stdcall => .BORLAND_stdcall,4155 .x86_stdcall => .BORLAND_stdcall,
4157 .x86_fastcall => .BORLAND_msfastcall,4156 .x86_fastcall => .BORLAND_msfastcall,
4158 .x86_thiscall => .BORLAND_thiscall,4157 .x86_thiscall => .BORLAND_thiscall,