authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-03-05 07:19:20+01:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-03-08 12:16:13+01:00
log5466a2f72dd5108846a5318cc70644d8a50bc076
treec0da464815b1d87d185b02d344c7c8de6551c5c9
parent5c57e90ffb6d7498ec3d8bd06ae4a50a8a7a917d

llvm: Replace DataLayoutBuilder with a simple target -> string switch.

This should be a lot easier to maintain. It's also a small step towards eventually making the builder API parse the data layout string in order to answer layout questions that we need to ask during code generation.

1 files changed, 146 insertions(+), 460 deletions(-)

src/codegen/llvm.zig+146-460
......@@ -100,7 +100,6 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![]const u8 {
100100 .kalimba,
101101 .propeller,
102102 => unreachable, // Gated by hasLlvmSupport().
103
104103 };
105104
106105 try llvm_triple.appendSlice(llvm_arch);
......@@ -309,467 +308,154 @@ pub fn supportsTailCall(target: std.Target) bool {
309308 }
310309}
311310
312const DataLayoutBuilder = struct {
313 target: std.Target,
311pub fn dataLayout(target: std.Target) []const u8 {
312 // These data layouts should match Clang.
313 return switch (target.cpu.arch) {
314 .arc => "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-f32:32:32-i64:32-f64:32-a:0:32-n32",
315 .xcore => "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i64:32-f64:32-a:0:32-n32",
316 .hexagon => "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048",
317 .lanai => "E-m:e-p:32:32-i64:64-a:0:32-n32-S64",
318 .aarch64 => if (target.ofmt == .macho)
319 if (target.os.tag == .windows)
320 "e-m:o-i64:64-i128:128-n32:64-S128-Fn32"
321 else if (target.abi == .ilp32)
322 "e-m:o-p:32:32-i64:64-i128:128-n32:64-S128-Fn32"
323 else
324 "e-m:o-i64:64-i128:128-n32:64-S128-Fn32"
325 else if (target.os.tag == .windows)
326 "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128-Fn32"
327 else
328 "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32",
329 .aarch64_be => "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32",
330 .arm => if (target.ofmt == .macho)
331 "e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
332 else
333 "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64",
334 .armeb, .thumbeb => if (target.ofmt == .macho)
335 "E-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
336 else
337 "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64",
338 .thumb => if (target.ofmt == .macho)
339 "e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
340 else if (target.os.tag == .windows)
341 "e-m:w-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
342 else
343 "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64",
344 .avr => "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8",
345 .bpfeb => "E-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
346 .bpfel => "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
347 .msp430 => "e-m:e-p:16:16-i32:16-i64:16-f32:16-f64:16-a:8-n8:16-S16",
348 .mips => "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64",
349 .mipsel => "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64",
350 .mips64 => switch (target.abi) {
351 .gnuabin32, .muslabin32 => "E-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32:64-S128",
352 else => "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128",
353 },
354 .mips64el => switch (target.abi) {
355 .gnuabin32, .muslabin32 => "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32:64-S128",
356 else => "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128",
357 },
358 .m68k => "E-m:e-p:32:16:32-i8:8:8-i16:16:16-i32:16:32-n8:16:32-a:0:16-S16",
359 .powerpc => if (target.os.tag == .aix)
360 "E-m:a-p:32:32-Fi32-i64:64-n32"
361 else
362 "E-m:e-p:32:32-Fn32-i64:64-n32",
363 .powerpcle => "e-m:e-p:32:32-Fn32-i64:64-n32",
364 .powerpc64 => switch (target.os.tag) {
365 .aix => "E-m:a-Fi64-i64:64-n32:64-S128-v256:256:256-v512:512:512",
366 .linux => if (target.abi.isMusl())
367 "E-m:e-Fn32-i64:64-n32:64-S128-v256:256:256-v512:512:512"
368 else
369 "E-m:e-Fi64-i64:64-n32:64-S128-v256:256:256-v512:512:512",
370 .ps3 => "E-m:e-p:32:32-Fi64-i64:64-n32:64",
371 else => if (target.os.tag == .openbsd or
372 (target.os.tag == .freebsd and target.os.version_range.semver.isAtLeast(.{ .major = 13, .minor = 0, .patch = 0 }) orelse false))
373 "E-m:e-Fn32-i64:64-n32:64"
374 else
375 "E-m:e-Fi64-i64:64-n32:64",
376 },
377 .powerpc64le => if (target.os.tag == .linux)
378 "e-m:e-Fn32-i64:64-n32:64-S128-v256:256:256-v512:512:512"
379 else
380 "e-m:e-Fn32-i64:64-n32:64",
381 .nvptx => "e-p:32:32-i64:64-i128:128-v16:16-v32:32-n16:32:64",
382 .nvptx64 => "e-i64:64-i128:128-v16:16-v32:32-n16:32:64",
383 .amdgcn => "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128-p9:192:256:256:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9",
384 .riscv32 => if (std.Target.riscv.featureSetHas(target.cpu.features, .e))
385 "e-m:e-p:32:32-i64:64-n32-S32"
386 else
387 "e-m:e-p:32:32-i64:64-n32-S128",
388 .riscv64 => if (std.Target.riscv.featureSetHas(target.cpu.features, .e))
389 "e-m:e-p:64:64-i64:64-i128:128-n32:64-S64"
390 else
391 "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
392 .sparc => "E-m:e-p:32:32-i64:64-f128:64-n32-S64",
393 .sparc64 => "E-m:e-i64:64-n32:64-S128",
394 .s390x => if (target.os.tag == .zos)
395 "E-m:l-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64"
396 else
397 "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64",
398 .x86 => switch (target.os.tag) {
399 .elfiamcu => "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:32-f64:32-f128:32-n8:16:32-a:0:32-S32",
400 .windows => switch (target.abi) {
401 .cygnus => "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32",
402 .gnu => if (target.ofmt == .coff)
403 "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32"
404 else
405 "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32",
406 else => blk: {
407 const msvc = switch (target.abi) {
408 .none, .msvc => true,
409 else => false,
410 };
314411
315 pub fn format(
316 self: DataLayoutBuilder,
317 comptime _: []const u8,
318 _: std.fmt.FormatOptions,
319 writer: anytype,
320 ) @TypeOf(writer).Error!void {
321 try writer.writeByte(switch (self.target.cpu.arch.endian()) {
322 .little => 'e',
323 .big => 'E',
324 });
325 switch (self.target.cpu.arch) {
326 .amdgcn,
327 .nvptx,
328 .nvptx64,
329 => {},
330 .avr => try writer.writeAll("-P1"),
331 else => try writer.print("-m:{c}", .{@as(u8, switch (self.target.cpu.arch) {
332 .mips, .mipsel => 'm', // Mips mangling: Private symbols get a $ prefix.
333 else => switch (self.target.ofmt) {
334 .elf => 'e', // ELF mangling: Private symbols get a `.L` prefix.
335 //.goff => 'l', // GOFF mangling: Private symbols get a `@` prefix.
336 .macho => 'o', // Mach-O mangling: Private symbols get `L` prefix.
337 // Other symbols get a `_` prefix.
338 .coff => switch (self.target.os.tag) {
339 .uefi, .windows => switch (self.target.cpu.arch) {
340 .x86 => 'x', // Windows x86 COFF mangling: Private symbols get the usual
341 // prefix. Regular C symbols get a `_` prefix. Functions with `__stdcall`,
342 //`__fastcall`, and `__vectorcall` have custom mangling that appends `@N`
343 // where N is the number of bytes used to pass parameters. C++ symbols
344 // starting with `?` are not mangled in any way.
345 else => 'w', // Windows COFF mangling: Similar to x, except that normal C
346 // symbols do not receive a `_` prefix.
347 },
348 else => 'e',
349 },
350 //.xcoff => 'a', // XCOFF mangling: Private symbols get a `L..` prefix.
351 else => 'e',
352 },
353 })}),
354 }
355 const stack_abi = self.target.stackAlignment() * 8;
356 if (self.target.cpu.arch == .csky) try writer.print("-S{d}", .{stack_abi});
357 var any_non_integral = false;
358 const ptr_bit_width = self.target.ptrBitWidth();
359 var default_info = struct { size: u16, abi: u16, pref: u16, idx: u16 }{
360 .size = 64,
361 .abi = 64,
362 .pref = 64,
363 .idx = 64,
364 };
365 const addr_space_info = llvmAddrSpaceInfo(self.target);
366 for (addr_space_info, 0..) |info, i| {
367 assert((info.llvm == .default) == (i == 0));
368 if (info.non_integral) {
369 assert(info.llvm != .default);
370 any_non_integral = true;
371 }
372 const size = info.size orelse ptr_bit_width;
373 const abi = info.abi orelse ptr_bit_width;
374 const pref = info.pref orelse abi;
375 const idx = info.idx orelse size;
376 const matches_default =
377 size == default_info.size and
378 abi == default_info.abi and
379 pref == default_info.pref and
380 idx == default_info.idx;
381 if (info.llvm == .default) default_info = .{
382 .size = size,
383 .abi = abi,
384 .pref = pref,
385 .idx = idx,
386 };
387 if (!info.force_in_data_layout and matches_default and
388 self.target.cpu.arch != .riscv64 and
389 self.target.cpu.arch != .loongarch64 and
390 !(self.target.cpu.arch == .aarch64 and
391 (self.target.os.tag == .uefi or self.target.os.tag == .windows)) and
392 self.target.cpu.arch != .bpfeb and self.target.cpu.arch != .bpfel) continue;
393 try writer.writeAll("-p");
394 if (info.llvm != .default) try writer.print("{d}", .{@intFromEnum(info.llvm)});
395 try writer.print(":{d}:{d}", .{ size, abi });
396 if (pref != abi or idx != size or self.target.cpu.arch == .hexagon) {
397 try writer.print(":{d}", .{pref});
398 if (idx != size) try writer.print(":{d}", .{idx});
399 }
400 }
401 if (self.target.cpu.arch.isArm())
402 try writer.writeAll("-Fi8") // for thumb interwork
403 else if (self.target.cpu.arch == .powerpc64 and
404 self.target.os.tag != .freebsd and
405 self.target.os.tag != .openbsd and
406 !self.target.abi.isMusl())
407 try writer.writeAll("-Fi64")
408 else if (self.target.cpu.arch.isPowerPC() and self.target.os.tag == .aix)
409 try writer.writeAll(if (self.target.cpu.arch.isPowerPC64()) "-Fi64" else "-Fi32")
410 else if (self.target.cpu.arch.isPowerPC())
411 try writer.writeAll("-Fn32");
412 if (self.target.cpu.arch != .hexagon) {
413 if (self.target.cpu.arch == .arc or self.target.cpu.arch == .s390x)
414 try self.typeAlignment(.integer, 1, 8, 8, false, writer);
415 try self.typeAlignment(.integer, 8, 8, 8, false, writer);
416 try self.typeAlignment(.integer, 16, 16, 16, false, writer);
417 try self.typeAlignment(.integer, 32, 32, 32, false, writer);
418 if (self.target.cpu.arch == .arc)
419 try self.typeAlignment(.float, 32, 32, 32, false, writer);
420 try self.typeAlignment(.integer, 64, 32, 64, false, writer);
421 try self.typeAlignment(.integer, 128, 32, 64, false, writer);
422 if (backendSupportsF16(self.target))
423 try self.typeAlignment(.float, 16, 16, 16, false, writer);
424 if (self.target.cpu.arch != .arc)
425 try self.typeAlignment(.float, 32, 32, 32, false, writer);
426 try self.typeAlignment(.float, 64, 64, 64, false, writer);
427 if (self.target.cpu.arch.isX86()) try self.typeAlignment(.float, 80, 0, 0, false, writer);
428 try self.typeAlignment(.float, 128, 128, 128, false, writer);
429 }
430 switch (self.target.cpu.arch) {
431 .amdgcn => {
432 try self.typeAlignment(.vector, 16, 16, 16, false, writer);
433 try self.typeAlignment(.vector, 24, 32, 32, false, writer);
434 try self.typeAlignment(.vector, 32, 32, 32, false, writer);
435 try self.typeAlignment(.vector, 48, 64, 64, false, writer);
436 try self.typeAlignment(.vector, 96, 128, 128, false, writer);
437 try self.typeAlignment(.vector, 192, 256, 256, false, writer);
438 try self.typeAlignment(.vector, 256, 256, 256, false, writer);
439 try self.typeAlignment(.vector, 512, 512, 512, false, writer);
440 try self.typeAlignment(.vector, 1024, 1024, 1024, false, writer);
441 try self.typeAlignment(.vector, 2048, 2048, 2048, false, writer);
442 },
443 .ve => {},
444 else => {
445 try self.typeAlignment(.vector, 16, 32, 32, false, writer);
446 try self.typeAlignment(.vector, 32, 32, 32, false, writer);
447 try self.typeAlignment(.vector, 64, 64, 64, false, writer);
448 try self.typeAlignment(.vector, 128, 128, 128, true, writer);
449 },
450 }
451 const swap_agg_nat = switch (self.target.cpu.arch) {
452 .x86, .x86_64 => switch (self.target.os.tag) {
453 .uefi, .windows => true,
454 else => false,
455 },
456 .avr, .m68k => true,
457 else => false,
458 };
459 if (!swap_agg_nat) try self.typeAlignment(.aggregate, 0, 0, 64, false, writer);
460 if (self.target.cpu.arch == .csky) try writer.writeAll("-Fi32");
461 for (@as([]const u24, switch (self.target.cpu.arch) {
462 .avr => &.{8},
463 .msp430 => &.{ 8, 16 },
464 .arc,
465 .arm,
466 .armeb,
467 .csky,
468 .loongarch32,
469 .mips,
470 .mipsel,
471 .powerpc,
472 .powerpcle,
473 .riscv32,
474 .sparc,
475 .thumb,
476 .thumbeb,
477 .xtensa,
478 => &.{32},
479 .aarch64,
480 .aarch64_be,
481 .amdgcn,
482 .bpfeb,
483 .bpfel,
484 .loongarch64,
485 .mips64,
486 .mips64el,
487 .powerpc64,
488 .powerpc64le,
489 .riscv64,
490 .s390x,
491 .sparc64,
492 .ve,
493 .wasm32,
494 .wasm64,
495 => &.{ 32, 64 },
496 .hexagon => &.{ 16, 32 },
497 .m68k,
498 .x86,
499 => &.{ 8, 16, 32 },
500 .nvptx,
501 .nvptx64,
502 => &.{ 16, 32, 64 },
503 .x86_64 => &.{ 8, 16, 32, 64 },
504 else => &.{},
505 }), 0..) |natural, index| switch (index) {
506 0 => try writer.print("-n{d}", .{natural}),
507 else => try writer.print(":{d}", .{natural}),
508 };
509 if (swap_agg_nat) try self.typeAlignment(.aggregate, 0, 0, 64, false, writer);
510 if (self.target.cpu.arch == .hexagon) {
511 try self.typeAlignment(.integer, 64, 64, 64, true, writer);
512 try self.typeAlignment(.integer, 32, 32, 32, true, writer);
513 try self.typeAlignment(.integer, 16, 16, 16, true, writer);
514 try self.typeAlignment(.integer, 1, 8, 8, true, writer);
515 try self.typeAlignment(.float, 32, 32, 32, true, writer);
516 try self.typeAlignment(.float, 64, 64, 64, true, writer);
517 }
518 if (stack_abi != ptr_bit_width or self.target.cpu.arch == .msp430 or
519 self.target.os.tag == .uefi or self.target.os.tag == .windows or
520 self.target.cpu.arch == .riscv32)
521 try writer.print("-S{d}", .{stack_abi});
522 if (self.target.cpu.arch.isAARCH64())
523 try writer.writeAll("-Fn32");
524 switch (self.target.cpu.arch) {
525 .hexagon, .ve => {
526 try self.typeAlignment(.vector, 32, 128, 128, true, writer);
527 try self.typeAlignment(.vector, 64, 128, 128, true, writer);
528 try self.typeAlignment(.vector, 128, 128, 128, true, writer);
529 },
530 else => {},
531 }
532 if (self.target.cpu.arch != .amdgcn) {
533 try self.typeAlignment(.vector, 256, 128, 128, true, writer);
534 try self.typeAlignment(.vector, 512, 128, 128, true, writer);
535 try self.typeAlignment(.vector, 1024, 128, 128, true, writer);
536 try self.typeAlignment(.vector, 2048, 128, 128, true, writer);
537 try self.typeAlignment(.vector, 4096, 128, 128, true, writer);
538 try self.typeAlignment(.vector, 8192, 128, 128, true, writer);
539 try self.typeAlignment(.vector, 16384, 128, 128, true, writer);
540 }
541 const alloca_addr_space = llvmAllocaAddressSpace(self.target);
542 if (alloca_addr_space != .default) try writer.print("-A{d}", .{@intFromEnum(alloca_addr_space)});
543 const global_addr_space = llvmDefaultGlobalAddressSpace(self.target);
544 if (global_addr_space != .default) try writer.print("-G{d}", .{@intFromEnum(global_addr_space)});
545 if (any_non_integral) {
546 try writer.writeAll("-ni");
547 for (addr_space_info) |info| if (info.non_integral)
548 try writer.print(":{d}", .{@intFromEnum(info.llvm)});
549 }
550 }
551
552 fn typeAlignment(
553 self: DataLayoutBuilder,
554 kind: enum { integer, vector, float, aggregate },
555 size: u24,
556 default_abi: u24,
557 default_pref: u24,
558 default_force_pref: bool,
559 writer: anytype,
560 ) @TypeOf(writer).Error!void {
561 var abi = default_abi;
562 var pref = default_pref;
563 var force_abi = false;
564 var force_pref = default_force_pref;
565 if (kind == .float and size == 80) {
566 abi = 128;
567 pref = 128;
568 }
569 for (@as([]const std.Target.CType, switch (kind) {
570 .integer => &.{ .char, .short, .int, .long, .longlong },
571 .float => &.{ .float, .double, .longdouble },
572 .vector, .aggregate => &.{},
573 })) |cty| {
574 if (self.target.cTypeBitSize(cty) != size) continue;
575 abi = self.target.cTypeAlignment(cty) * 8;
576 pref = self.target.cTypePreferredAlignment(cty) * 8;
577 break;
578 }
579 switch (kind) {
580 .integer => {
581 if (self.target.ptrBitWidth() <= 16 and size >= 128) return;
582 abi = @min(abi, Type.maxIntAlignment(self.target) * 8);
583 switch (self.target.cpu.arch) {
584 .aarch64,
585 .aarch64_be,
586 => if (size == 128) {
587 abi = size;
588 pref = size;
589 } else switch (self.target.os.tag) {
590 .macos, .ios, .watchos, .tvos, .visionos => {},
591 .uefi, .windows => {
592 pref = size;
593 force_abi = size >= 32;
594 },
595 else => pref = @max(pref, 32),
596 },
597 .arc => if (size <= 64) {
598 abi = @min((std.math.divCeil(u24, size, 8) catch unreachable) * 8, 32);
599 pref = 32;
600 force_abi = true;
601 force_pref = size <= 32;
602 },
603 .bpfeb,
604 .bpfel,
605 .nvptx,
606 .nvptx64,
607 .riscv64,
608 => if (size == 128) {
609 abi = size;
610 pref = size;
611 },
612 .csky => if (size == 32 or size == 64) {
613 abi = 32;
614 pref = 32;
615 force_abi = true;
616 force_pref = true;
617 },
618 .hexagon => force_abi = true,
619 .m68k => if (size <= 32) {
620 abi = @min(size, 16);
621 pref = size;
622 force_abi = true;
623 force_pref = true;
624 } else if (size == 64) {
625 abi = 32;
626 pref = size;
627 },
628 .mips,
629 .mipsel,
630 .mips64,
631 .mips64el,
632 => pref = @max(pref, 32),
633 .s390x => pref = @max(pref, 16),
634 .ve => if (size == 64) {
635 abi = size;
636 pref = size;
637 },
638 .xtensa => if (size <= 64) {
639 pref = @max(size, 32);
640 abi = size;
641 force_abi = size == 64;
642 },
643 .x86 => switch (size) {
644 128 => {
645 abi = size;
646 pref = size;
647 },
648 else => {},
649 },
650 .x86_64 => switch (size) {
651 64, 128 => {
652 abi = size;
653 pref = size;
654 },
655 else => {},
656 },
657 .loongarch64 => switch (size) {
658 128 => {
659 abi = size;
660 pref = size;
661 force_abi = true;
662 },
663 else => {},
664 },
665 else => {},
666 }
667 },
668 .vector => if (self.target.cpu.arch.isArm()) {
669 switch (size) {
670 128 => abi = 64,
671 else => {},
672 }
673 } else if ((self.target.cpu.arch.isPowerPC64() and self.target.os.tag == .linux and
674 (size == 256 or size == 512)) or
675 (self.target.cpu.arch.isNvptx() and (size == 16 or size == 32)))
676 {
677 force_abi = true;
678 abi = size;
679 pref = size;
680 } else if (self.target.cpu.arch == .amdgcn and size <= 2048) {
681 force_abi = true;
682 } else if (self.target.cpu.arch == .csky and (size == 64 or size == 128)) {
683 abi = 32;
684 pref = 32;
685 force_pref = true;
686 } else if (self.target.cpu.arch == .hexagon and
687 ((size >= 32 and size <= 64) or (size >= 512 and size <= 2048)))
688 {
689 abi = size;
690 pref = size;
691 force_pref = true;
692 } else if (self.target.cpu.arch == .s390x and size == 128) {
693 abi = 64;
694 pref = 64;
695 force_pref = false;
696 } else if (self.target.cpu.arch == .ve and (size >= 64 and size <= 16384)) {
697 abi = 64;
698 pref = 64;
699 force_abi = true;
700 force_pref = true;
701 },
702 .float => switch (self.target.cpu.arch) {
703 .amdgcn => if (size == 128) {
704 abi = size;
705 pref = size;
706 },
707 .arc => if (size == 32 or size == 64) {
708 abi = 32;
709 pref = 32;
710 force_abi = true;
711 force_pref = size == 32;
712 },
713 .avr, .msp430, .sparc64 => if (size != 32 and size != 64) return,
714 .csky => if (size == 32 or size == 64) {
715 abi = 32;
716 pref = 32;
717 force_abi = true;
718 force_pref = true;
719 },
720 .hexagon => if (size == 32 or size == 64) {
721 force_abi = true;
722 },
723 .ve, .xtensa => if (size == 64) {
724 abi = size;
725 pref = size;
726 },
727 .wasm32, .wasm64 => if (self.target.os.tag == .emscripten and size == 128) {
728 abi = 64;
729 pref = 64;
730 },
731 else => {},
732 },
733 .aggregate => if (self.target.os.tag == .uefi or self.target.os.tag == .windows or
734 self.target.cpu.arch.isArm())
735 {
736 pref = @min(pref, self.target.ptrBitWidth());
737 } else switch (self.target.cpu.arch) {
738 .arc, .csky => {
739 abi = 0;
740 pref = 32;
741 },
742 .hexagon => {
743 abi = 0;
744 pref = 0;
745 },
746 .m68k => {
747 abi = 0;
748 pref = 16;
749 },
750 .msp430 => {
751 abi = 8;
752 pref = 8;
753 },
754 .s390x => {
755 abi = 8;
756 pref = 16;
412 break :blk if (target.ofmt == .coff)
413 if (msvc)
414 "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32"
415 else
416 "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32"
417 else if (msvc)
418 "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32"
419 else
420 "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32";
757421 },
758 else => {},
759422 },
760 }
761 if (kind != .vector and self.target.cpu.arch == .avr) {
762 force_abi = true;
763 abi = 8;
764 pref = 8;
765 }
766 if (!force_abi and abi == default_abi and pref == default_pref) return;
767 try writer.print("-{c}", .{@tagName(kind)[0]});
768 if (size != 0) try writer.print("{d}", .{size});
769 try writer.print(":{d}", .{abi});
770 if (pref != abi or force_pref) try writer.print(":{d}", .{pref});
771 }
772};
423 else => if (target.ofmt == .macho)
424 "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:32-n8:16:32-S128"
425 else
426 "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:32-n8:16:32-S128",
427 },
428 .x86_64 => if (target.os.tag.isDarwin() or target.ofmt == .macho)
429 "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
430 else switch (target.abi) {
431 .gnux32, .muslx32 => "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128",
432 else => if (target.os.tag == .windows and target.ofmt == .coff)
433 "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
434 else
435 "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128",
436 },
437 .spirv => "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1",
438 .spirv32 => "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1",
439 .spirv64 => "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1",
440 .wasm32 => if (target.os.tag == .emscripten)
441 "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-f128:64-n32:64-S128-ni:1:10:20"
442 else
443 "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20",
444 .wasm64 => if (target.os.tag == .emscripten)
445 "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-f128:64-n32:64-S128-ni:1:10:20"
446 else
447 "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20",
448 .ve => "e-m:e-i64:64-n32:64-S128-v64:64:64-v128:64:64-v256:64:64-v512:64:64-v1024:64:64-v2048:64:64-v4096:64:64-v8192:64:64-v16384:64:64",
449 .csky => "e-m:e-S32-p:32:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:32-v128:32:32-a:0:32-Fi32-n32",
450 .loongarch32 => "e-m:e-p:32:32-i64:64-n32-S128",
451 .loongarch64 => "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128",
452 .xtensa => "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32",
453
454 .kalimba,
455 .propeller,
456 => unreachable, // Gated by hasLlvmSupport().
457 };
458}
773459
774460pub const Object = struct {
775461 gpa: Allocator,
......@@ -856,7 +542,7 @@ pub const Object = struct {
856542 });
857543 errdefer builder.deinit();
858544
859 builder.data_layout = try builder.fmt("{}", .{DataLayoutBuilder{ .target = target }});
545 builder.data_layout = try builder.string(dataLayout(target));
860546
861547 const debug_compile_unit, const debug_enums_fwd_ref, const debug_globals_fwd_ref =
862548 if (!builder.strip) debug_info: {