| author | |
| committer | |
| log | 703baa4cd662e55ba39ea14ae2f30209e7ff023b |
| tree | 91516ec30a9b798f3279d2538d9d498895deef1f |
| parent | 092f019be98b9cba5ecdc9a2b1a14ba107479a41 |
Closes #357983 files changed, 220 insertions(+), 0 deletions(-)
CMakeLists.txt+1| ... | ... | @@ -358,6 +358,7 @@ set(ZIG_STAGE2_SOURCES |
| 358 | 358 | src/codegen/c/type/render_defs.zig |
| 359 | 359 | src/codegen/llvm.zig |
| 360 | 360 | src/codegen/llvm/bindings.zig |
| 361 | src/codegen/loongarch/abi.zig | |
| 361 | 362 | src/codegen/s390x/abi.zig |
| 362 | 363 | src/crash_report.zig |
| 363 | 364 | src/dev.zig |
src/codegen/llvm/FuncGen.zig+86| ... | ... | @@ -7016,6 +7016,71 @@ const ParamTypeIterator = struct { |
| 7016 | 7016 | .i64_array => |size| return .{ .i64_array = size }, |
| 7017 | 7017 | } |
| 7018 | 7018 | }, |
| 7019 | .loongarch32_ilp32, .loongarch64_lp64 => switch (loongarch_c_abi.classifyType(ty, zcu)) { | |
| 7020 | .ignored => { | |
| 7021 | it.zig_index += 1; | |
| 7022 | return .no_bits; | |
| 7023 | }, | |
| 7024 | .gar, .far => { | |
| 7025 | it.zig_index += 1; | |
| 7026 | it.llvm_index += 1; | |
| 7027 | return .byval; | |
| 7028 | }, | |
| 7029 | .member => |member_ty| { | |
| 7030 | it.types_buffer[0..1].* = .{ | |
| 7031 | try it.object.lowerType(member_ty, .as_value), | |
| 7032 | }; | |
| 7033 | it.offsets_buffer[0..2].* = .{ 0, member_ty.abiSize(zcu) }; | |
| 7034 | it.types_len = 1; | |
| 7035 | it.zig_index += 1; | |
| 7036 | it.llvm_index += 1; | |
| 7037 | return .multiple_llvm_types; | |
| 7038 | }, | |
| 7039 | .member_pair => |member_tys| { | |
| 7040 | it.types_buffer[0..2].* = .{ | |
| 7041 | try it.object.lowerType(member_tys[0], .as_value), | |
| 7042 | try it.object.lowerType(member_tys[1], .as_value), | |
| 7043 | }; | |
| 7044 | const first_size = member_tys[0].abiSize(zcu); | |
| 7045 | const second_size = member_tys[0].abiSize(zcu); | |
| 7046 | it.offsets_buffer[0..3].* = .{ 0, first_size, first_size + second_size }; | |
| 7047 | it.types_len = 2; | |
| 7048 | it.zig_index += 1; | |
| 7049 | it.llvm_index += 2; | |
| 7050 | return .multiple_llvm_types; | |
| 7051 | }, | |
| 7052 | .memory_gar => { | |
| 7053 | switch (it.cc) { | |
| 7054 | else => unreachable, | |
| 7055 | .loongarch32_ilp32 => { | |
| 7056 | it.types_buffer[0..1].* = .{.i32}; | |
| 7057 | it.offsets_buffer[0..2].* = .{ 0, 4 }; | |
| 7058 | }, | |
| 7059 | .loongarch64_lp64 => { | |
| 7060 | it.types_buffer[0..1].* = .{.i64}; | |
| 7061 | it.offsets_buffer[0..2].* = .{ 0, 8 }; | |
| 7062 | }, | |
| 7063 | } | |
| 7064 | it.types_len = 1; | |
| 7065 | it.zig_index += 1; | |
| 7066 | it.llvm_index += 1; | |
| 7067 | return .multiple_llvm_types; | |
| 7068 | }, | |
| 7069 | .memory_gar_pair => { | |
| 7070 | it.zig_index += 1; | |
| 7071 | it.llvm_index += 1; | |
| 7072 | return switch (it.cc) { | |
| 7073 | else => unreachable, | |
| 7074 | .loongarch32_ilp32 => .{ .i32_array = 2 }, | |
| 7075 | .loongarch64_lp64 => .{ .i64_array = 2 }, | |
| 7076 | }; | |
| 7077 | }, | |
| 7078 | .address => { | |
| 7079 | it.zig_index += 1; | |
| 7080 | it.llvm_index += 1; | |
| 7081 | return .byref; | |
| 7082 | }, | |
| 7083 | }, | |
| 7019 | 7084 | .mips_o32 => { |
| 7020 | 7085 | it.zig_index += 1; |
| 7021 | 7086 | it.llvm_index += 1; |
| ... | ... | @@ -7330,6 +7395,26 @@ pub fn fnReturnStrat(o: *Object, cc: std.lang.CallingConvention, ret_ty: Type) A |
| 7330 | 7395 | .i32_array => |len| if (len == 1) .{ .mem_cast = .i32 } else .sret, |
| 7331 | 7396 | .byval => .forceByVal(o, ret_ty), |
| 7332 | 7397 | }, |
| 7398 | .loongarch32_ilp32, .loongarch64_lp64 => switch (loongarch_c_abi.classifyType(ret_ty, zcu)) { | |
| 7399 | .ignored => .void, | |
| 7400 | .gar, .far => .by_val, | |
| 7401 | .member => |member_ty| .{ .mem_cast = try o.lowerType(member_ty, .as_value) }, | |
| 7402 | .member_pair => |member_tys| .{ .mem_cast = try o.builder.structType(.normal, &.{ | |
| 7403 | try o.lowerType(member_tys[0], .as_value), | |
| 7404 | try o.lowerType(member_tys[1], .as_value), | |
| 7405 | }) }, | |
| 7406 | .memory_gar => .{ .mem_cast = switch (cc) { | |
| 7407 | else => unreachable, | |
| 7408 | .loongarch32_ilp32 => .i32, | |
| 7409 | .loongarch64_lp64 => .i64, | |
| 7410 | } }, | |
| 7411 | .memory_gar_pair => .{ .mem_cast = try o.builder.arrayType(2, switch (cc) { | |
| 7412 | else => unreachable, | |
| 7413 | .loongarch32_ilp32 => .i32, | |
| 7414 | .loongarch64_lp64 => .i64, | |
| 7415 | }) }, | |
| 7416 | .address => .sret, | |
| 7417 | }, | |
| 7333 | 7418 | .mips_o32 => switch (mips_c_abi.classifyType(ret_ty, zcu, .ret)) { |
| 7334 | 7419 | .memory, .i32_array => .sret, |
| 7335 | 7420 | .byval => .forceByVal(o, ret_ty), |
| ... | ... | @@ -8124,6 +8209,7 @@ const math = std.math; |
| 8124 | 8209 | |
| 8125 | 8210 | const aarch64_c_abi = @import("../aarch64/abi.zig"); |
| 8126 | 8211 | const arm_c_abi = @import("../arm/abi.zig"); |
| 8212 | const loongarch_c_abi = @import("../loongarch/abi.zig"); | |
| 8127 | 8213 | const mips_c_abi = @import("../mips/abi.zig"); |
| 8128 | 8214 | const riscv_c_abi = @import("../riscv64/abi.zig"); |
| 8129 | 8215 | const s390x_c_abi = @import("../s390x/abi.zig"); |
src/codegen/loongarch/abi.zig created+133| ... | ... | @@ -0,0 +1,133 @@ |
| 1 | const std = @import("std"); | |
| 2 | const InternPool = @import("../../InternPool.zig"); | |
| 3 | const Type = @import("../../Type.zig"); | |
| 4 | const Zcu = @import("../../Zcu.zig"); | |
| 5 | ||
| 6 | pub const Class = union(enum) { | |
| 7 | ignored, | |
| 8 | gar, | |
| 9 | far, | |
| 10 | member: Type, | |
| 11 | member_pair: [2]Type, | |
| 12 | memory_gar, | |
| 13 | memory_gar_pair, | |
| 14 | address, | |
| 15 | ||
| 16 | fn combineMember(container_class: Class, member_class: Class, member_ty: Type) Class { | |
| 17 | const second_member_ty = switch (member_class) { | |
| 18 | .ignored => return container_class, | |
| 19 | .gar, .far => member_ty, | |
| 20 | .member => |second_member_ty| second_member_ty, | |
| 21 | .member_pair, .memory_gar, .memory_gar_pair, .address => return .address, | |
| 22 | }; | |
| 23 | return switch (container_class) { | |
| 24 | .ignored => .{ .member = second_member_ty }, | |
| 25 | .gar, .far, .memory_gar, .memory_gar_pair => unreachable, | |
| 26 | .member => |first_member_ty| .{ .member_pair = .{ first_member_ty, second_member_ty } }, | |
| 27 | .member_pair, .address => .address, | |
| 28 | }; | |
| 29 | } | |
| 30 | }; | |
| 31 | ||
| 32 | pub fn classifyType(ty: Type, zcu: *Zcu) Class { | |
| 33 | return Classifier.init(zcu).classifyType(ty); | |
| 34 | } | |
| 35 | ||
| 36 | const Classifier = struct { | |
| 37 | zcu: *Zcu, | |
| 38 | target: *const std.Target, | |
| 39 | grlen: u8, | |
| 40 | frlen: u8, | |
| 41 | ||
| 42 | fn init(zcu: *Zcu) Classifier { | |
| 43 | const target = zcu.getTarget(); | |
| 44 | return .{ | |
| 45 | .zcu = zcu, | |
| 46 | .target = target, | |
| 47 | .grlen = switch (target.cpu.arch) { | |
| 48 | else => unreachable, | |
| 49 | .loongarch32 => 32, | |
| 50 | .loongarch64 => 64, | |
| 51 | }, | |
| 52 | .frlen = if (target.cpu.has(.loongarch, .d)) | |
| 53 | 64 | |
| 54 | else if (target.cpu.has(.loongarch, .f)) | |
| 55 | 32 | |
| 56 | else | |
| 57 | 0, | |
| 58 | }; | |
| 59 | } | |
| 60 | ||
| 61 | fn classifyType(c: Classifier, ty: Type) Class { | |
| 62 | switch (ty.zigTypeTag(c.zcu)) { | |
| 63 | .type, | |
| 64 | .comptime_float, | |
| 65 | .comptime_int, | |
| 66 | .undefined, | |
| 67 | .null, | |
| 68 | .error_union, | |
| 69 | .error_set, | |
| 70 | .@"fn", | |
| 71 | .@"opaque", | |
| 72 | .frame, | |
| 73 | .@"anyframe", | |
| 74 | .enum_literal, | |
| 75 | .spirv, | |
| 76 | => unreachable, | |
| 77 | .void, .noreturn => return .ignored, | |
| 78 | .bool => return .gar, | |
| 79 | .int, .@"enum" => { | |
| 80 | const bits = ty.intInfo(c.zcu).bits; | |
| 81 | if (bits == 0) return .ignored; | |
| 82 | if (bits <= c.grlen) return .gar; | |
| 83 | if (bits <= 2 * c.grlen) return .memory_gar_pair; | |
| 84 | return .address; | |
| 85 | }, | |
| 86 | .float => { | |
| 87 | const bits = ty.floatBits(c.target); | |
| 88 | if (bits <= c.frlen) return .far; | |
| 89 | if (bits <= c.grlen) return .gar; | |
| 90 | if (bits <= 2 * c.grlen) return .memory_gar_pair; | |
| 91 | return .address; | |
| 92 | }, | |
| 93 | .pointer, .optional => return .gar, | |
| 94 | .array => { | |
| 95 | var class: Class = .ignored; | |
| 96 | const elem_ty = ty.childType(c.zcu); | |
| 97 | const elem_class = c.classifyType(elem_ty); | |
| 98 | for (0..std.math.lossyCast(usize, ty.arrayLen(c.zcu))) |_| { | |
| 99 | class = class.combineMember(elem_class, elem_ty); | |
| 100 | if (class == .address) break; | |
| 101 | } | |
| 102 | if (class != .address) return class; | |
| 103 | }, | |
| 104 | .@"struct" => switch (ty.containerLayout(c.zcu)) { | |
| 105 | .auto => unreachable, | |
| 106 | .@"extern" => { | |
| 107 | var class: Class = .ignored; | |
| 108 | var field_it: InternPool.LoadedStructType.RuntimeOrderIterator = if (c.zcu.typeToStruct(ty)) |loaded_struct| | |
| 109 | loaded_struct.iterateRuntimeOrder(&c.zcu.intern_pool) | |
| 110 | else | |
| 111 | .{ .runtime_order = null, .fields_len = ty.structFieldCount(c.zcu), .next_index = 0 }; | |
| 112 | while (field_it.next()) |field_index| { | |
| 113 | const field_ty = ty.fieldType(field_index, c.zcu); | |
| 114 | class = class.combineMember(c.classifyType(field_ty), field_ty); | |
| 115 | if (class == .address) break; | |
| 116 | } | |
| 117 | if (class != .address) return class; | |
| 118 | }, | |
| 119 | .@"packed" => return c.classifyType(ty.backingIntType(c.zcu)), | |
| 120 | }, | |
| 121 | .@"union" => switch (ty.containerLayout(c.zcu)) { | |
| 122 | .auto => unreachable, | |
| 123 | .@"extern" => {}, | |
| 124 | .@"packed" => return c.classifyType(ty.backingIntType(c.zcu)), | |
| 125 | }, | |
| 126 | .vector => {}, | |
| 127 | } | |
| 128 | const size = ty.abiSize(c.zcu); | |
| 129 | if (size <= @divExact(c.grlen, 8)) return .memory_gar; | |
| 130 | if (size <= @divExact(2 * c.grlen, 8)) return .memory_gar_pair; | |
| 131 | return .address; | |
| 132 | } | |
| 133 | }; |