| ... | @@ -328,6 +328,212 @@ pub fn supportsTailCall(target: std.Target) bool { | ... | @@ -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 | /// TODO can this be done with simpler logic / different API binding? | 537 | /// TODO can this be done with simpler logic / different API binding? |
| 332 | fn deleteLlvmGlobal(llvm_global: *llvm.Value) void { | 538 | fn deleteLlvmGlobal(llvm_global: *llvm.Value) void { |
| 333 | if (llvm_global.globalGetValueType().getTypeKind() == .Function) { | 539 | if (llvm_global.globalGetValueType().getTypeKind() == .Function) { |
| ... | @@ -530,12 +736,17 @@ pub const Object = struct { | ... | @@ -530,12 +736,17 @@ pub const Object = struct { |
| 530 | try builder.init(); | 736 | try builder.init(); |
| 531 | errdefer builder.deinit(); | 737 | errdefer builder.deinit(); |
| 532 | builder.source_filename = try builder.string(options.root_name); | 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 | const rep = target_data.stringRep(); | 743 | const rep = target_data.stringRep(); |
| 535 | defer llvm.disposeMessage(rep); | 744 | defer llvm.disposeMessage(rep); |
| 536 | break :rep try builder.string(std.mem.span(rep)); | 745 | std.testing.expectEqualStrings( |
| 537 | }; | 746 | std.mem.span(rep), |
| 538 | builder.target_triple = try builder.string(llvm_target_triple); | 747 | builder.data_layout.toSlice(&builder).?, |
| | 748 | ) catch unreachable; |
| | 749 | } |
| 539 | | 750 | |
| 540 | return Object{ | 751 | return Object{ |
| 541 | .gpa = gpa, | 752 | .gpa = gpa, |
| ... | @@ -768,6 +979,10 @@ pub const Object = struct { | ... | @@ -768,6 +979,10 @@ pub const Object = struct { |
| 768 | if (comp.verbose_llvm_ir) |path| { | 979 | if (comp.verbose_llvm_ir) |path| { |
| 769 | if (std.mem.eql(u8, path, "-")) { | 980 | if (std.mem.eql(u8, path, "-")) { |
| 770 | self.llvm_module.dump(); | 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 | } else { | 986 | } else { |
| 772 | const path_z = try comp.gpa.dupeZ(u8, path); | 987 | const path_z = try comp.gpa.dupeZ(u8, path); |
| 773 | defer comp.gpa.free(path_z); | 988 | defer comp.gpa.free(path_z); |
| ... | @@ -836,12 +1051,6 @@ pub const Object = struct { | ... | @@ -836,12 +1051,6 @@ pub const Object = struct { |
| 836 | emit_asm_msg, emit_bin_msg, emit_llvm_ir_msg, emit_llvm_bc_msg, | 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 | // Unfortunately, LLVM shits the bed when we ask for both binary and assembly. | 1054 | // Unfortunately, LLVM shits the bed when we ask for both binary and assembly. |
| 846 | // So we call the entire pipeline multiple times if this is requested. | 1055 | // So we call the entire pipeline multiple times if this is requested. |
| 847 | var error_message: [*:0]const u8 = undefined; | 1056 | var error_message: [*:0]const u8 = undefined; |
| ... | @@ -1311,7 +1520,7 @@ pub const Object = struct { | ... | @@ -1311,7 +1520,7 @@ pub const Object = struct { |
| 1311 | try global_index.rename(&self.builder, decl_name); | 1520 | try global_index.rename(&self.builder, decl_name); |
| 1312 | const decl_name_slice = decl_name.toSlice(&self.builder).?; | 1521 | const decl_name_slice = decl_name.toSlice(&self.builder).?; |
| 1313 | const global = global_index.ptr(&self.builder); | 1522 | const global = global_index.ptr(&self.builder); |
| 1314 | global.unnamed_addr = .none; | 1523 | global.unnamed_addr = .default; |
| 1315 | llvm_global.setUnnamedAddr(.False); | 1524 | llvm_global.setUnnamedAddr(.False); |
| 1316 | global.linkage = .external; | 1525 | global.linkage = .external; |
| 1317 | llvm_global.setLinkage(.External); | 1526 | llvm_global.setLinkage(.External); |
| ... | @@ -2674,11 +2883,15 @@ pub const Object = struct { | ... | @@ -2674,11 +2883,15 @@ pub const Object = struct { |
| 2674 | | 2883 | |
| 2675 | const target = mod.getTarget(); | 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 | const llvm_actual_addrspace = toLlvmGlobalAddressSpace(decl.@"addrspace", target); | 2891 | const llvm_actual_addrspace = toLlvmGlobalAddressSpace(decl.@"addrspace", target); |
| 2679 | | 2892 | |
| 2680 | var global = Builder.Global{ | 2893 | var global = Builder.Global{ |
| 2681 | .type = .void, | 2894 | .type = if (ty != .none) ty else .void, |
| 2682 | .kind = .{ .object = @enumFromInt(o.builder.objects.items.len) }, | 2895 | .kind = .{ .object = @enumFromInt(o.builder.objects.items.len) }, |
| 2683 | }; | 2896 | }; |
| 2684 | var object = Builder.Object{ | 2897 | var object = Builder.Object{ |
| ... | @@ -2698,7 +2911,7 @@ pub const Object = struct { | ... | @@ -2698,7 +2911,7 @@ pub const Object = struct { |
| 2698 | | 2911 | |
| 2699 | // This is needed for declarations created by `@extern`. | 2912 | // This is needed for declarations created by `@extern`. |
| 2700 | if (is_extern) { | 2913 | if (is_extern) { |
| 2701 | global.unnamed_addr = .none; | 2914 | global.unnamed_addr = .default; |
| 2702 | llvm_global.setUnnamedAddr(.False); | 2915 | llvm_global.setUnnamedAddr(.False); |
| 2703 | global.linkage = .external; | 2916 | global.linkage = .external; |
| 2704 | llvm_global.setLinkage(.External); | 2917 | llvm_global.setLinkage(.External); |
| ... | @@ -2708,7 +2921,7 @@ pub const Object = struct { | ... | @@ -2708,7 +2921,7 @@ pub const Object = struct { |
| 2708 | object.thread_local = .generaldynamic; | 2921 | object.thread_local = .generaldynamic; |
| 2709 | llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel); | 2922 | llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel); |
| 2710 | } else { | 2923 | } else { |
| 2711 | object.thread_local = .none; | 2924 | object.thread_local = .default; |
| 2712 | llvm_global.setThreadLocalMode(.NotThreadLocal); | 2925 | llvm_global.setThreadLocalMode(.NotThreadLocal); |
| 2713 | } | 2926 | } |
| 2714 | if (variable.is_weak_linkage) { | 2927 | if (variable.is_weak_linkage) { |
| ... | @@ -2962,9 +3175,9 @@ pub const Object = struct { | ... | @@ -2962,9 +3175,9 @@ pub const Object = struct { |
| 2962 | const name = try o.builder.string(mod.intern_pool.stringToSlice( | 3175 | const name = try o.builder.string(mod.intern_pool.stringToSlice( |
| 2963 | try struct_obj.getFullyQualifiedName(mod), | 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 | gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls | 3181 | gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls |
| 2969 | | 3182 | |
| 2970 | assert(struct_obj.haveFieldTypes()); | 3183 | assert(struct_obj.haveFieldTypes()); |
| ... | @@ -3101,16 +3314,6 @@ pub const Object = struct { | ... | @@ -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 | fn lowerLlvmTypeFn(o: *Object, fn_ty: Type) Allocator.Error!*llvm.Type { | 3317 | fn lowerLlvmTypeFn(o: *Object, fn_ty: Type) Allocator.Error!*llvm.Type { |
| 3115 | const mod = o.module; | 3318 | const mod = o.module; |
| 3116 | const ip = &mod.intern_pool; | 3319 | const ip = &mod.intern_pool; |
| ... | @@ -3206,6 +3409,149 @@ pub const Object = struct { | ... | @@ -3206,6 +3409,149 @@ pub const Object = struct { |
| 3206 | return llvm_elem_ty; | 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 | fn lowerValue(o: *Object, arg_tv: TypedValue) Error!*llvm.Value { | 3555 | fn lowerValue(o: *Object, arg_tv: TypedValue) Error!*llvm.Value { |
| 3210 | const mod = o.module; | 3556 | const mod = o.module; |
| 3211 | const gpa = o.gpa; | 3557 | const gpa = o.gpa; |
| ... | @@ -10606,44 +10952,63 @@ fn toLlvmCallConv(cc: std.builtin.CallingConvention, target: std.Target) llvm.Ca | ... | @@ -10606,44 +10952,63 @@ fn toLlvmCallConv(cc: std.builtin.CallingConvention, target: std.Target) llvm.Ca |
| 10606 | | 10952 | |
| 10607 | /// Convert a zig-address space to an llvm address space. | 10953 | /// Convert a zig-address space to an llvm address space. |
| 10608 | fn toLlvmAddressSpace(address_space: std.builtin.AddressSpace, target: std.Target) c_uint { | 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 | return switch (target.cpu.arch) { | 10970 | return switch (target.cpu.arch) { |
| 10610 | .x86, .x86_64 => switch (address_space) { | 10971 | .x86, .x86_64 => &.{ |
| 10611 | .generic => llvm.address_space.default, | 10972 | .{ .zig = .generic, .llvm = llvm.address_space.default }, |
| 10612 | .gs => llvm.address_space.x86.gs, | 10973 | .{ .zig = .gs, .llvm = llvm.address_space.x86.gs }, |
| 10613 | .fs => llvm.address_space.x86.fs, | 10974 | .{ .zig = .fs, .llvm = llvm.address_space.x86.fs }, |
| 10614 | .ss => llvm.address_space.x86.ss, | 10975 | .{ .zig = .ss, .llvm = llvm.address_space.x86.ss }, |
| 10615 | else => unreachable, | 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) { | 10980 | .nvptx, .nvptx64 => &.{ |
| 10618 | .generic => llvm.address_space.default, | 10981 | .{ .zig = .generic, .llvm = llvm.address_space.default }, |
| 10619 | .global => llvm.address_space.nvptx.global, | 10982 | .{ .zig = .global, .llvm = llvm.address_space.nvptx.global }, |
| 10620 | .constant => llvm.address_space.nvptx.constant, | 10983 | .{ .zig = .constant, .llvm = llvm.address_space.nvptx.constant }, |
| 10621 | .param => llvm.address_space.nvptx.param, | 10984 | .{ .zig = .param, .llvm = llvm.address_space.nvptx.param }, |
| 10622 | .shared => llvm.address_space.nvptx.shared, | 10985 | .{ .zig = .shared, .llvm = llvm.address_space.nvptx.shared }, |
| 10623 | .local => llvm.address_space.nvptx.local, | 10986 | .{ .zig = .local, .llvm = llvm.address_space.nvptx.local }, |
| 10624 | else => unreachable, | | |
| 10625 | }, | 10987 | }, |
| 10626 | .amdgcn => switch (address_space) { | 10988 | .amdgcn => &.{ |
| 10627 | .generic => llvm.address_space.amdgpu.flat, | 10989 | .{ .zig = .generic, .llvm = llvm.address_space.amdgpu.flat }, |
| 10628 | .global => llvm.address_space.amdgpu.global, | 10990 | .{ .zig = .global, .llvm = llvm.address_space.amdgpu.global }, |
| 10629 | .constant => llvm.address_space.amdgpu.constant, | 10991 | .{ .zig = .constant, .llvm = llvm.address_space.amdgpu.constant }, |
| 10630 | .shared => llvm.address_space.amdgpu.local, | 10992 | .{ .zig = .shared, .llvm = llvm.address_space.amdgpu.local }, |
| 10631 | .local => llvm.address_space.amdgpu.private, | 10993 | .{ .zig = .local, .llvm = llvm.address_space.amdgpu.private }, |
| 10632 | else => unreachable, | | |
| 10633 | }, | 10994 | }, |
| 10634 | .avr => switch (address_space) { | 10995 | .avr => &.{ |
| 10635 | .generic => llvm.address_space.default, | 10996 | .{ .zig = .generic, .llvm = llvm.address_space.default }, |
| 10636 | .flash => llvm.address_space.avr.flash, | 10997 | .{ .zig = .flash, .llvm = llvm.address_space.avr.flash }, |
| 10637 | .flash1 => llvm.address_space.avr.flash1, | 10998 | .{ .zig = .flash1, .llvm = llvm.address_space.avr.flash1 }, |
| 10638 | .flash2 => llvm.address_space.avr.flash2, | 10999 | .{ .zig = .flash2, .llvm = llvm.address_space.avr.flash2 }, |
| 10639 | .flash3 => llvm.address_space.avr.flash3, | 11000 | .{ .zig = .flash3, .llvm = llvm.address_space.avr.flash3 }, |
| 10640 | .flash4 => llvm.address_space.avr.flash4, | 11001 | .{ .zig = .flash4, .llvm = llvm.address_space.avr.flash4 }, |
| 10641 | .flash5 => llvm.address_space.avr.flash5, | 11002 | .{ .zig = .flash5, .llvm = llvm.address_space.avr.flash5 }, |
| 10642 | else => unreachable, | | |
| 10643 | }, | 11003 | }, |
| 10644 | else => switch (address_space) { | 11004 | .wasm32, .wasm64 => &.{ |
| 10645 | .generic => llvm.address_space.default, | 11005 | .{ .zig = .generic, .llvm = llvm.address_space.default }, |
| 10646 | else => unreachable, | 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 | } |