| ... | ... | @@ -328,6 +328,212 @@ pub fn supportsTailCall(target: std.Target) bool { |
| 328 | 328 | } |
| 329 | 329 | } |
| 330 | 330 | |
| 331 | const DataLayoutBuilder = struct { |
| 332 | target: std.Target, |
| 333 | |
| 334 | pub fn format( |
| 335 | self: DataLayoutBuilder, |
| 336 | comptime _: []const u8, |
| 337 | _: std.fmt.FormatOptions, |
| 338 | writer: anytype, |
| 339 | ) @TypeOf(writer).Error!void { |
| 340 | const is_aarch64_windows = self.target.cpu.arch == .aarch64 and self.target.os.tag == .windows; |
| 341 | try writer.print("{c}-m:{c}", .{ |
| 342 | @as(u8, switch (self.target.cpu.arch.endian()) { |
| 343 | .Little => 'e', |
| 344 | .Big => 'E', |
| 345 | }), |
| 346 | @as(u8, if (self.target.cpu.arch.isMIPS()) |
| 347 | 'm' // Mips mangling: Private symbols get a $ prefix. |
| 348 | else switch (self.target.ofmt) { |
| 349 | .elf => 'e', // ELF mangling: Private symbols get a `.L` prefix. |
| 350 | //.goff => 'l', // GOFF mangling: Private symbols get a `@` prefix. |
| 351 | .macho => 'o', // Mach-O mangling: Private symbols get `L` prefix. |
| 352 | // Other symbols get a `_` prefix. |
| 353 | .coff => switch (self.target.os.tag) { |
| 354 | .windows => switch (self.target.cpu.arch) { |
| 355 | .x86 => 'x', // Windows x86 COFF mangling: Private symbols get the usual prefix. |
| 356 | // Regular C symbols get a `_` prefix. Functions with `__stdcall`, `__fastcall`, |
| 357 | // and `__vectorcall` have custom mangling that appends `@N` where N is the |
| 358 | // number of bytes used to pass parameters. C++ symbols starting with `?` are |
| 359 | // not mangled in any way. |
| 360 | else => 'w', // Windows COFF mangling: Similar to x, except that normal C |
| 361 | // symbols do not receive a `_` prefix. |
| 362 | }, |
| 363 | else => 'e', |
| 364 | }, |
| 365 | //.xcoff => 'a', // XCOFF mangling: Private symbols get a `L..` prefix. |
| 366 | else => 'e', |
| 367 | }), |
| 368 | }); |
| 369 | var any_non_integral = false; |
| 370 | const ptr_bit_width = self.target.ptrBitWidth(); |
| 371 | var default_info = struct { size: u16, abi: u16, pref: u16, idx: u16 }{ |
| 372 | .size = 64, |
| 373 | .abi = 64, |
| 374 | .pref = 64, |
| 375 | .idx = 64, |
| 376 | }; |
| 377 | const address_space_info = llvmAddressSpaceInfo(self.target); |
| 378 | assert(address_space_info[0].llvm == llvm.address_space.default); |
| 379 | for (address_space_info) |info| { |
| 380 | const is_default = info.llvm == llvm.address_space.default; |
| 381 | if (info.non_integral) { |
| 382 | assert(!is_default); |
| 383 | any_non_integral = true; |
| 384 | } |
| 385 | const size = info.size orelse ptr_bit_width; |
| 386 | const abi = info.abi orelse ptr_bit_width; |
| 387 | const pref = info.pref orelse abi; |
| 388 | const idx = info.idx orelse size; |
| 389 | const matches_default = |
| 390 | size == default_info.size and |
| 391 | abi == default_info.abi and |
| 392 | pref == default_info.pref and |
| 393 | idx == default_info.idx; |
| 394 | if (is_default) default_info = .{ |
| 395 | .size = size, |
| 396 | .abi = abi, |
| 397 | .pref = pref, |
| 398 | .idx = idx, |
| 399 | }; |
| 400 | if (!info.force_in_data_layout and matches_default and |
| 401 | self.target.cpu.arch != .riscv64 and !is_aarch64_windows) continue; |
| 402 | try writer.writeAll("-p"); |
| 403 | if (!is_default) try writer.print("{d}", .{info.llvm}); |
| 404 | try writer.print(":{d}:{d}", .{ size, abi }); |
| 405 | if (pref != abi or idx != size) { |
| 406 | try writer.print(":{d}", .{pref}); |
| 407 | if (idx != size) try writer.print(":{d}", .{idx}); |
| 408 | } |
| 409 | } |
| 410 | if (self.target.cpu.arch.isARM() or self.target.cpu.arch.isThumb()) |
| 411 | try writer.writeAll("-Fi8"); // for thumb interwork |
| 412 | try self.typeAlignment(.integer, 8, 8, 8, false, writer); |
| 413 | try self.typeAlignment(.integer, 16, 16, 16, false, writer); |
| 414 | try self.typeAlignment(.integer, 32, if (is_aarch64_windows) 0 else 32, 32, false, writer); |
| 415 | try self.typeAlignment(.integer, 64, 32, 64, false, writer); |
| 416 | try self.typeAlignment(.integer, 128, 32, 64, false, writer); |
| 417 | if (backendSupportsF16(self.target)) try self.typeAlignment(.float, 16, 16, 16, false, writer); |
| 418 | try self.typeAlignment(.float, 32, 32, 32, false, writer); |
| 419 | try self.typeAlignment(.float, 64, 64, 64, false, writer); |
| 420 | if (backendSupportsF80(self.target)) try self.typeAlignment(.float, 80, 0, 0, false, writer); |
| 421 | try self.typeAlignment(.float, 128, 128, 128, false, writer); |
| 422 | try self.typeAlignment(.vector, 64, 64, 64, false, writer); |
| 423 | try self.typeAlignment(.vector, 128, 128, 128, false, writer); |
| 424 | if (self.target.os.tag != .windows) try self.typeAlignment(.aggregate, 0, 0, 64, false, writer); |
| 425 | for (@as([]const u24, switch (self.target.cpu.arch) { |
| 426 | .aarch64_32, |
| 427 | .arm, |
| 428 | .armeb, |
| 429 | .mips, |
| 430 | .mipsel, |
| 431 | .powerpc, |
| 432 | .powerpcle, |
| 433 | .thumb, |
| 434 | .thumbeb, |
| 435 | .riscv32, |
| 436 | => &.{32}, |
| 437 | .aarch64, |
| 438 | .aarch64_be, |
| 439 | .mips64, |
| 440 | .mips64el, |
| 441 | .powerpc64, |
| 442 | .powerpc64le, |
| 443 | .riscv64, |
| 444 | .wasm32, |
| 445 | .wasm64, |
| 446 | => &.{ 32, 64 }, |
| 447 | .x86 => &.{ 8, 16, 32 }, |
| 448 | .x86_64 => &.{ 8, 16, 32, 64 }, |
| 449 | else => &.{}, |
| 450 | }), 0..) |natural, index| switch (index) { |
| 451 | 0 => try writer.print("-n{d}", .{natural}), |
| 452 | else => try writer.print(":{d}", .{natural}), |
| 453 | }; |
| 454 | if (self.target.os.tag == .windows) try self.typeAlignment(.aggregate, 0, 0, 64, false, writer); |
| 455 | const stack_abi = self.target.stackAlignment() * 8; |
| 456 | if (self.target.os.tag == .windows or stack_abi != ptr_bit_width) |
| 457 | try writer.print("-S{d}", .{stack_abi}); |
| 458 | try self.typeAlignment(.vector, 256, 128, 128, true, writer); |
| 459 | try self.typeAlignment(.vector, 512, 128, 128, true, writer); |
| 460 | if (any_non_integral) { |
| 461 | try writer.writeAll("-ni"); |
| 462 | for (address_space_info) |info| if (info.non_integral) |
| 463 | try writer.print(":{d}", .{info.llvm}); |
| 464 | } |
| 465 | } |
| 466 | |
| 467 | fn typeAlignment( |
| 468 | self: DataLayoutBuilder, |
| 469 | kind: enum { integer, vector, float, aggregate }, |
| 470 | size: u24, |
| 471 | default_abi: u24, |
| 472 | default_pref: u24, |
| 473 | force_pref: bool, |
| 474 | writer: anytype, |
| 475 | ) @TypeOf(writer).Error!void { |
| 476 | var abi = default_abi; |
| 477 | var pref = default_pref; |
| 478 | if (kind == .float and size == 80) { |
| 479 | abi = 128; |
| 480 | pref = 128; |
| 481 | } |
| 482 | for (@as([]const std.Target.CType, switch (kind) { |
| 483 | .integer => &.{ .char, .short, .int, .long, .longlong }, |
| 484 | .float => &.{ .float, .double, .longdouble }, |
| 485 | .vector, .aggregate => &.{}, |
| 486 | })) |cty| { |
| 487 | if (self.target.c_type_bit_size(cty) != size) continue; |
| 488 | abi = self.target.c_type_alignment(cty) * 8; |
| 489 | pref = self.target.c_type_preferred_alignment(cty) * 8; |
| 490 | break; |
| 491 | } |
| 492 | switch (kind) { |
| 493 | .integer => { |
| 494 | abi = @min(abi, self.target.maxIntAlignment() * 8); |
| 495 | switch (self.target.os.tag) { |
| 496 | .linux => switch (self.target.cpu.arch) { |
| 497 | .aarch64, .aarch64_be, .mips, .mipsel => pref = @max(pref, 32), |
| 498 | else => {}, |
| 499 | }, |
| 500 | else => {}, |
| 501 | } |
| 502 | switch (self.target.cpu.arch) { |
| 503 | .aarch64, .aarch64_be, .riscv64 => switch (size) { |
| 504 | 128 => { |
| 505 | abi = size; |
| 506 | pref = size; |
| 507 | }, |
| 508 | else => {}, |
| 509 | }, |
| 510 | else => {}, |
| 511 | } |
| 512 | }, |
| 513 | .vector => if (self.target.cpu.arch.isARM() or self.target.cpu.arch.isThumb()) { |
| 514 | switch (size) { |
| 515 | 128 => abi = 64, |
| 516 | else => {}, |
| 517 | } |
| 518 | } else if (self.target.cpu.arch.isPPC64()) { |
| 519 | abi = size; |
| 520 | pref = size; |
| 521 | }, |
| 522 | .float => {}, |
| 523 | .aggregate => if (self.target.os.tag == .windows or |
| 524 | self.target.cpu.arch.isARM() or self.target.cpu.arch.isThumb()) |
| 525 | { |
| 526 | pref = @min(pref, self.target.ptrBitWidth()); |
| 527 | }, |
| 528 | } |
| 529 | if (abi == default_abi and pref == default_pref) return; |
| 530 | try writer.print("-{c}", .{@tagName(kind)[0]}); |
| 531 | if (size != 0) try writer.print("{d}", .{size}); |
| 532 | try writer.print(":{d}", .{abi}); |
| 533 | if (pref != abi or force_pref) try writer.print(":{d}", .{pref}); |
| 534 | } |
| 535 | }; |
| 536 | |
| 331 | 537 | /// TODO can this be done with simpler logic / different API binding? |
| 332 | 538 | fn deleteLlvmGlobal(llvm_global: *llvm.Value) void { |
| 333 | 539 | if (llvm_global.globalGetValueType().getTypeKind() == .Function) { |
| ... | ... | @@ -530,12 +736,17 @@ pub const Object = struct { |
| 530 | 736 | try builder.init(); |
| 531 | 737 | errdefer builder.deinit(); |
| 532 | 738 | builder.source_filename = try builder.string(options.root_name); |
| 533 | | builder.data_layout = rep: { |
| 739 | builder.data_layout = try builder.fmt("{}", .{DataLayoutBuilder{ .target = options.target }}); |
| 740 | builder.target_triple = try builder.string(llvm_target_triple); |
| 741 | |
| 742 | if (std.debug.runtime_safety) { |
| 534 | 743 | const rep = target_data.stringRep(); |
| 535 | 744 | defer llvm.disposeMessage(rep); |
| 536 | | break :rep try builder.string(std.mem.span(rep)); |
| 537 | | }; |
| 538 | | builder.target_triple = try builder.string(llvm_target_triple); |
| 745 | std.testing.expectEqualStrings( |
| 746 | std.mem.span(rep), |
| 747 | builder.data_layout.toSlice(&builder).?, |
| 748 | ) catch unreachable; |
| 749 | } |
| 539 | 750 | |
| 540 | 751 | return Object{ |
| 541 | 752 | .gpa = gpa, |
| ... | ... | @@ -768,6 +979,10 @@ pub const Object = struct { |
| 768 | 979 | if (comp.verbose_llvm_ir) |path| { |
| 769 | 980 | if (std.mem.eql(u8, path, "-")) { |
| 770 | 981 | self.llvm_module.dump(); |
| 982 | |
| 983 | const writer = std.io.getStdErr().writer(); |
| 984 | try writer.writeAll("\n" ++ "-" ** 200 ++ "\n\n"); |
| 985 | try self.builder.dump(writer); |
| 771 | 986 | } else { |
| 772 | 987 | const path_z = try comp.gpa.dupeZ(u8, path); |
| 773 | 988 | defer comp.gpa.free(path_z); |
| ... | ... | @@ -836,12 +1051,6 @@ pub const Object = struct { |
| 836 | 1051 | emit_asm_msg, emit_bin_msg, emit_llvm_ir_msg, emit_llvm_bc_msg, |
| 837 | 1052 | }); |
| 838 | 1053 | |
| 839 | | { |
| 840 | | const writer = std.io.getStdErr().writer(); |
| 841 | | try writer.writeAll("\n" ++ "-" ** 200 ++ "\n\n"); |
| 842 | | try self.builder.dump(writer); |
| 843 | | } |
| 844 | | |
| 845 | 1054 | // Unfortunately, LLVM shits the bed when we ask for both binary and assembly. |
| 846 | 1055 | // So we call the entire pipeline multiple times if this is requested. |
| 847 | 1056 | var error_message: [*:0]const u8 = undefined; |
| ... | ... | @@ -1311,7 +1520,7 @@ pub const Object = struct { |
| 1311 | 1520 | try global_index.rename(&self.builder, decl_name); |
| 1312 | 1521 | const decl_name_slice = decl_name.toSlice(&self.builder).?; |
| 1313 | 1522 | const global = global_index.ptr(&self.builder); |
| 1314 | | global.unnamed_addr = .none; |
| 1523 | global.unnamed_addr = .default; |
| 1315 | 1524 | llvm_global.setUnnamedAddr(.False); |
| 1316 | 1525 | global.linkage = .external; |
| 1317 | 1526 | llvm_global.setLinkage(.External); |
| ... | ... | @@ -2674,11 +2883,15 @@ pub const Object = struct { |
| 2674 | 2883 | |
| 2675 | 2884 | const target = mod.getTarget(); |
| 2676 | 2885 | |
| 2677 | | const llvm_type = try o.lowerLlvmType(decl.ty); |
| 2886 | const ty = try o.lowerType(decl.ty); |
| 2887 | const llvm_type = if (ty != .none) |
| 2888 | o.builder.llvm_types.items[@intFromEnum(ty)] |
| 2889 | else |
| 2890 | try o.lowerLlvmType(decl.ty); |
| 2678 | 2891 | const llvm_actual_addrspace = toLlvmGlobalAddressSpace(decl.@"addrspace", target); |
| 2679 | 2892 | |
| 2680 | 2893 | var global = Builder.Global{ |
| 2681 | | .type = .void, |
| 2894 | .type = if (ty != .none) ty else .void, |
| 2682 | 2895 | .kind = .{ .object = @enumFromInt(o.builder.objects.items.len) }, |
| 2683 | 2896 | }; |
| 2684 | 2897 | var object = Builder.Object{ |
| ... | ... | @@ -2698,7 +2911,7 @@ pub const Object = struct { |
| 2698 | 2911 | |
| 2699 | 2912 | // This is needed for declarations created by `@extern`. |
| 2700 | 2913 | if (is_extern) { |
| 2701 | | global.unnamed_addr = .none; |
| 2914 | global.unnamed_addr = .default; |
| 2702 | 2915 | llvm_global.setUnnamedAddr(.False); |
| 2703 | 2916 | global.linkage = .external; |
| 2704 | 2917 | llvm_global.setLinkage(.External); |
| ... | ... | @@ -2708,7 +2921,7 @@ pub const Object = struct { |
| 2708 | 2921 | object.thread_local = .generaldynamic; |
| 2709 | 2922 | llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel); |
| 2710 | 2923 | } else { |
| 2711 | | object.thread_local = .none; |
| 2924 | object.thread_local = .default; |
| 2712 | 2925 | llvm_global.setThreadLocalMode(.NotThreadLocal); |
| 2713 | 2926 | } |
| 2714 | 2927 | if (variable.is_weak_linkage) { |
| ... | ... | @@ -2962,9 +3175,9 @@ pub const Object = struct { |
| 2962 | 3175 | const name = try o.builder.string(mod.intern_pool.stringToSlice( |
| 2963 | 3176 | try struct_obj.getFullyQualifiedName(mod), |
| 2964 | 3177 | )); |
| 2965 | | _ = try o.builder.opaqueType(name); |
| 3178 | const ty = try o.builder.opaqueType(name); |
| 2966 | 3179 | |
| 2967 | | const llvm_struct_ty = o.context.structCreateNamed(name.toSlice(&o.builder).?); |
| 3180 | const llvm_struct_ty = o.builder.llvm_types.items[@intFromEnum(ty)]; |
| 2968 | 3181 | gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls |
| 2969 | 3182 | |
| 2970 | 3183 | assert(struct_obj.haveFieldTypes()); |
| ... | ... | @@ -3101,16 +3314,6 @@ pub const Object = struct { |
| 3101 | 3314 | } |
| 3102 | 3315 | } |
| 3103 | 3316 | |
| 3104 | | fn lowerType(o: *Object, t: Type) Allocator.Error!Builder.Type { |
| 3105 | | const mod = o.module; |
| 3106 | | switch (t.toIntern()) { |
| 3107 | | .void_type, .noreturn_type => return .void, |
| 3108 | | else => switch (mod.intern_pool.indexToKey(t.toIntern())) { |
| 3109 | | else => return .none, |
| 3110 | | }, |
| 3111 | | } |
| 3112 | | } |
| 3113 | | |
| 3114 | 3317 | fn lowerLlvmTypeFn(o: *Object, fn_ty: Type) Allocator.Error!*llvm.Type { |
| 3115 | 3318 | const mod = o.module; |
| 3116 | 3319 | const ip = &mod.intern_pool; |
| ... | ... | @@ -3206,6 +3409,149 @@ pub const Object = struct { |
| 3206 | 3409 | return llvm_elem_ty; |
| 3207 | 3410 | } |
| 3208 | 3411 | |
| 3412 | fn lowerType(o: *Object, t: Type) Allocator.Error!Builder.Type { |
| 3413 | const mod = o.module; |
| 3414 | const target = mod.getTarget(); |
| 3415 | return switch (t.toIntern()) { |
| 3416 | .u0_type, .i0_type => unreachable, |
| 3417 | inline .u1_type, |
| 3418 | .u8_type, |
| 3419 | .i8_type, |
| 3420 | .u16_type, |
| 3421 | .i16_type, |
| 3422 | .u29_type, |
| 3423 | .u32_type, |
| 3424 | .i32_type, |
| 3425 | .u64_type, |
| 3426 | .i64_type, |
| 3427 | .u80_type, |
| 3428 | .u128_type, |
| 3429 | .i128_type, |
| 3430 | => |tag| @field(Builder.Type, "i" ++ @tagName(tag)[1 .. @tagName(tag).len - "_type".len]), |
| 3431 | .usize_type, .isize_type => try o.builder.intType(target.ptrBitWidth()), |
| 3432 | inline .c_char_type, |
| 3433 | .c_short_type, |
| 3434 | .c_ushort_type, |
| 3435 | .c_int_type, |
| 3436 | .c_uint_type, |
| 3437 | .c_long_type, |
| 3438 | .c_ulong_type, |
| 3439 | .c_longlong_type, |
| 3440 | .c_ulonglong_type, |
| 3441 | => |tag| try o.builder.intType(target.c_type_bit_size( |
| 3442 | @field(std.Target.CType, @tagName(tag)["c_".len .. @tagName(tag).len - "_type".len]), |
| 3443 | )), |
| 3444 | .c_longdouble_type, |
| 3445 | .f16_type, |
| 3446 | .f32_type, |
| 3447 | .f64_type, |
| 3448 | .f80_type, |
| 3449 | .f128_type, |
| 3450 | => switch (t.floatBits(target)) { |
| 3451 | 16 => if (backendSupportsF16(target)) .half else .i16, |
| 3452 | 32 => .float, |
| 3453 | 64 => .double, |
| 3454 | 80 => if (backendSupportsF80(target)) .x86_fp80 else .i80, |
| 3455 | 128 => .fp128, |
| 3456 | else => unreachable, |
| 3457 | }, |
| 3458 | .anyopaque_type => unreachable, |
| 3459 | .bool_type => .i1, |
| 3460 | .void_type => .void, |
| 3461 | .type_type => unreachable, |
| 3462 | .anyerror_type => .i16, |
| 3463 | .comptime_int_type, .comptime_float_type, .noreturn_type => unreachable, |
| 3464 | .anyframe_type => @panic("TODO implement lowerType for AnyFrame types"), |
| 3465 | .null_type, |
| 3466 | .undefined_type, |
| 3467 | .enum_literal_type, |
| 3468 | .atomic_order_type, |
| 3469 | .atomic_rmw_op_type, |
| 3470 | .calling_convention_type, |
| 3471 | .address_space_type, |
| 3472 | .float_mode_type, |
| 3473 | .reduce_op_type, |
| 3474 | .call_modifier_type, |
| 3475 | .prefetch_options_type, |
| 3476 | .export_options_type, |
| 3477 | .extern_options_type, |
| 3478 | .type_info_type, |
| 3479 | => unreachable, |
| 3480 | .manyptr_u8_type, |
| 3481 | .manyptr_const_u8_type, |
| 3482 | .manyptr_const_u8_sentinel_0_type, |
| 3483 | .single_const_pointer_to_comptime_int_type, |
| 3484 | => .ptr, |
| 3485 | .slice_const_u8_type, .slice_const_u8_sentinel_0_type => .none, |
| 3486 | .optional_noreturn_type => unreachable, |
| 3487 | .anyerror_void_error_union_type => .i16, |
| 3488 | .generic_poison_type, .empty_struct_type => unreachable, |
| 3489 | // values, not types |
| 3490 | .undef, |
| 3491 | .zero, |
| 3492 | .zero_usize, |
| 3493 | .zero_u8, |
| 3494 | .one, |
| 3495 | .one_usize, |
| 3496 | .one_u8, |
| 3497 | .four_u8, |
| 3498 | .negative_one, |
| 3499 | .calling_convention_c, |
| 3500 | .calling_convention_inline, |
| 3501 | .void_value, |
| 3502 | .unreachable_value, |
| 3503 | .null_value, |
| 3504 | .bool_true, |
| 3505 | .bool_false, |
| 3506 | .empty_struct, |
| 3507 | .generic_poison, |
| 3508 | .var_args_param_type, |
| 3509 | .none, |
| 3510 | => unreachable, |
| 3511 | else => switch (mod.intern_pool.indexToKey(t.toIntern())) { |
| 3512 | .int_type => |int_type| try o.builder.intType(int_type.bits), |
| 3513 | .ptr_type => |ptr_type| switch (ptr_type.flags.size) { |
| 3514 | .One, .Many, .C => try o.builder.pointerType(@enumFromInt( |
| 3515 | toLlvmAddressSpace(ptr_type.flags.address_space, target), |
| 3516 | )), |
| 3517 | .Slice => .none, |
| 3518 | }, |
| 3519 | .array_type, .vector_type, .opt_type => .none, |
| 3520 | .anyframe_type => @panic("TODO implement lowerType for AnyFrame types"), |
| 3521 | .error_union_type => .none, |
| 3522 | .simple_type => unreachable, |
| 3523 | .struct_type, |
| 3524 | .anon_struct_type, |
| 3525 | .union_type, |
| 3526 | .opaque_type, |
| 3527 | => .none, |
| 3528 | .enum_type => |enum_type| try o.lowerType(enum_type.tag_ty.toType()), |
| 3529 | .func_type, .error_set_type, .inferred_error_set_type => .none, |
| 3530 | // values, not types |
| 3531 | .undef, |
| 3532 | .runtime_value, |
| 3533 | .simple_value, |
| 3534 | .variable, |
| 3535 | .extern_func, |
| 3536 | .func, |
| 3537 | .int, |
| 3538 | .err, |
| 3539 | .error_union, |
| 3540 | .enum_literal, |
| 3541 | .enum_tag, |
| 3542 | .empty_enum_value, |
| 3543 | .float, |
| 3544 | .ptr, |
| 3545 | .opt, |
| 3546 | .aggregate, |
| 3547 | .un, |
| 3548 | // memoization, not types |
| 3549 | .memoized_call, |
| 3550 | => unreachable, |
| 3551 | }, |
| 3552 | }; |
| 3553 | } |
| 3554 | |
| 3209 | 3555 | fn lowerValue(o: *Object, arg_tv: TypedValue) Error!*llvm.Value { |
| 3210 | 3556 | const mod = o.module; |
| 3211 | 3557 | const gpa = o.gpa; |
| ... | ... | @@ -10606,44 +10952,63 @@ fn toLlvmCallConv(cc: std.builtin.CallingConvention, target: std.Target) llvm.Ca |
| 10606 | 10952 | |
| 10607 | 10953 | /// Convert a zig-address space to an llvm address space. |
| 10608 | 10954 | fn toLlvmAddressSpace(address_space: std.builtin.AddressSpace, target: std.Target) c_uint { |
| 10955 | for (llvmAddressSpaceInfo(target)) |info| if (info.zig == address_space) return info.llvm; |
| 10956 | unreachable; |
| 10957 | } |
| 10958 | |
| 10959 | const AddressSpaceInfo = struct { |
| 10960 | zig: ?std.builtin.AddressSpace, |
| 10961 | llvm: c_uint, |
| 10962 | non_integral: bool = false, |
| 10963 | size: ?u16 = null, |
| 10964 | abi: ?u16 = null, |
| 10965 | pref: ?u16 = null, |
| 10966 | idx: ?u16 = null, |
| 10967 | force_in_data_layout: bool = false, |
| 10968 | }; |
| 10969 | fn llvmAddressSpaceInfo(target: std.Target) []const AddressSpaceInfo { |
| 10609 | 10970 | return switch (target.cpu.arch) { |
| 10610 | | .x86, .x86_64 => switch (address_space) { |
| 10611 | | .generic => llvm.address_space.default, |
| 10612 | | .gs => llvm.address_space.x86.gs, |
| 10613 | | .fs => llvm.address_space.x86.fs, |
| 10614 | | .ss => llvm.address_space.x86.ss, |
| 10615 | | else => unreachable, |
| 10971 | .x86, .x86_64 => &.{ |
| 10972 | .{ .zig = .generic, .llvm = llvm.address_space.default }, |
| 10973 | .{ .zig = .gs, .llvm = llvm.address_space.x86.gs }, |
| 10974 | .{ .zig = .fs, .llvm = llvm.address_space.x86.fs }, |
| 10975 | .{ .zig = .ss, .llvm = llvm.address_space.x86.ss }, |
| 10976 | .{ .zig = null, .llvm = llvm.address_space.x86.ptr32_sptr, .size = 32, .abi = 32, .force_in_data_layout = true }, |
| 10977 | .{ .zig = null, .llvm = llvm.address_space.x86.ptr32_uptr, .size = 32, .abi = 32, .force_in_data_layout = true }, |
| 10978 | .{ .zig = null, .llvm = llvm.address_space.x86.ptr64, .size = 64, .abi = 64, .force_in_data_layout = true }, |
| 10616 | 10979 | }, |
| 10617 | | .nvptx, .nvptx64 => switch (address_space) { |
| 10618 | | .generic => llvm.address_space.default, |
| 10619 | | .global => llvm.address_space.nvptx.global, |
| 10620 | | .constant => llvm.address_space.nvptx.constant, |
| 10621 | | .param => llvm.address_space.nvptx.param, |
| 10622 | | .shared => llvm.address_space.nvptx.shared, |
| 10623 | | .local => llvm.address_space.nvptx.local, |
| 10624 | | else => unreachable, |
| 10980 | .nvptx, .nvptx64 => &.{ |
| 10981 | .{ .zig = .generic, .llvm = llvm.address_space.default }, |
| 10982 | .{ .zig = .global, .llvm = llvm.address_space.nvptx.global }, |
| 10983 | .{ .zig = .constant, .llvm = llvm.address_space.nvptx.constant }, |
| 10984 | .{ .zig = .param, .llvm = llvm.address_space.nvptx.param }, |
| 10985 | .{ .zig = .shared, .llvm = llvm.address_space.nvptx.shared }, |
| 10986 | .{ .zig = .local, .llvm = llvm.address_space.nvptx.local }, |
| 10625 | 10987 | }, |
| 10626 | | .amdgcn => switch (address_space) { |
| 10627 | | .generic => llvm.address_space.amdgpu.flat, |
| 10628 | | .global => llvm.address_space.amdgpu.global, |
| 10629 | | .constant => llvm.address_space.amdgpu.constant, |
| 10630 | | .shared => llvm.address_space.amdgpu.local, |
| 10631 | | .local => llvm.address_space.amdgpu.private, |
| 10632 | | else => unreachable, |
| 10988 | .amdgcn => &.{ |
| 10989 | .{ .zig = .generic, .llvm = llvm.address_space.amdgpu.flat }, |
| 10990 | .{ .zig = .global, .llvm = llvm.address_space.amdgpu.global }, |
| 10991 | .{ .zig = .constant, .llvm = llvm.address_space.amdgpu.constant }, |
| 10992 | .{ .zig = .shared, .llvm = llvm.address_space.amdgpu.local }, |
| 10993 | .{ .zig = .local, .llvm = llvm.address_space.amdgpu.private }, |
| 10633 | 10994 | }, |
| 10634 | | .avr => switch (address_space) { |
| 10635 | | .generic => llvm.address_space.default, |
| 10636 | | .flash => llvm.address_space.avr.flash, |
| 10637 | | .flash1 => llvm.address_space.avr.flash1, |
| 10638 | | .flash2 => llvm.address_space.avr.flash2, |
| 10639 | | .flash3 => llvm.address_space.avr.flash3, |
| 10640 | | .flash4 => llvm.address_space.avr.flash4, |
| 10641 | | .flash5 => llvm.address_space.avr.flash5, |
| 10642 | | else => unreachable, |
| 10995 | .avr => &.{ |
| 10996 | .{ .zig = .generic, .llvm = llvm.address_space.default }, |
| 10997 | .{ .zig = .flash, .llvm = llvm.address_space.avr.flash }, |
| 10998 | .{ .zig = .flash1, .llvm = llvm.address_space.avr.flash1 }, |
| 10999 | .{ .zig = .flash2, .llvm = llvm.address_space.avr.flash2 }, |
| 11000 | .{ .zig = .flash3, .llvm = llvm.address_space.avr.flash3 }, |
| 11001 | .{ .zig = .flash4, .llvm = llvm.address_space.avr.flash4 }, |
| 11002 | .{ .zig = .flash5, .llvm = llvm.address_space.avr.flash5 }, |
| 10643 | 11003 | }, |
| 10644 | | else => switch (address_space) { |
| 10645 | | .generic => llvm.address_space.default, |
| 10646 | | else => unreachable, |
| 11004 | .wasm32, .wasm64 => &.{ |
| 11005 | .{ .zig = .generic, .llvm = llvm.address_space.default }, |
| 11006 | .{ .zig = null, .llvm = llvm.address_space.wasm.variable, .non_integral = true }, |
| 11007 | .{ .zig = null, .llvm = llvm.address_space.wasm.externref, .non_integral = true, .size = 8, .abi = 8 }, |
| 11008 | .{ .zig = null, .llvm = llvm.address_space.wasm.funcref, .non_integral = true, .size = 8, .abi = 8 }, |
| 11009 | }, |
| 11010 | else => &.{ |
| 11011 | .{ .zig = .generic, .llvm = llvm.address_space.default }, |
| 10647 | 11012 | }, |
| 10648 | 11013 | }; |
| 10649 | 11014 | } |