@zigc/lib 0.16.0-test.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +19 -0
- package/c/math.zig +135 -35
- package/c/stropts.zig +17 -0
- package/c.zig +1 -0
- package/compiler/aro/aro/Attribute/names.zig +604 -589
- package/compiler/aro/aro/Attribute.zig +202 -116
- package/compiler/aro/aro/Builtins/common.zig +874 -863
- package/compiler/aro/aro/Builtins/eval.zig +15 -7
- package/compiler/aro/aro/Builtins.zig +0 -1
- package/compiler/aro/aro/CodeGen.zig +3 -1
- package/compiler/aro/aro/Compilation.zig +120 -97
- package/compiler/aro/aro/Diagnostics.zig +21 -17
- package/compiler/aro/aro/Driver/GCCDetector.zig +635 -0
- package/compiler/aro/aro/Driver.zig +124 -50
- package/compiler/aro/aro/LangOpts.zig +12 -2
- package/compiler/aro/aro/Parser/Diagnostic.zig +79 -19
- package/compiler/aro/aro/Parser.zig +336 -142
- package/compiler/aro/aro/Preprocessor/Diagnostic.zig +21 -0
- package/compiler/aro/aro/Preprocessor.zig +127 -56
- package/compiler/aro/aro/Target.zig +17 -12
- package/compiler/aro/aro/Tokenizer.zig +31 -14
- package/compiler/aro/aro/Toolchain.zig +4 -7
- package/compiler/aro/aro/Tree.zig +178 -148
- package/compiler/aro/aro/TypeStore.zig +82 -24
- package/compiler/aro/aro/Value.zig +13 -17
- package/compiler/aro/aro/features.zig +1 -0
- package/compiler/aro/aro/pragmas/once.zig +0 -1
- package/compiler/aro/aro/record_layout.zig +3 -3
- package/compiler/aro/assembly_backend/x86_64.zig +3 -4
- package/compiler/aro/backend/Assembly.zig +1 -2
- package/compiler/aro/backend/Interner.zig +2 -2
- package/compiler/aro/backend/Ir.zig +100 -92
- package/compiler/aro/include/ptrcheck.h +49 -0
- package/compiler/aro/main.zig +26 -10
- package/compiler/build_runner.zig +1 -0
- package/compiler/objdump.zig +93 -0
- package/compiler/reduce.zig +5 -1
- package/compiler/resinator/compile.zig +2 -2
- package/compiler/resinator/main.zig +7 -1
- package/compiler/resinator/preprocess.zig +1 -3
- package/compiler/std-docs.zig +8 -1
- package/compiler/test_runner.zig +193 -61
- package/compiler/translate-c/MacroTranslator.zig +80 -11
- package/compiler/translate-c/PatternList.zig +1 -9
- package/compiler/translate-c/Scope.zig +43 -6
- package/compiler/translate-c/Translator.zig +364 -126
- package/compiler/translate-c/ast.zig +19 -11
- package/compiler/translate-c/main.zig +75 -16
- package/compiler_rt/cos.zig +141 -52
- package/compiler_rt/limb64.zig +266 -0
- package/compiler_rt/long_double.zig +37 -0
- package/compiler_rt/mulo.zig +6 -1
- package/compiler_rt/rem_pio2l.zig +173 -0
- package/compiler_rt/sin.zig +140 -55
- package/compiler_rt/sincos.zig +279 -72
- package/compiler_rt/tan.zig +118 -47
- package/compiler_rt/trig.zig +256 -6
- package/compiler_rt.zig +2 -0
- package/fuzzer.zig +855 -307
- package/libc/musl/src/math/pow.c +343 -0
- package/package.json +1 -1
- package/std/Build/Fuzz.zig +6 -19
- package/std/Build/Module.zig +1 -1
- package/std/Build/Step/CheckObject.zig +3 -3
- package/std/Build/Step/Compile.zig +18 -0
- package/std/Build/Step/ConfigHeader.zig +49 -33
- package/std/Build/Step/InstallArtifact.zig +18 -0
- package/std/Build/Step/Run.zig +536 -87
- package/std/Build/Step/TranslateC.zig +0 -6
- package/std/Build/Step.zig +8 -15
- package/std/Build/WebServer.zig +29 -17
- package/std/Build/abi.zig +47 -11
- package/std/Build.zig +17 -14
- package/std/Io/Dispatch.zig +2 -0
- package/std/Io/File/Reader.zig +3 -1
- package/std/Io/File.zig +1 -0
- package/std/Io/Kqueue.zig +2 -2
- package/std/Io/Threaded.zig +181 -143
- package/std/Io/Uring.zig +2 -1
- package/std/Io.zig +970 -2
- package/std/Target.zig +3 -2
- package/std/Thread.zig +8 -3
- package/std/array_hash_map.zig +96 -555
- package/std/array_list.zig +22 -31
- package/std/bit_set.zig +22 -6
- package/std/builtin/assembly.zig +68 -0
- package/std/c.zig +17 -17
- package/std/compress/flate/Compress.zig +3 -3
- package/std/crypto/Certificate/Bundle.zig +15 -1
- package/std/crypto/codecs/asn1.zig +33 -18
- package/std/crypto/codecs/base64_hex_ct.zig +14 -4
- package/std/debug/Dwarf.zig +29 -9
- package/std/debug/Info.zig +4 -0
- package/std/debug/MachOFile.zig +46 -8
- package/std/debug/Pdb.zig +539 -36
- package/std/debug/SelfInfo/Elf.zig +19 -18
- package/std/debug/SelfInfo/MachO.zig +18 -7
- package/std/debug/SelfInfo/Windows.zig +138 -36
- package/std/debug.zig +179 -65
- package/std/enums.zig +25 -19
- package/std/heap/ArenaAllocator.zig +145 -154
- package/std/heap/debug_allocator.zig +7 -7
- package/std/http/Client.zig +10 -6
- package/std/http.zig +11 -9
- package/std/json/Stringify.zig +3 -3
- package/std/json/dynamic.zig +4 -4
- package/std/math/big/int.zig +16 -17
- package/std/mem/Allocator.zig +4 -5
- package/std/mem.zig +48 -0
- package/std/os/emscripten.zig +1 -17
- package/std/os/linux.zig +7 -2
- package/std/os/windows.zig +2 -2
- package/std/pdb.zig +143 -4
- package/std/posix.zig +6 -12
- package/std/priority_dequeue.zig +13 -12
- package/std/priority_queue.zig +5 -4
- package/std/process/Child.zig +1 -1
- package/std/process/Environ.zig +1 -1
- package/std/start.zig +17 -4
- package/std/std.zig +19 -6
- package/std/testing/FailingAllocator.zig +4 -4
- package/std/testing/Smith.zig +37 -2
- package/std/zig/Ast/Render.zig +186 -458
- package/std/zig/Ast.zig +0 -4
- package/std/zig/AstGen.zig +44 -7
- package/std/zig/AstSmith.zig +2602 -0
- package/std/zig/Client.zig +8 -3
- package/std/zig/Parse.zig +83 -74
- package/std/zig/Server.zig +26 -0
- package/std/zig/Zir.zig +17 -0
- package/std/zig/c_translation/helpers.zig +14 -9
- package/std/zig/llvm/Builder.zig +107 -48
- package/std/zig/system.zig +20 -4
- package/std/zig/tokenizer.zig +2 -1
- package/std/zig.zig +6 -0
- package/compiler/aro/aro/Driver/Filesystem.zig +0 -241
- package/libc/mingw/complex/cabs.c +0 -48
- package/libc/mingw/complex/cabsf.c +0 -48
- package/libc/mingw/complex/cacos.c +0 -50
- package/libc/mingw/complex/cacosf.c +0 -50
- package/libc/mingw/complex/carg.c +0 -48
- package/libc/mingw/complex/cargf.c +0 -48
- package/libc/mingw/complex/casin.c +0 -50
- package/libc/mingw/complex/casinf.c +0 -50
- package/libc/mingw/complex/catan.c +0 -50
- package/libc/mingw/complex/catanf.c +0 -50
- package/libc/mingw/complex/ccos.c +0 -50
- package/libc/mingw/complex/ccosf.c +0 -50
- package/libc/mingw/complex/cexp.c +0 -48
- package/libc/mingw/complex/cexpf.c +0 -48
- package/libc/mingw/complex/cimag.c +0 -48
- package/libc/mingw/complex/cimagf.c +0 -48
- package/libc/mingw/complex/clog.c +0 -48
- package/libc/mingw/complex/clog10.c +0 -49
- package/libc/mingw/complex/clog10f.c +0 -49
- package/libc/mingw/complex/clogf.c +0 -48
- package/libc/mingw/complex/conj.c +0 -48
- package/libc/mingw/complex/conjf.c +0 -48
- package/libc/mingw/complex/cpow.c +0 -48
- package/libc/mingw/complex/cpowf.c +0 -48
- package/libc/mingw/complex/cproj.c +0 -48
- package/libc/mingw/complex/cprojf.c +0 -48
- package/libc/mingw/complex/creal.c +0 -48
- package/libc/mingw/complex/crealf.c +0 -48
- package/libc/mingw/complex/csin.c +0 -50
- package/libc/mingw/complex/csinf.c +0 -50
- package/libc/mingw/complex/csqrt.c +0 -48
- package/libc/mingw/complex/csqrtf.c +0 -48
- package/libc/mingw/complex/ctan.c +0 -50
- package/libc/mingw/complex/ctanf.c +0 -50
- package/libc/mingw/math/arm/s_rint.c +0 -86
- package/libc/mingw/math/arm/s_rintf.c +0 -51
- package/libc/mingw/math/arm/sincos.S +0 -30
- package/libc/mingw/math/arm-common/sincosl.c +0 -13
- package/libc/mingw/math/arm64/rint.c +0 -12
- package/libc/mingw/math/arm64/rintf.c +0 -12
- package/libc/mingw/math/arm64/sincos.S +0 -32
- package/libc/mingw/math/bsd_private_base.h +0 -148
- package/libc/mingw/math/frexpf.c +0 -13
- package/libc/mingw/math/frexpl.c +0 -71
- package/libc/mingw/math/x86/acosf.c +0 -29
- package/libc/mingw/math/x86/atanf.c +0 -23
- package/libc/mingw/math/x86/atanl.c +0 -18
- package/libc/mingw/math/x86/cos.def.h +0 -65
- package/libc/mingw/math/x86/cosl.c +0 -46
- package/libc/mingw/math/x86/cosl_internal.S +0 -55
- package/libc/mingw/math/x86/ldexp.c +0 -23
- package/libc/mingw/math/x86/scalbn.S +0 -41
- package/libc/mingw/math/x86/scalbnf.S +0 -40
- package/libc/mingw/math/x86/sin.def.h +0 -65
- package/libc/mingw/math/x86/sinl.c +0 -46
- package/libc/mingw/math/x86/sinl_internal.S +0 -58
- package/libc/mingw/math/x86/tanl.S +0 -62
- package/libc/mingw/misc/btowc.c +0 -28
- package/libc/mingw/misc/wcstof.c +0 -66
- package/libc/mingw/misc/wcstoimax.c +0 -132
- package/libc/mingw/misc/wcstoumax.c +0 -126
- package/libc/mingw/misc/wctob.c +0 -29
- package/libc/mingw/misc/winbs_uint64.c +0 -6
- package/libc/mingw/misc/winbs_ulong.c +0 -6
- package/libc/mingw/misc/winbs_ushort.c +0 -6
- package/libc/mingw/stdio/_Exit.c +0 -10
- package/libc/mingw/stdio/_findfirst64i32.c +0 -21
- package/libc/mingw/stdio/_findnext64i32.c +0 -21
- package/libc/mingw/stdio/_fstat64i32.c +0 -37
- package/libc/mingw/stdio/_stat64i32.c +0 -37
- package/libc/mingw/stdio/_wfindfirst64i32.c +0 -21
- package/libc/mingw/stdio/_wfindnext64i32.c +0 -21
- package/libc/mingw/stdio/_wstat64i32.c +0 -37
- package/libc/musl/src/legacy/isastream.c +0 -7
- package/libc/musl/src/legacy/valloc.c +0 -8
- package/libc/musl/src/math/__cosl.c +0 -96
- package/libc/musl/src/math/__sinl.c +0 -78
- package/libc/musl/src/math/__tanl.c +0 -143
- package/libc/musl/src/math/aarch64/lrint.c +0 -10
- package/libc/musl/src/math/aarch64/lrintf.c +0 -10
- package/libc/musl/src/math/aarch64/rintf.c +0 -7
- package/libc/musl/src/math/cosl.c +0 -39
- package/libc/musl/src/math/fdim.c +0 -10
- package/libc/musl/src/math/finite.c +0 -7
- package/libc/musl/src/math/finitef.c +0 -7
- package/libc/musl/src/math/frexp.c +0 -23
- package/libc/musl/src/math/frexpf.c +0 -23
- package/libc/musl/src/math/frexpl.c +0 -29
- package/libc/musl/src/math/i386/lrint.c +0 -8
- package/libc/musl/src/math/i386/lrintf.c +0 -8
- package/libc/musl/src/math/i386/rintf.c +0 -7
- package/libc/musl/src/math/lrint.c +0 -72
- package/libc/musl/src/math/lrintf.c +0 -8
- package/libc/musl/src/math/powerpc64/lrint.c +0 -16
- package/libc/musl/src/math/powerpc64/lrintf.c +0 -16
- package/libc/musl/src/math/rintf.c +0 -30
- package/libc/musl/src/math/s390x/rintf.c +0 -15
- package/libc/musl/src/math/sincosl.c +0 -60
- package/libc/musl/src/math/sinl.c +0 -41
- package/libc/musl/src/math/tanl.c +0 -29
- package/libc/musl/src/math/x32/lrint.s +0 -5
- package/libc/musl/src/math/x32/lrintf.s +0 -5
- package/libc/musl/src/math/x86_64/lrint.c +0 -8
- package/libc/musl/src/math/x86_64/lrintf.c +0 -8
- package/libc/wasi/libc-bottom-half/sources/reallocarray.c +0 -14
|
@@ -19,10 +19,63 @@ const MacroTranslator = @import("MacroTranslator.zig");
|
|
|
19
19
|
const PatternList = @import("PatternList.zig");
|
|
20
20
|
const Scope = @import("Scope.zig");
|
|
21
21
|
|
|
22
|
+
const AnonymousRecordFieldNames = struct {
|
|
23
|
+
pub const Key = struct {
|
|
24
|
+
parent: QualType,
|
|
25
|
+
field: QualType,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
pub const Context = struct {
|
|
29
|
+
pub fn hash(ctx: Context, key: Key) u64 {
|
|
30
|
+
const auto_hash = std.hash_map.getAutoHashFn(Key, Context);
|
|
31
|
+
return auto_hash(ctx, .{
|
|
32
|
+
.parent = key.parent.unqualified(),
|
|
33
|
+
.field = key.field.unqualified(),
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
pub fn eql(ctx: Context, a: Key, b: Key) bool {
|
|
38
|
+
const auto_eql = std.hash_map.getAutoEqlFn(Key, Context);
|
|
39
|
+
return auto_eql(ctx, .{
|
|
40
|
+
.parent = a.parent.unqualified(),
|
|
41
|
+
.field = a.field.unqualified(),
|
|
42
|
+
}, .{
|
|
43
|
+
.parent = b.parent.unqualified(),
|
|
44
|
+
.field = b.field.unqualified(),
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
pub const QualTypeHashContext = struct {
|
|
51
|
+
pub fn hash(ctx: QualTypeHashContext, key: QualType) u64 {
|
|
52
|
+
const auto_hash = std.hash_map.getAutoHashFn(QualType, QualTypeHashContext);
|
|
53
|
+
return auto_hash(ctx, key.unqualified());
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
pub fn eql(ctx: QualTypeHashContext, a: QualType, b: QualType) bool {
|
|
57
|
+
const auto_eql = std.hash_map.getAutoEqlFn(QualType, QualTypeHashContext);
|
|
58
|
+
return auto_eql(ctx, a.unqualified(), b.unqualified());
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
|
|
22
62
|
pub const Error = std.mem.Allocator.Error;
|
|
23
63
|
pub const MacroProcessingError = Error || error{UnexpectedMacroToken};
|
|
24
64
|
pub const TypeError = Error || error{UnsupportedType};
|
|
25
|
-
pub const TransError = TypeError || error{UnsupportedTranslation};
|
|
65
|
+
pub const TransError = TypeError || error{ UnsupportedTranslation, SelfReferential };
|
|
66
|
+
|
|
67
|
+
/// Control when to treat a trailing array as a flexible array member.
|
|
68
|
+
/// Mirrors the -fstrict-flex-arrays=<n> compiler flag.
|
|
69
|
+
pub const StrictFlexArraysLevel = enum {
|
|
70
|
+
/// Any trailing array member is a flexible array.
|
|
71
|
+
@"0",
|
|
72
|
+
/// Trailing arrays of size 0, 1, or undefined are flexible.
|
|
73
|
+
@"1",
|
|
74
|
+
/// Trailing arrays of size 0 or undefined are flexible (default).
|
|
75
|
+
@"2",
|
|
76
|
+
/// Only trailing arrays of undefined size are flexible.
|
|
77
|
+
@"3",
|
|
78
|
+
};
|
|
26
79
|
|
|
27
80
|
const Translator = @This();
|
|
28
81
|
|
|
@@ -33,6 +86,17 @@ comp: *aro.Compilation,
|
|
|
33
86
|
/// The Preprocessor that produced the source for `tree`.
|
|
34
87
|
pp: *const aro.Preprocessor,
|
|
35
88
|
|
|
89
|
+
/// Should static functions be translated as `pub`.
|
|
90
|
+
pub_static: bool,
|
|
91
|
+
/// Should function bodies be translated.
|
|
92
|
+
func_bodies: bool,
|
|
93
|
+
/// Should macro names of literals be preserved.
|
|
94
|
+
keep_macro_literals: bool,
|
|
95
|
+
/// Should struct fields be default initialized.
|
|
96
|
+
default_init: bool,
|
|
97
|
+
/// Control when to treat a trailing array as a flexible array member.
|
|
98
|
+
strict_flex_arrays: StrictFlexArraysLevel,
|
|
99
|
+
|
|
36
100
|
gpa: mem.Allocator,
|
|
37
101
|
arena: mem.Allocator,
|
|
38
102
|
|
|
@@ -44,14 +108,16 @@ mangle_count: u32 = 0,
|
|
|
44
108
|
/// Table of declarations for enum, struct, union and typedef types.
|
|
45
109
|
type_decls: std.AutoArrayHashMapUnmanaged(Node.Index, []const u8) = .empty,
|
|
46
110
|
/// Table of record decls that have been demoted to opaques.
|
|
47
|
-
opaque_demotes: std.
|
|
111
|
+
opaque_demotes: std.HashMapUnmanaged(QualType, void, QualTypeHashContext, std.hash_map.default_max_load_percentage) = .empty,
|
|
48
112
|
/// Table of unnamed enums and records that are child types of typedefs.
|
|
49
|
-
unnamed_typedefs: std.
|
|
113
|
+
unnamed_typedefs: std.HashMapUnmanaged(QualType, []const u8, QualTypeHashContext, std.hash_map.default_max_load_percentage) = .empty,
|
|
50
114
|
/// Table of anonymous record to generated field names.
|
|
51
|
-
anonymous_record_field_names: std.
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
115
|
+
anonymous_record_field_names: std.HashMapUnmanaged(
|
|
116
|
+
AnonymousRecordFieldNames.Key,
|
|
117
|
+
[]const u8,
|
|
118
|
+
AnonymousRecordFieldNames.Context,
|
|
119
|
+
std.hash_map.default_max_load_percentage,
|
|
120
|
+
) = .empty,
|
|
55
121
|
|
|
56
122
|
/// This one is different than the root scope's name table. This contains
|
|
57
123
|
/// a list of names that we found by visiting all the top level decls without
|
|
@@ -75,6 +141,10 @@ typedefs: std.StringArrayHashMapUnmanaged(void) = .empty,
|
|
|
75
141
|
/// The lhs lval of a compound assignment expression.
|
|
76
142
|
compound_assign_dummy: ?ZigNode = null,
|
|
77
143
|
|
|
144
|
+
/// Set of variables whose initializers are currently being translated.
|
|
145
|
+
/// Used to detect self-referential initializers.
|
|
146
|
+
wip_var_inits: std.AutoHashMapUnmanaged(Node.Index, void) = .empty,
|
|
147
|
+
|
|
78
148
|
pub fn getMangle(t: *Translator) u32 {
|
|
79
149
|
t.mangle_count += 1;
|
|
80
150
|
return t.mangle_count;
|
|
@@ -98,10 +168,9 @@ fn maybeSuppressResult(t: *Translator, used: ResultUsed, result: ZigNode) TransE
|
|
|
98
168
|
|
|
99
169
|
pub fn addTopLevelDecl(t: *Translator, name: []const u8, decl_node: ZigNode) !void {
|
|
100
170
|
const gop = try t.global_scope.sym_table.getOrPut(t.gpa, name);
|
|
101
|
-
if (
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
171
|
+
if (gop.found_existing) return; // Any duplicate decls are equivalent
|
|
172
|
+
gop.value_ptr.* = decl_node;
|
|
173
|
+
try t.global_scope.nodes.append(t.gpa, decl_node);
|
|
105
174
|
}
|
|
106
175
|
|
|
107
176
|
fn fail(
|
|
@@ -172,6 +241,12 @@ pub const Options = struct {
|
|
|
172
241
|
comp: *aro.Compilation,
|
|
173
242
|
pp: *const aro.Preprocessor,
|
|
174
243
|
tree: *const aro.Tree,
|
|
244
|
+
module_libs: bool,
|
|
245
|
+
pub_static: bool,
|
|
246
|
+
func_bodies: bool,
|
|
247
|
+
keep_macro_literals: bool,
|
|
248
|
+
default_init: bool,
|
|
249
|
+
strict_flex_arrays: StrictFlexArraysLevel,
|
|
175
250
|
};
|
|
176
251
|
|
|
177
252
|
pub fn translate(options: Options) mem.Allocator.Error![]u8 {
|
|
@@ -188,6 +263,11 @@ pub fn translate(options: Options) mem.Allocator.Error![]u8 {
|
|
|
188
263
|
.comp = options.comp,
|
|
189
264
|
.pp = options.pp,
|
|
190
265
|
.tree = options.tree,
|
|
266
|
+
.pub_static = options.pub_static,
|
|
267
|
+
.func_bodies = options.func_bodies,
|
|
268
|
+
.keep_macro_literals = options.keep_macro_literals,
|
|
269
|
+
.default_init = options.default_init,
|
|
270
|
+
.strict_flex_arrays = options.strict_flex_arrays,
|
|
191
271
|
};
|
|
192
272
|
translator.global_scope.* = Scope.Root.init(&translator);
|
|
193
273
|
defer {
|
|
@@ -200,6 +280,7 @@ pub fn translate(options: Options) mem.Allocator.Error![]u8 {
|
|
|
200
280
|
translator.anonymous_record_field_names.deinit(gpa);
|
|
201
281
|
translator.typedefs.deinit(gpa);
|
|
202
282
|
translator.global_scope.deinit();
|
|
283
|
+
translator.wip_var_inits.deinit(gpa);
|
|
203
284
|
}
|
|
204
285
|
|
|
205
286
|
try translator.prepopulateGlobalNameTable();
|
|
@@ -227,7 +308,6 @@ pub fn translate(options: Options) mem.Allocator.Error![]u8 {
|
|
|
227
308
|
\\pub const __builtin = @import("std").zig.c_translation.builtins;
|
|
228
309
|
\\pub const __helpers = @import("std").zig.c_translation.helpers;
|
|
229
310
|
\\
|
|
230
|
-
\\
|
|
231
311
|
) catch return error.OutOfMemory;
|
|
232
312
|
|
|
233
313
|
var zig_ast = try ast.render(gpa, translator.global_scope.nodes.items);
|
|
@@ -261,10 +341,12 @@ fn prepopulateGlobalNameTable(t: *Translator) !void {
|
|
|
261
341
|
const gop = try t.unnamed_typedefs.getOrPut(t.gpa, base.qt);
|
|
262
342
|
if (gop.found_existing) {
|
|
263
343
|
// One typedef can declare multiple names.
|
|
264
|
-
//
|
|
344
|
+
// Don't put this one in `decl_table` so it's processed later.
|
|
265
345
|
continue;
|
|
266
346
|
}
|
|
267
347
|
gop.value_ptr.* = decl_name;
|
|
348
|
+
try t.type_decls.put(t.gpa, decl, decl_name);
|
|
349
|
+
try t.typedefs.put(t.gpa, decl_name, {});
|
|
268
350
|
},
|
|
269
351
|
|
|
270
352
|
.struct_decl,
|
|
@@ -344,15 +426,26 @@ fn transDecl(t: *Translator, scope: *Scope, decl: Node.Index) !void {
|
|
|
344
426
|
try t.transRecordDecl(scope, record_decl.container_qt);
|
|
345
427
|
},
|
|
346
428
|
|
|
429
|
+
.struct_forward_decl, .union_forward_decl => |record_decl| {
|
|
430
|
+
if (record_decl.definition) |some| {
|
|
431
|
+
return t.transDecl(scope, some);
|
|
432
|
+
}
|
|
433
|
+
try t.transRecordDecl(scope, record_decl.container_qt);
|
|
434
|
+
},
|
|
435
|
+
|
|
347
436
|
.enum_decl => |enum_decl| {
|
|
348
437
|
try t.transEnumDecl(scope, enum_decl.container_qt);
|
|
349
438
|
},
|
|
350
439
|
|
|
440
|
+
.enum_forward_decl => |enum_decl| {
|
|
441
|
+
if (enum_decl.definition) |some| {
|
|
442
|
+
return t.transDecl(scope, some);
|
|
443
|
+
}
|
|
444
|
+
try t.transEnumDecl(scope, enum_decl.container_qt);
|
|
445
|
+
},
|
|
446
|
+
|
|
351
447
|
.enum_field,
|
|
352
448
|
.record_field,
|
|
353
|
-
.struct_forward_decl,
|
|
354
|
-
.union_forward_decl,
|
|
355
|
-
.enum_forward_decl,
|
|
356
449
|
=> return,
|
|
357
450
|
|
|
358
451
|
.function => |function| {
|
|
@@ -364,7 +457,7 @@ fn transDecl(t: *Translator, scope: *Scope, decl: Node.Index) !void {
|
|
|
364
457
|
|
|
365
458
|
.variable => |variable| {
|
|
366
459
|
if (variable.definition != null) return;
|
|
367
|
-
try t.transVarDecl(scope, variable);
|
|
460
|
+
try t.transVarDecl(scope, variable, decl);
|
|
368
461
|
},
|
|
369
462
|
.static_assert => |static_assert| {
|
|
370
463
|
try t.transStaticAssert(&t.global_scope.base, static_assert);
|
|
@@ -531,13 +624,6 @@ fn transRecordDecl(t: *Translator, scope: *Scope, record_qt: QualType) Error!voi
|
|
|
531
624
|
break :init ZigTag.opaque_literal.init();
|
|
532
625
|
}
|
|
533
626
|
|
|
534
|
-
// Demote record to opaque if it contains an opaque field
|
|
535
|
-
if (t.typeWasDemotedToOpaque(field.qt)) {
|
|
536
|
-
try t.opaque_demotes.put(t.gpa, base.qt, {});
|
|
537
|
-
try t.warn(scope, field_loc, "{s} demoted to opaque type - has opaque field", .{container_kind_name});
|
|
538
|
-
break :init ZigTag.opaque_literal.init();
|
|
539
|
-
}
|
|
540
|
-
|
|
541
627
|
var field_name = field.name.lookup(t.comp);
|
|
542
628
|
if (field.name_tok == 0) {
|
|
543
629
|
field_name = try std.fmt.allocPrint(t.arena, "unnamed_{d}", .{unnamed_field_count});
|
|
@@ -548,23 +634,22 @@ fn transRecordDecl(t: *Translator, scope: *Scope, record_qt: QualType) Error!voi
|
|
|
548
634
|
}, field_name);
|
|
549
635
|
}
|
|
550
636
|
|
|
551
|
-
const field_alignment = if (has_alignment_attributes)
|
|
552
|
-
t.alignmentForField(record_ty, head_field_alignment, field_index)
|
|
553
|
-
else
|
|
554
|
-
null;
|
|
555
|
-
|
|
556
637
|
const field_type = field_type: {
|
|
557
638
|
// Check if this is a flexible array member.
|
|
558
639
|
flexible: {
|
|
559
640
|
if (field_index != record_ty.fields.len - 1 and container_kind != .@"union") break :flexible;
|
|
560
641
|
const array_ty = field.qt.get(t.comp, .array) orelse break :flexible;
|
|
561
|
-
if (
|
|
642
|
+
if (!t.isFlexibleArrayLen(array_ty.len)) break :flexible;
|
|
562
643
|
|
|
563
644
|
const elem_type = t.transType(scope, array_ty.elem, field_loc) catch |err| switch (err) {
|
|
564
645
|
error.UnsupportedType => break :flexible,
|
|
565
646
|
else => |e| return e,
|
|
566
647
|
};
|
|
567
|
-
const
|
|
648
|
+
const backing_array_len: usize = switch (array_ty.len) {
|
|
649
|
+
.fixed => |n| @intCast(n),
|
|
650
|
+
else => 0,
|
|
651
|
+
};
|
|
652
|
+
const backing_array = try ZigTag.array_type.create(t.arena, .{ .len = backing_array_len, .elem_type = elem_type });
|
|
568
653
|
|
|
569
654
|
const member_name = field_name;
|
|
570
655
|
field_name = try std.fmt.allocPrint(t.arena, "_{s}", .{field_name});
|
|
@@ -572,7 +657,7 @@ fn transRecordDecl(t: *Translator, scope: *Scope, record_qt: QualType) Error!voi
|
|
|
572
657
|
const member = try t.createFlexibleMemberFn(member_name, field_name);
|
|
573
658
|
try functions.append(t.gpa, member);
|
|
574
659
|
|
|
575
|
-
break :field_type
|
|
660
|
+
break :field_type backing_array;
|
|
576
661
|
}
|
|
577
662
|
|
|
578
663
|
break :field_type t.transType(scope, field.qt, field_loc) catch |err| switch (err) {
|
|
@@ -588,10 +673,22 @@ fn transRecordDecl(t: *Translator, scope: *Scope, record_qt: QualType) Error!voi
|
|
|
588
673
|
};
|
|
589
674
|
};
|
|
590
675
|
|
|
676
|
+
// Demote record to opaque if it contains an opaque field
|
|
677
|
+
if (t.typeWasDemotedToOpaque(field.qt)) {
|
|
678
|
+
try t.opaque_demotes.put(t.gpa, base.qt, {});
|
|
679
|
+
try t.warn(scope, field_loc, "{s} demoted to opaque type - has opaque field", .{container_kind_name});
|
|
680
|
+
break :init ZigTag.opaque_literal.init();
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
const field_alignment = if (has_alignment_attributes)
|
|
684
|
+
t.alignmentForField(record_ty, head_field_alignment, field_index)
|
|
685
|
+
else
|
|
686
|
+
null;
|
|
687
|
+
|
|
591
688
|
// C99 introduced designated initializers for structs. Omitted fields are implicitly
|
|
592
689
|
// initialized to zero. Some C APIs are designed with this in mind. Defaulting to zero
|
|
593
690
|
// values for translated struct fields permits Zig code to comfortably use such an API.
|
|
594
|
-
const default_value = if (container_kind == .@"struct")
|
|
691
|
+
const default_value = if (t.default_init and container_kind == .@"struct")
|
|
595
692
|
try t.createZeroValueNode(field.qt, field_type, .no_as)
|
|
596
693
|
else
|
|
597
694
|
null;
|
|
@@ -616,7 +713,7 @@ fn transRecordDecl(t: *Translator, scope: *Scope, record_qt: QualType) Error!voi
|
|
|
616
713
|
.name = "_padding",
|
|
617
714
|
.type = try ZigTag.type.create(t.arena, try std.fmt.allocPrint(t.arena, "u{d}", .{padding_bits})),
|
|
618
715
|
.alignment = @divExact(alignment_bits, 8),
|
|
619
|
-
.default_value = if (container_kind == .@"struct")
|
|
716
|
+
.default_value = if (t.default_init and container_kind == .@"struct")
|
|
620
717
|
ZigTag.zero_literal.init()
|
|
621
718
|
else
|
|
622
719
|
null,
|
|
@@ -663,14 +760,12 @@ fn transRecordDecl(t: *Translator, scope: *Scope, record_qt: QualType) Error!voi
|
|
|
663
760
|
fn transFnDecl(t: *Translator, scope: *Scope, function: Node.Function) Error!void {
|
|
664
761
|
const func_ty = function.qt.get(t.comp, .func).?;
|
|
665
762
|
|
|
666
|
-
const is_pub = scope.id == .root;
|
|
667
|
-
|
|
668
763
|
const fn_name = t.tree.tokSlice(function.name_tok);
|
|
669
764
|
if (scope.getAlias(fn_name) != null or t.global_scope.containsNow(fn_name))
|
|
670
765
|
return; // Avoid processing this decl twice
|
|
671
766
|
|
|
672
767
|
const fn_decl_loc = function.name_tok;
|
|
673
|
-
const has_body = function.body != null and func_ty.kind != .variadic;
|
|
768
|
+
const has_body = function.body != null and func_ty.kind != .variadic and t.func_bodies;
|
|
674
769
|
if (function.body != null and func_ty.kind == .variadic) {
|
|
675
770
|
try t.warn(scope, function.name_tok, "TODO unable to translate variadic function, demoted to extern", .{});
|
|
676
771
|
}
|
|
@@ -681,7 +776,7 @@ fn transFnDecl(t: *Translator, scope: *Scope, function: Node.Function) Error!voi
|
|
|
681
776
|
.is_always_inline = is_always_inline,
|
|
682
777
|
.is_extern = !has_body,
|
|
683
778
|
.is_export = !function.static and has_body and !is_always_inline and !function.@"inline",
|
|
684
|
-
.is_pub =
|
|
779
|
+
.is_pub = scope.id == .root and (!function.static or t.pub_static),
|
|
685
780
|
.has_body = has_body,
|
|
686
781
|
.cc = if (function.qt.getAttribute(t.comp, .calling_convention)) |some| switch (some.cc) {
|
|
687
782
|
.c => .c,
|
|
@@ -761,6 +856,7 @@ fn transFnDecl(t: *Translator, scope: *Scope, function: Node.Function) Error!voi
|
|
|
761
856
|
|
|
762
857
|
t.transCompoundStmtInline(body_stmt, &block_scope) catch |err| switch (err) {
|
|
763
858
|
error.OutOfMemory => |e| return e,
|
|
859
|
+
error.SelfReferential => unreachable,
|
|
764
860
|
error.UnsupportedTranslation,
|
|
765
861
|
error.UnsupportedType,
|
|
766
862
|
=> {
|
|
@@ -777,7 +873,7 @@ fn transFnDecl(t: *Translator, scope: *Scope, function: Node.Function) Error!voi
|
|
|
777
873
|
return t.addTopLevelDecl(fn_name, proto_node);
|
|
778
874
|
}
|
|
779
875
|
|
|
780
|
-
fn transVarDecl(t: *Translator, scope: *Scope, variable: Node.Variable) Error!void {
|
|
876
|
+
fn transVarDecl(t: *Translator, scope: *Scope, variable: Node.Variable, decl_node: Node.Index) Error!void {
|
|
781
877
|
const base_name = t.tree.tokSlice(variable.name_tok);
|
|
782
878
|
const toplevel = scope.id == .root;
|
|
783
879
|
const bs: *Scope.Block = if (!toplevel) try scope.findBlockScope(t) else undefined;
|
|
@@ -815,24 +911,28 @@ fn transVarDecl(t: *Translator, scope: *Scope, variable: Node.Variable) Error!vo
|
|
|
815
911
|
var is_const = variable.qt.@"const" or (array_ty != null and array_ty.?.elem.@"const");
|
|
816
912
|
var is_extern = variable.storage_class == .@"extern";
|
|
817
913
|
|
|
914
|
+
var self_referential = false;
|
|
818
915
|
const init_node = init: {
|
|
819
916
|
if (variable.initializer) |init| {
|
|
820
917
|
const maybe_literal = init.get(t.tree);
|
|
918
|
+
if (!toplevel) try t.wip_var_inits.putNoClobber(t.gpa, decl_node, {});
|
|
919
|
+
defer _ = t.wip_var_inits.remove(decl_node);
|
|
920
|
+
|
|
821
921
|
const init_node = (if (maybe_literal == .string_literal_expr)
|
|
822
922
|
t.transStringLiteralInitializer(init, maybe_literal.string_literal_expr, type_node)
|
|
823
923
|
else
|
|
824
924
|
t.transExprCoercing(scope, init, .used)) catch |err| switch (err) {
|
|
925
|
+
error.SelfReferential => {
|
|
926
|
+
self_referential = true;
|
|
927
|
+
break :init ZigTag.undefined_literal.init();
|
|
928
|
+
},
|
|
825
929
|
error.UnsupportedTranslation, error.UnsupportedType => {
|
|
826
930
|
return t.failDecl(scope, variable.name_tok, name, "unable to resolve var init expr", .{});
|
|
827
931
|
},
|
|
828
932
|
else => |e| return e,
|
|
829
933
|
};
|
|
830
934
|
|
|
831
|
-
|
|
832
|
-
break :init try ZigTag.int_from_bool.create(t.arena, init_node);
|
|
833
|
-
} else {
|
|
834
|
-
break :init init_node;
|
|
835
|
-
}
|
|
935
|
+
break :init try t.toNonBool(init_node, variable.qt);
|
|
836
936
|
}
|
|
837
937
|
if (variable.storage_class == .@"extern") {
|
|
838
938
|
if (array_ty != null and array_ty.?.len == .incomplete) {
|
|
@@ -876,7 +976,7 @@ fn transVarDecl(t: *Translator, scope: *Scope, variable: Node.Variable) Error!vo
|
|
|
876
976
|
const alignment: ?c_uint = variable.qt.requestedAlignment(t.comp) orelse null;
|
|
877
977
|
var node = try ZigTag.var_decl.create(t.arena, .{
|
|
878
978
|
.is_pub = toplevel,
|
|
879
|
-
.is_const = is_const,
|
|
979
|
+
.is_const = is_const and !self_referential,
|
|
880
980
|
.is_extern = is_extern,
|
|
881
981
|
.is_export = toplevel and variable.storage_class == .auto and linkage == .strong,
|
|
882
982
|
.is_threadlocal = variable.thread_local,
|
|
@@ -894,6 +994,21 @@ fn transVarDecl(t: *Translator, scope: *Scope, variable: Node.Variable) Error!vo
|
|
|
894
994
|
node = try ZigTag.wrapped_local.create(t.arena, .{ .name = name, .init = node });
|
|
895
995
|
}
|
|
896
996
|
try scope.appendNode(node);
|
|
997
|
+
if (self_referential) {
|
|
998
|
+
const deferred_init = t.transExprCoercing(scope, variable.initializer.?, .used) catch |err| switch (err) {
|
|
999
|
+
error.SelfReferential => unreachable,
|
|
1000
|
+
error.UnsupportedTranslation, error.UnsupportedType => {
|
|
1001
|
+
return t.failDecl(scope, variable.name_tok, name, "unable to resolve var init expr", .{});
|
|
1002
|
+
},
|
|
1003
|
+
else => |e| return e,
|
|
1004
|
+
};
|
|
1005
|
+
|
|
1006
|
+
const assign = try ZigTag.assign.create(t.arena, .{
|
|
1007
|
+
.lhs = try ZigTag.identifier.create(t.arena, name),
|
|
1008
|
+
.rhs = try t.toNonBool(deferred_init, variable.qt),
|
|
1009
|
+
});
|
|
1010
|
+
try scope.appendNode(assign);
|
|
1011
|
+
}
|
|
897
1012
|
try bs.discardVariable(name);
|
|
898
1013
|
|
|
899
1014
|
if (variable.qt.getAttribute(t.comp, .cleanup)) |cleanup_attr| {
|
|
@@ -1001,6 +1116,7 @@ fn transEnumDecl(t: *Translator, scope: *Scope, enum_qt: QualType) Error!void {
|
|
|
1001
1116
|
|
|
1002
1117
|
fn transStaticAssert(t: *Translator, scope: *Scope, static_assert: Node.StaticAssert) Error!void {
|
|
1003
1118
|
const condition = t.transExpr(scope, static_assert.cond, .used) catch |err| switch (err) {
|
|
1119
|
+
error.SelfReferential => unreachable,
|
|
1004
1120
|
error.UnsupportedTranslation, error.UnsupportedType => {
|
|
1005
1121
|
return try t.warn(&t.global_scope.base, static_assert.cond.tok(t.tree), "unable to translate _Static_assert condition", .{});
|
|
1006
1122
|
},
|
|
@@ -1084,21 +1200,17 @@ fn transType(t: *Translator, scope: *Scope, qt: QualType, source_loc: TokenIndex
|
|
|
1084
1200
|
},
|
|
1085
1201
|
.float => |float_ty| switch (float_ty) {
|
|
1086
1202
|
.fp16, .float16 => return ZigTag.type.create(t.arena, "f16"),
|
|
1087
|
-
.float => return ZigTag.type.create(t.arena, "f32"),
|
|
1088
|
-
.double => return ZigTag.type.create(t.arena, "f64"),
|
|
1089
|
-
.long_double => return ZigTag.type.create(t.arena, "c_longdouble"),
|
|
1203
|
+
.float, .float32 => return ZigTag.type.create(t.arena, "f32"),
|
|
1204
|
+
.double, .float64, .float32x => return ZigTag.type.create(t.arena, "f64"),
|
|
1205
|
+
.long_double, .float64x => return ZigTag.type.create(t.arena, "c_longdouble"),
|
|
1090
1206
|
.float128 => return ZigTag.type.create(t.arena, "f128"),
|
|
1091
|
-
.bf16,
|
|
1092
|
-
.float32,
|
|
1093
|
-
.float64,
|
|
1094
|
-
.float32x,
|
|
1095
|
-
.float64x,
|
|
1096
|
-
.float128x,
|
|
1207
|
+
.bf16 => return t.fail(error.UnsupportedType, source_loc, "TODO support bfloat16", .{}),
|
|
1097
1208
|
.dfloat32,
|
|
1098
1209
|
.dfloat64,
|
|
1099
1210
|
.dfloat128,
|
|
1100
1211
|
.dfloat64x,
|
|
1101
|
-
=> return t.fail(error.UnsupportedType, source_loc, "TODO support float type: '{s}'", .{try t.getTypeStr(qt)}),
|
|
1212
|
+
=> return t.fail(error.UnsupportedType, source_loc, "TODO support decimal float type: '{s}'", .{try t.getTypeStr(qt)}),
|
|
1213
|
+
.float128x => unreachable, // Unsupported on all targets
|
|
1102
1214
|
},
|
|
1103
1215
|
.pointer => |pointer_ty| {
|
|
1104
1216
|
const child_qt = pointer_ty.child;
|
|
@@ -1173,9 +1285,21 @@ fn transType(t: *Translator, scope: *Scope, qt: QualType, source_loc: TokenIndex
|
|
|
1173
1285
|
return ZigTag.identifier.create(t.arena, name);
|
|
1174
1286
|
},
|
|
1175
1287
|
.attributed => |attributed_ty| continue :loop attributed_ty.base.type(t.comp),
|
|
1176
|
-
.typeof => |typeof_ty|
|
|
1288
|
+
.typeof => |typeof_ty| {
|
|
1289
|
+
if (typeof_ty.expr) |expr| {
|
|
1290
|
+
if (t.transExpr(scope, expr, .used)) |node| {
|
|
1291
|
+
return ZigTag.typeof.create(t.arena, node);
|
|
1292
|
+
} else |err| switch (err) {
|
|
1293
|
+
error.SelfReferential => {},
|
|
1294
|
+
error.UnsupportedTranslation => {},
|
|
1295
|
+
error.UnsupportedType => {},
|
|
1296
|
+
error.OutOfMemory => return error.OutOfMemory,
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
continue :loop typeof_ty.base.type(t.comp);
|
|
1300
|
+
},
|
|
1177
1301
|
.vector => |vector_ty| {
|
|
1178
|
-
const len = try t.createNumberNode(vector_ty.len
|
|
1302
|
+
const len = try t.createNumberNode(vector_ty.len);
|
|
1179
1303
|
const elem_type = try t.transType(scope, vector_ty.elem, source_loc);
|
|
1180
1304
|
return ZigTag.vector.create(t.arena, .{ .lhs = len, .rhs = elem_type });
|
|
1181
1305
|
},
|
|
@@ -1384,7 +1508,10 @@ fn transFnType(
|
|
|
1384
1508
|
.is_var_args = switch (func_ty.kind) {
|
|
1385
1509
|
.normal => false,
|
|
1386
1510
|
.variadic => true,
|
|
1387
|
-
.old_style =>
|
|
1511
|
+
.old_style => if (t.comp.target.cpu.arch.isWasm())
|
|
1512
|
+
false
|
|
1513
|
+
else
|
|
1514
|
+
!ctx.is_export and !ctx.is_always_inline and !ctx.has_body,
|
|
1388
1515
|
},
|
|
1389
1516
|
.name = ctx.fn_name,
|
|
1390
1517
|
.linksection_string = linksection_string,
|
|
@@ -1468,7 +1595,7 @@ fn typeIsOpaque(t: *Translator, qt: QualType) bool {
|
|
|
1468
1595
|
}
|
|
1469
1596
|
|
|
1470
1597
|
fn typeWasDemotedToOpaque(t: *Translator, qt: QualType) bool {
|
|
1471
|
-
return t.opaque_demotes.contains(qt);
|
|
1598
|
+
return t.opaque_demotes.contains(qt.base(t.comp).qt);
|
|
1472
1599
|
}
|
|
1473
1600
|
|
|
1474
1601
|
fn typeHasWrappingOverflow(t: *Translator, qt: QualType) bool {
|
|
@@ -1531,16 +1658,30 @@ fn transStmt(t: *Translator, scope: *Scope, stmt: Node.Index) TransError!ZigNode
|
|
|
1531
1658
|
try t.transRecordDecl(scope, record_decl.container_qt);
|
|
1532
1659
|
return ZigTag.declaration.init();
|
|
1533
1660
|
},
|
|
1661
|
+
.struct_forward_decl, .union_forward_decl => |record_decl| {
|
|
1662
|
+
if (record_decl.definition) |some| {
|
|
1663
|
+
return t.transStmt(scope, some);
|
|
1664
|
+
}
|
|
1665
|
+
try t.transRecordDecl(scope, record_decl.container_qt);
|
|
1666
|
+
return ZigTag.declaration.init();
|
|
1667
|
+
},
|
|
1534
1668
|
.enum_decl => |enum_decl| {
|
|
1535
1669
|
try t.transEnumDecl(scope, enum_decl.container_qt);
|
|
1536
1670
|
return ZigTag.declaration.init();
|
|
1537
1671
|
},
|
|
1672
|
+
.enum_forward_decl => |enum_decl| {
|
|
1673
|
+
if (enum_decl.definition) |some| {
|
|
1674
|
+
return t.transStmt(scope, some);
|
|
1675
|
+
}
|
|
1676
|
+
try t.transEnumDecl(scope, enum_decl.container_qt);
|
|
1677
|
+
return ZigTag.declaration.init();
|
|
1678
|
+
},
|
|
1538
1679
|
.function => |function| {
|
|
1539
1680
|
try t.transFnDecl(scope, function);
|
|
1540
1681
|
return ZigTag.declaration.init();
|
|
1541
1682
|
},
|
|
1542
1683
|
.variable => |variable| {
|
|
1543
|
-
try t.transVarDecl(scope, variable);
|
|
1684
|
+
try t.transVarDecl(scope, variable, stmt);
|
|
1544
1685
|
return ZigTag.declaration.init();
|
|
1545
1686
|
},
|
|
1546
1687
|
.switch_stmt => |switch_stmt| return t.transSwitch(scope, switch_stmt),
|
|
@@ -1562,7 +1703,10 @@ fn transCompoundStmtInline(t: *Translator, compound: Node.CompoundStmt, block: *
|
|
|
1562
1703
|
const result = try t.transStmt(&block.base, stmt);
|
|
1563
1704
|
switch (result.tag()) {
|
|
1564
1705
|
.declaration, .empty_block => {},
|
|
1565
|
-
else =>
|
|
1706
|
+
else => {
|
|
1707
|
+
try block.statements.append(t.gpa, result);
|
|
1708
|
+
if (result.isNoreturn()) return;
|
|
1709
|
+
},
|
|
1566
1710
|
}
|
|
1567
1711
|
}
|
|
1568
1712
|
}
|
|
@@ -1578,12 +1722,9 @@ fn transReturnStmt(t: *Translator, scope: *Scope, return_stmt: Node.ReturnStmt)
|
|
|
1578
1722
|
switch (return_stmt.operand) {
|
|
1579
1723
|
.none => return ZigTag.return_void.init(),
|
|
1580
1724
|
.expr => |operand| {
|
|
1581
|
-
|
|
1725
|
+
const rhs = try t.transExprCoercing(scope, operand, .used);
|
|
1582
1726
|
const return_qt = scope.findBlockReturnType();
|
|
1583
|
-
|
|
1584
|
-
rhs = try ZigTag.int_from_bool.create(t.arena, rhs);
|
|
1585
|
-
}
|
|
1586
|
-
return ZigTag.@"return".create(t.arena, rhs);
|
|
1727
|
+
return ZigTag.@"return".create(t.arena, try t.toNonBool(rhs, return_qt));
|
|
1587
1728
|
},
|
|
1588
1729
|
.implicit => |zero| {
|
|
1589
1730
|
if (zero) return ZigTag.@"return".create(t.arena, ZigTag.zero_literal.init());
|
|
@@ -1698,7 +1839,7 @@ fn transDoWhileStmt(t: *Translator, scope: *Scope, do_stmt: Node.DoWhileStmt) Tr
|
|
|
1698
1839
|
};
|
|
1699
1840
|
|
|
1700
1841
|
var body_node = try t.transStmt(&loop_scope, do_stmt.body);
|
|
1701
|
-
if (body_node.isNoreturn(
|
|
1842
|
+
if (body_node.isNoreturn()) {
|
|
1702
1843
|
// The body node ends in a noreturn statement. Simply put it in a while (true)
|
|
1703
1844
|
// in case it contains breaks or continues.
|
|
1704
1845
|
} else if (do_stmt.body.get(t.tree) == .compound_stmt) {
|
|
@@ -1918,8 +2059,6 @@ fn transSwitchProngStmt(
|
|
|
1918
2059
|
body: []const Node.Index,
|
|
1919
2060
|
) TransError!ZigNode {
|
|
1920
2061
|
switch (stmt.get(t.tree)) {
|
|
1921
|
-
.break_stmt => return ZigTag.@"break".init(),
|
|
1922
|
-
.return_stmt => return t.transStmt(scope, stmt),
|
|
1923
2062
|
.case_stmt, .default_stmt => unreachable,
|
|
1924
2063
|
else => {
|
|
1925
2064
|
var block_scope = try Scope.Block.init(t, scope, false);
|
|
@@ -1940,15 +2079,6 @@ fn transSwitchProngStmtInline(
|
|
|
1940
2079
|
) TransError!void {
|
|
1941
2080
|
for (body) |stmt| {
|
|
1942
2081
|
switch (stmt.get(t.tree)) {
|
|
1943
|
-
.return_stmt => {
|
|
1944
|
-
const result = try t.transStmt(&block.base, stmt);
|
|
1945
|
-
try block.statements.append(t.gpa, result);
|
|
1946
|
-
return;
|
|
1947
|
-
},
|
|
1948
|
-
.break_stmt => {
|
|
1949
|
-
try block.statements.append(t.gpa, ZigTag.@"break".init());
|
|
1950
|
-
return;
|
|
1951
|
-
},
|
|
1952
2082
|
.case_stmt => |case_stmt| {
|
|
1953
2083
|
var sub = case_stmt.body;
|
|
1954
2084
|
while (true) switch (sub.get(t.tree)) {
|
|
@@ -1959,7 +2089,7 @@ fn transSwitchProngStmtInline(
|
|
|
1959
2089
|
const result = try t.transStmt(&block.base, sub);
|
|
1960
2090
|
assert(result.tag() != .declaration);
|
|
1961
2091
|
try block.statements.append(t.gpa, result);
|
|
1962
|
-
if (result.isNoreturn(
|
|
2092
|
+
if (result.isNoreturn()) return;
|
|
1963
2093
|
},
|
|
1964
2094
|
.default_stmt => |default_stmt| {
|
|
1965
2095
|
var sub = default_stmt.body;
|
|
@@ -1971,18 +2101,16 @@ fn transSwitchProngStmtInline(
|
|
|
1971
2101
|
const result = try t.transStmt(&block.base, sub);
|
|
1972
2102
|
assert(result.tag() != .declaration);
|
|
1973
2103
|
try block.statements.append(t.gpa, result);
|
|
1974
|
-
if (result.isNoreturn(
|
|
1975
|
-
},
|
|
1976
|
-
.compound_stmt => |compound_stmt| {
|
|
1977
|
-
const result = try t.transCompoundStmt(&block.base, compound_stmt);
|
|
1978
|
-
try block.statements.append(t.gpa, result);
|
|
1979
|
-
if (result.isNoreturn(true)) return;
|
|
2104
|
+
if (result.isNoreturn()) return;
|
|
1980
2105
|
},
|
|
1981
2106
|
else => {
|
|
1982
2107
|
const result = try t.transStmt(&block.base, stmt);
|
|
1983
2108
|
switch (result.tag()) {
|
|
1984
2109
|
.declaration, .empty_block => {},
|
|
1985
|
-
else =>
|
|
2110
|
+
else => {
|
|
2111
|
+
try block.statements.append(t.gpa, result);
|
|
2112
|
+
if (result.isNoreturn()) return;
|
|
2113
|
+
},
|
|
1986
2114
|
}
|
|
1987
2115
|
},
|
|
1988
2116
|
}
|
|
@@ -2015,7 +2143,14 @@ fn transExpr(t: *Translator, scope: *Scope, expr: Node.Index, used: ResultUsed)
|
|
|
2015
2143
|
break :res try ZigTag.deref.create(t.arena, try t.transExpr(scope, deref_expr.operand, .used));
|
|
2016
2144
|
},
|
|
2017
2145
|
.bool_not_expr => |bool_not_expr| try ZigTag.not.create(t.arena, try t.transBoolExpr(scope, bool_not_expr.operand)),
|
|
2018
|
-
.bit_not_expr => |bit_not_expr| try ZigTag.bit_not.create(t.arena,
|
|
2146
|
+
.bit_not_expr => |bit_not_expr| try ZigTag.bit_not.create(t.arena, op: {
|
|
2147
|
+
const operand = try t.transExpr(scope, bit_not_expr.operand, .used);
|
|
2148
|
+
if (!operand.isBoolRes()) break :op operand;
|
|
2149
|
+
|
|
2150
|
+
const casted = try ZigTag.int_from_bool.create(t.arena, operand);
|
|
2151
|
+
const ty = try t.transType(scope, bit_not_expr.qt, bit_not_expr.op_tok);
|
|
2152
|
+
break :op try ZigTag.as.create(t.arena, .{ .lhs = ty, .rhs = casted });
|
|
2153
|
+
}),
|
|
2019
2154
|
.plus_expr => |plus_expr| return t.transExpr(scope, plus_expr.operand, used),
|
|
2020
2155
|
.negate_expr => |negate_expr| res: {
|
|
2021
2156
|
const operand_qt = negate_expr.operand.qt(t.tree);
|
|
@@ -2109,8 +2244,8 @@ fn transExpr(t: *Translator, scope: *Scope, expr: Node.Index, used: ResultUsed)
|
|
|
2109
2244
|
.shl_expr => |shl_expr| try t.transShiftExpr(scope, shl_expr, .shl),
|
|
2110
2245
|
.shr_expr => |shr_expr| try t.transShiftExpr(scope, shr_expr, .shr),
|
|
2111
2246
|
|
|
2112
|
-
.member_access_expr => |member_access| try t.transMemberAccess(scope, .normal, member_access, null),
|
|
2113
|
-
.member_access_ptr_expr => |member_access| try t.transMemberAccess(scope, .ptr, member_access, null),
|
|
2247
|
+
.member_access_expr => |member_access| try t.transMemberAccess(scope, .normal, member_access, null, .accessor),
|
|
2248
|
+
.member_access_ptr_expr => |member_access| try t.transMemberAccess(scope, .ptr, member_access, null, .accessor),
|
|
2114
2249
|
.array_access_expr => |array_access| try t.transArrayAccess(scope, array_access, null),
|
|
2115
2250
|
|
|
2116
2251
|
.builtin_ref => unreachable,
|
|
@@ -2195,6 +2330,10 @@ fn transExpr(t: *Translator, scope: *Scope, expr: Node.Index, used: ResultUsed)
|
|
|
2195
2330
|
.builtin_convertvector => |convertvector| try t.transConvertvectorExpr(scope, convertvector),
|
|
2196
2331
|
.builtin_shufflevector => |shufflevector| try t.transShufflevectorExpr(scope, shufflevector),
|
|
2197
2332
|
|
|
2333
|
+
.builtin_va_arg_pack, .builtin_va_arg_pack_len => |va_arg_pack| {
|
|
2334
|
+
return t.fail(error.UnsupportedTranslation, va_arg_pack.builtin_tok, "TODO va arg pack", .{});
|
|
2335
|
+
},
|
|
2336
|
+
|
|
2198
2337
|
.compound_stmt,
|
|
2199
2338
|
.static_assert,
|
|
2200
2339
|
.return_stmt,
|
|
@@ -2293,6 +2432,12 @@ fn transBoolExpr(t: *Translator, scope: *Scope, expr: Node.Index) TransError!Zig
|
|
|
2293
2432
|
return t.finishBoolExpr(expr.qt(t.tree), maybe_bool_res);
|
|
2294
2433
|
}
|
|
2295
2434
|
|
|
2435
|
+
fn toNonBool(t: *Translator, node: ZigNode, qt: QualType) Error!ZigNode {
|
|
2436
|
+
if (!node.isBoolRes()) return node;
|
|
2437
|
+
if (qt.is(t.comp, .bool)) return node;
|
|
2438
|
+
return ZigTag.int_from_bool.create(t.arena, node);
|
|
2439
|
+
}
|
|
2440
|
+
|
|
2296
2441
|
fn finishBoolExpr(t: *Translator, qt: QualType, node: ZigNode) TransError!ZigNode {
|
|
2297
2442
|
const sk = qt.scalarKind(t.comp);
|
|
2298
2443
|
if (sk == .bool) return node;
|
|
@@ -2385,8 +2530,22 @@ fn transCastExpr(
|
|
|
2385
2530
|
else => {},
|
|
2386
2531
|
}
|
|
2387
2532
|
|
|
2388
|
-
|
|
2389
|
-
|
|
2533
|
+
// Flexible array members are translated as member functions returning
|
|
2534
|
+
// [*c]T, so no address-of + @ptrCast wrapping is needed.
|
|
2535
|
+
flexible: {
|
|
2536
|
+
if (cast.operand.qt(t.tree).arrayLen(t.comp) == null) {
|
|
2537
|
+
return try t.transExpr(scope, cast.operand, used);
|
|
2538
|
+
}
|
|
2539
|
+
|
|
2540
|
+
const member_index, const base_qt = switch (cast.operand.get(t.tree)) {
|
|
2541
|
+
.member_access_expr => |ma| .{ ma.member_index, ma.base.qt(t.tree) },
|
|
2542
|
+
.member_access_ptr_expr => |ma| .{ ma.member_index, ma.base.qt(t.tree).childType(t.comp) },
|
|
2543
|
+
else => break :flexible,
|
|
2544
|
+
};
|
|
2545
|
+
const record = base_qt.getRecord(t.comp) orelse break :flexible;
|
|
2546
|
+
if (member_index != record.fields.len - 1 and base_qt.base(t.comp).type != .@"union") break :flexible;
|
|
2547
|
+
const array_ty = record.fields[member_index].qt.get(t.comp, .array) orelse break :flexible;
|
|
2548
|
+
if (t.isFlexibleArrayLen(array_ty.len)) return try t.transExpr(scope, cast.operand, used);
|
|
2390
2549
|
}
|
|
2391
2550
|
|
|
2392
2551
|
const sub_expr_node = try t.transExpr(scope, cast.operand, .used);
|
|
@@ -2402,6 +2561,8 @@ fn transCastExpr(
|
|
|
2402
2561
|
.lhs = try ZigTag.type.create(t.arena, "usize"),
|
|
2403
2562
|
.rhs = try ZigTag.int_cast.create(t.arena, sub_expr_node),
|
|
2404
2563
|
});
|
|
2564
|
+
} else if (sub_expr_node.isBoolRes()) {
|
|
2565
|
+
sub_expr_node = try ZigTag.int_from_bool.create(t.arena, sub_expr_node);
|
|
2405
2566
|
}
|
|
2406
2567
|
break :int_to_pointer try ZigTag.ptr_from_int.create(t.arena, sub_expr_node);
|
|
2407
2568
|
},
|
|
@@ -2560,6 +2721,8 @@ fn transPointerCastExpr(t: *Translator, scope: *Scope, expr: Node.Index) TransEr
|
|
|
2560
2721
|
}
|
|
2561
2722
|
|
|
2562
2723
|
fn transDeclRefExpr(t: *Translator, scope: *Scope, decl_ref: Node.DeclRef) TransError!ZigNode {
|
|
2724
|
+
if (t.wip_var_inits.contains(decl_ref.decl)) return error.SelfReferential;
|
|
2725
|
+
|
|
2563
2726
|
const name = t.tree.tokSlice(decl_ref.name_tok);
|
|
2564
2727
|
const maybe_alias = scope.getAlias(name);
|
|
2565
2728
|
const mangled_name = maybe_alias orelse name;
|
|
@@ -2631,7 +2794,7 @@ fn transShiftExpr(t: *Translator, scope: *Scope, bin: Node.Binary, op_id: ZigTag
|
|
|
2631
2794
|
// lhs >> @intCast(rh)
|
|
2632
2795
|
const lhs = try t.transExpr(scope, bin.lhs, .used);
|
|
2633
2796
|
|
|
2634
|
-
const rhs = try t.
|
|
2797
|
+
const rhs = try t.transExpr(scope, bin.rhs, .used);
|
|
2635
2798
|
const rhs_casted = try ZigTag.int_cast.create(t.arena, rhs);
|
|
2636
2799
|
|
|
2637
2800
|
return t.createBinOpNode(op_id, lhs, rhs_casted);
|
|
@@ -2758,7 +2921,7 @@ fn transCommaExpr(t: *Translator, scope: *Scope, bin: Node.Binary, used: ResultU
|
|
|
2758
2921
|
const rhs = try t.transExprCoercing(&block_scope.base, bin.rhs, .used);
|
|
2759
2922
|
const break_node = try ZigTag.break_val.create(t.arena, .{
|
|
2760
2923
|
.label = block_scope.label,
|
|
2761
|
-
.val = rhs,
|
|
2924
|
+
.val = try t.toNonBool(rhs, bin.qt),
|
|
2762
2925
|
});
|
|
2763
2926
|
try block_scope.statements.append(t.gpa, break_node);
|
|
2764
2927
|
|
|
@@ -2768,14 +2931,10 @@ fn transCommaExpr(t: *Translator, scope: *Scope, bin: Node.Binary, used: ResultU
|
|
|
2768
2931
|
fn transAssignExpr(t: *Translator, scope: *Scope, bin: Node.Binary, used: ResultUsed) !ZigNode {
|
|
2769
2932
|
if (used == .unused) {
|
|
2770
2933
|
const lhs = try t.transExpr(scope, bin.lhs, .used);
|
|
2771
|
-
|
|
2934
|
+
const rhs = try t.transExprCoercing(scope, bin.rhs, .used);
|
|
2772
2935
|
|
|
2773
2936
|
const lhs_qt = bin.lhs.qt(t.tree);
|
|
2774
|
-
|
|
2775
|
-
rhs = try ZigTag.int_from_bool.create(t.arena, rhs);
|
|
2776
|
-
}
|
|
2777
|
-
|
|
2778
|
-
return t.createBinOpNode(.assign, lhs, rhs);
|
|
2937
|
+
return t.createBinOpNode(.assign, lhs, try t.toNonBool(rhs, lhs_qt));
|
|
2779
2938
|
}
|
|
2780
2939
|
|
|
2781
2940
|
var block_scope = try Scope.Block.init(t, scope, true);
|
|
@@ -2783,13 +2942,12 @@ fn transAssignExpr(t: *Translator, scope: *Scope, bin: Node.Binary, used: Result
|
|
|
2783
2942
|
|
|
2784
2943
|
const tmp = try block_scope.reserveMangledName("tmp");
|
|
2785
2944
|
|
|
2786
|
-
|
|
2945
|
+
const rhs = try t.transExpr(&block_scope.base, bin.rhs, .used);
|
|
2787
2946
|
const lhs_qt = bin.lhs.qt(t.tree);
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
const tmp_decl = try ZigTag.var_simple.create(t.arena, .{ .name = tmp, .init = rhs });
|
|
2947
|
+
const tmp_decl = try ZigTag.var_simple.create(t.arena, .{
|
|
2948
|
+
.name = tmp,
|
|
2949
|
+
.init = try t.toNonBool(rhs, lhs_qt),
|
|
2950
|
+
});
|
|
2793
2951
|
try block_scope.statements.append(t.gpa, tmp_decl);
|
|
2794
2952
|
|
|
2795
2953
|
const lhs = try t.transExprCoercing(&block_scope.base, bin.lhs, .used);
|
|
@@ -3040,6 +3198,7 @@ fn transMemberAccess(
|
|
|
3040
3198
|
kind: enum { normal, ptr },
|
|
3041
3199
|
member_access: Node.MemberAccess,
|
|
3042
3200
|
opt_base: ?ZigNode,
|
|
3201
|
+
flex_array_mode: enum { accessor, backing },
|
|
3043
3202
|
) TransError!ZigNode {
|
|
3044
3203
|
const base_info = switch (kind) {
|
|
3045
3204
|
.normal => member_access.base.qt(t.tree),
|
|
@@ -3068,8 +3227,14 @@ fn transMemberAccess(
|
|
|
3068
3227
|
// Flexible array members are translated as member functions.
|
|
3069
3228
|
if (member_access.member_index == record.fields.len - 1 or base_info.base(t.comp).type == .@"union") {
|
|
3070
3229
|
if (field.qt.get(t.comp, .array)) |array_ty| {
|
|
3071
|
-
if (
|
|
3072
|
-
|
|
3230
|
+
if (t.isFlexibleArrayLen(array_ty.len)) {
|
|
3231
|
+
switch (flex_array_mode) {
|
|
3232
|
+
.accessor => return ZigTag.call.create(t.arena, .{ .lhs = field_access, .args = &.{} }),
|
|
3233
|
+
.backing => {
|
|
3234
|
+
const backing_name = try std.fmt.allocPrint(t.arena, "_{s}", .{field_name});
|
|
3235
|
+
return ZigTag.field_access.create(t.arena, .{ .lhs = lhs, .field_name = backing_name });
|
|
3236
|
+
},
|
|
3237
|
+
}
|
|
3073
3238
|
}
|
|
3074
3239
|
}
|
|
3075
3240
|
}
|
|
@@ -3091,7 +3256,7 @@ fn transArrayAccess(t: *Translator, scope: *Scope, array_access: Node.ArrayAcces
|
|
|
3091
3256
|
const index = index: {
|
|
3092
3257
|
const index = try t.transExpr(scope, array_access.index, .used);
|
|
3093
3258
|
const index_qt = array_access.index.qt(t.tree);
|
|
3094
|
-
const maybe_bigger_than_usize = switch (index_qt.base(t.comp).type) {
|
|
3259
|
+
const maybe_bigger_than_usize = type: switch (index_qt.base(t.comp).type) {
|
|
3095
3260
|
.bool => {
|
|
3096
3261
|
break :index try ZigTag.int_from_bool.create(t.arena, index);
|
|
3097
3262
|
},
|
|
@@ -3100,6 +3265,7 @@ fn transArrayAccess(t: *Translator, scope: *Scope, array_access: Node.ArrayAcces
|
|
|
3100
3265
|
else => false,
|
|
3101
3266
|
},
|
|
3102
3267
|
.bit_int => |bit_int| bit_int.bits > t.comp.target.ptrBitWidth(),
|
|
3268
|
+
.@"enum" => |e| if (e.tag) |tag| continue :type tag.base(t.comp).type else false,
|
|
3103
3269
|
else => unreachable,
|
|
3104
3270
|
};
|
|
3105
3271
|
|
|
@@ -3158,7 +3324,10 @@ fn transMemberDesignator(t: *Translator, scope: *Scope, arg: Node.Index) TransEr
|
|
|
3158
3324
|
},
|
|
3159
3325
|
.member_access_expr => |access| {
|
|
3160
3326
|
const base = try t.transMemberDesignator(scope, access.base);
|
|
3161
|
-
|
|
3327
|
+
// In offsetof context, flexible array members must be accessed via
|
|
3328
|
+
// the backing field (`_name`) rather than the accessor function,
|
|
3329
|
+
// because you can't take the address of a function call result.
|
|
3330
|
+
return t.transMemberAccess(scope, .normal, access, base, .backing);
|
|
3162
3331
|
},
|
|
3163
3332
|
.cast => |cast| {
|
|
3164
3333
|
assert(cast.kind == .array_to_pointer);
|
|
@@ -3292,6 +3461,51 @@ fn transCall(
|
|
|
3292
3461
|
|
|
3293
3462
|
const SuppressCast = enum { with_as, no_as };
|
|
3294
3463
|
|
|
3464
|
+
/// Attempt to translate literal as the name of the simple macro
|
|
3465
|
+
/// it was expanded from.
|
|
3466
|
+
fn checkLiteralMacro(t: *Translator, tok: TokenIndex, used: ResultUsed) !?ZigNode {
|
|
3467
|
+
if (!t.keep_macro_literals) return null;
|
|
3468
|
+
const expansion_locs = t.pp.expansionSlice(tok);
|
|
3469
|
+
if (expansion_locs.len == 0) return null;
|
|
3470
|
+
|
|
3471
|
+
const last_expand = expansion_locs[0];
|
|
3472
|
+
const source = t.comp.getSource(last_expand.id);
|
|
3473
|
+
var tokenizer: aro.Tokenizer = .{
|
|
3474
|
+
.buf = source.buf,
|
|
3475
|
+
.langopts = t.comp.langopts,
|
|
3476
|
+
.source = last_expand.id,
|
|
3477
|
+
.index = last_expand.byte_offset,
|
|
3478
|
+
.splice_locs = &.{},
|
|
3479
|
+
};
|
|
3480
|
+
const name_tok = tokenizer.next();
|
|
3481
|
+
if (!name_tok.id.isMacroIdentifier()) return null;
|
|
3482
|
+
|
|
3483
|
+
const name = t.pp.tokSlice(name_tok);
|
|
3484
|
+
if (t.global_scope.containsNow(name)) return null;
|
|
3485
|
+
const macro = t.pp.defines.get(name) orelse return null;
|
|
3486
|
+
if (macro.is_func) return null;
|
|
3487
|
+
if (macro.isBuiltin()) return null;
|
|
3488
|
+
|
|
3489
|
+
var tok_count: u8 = 0;
|
|
3490
|
+
for (macro.tokens) |macro_tok| {
|
|
3491
|
+
switch (macro_tok.id) {
|
|
3492
|
+
.invalid => continue,
|
|
3493
|
+
.whitespace => continue,
|
|
3494
|
+
.comment => continue,
|
|
3495
|
+
.macro_ws => continue,
|
|
3496
|
+
else => {
|
|
3497
|
+
if (tok_count != 0) return null;
|
|
3498
|
+
tok_count += 1;
|
|
3499
|
+
},
|
|
3500
|
+
}
|
|
3501
|
+
}
|
|
3502
|
+
|
|
3503
|
+
if (t.checkTranslatableMacro(macro.tokens, macro.params) != null) return null;
|
|
3504
|
+
|
|
3505
|
+
const ident = try ZigTag.identifier.create(t.arena, name);
|
|
3506
|
+
return try t.maybeSuppressResult(used, ident);
|
|
3507
|
+
}
|
|
3508
|
+
|
|
3295
3509
|
fn transIntLiteral(
|
|
3296
3510
|
t: *Translator,
|
|
3297
3511
|
scope: *Scope,
|
|
@@ -3299,6 +3513,7 @@ fn transIntLiteral(
|
|
|
3299
3513
|
used: ResultUsed,
|
|
3300
3514
|
suppress_as: SuppressCast,
|
|
3301
3515
|
) TransError!ZigNode {
|
|
3516
|
+
if (try t.checkLiteralMacro(literal_index.tok(t.tree), used)) |node| return node;
|
|
3302
3517
|
const val = t.tree.value_map.get(literal_index).?;
|
|
3303
3518
|
const int_lit_node = try t.createIntNode(val);
|
|
3304
3519
|
if (suppress_as == .no_as) {
|
|
@@ -3325,6 +3540,7 @@ fn transCharLiteral(
|
|
|
3325
3540
|
used: ResultUsed,
|
|
3326
3541
|
suppress_as: SuppressCast,
|
|
3327
3542
|
) TransError!ZigNode {
|
|
3543
|
+
if (try t.checkLiteralMacro(literal_index.tok(t.tree), used)) |node| return node;
|
|
3328
3544
|
const val = t.tree.value_map.get(literal_index).?;
|
|
3329
3545
|
const char_literal = literal_index.get(t.tree).char_literal;
|
|
3330
3546
|
const narrow = char_literal.kind == .ascii or char_literal.kind == .utf8;
|
|
@@ -3333,7 +3549,7 @@ fn transCharLiteral(
|
|
|
3333
3549
|
// e.g. 'abcd'
|
|
3334
3550
|
const int_value = val.toInt(u32, t.comp).?;
|
|
3335
3551
|
const int_lit_node = if (char_literal.kind == .ascii and int_value > 255)
|
|
3336
|
-
try t.createNumberNode(int_value
|
|
3552
|
+
try t.createNumberNode(int_value)
|
|
3337
3553
|
else
|
|
3338
3554
|
try t.createCharLiteralNode(narrow, int_value);
|
|
3339
3555
|
|
|
@@ -3357,12 +3573,16 @@ fn transFloatLiteral(
|
|
|
3357
3573
|
used: ResultUsed,
|
|
3358
3574
|
suppress_as: SuppressCast,
|
|
3359
3575
|
) TransError!ZigNode {
|
|
3576
|
+
if (try t.checkLiteralMacro(literal_index.tok(t.tree), used)) |node| return node;
|
|
3360
3577
|
const val = t.tree.value_map.get(literal_index).?;
|
|
3361
3578
|
const float_literal = literal_index.get(t.tree).float_literal;
|
|
3362
3579
|
|
|
3363
3580
|
var allocating: std.Io.Writer.Allocating = .init(t.gpa);
|
|
3364
3581
|
defer allocating.deinit();
|
|
3365
3582
|
_ = val.print(float_literal.qt, t.comp, &allocating.writer) catch return error.OutOfMemory;
|
|
3583
|
+
if (mem.findScalar(u8, allocating.written(), '.') == null) {
|
|
3584
|
+
allocating.writer.writeAll(".0") catch return error.OutOfMemory;
|
|
3585
|
+
}
|
|
3366
3586
|
|
|
3367
3587
|
const float_lit_node = try ZigTag.float_literal.create(t.arena, try t.arena.dupe(u8, allocating.written()));
|
|
3368
3588
|
if (suppress_as == .no_as) {
|
|
@@ -3588,7 +3808,7 @@ fn transArrayInit(
|
|
|
3588
3808
|
while (i < array_init.items.len) : (i += 1) {
|
|
3589
3809
|
if (array_init.items[i].get(t.tree) == .array_filler_expr) break;
|
|
3590
3810
|
const expr = try t.transExprCoercing(scope, array_init.items[i], .used);
|
|
3591
|
-
try val_list.append(t.gpa, expr);
|
|
3811
|
+
try val_list.append(t.gpa, try t.toNonBool(expr, array_item_qt));
|
|
3592
3812
|
}
|
|
3593
3813
|
const array_type = try ZigTag.array_type.create(t.arena, .{
|
|
3594
3814
|
.elem_type = array_item_type,
|
|
@@ -3638,7 +3858,7 @@ fn transUnionInit(
|
|
|
3638
3858
|
const field_init = try t.arena.create(ast.Payload.ContainerInit.Initializer);
|
|
3639
3859
|
field_init.* = .{
|
|
3640
3860
|
.name = field_name,
|
|
3641
|
-
.value = try t.transExprCoercing(scope, init_expr, .used),
|
|
3861
|
+
.value = try t.toNonBool(try t.transExprCoercing(scope, init_expr, .used), field.qt),
|
|
3642
3862
|
};
|
|
3643
3863
|
const container_init = try ZigTag.container_init.create(t.arena, .{
|
|
3644
3864
|
.lhs = union_type,
|
|
@@ -3669,7 +3889,7 @@ fn transStructInit(
|
|
|
3669
3889
|
}).? else field.name.lookup(t.comp);
|
|
3670
3890
|
init.* = .{
|
|
3671
3891
|
.name = field_name,
|
|
3672
|
-
.value = try t.transExprCoercing(scope, field_expr, .used),
|
|
3892
|
+
.value = try t.toNonBool(try t.transExprCoercing(scope, field_expr, .used), field.qt),
|
|
3673
3893
|
};
|
|
3674
3894
|
}
|
|
3675
3895
|
|
|
@@ -3766,7 +3986,7 @@ fn transConvertvectorExpr(
|
|
|
3766
3986
|
for (items, 0..dest_vec_ty.len) |*item, i| {
|
|
3767
3987
|
const value = try ZigTag.array_access.create(t.arena, .{
|
|
3768
3988
|
.lhs = tmp_ident,
|
|
3769
|
-
.rhs = try t.createNumberNode(i
|
|
3989
|
+
.rhs = try t.createNumberNode(i),
|
|
3770
3990
|
});
|
|
3771
3991
|
|
|
3772
3992
|
if (src_elem_sk == .float and dest_elem_sk == .float) {
|
|
@@ -3812,7 +4032,7 @@ fn transShufflevectorExpr(
|
|
|
3812
4032
|
const mask_len = shufflevector.indexes.len;
|
|
3813
4033
|
|
|
3814
4034
|
const mask_type = try ZigTag.vector.create(t.arena, .{
|
|
3815
|
-
.lhs = try t.createNumberNode(mask_len
|
|
4035
|
+
.lhs = try t.createNumberNode(mask_len),
|
|
3816
4036
|
.rhs = try ZigTag.type.create(t.arena, "i32"),
|
|
3817
4037
|
});
|
|
3818
4038
|
|
|
@@ -3882,16 +4102,9 @@ fn createIntNode(t: *Translator, int: aro.Value) !ZigNode {
|
|
|
3882
4102
|
return res;
|
|
3883
4103
|
}
|
|
3884
4104
|
|
|
3885
|
-
fn createNumberNode(t: *Translator, num: anytype
|
|
3886
|
-
const
|
|
3887
|
-
|
|
3888
|
-
else => "{s}",
|
|
3889
|
-
};
|
|
3890
|
-
const str = try std.fmt.allocPrint(t.arena, fmt_s, .{num});
|
|
3891
|
-
if (num_kind == .float)
|
|
3892
|
-
return ZigTag.float_literal.create(t.arena, str)
|
|
3893
|
-
else
|
|
3894
|
-
return ZigTag.integer_literal.create(t.arena, str);
|
|
4105
|
+
fn createNumberNode(t: *Translator, num: anytype) !ZigNode {
|
|
4106
|
+
const str = try std.fmt.allocPrint(t.arena, "{d}", .{num});
|
|
4107
|
+
return ZigTag.integer_literal.create(t.arena, str);
|
|
3895
4108
|
}
|
|
3896
4109
|
|
|
3897
4110
|
fn createCharLiteralNode(t: *Translator, narrow: bool, val: u32) TransError!ZigNode {
|
|
@@ -3953,6 +4166,25 @@ fn vectorTypeInfo(t: *Translator, vec_node: ZigNode, field: []const u8) TransErr
|
|
|
3953
4166
|
return ZigTag.field_access.create(t.arena, .{ .lhs = vector_type_info, .field_name = field });
|
|
3954
4167
|
}
|
|
3955
4168
|
|
|
4169
|
+
/// Returns true if the given array length qualifies as a flexible array member
|
|
4170
|
+
/// under the current -fstrict-flex-arrays level.
|
|
4171
|
+
fn isFlexibleArrayLen(t: *const Translator, len: anytype) bool {
|
|
4172
|
+
return switch (t.strict_flex_arrays) {
|
|
4173
|
+
.@"0" => true,
|
|
4174
|
+
.@"1" => switch (len) {
|
|
4175
|
+
.incomplete => true,
|
|
4176
|
+
.fixed => |n| n <= 1,
|
|
4177
|
+
else => false,
|
|
4178
|
+
},
|
|
4179
|
+
.@"2" => switch (len) {
|
|
4180
|
+
.incomplete => true,
|
|
4181
|
+
.fixed => |n| n == 0,
|
|
4182
|
+
else => false,
|
|
4183
|
+
},
|
|
4184
|
+
.@"3" => len == .incomplete,
|
|
4185
|
+
};
|
|
4186
|
+
}
|
|
4187
|
+
|
|
3956
4188
|
/// Build a getter function for a flexible array field in a C record
|
|
3957
4189
|
/// e.g. `T items[]` or `T items[0]`. The generated function returns a [*c] pointer
|
|
3958
4190
|
/// to the flexible array with the correct const and volatile qualifiers
|
|
@@ -3961,7 +4193,13 @@ fn createFlexibleMemberFn(
|
|
|
3961
4193
|
member_name: []const u8,
|
|
3962
4194
|
field_name: []const u8,
|
|
3963
4195
|
) Error!ZigNode {
|
|
3964
|
-
|
|
4196
|
+
// Use `_self` instead of the conventional `self` to avoid the Zig error
|
|
4197
|
+
// "function parameter shadows declaration of 'self'".
|
|
4198
|
+
// `processContainerMemberFns` merges C functions matching a struct's name
|
|
4199
|
+
// prefix into the struct as `pub const` aliases (e.g. `foo_self()` becomes
|
|
4200
|
+
// `pub const self = __root.foo_self`). A parameter also named `self` would
|
|
4201
|
+
// then shadow that declaration, which Zig rejects.
|
|
4202
|
+
const self_param_name = "_self";
|
|
3965
4203
|
const self_param = try ZigTag.identifier.create(t.arena, self_param_name);
|
|
3966
4204
|
const self_type = try ZigTag.typeof.create(t.arena, self_param);
|
|
3967
4205
|
|