| author | |
| committer | |
| log | 699b6cdf01babd86d56206667a35491d2c4d00f1 |
| tree | ddf70f0d6282034497707a579197428740cb3b30 |
| parent | ec36b82d058b7e20101a2f55a7ec123077ce9b70 |
9 files changed, 697 insertions(+), 672 deletions(-)
lib/std/c.zig-1| ... | ... | @@ -10,7 +10,6 @@ const page_size = std.mem.page_size; |
| 10 | 10 | pub const tokenizer = @import("c/tokenizer.zig"); |
| 11 | 11 | pub const Token = tokenizer.Token; |
| 12 | 12 | pub const Tokenizer = tokenizer.Tokenizer; |
| 13 | pub const builtins = @import("c/builtins.zig"); | |
| 14 | 13 | |
| 15 | 14 | test { |
| 16 | 15 | _ = tokenizer; |
lib/std/c/builtins.zig deleted-196| ... | ... | @@ -1,196 +0,0 @@ |
| 1 | // SPDX-License-Identifier: MIT | |
| 2 | // Copyright (c) 2015-2021 Zig Contributors | |
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | |
| 4 | // The MIT license requires this copyright notice to be included in all copies | |
| 5 | // and substantial portions of the software. | |
| 6 | ||
| 7 | const std = @import("std"); | |
| 8 | ||
| 9 | pub inline fn __builtin_bswap16(val: u16) u16 { | |
| 10 | return @byteSwap(u16, val); | |
| 11 | } | |
| 12 | pub inline fn __builtin_bswap32(val: u32) u32 { | |
| 13 | return @byteSwap(u32, val); | |
| 14 | } | |
| 15 | pub inline fn __builtin_bswap64(val: u64) u64 { | |
| 16 | return @byteSwap(u64, val); | |
| 17 | } | |
| 18 | ||
| 19 | pub inline fn __builtin_signbit(val: f64) c_int { | |
| 20 | return @boolToInt(std.math.signbit(val)); | |
| 21 | } | |
| 22 | pub inline fn __builtin_signbitf(val: f32) c_int { | |
| 23 | return @boolToInt(std.math.signbit(val)); | |
| 24 | } | |
| 25 | ||
| 26 | pub inline fn __builtin_popcount(val: c_uint) c_int { | |
| 27 | // popcount of a c_uint will never exceed the capacity of a c_int | |
| 28 | @setRuntimeSafety(false); | |
| 29 | return @bitCast(c_int, @as(c_uint, @popCount(c_uint, val))); | |
| 30 | } | |
| 31 | pub inline fn __builtin_ctz(val: c_uint) c_int { | |
| 32 | // Returns the number of trailing 0-bits in val, starting at the least significant bit position. | |
| 33 | // In C if `val` is 0, the result is undefined; in zig it's the number of bits in a c_uint | |
| 34 | @setRuntimeSafety(false); | |
| 35 | return @bitCast(c_int, @as(c_uint, @ctz(c_uint, val))); | |
| 36 | } | |
| 37 | pub inline fn __builtin_clz(val: c_uint) c_int { | |
| 38 | // Returns the number of leading 0-bits in x, starting at the most significant bit position. | |
| 39 | // In C if `val` is 0, the result is undefined; in zig it's the number of bits in a c_uint | |
| 40 | @setRuntimeSafety(false); | |
| 41 | return @bitCast(c_int, @as(c_uint, @clz(c_uint, val))); | |
| 42 | } | |
| 43 | ||
| 44 | pub inline fn __builtin_sqrt(val: f64) f64 { | |
| 45 | return @sqrt(val); | |
| 46 | } | |
| 47 | pub inline fn __builtin_sqrtf(val: f32) f32 { | |
| 48 | return @sqrt(val); | |
| 49 | } | |
| 50 | ||
| 51 | pub inline fn __builtin_sin(val: f64) f64 { | |
| 52 | return @sin(val); | |
| 53 | } | |
| 54 | pub inline fn __builtin_sinf(val: f32) f32 { | |
| 55 | return @sin(val); | |
| 56 | } | |
| 57 | pub inline fn __builtin_cos(val: f64) f64 { | |
| 58 | return @cos(val); | |
| 59 | } | |
| 60 | pub inline fn __builtin_cosf(val: f32) f32 { | |
| 61 | return @cos(val); | |
| 62 | } | |
| 63 | ||
| 64 | pub inline fn __builtin_exp(val: f64) f64 { | |
| 65 | return @exp(val); | |
| 66 | } | |
| 67 | pub inline fn __builtin_expf(val: f32) f32 { | |
| 68 | return @exp(val); | |
| 69 | } | |
| 70 | pub inline fn __builtin_exp2(val: f64) f64 { | |
| 71 | return @exp2(val); | |
| 72 | } | |
| 73 | pub inline fn __builtin_exp2f(val: f32) f32 { | |
| 74 | return @exp2(val); | |
| 75 | } | |
| 76 | pub inline fn __builtin_log(val: f64) f64 { | |
| 77 | return @log(val); | |
| 78 | } | |
| 79 | pub inline fn __builtin_logf(val: f32) f32 { | |
| 80 | return @log(val); | |
| 81 | } | |
| 82 | pub inline fn __builtin_log2(val: f64) f64 { | |
| 83 | return @log2(val); | |
| 84 | } | |
| 85 | pub inline fn __builtin_log2f(val: f32) f32 { | |
| 86 | return @log2(val); | |
| 87 | } | |
| 88 | pub inline fn __builtin_log10(val: f64) f64 { | |
| 89 | return @log10(val); | |
| 90 | } | |
| 91 | pub inline fn __builtin_log10f(val: f32) f32 { | |
| 92 | return @log10(val); | |
| 93 | } | |
| 94 | ||
| 95 | // Standard C Library bug: The absolute value of the most negative integer remains negative. | |
| 96 | pub inline fn __builtin_abs(val: c_int) c_int { | |
| 97 | return std.math.absInt(val) catch std.math.minInt(c_int); | |
| 98 | } | |
| 99 | pub inline fn __builtin_fabs(val: f64) f64 { | |
| 100 | return @fabs(val); | |
| 101 | } | |
| 102 | pub inline fn __builtin_fabsf(val: f32) f32 { | |
| 103 | return @fabs(val); | |
| 104 | } | |
| 105 | ||
| 106 | pub inline fn __builtin_floor(val: f64) f64 { | |
| 107 | return @floor(val); | |
| 108 | } | |
| 109 | pub inline fn __builtin_floorf(val: f32) f32 { | |
| 110 | return @floor(val); | |
| 111 | } | |
| 112 | pub inline fn __builtin_ceil(val: f64) f64 { | |
| 113 | return @ceil(val); | |
| 114 | } | |
| 115 | pub inline fn __builtin_ceilf(val: f32) f32 { | |
| 116 | return @ceil(val); | |
| 117 | } | |
| 118 | pub inline fn __builtin_trunc(val: f64) f64 { | |
| 119 | return @trunc(val); | |
| 120 | } | |
| 121 | pub inline fn __builtin_truncf(val: f32) f32 { | |
| 122 | return @trunc(val); | |
| 123 | } | |
| 124 | pub inline fn __builtin_round(val: f64) f64 { | |
| 125 | return @round(val); | |
| 126 | } | |
| 127 | pub inline fn __builtin_roundf(val: f32) f32 { | |
| 128 | return @round(val); | |
| 129 | } | |
| 130 | ||
| 131 | pub inline fn __builtin_strlen(s: [*c]const u8) usize { | |
| 132 | return std.mem.lenZ(s); | |
| 133 | } | |
| 134 | pub inline fn __builtin_strcmp(s1: [*c]const u8, s2: [*c]const u8) c_int { | |
| 135 | return @as(c_int, std.cstr.cmp(s1, s2)); | |
| 136 | } | |
| 137 | ||
| 138 | pub inline fn __builtin_object_size(ptr: ?*const c_void, ty: c_int) usize { | |
| 139 | // clang semantics match gcc's: https://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html | |
| 140 | // If it is not possible to determine which objects ptr points to at compile time, | |
| 141 | // __builtin_object_size should return (size_t) -1 for type 0 or 1 and (size_t) 0 | |
| 142 | // for type 2 or 3. | |
| 143 | if (ty == 0 or ty == 1) return @bitCast(usize, -@as(isize, 1)); | |
| 144 | if (ty == 2 or ty == 3) return 0; | |
| 145 | unreachable; | |
| 146 | } | |
| 147 | ||
| 148 | pub inline fn __builtin___memset_chk( | |
| 149 | dst: ?*c_void, | |
| 150 | val: c_int, | |
| 151 | len: usize, | |
| 152 | remaining: usize, | |
| 153 | ) ?*c_void { | |
| 154 | if (len > remaining) @panic("std.c.builtins.memset_chk called with len > remaining"); | |
| 155 | return __builtin_memset(dst, val, len); | |
| 156 | } | |
| 157 | ||
| 158 | pub inline fn __builtin_memset(dst: ?*c_void, val: c_int, len: usize) ?*c_void { | |
| 159 | const dst_cast = @ptrCast([*c]u8, dst); | |
| 160 | @memset(dst_cast, @bitCast(u8, @truncate(i8, val)), len); | |
| 161 | return dst; | |
| 162 | } | |
| 163 | ||
| 164 | pub inline fn __builtin___memcpy_chk( | |
| 165 | noalias dst: ?*c_void, | |
| 166 | noalias src: ?*const c_void, | |
| 167 | len: usize, | |
| 168 | remaining: usize, | |
| 169 | ) ?*c_void { | |
| 170 | if (len > remaining) @panic("std.c.builtins.memcpy_chk called with len > remaining"); | |
| 171 | return __builtin_memcpy(dst, src, len); | |
| 172 | } | |
| 173 | ||
| 174 | pub inline fn __builtin_memcpy( | |
| 175 | noalias dst: ?*c_void, | |
| 176 | noalias src: ?*const c_void, | |
| 177 | len: usize, | |
| 178 | ) ?*c_void { | |
| 179 | const dst_cast = @ptrCast([*c]u8, dst); | |
| 180 | const src_cast = @ptrCast([*c]const u8, src); | |
| 181 | ||
| 182 | @memcpy(dst_cast, src_cast, len); | |
| 183 | return dst; | |
| 184 | } | |
| 185 | ||
| 186 | /// The return value of __builtin_expect is `expr`. `c` is the expected value | |
| 187 | /// of `expr` and is used as a hint to the compiler in C. Here it is unused. | |
| 188 | pub inline fn __builtin_expect(expr: c_long, c: c_long) c_long { | |
| 189 | return expr; | |
| 190 | } | |
| 191 | ||
| 192 | // __builtin_alloca_with_align is not currently implemented. | |
| 193 | // It is used in a run-translated-c test and a test-translate-c test to ensure that non-implemented | |
| 194 | // builtins are correctly demoted. If you implement __builtin_alloca_with_align, please update the | |
| 195 | // run-translated-c test and the test-translate-c test to use a different non-implemented builtin. | |
| 196 | // pub fn __builtin_alloca_with_align(size: usize, alignment: usize) callconv(.Inline) *c_void {} |
lib/std/meta.zig-376| ... | ... | @@ -884,319 +884,6 @@ pub fn Vector(comptime len: u32, comptime child: type) type { |
| 884 | 884 | }); |
| 885 | 885 | } |
| 886 | 886 | |
| 887 | /// Given a type and value, cast the value to the type as c would. | |
| 888 | /// This is for translate-c and is not intended for general use. | |
| 889 | pub fn cast(comptime DestType: type, target: anytype) DestType { | |
| 890 | // this function should behave like transCCast in translate-c, except it's for macros and enums | |
| 891 | const SourceType = @TypeOf(target); | |
| 892 | switch (@typeInfo(DestType)) { | |
| 893 | .Pointer => return castToPtr(DestType, SourceType, target), | |
| 894 | .Optional => |dest_opt| { | |
| 895 | if (@typeInfo(dest_opt.child) == .Pointer) { | |
| 896 | return castToPtr(DestType, SourceType, target); | |
| 897 | } | |
| 898 | }, | |
| 899 | .Enum => |enum_type| { | |
| 900 | if (@typeInfo(SourceType) == .Int or @typeInfo(SourceType) == .ComptimeInt) { | |
| 901 | const intermediate = cast(enum_type.tag_type, target); | |
| 902 | return @intToEnum(DestType, intermediate); | |
| 903 | } | |
| 904 | }, | |
| 905 | .Int => { | |
| 906 | switch (@typeInfo(SourceType)) { | |
| 907 | .Pointer => { | |
| 908 | return castInt(DestType, @ptrToInt(target)); | |
| 909 | }, | |
| 910 | .Optional => |opt| { | |
| 911 | if (@typeInfo(opt.child) == .Pointer) { | |
| 912 | return castInt(DestType, @ptrToInt(target)); | |
| 913 | } | |
| 914 | }, | |
| 915 | .Enum => { | |
| 916 | return castInt(DestType, @enumToInt(target)); | |
| 917 | }, | |
| 918 | .Int => { | |
| 919 | return castInt(DestType, target); | |
| 920 | }, | |
| 921 | else => {}, | |
| 922 | } | |
| 923 | }, | |
| 924 | else => {}, | |
| 925 | } | |
| 926 | return @as(DestType, target); | |
| 927 | } | |
| 928 | ||
| 929 | fn castInt(comptime DestType: type, target: anytype) DestType { | |
| 930 | const dest = @typeInfo(DestType).Int; | |
| 931 | const source = @typeInfo(@TypeOf(target)).Int; | |
| 932 | ||
| 933 | if (dest.bits < source.bits) | |
| 934 | return @bitCast(DestType, @truncate(Int(source.signedness, dest.bits), target)) | |
| 935 | else | |
| 936 | return @bitCast(DestType, @as(Int(source.signedness, dest.bits), target)); | |
| 937 | } | |
| 938 | ||
| 939 | fn castPtr(comptime DestType: type, target: anytype) DestType { | |
| 940 | const dest = ptrInfo(DestType); | |
| 941 | const source = ptrInfo(@TypeOf(target)); | |
| 942 | ||
| 943 | if (source.is_const and !dest.is_const or source.is_volatile and !dest.is_volatile) | |
| 944 | return @intToPtr(DestType, @ptrToInt(target)) | |
| 945 | else if (@typeInfo(dest.child) == .Opaque) | |
| 946 | // dest.alignment would error out | |
| 947 | return @ptrCast(DestType, target) | |
| 948 | else | |
| 949 | return @ptrCast(DestType, @alignCast(dest.alignment, target)); | |
| 950 | } | |
| 951 | ||
| 952 | fn castToPtr(comptime DestType: type, comptime SourceType: type, target: anytype) DestType { | |
| 953 | switch (@typeInfo(SourceType)) { | |
| 954 | .Int => { | |
| 955 | return @intToPtr(DestType, castInt(usize, target)); | |
| 956 | }, | |
| 957 | .ComptimeInt => { | |
| 958 | if (target < 0) | |
| 959 | return @intToPtr(DestType, @bitCast(usize, @intCast(isize, target))) | |
| 960 | else | |
| 961 | return @intToPtr(DestType, @intCast(usize, target)); | |
| 962 | }, | |
| 963 | .Pointer => { | |
| 964 | return castPtr(DestType, target); | |
| 965 | }, | |
| 966 | .Optional => |target_opt| { | |
| 967 | if (@typeInfo(target_opt.child) == .Pointer) { | |
| 968 | return castPtr(DestType, target); | |
| 969 | } | |
| 970 | }, | |
| 971 | else => {}, | |
| 972 | } | |
| 973 | return @as(DestType, target); | |
| 974 | } | |
| 975 | ||
| 976 | fn ptrInfo(comptime PtrType: type) TypeInfo.Pointer { | |
| 977 | return switch (@typeInfo(PtrType)) { | |
| 978 | .Optional => |opt_info| @typeInfo(opt_info.child).Pointer, | |
| 979 | .Pointer => |ptr_info| ptr_info, | |
| 980 | else => unreachable, | |
| 981 | }; | |
| 982 | } | |
| 983 | ||
| 984 | test "std.meta.cast" { | |
| 985 | const E = enum(u2) { | |
| 986 | Zero, | |
| 987 | One, | |
| 988 | Two, | |
| 989 | }; | |
| 990 | ||
| 991 | var i = @as(i64, 10); | |
| 992 | ||
| 993 | try testing.expect(cast(*u8, 16) == @intToPtr(*u8, 16)); | |
| 994 | try testing.expect(cast(*u64, &i).* == @as(u64, 10)); | |
| 995 | try testing.expect(cast(*i64, @as(?*align(1) i64, &i)) == &i); | |
| 996 | ||
| 997 | try testing.expect(cast(?*u8, 2) == @intToPtr(*u8, 2)); | |
| 998 | try testing.expect(cast(?*i64, @as(*align(1) i64, &i)) == &i); | |
| 999 | try testing.expect(cast(?*i64, @as(?*align(1) i64, &i)) == &i); | |
| 1000 | ||
| 1001 | try testing.expect(cast(E, 1) == .One); | |
| 1002 | ||
| 1003 | try testing.expectEqual(@as(u32, 4), cast(u32, @intToPtr(*u32, 4))); | |
| 1004 | try testing.expectEqual(@as(u32, 4), cast(u32, @intToPtr(?*u32, 4))); | |
| 1005 | try testing.expectEqual(@as(u32, 10), cast(u32, @as(u64, 10))); | |
| 1006 | try testing.expectEqual(@as(u8, 2), cast(u8, E.Two)); | |
| 1007 | ||
| 1008 | try testing.expectEqual(@bitCast(i32, @as(u32, 0x8000_0000)), cast(i32, @as(u32, 0x8000_0000))); | |
| 1009 | ||
| 1010 | try testing.expectEqual(@intToPtr(*u8, 2), cast(*u8, @intToPtr(*const u8, 2))); | |
| 1011 | try testing.expectEqual(@intToPtr(*u8, 2), cast(*u8, @intToPtr(*volatile u8, 2))); | |
| 1012 | ||
| 1013 | try testing.expectEqual(@intToPtr(?*c_void, 2), cast(?*c_void, @intToPtr(*u8, 2))); | |
| 1014 | ||
| 1015 | const C_ENUM = enum(c_int) { | |
| 1016 | A = 0, | |
| 1017 | B, | |
| 1018 | C, | |
| 1019 | _, | |
| 1020 | }; | |
| 1021 | try testing.expectEqual(cast(C_ENUM, @as(i64, -1)), @intToEnum(C_ENUM, -1)); | |
| 1022 | try testing.expectEqual(cast(C_ENUM, @as(i8, 1)), .B); | |
| 1023 | try testing.expectEqual(cast(C_ENUM, @as(u64, 1)), .B); | |
| 1024 | try testing.expectEqual(cast(C_ENUM, @as(u64, 42)), @intToEnum(C_ENUM, 42)); | |
| 1025 | ||
| 1026 | var foo: c_int = -1; | |
| 1027 | try testing.expect(cast(*c_void, -1) == @intToPtr(*c_void, @bitCast(usize, @as(isize, -1)))); | |
| 1028 | try testing.expect(cast(*c_void, foo) == @intToPtr(*c_void, @bitCast(usize, @as(isize, -1)))); | |
| 1029 | try testing.expect(cast(?*c_void, -1) == @intToPtr(?*c_void, @bitCast(usize, @as(isize, -1)))); | |
| 1030 | try testing.expect(cast(?*c_void, foo) == @intToPtr(?*c_void, @bitCast(usize, @as(isize, -1)))); | |
| 1031 | } | |
| 1032 | ||
| 1033 | /// Given a value returns its size as C's sizeof operator would. | |
| 1034 | /// This is for translate-c and is not intended for general use. | |
| 1035 | pub fn sizeof(target: anytype) usize { | |
| 1036 | const T: type = if (@TypeOf(target) == type) target else @TypeOf(target); | |
| 1037 | switch (@typeInfo(T)) { | |
| 1038 | .Float, .Int, .Struct, .Union, .Enum, .Array, .Bool, .Vector => return @sizeOf(T), | |
| 1039 | .Fn => { | |
| 1040 | // sizeof(main) returns 1, sizeof(&main) returns pointer size. | |
| 1041 | // We cannot distinguish those types in Zig, so use pointer size. | |
| 1042 | return @sizeOf(T); | |
| 1043 | }, | |
| 1044 | .Null => return @sizeOf(*c_void), | |
| 1045 | .Void => { | |
| 1046 | // Note: sizeof(void) is 1 on clang/gcc and 0 on MSVC. | |
| 1047 | return 1; | |
| 1048 | }, | |
| 1049 | .Opaque => { | |
| 1050 | if (T == c_void) { | |
| 1051 | // Note: sizeof(void) is 1 on clang/gcc and 0 on MSVC. | |
| 1052 | return 1; | |
| 1053 | } else { | |
| 1054 | @compileError("Cannot use C sizeof on opaque type " ++ @typeName(T)); | |
| 1055 | } | |
| 1056 | }, | |
| 1057 | .Optional => |opt| { | |
| 1058 | if (@typeInfo(opt.child) == .Pointer) { | |
| 1059 | return sizeof(opt.child); | |
| 1060 | } else { | |
| 1061 | @compileError("Cannot use C sizeof on non-pointer optional " ++ @typeName(T)); | |
| 1062 | } | |
| 1063 | }, | |
| 1064 | .Pointer => |ptr| { | |
| 1065 | if (ptr.size == .Slice) { | |
| 1066 | @compileError("Cannot use C sizeof on slice type " ++ @typeName(T)); | |
| 1067 | } | |
| 1068 | // for strings, sizeof("a") returns 2. | |
| 1069 | // normal pointer decay scenarios from C are handled | |
| 1070 | // in the .Array case above, but strings remain literals | |
| 1071 | // and are therefore always pointers, so they need to be | |
| 1072 | // specially handled here. | |
| 1073 | if (ptr.size == .One and ptr.is_const and @typeInfo(ptr.child) == .Array) { | |
| 1074 | const array_info = @typeInfo(ptr.child).Array; | |
| 1075 | if ((array_info.child == u8 or array_info.child == u16) and | |
| 1076 | array_info.sentinel != null and | |
| 1077 | array_info.sentinel.? == 0) | |
| 1078 | { | |
| 1079 | // length of the string plus one for the null terminator. | |
| 1080 | return (array_info.len + 1) * @sizeOf(array_info.child); | |
| 1081 | } | |
| 1082 | } | |
| 1083 | // When zero sized pointers are removed, this case will no | |
| 1084 | // longer be reachable and can be deleted. | |
| 1085 | if (@sizeOf(T) == 0) { | |
| 1086 | return @sizeOf(*c_void); | |
| 1087 | } | |
| 1088 | return @sizeOf(T); | |
| 1089 | }, | |
| 1090 | .ComptimeFloat => return @sizeOf(f64), // TODO c_double #3999 | |
| 1091 | .ComptimeInt => { | |
| 1092 | // TODO to get the correct result we have to translate | |
| 1093 | // `1073741824 * 4` as `int(1073741824) *% int(4)` since | |
| 1094 | // sizeof(1073741824 * 4) != sizeof(4294967296). | |
| 1095 | ||
| 1096 | // TODO test if target fits in int, long or long long | |
| 1097 | return @sizeOf(c_int); | |
| 1098 | }, | |
| 1099 | else => @compileError("std.meta.sizeof does not support type " ++ @typeName(T)), | |
| 1100 | } | |
| 1101 | } | |
| 1102 | ||
| 1103 | test "sizeof" { | |
| 1104 | const E = enum(c_int) { One, _ }; | |
| 1105 | const S = extern struct { a: u32 }; | |
| 1106 | ||
| 1107 | const ptr_size = @sizeOf(*c_void); | |
| 1108 | ||
| 1109 | try testing.expect(sizeof(u32) == 4); | |
| 1110 | try testing.expect(sizeof(@as(u32, 2)) == 4); | |
| 1111 | try testing.expect(sizeof(2) == @sizeOf(c_int)); | |
| 1112 | ||
| 1113 | try testing.expect(sizeof(2.0) == @sizeOf(f64)); | |
| 1114 | ||
| 1115 | try testing.expect(sizeof(E) == @sizeOf(c_int)); | |
| 1116 | try testing.expect(sizeof(E.One) == @sizeOf(c_int)); | |
| 1117 | ||
| 1118 | try testing.expect(sizeof(S) == 4); | |
| 1119 | ||
| 1120 | try testing.expect(sizeof([_]u32{ 4, 5, 6 }) == 12); | |
| 1121 | try testing.expect(sizeof([3]u32) == 12); | |
| 1122 | try testing.expect(sizeof([3:0]u32) == 16); | |
| 1123 | try testing.expect(sizeof(&[_]u32{ 4, 5, 6 }) == ptr_size); | |
| 1124 | ||
| 1125 | try testing.expect(sizeof(*u32) == ptr_size); | |
| 1126 | try testing.expect(sizeof([*]u32) == ptr_size); | |
| 1127 | try testing.expect(sizeof([*c]u32) == ptr_size); | |
| 1128 | try testing.expect(sizeof(?*u32) == ptr_size); | |
| 1129 | try testing.expect(sizeof(?[*]u32) == ptr_size); | |
| 1130 | try testing.expect(sizeof(*c_void) == ptr_size); | |
| 1131 | try testing.expect(sizeof(*void) == ptr_size); | |
| 1132 | try testing.expect(sizeof(null) == ptr_size); | |
| 1133 | ||
| 1134 | try testing.expect(sizeof("foobar") == 7); | |
| 1135 | try testing.expect(sizeof(&[_:0]u16{ 'f', 'o', 'o', 'b', 'a', 'r' }) == 14); | |
| 1136 | try testing.expect(sizeof(*const [4:0]u8) == 5); | |
| 1137 | try testing.expect(sizeof(*[4:0]u8) == ptr_size); | |
| 1138 | try testing.expect(sizeof([*]const [4:0]u8) == ptr_size); | |
| 1139 | try testing.expect(sizeof(*const *const [4:0]u8) == ptr_size); | |
| 1140 | try testing.expect(sizeof(*const [4]u8) == ptr_size); | |
| 1141 | ||
| 1142 | try testing.expect(sizeof(sizeof) == @sizeOf(@TypeOf(sizeof))); | |
| 1143 | ||
| 1144 | try testing.expect(sizeof(void) == 1); | |
| 1145 | try testing.expect(sizeof(c_void) == 1); | |
| 1146 | } | |
| 1147 | ||
| 1148 | pub const CIntLiteralRadix = enum { decimal, octal, hexadecimal }; | |
| 1149 | ||
| 1150 | fn PromoteIntLiteralReturnType(comptime SuffixType: type, comptime number: comptime_int, comptime radix: CIntLiteralRadix) type { | |
| 1151 | const signed_decimal = [_]type{ c_int, c_long, c_longlong }; | |
| 1152 | const signed_oct_hex = [_]type{ c_int, c_uint, c_long, c_ulong, c_longlong, c_ulonglong }; | |
| 1153 | const unsigned = [_]type{ c_uint, c_ulong, c_ulonglong }; | |
| 1154 | ||
| 1155 | const list: []const type = if (@typeInfo(SuffixType).Int.signedness == .unsigned) | |
| 1156 | &unsigned | |
| 1157 | else if (radix == .decimal) | |
| 1158 | &signed_decimal | |
| 1159 | else | |
| 1160 | &signed_oct_hex; | |
| 1161 | ||
| 1162 | var pos = mem.indexOfScalar(type, list, SuffixType).?; | |
| 1163 | ||
| 1164 | while (pos < list.len) : (pos += 1) { | |
| 1165 | if (number >= math.minInt(list[pos]) and number <= math.maxInt(list[pos])) { | |
| 1166 | return list[pos]; | |
| 1167 | } | |
| 1168 | } | |
| 1169 | @compileError("Integer literal is too large"); | |
| 1170 | } | |
| 1171 | ||
| 1172 | /// Promote the type of an integer literal until it fits as C would. | |
| 1173 | /// This is for translate-c and is not intended for general use. | |
| 1174 | pub fn promoteIntLiteral( | |
| 1175 | comptime SuffixType: type, | |
| 1176 | comptime number: comptime_int, | |
| 1177 | comptime radix: CIntLiteralRadix, | |
| 1178 | ) PromoteIntLiteralReturnType(SuffixType, number, radix) { | |
| 1179 | return number; | |
| 1180 | } | |
| 1181 | ||
| 1182 | test "promoteIntLiteral" { | |
| 1183 | const signed_hex = promoteIntLiteral(c_int, math.maxInt(c_int) + 1, .hexadecimal); | |
| 1184 | try testing.expectEqual(c_uint, @TypeOf(signed_hex)); | |
| 1185 | ||
| 1186 | if (math.maxInt(c_longlong) == math.maxInt(c_int)) return; | |
| 1187 | ||
| 1188 | const signed_decimal = promoteIntLiteral(c_int, math.maxInt(c_int) + 1, .decimal); | |
| 1189 | const unsigned = promoteIntLiteral(c_uint, math.maxInt(c_uint) + 1, .hexadecimal); | |
| 1190 | ||
| 1191 | if (math.maxInt(c_long) > math.maxInt(c_int)) { | |
| 1192 | try testing.expectEqual(c_long, @TypeOf(signed_decimal)); | |
| 1193 | try testing.expectEqual(c_ulong, @TypeOf(unsigned)); | |
| 1194 | } else { | |
| 1195 | try testing.expectEqual(c_longlong, @TypeOf(signed_decimal)); | |
| 1196 | try testing.expectEqual(c_ulonglong, @TypeOf(unsigned)); | |
| 1197 | } | |
| 1198 | } | |
| 1199 | ||
| 1200 | 887 | /// For a given function type, returns a tuple type which fields will |
| 1201 | 888 | /// correspond to the argument types. |
| 1202 | 889 | /// |
| ... | ... | @@ -1316,38 +1003,6 @@ pub fn globalOption(comptime name: []const u8, comptime T: type) ?T { |
| 1316 | 1003 | return @as(T, @field(root, name)); |
| 1317 | 1004 | } |
| 1318 | 1005 | |
| 1319 | /// This function is for translate-c and is not intended for general use. | |
| 1320 | /// Convert from clang __builtin_shufflevector index to Zig @shuffle index | |
| 1321 | /// clang requires __builtin_shufflevector index arguments to be integer constants. | |
| 1322 | /// negative values for `this_index` indicate "don't care" so we arbitrarily choose 0 | |
| 1323 | /// clang enforces that `this_index` is less than the total number of vector elements | |
| 1324 | /// See https://ziglang.org/documentation/master/#shuffle | |
| 1325 | /// See https://clang.llvm.org/docs/LanguageExtensions.html#langext-builtin-shufflevector | |
| 1326 | pub fn shuffleVectorIndex(comptime this_index: c_int, comptime source_vector_len: usize) i32 { | |
| 1327 | if (this_index <= 0) return 0; | |
| 1328 | ||
| 1329 | const positive_index = @intCast(usize, this_index); | |
| 1330 | if (positive_index < source_vector_len) return @intCast(i32, this_index); | |
| 1331 | const b_index = positive_index - source_vector_len; | |
| 1332 | return ~@intCast(i32, b_index); | |
| 1333 | } | |
| 1334 | ||
| 1335 | test "shuffleVectorIndex" { | |
| 1336 | const vector_len: usize = 4; | |
| 1337 | ||
| 1338 | try testing.expect(shuffleVectorIndex(-1, vector_len) == 0); | |
| 1339 | ||
| 1340 | try testing.expect(shuffleVectorIndex(0, vector_len) == 0); | |
| 1341 | try testing.expect(shuffleVectorIndex(1, vector_len) == 1); | |
| 1342 | try testing.expect(shuffleVectorIndex(2, vector_len) == 2); | |
| 1343 | try testing.expect(shuffleVectorIndex(3, vector_len) == 3); | |
| 1344 | ||
| 1345 | try testing.expect(shuffleVectorIndex(4, vector_len) == -1); | |
| 1346 | try testing.expect(shuffleVectorIndex(5, vector_len) == -2); | |
| 1347 | try testing.expect(shuffleVectorIndex(6, vector_len) == -3); | |
| 1348 | try testing.expect(shuffleVectorIndex(7, vector_len) == -4); | |
| 1349 | } | |
| 1350 | ||
| 1351 | 1006 | /// Returns whether `error_union` contains an error. |
| 1352 | 1007 | pub fn isError(error_union: anytype) bool { |
| 1353 | 1008 | return if (error_union) |_| false else |_| true; |
| ... | ... | @@ -1357,34 +1012,3 @@ test "isError" { |
| 1357 | 1012 | try std.testing.expect(isError(math.absInt(@as(i8, -128)))); |
| 1358 | 1013 | try std.testing.expect(!isError(math.absInt(@as(i8, -127)))); |
| 1359 | 1014 | } |
| 1360 | ||
| 1361 | /// This function is for translate-c and is not intended for general use. | |
| 1362 | /// Constructs a [*c] pointer with the const and volatile annotations | |
| 1363 | /// from SelfType for pointing to a C flexible array of ElementType. | |
| 1364 | pub fn FlexibleArrayType(comptime SelfType: type, ElementType: type) type { | |
| 1365 | switch (@typeInfo(SelfType)) { | |
| 1366 | .Pointer => |ptr| { | |
| 1367 | return @Type(TypeInfo{ .Pointer = .{ | |
| 1368 | .size = .C, | |
| 1369 | .is_const = ptr.is_const, | |
| 1370 | .is_volatile = ptr.is_volatile, | |
| 1371 | .alignment = @alignOf(ElementType), | |
| 1372 | .child = ElementType, | |
| 1373 | .is_allowzero = true, | |
| 1374 | .sentinel = null, | |
| 1375 | } }); | |
| 1376 | }, | |
| 1377 | else => |info| @compileError("Invalid self type \"" ++ @tagName(info) ++ "\" for flexible array getter: " ++ @typeName(SelfType)), | |
| 1378 | } | |
| 1379 | } | |
| 1380 | ||
| 1381 | test "Flexible Array Type" { | |
| 1382 | const Container = extern struct { | |
| 1383 | size: usize, | |
| 1384 | }; | |
| 1385 | ||
| 1386 | try testing.expectEqual(FlexibleArrayType(*Container, c_int), [*c]c_int); | |
| 1387 | try testing.expectEqual(FlexibleArrayType(*const Container, c_int), [*c]const c_int); | |
| 1388 | try testing.expectEqual(FlexibleArrayType(*volatile Container, c_int), [*c]volatile c_int); | |
| 1389 | try testing.expectEqual(FlexibleArrayType(*const volatile Container, c_int), [*c]const volatile c_int); | |
| 1390 | } |
lib/std/zig.zig+4| ... | ... | @@ -16,6 +16,10 @@ pub const ast = @import("zig/ast.zig"); |
| 16 | 16 | pub const system = @import("zig/system.zig"); |
| 17 | 17 | pub const CrossTarget = @import("zig/cross_target.zig").CrossTarget; |
| 18 | 18 | |
| 19 | // Files needed by translate-c. | |
| 20 | pub const c_builtins = @import("zig/c_builtins.zig"); | |
| 21 | pub const c_translation = @import("zig/c_translation.zig"); | |
| 22 | ||
| 19 | 23 | pub const SrcHash = [16]u8; |
| 20 | 24 | |
| 21 | 25 | pub fn hashSrc(src: []const u8) SrcHash { |
lib/std/zig/c_builtins.zig created+196| ... | ... | @@ -0,0 +1,196 @@ |
| 1 | // SPDX-License-Identifier: MIT | |
| 2 | // Copyright (c) 2015-2021 Zig Contributors | |
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | |
| 4 | // The MIT license requires this copyright notice to be included in all copies | |
| 5 | // and substantial portions of the software. | |
| 6 | ||
| 7 | const std = @import("std"); | |
| 8 | ||
| 9 | pub inline fn __builtin_bswap16(val: u16) u16 { | |
| 10 | return @byteSwap(u16, val); | |
| 11 | } | |
| 12 | pub inline fn __builtin_bswap32(val: u32) u32 { | |
| 13 | return @byteSwap(u32, val); | |
| 14 | } | |
| 15 | pub inline fn __builtin_bswap64(val: u64) u64 { | |
| 16 | return @byteSwap(u64, val); | |
| 17 | } | |
| 18 | ||
| 19 | pub inline fn __builtin_signbit(val: f64) c_int { | |
| 20 | return @boolToInt(std.math.signbit(val)); | |
| 21 | } | |
| 22 | pub inline fn __builtin_signbitf(val: f32) c_int { | |
| 23 | return @boolToInt(std.math.signbit(val)); | |
| 24 | } | |
| 25 | ||
| 26 | pub inline fn __builtin_popcount(val: c_uint) c_int { | |
| 27 | // popcount of a c_uint will never exceed the capacity of a c_int | |
| 28 | @setRuntimeSafety(false); | |
| 29 | return @bitCast(c_int, @as(c_uint, @popCount(c_uint, val))); | |
| 30 | } | |
| 31 | pub inline fn __builtin_ctz(val: c_uint) c_int { | |
| 32 | // Returns the number of trailing 0-bits in val, starting at the least significant bit position. | |
| 33 | // In C if `val` is 0, the result is undefined; in zig it's the number of bits in a c_uint | |
| 34 | @setRuntimeSafety(false); | |
| 35 | return @bitCast(c_int, @as(c_uint, @ctz(c_uint, val))); | |
| 36 | } | |
| 37 | pub inline fn __builtin_clz(val: c_uint) c_int { | |
| 38 | // Returns the number of leading 0-bits in x, starting at the most significant bit position. | |
| 39 | // In C if `val` is 0, the result is undefined; in zig it's the number of bits in a c_uint | |
| 40 | @setRuntimeSafety(false); | |
| 41 | return @bitCast(c_int, @as(c_uint, @clz(c_uint, val))); | |
| 42 | } | |
| 43 | ||
| 44 | pub inline fn __builtin_sqrt(val: f64) f64 { | |
| 45 | return @sqrt(val); | |
| 46 | } | |
| 47 | pub inline fn __builtin_sqrtf(val: f32) f32 { | |
| 48 | return @sqrt(val); | |
| 49 | } | |
| 50 | ||
| 51 | pub inline fn __builtin_sin(val: f64) f64 { | |
| 52 | return @sin(val); | |
| 53 | } | |
| 54 | pub inline fn __builtin_sinf(val: f32) f32 { | |
| 55 | return @sin(val); | |
| 56 | } | |
| 57 | pub inline fn __builtin_cos(val: f64) f64 { | |
| 58 | return @cos(val); | |
| 59 | } | |
| 60 | pub inline fn __builtin_cosf(val: f32) f32 { | |
| 61 | return @cos(val); | |
| 62 | } | |
| 63 | ||
| 64 | pub inline fn __builtin_exp(val: f64) f64 { | |
| 65 | return @exp(val); | |
| 66 | } | |
| 67 | pub inline fn __builtin_expf(val: f32) f32 { | |
| 68 | return @exp(val); | |
| 69 | } | |
| 70 | pub inline fn __builtin_exp2(val: f64) f64 { | |
| 71 | return @exp2(val); | |
| 72 | } | |
| 73 | pub inline fn __builtin_exp2f(val: f32) f32 { | |
| 74 | return @exp2(val); | |
| 75 | } | |
| 76 | pub inline fn __builtin_log(val: f64) f64 { | |
| 77 | return @log(val); | |
| 78 | } | |
| 79 | pub inline fn __builtin_logf(val: f32) f32 { | |
| 80 | return @log(val); | |
| 81 | } | |
| 82 | pub inline fn __builtin_log2(val: f64) f64 { | |
| 83 | return @log2(val); | |
| 84 | } | |
| 85 | pub inline fn __builtin_log2f(val: f32) f32 { | |
| 86 | return @log2(val); | |
| 87 | } | |
| 88 | pub inline fn __builtin_log10(val: f64) f64 { | |
| 89 | return @log10(val); | |
| 90 | } | |
| 91 | pub inline fn __builtin_log10f(val: f32) f32 { | |
| 92 | return @log10(val); | |
| 93 | } | |
| 94 | ||
| 95 | // Standard C Library bug: The absolute value of the most negative integer remains negative. | |
| 96 | pub inline fn __builtin_abs(val: c_int) c_int { | |
| 97 | return std.math.absInt(val) catch std.math.minInt(c_int); | |
| 98 | } | |
| 99 | pub inline fn __builtin_fabs(val: f64) f64 { | |
| 100 | return @fabs(val); | |
| 101 | } | |
| 102 | pub inline fn __builtin_fabsf(val: f32) f32 { | |
| 103 | return @fabs(val); | |
| 104 | } | |
| 105 | ||
| 106 | pub inline fn __builtin_floor(val: f64) f64 { | |
| 107 | return @floor(val); | |
| 108 | } | |
| 109 | pub inline fn __builtin_floorf(val: f32) f32 { | |
| 110 | return @floor(val); | |
| 111 | } | |
| 112 | pub inline fn __builtin_ceil(val: f64) f64 { | |
| 113 | return @ceil(val); | |
| 114 | } | |
| 115 | pub inline fn __builtin_ceilf(val: f32) f32 { | |
| 116 | return @ceil(val); | |
| 117 | } | |
| 118 | pub inline fn __builtin_trunc(val: f64) f64 { | |
| 119 | return @trunc(val); | |
| 120 | } | |
| 121 | pub inline fn __builtin_truncf(val: f32) f32 { | |
| 122 | return @trunc(val); | |
| 123 | } | |
| 124 | pub inline fn __builtin_round(val: f64) f64 { | |
| 125 | return @round(val); | |
| 126 | } | |
| 127 | pub inline fn __builtin_roundf(val: f32) f32 { | |
| 128 | return @round(val); | |
| 129 | } | |
| 130 | ||
| 131 | pub inline fn __builtin_strlen(s: [*c]const u8) usize { | |
| 132 | return std.mem.lenZ(s); | |
| 133 | } | |
| 134 | pub inline fn __builtin_strcmp(s1: [*c]const u8, s2: [*c]const u8) c_int { | |
| 135 | return @as(c_int, std.cstr.cmp(s1, s2)); | |
| 136 | } | |
| 137 | ||
| 138 | pub inline fn __builtin_object_size(ptr: ?*const c_void, ty: c_int) usize { | |
| 139 | // clang semantics match gcc's: https://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html | |
| 140 | // If it is not possible to determine which objects ptr points to at compile time, | |
| 141 | // __builtin_object_size should return (size_t) -1 for type 0 or 1 and (size_t) 0 | |
| 142 | // for type 2 or 3. | |
| 143 | if (ty == 0 or ty == 1) return @bitCast(usize, -@as(isize, 1)); | |
| 144 | if (ty == 2 or ty == 3) return 0; | |
| 145 | unreachable; | |
| 146 | } | |
| 147 | ||
| 148 | pub inline fn __builtin___memset_chk( | |
| 149 | dst: ?*c_void, | |
| 150 | val: c_int, | |
| 151 | len: usize, | |
| 152 | remaining: usize, | |
| 153 | ) ?*c_void { | |
| 154 | if (len > remaining) @panic("std.c.builtins.memset_chk called with len > remaining"); | |
| 155 | return __builtin_memset(dst, val, len); | |
| 156 | } | |
| 157 | ||
| 158 | pub inline fn __builtin_memset(dst: ?*c_void, val: c_int, len: usize) ?*c_void { | |
| 159 | const dst_cast = @ptrCast([*c]u8, dst); | |
| 160 | @memset(dst_cast, @bitCast(u8, @truncate(i8, val)), len); | |
| 161 | return dst; | |
| 162 | } | |
| 163 | ||
| 164 | pub inline fn __builtin___memcpy_chk( | |
| 165 | noalias dst: ?*c_void, | |
| 166 | noalias src: ?*const c_void, | |
| 167 | len: usize, | |
| 168 | remaining: usize, | |
| 169 | ) ?*c_void { | |
| 170 | if (len > remaining) @panic("std.c.builtins.memcpy_chk called with len > remaining"); | |
| 171 | return __builtin_memcpy(dst, src, len); | |
| 172 | } | |
| 173 | ||
| 174 | pub inline fn __builtin_memcpy( | |
| 175 | noalias dst: ?*c_void, | |
| 176 | noalias src: ?*const c_void, | |
| 177 | len: usize, | |
| 178 | ) ?*c_void { | |
| 179 | const dst_cast = @ptrCast([*c]u8, dst); | |
| 180 | const src_cast = @ptrCast([*c]const u8, src); | |
| 181 | ||
| 182 | @memcpy(dst_cast, src_cast, len); | |
| 183 | return dst; | |
| 184 | } | |
| 185 | ||
| 186 | /// The return value of __builtin_expect is `expr`. `c` is the expected value | |
| 187 | /// of `expr` and is used as a hint to the compiler in C. Here it is unused. | |
| 188 | pub inline fn __builtin_expect(expr: c_long, c: c_long) c_long { | |
| 189 | return expr; | |
| 190 | } | |
| 191 | ||
| 192 | // __builtin_alloca_with_align is not currently implemented. | |
| 193 | // It is used in a run-translated-c test and a test-translate-c test to ensure that non-implemented | |
| 194 | // builtins are correctly demoted. If you implement __builtin_alloca_with_align, please update the | |
| 195 | // run-translated-c test and the test-translate-c test to use a different non-implemented builtin. | |
| 196 | // pub fn __builtin_alloca_with_align(size: usize, alignment: usize) callconv(.Inline) *c_void {} |
lib/std/zig/c_translation.zig created+385| ... | ... | @@ -0,0 +1,385 @@ |
| 1 | // SPDX-License-Identifier: MIT | |
| 2 | // Copyright (c) 2015-2021 Zig Contributors | |
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | |
| 4 | // The MIT license requires this copyright notice to be included in all copies | |
| 5 | // and substantial portions of the software. | |
| 6 | ||
| 7 | const std = @import("std"); | |
| 8 | const testing = std.testing; | |
| 9 | const math = std.math; | |
| 10 | const mem = std.mem; | |
| 11 | ||
| 12 | /// Given a type and value, cast the value to the type as c would. | |
| 13 | pub fn cast(comptime DestType: type, target: anytype) DestType { | |
| 14 | // this function should behave like transCCast in translate-c, except it's for macros and enums | |
| 15 | const SourceType = @TypeOf(target); | |
| 16 | switch (@typeInfo(DestType)) { | |
| 17 | .Fn, .Pointer => return castToPtr(DestType, SourceType, target), | |
| 18 | .Optional => |dest_opt| { | |
| 19 | if (@typeInfo(dest_opt.child) == .Pointer or @typeInfo(dest_opt.child) == .Fn) { | |
| 20 | return castToPtr(DestType, SourceType, target); | |
| 21 | } | |
| 22 | }, | |
| 23 | .Enum => |enum_type| { | |
| 24 | if (@typeInfo(SourceType) == .Int or @typeInfo(SourceType) == .ComptimeInt) { | |
| 25 | const intermediate = cast(enum_type.tag_type, target); | |
| 26 | return @intToEnum(DestType, intermediate); | |
| 27 | } | |
| 28 | }, | |
| 29 | .Int => { | |
| 30 | switch (@typeInfo(SourceType)) { | |
| 31 | .Pointer => { | |
| 32 | return castInt(DestType, @ptrToInt(target)); | |
| 33 | }, | |
| 34 | .Optional => |opt| { | |
| 35 | if (@typeInfo(opt.child) == .Pointer) { | |
| 36 | return castInt(DestType, @ptrToInt(target)); | |
| 37 | } | |
| 38 | }, | |
| 39 | .Enum => { | |
| 40 | return castInt(DestType, @enumToInt(target)); | |
| 41 | }, | |
| 42 | .Int => { | |
| 43 | return castInt(DestType, target); | |
| 44 | }, | |
| 45 | else => {}, | |
| 46 | } | |
| 47 | }, | |
| 48 | else => {}, | |
| 49 | } | |
| 50 | return @as(DestType, target); | |
| 51 | } | |
| 52 | ||
| 53 | fn castInt(comptime DestType: type, target: anytype) DestType { | |
| 54 | const dest = @typeInfo(DestType).Int; | |
| 55 | const source = @typeInfo(@TypeOf(target)).Int; | |
| 56 | ||
| 57 | if (dest.bits < source.bits) | |
| 58 | return @bitCast(DestType, @truncate(std.meta.Int(source.signedness, dest.bits), target)) | |
| 59 | else | |
| 60 | return @bitCast(DestType, @as(std.meta.Int(source.signedness, dest.bits), target)); | |
| 61 | } | |
| 62 | ||
| 63 | fn castPtr(comptime DestType: type, target: anytype) DestType { | |
| 64 | const dest = ptrInfo(DestType); | |
| 65 | const source = ptrInfo(@TypeOf(target)); | |
| 66 | ||
| 67 | if (source.is_const and !dest.is_const or source.is_volatile and !dest.is_volatile) | |
| 68 | return @intToPtr(DestType, @ptrToInt(target)) | |
| 69 | else if (@typeInfo(dest.child) == .Opaque) | |
| 70 | // dest.alignment would error out | |
| 71 | return @ptrCast(DestType, target) | |
| 72 | else | |
| 73 | return @ptrCast(DestType, @alignCast(dest.alignment, target)); | |
| 74 | } | |
| 75 | ||
| 76 | fn castToPtr(comptime DestType: type, comptime SourceType: type, target: anytype) DestType { | |
| 77 | switch (@typeInfo(SourceType)) { | |
| 78 | .Int => { | |
| 79 | return @intToPtr(DestType, castInt(usize, target)); | |
| 80 | }, | |
| 81 | .ComptimeInt => { | |
| 82 | if (target < 0) | |
| 83 | return @intToPtr(DestType, @bitCast(usize, @intCast(isize, target))) | |
| 84 | else | |
| 85 | return @intToPtr(DestType, @intCast(usize, target)); | |
| 86 | }, | |
| 87 | .Pointer => { | |
| 88 | return castPtr(DestType, target); | |
| 89 | }, | |
| 90 | .Optional => |target_opt| { | |
| 91 | if (@typeInfo(target_opt.child) == .Pointer) { | |
| 92 | return castPtr(DestType, target); | |
| 93 | } | |
| 94 | }, | |
| 95 | else => {}, | |
| 96 | } | |
| 97 | return @as(DestType, target); | |
| 98 | } | |
| 99 | ||
| 100 | fn ptrInfo(comptime PtrType: type) std.builtin.TypeInfo.Pointer { | |
| 101 | return switch (@typeInfo(PtrType)) { | |
| 102 | .Optional => |opt_info| @typeInfo(opt_info.child).Pointer, | |
| 103 | .Pointer => |ptr_info| ptr_info, | |
| 104 | else => unreachable, | |
| 105 | }; | |
| 106 | } | |
| 107 | ||
| 108 | test "cast" { | |
| 109 | const E = enum(u2) { | |
| 110 | Zero, | |
| 111 | One, | |
| 112 | Two, | |
| 113 | }; | |
| 114 | ||
| 115 | var i = @as(i64, 10); | |
| 116 | ||
| 117 | try testing.expect(cast(*u8, 16) == @intToPtr(*u8, 16)); | |
| 118 | try testing.expect(cast(*u64, &i).* == @as(u64, 10)); | |
| 119 | try testing.expect(cast(*i64, @as(?*align(1) i64, &i)) == &i); | |
| 120 | ||
| 121 | try testing.expect(cast(?*u8, 2) == @intToPtr(*u8, 2)); | |
| 122 | try testing.expect(cast(?*i64, @as(*align(1) i64, &i)) == &i); | |
| 123 | try testing.expect(cast(?*i64, @as(?*align(1) i64, &i)) == &i); | |
| 124 | ||
| 125 | try testing.expect(cast(E, 1) == .One); | |
| 126 | ||
| 127 | try testing.expectEqual(@as(u32, 4), cast(u32, @intToPtr(*u32, 4))); | |
| 128 | try testing.expectEqual(@as(u32, 4), cast(u32, @intToPtr(?*u32, 4))); | |
| 129 | try testing.expectEqual(@as(u32, 10), cast(u32, @as(u64, 10))); | |
| 130 | try testing.expectEqual(@as(u8, 2), cast(u8, E.Two)); | |
| 131 | ||
| 132 | try testing.expectEqual(@bitCast(i32, @as(u32, 0x8000_0000)), cast(i32, @as(u32, 0x8000_0000))); | |
| 133 | ||
| 134 | try testing.expectEqual(@intToPtr(*u8, 2), cast(*u8, @intToPtr(*const u8, 2))); | |
| 135 | try testing.expectEqual(@intToPtr(*u8, 2), cast(*u8, @intToPtr(*volatile u8, 2))); | |
| 136 | ||
| 137 | try testing.expectEqual(@intToPtr(?*c_void, 2), cast(?*c_void, @intToPtr(*u8, 2))); | |
| 138 | ||
| 139 | const C_ENUM = enum(c_int) { | |
| 140 | A = 0, | |
| 141 | B, | |
| 142 | C, | |
| 143 | _, | |
| 144 | }; | |
| 145 | try testing.expectEqual(cast(C_ENUM, @as(i64, -1)), @intToEnum(C_ENUM, -1)); | |
| 146 | try testing.expectEqual(cast(C_ENUM, @as(i8, 1)), .B); | |
| 147 | try testing.expectEqual(cast(C_ENUM, @as(u64, 1)), .B); | |
| 148 | try testing.expectEqual(cast(C_ENUM, @as(u64, 42)), @intToEnum(C_ENUM, 42)); | |
| 149 | ||
| 150 | var foo: c_int = -1; | |
| 151 | try testing.expect(cast(*c_void, -1) == @intToPtr(*c_void, @bitCast(usize, @as(isize, -1)))); | |
| 152 | try testing.expect(cast(*c_void, foo) == @intToPtr(*c_void, @bitCast(usize, @as(isize, -1)))); | |
| 153 | try testing.expect(cast(?*c_void, -1) == @intToPtr(?*c_void, @bitCast(usize, @as(isize, -1)))); | |
| 154 | try testing.expect(cast(?*c_void, foo) == @intToPtr(?*c_void, @bitCast(usize, @as(isize, -1)))); | |
| 155 | ||
| 156 | const FnPtr = ?fn (*c_void) void; | |
| 157 | try testing.expect(cast(FnPtr, 0) == @intToPtr(FnPtr, @as(usize, 0))); | |
| 158 | try testing.expect(cast(FnPtr, foo) == @intToPtr(FnPtr, @bitCast(usize, @as(isize, -1)))); | |
| 159 | } | |
| 160 | ||
| 161 | /// Given a value returns its size as C's sizeof operator would. | |
| 162 | pub fn sizeof(target: anytype) usize { | |
| 163 | const T: type = if (@TypeOf(target) == type) target else @TypeOf(target); | |
| 164 | switch (@typeInfo(T)) { | |
| 165 | .Float, .Int, .Struct, .Union, .Enum, .Array, .Bool, .Vector => return @sizeOf(T), | |
| 166 | .Fn => { | |
| 167 | // sizeof(main) returns 1, sizeof(&main) returns pointer size. | |
| 168 | // We cannot distinguish those types in Zig, so use pointer size. | |
| 169 | return @sizeOf(T); | |
| 170 | }, | |
| 171 | .Null => return @sizeOf(*c_void), | |
| 172 | .Void => { | |
| 173 | // Note: sizeof(void) is 1 on clang/gcc and 0 on MSVC. | |
| 174 | return 1; | |
| 175 | }, | |
| 176 | .Opaque => { | |
| 177 | if (T == c_void) { | |
| 178 | // Note: sizeof(void) is 1 on clang/gcc and 0 on MSVC. | |
| 179 | return 1; | |
| 180 | } else { | |
| 181 | @compileError("Cannot use C sizeof on opaque type " ++ @typeName(T)); | |
| 182 | } | |
| 183 | }, | |
| 184 | .Optional => |opt| { | |
| 185 | if (@typeInfo(opt.child) == .Pointer) { | |
| 186 | return sizeof(opt.child); | |
| 187 | } else { | |
| 188 | @compileError("Cannot use C sizeof on non-pointer optional " ++ @typeName(T)); | |
| 189 | } | |
| 190 | }, | |
| 191 | .Pointer => |ptr| { | |
| 192 | if (ptr.size == .Slice) { | |
| 193 | @compileError("Cannot use C sizeof on slice type " ++ @typeName(T)); | |
| 194 | } | |
| 195 | // for strings, sizeof("a") returns 2. | |
| 196 | // normal pointer decay scenarios from C are handled | |
| 197 | // in the .Array case above, but strings remain literals | |
| 198 | // and are therefore always pointers, so they need to be | |
| 199 | // specially handled here. | |
| 200 | if (ptr.size == .One and ptr.is_const and @typeInfo(ptr.child) == .Array) { | |
| 201 | const array_info = @typeInfo(ptr.child).Array; | |
| 202 | if ((array_info.child == u8 or array_info.child == u16) and | |
| 203 | array_info.sentinel != null and | |
| 204 | array_info.sentinel.? == 0) | |
| 205 | { | |
| 206 | // length of the string plus one for the null terminator. | |
| 207 | return (array_info.len + 1) * @sizeOf(array_info.child); | |
| 208 | } | |
| 209 | } | |
| 210 | // When zero sized pointers are removed, this case will no | |
| 211 | // longer be reachable and can be deleted. | |
| 212 | if (@sizeOf(T) == 0) { | |
| 213 | return @sizeOf(*c_void); | |
| 214 | } | |
| 215 | return @sizeOf(T); | |
| 216 | }, | |
| 217 | .ComptimeFloat => return @sizeOf(f64), // TODO c_double #3999 | |
| 218 | .ComptimeInt => { | |
| 219 | // TODO to get the correct result we have to translate | |
| 220 | // `1073741824 * 4` as `int(1073741824) *% int(4)` since | |
| 221 | // sizeof(1073741824 * 4) != sizeof(4294967296). | |
| 222 | ||
| 223 | // TODO test if target fits in int, long or long long | |
| 224 | return @sizeOf(c_int); | |
| 225 | }, | |
| 226 | else => @compileError("std.meta.sizeof does not support type " ++ @typeName(T)), | |
| 227 | } | |
| 228 | } | |
| 229 | ||
| 230 | test "sizeof" { | |
| 231 | const E = enum(c_int) { One, _ }; | |
| 232 | const S = extern struct { a: u32 }; | |
| 233 | ||
| 234 | const ptr_size = @sizeOf(*c_void); | |
| 235 | ||
| 236 | try testing.expect(sizeof(u32) == 4); | |
| 237 | try testing.expect(sizeof(@as(u32, 2)) == 4); | |
| 238 | try testing.expect(sizeof(2) == @sizeOf(c_int)); | |
| 239 | ||
| 240 | try testing.expect(sizeof(2.0) == @sizeOf(f64)); | |
| 241 | ||
| 242 | try testing.expect(sizeof(E) == @sizeOf(c_int)); | |
| 243 | try testing.expect(sizeof(E.One) == @sizeOf(c_int)); | |
| 244 | ||
| 245 | try testing.expect(sizeof(S) == 4); | |
| 246 | ||
| 247 | try testing.expect(sizeof([_]u32{ 4, 5, 6 }) == 12); | |
| 248 | try testing.expect(sizeof([3]u32) == 12); | |
| 249 | try testing.expect(sizeof([3:0]u32) == 16); | |
| 250 | try testing.expect(sizeof(&[_]u32{ 4, 5, 6 }) == ptr_size); | |
| 251 | ||
| 252 | try testing.expect(sizeof(*u32) == ptr_size); | |
| 253 | try testing.expect(sizeof([*]u32) == ptr_size); | |
| 254 | try testing.expect(sizeof([*c]u32) == ptr_size); | |
| 255 | try testing.expect(sizeof(?*u32) == ptr_size); | |
| 256 | try testing.expect(sizeof(?[*]u32) == ptr_size); | |
| 257 | try testing.expect(sizeof(*c_void) == ptr_size); | |
| 258 | try testing.expect(sizeof(*void) == ptr_size); | |
| 259 | try testing.expect(sizeof(null) == ptr_size); | |
| 260 | ||
| 261 | try testing.expect(sizeof("foobar") == 7); | |
| 262 | try testing.expect(sizeof(&[_:0]u16{ 'f', 'o', 'o', 'b', 'a', 'r' }) == 14); | |
| 263 | try testing.expect(sizeof(*const [4:0]u8) == 5); | |
| 264 | try testing.expect(sizeof(*[4:0]u8) == ptr_size); | |
| 265 | try testing.expect(sizeof([*]const [4:0]u8) == ptr_size); | |
| 266 | try testing.expect(sizeof(*const *const [4:0]u8) == ptr_size); | |
| 267 | try testing.expect(sizeof(*const [4]u8) == ptr_size); | |
| 268 | ||
| 269 | try testing.expect(sizeof(sizeof) == @sizeOf(@TypeOf(sizeof))); | |
| 270 | ||
| 271 | try testing.expect(sizeof(void) == 1); | |
| 272 | try testing.expect(sizeof(c_void) == 1); | |
| 273 | } | |
| 274 | ||
| 275 | pub const CIntLiteralRadix = enum { decimal, octal, hexadecimal }; | |
| 276 | ||
| 277 | fn PromoteIntLiteralReturnType(comptime SuffixType: type, comptime number: comptime_int, comptime radix: CIntLiteralRadix) type { | |
| 278 | const signed_decimal = [_]type{ c_int, c_long, c_longlong }; | |
| 279 | const signed_oct_hex = [_]type{ c_int, c_uint, c_long, c_ulong, c_longlong, c_ulonglong }; | |
| 280 | const unsigned = [_]type{ c_uint, c_ulong, c_ulonglong }; | |
| 281 | ||
| 282 | const list: []const type = if (@typeInfo(SuffixType).Int.signedness == .unsigned) | |
| 283 | &unsigned | |
| 284 | else if (radix == .decimal) | |
| 285 | &signed_decimal | |
| 286 | else | |
| 287 | &signed_oct_hex; | |
| 288 | ||
| 289 | var pos = mem.indexOfScalar(type, list, SuffixType).?; | |
| 290 | ||
| 291 | while (pos < list.len) : (pos += 1) { | |
| 292 | if (number >= math.minInt(list[pos]) and number <= math.maxInt(list[pos])) { | |
| 293 | return list[pos]; | |
| 294 | } | |
| 295 | } | |
| 296 | @compileError("Integer literal is too large"); | |
| 297 | } | |
| 298 | ||
| 299 | /// Promote the type of an integer literal until it fits as C would. | |
| 300 | pub fn promoteIntLiteral( | |
| 301 | comptime SuffixType: type, | |
| 302 | comptime number: comptime_int, | |
| 303 | comptime radix: CIntLiteralRadix, | |
| 304 | ) PromoteIntLiteralReturnType(SuffixType, number, radix) { | |
| 305 | return number; | |
| 306 | } | |
| 307 | ||
| 308 | test "promoteIntLiteral" { | |
| 309 | const signed_hex = promoteIntLiteral(c_int, math.maxInt(c_int) + 1, .hexadecimal); | |
| 310 | try testing.expectEqual(c_uint, @TypeOf(signed_hex)); | |
| 311 | ||
| 312 | if (math.maxInt(c_longlong) == math.maxInt(c_int)) return; | |
| 313 | ||
| 314 | const signed_decimal = promoteIntLiteral(c_int, math.maxInt(c_int) + 1, .decimal); | |
| 315 | const unsigned = promoteIntLiteral(c_uint, math.maxInt(c_uint) + 1, .hexadecimal); | |
| 316 | ||
| 317 | if (math.maxInt(c_long) > math.maxInt(c_int)) { | |
| 318 | try testing.expectEqual(c_long, @TypeOf(signed_decimal)); | |
| 319 | try testing.expectEqual(c_ulong, @TypeOf(unsigned)); | |
| 320 | } else { | |
| 321 | try testing.expectEqual(c_longlong, @TypeOf(signed_decimal)); | |
| 322 | try testing.expectEqual(c_ulonglong, @TypeOf(unsigned)); | |
| 323 | } | |
| 324 | } | |
| 325 | ||
| 326 | /// Convert from clang __builtin_shufflevector index to Zig @shuffle index | |
| 327 | /// clang requires __builtin_shufflevector index arguments to be integer constants. | |
| 328 | /// negative values for `this_index` indicate "don't care" so we arbitrarily choose 0 | |
| 329 | /// clang enforces that `this_index` is less than the total number of vector elements | |
| 330 | /// See https://ziglang.org/documentation/master/#shuffle | |
| 331 | /// See https://clang.llvm.org/docs/LanguageExtensions.html#langext-builtin-shufflevector | |
| 332 | pub fn shuffleVectorIndex(comptime this_index: c_int, comptime source_vector_len: usize) i32 { | |
| 333 | if (this_index <= 0) return 0; | |
| 334 | ||
| 335 | const positive_index = @intCast(usize, this_index); | |
| 336 | if (positive_index < source_vector_len) return @intCast(i32, this_index); | |
| 337 | const b_index = positive_index - source_vector_len; | |
| 338 | return ~@intCast(i32, b_index); | |
| 339 | } | |
| 340 | ||
| 341 | test "shuffleVectorIndex" { | |
| 342 | const vector_len: usize = 4; | |
| 343 | ||
| 344 | try testing.expect(shuffleVectorIndex(-1, vector_len) == 0); | |
| 345 | ||
| 346 | try testing.expect(shuffleVectorIndex(0, vector_len) == 0); | |
| 347 | try testing.expect(shuffleVectorIndex(1, vector_len) == 1); | |
| 348 | try testing.expect(shuffleVectorIndex(2, vector_len) == 2); | |
| 349 | try testing.expect(shuffleVectorIndex(3, vector_len) == 3); | |
| 350 | ||
| 351 | try testing.expect(shuffleVectorIndex(4, vector_len) == -1); | |
| 352 | try testing.expect(shuffleVectorIndex(5, vector_len) == -2); | |
| 353 | try testing.expect(shuffleVectorIndex(6, vector_len) == -3); | |
| 354 | try testing.expect(shuffleVectorIndex(7, vector_len) == -4); | |
| 355 | } | |
| 356 | ||
| 357 | /// Constructs a [*c] pointer with the const and volatile annotations | |
| 358 | /// from SelfType for pointing to a C flexible array of ElementType. | |
| 359 | pub fn FlexibleArrayType(comptime SelfType: type, ElementType: type) type { | |
| 360 | switch (@typeInfo(SelfType)) { | |
| 361 | .Pointer => |ptr| { | |
| 362 | return @Type(.{ .Pointer = .{ | |
| 363 | .size = .C, | |
| 364 | .is_const = ptr.is_const, | |
| 365 | .is_volatile = ptr.is_volatile, | |
| 366 | .alignment = @alignOf(ElementType), | |
| 367 | .child = ElementType, | |
| 368 | .is_allowzero = true, | |
| 369 | .sentinel = null, | |
| 370 | } }); | |
| 371 | }, | |
| 372 | else => |info| @compileError("Invalid self type \"" ++ @tagName(info) ++ "\" for flexible array getter: " ++ @typeName(SelfType)), | |
| 373 | } | |
| 374 | } | |
| 375 | ||
| 376 | test "Flexible Array Type" { | |
| 377 | const Container = extern struct { | |
| 378 | size: usize, | |
| 379 | }; | |
| 380 | ||
| 381 | try testing.expectEqual(FlexibleArrayType(*Container, c_int), [*c]c_int); | |
| 382 | try testing.expectEqual(FlexibleArrayType(*const Container, c_int), [*c]const c_int); | |
| 383 | try testing.expectEqual(FlexibleArrayType(*volatile Container, c_int), [*c]volatile c_int); | |
| 384 | try testing.expectEqual(FlexibleArrayType(*const volatile Container, c_int), [*c]const volatile c_int); | |
| 385 | } |
src/translate_c.zig+35-23| ... | ... | @@ -12,7 +12,6 @@ const meta = std.meta; |
| 12 | 12 | const ast = @import("translate_c/ast.zig"); |
| 13 | 13 | const Node = ast.Node; |
| 14 | 14 | const Tag = Node.Tag; |
| 15 | const c_builtins = std.c.builtins; | |
| 16 | 15 | |
| 17 | 16 | const CallingConvention = std.builtin.CallingConvention; |
| 18 | 17 | |
| ... | ... | @@ -863,7 +862,7 @@ fn buildFlexibleArrayFn( |
| 863 | 862 | defer block_scope.deinit(); |
| 864 | 863 | |
| 865 | 864 | const intermediate_type_name = try block_scope.makeMangledName(c, "Intermediate"); |
| 866 | const intermediate_type = try Tag.std_meta_flexible_array_type.create(c.arena, .{ .lhs = self_type, .rhs = u8_type }); | |
| 865 | const intermediate_type = try Tag.helpers_flexible_array_type.create(c.arena, .{ .lhs = self_type, .rhs = u8_type }); | |
| 867 | 866 | const intermediate_type_decl = try Tag.var_simple.create(c.arena, .{ |
| 868 | 867 | .name = intermediate_type_name, |
| 869 | 868 | .init = intermediate_type, |
| ... | ... | @@ -872,7 +871,7 @@ fn buildFlexibleArrayFn( |
| 872 | 871 | const intermediate_type_ident = try Tag.identifier.create(c.arena, intermediate_type_name); |
| 873 | 872 | |
| 874 | 873 | const return_type_name = try block_scope.makeMangledName(c, "ReturnType"); |
| 875 | const return_type = try Tag.std_meta_flexible_array_type.create(c.arena, .{ .lhs = self_type, .rhs = element_type }); | |
| 874 | const return_type = try Tag.helpers_flexible_array_type.create(c.arena, .{ .lhs = self_type, .rhs = element_type }); | |
| 876 | 875 | const return_type_decl = try Tag.var_simple.create(c.arena, .{ |
| 877 | 876 | .name = return_type_name, |
| 878 | 877 | .init = return_type, |
| ... | ... | @@ -1290,9 +1289,19 @@ fn transStmt( |
| 1290 | 1289 | return maybeSuppressResult(c, scope, result_used, shuffle_vec_node); |
| 1291 | 1290 | }, |
| 1292 | 1291 | // When adding new cases here, see comment for maybeBlockify() |
| 1293 | else => { | |
| 1294 | return fail(c, error.UnsupportedTranslation, stmt.getBeginLoc(), "TODO implement translation of stmt class {s}", .{@tagName(sc)}); | |
| 1295 | }, | |
| 1292 | .GCCAsmStmtClass, | |
| 1293 | .GotoStmtClass, | |
| 1294 | .IndirectGotoStmtClass, | |
| 1295 | .AttributedStmtClass, | |
| 1296 | .AddrLabelExprClass, | |
| 1297 | .AtomicExprClass, | |
| 1298 | .BlockExprClass, | |
| 1299 | .UserDefinedLiteralClass, | |
| 1300 | .BuiltinBitCastExprClass, | |
| 1301 | .DesignatedInitExprClass, | |
| 1302 | .LabelStmtClass, | |
| 1303 | => return fail(c, error.UnsupportedTranslation, stmt.getBeginLoc(), "TODO implement translation of stmt class {s}", .{@tagName(sc)}), | |
| 1304 | else => return fail(c, error.UnsupportedTranslation, stmt.getBeginLoc(), "unsupported stmt class {s}", .{@tagName(sc)}), | |
| 1296 | 1305 | } |
| 1297 | 1306 | } |
| 1298 | 1307 | |
| ... | ... | @@ -1374,7 +1383,7 @@ fn makeShuffleMask(c: *Context, scope: *Scope, expr: *const clang.ShuffleVectorE |
| 1374 | 1383 | |
| 1375 | 1384 | for (init_list) |*init, i| { |
| 1376 | 1385 | const index_expr = try transExprCoercing(c, scope, expr.getExpr(@intCast(c_uint, i + 2)), .used); |
| 1377 | const converted_index = try Tag.std_meta_shuffle_vector_index.create(c.arena, .{ .lhs = index_expr, .rhs = vector_len }); | |
| 1386 | const converted_index = try Tag.helpers_shuffle_vector_index.create(c.arena, .{ .lhs = index_expr, .rhs = vector_len }); | |
| 1378 | 1387 | init.* = converted_index; |
| 1379 | 1388 | } |
| 1380 | 1389 | |
| ... | ... | @@ -1820,13 +1829,10 @@ fn transDeclStmtOne( |
| 1820 | 1829 | .Function => { |
| 1821 | 1830 | try visitFnDecl(c, @ptrCast(*const clang.FunctionDecl, decl)); |
| 1822 | 1831 | }, |
| 1823 | else => |kind| return fail( | |
| 1824 | c, | |
| 1825 | error.UnsupportedTranslation, | |
| 1826 | decl.getLocation(), | |
| 1827 | "TODO implement translation of DeclStmt kind {s}", | |
| 1828 | .{@tagName(kind)}, | |
| 1829 | ), | |
| 1832 | else => { | |
| 1833 | const decl_name = try c.str(decl.getDeclKindName()); | |
| 1834 | try warn(c, &c.global_scope.base, decl.getLocation(), "ignoring {s} declaration", .{decl_name}); | |
| 1835 | }, | |
| 1830 | 1836 | } |
| 1831 | 1837 | } |
| 1832 | 1838 | |
| ... | ... | @@ -1902,7 +1908,7 @@ fn transImplicitCastExpr( |
| 1902 | 1908 | const ne = try Tag.not_equal.create(c.arena, .{ .lhs = ptr_to_int, .rhs = Tag.zero_literal.init() }); |
| 1903 | 1909 | return maybeSuppressResult(c, scope, result_used, ne); |
| 1904 | 1910 | }, |
| 1905 | .IntegralToBoolean => { | |
| 1911 | .IntegralToBoolean, .FloatingToBoolean => { | |
| 1906 | 1912 | const sub_expr_node = try transExpr(c, scope, sub_expr, .used); |
| 1907 | 1913 | |
| 1908 | 1914 | // The expression is already a boolean one, return it as-is |
| ... | ... | @@ -1924,14 +1930,14 @@ fn transImplicitCastExpr( |
| 1924 | 1930 | c, |
| 1925 | 1931 | error.UnsupportedTranslation, |
| 1926 | 1932 | @ptrCast(*const clang.Stmt, expr).getBeginLoc(), |
| 1927 | "TODO implement translation of CastKind {s}", | |
| 1933 | "unsupported CastKind {s}", | |
| 1928 | 1934 | .{@tagName(kind)}, |
| 1929 | 1935 | ), |
| 1930 | 1936 | } |
| 1931 | 1937 | } |
| 1932 | 1938 | |
| 1933 | 1939 | fn isBuiltinDefined(name: []const u8) bool { |
| 1934 | inline for (meta.declarations(c_builtins)) |decl| { | |
| 1940 | inline for (meta.declarations(std.zig.c_builtins)) |decl| { | |
| 1935 | 1941 | if (std.mem.eql(u8, name, decl.name)) return true; |
| 1936 | 1942 | } |
| 1937 | 1943 | return false; |
| ... | ... | @@ -2358,8 +2364,10 @@ fn transCCast( |
| 2358 | 2364 | return Tag.float_to_int.create(c.arena, .{ .lhs = dst_node, .rhs = expr }); |
| 2359 | 2365 | } |
| 2360 | 2366 | if (!cIsFloating(src_type) and cIsFloating(dst_type)) { |
| 2367 | var rhs = expr; | |
| 2368 | if (qualTypeIsBoolean(src_type)) rhs = try Tag.bool_to_int.create(c.arena, expr); | |
| 2361 | 2369 | // @intToFloat(dest_type, val) |
| 2362 | return Tag.int_to_float.create(c.arena, .{ .lhs = dst_node, .rhs = expr }); | |
| 2370 | return Tag.int_to_float.create(c.arena, .{ .lhs = dst_node, .rhs = rhs }); | |
| 2363 | 2371 | } |
| 2364 | 2372 | if (qualTypeIsBoolean(src_type) and !qualTypeIsBoolean(dst_type)) { |
| 2365 | 2373 | // @boolToInt returns either a comptime_int or a u1 |
| ... | ... | @@ -2370,7 +2378,7 @@ fn transCCast( |
| 2370 | 2378 | } |
| 2371 | 2379 | if (cIsEnum(dst_type)) { |
| 2372 | 2380 | // import("std").meta.cast(dest_type, val) |
| 2373 | return Tag.std_meta_cast.create(c.arena, .{ .lhs = dst_node, .rhs = expr }); | |
| 2381 | return Tag.helpers_cast.create(c.arena, .{ .lhs = dst_node, .rhs = expr }); | |
| 2374 | 2382 | } |
| 2375 | 2383 | if (cIsEnum(src_type) and !cIsEnum(dst_type)) { |
| 2376 | 2384 | // @enumToInt(val) |
| ... | ... | @@ -4547,6 +4555,10 @@ fn transType(c: *Context, scope: *Scope, ty: *const clang.Type, source_loc: clan |
| 4547 | 4555 | .rhs = try transQualType(c, scope, element_qt, source_loc), |
| 4548 | 4556 | }); |
| 4549 | 4557 | }, |
| 4558 | .ExtInt, .ExtVector => { | |
| 4559 | const type_name = c.str(ty.getTypeClassName()); | |
| 4560 | return fail(c, error.UnsupportedType, source_loc, "TODO implement translation of type: '{s}'", .{type_name}); | |
| 4561 | }, | |
| 4550 | 4562 | else => { |
| 4551 | 4563 | const type_name = c.str(ty.getTypeClassName()); |
| 4552 | 4564 | return fail(c, error.UnsupportedType, source_loc, "unsupported type: '{s}'", .{type_name}); |
| ... | ... | @@ -4982,7 +4994,7 @@ fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void { |
| 4982 | 4994 | break :blk br.data.val; |
| 4983 | 4995 | } else expr; |
| 4984 | 4996 | |
| 4985 | const return_type = if (typeof_arg.castTag(.std_meta_cast) orelse typeof_arg.castTag(.std_mem_zeroinit)) |some| | |
| 4997 | const return_type = if (typeof_arg.castTag(.helpers_cast) orelse typeof_arg.castTag(.std_mem_zeroinit)) |some| | |
| 4986 | 4998 | some.data.lhs |
| 4987 | 4999 | else if (typeof_arg.castTag(.std_mem_zeroes)) |some| |
| 4988 | 5000 | some.data |
| ... | ... | @@ -5095,7 +5107,7 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node { |
| 5095 | 5107 | if (guaranteed_to_fit) { |
| 5096 | 5108 | return Tag.as.create(c.arena, .{ .lhs = type_node, .rhs = literal_node }); |
| 5097 | 5109 | } else { |
| 5098 | return Tag.std_meta_promoteIntLiteral.create(c.arena, .{ | |
| 5110 | return Tag.helpers_promoteIntLiteral.create(c.arena, .{ | |
| 5099 | 5111 | .type = type_node, |
| 5100 | 5112 | .value = literal_node, |
| 5101 | 5113 | .radix = try Tag.enum_literal.create(c.arena, radix), |
| ... | ... | @@ -5578,7 +5590,7 @@ fn parseCCastExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 5578 | 5590 | return parseCPostfixExpr(c, m, scope, type_name); |
| 5579 | 5591 | } |
| 5580 | 5592 | const node_to_cast = try parseCCastExpr(c, m, scope); |
| 5581 | return Tag.std_meta_cast.create(c.arena, .{ .lhs = type_name, .rhs = node_to_cast }); | |
| 5593 | return Tag.helpers_cast.create(c.arena, .{ .lhs = type_name, .rhs = node_to_cast }); | |
| 5582 | 5594 | } |
| 5583 | 5595 | }, |
| 5584 | 5596 | else => {}, |
| ... | ... | @@ -5925,7 +5937,7 @@ fn parseCUnaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { |
| 5925 | 5937 | break :blk inner; |
| 5926 | 5938 | } else try parseCUnaryExpr(c, m, scope); |
| 5927 | 5939 | |
| 5928 | return Tag.std_meta_sizeof.create(c.arena, operand); | |
| 5940 | return Tag.helpers_sizeof.create(c.arena, operand); | |
| 5929 | 5941 | }, |
| 5930 | 5942 | .Keyword_alignof => { |
| 5931 | 5943 | // TODO this won't work if using <stdalign.h>'s |
src/translate_c/ast.zig+44-43| ... | ... | @@ -74,7 +74,7 @@ pub const Node = extern union { |
| 74 | 74 | tuple, |
| 75 | 75 | container_init, |
| 76 | 76 | container_init_dot, |
| 77 | std_meta_cast, | |
| 77 | helpers_cast, | |
| 78 | 78 | /// _ = operand; |
| 79 | 79 | discard, |
| 80 | 80 | |
| ... | ... | @@ -124,8 +124,8 @@ pub const Node = extern union { |
| 124 | 124 | std_math_Log2Int, |
| 125 | 125 | /// @intCast(lhs, rhs) |
| 126 | 126 | int_cast, |
| 127 | /// @import("std").meta.promoteIntLiteral(value, type, radix) | |
| 128 | std_meta_promoteIntLiteral, | |
| 127 | /// @import("std").zig.c_translation.promoteIntLiteral(value, type, radix) | |
| 128 | helpers_promoteIntLiteral, | |
| 129 | 129 | /// @import("std").meta.alignment(value) |
| 130 | 130 | std_meta_alignment, |
| 131 | 131 | /// @rem(lhs, rhs) |
| ... | ... | @@ -193,12 +193,12 @@ pub const Node = extern union { |
| 193 | 193 | array_type, |
| 194 | 194 | null_sentinel_array_type, |
| 195 | 195 | |
| 196 | /// @import("std").meta.sizeof(operand) | |
| 197 | std_meta_sizeof, | |
| 198 | /// @import("std").meta.FlexibleArrayType(lhs, rhs) | |
| 199 | std_meta_flexible_array_type, | |
| 200 | /// @import("std").meta.shuffleVectorIndex(lhs, rhs) | |
| 201 | std_meta_shuffle_vector_index, | |
| 196 | /// @import("std").zig.c_translation.sizeof(operand) | |
| 197 | helpers_sizeof, | |
| 198 | /// @import("std").zig.c_translation.FlexibleArrayType(lhs, rhs) | |
| 199 | helpers_flexible_array_type, | |
| 200 | /// @import("std").zig.c_translation.shuffleVectorIndex(lhs, rhs) | |
| 201 | helpers_shuffle_vector_index, | |
| 202 | 202 | /// @import("std").meta.Vector(lhs, rhs) |
| 203 | 203 | std_meta_vector, |
| 204 | 204 | /// @import("std").mem.zeroes(operand) |
| ... | ... | @@ -272,7 +272,7 @@ pub const Node = extern union { |
| 272 | 272 | .if_not_break, |
| 273 | 273 | .switch_else, |
| 274 | 274 | .block_single, |
| 275 | .std_meta_sizeof, | |
| 275 | .helpers_sizeof, | |
| 276 | 276 | .std_meta_alignment, |
| 277 | 277 | .bool_to_int, |
| 278 | 278 | .sizeof, |
| ... | ... | @@ -332,13 +332,13 @@ pub const Node = extern union { |
| 332 | 332 | .align_cast, |
| 333 | 333 | .array_access, |
| 334 | 334 | .std_mem_zeroinit, |
| 335 | .std_meta_flexible_array_type, | |
| 336 | .std_meta_shuffle_vector_index, | |
| 335 | .helpers_flexible_array_type, | |
| 336 | .helpers_shuffle_vector_index, | |
| 337 | 337 | .std_meta_vector, |
| 338 | 338 | .ptr_cast, |
| 339 | 339 | .div_exact, |
| 340 | 340 | .offset_of, |
| 341 | .std_meta_cast, | |
| 341 | .helpers_cast, | |
| 342 | 342 | => Payload.BinOp, |
| 343 | 343 | |
| 344 | 344 | .integer_literal, |
| ... | ... | @@ -362,7 +362,7 @@ pub const Node = extern union { |
| 362 | 362 | .tuple => Payload.TupleInit, |
| 363 | 363 | .container_init => Payload.ContainerInit, |
| 364 | 364 | .container_init_dot => Payload.ContainerInitDot, |
| 365 | .std_meta_promoteIntLiteral => Payload.PromoteIntLiteral, | |
| 365 | .helpers_promoteIntLiteral => Payload.PromoteIntLiteral, | |
| 366 | 366 | .block => Payload.Block, |
| 367 | 367 | .c_pointer, .single_pointer => Payload.Pointer, |
| 368 | 368 | .array_type, .null_sentinel_array_type => Payload.Array, |
| ... | ... | @@ -868,7 +868,7 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 868 | 868 | // pub usingnamespace @import("std").c.builtins; |
| 869 | 869 | _ = try c.addToken(.keyword_pub, "pub"); |
| 870 | 870 | const usingnamespace_token = try c.addToken(.keyword_usingnamespace, "usingnamespace"); |
| 871 | const import_node = try renderStdImport(c, "c", "builtins"); | |
| 871 | const import_node = try renderStdImport(c, &.{ "zig", "c_builtins" }); | |
| 872 | 872 | _ = try c.addToken(.semicolon, ";"); |
| 873 | 873 | |
| 874 | 874 | return c.addNode(.{ |
| ... | ... | @@ -882,52 +882,52 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { |
| 882 | 882 | }, |
| 883 | 883 | .std_math_Log2Int => { |
| 884 | 884 | const payload = node.castTag(.std_math_Log2Int).?.data; |
| 885 | const import_node = try renderStdImport(c, "math", "Log2Int"); | |
| 885 | const import_node = try renderStdImport(c, &.{ "math", "Log2Int" }); | |
| 886 | 886 | return renderCall(c, import_node, &.{payload}); |
| 887 | 887 | }, |
| 888 | .std_meta_cast => { | |
| 889 | const payload = node.castTag(.std_meta_cast).?.data; | |
| 890 | const import_node = try renderStdImport(c, "meta", "cast"); | |
| 888 | .helpers_cast => { | |
| 889 | const payload = node.castTag(.helpers_cast).?.data; | |
| 890 | const import_node = try renderStdImport(c, &.{ "zig", "c_translation", "cast" }); | |
| 891 | 891 | return renderCall(c, import_node, &.{ payload.lhs, payload.rhs }); |
| 892 | 892 | }, |
| 893 | .std_meta_promoteIntLiteral => { | |
| 894 | const payload = node.castTag(.std_meta_promoteIntLiteral).?.data; | |
| 895 | const import_node = try renderStdImport(c, "meta", "promoteIntLiteral"); | |
| 893 | .helpers_promoteIntLiteral => { | |
| 894 | const payload = node.castTag(.helpers_promoteIntLiteral).?.data; | |
| 895 | const import_node = try renderStdImport(c, &.{ "zig", "c_translation", "promoteIntLiteral" }); | |
| 896 | 896 | return renderCall(c, import_node, &.{ payload.type, payload.value, payload.radix }); |
| 897 | 897 | }, |
| 898 | 898 | .std_meta_alignment => { |
| 899 | 899 | const payload = node.castTag(.std_meta_alignment).?.data; |
| 900 | const import_node = try renderStdImport(c, "meta", "alignment"); | |
| 900 | const import_node = try renderStdImport(c, &.{ "meta", "alignment" }); | |
| 901 | 901 | return renderCall(c, import_node, &.{payload}); |
| 902 | 902 | }, |
| 903 | .std_meta_sizeof => { | |
| 904 | const payload = node.castTag(.std_meta_sizeof).?.data; | |
| 905 | const import_node = try renderStdImport(c, "meta", "sizeof"); | |
| 903 | .helpers_sizeof => { | |
| 904 | const payload = node.castTag(.helpers_sizeof).?.data; | |
| 905 | const import_node = try renderStdImport(c, &.{ "zig", "c_translation", "sizeof" }); | |
| 906 | 906 | return renderCall(c, import_node, &.{payload}); |
| 907 | 907 | }, |
| 908 | 908 | .std_mem_zeroes => { |
| 909 | 909 | const payload = node.castTag(.std_mem_zeroes).?.data; |
| 910 | const import_node = try renderStdImport(c, "mem", "zeroes"); | |
| 910 | const import_node = try renderStdImport(c, &.{ "mem", "zeroes" }); | |
| 911 | 911 | return renderCall(c, import_node, &.{payload}); |
| 912 | 912 | }, |
| 913 | 913 | .std_mem_zeroinit => { |
| 914 | 914 | const payload = node.castTag(.std_mem_zeroinit).?.data; |
| 915 | const import_node = try renderStdImport(c, "mem", "zeroInit"); | |
| 915 | const import_node = try renderStdImport(c, &.{ "mem", "zeroInit" }); | |
| 916 | 916 | return renderCall(c, import_node, &.{ payload.lhs, payload.rhs }); |
| 917 | 917 | }, |
| 918 | .std_meta_flexible_array_type => { | |
| 919 | const payload = node.castTag(.std_meta_flexible_array_type).?.data; | |
| 920 | const import_node = try renderStdImport(c, "meta", "FlexibleArrayType"); | |
| 918 | .helpers_flexible_array_type => { | |
| 919 | const payload = node.castTag(.helpers_flexible_array_type).?.data; | |
| 920 | const import_node = try renderStdImport(c, &.{ "zig", "c_translation", "FlexibleArrayType" }); | |
| 921 | 921 | return renderCall(c, import_node, &.{ payload.lhs, payload.rhs }); |
| 922 | 922 | }, |
| 923 | .std_meta_shuffle_vector_index => { | |
| 924 | const payload = node.castTag(.std_meta_shuffle_vector_index).?.data; | |
| 925 | const import_node = try renderStdImport(c, "meta", "shuffleVectorIndex"); | |
| 923 | .helpers_shuffle_vector_index => { | |
| 924 | const payload = node.castTag(.helpers_shuffle_vector_index).?.data; | |
| 925 | const import_node = try renderStdImport(c, &.{ "zig", "c_translation", "shuffleVectorIndex" }); | |
| 926 | 926 | return renderCall(c, import_node, &.{ payload.lhs, payload.rhs }); |
| 927 | 927 | }, |
| 928 | 928 | .std_meta_vector => { |
| 929 | 929 | const payload = node.castTag(.std_meta_vector).?.data; |
| 930 | const import_node = try renderStdImport(c, "meta", "Vector"); | |
| 930 | const import_node = try renderStdImport(c, &.{ "meta", "Vector" }); | |
| 931 | 931 | return renderCall(c, import_node, &.{ payload.lhs, payload.rhs }); |
| 932 | 932 | }, |
| 933 | 933 | .call => { |
| ... | ... | @@ -2269,13 +2269,13 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex { |
| 2269 | 2269 | .alignof, |
| 2270 | 2270 | .typeof, |
| 2271 | 2271 | .typeinfo, |
| 2272 | .std_meta_sizeof, | |
| 2273 | 2272 | .std_meta_alignment, |
| 2274 | .std_meta_cast, | |
| 2275 | .std_meta_promoteIntLiteral, | |
| 2276 | 2273 | .std_meta_vector, |
| 2277 | .std_meta_shuffle_vector_index, | |
| 2278 | .std_meta_flexible_array_type, | |
| 2274 | .helpers_sizeof, | |
| 2275 | .helpers_cast, | |
| 2276 | .helpers_promoteIntLiteral, | |
| 2277 | .helpers_shuffle_vector_index, | |
| 2278 | .helpers_flexible_array_type, | |
| 2279 | 2279 | .std_mem_zeroinit, |
| 2280 | 2280 | .integer_literal, |
| 2281 | 2281 | .float_literal, |
| ... | ... | @@ -2442,7 +2442,7 @@ fn renderBinOp(c: *Context, node: Node, tag: std.zig.ast.Node.Tag, tok_tag: Toke |
| 2442 | 2442 | }); |
| 2443 | 2443 | } |
| 2444 | 2444 | |
| 2445 | fn renderStdImport(c: *Context, first: []const u8, second: []const u8) !NodeIndex { | |
| 2445 | fn renderStdImport(c: *Context, parts: []const []const u8) !NodeIndex { | |
| 2446 | 2446 | const import_tok = try c.addToken(.builtin, "@import"); |
| 2447 | 2447 | _ = try c.addToken(.l_paren, "("); |
| 2448 | 2448 | const std_tok = try c.addToken(.string_literal, "\"std\""); |
| ... | ... | @@ -2463,8 +2463,9 @@ fn renderStdImport(c: *Context, first: []const u8, second: []const u8) !NodeInde |
| 2463 | 2463 | }); |
| 2464 | 2464 | |
| 2465 | 2465 | var access_chain = import_node; |
| 2466 | access_chain = try renderFieldAccess(c, access_chain, first); | |
| 2467 | access_chain = try renderFieldAccess(c, access_chain, second); | |
| 2466 | for (parts) |part| { | |
| 2467 | access_chain = try renderFieldAccess(c, access_chain, part); | |
| 2468 | } | |
| 2468 | 2469 | return access_chain; |
| 2469 | 2470 | } |
| 2470 | 2471 |
test/translate_c.zig+33-33| ... | ... | @@ -133,7 +133,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 133 | 133 | \\ const A = @enumToInt(enum_Foo.A); |
| 134 | 134 | \\ const B = @enumToInt(enum_Foo.B); |
| 135 | 135 | \\ const C = @enumToInt(enum_Foo.C); |
| 136 | \\ var a: enum_Foo = @import("std").meta.cast(enum_Foo, B); | |
| 136 | \\ var a: enum_Foo = @import("std").zig.c_translation.cast(enum_Foo, B); | |
| 137 | 137 | \\ { |
| 138 | 138 | \\ const enum_Foo = extern enum( |
| 139 | 139 | ++ default_enum_type ++ |
| ... | ... | @@ -146,7 +146,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 146 | 146 | \\ const A_2 = @enumToInt(enum_Foo.A); |
| 147 | 147 | \\ const B_3 = @enumToInt(enum_Foo.B); |
| 148 | 148 | \\ const C_4 = @enumToInt(enum_Foo.C); |
| 149 | \\ var a_5: enum_Foo = @import("std").meta.cast(enum_Foo, B_3); | |
| 149 | \\ var a_5: enum_Foo = @import("std").zig.c_translation.cast(enum_Foo, B_3); | |
| 150 | 150 | \\ } |
| 151 | 151 | \\} |
| 152 | 152 | }); |
| ... | ... | @@ -242,7 +242,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 242 | 242 | \\#define MEM_PHYSICAL_TO_K0(x) (void*)((uint32_t)(x) + SYS_BASE_CACHED) |
| 243 | 243 | , &[_][]const u8{ |
| 244 | 244 | \\pub inline fn MEM_PHYSICAL_TO_K0(x: anytype) ?*c_void { |
| 245 | \\ return @import("std").meta.cast(?*c_void, @import("std").meta.cast(u32, x) + SYS_BASE_CACHED); | |
| 245 | \\ return @import("std").zig.c_translation.cast(?*c_void, @import("std").zig.c_translation.cast(u32, x) + SYS_BASE_CACHED); | |
| 246 | 246 | \\} |
| 247 | 247 | }); |
| 248 | 248 | |
| ... | ... | @@ -282,8 +282,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 282 | 282 | , |
| 283 | 283 | \\pub const VALUE = ((((@as(c_int, 1) + (@as(c_int, 2) * @as(c_int, 3))) + (@as(c_int, 4) * @as(c_int, 5))) + @as(c_int, 6)) << @as(c_int, 7)) | @boolToInt(@as(c_int, 8) == @as(c_int, 9)); |
| 284 | 284 | , |
| 285 | \\pub inline fn _AL_READ3BYTES(p: anytype) @TypeOf((@import("std").meta.cast([*c]u8, p).* | ((@import("std").meta.cast([*c]u8, p) + @as(c_int, 1)).* << @as(c_int, 8))) | ((@import("std").meta.cast([*c]u8, p) + @as(c_int, 2)).* << @as(c_int, 16))) { | |
| 286 | \\ return (@import("std").meta.cast([*c]u8, p).* | ((@import("std").meta.cast([*c]u8, p) + @as(c_int, 1)).* << @as(c_int, 8))) | ((@import("std").meta.cast([*c]u8, p) + @as(c_int, 2)).* << @as(c_int, 16)); | |
| 285 | \\pub inline fn _AL_READ3BYTES(p: anytype) @TypeOf((@import("std").zig.c_translation.cast([*c]u8, p).* | ((@import("std").zig.c_translation.cast([*c]u8, p) + @as(c_int, 1)).* << @as(c_int, 8))) | ((@import("std").zig.c_translation.cast([*c]u8, p) + @as(c_int, 2)).* << @as(c_int, 16))) { | |
| 286 | \\ return (@import("std").zig.c_translation.cast([*c]u8, p).* | ((@import("std").zig.c_translation.cast([*c]u8, p) + @as(c_int, 1)).* << @as(c_int, 8))) | ((@import("std").zig.c_translation.cast([*c]u8, p) + @as(c_int, 2)).* << @as(c_int, 16)); | |
| 287 | 287 | \\} |
| 288 | 288 | }); |
| 289 | 289 | |
| ... | ... | @@ -438,17 +438,17 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 438 | 438 | , &[_][]const u8{ |
| 439 | 439 | \\pub const struct_foo = extern struct { |
| 440 | 440 | \\ x: c_int align(4), |
| 441 | \\ pub fn y(self: anytype) @import("std").meta.FlexibleArrayType(@TypeOf(self), c_int) { | |
| 442 | \\ const Intermediate = @import("std").meta.FlexibleArrayType(@TypeOf(self), u8); | |
| 443 | \\ const ReturnType = @import("std").meta.FlexibleArrayType(@TypeOf(self), c_int); | |
| 441 | \\ pub fn y(self: anytype) @import("std").zig.c_translation.FlexibleArrayType(@TypeOf(self), c_int) { | |
| 442 | \\ const Intermediate = @import("std").zig.c_translation.FlexibleArrayType(@TypeOf(self), u8); | |
| 443 | \\ const ReturnType = @import("std").zig.c_translation.FlexibleArrayType(@TypeOf(self), c_int); | |
| 444 | 444 | \\ return @ptrCast(ReturnType, @alignCast(@alignOf(c_int), @ptrCast(Intermediate, self) + 4)); |
| 445 | 445 | \\ } |
| 446 | 446 | \\}; |
| 447 | 447 | \\pub const struct_bar = extern struct { |
| 448 | 448 | \\ x: c_int align(4), |
| 449 | \\ pub fn y(self: anytype) @import("std").meta.FlexibleArrayType(@TypeOf(self), c_int) { | |
| 450 | \\ const Intermediate = @import("std").meta.FlexibleArrayType(@TypeOf(self), u8); | |
| 451 | \\ const ReturnType = @import("std").meta.FlexibleArrayType(@TypeOf(self), c_int); | |
| 449 | \\ pub fn y(self: anytype) @import("std").zig.c_translation.FlexibleArrayType(@TypeOf(self), c_int) { | |
| 450 | \\ const Intermediate = @import("std").zig.c_translation.FlexibleArrayType(@TypeOf(self), u8); | |
| 451 | \\ const ReturnType = @import("std").zig.c_translation.FlexibleArrayType(@TypeOf(self), c_int); | |
| 452 | 452 | \\ return @ptrCast(ReturnType, @alignCast(@alignOf(c_int), @ptrCast(Intermediate, self) + 4)); |
| 453 | 453 | \\ } |
| 454 | 454 | \\}; |
| ... | ... | @@ -583,7 +583,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 583 | 583 | cases.add("#define hex literal with capital X", |
| 584 | 584 | \\#define VAL 0XF00D |
| 585 | 585 | , &[_][]const u8{ |
| 586 | \\pub const VAL = @import("std").meta.promoteIntLiteral(c_int, 0xF00D, .hexadecimal); | |
| 586 | \\pub const VAL = @import("std").zig.c_translation.promoteIntLiteral(c_int, 0xF00D, .hexadecimal); | |
| 587 | 587 | }); |
| 588 | 588 | |
| 589 | 589 | cases.add("anonymous struct & unions", |
| ... | ... | @@ -1738,7 +1738,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1738 | 1738 | \\pub const e = @enumToInt(enum_unnamed_1.e); |
| 1739 | 1739 | \\pub const f = @enumToInt(enum_unnamed_1.f); |
| 1740 | 1740 | \\pub const g = @enumToInt(enum_unnamed_1.g); |
| 1741 | \\pub export var h: enum_unnamed_1 = @import("std").meta.cast(enum_unnamed_1, e); | |
| 1741 | \\pub export var h: enum_unnamed_1 = @import("std").zig.c_translation.cast(enum_unnamed_1, e); | |
| 1742 | 1742 | \\const enum_unnamed_2 = extern enum( |
| 1743 | 1743 | ++ default_enum_type ++ |
| 1744 | 1744 | \\) { |
| ... | ... | @@ -1882,7 +1882,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1882 | 1882 | \\typedef struct { int dummy; } NRF_GPIO_Type; |
| 1883 | 1883 | \\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE) |
| 1884 | 1884 | , &[_][]const u8{ |
| 1885 | \\pub const NRF_GPIO = @import("std").meta.cast([*c]NRF_GPIO_Type, NRF_GPIO_BASE); | |
| 1885 | \\pub const NRF_GPIO = @import("std").zig.c_translation.cast([*c]NRF_GPIO_Type, NRF_GPIO_BASE); | |
| 1886 | 1886 | }); |
| 1887 | 1887 | |
| 1888 | 1888 | cases.add("basic macro function", |
| ... | ... | @@ -2379,7 +2379,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 2379 | 2379 | \\ var a = arg_a; |
| 2380 | 2380 | \\ var b = arg_b; |
| 2381 | 2381 | \\ var c = arg_c; |
| 2382 | \\ var d: enum_Foo = @import("std").meta.cast(enum_Foo, FooA); | |
| 2382 | \\ var d: enum_Foo = @import("std").zig.c_translation.cast(enum_Foo, FooA); | |
| 2383 | 2383 | \\ var e: c_int = @boolToInt((a != 0) and (b != 0)); |
| 2384 | 2384 | \\ var f: c_int = @boolToInt((b != 0) and (c != null)); |
| 2385 | 2385 | \\ var g: c_int = @boolToInt((a != 0) and (c != null)); |
| ... | ... | @@ -3182,13 +3182,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 3182 | 3182 | \\#define BAR (void*) a |
| 3183 | 3183 | \\#define BAZ (uint32_t)(2) |
| 3184 | 3184 | , &[_][]const u8{ |
| 3185 | \\pub inline fn FOO(bar: anytype) @TypeOf(baz(@import("std").meta.cast(?*c_void, baz))) { | |
| 3186 | \\ return baz(@import("std").meta.cast(?*c_void, baz)); | |
| 3185 | \\pub inline fn FOO(bar: anytype) @TypeOf(baz(@import("std").zig.c_translation.cast(?*c_void, baz))) { | |
| 3186 | \\ return baz(@import("std").zig.c_translation.cast(?*c_void, baz)); | |
| 3187 | 3187 | \\} |
| 3188 | 3188 | , |
| 3189 | \\pub const BAR = @import("std").meta.cast(?*c_void, a); | |
| 3189 | \\pub const BAR = @import("std").zig.c_translation.cast(?*c_void, a); | |
| 3190 | 3190 | , |
| 3191 | \\pub const BAZ = @import("std").meta.cast(u32, @as(c_int, 2)); | |
| 3191 | \\pub const BAZ = @import("std").zig.c_translation.cast(u32, @as(c_int, 2)); | |
| 3192 | 3192 | }); |
| 3193 | 3193 | |
| 3194 | 3194 | cases.add("macro with cast to unsigned short, long, and long long", |
| ... | ... | @@ -3196,9 +3196,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 3196 | 3196 | \\#define CURLAUTH_BASIC ((unsigned long) 1) |
| 3197 | 3197 | \\#define CURLAUTH_BASIC_BUT_ULONGLONG ((unsigned long long) 1) |
| 3198 | 3198 | , &[_][]const u8{ |
| 3199 | \\pub const CURLAUTH_BASIC_BUT_USHORT = @import("std").meta.cast(c_ushort, @as(c_int, 1)); | |
| 3200 | \\pub const CURLAUTH_BASIC = @import("std").meta.cast(c_ulong, @as(c_int, 1)); | |
| 3201 | \\pub const CURLAUTH_BASIC_BUT_ULONGLONG = @import("std").meta.cast(c_ulonglong, @as(c_int, 1)); | |
| 3199 | \\pub const CURLAUTH_BASIC_BUT_USHORT = @import("std").zig.c_translation.cast(c_ushort, @as(c_int, 1)); | |
| 3200 | \\pub const CURLAUTH_BASIC = @import("std").zig.c_translation.cast(c_ulong, @as(c_int, 1)); | |
| 3201 | \\pub const CURLAUTH_BASIC_BUT_ULONGLONG = @import("std").zig.c_translation.cast(c_ulonglong, @as(c_int, 1)); | |
| 3202 | 3202 | }); |
| 3203 | 3203 | |
| 3204 | 3204 | cases.add("macro conditional operator", |
| ... | ... | @@ -3413,8 +3413,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 3413 | 3413 | \\#define DefaultScreen(dpy) (((_XPrivDisplay)(dpy))->default_screen) |
| 3414 | 3414 | \\ |
| 3415 | 3415 | , &[_][]const u8{ |
| 3416 | \\pub inline fn DefaultScreen(dpy: anytype) @TypeOf(@import("std").meta.cast(_XPrivDisplay, dpy).*.default_screen) { | |
| 3417 | \\ return @import("std").meta.cast(_XPrivDisplay, dpy).*.default_screen; | |
| 3416 | \\pub inline fn DefaultScreen(dpy: anytype) @TypeOf(@import("std").zig.c_translation.cast(_XPrivDisplay, dpy).*.default_screen) { | |
| 3417 | \\ return @import("std").zig.c_translation.cast(_XPrivDisplay, dpy).*.default_screen; | |
| 3418 | 3418 | \\} |
| 3419 | 3419 | }); |
| 3420 | 3420 | |
| ... | ... | @@ -3422,9 +3422,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 3422 | 3422 | \\#define NULL ((void*)0) |
| 3423 | 3423 | \\#define FOO ((int)0x8000) |
| 3424 | 3424 | , &[_][]const u8{ |
| 3425 | \\pub const NULL = @import("std").meta.cast(?*c_void, @as(c_int, 0)); | |
| 3425 | \\pub const NULL = @import("std").zig.c_translation.cast(?*c_void, @as(c_int, 0)); | |
| 3426 | 3426 | , |
| 3427 | \\pub const FOO = @import("std").meta.cast(c_int, @import("std").meta.promoteIntLiteral(c_int, 0x8000, .hexadecimal)); | |
| 3427 | \\pub const FOO = @import("std").zig.c_translation.cast(c_int, @import("std").zig.c_translation.promoteIntLiteral(c_int, 0x8000, .hexadecimal)); | |
| 3428 | 3428 | }); |
| 3429 | 3429 | |
| 3430 | 3430 | if (std.Target.current.abi == .msvc) { |
| ... | ... | @@ -3503,11 +3503,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 3503 | 3503 | \\pub const GUARANTEED_TO_FIT_1 = @as(c_int, 1024); |
| 3504 | 3504 | \\pub const GUARANTEED_TO_FIT_2 = @as(c_long, 10241024); |
| 3505 | 3505 | \\pub const GUARANTEED_TO_FIT_3 = @as(c_ulong, 20482048); |
| 3506 | \\pub const MAY_NEED_PROMOTION_1 = @import("std").meta.promoteIntLiteral(c_int, 10241024, .decimal); | |
| 3507 | \\pub const MAY_NEED_PROMOTION_2 = @import("std").meta.promoteIntLiteral(c_long, 307230723072, .decimal); | |
| 3508 | \\pub const MAY_NEED_PROMOTION_3 = @import("std").meta.promoteIntLiteral(c_ulong, 819281928192, .decimal); | |
| 3509 | \\pub const MAY_NEED_PROMOTION_HEX = @import("std").meta.promoteIntLiteral(c_int, 0x80000000, .hexadecimal); | |
| 3510 | \\pub const MAY_NEED_PROMOTION_OCT = @import("std").meta.promoteIntLiteral(c_int, 0o20000000000, .octal); | |
| 3506 | \\pub const MAY_NEED_PROMOTION_1 = @import("std").zig.c_translation.promoteIntLiteral(c_int, 10241024, .decimal); | |
| 3507 | \\pub const MAY_NEED_PROMOTION_2 = @import("std").zig.c_translation.promoteIntLiteral(c_long, 307230723072, .decimal); | |
| 3508 | \\pub const MAY_NEED_PROMOTION_3 = @import("std").zig.c_translation.promoteIntLiteral(c_ulong, 819281928192, .decimal); | |
| 3509 | \\pub const MAY_NEED_PROMOTION_HEX = @import("std").zig.c_translation.promoteIntLiteral(c_int, 0x80000000, .hexadecimal); | |
| 3510 | \\pub const MAY_NEED_PROMOTION_OCT = @import("std").zig.c_translation.promoteIntLiteral(c_int, 0o20000000000, .octal); | |
| 3511 | 3511 | }); |
| 3512 | 3512 | |
| 3513 | 3513 | // See __builtin_alloca_with_align comment in std.c.builtins |
| ... | ... | @@ -3642,7 +3642,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 3642 | 3642 | \\typedef long long LONG_PTR; |
| 3643 | 3643 | \\#define INVALID_HANDLE_VALUE ((void *)(LONG_PTR)-1) |
| 3644 | 3644 | , &[_][]const u8{ |
| 3645 | \\pub const MAP_FAILED = @import("std").meta.cast(?*c_void, -@as(c_int, 1)); | |
| 3646 | \\pub const INVALID_HANDLE_VALUE = @import("std").meta.cast(?*c_void, @import("std").meta.cast(LONG_PTR, -@as(c_int, 1))); | |
| 3645 | \\pub const MAP_FAILED = @import("std").zig.c_translation.cast(?*c_void, -@as(c_int, 1)); | |
| 3646 | \\pub const INVALID_HANDLE_VALUE = @import("std").zig.c_translation.cast(?*c_void, @import("std").zig.c_translation.cast(LONG_PTR, -@as(c_int, 1))); | |
| 3647 | 3647 | }); |
| 3648 | 3648 | } |