| author | |
| committer | |
| log | b2d0675f90cc4e26fdf7a81c1edda8f1b8a00f1f |
| tree | f0b2698b7dab4de1f1e50b9fbee01488de0036fb |
| parent | d85c0ba08048d3e729d535a6df7d095fb72c6677 |
Also invert `xclang_flags` loop nesting which will make it easier to
translate features to something without `-Xclang` in the future.8 files changed, 89 insertions(+), 43 deletions(-)
lib/std/Target.zig+9-9| ... | ... | @@ -3212,7 +3212,7 @@ pub const CType = enum { |
| 3212 | 3212 | longdouble, |
| 3213 | 3213 | }; |
| 3214 | 3214 | |
| 3215 | /// Returns `null` if no C ABI is defined for this target. | |
| 3215 | /// Returns `null` if no C ABI for `c_type` is defined for this target. | |
| 3216 | 3216 | pub fn cTypeByteSize(t: *const Target, c_type: CType) ?u16 { |
| 3217 | 3217 | return switch (c_type) { |
| 3218 | 3218 | .char, |
| ... | ... | @@ -3238,7 +3238,7 @@ pub fn cTypeByteSize(t: *const Target, c_type: CType) ?u16 { |
| 3238 | 3238 | }; |
| 3239 | 3239 | } |
| 3240 | 3240 | |
| 3241 | /// Returns `null` if no C ABI is defined for this target. | |
| 3241 | /// Returns `null` if no C ABI for `c_type` is defined for this target. | |
| 3242 | 3242 | pub fn cTypeBitSize(target: *const Target, c_type: CType) ?u16 { |
| 3243 | 3243 | return switch (target.os.tag) { |
| 3244 | 3244 | .freestanding, |
| ... | ... | @@ -3285,7 +3285,7 @@ pub fn cTypeBitSize(target: *const Target, c_type: CType) ?u16 { |
| 3285 | 3285 | |
| 3286 | 3286 | .x86, |
| 3287 | 3287 | .x86_64, |
| 3288 | => 80, | |
| 3288 | => if (target.cpu.has(.x86, .x87)) 80 else null, | |
| 3289 | 3289 | |
| 3290 | 3290 | .alpha, |
| 3291 | 3291 | .riscv32, |
| ... | ... | @@ -3345,7 +3345,7 @@ pub fn cTypeBitSize(target: *const Target, c_type: CType) ?u16 { |
| 3345 | 3345 | .x86_64, |
| 3346 | 3346 | => switch (target.abi) { |
| 3347 | 3347 | .android, .ohos => 64, |
| 3348 | else => 80, | |
| 3348 | else => if (target.cpu.has(.x86, .x87)) 80 else null, | |
| 3349 | 3349 | }, |
| 3350 | 3350 | |
| 3351 | 3351 | .powerpc, |
| ... | ... | @@ -3409,7 +3409,7 @@ pub fn cTypeBitSize(target: *const Target, c_type: CType) ?u16 { |
| 3409 | 3409 | .long, .ulong => 32, |
| 3410 | 3410 | .longlong, .ulonglong, .double => 64, |
| 3411 | 3411 | .longdouble => switch (target.abi) { |
| 3412 | .gnu => 80, | |
| 3412 | .gnu => if (target.cpu.has(.x86, .x87)) 80 else null, | |
| 3413 | 3413 | else => 64, |
| 3414 | 3414 | }, |
| 3415 | 3415 | }, |
| ... | ... | @@ -3420,7 +3420,7 @@ pub fn cTypeBitSize(target: *const Target, c_type: CType) ?u16 { |
| 3420 | 3420 | .long, .ulong => 32, |
| 3421 | 3421 | .longlong, .ulonglong, .double => 64, |
| 3422 | 3422 | .longdouble => switch (target.abi) { |
| 3423 | .gnu => 80, | |
| 3423 | .gnu => if (target.cpu.has(.x86, .x87)) 80 else null, | |
| 3424 | 3424 | else => 64, |
| 3425 | 3425 | }, |
| 3426 | 3426 | }, |
| ... | ... | @@ -3454,7 +3454,7 @@ pub fn cTypeBitSize(target: *const Target, c_type: CType) ?u16 { |
| 3454 | 3454 | }, |
| 3455 | 3455 | .longlong, .ulonglong, .double => 64, |
| 3456 | 3456 | .longdouble => switch (target.cpu.arch) { |
| 3457 | .x86_64 => 80, | |
| 3457 | .x86_64 => if (target.cpu.has(.x86, .x87)) 80 else null, | |
| 3458 | 3458 | else => 64, |
| 3459 | 3459 | }, |
| 3460 | 3460 | }, |
| ... | ... | @@ -3492,14 +3492,14 @@ pub fn cTypeBitSize(target: *const Target, c_type: CType) ?u16 { |
| 3492 | 3492 | .short, .ushort => 16, |
| 3493 | 3493 | .int, .uint, .float => 32, |
| 3494 | 3494 | .long, .ulong, .longlong, .ulonglong, .double => 64, |
| 3495 | .longdouble => 80, | |
| 3495 | .longdouble => if (target.cpu.has(.x86, .x87)) 80 else null, | |
| 3496 | 3496 | }, |
| 3497 | 3497 | |
| 3498 | 3498 | .opengl => null, |
| 3499 | 3499 | }; |
| 3500 | 3500 | } |
| 3501 | 3501 | |
| 3502 | /// Returns `null` if no C ABI is defined for this target. | |
| 3502 | /// Returns `null` if no C ABI for `c_type` is defined for this target. | |
| 3503 | 3503 | pub fn cTypeAlignment(target: *const Target, c_type: CType) ?u16 { |
| 3504 | 3504 | // Overrides for unusual alignments |
| 3505 | 3505 | switch (target.cpu.arch) { |
lib/std/math/float.zig+5-4| ... | ... | @@ -12,10 +12,11 @@ pub const long_double = struct { |
| 12 | 12 | |
| 13 | 13 | inline fn bitWidth(x: anytype) u16 { |
| 14 | 14 | const T = @TypeOf(x); |
| 15 | return switch (T) { | |
| 16 | f80, f128, c_longdouble => @typeInfo(T).float.bits, | |
| 17 | else => @compileError("Unsupported type: " ++ @typeName(T) ++ "\nPass a `f80`, `f128`, or `c_longdouble`."), | |
| 18 | }; | |
| 15 | switch (@typeInfo(T)) { | |
| 16 | .float => |float| if (float.bits >= 80) return float.bits, | |
| 17 | else => {}, | |
| 18 | } | |
| 19 | @compileError("Unsupported type: " ++ @typeName(T) ++ "\nPass a `f80`, `f128`, or `c_longdouble`."); | |
| 19 | 20 | } |
| 20 | 21 | |
| 21 | 22 | /// Returns the sign + exponent bits of a `long double`. |
lib/std/zig/AstGen.zig+16| ... | ... | @@ -8140,6 +8140,22 @@ fn identifier( |
| 8140 | 8140 | // if not @"" syntax, just use raw token slice |
| 8141 | 8141 | if (ident_name_raw[0] != '@') { |
| 8142 | 8142 | if (primitive_instrs.get(ident_name_raw)) |zir_const_ref| { |
| 8143 | const maybe_c_type: ?std.Target.CType = switch (zir_const_ref) { | |
| 8144 | else => null, | |
| 8145 | .c_char_type => .char, | |
| 8146 | .c_short_type => .short, | |
| 8147 | .c_ushort_type => .ushort, | |
| 8148 | .c_int_type => .int, | |
| 8149 | .c_uint_type => .uint, | |
| 8150 | .c_long_type => .long, | |
| 8151 | .c_ulong_type => .ulong, | |
| 8152 | .c_longlong_type => .longlong, | |
| 8153 | .c_ulonglong_type => .ulonglong, | |
| 8154 | .c_longdouble_type => .longdouble, | |
| 8155 | }; | |
| 8156 | if (maybe_c_type) |c_type| { | |
| 8157 | _ = try gz.addExtendedNodeSmall(.validate_c_type, ident, @backingInt(c_type)); | |
| 8158 | } | |
| 8143 | 8159 | return rvalue(gz, ri, zir_const_ref, ident); |
| 8144 | 8160 | } |
| 8145 | 8161 |
lib/std/zig/Zir.zig+6| ... | ... | @@ -2186,6 +2186,11 @@ pub const Inst = struct { |
| 2186 | 2186 | /// For example: Provided with `error{Foo}!?f64`, returns `f64`. |
| 2187 | 2187 | /// `operand` is payload index to `UnNode`. |
| 2188 | 2188 | float_op_result_ty, |
| 2189 | /// Validate that the given `CType` is valid for the current target. | |
| 2190 | /// This can be folded into the `@CType` tag once that is implemented. | |
| 2191 | /// `operand` is `src_node: Ast.Node.Offset`. | |
| 2192 | /// `small` is a `std.Target.CType`. | |
| 2193 | validate_c_type, | |
| 2189 | 2194 | |
| 2190 | 2195 | pub const InstData = struct { |
| 2191 | 2196 | opcode: Extended, |
| ... | ... | @@ -4441,6 +4446,7 @@ fn findTrackableInner( |
| 4441 | 4446 | .astgen_error, |
| 4442 | 4447 | .float_op_result_ty, |
| 4443 | 4448 | .round_op_ty, |
| 4449 | .validate_c_type, | |
| 4444 | 4450 | => return, |
| 4445 | 4451 | |
| 4446 | 4452 | // `@TypeOf` has a body. |
src/Compilation.zig+28-27| ... | ... | @@ -6761,39 +6761,40 @@ pub fn addCCArgs( |
| 6761 | 6761 | else => &.{"-Xclang"}, |
| 6762 | 6762 | }; |
| 6763 | 6763 | |
| 6764 | for (xclang_flags) |xclang| { | |
| 6765 | if (target_util.clangSupportsTargetCpuArg(target)) { | |
| 6766 | if (target.cpu.model.llvm_name) |llvm_name| { | |
| 6764 | if (target_util.clangSupportsTargetCpuArg(target)) { | |
| 6765 | if (target.cpu.model.llvm_name) |llvm_name| { | |
| 6766 | for (xclang_flags) |xclang| { | |
| 6767 | 6767 | try argv.appendSlice(&[_][]const u8{ |
| 6768 | 6768 | xclang, "-target-cpu", xclang, llvm_name, |
| 6769 | 6769 | }); |
| 6770 | 6770 | } |
| 6771 | 6771 | } |
| 6772 | } | |
| 6773 | ||
| 6774 | // It would be really nice if there was a more compact way to communicate this info to Clang. | |
| 6775 | const all_features_list = target.cpu.arch.allFeaturesList(); | |
| 6776 | try argv.ensureUnusedCapacity(all_features_list.len * xclang_flags.len * 4); | |
| 6777 | for (all_features_list, 0..) |feature, index_usize| { | |
| 6778 | const index = @as(std.Target.Cpu.Feature.Set.Index, @intCast(index_usize)); | |
| 6779 | const is_enabled = target.cpu.features.isEnabled(index); | |
| 6772 | 6780 | |
| 6773 | // It would be really nice if there was a more compact way to communicate this info to Clang. | |
| 6774 | const all_features_list = target.cpu.arch.allFeaturesList(); | |
| 6775 | try argv.ensureUnusedCapacity(all_features_list.len * 4); | |
| 6776 | for (all_features_list, 0..) |feature, index_usize| { | |
| 6777 | const index = @as(std.Target.Cpu.Feature.Set.Index, @intCast(index_usize)); | |
| 6778 | const is_enabled = target.cpu.features.isEnabled(index); | |
| 6779 | ||
| 6780 | if (feature.llvm_name) |llvm_name| { | |
| 6781 | // We communicate these to Clang through the dedicated options. | |
| 6782 | if (std.mem.startsWith(u8, llvm_name, "soft-float") or | |
| 6783 | std.mem.startsWith(u8, llvm_name, "hard-float") or | |
| 6784 | (target.cpu.arch.isPowerPC() and std.mem.startsWith(u8, llvm_name, "64bit")) or | |
| 6785 | (target.cpu.arch.isX86() and std.mem.startsWith(u8, llvm_name, "x32")) or | |
| 6786 | (target.cpu.arch == .s390x and std.mem.eql(u8, llvm_name, "backchain"))) | |
| 6787 | continue; | |
| 6788 | ||
| 6789 | // Ignore these until we figure out how to handle the concept of omitting features. | |
| 6790 | // See https://github.com/ziglang/zig/issues/23539 | |
| 6791 | if (target_util.isDynamicAMDGCNFeature(target, feature)) continue; | |
| 6792 | ||
| 6793 | argv.appendSliceAssumeCapacity(&[_][]const u8{ xclang, "-target-feature", xclang }); | |
| 6794 | const plus_or_minus = "-+"[@intFromBool(is_enabled)]; | |
| 6795 | const arg = try std.fmt.allocPrint(arena, "{c}{s}", .{ plus_or_minus, llvm_name }); | |
| 6796 | argv.appendAssumeCapacity(arg); | |
| 6781 | if (feature.llvm_name) |llvm_name| { | |
| 6782 | // We communicate these to Clang through the dedicated options. | |
| 6783 | if (std.mem.startsWith(u8, llvm_name, "soft-float") or | |
| 6784 | std.mem.startsWith(u8, llvm_name, "hard-float") or | |
| 6785 | (target.cpu.arch.isPowerPC() and std.mem.startsWith(u8, llvm_name, "64bit")) or | |
| 6786 | (target.cpu.arch.isX86() and std.mem.startsWith(u8, llvm_name, "x32")) or | |
| 6787 | (target.cpu.arch == .s390x and std.mem.eql(u8, llvm_name, "backchain"))) | |
| 6788 | continue; | |
| 6789 | ||
| 6790 | // Ignore these until we figure out how to handle the concept of omitting features. | |
| 6791 | // See https://github.com/ziglang/zig/issues/23539 | |
| 6792 | if (target_util.isDynamicAMDGCNFeature(target, feature)) continue; | |
| 6793 | ||
| 6794 | const plus_or_minus = "-+"[@intFromBool(is_enabled)]; | |
| 6795 | const arg = try std.fmt.allocPrint(arena, "{c}{s}", .{ plus_or_minus, llvm_name }); | |
| 6796 | for (xclang_flags) |xclang| { | |
| 6797 | argv.appendSliceAssumeCapacity(&[_][]const u8{ xclang, "-target-feature", xclang, arg }); | |
| 6797 | 6798 | } |
| 6798 | 6799 | } |
| 6799 | 6800 | } |
src/Sema.zig+13| ... | ... | @@ -1469,6 +1469,11 @@ fn analyzeBodyInner( |
| 1469 | 1469 | }, |
| 1470 | 1470 | .astgen_error => return sema.failTransitive(.astgen_error), |
| 1471 | 1471 | .float_op_result_ty => try sema.zirFloatOpResultType(block, extended), |
| 1472 | .validate_c_type => { | |
| 1473 | try sema.zirValidateCType(block, extended); | |
| 1474 | i += 1; | |
| 1475 | continue; | |
| 1476 | }, | |
| 1472 | 1477 | }; |
| 1473 | 1478 | }, |
| 1474 | 1479 | |
| ... | ... | @@ -4315,6 +4320,14 @@ fn zirTryOperandTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is_ref: boo |
| 4315 | 4320 | } |
| 4316 | 4321 | } |
| 4317 | 4322 | |
| 4323 | fn zirValidateCType(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void { | |
| 4324 | const c_type: std.Target.CType = @fromBackingInt(@intCast(extended.small)); | |
| 4325 | if (sema.pt.zcu.getTarget().cTypeBitSize(c_type)) |_| return; | |
| 4326 | const src_node: std.zig.Ast.Node.Offset = @fromBackingInt(@bitCast(extended.operand)); | |
| 4327 | const src = block.nodeOffset(src_node); | |
| 4328 | return sema.fail(block, src, "'c_{t}' is not valid on this target", .{c_type}); | |
| 4329 | } | |
| 4330 | ||
| 4318 | 4331 | fn zirValidateRefTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { |
| 4319 | 4332 | const pt = sema.pt; |
| 4320 | 4333 | const zcu = pt.zcu; |
src/Type.zig+4-1| ... | ... | @@ -3178,7 +3178,10 @@ pub fn validateExtern(ty: Type, position: ExternPosition, zcu: *const Zcu) bool |
| 3178 | 3178 | }, |
| 3179 | 3179 | .float => switch (ty.floatBits(zcu.getTarget())) { |
| 3180 | 3180 | else => true, |
| 3181 | 80 => |bits| std.zig.target.compilerRtFloatAbi(zcu.getTarget(), bits) == .hard, | |
| 3181 | 80 => |bits| switch (std.zig.target.compilerRtFloatAbi(zcu.getTarget(), bits)) { | |
| 3182 | .soft => false, | |
| 3183 | .hard => true, | |
| 3184 | }, | |
| 3182 | 3185 | }, |
| 3183 | 3186 | .@"fn" => { |
| 3184 | 3187 | if (position != .other) return false; |
src/print_zir.zig+8-2| ... | ... | @@ -712,8 +712,14 @@ const Writer = struct { |
| 712 | 712 | .std_lang_value => try self.writeStdLangValue(stream, extended), |
| 713 | 713 | .inplace_arith_result_ty => try self.writeInplaceArithResultTy(stream, extended), |
| 714 | 714 | |
| 715 | .dbg_empty_stmt => try stream.writeAll("))"), | |
| 716 | .astgen_error => try stream.writeAll("))"), | |
| 715 | .dbg_empty_stmt, .astgen_error => try stream.writeAll("))"), | |
| 716 | ||
| 717 | .validate_c_type => { | |
| 718 | const c_type: std.Target.CType = @fromBackingInt(@intCast(extended.small)); | |
| 719 | const src_node: Ast.Node.Offset = @fromBackingInt(@bitCast(extended.operand)); | |
| 720 | try stream.print("{t})) ", .{c_type}); | |
| 721 | try self.writeSrcNode(stream, src_node); | |
| 722 | }, | |
| 717 | 723 | } |
| 718 | 724 | } |
| 719 | 725 |