authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-06 15:49:47-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2019-12-06 15:49:47-05:00
log525b1e8fb4abc38143a6ae47272fd5d016ba7eeb
treeee16b05de3828936971df6d977e75d5825b10547
parentd28aa38db71a861fd2036efbb22e57c1d34a5615
parent656cc33f8d49cb5e79cd3f9f8f56963747d43ed6
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #3856 from ziglang/builtin-call

introduce `@call` and remove other builtin calls

35 files changed, 995 insertions(+), 445 deletions(-)

doc/langref.html.in+93-86
...@@ -6839,6 +6839,99 @@ async fn func(y: *i32) void {...@@ -6839,6 +6839,99 @@ async fn func(y: *i32) void {
6839 </p>6839 </p>
6840 {#header_close#}6840 {#header_close#}
68416841
6842 {#header_open|@call#}
6843 <pre>{#syntax#}@call(options: std.builtin.CallOptions, function: var, args: var) var{#endsyntax#}</pre>
6844 <p>
6845 Calls a function, in the same way that invoking an expression with parentheses does:
6846 </p>
6847 {#code_begin|test|call#}
6848const assert = @import("std").debug.assert;
6849
6850test "noinline function call" {
6851 assert(@call(.{}, add, .{3, 9}) == 12);
6852}
6853
6854fn add(a: i32, b: i32) i32 {
6855 return a + b;
6856}
6857 {#code_end#}
6858 <p>
6859 {#syntax#}@call{#endsyntax#} allows more flexibility than normal function call syntax does. The
6860 {#syntax#}CallOptions{#endsyntax#} struct is reproduced here:
6861 </p>
6862 {#code_begin|syntax#}
6863pub const CallOptions = struct {
6864 modifier: Modifier = .auto,
6865 stack: ?[]align(std.Target.stack_align) u8 = null,
6866
6867 pub const Modifier = enum {
6868 /// Equivalent to function call syntax.
6869 auto,
6870
6871 /// Prevents tail call optimization. This guarantees that the return
6872 /// address will point to the callsite, as opposed to the callsite's
6873 /// callsite. If the call is otherwise required to be tail-called
6874 /// or inlined, a compile error is emitted instead.
6875 never_tail,
6876
6877 /// Guarantees that the call will not be inlined. If the call is
6878 /// otherwise required to be inlined, a compile error is emitted instead.
6879 never_inline,
6880
6881 /// Asserts that the function call will not suspend. This allows a
6882 /// non-async function to call an async function.
6883 no_async,
6884
6885 /// Guarantees that the call will be generated with tail call optimization.
6886 /// If this is not possible, a compile error is emitted instead.
6887 always_tail,
6888
6889 /// Guarantees that the call will inlined at the callsite.
6890 /// If this is not possible, a compile error is emitted instead.
6891 always_inline,
6892
6893 /// Evaluates the call at compile-time. If the call cannot be completed at
6894 /// compile-time, a compile error is emitted instead.
6895 compile_time,
6896 };
6897};
6898 {#code_end#}
6899
6900 {#header_open|Calling with a New Stack#}
6901 <p>
6902 When the {#syntax#}stack{#endsyntax#} option is provided, instead of using the same stack as the caller, the function uses the provided stack.
6903 </p>
6904 {#code_begin|test|new_stack_call#}
6905const std = @import("std");
6906const assert = std.debug.assert;
6907
6908var new_stack_bytes: [1024]u8 align(16) = undefined;
6909
6910test "calling a function with a new stack" {
6911 const arg = 1234;
6912
6913 const a = @call(.{.stack = new_stack_bytes[0..512]}, targetFunction, .{arg});
6914 const b = @call(.{.stack = new_stack_bytes[512..]}, targetFunction, .{arg});
6915 _ = targetFunction(arg);
6916
6917 assert(arg == 1234);
6918 assert(a < b);
6919}
6920
6921fn targetFunction(x: i32) usize {
6922 assert(x == 1234);
6923
6924 var local_variable: i32 = 42;
6925 const ptr = &local_variable;
6926 ptr.* += 1;
6927
6928 assert(local_variable == 43);
6929 return @ptrToInt(ptr);
6930}
6931 {#code_end#}
6932 {#header_close#}
6933 {#header_close#}
6934
6842 {#header_open|@cDefine#}6935 {#header_open|@cDefine#}
6843 <pre>{#syntax#}@cDefine(comptime name: []u8, value){#endsyntax#}</pre>6936 <pre>{#syntax#}@cDefine(comptime name: []u8, value){#endsyntax#}</pre>
6844 <p>6937 <p>
...@@ -7424,27 +7517,6 @@ test "@hasDecl" {...@@ -7424,27 +7517,6 @@ test "@hasDecl" {
7424 {#see_also|Compile Variables|@embedFile#}7517 {#see_also|Compile Variables|@embedFile#}
7425 {#header_close#}7518 {#header_close#}
74267519
7427 {#header_open|@inlineCall#}
7428 <pre>{#syntax#}@inlineCall(function: X, args: ...) Y{#endsyntax#}</pre>
7429 <p>
7430 This calls a function, in the same way that invoking an expression with parentheses does:
7431 </p>
7432 {#code_begin|test#}
7433const assert = @import("std").debug.assert;
7434
7435test "inline function call" {
7436 assert(@inlineCall(add, 3, 9) == 12);
7437}
7438
7439fn add(a: i32, b: i32) i32 { return a + b; }
7440 {#code_end#}
7441 <p>
7442 Unlike a normal function call, however, {#syntax#}@inlineCall{#endsyntax#} guarantees that the call
7443 will be inlined. If the call cannot be inlined, a compile error is emitted.
7444 </p>
7445 {#see_also|@noInlineCall#}
7446 {#header_close#}
7447
7448 {#header_open|@intCast#}7520 {#header_open|@intCast#}
7449 <pre>{#syntax#}@intCast(comptime DestType: type, int: var) DestType{#endsyntax#}</pre>7521 <pre>{#syntax#}@intCast(comptime DestType: type, int: var) DestType{#endsyntax#}</pre>
7450 <p>7522 <p>
...@@ -7602,71 +7674,6 @@ mem.set(u8, dest, c);{#endsyntax#}</pre>...@@ -7602,71 +7674,6 @@ mem.set(u8, dest, c);{#endsyntax#}</pre>
7602 </p>7674 </p>
7603 {#header_close#}7675 {#header_close#}
76047676
7605 {#header_open|@newStackCall#}
7606 <pre>{#syntax#}@newStackCall(new_stack: []align(target_stack_align) u8, function: var, args: ...) var{#endsyntax#}</pre>
7607 <p>
7608 This calls a function, in the same way that invoking an expression with parentheses does. However,
7609 instead of using the same stack as the caller, the function uses the stack provided in the {#syntax#}new_stack{#endsyntax#}
7610 parameter.
7611 </p>
7612 <p>
7613 The new stack must be aligned to {#syntax#}target_stack_align{#endsyntax#} bytes. This is a target-specific
7614 number. A safe value that will work on all targets is {#syntax#}16{#endsyntax#}. This value can
7615 also be obtained by using {#link|@sizeOf#} on the {#link|@Frame#} type of {#link|Async Functions#}.
7616 </p>
7617 {#code_begin|test#}
7618const std = @import("std");
7619const assert = std.debug.assert;
7620
7621var new_stack_bytes: [1024]u8 align(16) = undefined;
7622
7623test "calling a function with a new stack" {
7624 const arg = 1234;
7625
7626 const a = @newStackCall(new_stack_bytes[0..512], targetFunction, arg);
7627 const b = @newStackCall(new_stack_bytes[512..], targetFunction, arg);
7628 _ = targetFunction(arg);
7629
7630 assert(arg == 1234);
7631 assert(a < b);
7632}
7633
7634fn targetFunction(x: i32) usize {
7635 assert(x == 1234);
7636
7637 var local_variable: i32 = 42;
7638 const ptr = &local_variable;
7639 ptr.* += 1;
7640
7641 assert(local_variable == 43);
7642 return @ptrToInt(ptr);
7643}
7644 {#code_end#}
7645 {#header_close#}
7646
7647 {#header_open|@noInlineCall#}
7648 <pre>{#syntax#}@noInlineCall(function: var, args: ...) var{#endsyntax#}</pre>
7649 <p>
7650 This calls a function, in the same way that invoking an expression with parentheses does:
7651 </p>
7652 {#code_begin|test#}
7653const assert = @import("std").debug.assert;
7654
7655test "noinline function call" {
7656 assert(@noInlineCall(add, 3, 9) == 12);
7657}
7658
7659fn add(a: i32, b: i32) i32 {
7660 return a + b;
7661}
7662 {#code_end#}
7663 <p>
7664 Unlike a normal function call, however, {#syntax#}@noInlineCall{#endsyntax#} guarantees that the call
7665 will not be inlined. If the call must be inlined, a compile error is emitted.
7666 </p>
7667 {#see_also|@inlineCall#}
7668 {#header_close#}
7669
7670 {#header_open|@OpaqueType#}7677 {#header_open|@OpaqueType#}
7671 <pre>{#syntax#}@OpaqueType() type{#endsyntax#}</pre>7678 <pre>{#syntax#}@OpaqueType() type{#endsyntax#}</pre>
7672 <p>7679 <p>
lib/std/builtin.zig+38
...@@ -372,6 +372,44 @@ pub const Version = struct {...@@ -372,6 +372,44 @@ pub const Version = struct {
372 patch: u32,372 patch: u32,
373};373};
374374
375/// This data structure is used by the Zig language code generation and
376/// therefore must be kept in sync with the compiler implementation.
377pub const CallOptions = struct {
378 modifier: Modifier = .auto,
379 stack: ?[]align(std.Target.stack_align) u8 = null,
380
381 pub const Modifier = enum {
382 /// Equivalent to function call syntax.
383 auto,
384
385 /// Prevents tail call optimization. This guarantees that the return
386 /// address will point to the callsite, as opposed to the callsite's
387 /// callsite. If the call is otherwise required to be tail-called
388 /// or inlined, a compile error is emitted instead.
389 never_tail,
390
391 /// Guarantees that the call will not be inlined. If the call is
392 /// otherwise required to be inlined, a compile error is emitted instead.
393 never_inline,
394
395 /// Asserts that the function call will not suspend. This allows a
396 /// non-async function to call an async function.
397 no_async,
398
399 /// Guarantees that the call will be generated with tail call optimization.
400 /// If this is not possible, a compile error is emitted instead.
401 always_tail,
402
403 /// Guarantees that the call will inlined at the callsite.
404 /// If this is not possible, a compile error is emitted instead.
405 always_inline,
406
407 /// Evaluates the call at compile-time. If the call cannot be completed at
408 /// compile-time, a compile error is emitted instead.
409 compile_time,
410 };
411};
412
375/// This function type is used by the Zig language code generation and413/// This function type is used by the Zig language code generation and
376/// therefore must be kept in sync with the compiler implementation.414/// therefore must be kept in sync with the compiler implementation.
377pub const PanicFn = fn ([]const u8, ?*StackTrace) noreturn;415pub const PanicFn = fn ([]const u8, ?*StackTrace) noreturn;
lib/std/hash/auto_hash.zig+2-2
...@@ -92,7 +92,7 @@ pub fn hash(hasher: var, key: var, comptime strat: HashStrategy) void {...@@ -92,7 +92,7 @@ pub fn hash(hasher: var, key: var, comptime strat: HashStrategy) void {
9292
93 // Help the optimizer see that hashing an int is easy by inlining!93 // Help the optimizer see that hashing an int is easy by inlining!
94 // TODO Check if the situation is better after #561 is resolved.94 // TODO Check if the situation is better after #561 is resolved.
95 .Int => @inlineCall(hasher.update, std.mem.asBytes(&key)),95 .Int => @call(.{ .modifier = .always_inline }, hasher.update, .{std.mem.asBytes(&key)}),
9696
97 .Float => |info| hash(hasher, @bitCast(@IntType(false, info.bits), key), strat),97 .Float => |info| hash(hasher, @bitCast(@IntType(false, info.bits), key), strat),
9898
...@@ -101,7 +101,7 @@ pub fn hash(hasher: var, key: var, comptime strat: HashStrategy) void {...@@ -101,7 +101,7 @@ pub fn hash(hasher: var, key: var, comptime strat: HashStrategy) void {
101 .ErrorSet => hash(hasher, @errorToInt(key), strat),101 .ErrorSet => hash(hasher, @errorToInt(key), strat),
102 .AnyFrame, .Fn => hash(hasher, @ptrToInt(key), strat),102 .AnyFrame, .Fn => hash(hasher, @ptrToInt(key), strat),
103103
104 .Pointer => @inlineCall(hashPointer, hasher, key, strat),104 .Pointer => @call(.{ .modifier = .always_inline }, hashPointer, .{ hasher, key, strat }),
105105
106 .Optional => if (key) |k| hash(hasher, k, strat),106 .Optional => if (key) |k| hash(hasher, k, strat),
107107
lib/std/hash/cityhash.zig+11-4
...@@ -197,7 +197,7 @@ pub const CityHash64 = struct {...@@ -197,7 +197,7 @@ pub const CityHash64 = struct {
197 }197 }
198198
199 fn hashLen16(u: u64, v: u64) u64 {199 fn hashLen16(u: u64, v: u64) u64 {
200 return @inlineCall(hash128To64, u, v);200 return @call(.{ .modifier = .always_inline }, hash128To64, .{ u, v });
201 }201 }
202202
203 fn hashLen16Mul(low: u64, high: u64, mul: u64) u64 {203 fn hashLen16Mul(low: u64, high: u64, mul: u64) u64 {
...@@ -210,7 +210,7 @@ pub const CityHash64 = struct {...@@ -210,7 +210,7 @@ pub const CityHash64 = struct {
210 }210 }
211211
212 fn hash128To64(low: u64, high: u64) u64 {212 fn hash128To64(low: u64, high: u64) u64 {
213 return @inlineCall(hashLen16Mul, low, high, 0x9ddfea08eb382d69);213 return @call(.{ .modifier = .always_inline }, hashLen16Mul, .{ low, high, 0x9ddfea08eb382d69 });
214 }214 }
215215
216 fn hashLen0To16(str: []const u8) u64 {216 fn hashLen0To16(str: []const u8) u64 {
...@@ -291,7 +291,14 @@ pub const CityHash64 = struct {...@@ -291,7 +291,14 @@ pub const CityHash64 = struct {
291 }291 }
292292
293 fn weakHashLen32WithSeeds(ptr: [*]const u8, a: u64, b: u64) WeakPair {293 fn weakHashLen32WithSeeds(ptr: [*]const u8, a: u64, b: u64) WeakPair {
294 return @inlineCall(weakHashLen32WithSeedsHelper, fetch64(ptr), fetch64(ptr + 8), fetch64(ptr + 16), fetch64(ptr + 24), a, b);294 return @call(.{ .modifier = .always_inline }, weakHashLen32WithSeedsHelper, .{
295 fetch64(ptr),
296 fetch64(ptr + 8),
297 fetch64(ptr + 16),
298 fetch64(ptr + 24),
299 a,
300 b,
301 });
295 }302 }
296303
297 pub fn hash(str: []const u8) u64 {304 pub fn hash(str: []const u8) u64 {
...@@ -339,7 +346,7 @@ pub const CityHash64 = struct {...@@ -339,7 +346,7 @@ pub const CityHash64 = struct {
339 }346 }
340347
341 pub fn hashWithSeed(str: []const u8, seed: u64) u64 {348 pub fn hashWithSeed(str: []const u8, seed: u64) u64 {
342 return @inlineCall(Self.hashWithSeeds, str, k2, seed);349 return @call(.{ .modifier = .always_inline }, Self.hashWithSeeds, .{ str, k2, seed });
343 }350 }
344351
345 pub fn hashWithSeeds(str: []const u8, seed0: u64, seed1: u64) u64 {352 pub fn hashWithSeeds(str: []const u8, seed0: u64, seed1: u64) u64 {
lib/std/hash/murmur.zig+9-9
...@@ -8,7 +8,7 @@ pub const Murmur2_32 = struct {...@@ -8,7 +8,7 @@ pub const Murmur2_32 = struct {
8 const Self = @This();8 const Self = @This();
99
10 pub fn hash(str: []const u8) u32 {10 pub fn hash(str: []const u8) u32 {
11 return @inlineCall(Self.hashWithSeed, str, default_seed);11 return @call(.{ .modifier = .always_inline }, Self.hashWithSeed, .{ str, default_seed });
12 }12 }
1313
14 pub fn hashWithSeed(str: []const u8, seed: u32) u32 {14 pub fn hashWithSeed(str: []const u8, seed: u32) u32 {
...@@ -44,7 +44,7 @@ pub const Murmur2_32 = struct {...@@ -44,7 +44,7 @@ pub const Murmur2_32 = struct {
44 }44 }
4545
46 pub fn hashUint32(v: u32) u32 {46 pub fn hashUint32(v: u32) u32 {
47 return @inlineCall(Self.hashUint32WithSeed, v, default_seed);47 return @call(.{ .modifier = .always_inline }, Self.hashUint32WithSeed, .{ v, default_seed });
48 }48 }
4949
50 pub fn hashUint32WithSeed(v: u32, seed: u32) u32 {50 pub fn hashUint32WithSeed(v: u32, seed: u32) u32 {
...@@ -64,7 +64,7 @@ pub const Murmur2_32 = struct {...@@ -64,7 +64,7 @@ pub const Murmur2_32 = struct {
64 }64 }
6565
66 pub fn hashUint64(v: u64) u32 {66 pub fn hashUint64(v: u64) u32 {
67 return @inlineCall(Self.hashUint64WithSeed, v, default_seed);67 return @call(.{ .modifier = .always_inline }, Self.hashUint64WithSeed, .{ v, default_seed });
68 }68 }
6969
70 pub fn hashUint64WithSeed(v: u64, seed: u32) u32 {70 pub fn hashUint64WithSeed(v: u64, seed: u32) u32 {
...@@ -93,7 +93,7 @@ pub const Murmur2_64 = struct {...@@ -93,7 +93,7 @@ pub const Murmur2_64 = struct {
93 const Self = @This();93 const Self = @This();
9494
95 pub fn hash(str: []const u8) u64 {95 pub fn hash(str: []const u8) u64 {
96 return @inlineCall(Self.hashWithSeed, str, default_seed);96 return @call(.{ .modifier = .always_inline }, Self.hashWithSeed, .{ str, default_seed });
97 }97 }
9898
99 pub fn hashWithSeed(str: []const u8, seed: u64) u64 {99 pub fn hashWithSeed(str: []const u8, seed: u64) u64 {
...@@ -127,7 +127,7 @@ pub const Murmur2_64 = struct {...@@ -127,7 +127,7 @@ pub const Murmur2_64 = struct {
127 }127 }
128128
129 pub fn hashUint32(v: u32) u64 {129 pub fn hashUint32(v: u32) u64 {
130 return @inlineCall(Self.hashUint32WithSeed, v, default_seed);130 return @call(.{ .modifier = .always_inline }, Self.hashUint32WithSeed, .{ v, default_seed });
131 }131 }
132132
133 pub fn hashUint32WithSeed(v: u32, seed: u32) u64 {133 pub fn hashUint32WithSeed(v: u32, seed: u32) u64 {
...@@ -144,7 +144,7 @@ pub const Murmur2_64 = struct {...@@ -144,7 +144,7 @@ pub const Murmur2_64 = struct {
144 }144 }
145145
146 pub fn hashUint64(v: u64) u64 {146 pub fn hashUint64(v: u64) u64 {
147 return @inlineCall(Self.hashUint64WithSeed, v, default_seed);147 return @call(.{ .modifier = .always_inline }, Self.hashUint64WithSeed, .{ v, default_seed });
148 }148 }
149149
150 pub fn hashUint64WithSeed(v: u64, seed: u32) u64 {150 pub fn hashUint64WithSeed(v: u64, seed: u32) u64 {
...@@ -172,7 +172,7 @@ pub const Murmur3_32 = struct {...@@ -172,7 +172,7 @@ pub const Murmur3_32 = struct {
172 }172 }
173173
174 pub fn hash(str: []const u8) u32 {174 pub fn hash(str: []const u8) u32 {
175 return @inlineCall(Self.hashWithSeed, str, default_seed);175 return @call(.{ .modifier = .always_inline }, Self.hashWithSeed, .{ str, default_seed });
176 }176 }
177177
178 pub fn hashWithSeed(str: []const u8, seed: u32) u32 {178 pub fn hashWithSeed(str: []const u8, seed: u32) u32 {
...@@ -220,7 +220,7 @@ pub const Murmur3_32 = struct {...@@ -220,7 +220,7 @@ pub const Murmur3_32 = struct {
220 }220 }
221221
222 pub fn hashUint32(v: u32) u32 {222 pub fn hashUint32(v: u32) u32 {
223 return @inlineCall(Self.hashUint32WithSeed, v, default_seed);223 return @call(.{ .modifier = .always_inline }, Self.hashUint32WithSeed, .{ v, default_seed });
224 }224 }
225225
226 pub fn hashUint32WithSeed(v: u32, seed: u32) u32 {226 pub fn hashUint32WithSeed(v: u32, seed: u32) u32 {
...@@ -246,7 +246,7 @@ pub const Murmur3_32 = struct {...@@ -246,7 +246,7 @@ pub const Murmur3_32 = struct {
246 }246 }
247247
248 pub fn hashUint64(v: u64) u32 {248 pub fn hashUint64(v: u64) u32 {
249 return @inlineCall(Self.hashUint64WithSeed, v, default_seed);249 return @call(.{ .modifier = .always_inline }, Self.hashUint64WithSeed, .{ v, default_seed });
250 }250 }
251251
252 pub fn hashUint64WithSeed(v: u64, seed: u32) u32 {252 pub fn hashUint64WithSeed(v: u64, seed: u32) u32 {
lib/std/hash/siphash.zig+12-7
...@@ -11,7 +11,7 @@ const testing = std.testing;...@@ -11,7 +11,7 @@ const testing = std.testing;
11const math = std.math;11const math = std.math;
12const mem = std.mem;12const mem = std.mem;
1313
14const Endian = @import("builtin").Endian;14const Endian = std.builtin.Endian;
1515
16pub fn SipHash64(comptime c_rounds: usize, comptime d_rounds: usize) type {16pub fn SipHash64(comptime c_rounds: usize, comptime d_rounds: usize) type {
17 return SipHash(u64, c_rounds, d_rounds);17 return SipHash(u64, c_rounds, d_rounds);
...@@ -62,7 +62,7 @@ fn SipHashStateless(comptime T: type, comptime c_rounds: usize, comptime d_round...@@ -62,7 +62,7 @@ fn SipHashStateless(comptime T: type, comptime c_rounds: usize, comptime d_round
6262
63 var off: usize = 0;63 var off: usize = 0;
64 while (off < b.len) : (off += 8) {64 while (off < b.len) : (off += 8) {
65 @inlineCall(self.round, b[off .. off + 8]);65 @call(.{ .modifier = .always_inline }, self.round, .{b[off .. off + 8]});
66 }66 }
6767
68 self.msg_len +%= @truncate(u8, b.len);68 self.msg_len +%= @truncate(u8, b.len);
...@@ -84,9 +84,12 @@ fn SipHashStateless(comptime T: type, comptime c_rounds: usize, comptime d_round...@@ -84,9 +84,12 @@ fn SipHashStateless(comptime T: type, comptime c_rounds: usize, comptime d_round
84 self.v2 ^= 0xff;84 self.v2 ^= 0xff;
85 }85 }
8686
87 // TODO this is a workaround, should be able to supply the value without a separate variable
88 const inl = std.builtin.CallOptions{ .modifier = .always_inline };
89
87 comptime var i: usize = 0;90 comptime var i: usize = 0;
88 inline while (i < d_rounds) : (i += 1) {91 inline while (i < d_rounds) : (i += 1) {
89 @inlineCall(sipRound, self);92 @call(inl, sipRound, .{self});
90 }93 }
9194
92 const b1 = self.v0 ^ self.v1 ^ self.v2 ^ self.v3;95 const b1 = self.v0 ^ self.v1 ^ self.v2 ^ self.v3;
...@@ -98,7 +101,7 @@ fn SipHashStateless(comptime T: type, comptime c_rounds: usize, comptime d_round...@@ -98,7 +101,7 @@ fn SipHashStateless(comptime T: type, comptime c_rounds: usize, comptime d_round
98101
99 comptime var j: usize = 0;102 comptime var j: usize = 0;
100 inline while (j < d_rounds) : (j += 1) {103 inline while (j < d_rounds) : (j += 1) {
101 @inlineCall(sipRound, self);104 @call(inl, sipRound, .{self});
102 }105 }
103106
104 const b2 = self.v0 ^ self.v1 ^ self.v2 ^ self.v3;107 const b2 = self.v0 ^ self.v1 ^ self.v2 ^ self.v3;
...@@ -111,9 +114,11 @@ fn SipHashStateless(comptime T: type, comptime c_rounds: usize, comptime d_round...@@ -111,9 +114,11 @@ fn SipHashStateless(comptime T: type, comptime c_rounds: usize, comptime d_round
111 const m = mem.readIntSliceLittle(u64, b[0..]);114 const m = mem.readIntSliceLittle(u64, b[0..]);
112 self.v3 ^= m;115 self.v3 ^= m;
113116
117 // TODO this is a workaround, should be able to supply the value without a separate variable
118 const inl = std.builtin.CallOptions{ .modifier = .always_inline };
114 comptime var i: usize = 0;119 comptime var i: usize = 0;
115 inline while (i < c_rounds) : (i += 1) {120 inline while (i < c_rounds) : (i += 1) {
116 @inlineCall(sipRound, self);121 @call(inl, sipRound, .{self});
117 }122 }
118123
119 self.v0 ^= m;124 self.v0 ^= m;
...@@ -140,8 +145,8 @@ fn SipHashStateless(comptime T: type, comptime c_rounds: usize, comptime d_round...@@ -140,8 +145,8 @@ fn SipHashStateless(comptime T: type, comptime c_rounds: usize, comptime d_round
140 const aligned_len = input.len - (input.len % 8);145 const aligned_len = input.len - (input.len % 8);
141146
142 var c = Self.init(key);147 var c = Self.init(key);
143 @inlineCall(c.update, input[0..aligned_len]);148 @call(.{ .modifier = .always_inline }, c.update, .{input[0..aligned_len]});
144 return @inlineCall(c.final, input[aligned_len..]);149 return @call(.{ .modifier = .always_inline }, c.final, .{input[aligned_len..]});
145 }150 }
146 };151 };
147}152}
lib/std/hash/wyhash.zig+3-3
...@@ -65,7 +65,7 @@ const WyhashStateless = struct {...@@ -65,7 +65,7 @@ const WyhashStateless = struct {
6565
66 var off: usize = 0;66 var off: usize = 0;
67 while (off < b.len) : (off += 32) {67 while (off < b.len) : (off += 32) {
68 @inlineCall(self.round, b[off .. off + 32]);68 @call(.{ .modifier = .always_inline }, self.round, .{b[off .. off + 32]});
69 }69 }
7070
71 self.msg_len += b.len;71 self.msg_len += b.len;
...@@ -121,8 +121,8 @@ const WyhashStateless = struct {...@@ -121,8 +121,8 @@ const WyhashStateless = struct {
121 const aligned_len = input.len - (input.len % 32);121 const aligned_len = input.len - (input.len % 32);
122122
123 var c = WyhashStateless.init(seed);123 var c = WyhashStateless.init(seed);
124 @inlineCall(c.update, input[0..aligned_len]);124 @call(.{ .modifier = .always_inline }, c.update, .{input[0..aligned_len]});
125 return @inlineCall(c.final, input[aligned_len..]);125 return @call(.{ .modifier = .always_inline }, c.final, .{input[aligned_len..]});
126 }126 }
127};127};
128128
lib/std/math/big/int.zig+11-3
...@@ -811,7 +811,7 @@ pub const Int = struct {...@@ -811,7 +811,7 @@ pub const Int = struct {
811811
812 var j: usize = 0;812 var j: usize = 0;
813 while (j < a_lo.len) : (j += 1) {813 while (j < a_lo.len) : (j += 1) {
814 a_lo[j] = @inlineCall(addMulLimbWithCarry, a_lo[j], y[j], xi, &carry);814 a_lo[j] = @call(.{ .modifier = .always_inline }, addMulLimbWithCarry, .{ a_lo[j], y[j], xi, &carry });
815 }815 }
816816
817 j = 0;817 j = 0;
...@@ -1214,7 +1214,11 @@ pub const Int = struct {...@@ -1214,7 +1214,11 @@ pub const Int = struct {
1214 const dst_i = src_i + limb_shift;1214 const dst_i = src_i + limb_shift;
12151215
1216 const src_digit = a[src_i];1216 const src_digit = a[src_i];
1217 r[dst_i] = carry | @inlineCall(math.shr, Limb, src_digit, Limb.bit_count - @intCast(Limb, interior_limb_shift));1217 r[dst_i] = carry | @call(.{ .modifier = .always_inline }, math.shr, .{
1218 Limb,
1219 src_digit,
1220 Limb.bit_count - @intCast(Limb, interior_limb_shift),
1221 });
1218 carry = (src_digit << interior_limb_shift);1222 carry = (src_digit << interior_limb_shift);
1219 }1223 }
12201224
...@@ -1254,7 +1258,11 @@ pub const Int = struct {...@@ -1254,7 +1258,11 @@ pub const Int = struct {
12541258
1255 const src_digit = a[src_i];1259 const src_digit = a[src_i];
1256 r[dst_i] = carry | (src_digit >> interior_limb_shift);1260 r[dst_i] = carry | (src_digit >> interior_limb_shift);
1257 carry = @inlineCall(math.shl, Limb, src_digit, Limb.bit_count - @intCast(Limb, interior_limb_shift));1261 carry = @call(.{ .modifier = .always_inline }, math.shl, .{
1262 Limb,
1263 src_digit,
1264 Limb.bit_count - @intCast(Limb, interior_limb_shift),
1265 });
1258 }1266 }
1259 }1267 }
12601268
lib/std/os/linux.zig+1-1
...@@ -94,7 +94,7 @@ pub fn fork() usize {...@@ -94,7 +94,7 @@ pub fn fork() usize {
94/// the compiler is not aware of how vfork affects control flow and you may94/// the compiler is not aware of how vfork affects control flow and you may
95/// see different results in optimized builds.95/// see different results in optimized builds.
96pub inline fn vfork() usize {96pub inline fn vfork() usize {
97 return @inlineCall(syscall0, SYS_vfork);97 return @call(.{ .modifier = .always_inline }, syscall0, .{SYS_vfork});
98}98}
9999
100pub fn futimens(fd: i32, times: *const [2]timespec) usize {100pub fn futimens(fd: i32, times: *const [2]timespec) usize {
lib/std/special/compiler_rt/arm/aeabi_dcmp.zig+5-5
...@@ -14,31 +14,31 @@ const ConditionalOperator = enum {...@@ -14,31 +14,31 @@ const ConditionalOperator = enum {
1414
15pub nakedcc fn __aeabi_dcmpeq() noreturn {15pub nakedcc fn __aeabi_dcmpeq() noreturn {
16 @setRuntimeSafety(false);16 @setRuntimeSafety(false);
17 @inlineCall(aeabi_dcmp, .Eq);17 @call(.{ .modifier = .always_inline }, aeabi_dcmp, .{.Eq});
18 unreachable;18 unreachable;
19}19}
2020
21pub nakedcc fn __aeabi_dcmplt() noreturn {21pub nakedcc fn __aeabi_dcmplt() noreturn {
22 @setRuntimeSafety(false);22 @setRuntimeSafety(false);
23 @inlineCall(aeabi_dcmp, .Lt);23 @call(.{ .modifier = .always_inline }, aeabi_dcmp, .{.Lt});
24 unreachable;24 unreachable;
25}25}
2626
27pub nakedcc fn __aeabi_dcmple() noreturn {27pub nakedcc fn __aeabi_dcmple() noreturn {
28 @setRuntimeSafety(false);28 @setRuntimeSafety(false);
29 @inlineCall(aeabi_dcmp, .Le);29 @call(.{ .modifier = .always_inline }, aeabi_dcmp, .{.Le});
30 unreachable;30 unreachable;
31}31}
3232
33pub nakedcc fn __aeabi_dcmpge() noreturn {33pub nakedcc fn __aeabi_dcmpge() noreturn {
34 @setRuntimeSafety(false);34 @setRuntimeSafety(false);
35 @inlineCall(aeabi_dcmp, .Ge);35 @call(.{ .modifier = .always_inline }, aeabi_dcmp, .{.Ge});
36 unreachable;36 unreachable;
37}37}
3838
39pub nakedcc fn __aeabi_dcmpgt() noreturn {39pub nakedcc fn __aeabi_dcmpgt() noreturn {
40 @setRuntimeSafety(false);40 @setRuntimeSafety(false);
41 @inlineCall(aeabi_dcmp, .Gt);41 @call(.{ .modifier = .always_inline }, aeabi_dcmp, .{.Gt});
42 unreachable;42 unreachable;
43}43}
4444
lib/std/special/compiler_rt/arm/aeabi_fcmp.zig+5-5
...@@ -14,31 +14,31 @@ const ConditionalOperator = enum {...@@ -14,31 +14,31 @@ const ConditionalOperator = enum {
1414
15pub nakedcc fn __aeabi_fcmpeq() noreturn {15pub nakedcc fn __aeabi_fcmpeq() noreturn {
16 @setRuntimeSafety(false);16 @setRuntimeSafety(false);
17 @inlineCall(aeabi_fcmp, .Eq);17 @call(.{ .modifier = .always_inline }, aeabi_fcmp, .{.Eq});
18 unreachable;18 unreachable;
19}19}
2020
21pub nakedcc fn __aeabi_fcmplt() noreturn {21pub nakedcc fn __aeabi_fcmplt() noreturn {
22 @setRuntimeSafety(false);22 @setRuntimeSafety(false);
23 @inlineCall(aeabi_fcmp, .Lt);23 @call(.{ .modifier = .always_inline }, aeabi_fcmp, .{.Lt});
24 unreachable;24 unreachable;
25}25}
2626
27pub nakedcc fn __aeabi_fcmple() noreturn {27pub nakedcc fn __aeabi_fcmple() noreturn {
28 @setRuntimeSafety(false);28 @setRuntimeSafety(false);
29 @inlineCall(aeabi_fcmp, .Le);29 @call(.{ .modifier = .always_inline }, aeabi_fcmp, .{.Le});
30 unreachable;30 unreachable;
31}31}
3232
33pub nakedcc fn __aeabi_fcmpge() noreturn {33pub nakedcc fn __aeabi_fcmpge() noreturn {
34 @setRuntimeSafety(false);34 @setRuntimeSafety(false);
35 @inlineCall(aeabi_fcmp, .Ge);35 @call(.{ .modifier = .always_inline }, aeabi_fcmp, .{.Ge});
36 unreachable;36 unreachable;
37}37}
3838
39pub nakedcc fn __aeabi_fcmpgt() noreturn {39pub nakedcc fn __aeabi_fcmpgt() noreturn {
40 @setRuntimeSafety(false);40 @setRuntimeSafety(false);
41 @inlineCall(aeabi_fcmp, .Gt);41 @call(.{ .modifier = .always_inline }, aeabi_fcmp, .{.Gt});
42 unreachable;42 unreachable;
43}43}
4444
lib/std/special/compiler_rt/divti3.zig+4-1
...@@ -17,7 +17,10 @@ pub extern fn __divti3(a: i128, b: i128) i128 {...@@ -17,7 +17,10 @@ pub extern fn __divti3(a: i128, b: i128) i128 {
1717
18const v128 = @Vector(2, u64);18const v128 = @Vector(2, u64);
19pub extern fn __divti3_windows_x86_64(a: v128, b: v128) v128 {19pub extern fn __divti3_windows_x86_64(a: v128, b: v128) v128 {
20 return @bitCast(v128, @inlineCall(__divti3, @bitCast(i128, a), @bitCast(i128, b)));20 return @bitCast(v128, @call(.{ .modifier = .always_inline }, __divti3, .{
21 @bitCast(i128, a),
22 @bitCast(i128, b),
23 }));
21}24}
2225
23test "import divti3" {26test "import divti3" {
lib/std/special/compiler_rt/extendXfYf2.zig+4-4
...@@ -3,19 +3,19 @@ const builtin = @import("builtin");...@@ -3,19 +3,19 @@ const builtin = @import("builtin");
3const is_test = builtin.is_test;3const is_test = builtin.is_test;
44
5pub extern fn __extendsfdf2(a: f32) f64 {5pub extern fn __extendsfdf2(a: f32) f64 {
6 return @inlineCall(extendXfYf2, f64, f32, @bitCast(u32, a));6 return @call(.{ .modifier = .always_inline }, extendXfYf2, .{ f64, f32, @bitCast(u32, a) });
7}7}
88
9pub extern fn __extenddftf2(a: f64) f128 {9pub extern fn __extenddftf2(a: f64) f128 {
10 return @inlineCall(extendXfYf2, f128, f64, @bitCast(u64, a));10 return @call(.{ .modifier = .always_inline }, extendXfYf2, .{ f128, f64, @bitCast(u64, a) });
11}11}
1212
13pub extern fn __extendsftf2(a: f32) f128 {13pub extern fn __extendsftf2(a: f32) f128 {
14 return @inlineCall(extendXfYf2, f128, f32, @bitCast(u32, a));14 return @call(.{ .modifier = .always_inline }, extendXfYf2, .{ f128, f32, @bitCast(u32, a) });
15}15}
1616
17pub extern fn __extendhfsf2(a: u16) f32 {17pub extern fn __extendhfsf2(a: u16) f32 {
18 return @inlineCall(extendXfYf2, f32, f16, a);18 return @call(.{ .modifier = .always_inline }, extendXfYf2, .{ f32, f16, a });
19}19}
2020
21const CHAR_BIT = 8;21const CHAR_BIT = 8;
lib/std/special/compiler_rt/floatsiXf.zig+3-3
...@@ -55,17 +55,17 @@ fn floatsiXf(comptime T: type, a: i32) T {...@@ -55,17 +55,17 @@ fn floatsiXf(comptime T: type, a: i32) T {
5555
56pub extern fn __floatsisf(arg: i32) f32 {56pub extern fn __floatsisf(arg: i32) f32 {
57 @setRuntimeSafety(builtin.is_test);57 @setRuntimeSafety(builtin.is_test);
58 return @inlineCall(floatsiXf, f32, arg);58 return @call(.{ .modifier = .always_inline }, floatsiXf, .{ f32, arg });
59}59}
6060
61pub extern fn __floatsidf(arg: i32) f64 {61pub extern fn __floatsidf(arg: i32) f64 {
62 @setRuntimeSafety(builtin.is_test);62 @setRuntimeSafety(builtin.is_test);
63 return @inlineCall(floatsiXf, f64, arg);63 return @call(.{ .modifier = .always_inline }, floatsiXf, .{ f64, arg });
64}64}
6565
66pub extern fn __floatsitf(arg: i32) f128 {66pub extern fn __floatsitf(arg: i32) f128 {
67 @setRuntimeSafety(builtin.is_test);67 @setRuntimeSafety(builtin.is_test);
68 return @inlineCall(floatsiXf, f128, arg);68 return @call(.{ .modifier = .always_inline }, floatsiXf, .{ f128, arg });
69}69}
7070
71fn test_one_floatsitf(a: i32, expected: u128) void {71fn test_one_floatsitf(a: i32, expected: u128) void {
lib/std/special/compiler_rt/modti3.zig+4-1
...@@ -22,7 +22,10 @@ pub extern fn __modti3(a: i128, b: i128) i128 {...@@ -22,7 +22,10 @@ pub extern fn __modti3(a: i128, b: i128) i128 {
2222
23const v128 = @Vector(2, u64);23const v128 = @Vector(2, u64);
24pub extern fn __modti3_windows_x86_64(a: v128, b: v128) v128 {24pub extern fn __modti3_windows_x86_64(a: v128, b: v128) v128 {
25 return @bitCast(v128, @inlineCall(__modti3, @bitCast(i128, a), @bitCast(i128, b)));25 return @bitCast(v128, @call(.{ .modifier = .always_inline }, __modti3, .{
26 @bitCast(i128, a),
27 @bitCast(i128, b),
28 }));
26}29}
2730
28test "import modti3" {31test "import modti3" {
lib/std/special/compiler_rt/multi3.zig+4-1
...@@ -16,7 +16,10 @@ pub extern fn __multi3(a: i128, b: i128) i128 {...@@ -16,7 +16,10 @@ pub extern fn __multi3(a: i128, b: i128) i128 {
1616
17const v128 = @Vector(2, u64);17const v128 = @Vector(2, u64);
18pub extern fn __multi3_windows_x86_64(a: v128, b: v128) v128 {18pub extern fn __multi3_windows_x86_64(a: v128, b: v128) v128 {
19 return @bitCast(v128, @inlineCall(__multi3, @bitCast(i128, a), @bitCast(i128, b)));19 return @bitCast(v128, @call(.{ .modifier = .always_inline }, __multi3, .{
20 @bitCast(i128, a),
21 @bitCast(i128, b),
22 }));
20}23}
2124
22fn __mulddi3(a: u64, b: u64) i128 {25fn __mulddi3(a: u64, b: u64) i128 {
lib/std/special/compiler_rt/stack_probe.zig+6-6
...@@ -182,25 +182,25 @@ fn win_probe_stack_adjust_sp() void {...@@ -182,25 +182,25 @@ fn win_probe_stack_adjust_sp() void {
182182
183pub nakedcc fn _chkstk() void {183pub nakedcc fn _chkstk() void {
184 @setRuntimeSafety(false);184 @setRuntimeSafety(false);
185 @inlineCall(win_probe_stack_adjust_sp);185 @call(.{ .modifier = .always_inline }, win_probe_stack_adjust_sp, .{});
186}186}
187pub nakedcc fn __chkstk() void {187pub nakedcc fn __chkstk() void {
188 @setRuntimeSafety(false);188 @setRuntimeSafety(false);
189 switch (builtin.arch) {189 switch (builtin.arch) {
190 .i386 => @inlineCall(win_probe_stack_adjust_sp),190 .i386 => @call(.{ .modifier = .always_inline }, win_probe_stack_adjust_sp, .{}),
191 .x86_64 => @inlineCall(win_probe_stack_only),191 .x86_64 => @call(.{ .modifier = .always_inline }, win_probe_stack_only, .{}),
192 else => unreachable,192 else => unreachable,
193 }193 }
194}194}
195pub nakedcc fn ___chkstk() void {195pub nakedcc fn ___chkstk() void {
196 @setRuntimeSafety(false);196 @setRuntimeSafety(false);
197 @inlineCall(win_probe_stack_adjust_sp);197 @call(.{ .modifier = .always_inline }, win_probe_stack_adjust_sp, .{});
198}198}
199pub nakedcc fn __chkstk_ms() void {199pub nakedcc fn __chkstk_ms() void {
200 @setRuntimeSafety(false);200 @setRuntimeSafety(false);
201 @inlineCall(win_probe_stack_only);201 @call(.{ .modifier = .always_inline }, win_probe_stack_only, .{});
202}202}
203pub nakedcc fn ___chkstk_ms() void {203pub nakedcc fn ___chkstk_ms() void {
204 @setRuntimeSafety(false);204 @setRuntimeSafety(false);
205 @inlineCall(win_probe_stack_only);205 @call(.{ .modifier = .always_inline }, win_probe_stack_only, .{});
206}206}
lib/std/special/compiler_rt/umodti3.zig+4-1
...@@ -11,5 +11,8 @@ pub extern fn __umodti3(a: u128, b: u128) u128 {...@@ -11,5 +11,8 @@ pub extern fn __umodti3(a: u128, b: u128) u128 {
1111
12const v128 = @Vector(2, u64);12const v128 = @Vector(2, u64);
13pub extern fn __umodti3_windows_x86_64(a: v128, b: v128) v128 {13pub extern fn __umodti3_windows_x86_64(a: v128, b: v128) v128 {
14 return @bitCast(v128, @inlineCall(__umodti3, @bitCast(u128, a), @bitCast(u128, b)));14 return @bitCast(v128, @call(.{ .modifier = .always_inline }, __umodti3, .{
15 @bitCast(u128, a),
16 @bitCast(u128, b),
17 }));
15}18}
lib/std/special/start.zig+7-7
...@@ -61,7 +61,7 @@ stdcallcc fn _DllMainCRTStartup(...@@ -61,7 +61,7 @@ stdcallcc fn _DllMainCRTStartup(
61extern fn wasm_freestanding_start() void {61extern fn wasm_freestanding_start() void {
62 // This is marked inline because for some reason LLVM in release mode fails to inline it,62 // This is marked inline because for some reason LLVM in release mode fails to inline it,
63 // and we want fewer call frames in stack traces.63 // and we want fewer call frames in stack traces.
64 _ = @inlineCall(callMain);64 _ = @call(.{ .modifier = .always_inline }, callMain, .{});
65}65}
6666
67extern fn EfiMain(handle: uefi.Handle, system_table: *uefi.tables.SystemTable) usize {67extern fn EfiMain(handle: uefi.Handle, system_table: *uefi.tables.SystemTable) usize {
...@@ -91,7 +91,7 @@ nakedcc fn _start() noreturn {...@@ -91,7 +91,7 @@ nakedcc fn _start() noreturn {
91 if (builtin.os == builtin.Os.wasi) {91 if (builtin.os == builtin.Os.wasi) {
92 // This is marked inline because for some reason LLVM in release mode fails to inline it,92 // This is marked inline because for some reason LLVM in release mode fails to inline it,
93 // and we want fewer call frames in stack traces.93 // and we want fewer call frames in stack traces.
94 std.os.wasi.proc_exit(@inlineCall(callMain));94 std.os.wasi.proc_exit(@call(.{ .modifier = .always_inline }, callMain, .{}));
95 }95 }
9696
97 switch (builtin.arch) {97 switch (builtin.arch) {
...@@ -127,7 +127,7 @@ nakedcc fn _start() noreturn {...@@ -127,7 +127,7 @@ nakedcc fn _start() noreturn {
127 }127 }
128 // If LLVM inlines stack variables into _start, they will overwrite128 // If LLVM inlines stack variables into _start, they will overwrite
129 // the command line argument data.129 // the command line argument data.
130 @noInlineCall(posixCallMainAndExit);130 @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{});
131}131}
132132
133stdcallcc fn WinMainCRTStartup() noreturn {133stdcallcc fn WinMainCRTStartup() noreturn {
...@@ -186,10 +186,10 @@ fn posixCallMainAndExit() noreturn {...@@ -186,10 +186,10 @@ fn posixCallMainAndExit() noreturn {
186 // 0,186 // 0,
187 //) catch @panic("out of memory");187 //) catch @panic("out of memory");
188 //std.os.mprotect(new_stack[0..std.mem.page_size], std.os.PROT_NONE) catch {};188 //std.os.mprotect(new_stack[0..std.mem.page_size], std.os.PROT_NONE) catch {};
189 //std.os.exit(@newStackCall(new_stack, callMainWithArgs, argc, argv, envp));189 //std.os.exit(@call(.{.stack = new_stack}, callMainWithArgs, .{argc, argv, envp}));
190 }190 }
191191
192 std.os.exit(@inlineCall(callMainWithArgs, argc, argv, envp));192 std.os.exit(@call(.{ .modifier = .always_inline }, callMainWithArgs, .{ argc, argv, envp }));
193}193}
194194
195fn callMainWithArgs(argc: usize, argv: [*][*:0]u8, envp: [][*:0]u8) u8 {195fn callMainWithArgs(argc: usize, argv: [*][*:0]u8, envp: [][*:0]u8) u8 {
...@@ -205,7 +205,7 @@ extern fn main(c_argc: i32, c_argv: [*][*:0]u8, c_envp: [*:null]?[*:0]u8) i32 {...@@ -205,7 +205,7 @@ extern fn main(c_argc: i32, c_argv: [*][*:0]u8, c_envp: [*:null]?[*:0]u8) i32 {
205 var env_count: usize = 0;205 var env_count: usize = 0;
206 while (c_envp[env_count] != null) : (env_count += 1) {}206 while (c_envp[env_count] != null) : (env_count += 1) {}
207 const envp = @ptrCast([*][*:0]u8, c_envp)[0..env_count];207 const envp = @ptrCast([*][*:0]u8, c_envp)[0..env_count];
208 return @inlineCall(callMainWithArgs, @intCast(usize, c_argc), c_argv, envp);208 return @call(.{ .modifier = .always_inline }, callMainWithArgs, .{ @intCast(usize, c_argc), c_argv, envp });
209}209}
210210
211// General error message for a malformed return type211// General error message for a malformed return type
...@@ -235,7 +235,7 @@ inline fn initEventLoopAndCallMain() u8 {...@@ -235,7 +235,7 @@ inline fn initEventLoopAndCallMain() u8 {
235235
236 // This is marked inline because for some reason LLVM in release mode fails to inline it,236 // This is marked inline because for some reason LLVM in release mode fails to inline it,
237 // and we want fewer call frames in stack traces.237 // and we want fewer call frames in stack traces.
238 return @inlineCall(callMain);238 return @call(.{ .modifier = .always_inline }, callMain, .{});
239}239}
240240
241async fn callMainAsync(loop: *std.event.Loop) u8 {241async fn callMainAsync(loop: *std.event.Loop) u8 {
src-self-hosted/ir.zig+2-2
...@@ -321,7 +321,7 @@ pub const Inst = struct {...@@ -321,7 +321,7 @@ pub const Inst = struct {
321 }321 }
322322
323 const llvm_cc = llvm.CCallConv;323 const llvm_cc = llvm.CCallConv;
324 const fn_inline = llvm.FnInline.Auto;324 const call_attr = llvm.CallAttr.Auto;
325325
326 return llvm.BuildCall(326 return llvm.BuildCall(
327 ofile.builder,327 ofile.builder,
...@@ -329,7 +329,7 @@ pub const Inst = struct {...@@ -329,7 +329,7 @@ pub const Inst = struct {
329 args.ptr,329 args.ptr,
330 @intCast(c_uint, args.len),330 @intCast(c_uint, args.len),
331 llvm_cc,331 llvm_cc,
332 fn_inline,332 call_attr,
333 "",333 "",
334 ) orelse error.OutOfMemory;334 ) orelse error.OutOfMemory;
335 }335 }
src-self-hosted/llvm.zig+6-4
...@@ -260,10 +260,12 @@ pub const X86StdcallCallConv = c.LLVMX86StdcallCallConv;...@@ -260,10 +260,12 @@ pub const X86StdcallCallConv = c.LLVMX86StdcallCallConv;
260pub const X86FastcallCallConv = c.LLVMX86FastcallCallConv;260pub const X86FastcallCallConv = c.LLVMX86FastcallCallConv;
261pub const CallConv = c.LLVMCallConv;261pub const CallConv = c.LLVMCallConv;
262262
263pub const FnInline = extern enum {263pub const CallAttr = extern enum {
264 Auto,264 Auto,
265 Always,265 NeverTail,
266 Never,266 NeverInline,
267 AlwaysTail,
268 AlwaysInline,
267};269};
268270
269fn removeNullability(comptime T: type) type {271fn removeNullability(comptime T: type) type {
...@@ -286,6 +288,6 @@ extern fn ZigLLVMTargetMachineEmitToFile(...@@ -286,6 +288,6 @@ extern fn ZigLLVMTargetMachineEmitToFile(
286) bool;288) bool;
287289
288pub const BuildCall = ZigLLVMBuildCall;290pub const BuildCall = ZigLLVMBuildCall;
289extern fn ZigLLVMBuildCall(B: *Builder, Fn: *Value, Args: [*]*Value, NumArgs: c_uint, CC: c_uint, fn_inline: FnInline, Name: [*:0]const u8) ?*Value;291extern fn ZigLLVMBuildCall(B: *Builder, Fn: *Value, Args: [*]*Value, NumArgs: c_uint, CC: c_uint, fn_inline: CallAttr, Name: [*:0]const u8) ?*Value;
290292
291pub const PrivateLinkage = c.LLVMLinkage.LLVMPrivateLinkage;293pub const PrivateLinkage = c.LLVMLinkage.LLVMPrivateLinkage;
src/all_types.hpp+40-8
...@@ -409,6 +409,9 @@ struct ZigValue {...@@ -409,6 +409,9 @@ struct ZigValue {
409 LLVMValueRef llvm_global;409 LLVMValueRef llvm_global;
410410
411 union {411 union {
412 // populated if special == ConstValSpecialLazy
413 LazyValue *x_lazy;
414
412 // populated if special == ConstValSpecialStatic415 // populated if special == ConstValSpecialStatic
413 BigInt x_bigint;416 BigInt x_bigint;
414 BigFloat x_bigfloat;417 BigFloat x_bigfloat;
...@@ -429,7 +432,6 @@ struct ZigValue {...@@ -429,7 +432,6 @@ struct ZigValue {
429 ConstPtrValue x_ptr;432 ConstPtrValue x_ptr;
430 ConstArgTuple x_arg_tuple;433 ConstArgTuple x_arg_tuple;
431 Buf *x_enum_literal;434 Buf *x_enum_literal;
432 LazyValue *x_lazy;
433435
434 // populated if special == ConstValSpecialRuntime436 // populated if special == ConstValSpecialRuntime
435 RuntimeHintErrorUnion rh_error_union;437 RuntimeHintErrorUnion rh_error_union;
...@@ -767,11 +769,19 @@ struct AstNodeUnwrapOptional {...@@ -767,11 +769,19 @@ struct AstNodeUnwrapOptional {
767 AstNode *expr;769 AstNode *expr;
768};770};
769771
772// Must be synchronized with std.builtin.CallOptions.Modifier
770enum CallModifier {773enum CallModifier {
771 CallModifierNone,774 CallModifierNone,
772 CallModifierAsync,775 CallModifierNeverTail,
776 CallModifierNeverInline,
773 CallModifierNoAsync,777 CallModifierNoAsync,
778 CallModifierAlwaysTail,
779 CallModifierAlwaysInline,
780 CallModifierCompileTime,
781
782 // These are additional tags in the compiler, but not exposed in the std lib.
774 CallModifierBuiltin,783 CallModifierBuiltin,
784 CallModifierAsync,
775};785};
776786
777struct AstNodeFnCallExpr {787struct AstNodeFnCallExpr {
...@@ -1692,8 +1702,6 @@ enum BuiltinFnId {...@@ -1692,8 +1702,6 @@ enum BuiltinFnId {
1692 BuiltinFnIdFieldParentPtr,1702 BuiltinFnIdFieldParentPtr,
1693 BuiltinFnIdByteOffsetOf,1703 BuiltinFnIdByteOffsetOf,
1694 BuiltinFnIdBitOffsetOf,1704 BuiltinFnIdBitOffsetOf,
1695 BuiltinFnIdInlineCall,
1696 BuiltinFnIdNoInlineCall,
1697 BuiltinFnIdNewStackCall,1705 BuiltinFnIdNewStackCall,
1698 BuiltinFnIdAsyncCall,1706 BuiltinFnIdAsyncCall,
1699 BuiltinFnIdTypeId,1707 BuiltinFnIdTypeId,
...@@ -1717,6 +1725,7 @@ enum BuiltinFnId {...@@ -1717,6 +1725,7 @@ enum BuiltinFnId {
1717 BuiltinFnIdFrameHandle,1725 BuiltinFnIdFrameHandle,
1718 BuiltinFnIdFrameSize,1726 BuiltinFnIdFrameSize,
1719 BuiltinFnIdAs,1727 BuiltinFnIdAs,
1728 BuiltinFnIdCall,
1720};1729};
17211730
1722struct BuiltinFnEntry {1731struct BuiltinFnEntry {
...@@ -2479,6 +2488,8 @@ enum IrInstructionId {...@@ -2479,6 +2488,8 @@ enum IrInstructionId {
2479 IrInstructionIdVarPtr,2488 IrInstructionIdVarPtr,
2480 IrInstructionIdReturnPtr,2489 IrInstructionIdReturnPtr,
2481 IrInstructionIdCallSrc,2490 IrInstructionIdCallSrc,
2491 IrInstructionIdCallSrcArgs,
2492 IrInstructionIdCallExtra,
2482 IrInstructionIdCallGen,2493 IrInstructionIdCallGen,
2483 IrInstructionIdConst,2494 IrInstructionIdConst,
2484 IrInstructionIdReturn,2495 IrInstructionIdReturn,
...@@ -2886,15 +2897,37 @@ struct IrInstructionCallSrc {...@@ -2886,15 +2897,37 @@ struct IrInstructionCallSrc {
2886 ZigFn *fn_entry;2897 ZigFn *fn_entry;
2887 size_t arg_count;2898 size_t arg_count;
2888 IrInstruction **args;2899 IrInstruction **args;
2900 IrInstruction *ret_ptr;
2889 ResultLoc *result_loc;2901 ResultLoc *result_loc;
28902902
2891 IrInstruction *new_stack;2903 IrInstruction *new_stack;
28922904
2893 FnInline fn_inline;
2894 CallModifier modifier;2905 CallModifier modifier;
2895
2896 bool is_async_call_builtin;2906 bool is_async_call_builtin;
2897 bool is_comptime;2907};
2908
2909// This is a pass1 instruction, used by @call when the args node is
2910// a tuple or struct literal.
2911struct IrInstructionCallSrcArgs {
2912 IrInstruction base;
2913
2914 IrInstruction *options;
2915 IrInstruction *fn_ref;
2916 IrInstruction **args_ptr;
2917 size_t args_len;
2918 ResultLoc *result_loc;
2919};
2920
2921// This is a pass1 instruction, used by @call, when the args node
2922// is not a literal.
2923// `args` is expected to be either a struct or a tuple.
2924struct IrInstructionCallExtra {
2925 IrInstruction base;
2926
2927 IrInstruction *options;
2928 IrInstruction *fn_ref;
2929 IrInstruction *args;
2930 ResultLoc *result_loc;
2898};2931};
28992932
2900struct IrInstructionCallGen {2933struct IrInstructionCallGen {
...@@ -2908,7 +2941,6 @@ struct IrInstructionCallGen {...@@ -2908,7 +2941,6 @@ struct IrInstructionCallGen {
2908 IrInstruction *frame_result_loc;2941 IrInstruction *frame_result_loc;
2909 IrInstruction *new_stack;2942 IrInstruction *new_stack;
29102943
2911 FnInline fn_inline;
2912 CallModifier modifier;2944 CallModifier modifier;
29132945
2914 bool is_async_call_builtin;2946 bool is_async_call_builtin;
src/analyze.cpp+15-9
...@@ -594,8 +594,11 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con...@@ -594,8 +594,11 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con
594 break;594 break;
595 }595 }
596596
597597 if (inferred_struct_field != nullptr) {
598 if (type_is_resolved(child_type, ResolveStatusZeroBitsKnown)) {598 entry->abi_size = g->builtin_types.entry_usize->abi_size;
599 entry->size_in_bits = g->builtin_types.entry_usize->size_in_bits;
600 entry->abi_align = g->builtin_types.entry_usize->abi_align;
601 } else if (type_is_resolved(child_type, ResolveStatusZeroBitsKnown)) {
599 if (type_has_bits(child_type)) {602 if (type_has_bits(child_type)) {
600 entry->abi_size = g->builtin_types.entry_usize->abi_size;603 entry->abi_size = g->builtin_types.entry_usize->abi_size;
601 entry->size_in_bits = g->builtin_types.entry_usize->size_in_bits;604 entry->size_in_bits = g->builtin_types.entry_usize->size_in_bits;
...@@ -956,10 +959,7 @@ bool calling_convention_allows_zig_types(CallingConvention cc) {...@@ -956,10 +959,7 @@ bool calling_convention_allows_zig_types(CallingConvention cc) {
956959
957ZigType *get_stack_trace_type(CodeGen *g) {960ZigType *get_stack_trace_type(CodeGen *g) {
958 if (g->stack_trace_type == nullptr) {961 if (g->stack_trace_type == nullptr) {
959 ZigValue *stack_trace_type_val = get_builtin_value(g, "StackTrace");962 g->stack_trace_type = get_builtin_type(g, "StackTrace");
960 assert(stack_trace_type_val->type->id == ZigTypeIdMetaType);
961
962 g->stack_trace_type = stack_trace_type_val->data.x_type;
963 assertNoError(type_resolve(g, g->stack_trace_type, ResolveStatusZeroBitsKnown));963 assertNoError(type_resolve(g, g->stack_trace_type, ResolveStatusZeroBitsKnown));
964 }964 }
965 return g->stack_trace_type;965 return g->stack_trace_type;
...@@ -2717,10 +2717,10 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {...@@ -2717,10 +2717,10 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
2717 src_assert(struct_type->data.structure.fields == nullptr, decl_node);2717 src_assert(struct_type->data.structure.fields == nullptr, decl_node);
2718 struct_type->data.structure.fields = alloc_type_struct_fields(field_count);2718 struct_type->data.structure.fields = alloc_type_struct_fields(field_count);
2719 } else if (decl_node->type == NodeTypeContainerInitExpr) {2719 } else if (decl_node->type == NodeTypeContainerInitExpr) {
2720 src_assert(struct_type->data.structure.is_inferred, decl_node);
2721 src_assert(struct_type->data.structure.fields != nullptr, decl_node);
2722
2723 field_count = struct_type->data.structure.src_field_count;2720 field_count = struct_type->data.structure.src_field_count;
2721
2722 src_assert(struct_type->data.structure.is_inferred, decl_node);
2723 src_assert(field_count == 0 || struct_type->data.structure.fields != nullptr, decl_node);
2724 } else zig_unreachable();2724 } else zig_unreachable();
27252725
2726 struct_type->data.structure.fields_by_name.init(field_count);2726 struct_type->data.structure.fields_by_name.init(field_count);
...@@ -7531,6 +7531,12 @@ ZigValue *get_builtin_value(CodeGen *codegen, const char *name) {...@@ -7531,6 +7531,12 @@ ZigValue *get_builtin_value(CodeGen *codegen, const char *name) {
7531 return var_value;7531 return var_value;
7532}7532}
75337533
7534ZigType *get_builtin_type(CodeGen *codegen, const char *name) {
7535 ZigValue *type_val = get_builtin_value(codegen, name);
7536 assert(type_val->type->id == ZigTypeIdMetaType);
7537 return type_val->data.x_type;
7538}
7539
7534bool type_is_global_error_set(ZigType *err_set_type) {7540bool type_is_global_error_set(ZigType *err_set_type) {
7535 assert(err_set_type->id == ZigTypeIdErrorSet);7541 assert(err_set_type->id == ZigTypeIdErrorSet);
7536 assert(!err_set_type->data.error_set.incomplete);7542 assert(!err_set_type->data.error_set.incomplete);
src/analyze.hpp+1
...@@ -207,6 +207,7 @@ void add_var_export(CodeGen *g, ZigVar *fn_table_entry, const char *symbol_name,...@@ -207,6 +207,7 @@ void add_var_export(CodeGen *g, ZigVar *fn_table_entry, const char *symbol_name,
207207
208208
209ZigValue *get_builtin_value(CodeGen *codegen, const char *name);209ZigValue *get_builtin_value(CodeGen *codegen, const char *name);
210ZigType *get_builtin_type(CodeGen *codegen, const char *name);
210ZigType *get_stack_trace_type(CodeGen *g);211ZigType *get_stack_trace_type(CodeGen *g);
211bool resolve_inferred_error_set(CodeGen *g, ZigType *err_set_type, AstNode *source_node);212bool resolve_inferred_error_set(CodeGen *g, ZigType *err_set_type, AstNode *source_node);
212213
src/ast_render.cpp+19-4
...@@ -702,14 +702,29 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -702,14 +702,29 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
702 switch (node->data.fn_call_expr.modifier) {702 switch (node->data.fn_call_expr.modifier) {
703 case CallModifierNone:703 case CallModifierNone:
704 break;704 break;
705 case CallModifierBuiltin:705 case CallModifierNoAsync:
706 fprintf(ar->f, "@");706 fprintf(ar->f, "noasync ");
707 break;707 break;
708 case CallModifierAsync:708 case CallModifierAsync:
709 fprintf(ar->f, "async ");709 fprintf(ar->f, "async ");
710 break;710 break;
711 case CallModifierNoAsync:711 case CallModifierNeverTail:
712 fprintf(ar->f, "noasync ");712 fprintf(ar->f, "notail ");
713 break;
714 case CallModifierNeverInline:
715 fprintf(ar->f, "noinline ");
716 break;
717 case CallModifierAlwaysTail:
718 fprintf(ar->f, "tail ");
719 break;
720 case CallModifierAlwaysInline:
721 fprintf(ar->f, "inline ");
722 break;
723 case CallModifierCompileTime:
724 fprintf(ar->f, "comptime ");
725 break;
726 case CallModifierBuiltin:
727 fprintf(ar->f, "@");
713 break;728 break;
714 }729 }
715 AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr;730 AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr;
src/codegen.cpp+48-25
...@@ -981,7 +981,7 @@ static void gen_panic(CodeGen *g, LLVMValueRef msg_arg, LLVMValueRef stack_trace...@@ -981,7 +981,7 @@ static void gen_panic(CodeGen *g, LLVMValueRef msg_arg, LLVMValueRef stack_trace
981 msg_arg,981 msg_arg,
982 stack_trace_arg,982 stack_trace_arg,
983 };983 };
984 ZigLLVMBuildCall(g->builder, fn_val, args, 2, llvm_cc, ZigLLVM_FnInlineAuto, "");984 ZigLLVMBuildCall(g->builder, fn_val, args, 2, llvm_cc, ZigLLVM_CallAttrAuto, "");
985 if (!stack_trace_is_llvm_alloca) {985 if (!stack_trace_is_llvm_alloca) {
986 // The stack trace argument is not in the stack of the caller, so986 // The stack trace argument is not in the stack of the caller, so
987 // we'd like to set tail call here, but because slices (the type of msg_arg) are987 // we'd like to set tail call here, but because slices (the type of msg_arg) are
...@@ -1201,7 +1201,8 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) {...@@ -1201,7 +1201,8 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) {
12011201
1202 LLVMPositionBuilderAtEnd(g->builder, dest_non_null_block);1202 LLVMPositionBuilderAtEnd(g->builder, dest_non_null_block);
1203 LLVMValueRef args[] = { err_ret_trace_ptr, return_address };1203 LLVMValueRef args[] = { err_ret_trace_ptr, return_address };
1204 ZigLLVMBuildCall(g->builder, add_error_return_trace_addr_fn_val, args, 2, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAlways, "");1204 ZigLLVMBuildCall(g->builder, add_error_return_trace_addr_fn_val, args, 2,
1205 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAlwaysInline, "");
1205 LLVMBuildRetVoid(g->builder);1206 LLVMBuildRetVoid(g->builder);
12061207
1207 LLVMPositionBuilderAtEnd(g->builder, prev_block);1208 LLVMPositionBuilderAtEnd(g->builder, prev_block);
...@@ -1370,13 +1371,13 @@ static void gen_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val, Scope *sc...@@ -1370,13 +1371,13 @@ static void gen_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val, Scope *sc
1370 err_val,1371 err_val,
1371 };1372 };
1372 call_instruction = ZigLLVMBuildCall(g->builder, safety_crash_err_fn, args, 2,1373 call_instruction = ZigLLVMBuildCall(g->builder, safety_crash_err_fn, args, 2,
1373 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");1374 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, "");
1374 } else {1375 } else {
1375 LLVMValueRef args[] = {1376 LLVMValueRef args[] = {
1376 err_val,1377 err_val,
1377 };1378 };
1378 call_instruction = ZigLLVMBuildCall(g->builder, safety_crash_err_fn, args, 1,1379 call_instruction = ZigLLVMBuildCall(g->builder, safety_crash_err_fn, args, 1,
1379 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");1380 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, "");
1380 }1381 }
1381 if (!is_llvm_alloca) {1382 if (!is_llvm_alloca) {
1382 LLVMSetTailCall(call_instruction, true);1383 LLVMSetTailCall(call_instruction, true);
...@@ -2216,7 +2217,7 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) {...@@ -2216,7 +2217,7 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) {
2216 LLVMValueRef addr_ptr = LLVMBuildInBoundsGEP(g->builder, src_ptr_val, &ptr_index, 1, "");2217 LLVMValueRef addr_ptr = LLVMBuildInBoundsGEP(g->builder, src_ptr_val, &ptr_index, 1, "");
2217 LLVMValueRef this_addr_val = LLVMBuildLoad(g->builder, addr_ptr, "");2218 LLVMValueRef this_addr_val = LLVMBuildLoad(g->builder, addr_ptr, "");
2218 LLVMValueRef args[] = {dest_stack_trace_ptr, this_addr_val};2219 LLVMValueRef args[] = {dest_stack_trace_ptr, this_addr_val};
2219 ZigLLVMBuildCall(g->builder, add_error_return_trace_addr_fn_val, args, 2, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAlways, "");2220 ZigLLVMBuildCall(g->builder, add_error_return_trace_addr_fn_val, args, 2, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAlwaysInline, "");
2220 LLVMValueRef prev_frames_left = LLVMBuildLoad(g->builder, frames_left_ptr, "");2221 LLVMValueRef prev_frames_left = LLVMBuildLoad(g->builder, frames_left_ptr, "");
2221 LLVMValueRef new_frames_left = LLVMBuildNUWSub(g->builder, prev_frames_left, usize_one, "");2222 LLVMValueRef new_frames_left = LLVMBuildNUWSub(g->builder, prev_frames_left, usize_one, "");
2222 LLVMValueRef done_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, new_frames_left, usize_zero, "");2223 LLVMValueRef done_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, new_frames_left, usize_zero, "");
...@@ -2253,7 +2254,7 @@ static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, IrExecutable *execut...@@ -2253,7 +2254,7 @@ static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, IrExecutable *execut
2253 LLVMValueRef my_err_trace_val = get_cur_err_ret_trace_val(g, save_err_ret_addr_instruction->base.scope,2254 LLVMValueRef my_err_trace_val = get_cur_err_ret_trace_val(g, save_err_ret_addr_instruction->base.scope,
2254 &is_llvm_alloca);2255 &is_llvm_alloca);
2255 ZigLLVMBuildCall(g->builder, return_err_fn, &my_err_trace_val, 1,2256 ZigLLVMBuildCall(g->builder, return_err_fn, &my_err_trace_val, 1,
2256 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");2257 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, "");
22572258
2258 ZigType *ret_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;2259 ZigType *ret_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;
2259 if (fn_is_async(g->cur_fn) && codegen_fn_has_err_ret_tracing_arg(g, ret_type)) {2260 if (fn_is_async(g->cur_fn) && codegen_fn_has_err_ret_tracing_arg(g, ret_type)) {
...@@ -2297,7 +2298,7 @@ static LLVMValueRef gen_resume(CodeGen *g, LLVMValueRef fn_val, LLVMValueRef tar...@@ -2297,7 +2298,7 @@ static LLVMValueRef gen_resume(CodeGen *g, LLVMValueRef fn_val, LLVMValueRef tar
2297 LLVMValueRef arg_val = LLVMConstSub(LLVMConstAllOnes(usize_type_ref),2298 LLVMValueRef arg_val = LLVMConstSub(LLVMConstAllOnes(usize_type_ref),
2298 LLVMConstInt(usize_type_ref, resume_id, false));2299 LLVMConstInt(usize_type_ref, resume_id, false));
2299 LLVMValueRef args[] = {target_frame_ptr, arg_val};2300 LLVMValueRef args[] = {target_frame_ptr, arg_val};
2300 return ZigLLVMBuildCall(g->builder, fn_val, args, 2, LLVMFastCallConv, ZigLLVM_FnInlineAuto, "");2301 return ZigLLVMBuildCall(g->builder, fn_val, args, 2, LLVMFastCallConv, ZigLLVM_CallAttrAuto, "");
2301}2302}
23022303
2303static LLVMBasicBlockRef gen_suspend_begin(CodeGen *g, const char *name_hint) {2304static LLVMBasicBlockRef gen_suspend_begin(CodeGen *g, const char *name_hint) {
...@@ -2424,7 +2425,7 @@ static void gen_async_return(CodeGen *g, IrInstructionReturn *instruction) {...@@ -2424,7 +2425,7 @@ static void gen_async_return(CodeGen *g, IrInstructionReturn *instruction) {
2424 LLVMValueRef my_err_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope, &is_llvm_alloca);2425 LLVMValueRef my_err_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope, &is_llvm_alloca);
2425 LLVMValueRef args[] = { dest_trace_ptr, my_err_trace_val };2426 LLVMValueRef args[] = { dest_trace_ptr, my_err_trace_val };
2426 ZigLLVMBuildCall(g->builder, get_merge_err_ret_traces_fn_val(g), args, 2,2427 ZigLLVMBuildCall(g->builder, get_merge_err_ret_traces_fn_val(g), args, 2,
2427 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");2428 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, "");
2428 }2429 }
2429 }2430 }
24302431
...@@ -3061,7 +3062,7 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,...@@ -3061,7 +3062,7 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
3061 ZigType *actual_type = cast_instruction->value->value->type;3062 ZigType *actual_type = cast_instruction->value->value->type;
3062 ZigType *wanted_type = cast_instruction->base.value->type;3063 ZigType *wanted_type = cast_instruction->base.value->type;
3063 LLVMValueRef expr_val = ir_llvm_value(g, cast_instruction->value);3064 LLVMValueRef expr_val = ir_llvm_value(g, cast_instruction->value);
3064 assert(expr_val);3065 ir_assert(expr_val, &cast_instruction->base);
30653066
3066 switch (cast_instruction->cast_op) {3067 switch (cast_instruction->cast_op) {
3067 case CastOpNoCast:3068 case CastOpNoCast:
...@@ -4142,16 +4143,28 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -4142,16 +4143,28 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
4142 fn_walk.data.call.gen_param_types = &gen_param_types;4143 fn_walk.data.call.gen_param_types = &gen_param_types;
4143 walk_function_params(g, fn_type, &fn_walk);4144 walk_function_params(g, fn_type, &fn_walk);
41444145
4145 ZigLLVM_FnInline fn_inline;4146 ZigLLVM_CallAttr call_attr;
4146 switch (instruction->fn_inline) {4147 switch (instruction->modifier) {
4147 case FnInlineAuto:4148 case CallModifierBuiltin:
4148 fn_inline = ZigLLVM_FnInlineAuto;4149 case CallModifierCompileTime:
4150 zig_unreachable();
4151 case CallModifierNone:
4152 case CallModifierNoAsync:
4153 case CallModifierAsync:
4154 call_attr = ZigLLVM_CallAttrAuto;
4149 break;4155 break;
4150 case FnInlineAlways:4156 case CallModifierNeverTail:
4151 fn_inline = (instruction->fn_entry == nullptr) ? ZigLLVM_FnInlineAuto : ZigLLVM_FnInlineAlways;4157 call_attr = ZigLLVM_CallAttrNeverTail;
4152 break;4158 break;
4153 case FnInlineNever:4159 case CallModifierNeverInline:
4154 fn_inline = ZigLLVM_FnInlineNever;4160 call_attr = ZigLLVM_CallAttrNeverInline;
4161 break;
4162 case CallModifierAlwaysTail:
4163 call_attr = ZigLLVM_CallAttrAlwaysTail;
4164 break;
4165 case CallModifierAlwaysInline:
4166 ir_assert(instruction->fn_entry != nullptr, &instruction->base);
4167 call_attr = ZigLLVM_CallAttrAlwaysInline;
4155 break;4168 break;
4156 }4169 }
41574170
...@@ -4257,7 +4270,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -4257,7 +4270,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
42574270
4258 if (instruction->new_stack == nullptr || instruction->is_async_call_builtin) {4271 if (instruction->new_stack == nullptr || instruction->is_async_call_builtin) {
4259 result = ZigLLVMBuildCall(g->builder, fn_val,4272 result = ZigLLVMBuildCall(g->builder, fn_val,
4260 gen_param_values.items, (unsigned)gen_param_values.length, llvm_cc, fn_inline, "");4273 gen_param_values.items, (unsigned)gen_param_values.length, llvm_cc, call_attr, "");
4261 } else if (instruction->modifier == CallModifierAsync) {4274 } else if (instruction->modifier == CallModifierAsync) {
4262 zig_panic("TODO @asyncCall of non-async function");4275 zig_panic("TODO @asyncCall of non-async function");
4263 } else {4276 } else {
...@@ -4269,7 +4282,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -4269,7 +4282,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
4269 }4282 }
4270 gen_set_stack_pointer(g, new_stack_addr);4283 gen_set_stack_pointer(g, new_stack_addr);
4271 result = ZigLLVMBuildCall(g->builder, fn_val,4284 result = ZigLLVMBuildCall(g->builder, fn_val,
4272 gen_param_values.items, (unsigned)gen_param_values.length, llvm_cc, fn_inline, "");4285 gen_param_values.items, (unsigned)gen_param_values.length, llvm_cc, call_attr, "");
4273 if (src_return_type->id != ZigTypeIdUnreachable) {4286 if (src_return_type->id != ZigTypeIdUnreachable) {
4274 LLVMValueRef stackrestore_fn_val = get_stackrestore_fn_val(g);4287 LLVMValueRef stackrestore_fn_val = get_stackrestore_fn_val(g);
4275 LLVMBuildCall(g->builder, stackrestore_fn_val, &old_stack_ref, 1, "");4288 LLVMBuildCall(g->builder, stackrestore_fn_val, &old_stack_ref, 1, "");
...@@ -4317,8 +4330,17 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa...@@ -4317,8 +4330,17 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa
4317 return struct_ptr;4330 return struct_ptr;
4318 }4331 }
43194332
4320 ZigType *struct_type = (struct_ptr_type->id == ZigTypeIdPointer) ?4333 ZigType *struct_type;
4321 struct_ptr_type->data.pointer.child_type : struct_ptr_type;4334 if (struct_ptr_type->id == ZigTypeIdPointer) {
4335 if (struct_ptr_type->data.pointer.inferred_struct_field != nullptr) {
4336 struct_type = struct_ptr_type->data.pointer.inferred_struct_field->inferred_struct_type;
4337 } else {
4338 struct_type = struct_ptr_type->data.pointer.child_type;
4339 }
4340 } else {
4341 struct_type = struct_ptr_type;
4342 }
4343
4322 if ((err = type_resolve(g, struct_type, ResolveStatusLLVMFull)))4344 if ((err = type_resolve(g, struct_type, ResolveStatusLLVMFull)))
4323 codegen_report_errors_and_exit(g);4345 codegen_report_errors_and_exit(g);
43244346
...@@ -4947,7 +4969,7 @@ static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, IrExecutable *executable...@@ -4947,7 +4969,7 @@ static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, IrExecutable *executable
49474969
4948 LLVMValueRef enum_tag_value = ir_llvm_value(g, instruction->target);4970 LLVMValueRef enum_tag_value = ir_llvm_value(g, instruction->target);
4949 return ZigLLVMBuildCall(g->builder, enum_name_function, &enum_tag_value, 1,4971 return ZigLLVMBuildCall(g->builder, enum_name_function, &enum_tag_value, 1,
4950 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");4972 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, "");
4951}4973}
49524974
4953static LLVMValueRef ir_render_field_parent_ptr(CodeGen *g, IrExecutable *executable,4975static LLVMValueRef ir_render_field_parent_ptr(CodeGen *g, IrExecutable *executable,
...@@ -5903,7 +5925,7 @@ static LLVMValueRef gen_await_early_return(CodeGen *g, IrInstruction *source_ins...@@ -5903,7 +5925,7 @@ static LLVMValueRef gen_await_early_return(CodeGen *g, IrInstruction *source_ins
5903 LLVMValueRef dest_trace_ptr = get_cur_err_ret_trace_val(g, source_instr->scope, &is_llvm_alloca);5925 LLVMValueRef dest_trace_ptr = get_cur_err_ret_trace_val(g, source_instr->scope, &is_llvm_alloca);
5904 LLVMValueRef args[] = { dest_trace_ptr, src_trace_ptr };5926 LLVMValueRef args[] = { dest_trace_ptr, src_trace_ptr };
5905 ZigLLVMBuildCall(g->builder, get_merge_err_ret_traces_fn_val(g), args, 2,5927 ZigLLVMBuildCall(g->builder, get_merge_err_ret_traces_fn_val(g), args, 2,
5906 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");5928 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, "");
5907 }5929 }
5908 if (non_async && type_has_bits(result_type)) {5930 if (non_async && type_has_bits(result_type)) {
5909 LLVMValueRef result_ptr = (result_loc == nullptr) ? their_result_ptr : result_loc;5931 LLVMValueRef result_ptr = (result_loc == nullptr) ? their_result_ptr : result_loc;
...@@ -6137,7 +6159,9 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -6137,7 +6159,9 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
6137 case IrInstructionIdLoadPtr:6159 case IrInstructionIdLoadPtr:
6138 case IrInstructionIdHasDecl:6160 case IrInstructionIdHasDecl:
6139 case IrInstructionIdUndeclaredIdent:6161 case IrInstructionIdUndeclaredIdent:
6162 case IrInstructionIdCallExtra:
6140 case IrInstructionIdCallSrc:6163 case IrInstructionIdCallSrc:
6164 case IrInstructionIdCallSrcArgs:
6141 case IrInstructionIdAllocaSrc:6165 case IrInstructionIdAllocaSrc:
6142 case IrInstructionIdEndExpr:6166 case IrInstructionIdEndExpr:
6143 case IrInstructionIdImplicitCast:6167 case IrInstructionIdImplicitCast:
...@@ -8118,8 +8142,6 @@ static void define_builtin_fns(CodeGen *g) {...@@ -8118,8 +8142,6 @@ static void define_builtin_fns(CodeGen *g) {
8118 create_builtin_fn(g, BuiltinFnIdNearbyInt, "nearbyInt", 2);8142 create_builtin_fn(g, BuiltinFnIdNearbyInt, "nearbyInt", 2);
8119 create_builtin_fn(g, BuiltinFnIdRound, "round", 2);8143 create_builtin_fn(g, BuiltinFnIdRound, "round", 2);
8120 create_builtin_fn(g, BuiltinFnIdMulAdd, "mulAdd", 4);8144 create_builtin_fn(g, BuiltinFnIdMulAdd, "mulAdd", 4);
8121 create_builtin_fn(g, BuiltinFnIdInlineCall, "inlineCall", SIZE_MAX);
8122 create_builtin_fn(g, BuiltinFnIdNoInlineCall, "noInlineCall", SIZE_MAX);
8123 create_builtin_fn(g, BuiltinFnIdNewStackCall, "newStackCall", SIZE_MAX);8145 create_builtin_fn(g, BuiltinFnIdNewStackCall, "newStackCall", SIZE_MAX);
8124 create_builtin_fn(g, BuiltinFnIdAsyncCall, "asyncCall", SIZE_MAX);8146 create_builtin_fn(g, BuiltinFnIdAsyncCall, "asyncCall", SIZE_MAX);
8125 create_builtin_fn(g, BuiltinFnIdTypeId, "typeId", 1);8147 create_builtin_fn(g, BuiltinFnIdTypeId, "typeId", 1);
...@@ -8146,6 +8168,7 @@ static void define_builtin_fns(CodeGen *g) {...@@ -8146,6 +8168,7 @@ static void define_builtin_fns(CodeGen *g) {
8146 create_builtin_fn(g, BuiltinFnIdFrameAddress, "frameAddress", 0);8168 create_builtin_fn(g, BuiltinFnIdFrameAddress, "frameAddress", 0);
8147 create_builtin_fn(g, BuiltinFnIdFrameSize, "frameSize", 1);8169 create_builtin_fn(g, BuiltinFnIdFrameSize, "frameSize", 1);
8148 create_builtin_fn(g, BuiltinFnIdAs, "as", 2);8170 create_builtin_fn(g, BuiltinFnIdAs, "as", 2);
8171 create_builtin_fn(g, BuiltinFnIdCall, "call", 3);
8149}8172}
81508173
8151static const char *bool_to_str(bool b) {8174static const char *bool_to_str(bool b) {
src/ir.cpp+462-203
...@@ -265,6 +265,7 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction...@@ -265,6 +265,7 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction
265static IrInstruction *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_name,265static IrInstruction *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_name,
266 IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type);266 IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type);
267static ResultLoc *no_result_loc(void);267static ResultLoc *no_result_loc(void);
268static IrInstruction *ir_analyze_test_non_null(IrAnalyze *ira, IrInstruction *source_inst, IrInstruction *value);
268269
269static void destroy_instruction(IrInstruction *inst) {270static void destroy_instruction(IrInstruction *inst) {
270#ifdef ZIG_ENABLE_MEM_PROFILE271#ifdef ZIG_ENABLE_MEM_PROFILE
...@@ -289,6 +290,10 @@ static void destroy_instruction(IrInstruction *inst) {...@@ -289,6 +290,10 @@ static void destroy_instruction(IrInstruction *inst) {
289 return destroy(reinterpret_cast<IrInstructionCast *>(inst), name);290 return destroy(reinterpret_cast<IrInstructionCast *>(inst), name);
290 case IrInstructionIdCallSrc:291 case IrInstructionIdCallSrc:
291 return destroy(reinterpret_cast<IrInstructionCallSrc *>(inst), name);292 return destroy(reinterpret_cast<IrInstructionCallSrc *>(inst), name);
293 case IrInstructionIdCallSrcArgs:
294 return destroy(reinterpret_cast<IrInstructionCallSrcArgs *>(inst), name);
295 case IrInstructionIdCallExtra:
296 return destroy(reinterpret_cast<IrInstructionCallExtra *>(inst), name);
292 case IrInstructionIdCallGen:297 case IrInstructionIdCallGen:
293 return destroy(reinterpret_cast<IrInstructionCallGen *>(inst), name);298 return destroy(reinterpret_cast<IrInstructionCallGen *>(inst), name);
294 case IrInstructionIdUnOp:299 case IrInstructionIdUnOp:
...@@ -646,6 +651,15 @@ static ZigValue *const_ptr_pointee_unchecked(CodeGen *g, ZigValue *const_val) {...@@ -646,6 +651,15 @@ static ZigValue *const_ptr_pointee_unchecked(CodeGen *g, ZigValue *const_val) {
646 assert(const_val->special == ConstValSpecialStatic);651 assert(const_val->special == ConstValSpecialStatic);
647 ZigValue *result;652 ZigValue *result;
648653
654 InferredStructField *isf = const_val->type->data.pointer.inferred_struct_field;
655 if (isf != nullptr) {
656 TypeStructField *field = find_struct_type_field(isf->inferred_struct_type, isf->field_name);
657 assert(field != nullptr);
658 assert(const_val->data.x_ptr.special == ConstPtrSpecialRef);
659 ZigValue *struct_val = const_val->data.x_ptr.data.ref.pointee;
660 return struct_val->data.x_struct.fields[field->src_index];
661 }
662
649 switch (type_has_one_possible_value(g, const_val->type->data.pointer.child_type)) {663 switch (type_has_one_possible_value(g, const_val->type->data.pointer.child_type)) {
650 case OnePossibleValueInvalid:664 case OnePossibleValueInvalid:
651 zig_unreachable();665 zig_unreachable();
...@@ -705,6 +719,13 @@ static bool is_opt_err_set(ZigType *ty) {...@@ -705,6 +719,13 @@ static bool is_opt_err_set(ZigType *ty) {
705 (ty->id == ZigTypeIdOptional && ty->data.maybe.child_type->id == ZigTypeIdErrorSet);719 (ty->id == ZigTypeIdOptional && ty->data.maybe.child_type->id == ZigTypeIdErrorSet);
706}720}
707721
722static bool is_tuple(ZigType *type) {
723 return type->id == ZigTypeIdStruct && type->data.structure.decl_node != nullptr &&
724 type->data.structure.decl_node->type == NodeTypeContainerInitExpr &&
725 (type->data.structure.decl_node->data.container_init_expr.kind == ContainerInitKindArray ||
726 type->data.structure.decl_node->data.container_init_expr.entries.length == 0);
727}
728
708static bool is_slice(ZigType *type) {729static bool is_slice(ZigType *type) {
709 return type->id == ZigTypeIdStruct && type->data.structure.is_slice;730 return type->id == ZigTypeIdStruct && type->data.structure.is_slice;
710}731}
...@@ -968,6 +989,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCallSrc *) {...@@ -968,6 +989,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCallSrc *) {
968 return IrInstructionIdCallSrc;989 return IrInstructionIdCallSrc;
969}990}
970991
992static constexpr IrInstructionId ir_instruction_id(IrInstructionCallSrcArgs *) {
993 return IrInstructionIdCallSrcArgs;
994}
995
996static constexpr IrInstructionId ir_instruction_id(IrInstructionCallExtra *) {
997 return IrInstructionIdCallExtra;
998}
999
971static constexpr IrInstructionId ir_instruction_id(IrInstructionCallGen *) {1000static constexpr IrInstructionId ir_instruction_id(IrInstructionCallGen *) {
972 return IrInstructionIdCallGen;1001 return IrInstructionIdCallGen;
973}1002}
...@@ -1891,30 +1920,61 @@ static IrInstruction *ir_build_union_field_ptr(IrBuilder *irb, Scope *scope, Ast...@@ -1891,30 +1920,61 @@ static IrInstruction *ir_build_union_field_ptr(IrBuilder *irb, Scope *scope, Ast
1891 return &instruction->base;1920 return &instruction->base;
1892}1921}
18931922
1923static IrInstruction *ir_build_call_extra(IrBuilder *irb, Scope *scope, AstNode *source_node,
1924 IrInstruction *options, IrInstruction *fn_ref, IrInstruction *args, ResultLoc *result_loc)
1925{
1926 IrInstructionCallExtra *call_instruction = ir_build_instruction<IrInstructionCallExtra>(irb, scope, source_node);
1927 call_instruction->options = options;
1928 call_instruction->fn_ref = fn_ref;
1929 call_instruction->args = args;
1930 call_instruction->result_loc = result_loc;
1931
1932 ir_ref_instruction(options, irb->current_basic_block);
1933 ir_ref_instruction(fn_ref, irb->current_basic_block);
1934 ir_ref_instruction(args, irb->current_basic_block);
1935
1936 return &call_instruction->base;
1937}
1938
1939static IrInstruction *ir_build_call_src_args(IrBuilder *irb, Scope *scope, AstNode *source_node,
1940 IrInstruction *options, IrInstruction *fn_ref, IrInstruction **args_ptr, size_t args_len,
1941 ResultLoc *result_loc)
1942{
1943 IrInstructionCallSrcArgs *call_instruction = ir_build_instruction<IrInstructionCallSrcArgs>(irb, scope, source_node);
1944 call_instruction->options = options;
1945 call_instruction->fn_ref = fn_ref;
1946 call_instruction->args_ptr = args_ptr;
1947 call_instruction->args_len = args_len;
1948 call_instruction->result_loc = result_loc;
1949
1950 ir_ref_instruction(options, irb->current_basic_block);
1951 ir_ref_instruction(fn_ref, irb->current_basic_block);
1952 for (size_t i = 0; i < args_len; i += 1)
1953 ir_ref_instruction(args_ptr[i], irb->current_basic_block);
1954
1955 return &call_instruction->base;
1956}
1957
1894static IrInstruction *ir_build_call_src(IrBuilder *irb, Scope *scope, AstNode *source_node,1958static IrInstruction *ir_build_call_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
1895 ZigFn *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args,1959 ZigFn *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args,
1896 bool is_comptime, FnInline fn_inline, CallModifier modifier, bool is_async_call_builtin,1960 IrInstruction *ret_ptr, CallModifier modifier, bool is_async_call_builtin,
1897 IrInstruction *new_stack, ResultLoc *result_loc)1961 IrInstruction *new_stack, ResultLoc *result_loc)
1898{1962{
1899 IrInstructionCallSrc *call_instruction = ir_build_instruction<IrInstructionCallSrc>(irb, scope, source_node);1963 IrInstructionCallSrc *call_instruction = ir_build_instruction<IrInstructionCallSrc>(irb, scope, source_node);
1900 call_instruction->fn_entry = fn_entry;1964 call_instruction->fn_entry = fn_entry;
1901 call_instruction->fn_ref = fn_ref;1965 call_instruction->fn_ref = fn_ref;
1902 call_instruction->is_comptime = is_comptime;
1903 call_instruction->fn_inline = fn_inline;
1904 call_instruction->args = args;1966 call_instruction->args = args;
1905 call_instruction->arg_count = arg_count;1967 call_instruction->arg_count = arg_count;
1906 call_instruction->modifier = modifier;1968 call_instruction->modifier = modifier;
1907 call_instruction->is_async_call_builtin = is_async_call_builtin;1969 call_instruction->is_async_call_builtin = is_async_call_builtin;
1908 call_instruction->new_stack = new_stack;1970 call_instruction->new_stack = new_stack;
1909 call_instruction->result_loc = result_loc;1971 call_instruction->result_loc = result_loc;
1972 call_instruction->ret_ptr = ret_ptr;
19101973
1911 if (fn_ref != nullptr) ir_ref_instruction(fn_ref, irb->current_basic_block);1974 if (fn_ref != nullptr) ir_ref_instruction(fn_ref, irb->current_basic_block);
1912 for (size_t i = 0; i < arg_count; i += 1)1975 for (size_t i = 0; i < arg_count; i += 1)
1913 ir_ref_instruction(args[i], irb->current_basic_block);1976 ir_ref_instruction(args[i], irb->current_basic_block);
1914 if (modifier == CallModifierAsync && new_stack != nullptr) {1977 if (ret_ptr != nullptr) ir_ref_instruction(ret_ptr, irb->current_basic_block);
1915 // in this case the arg at the end is the return pointer
1916 ir_ref_instruction(args[arg_count], irb->current_basic_block);
1917 }
1918 if (new_stack != nullptr) ir_ref_instruction(new_stack, irb->current_basic_block);1978 if (new_stack != nullptr) ir_ref_instruction(new_stack, irb->current_basic_block);
19191979
1920 return &call_instruction->base;1980 return &call_instruction->base;
...@@ -1922,7 +1982,7 @@ static IrInstruction *ir_build_call_src(IrBuilder *irb, Scope *scope, AstNode *s...@@ -1922,7 +1982,7 @@ static IrInstruction *ir_build_call_src(IrBuilder *irb, Scope *scope, AstNode *s
19221982
1923static IrInstructionCallGen *ir_build_call_gen(IrAnalyze *ira, IrInstruction *source_instruction,1983static IrInstructionCallGen *ir_build_call_gen(IrAnalyze *ira, IrInstruction *source_instruction,
1924 ZigFn *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args,1984 ZigFn *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args,
1925 FnInline fn_inline, CallModifier modifier, IrInstruction *new_stack, bool is_async_call_builtin,1985 CallModifier modifier, IrInstruction *new_stack, bool is_async_call_builtin,
1926 IrInstruction *result_loc, ZigType *return_type)1986 IrInstruction *result_loc, ZigType *return_type)
1927{1987{
1928 IrInstructionCallGen *call_instruction = ir_build_instruction<IrInstructionCallGen>(&ira->new_irb,1988 IrInstructionCallGen *call_instruction = ir_build_instruction<IrInstructionCallGen>(&ira->new_irb,
...@@ -1930,7 +1990,6 @@ static IrInstructionCallGen *ir_build_call_gen(IrAnalyze *ira, IrInstruction *so...@@ -1930,7 +1990,6 @@ static IrInstructionCallGen *ir_build_call_gen(IrAnalyze *ira, IrInstruction *so
1930 call_instruction->base.value->type = return_type;1990 call_instruction->base.value->type = return_type;
1931 call_instruction->fn_entry = fn_entry;1991 call_instruction->fn_entry = fn_entry;
1932 call_instruction->fn_ref = fn_ref;1992 call_instruction->fn_ref = fn_ref;
1933 call_instruction->fn_inline = fn_inline;
1934 call_instruction->args = args;1993 call_instruction->args = args;
1935 call_instruction->arg_count = arg_count;1994 call_instruction->arg_count = arg_count;
1936 call_instruction->modifier = modifier;1995 call_instruction->modifier = modifier;
...@@ -5054,10 +5113,7 @@ static IrInstruction *ir_gen_async_call(IrBuilder *irb, Scope *scope, AstNode *a...@@ -5054,10 +5113,7 @@ static IrInstruction *ir_gen_async_call(IrBuilder *irb, Scope *scope, AstNode *a
5054 return fn_ref;5113 return fn_ref;
50555114
5056 size_t arg_count = call_node->data.fn_call_expr.params.length - arg_offset;5115 size_t arg_count = call_node->data.fn_call_expr.params.length - arg_offset;
50575116 IrInstruction **args = allocate<IrInstruction*>(arg_count);
5058 // last "arg" is return pointer
5059 IrInstruction **args = allocate<IrInstruction*>(arg_count + 1);
5060
5061 for (size_t i = 0; i < arg_count; i += 1) {5117 for (size_t i = 0; i < arg_count; i += 1) {
5062 AstNode *arg_node = call_node->data.fn_call_expr.params.at(i + arg_offset);5118 AstNode *arg_node = call_node->data.fn_call_expr.params.at(i + arg_offset);
5063 IrInstruction *arg = ir_gen_node(irb, arg_node, scope);5119 IrInstruction *arg = ir_gen_node(irb, arg_node, scope);
...@@ -5066,15 +5122,50 @@ static IrInstruction *ir_gen_async_call(IrBuilder *irb, Scope *scope, AstNode *a...@@ -5066,15 +5122,50 @@ static IrInstruction *ir_gen_async_call(IrBuilder *irb, Scope *scope, AstNode *a
5066 args[i] = arg;5122 args[i] = arg;
5067 }5123 }
50685124
5069 args[arg_count] = ret_ptr;
5070
5071 CallModifier modifier = (await_node == nullptr) ? CallModifierAsync : CallModifierNone;5125 CallModifier modifier = (await_node == nullptr) ? CallModifierAsync : CallModifierNone;
5072 bool is_async_call_builtin = true;5126 bool is_async_call_builtin = true;
5073 IrInstruction *call = ir_build_call_src(irb, scope, call_node, nullptr, fn_ref, arg_count, args, false,5127 IrInstruction *call = ir_build_call_src(irb, scope, call_node, nullptr, fn_ref, arg_count, args,
5074 FnInlineAuto, modifier, is_async_call_builtin, bytes, result_loc);5128 ret_ptr, modifier, is_async_call_builtin, bytes, result_loc);
5075 return ir_lval_wrap(irb, scope, call, lval, result_loc);5129 return ir_lval_wrap(irb, scope, call, lval, result_loc);
5076}5130}
50775131
5132static IrInstruction *ir_gen_fn_call_with_args(IrBuilder *irb, Scope *scope, AstNode *source_node,
5133 AstNode *fn_ref_node, CallModifier modifier, IrInstruction *options,
5134 AstNode **args_ptr, size_t args_len, LVal lval, ResultLoc *result_loc)
5135{
5136 IrInstruction *fn_ref = ir_gen_node(irb, fn_ref_node, scope);
5137 if (fn_ref == irb->codegen->invalid_instruction)
5138 return fn_ref;
5139
5140 IrInstruction *fn_type = ir_build_typeof(irb, scope, source_node, fn_ref);
5141
5142 IrInstruction **args = allocate<IrInstruction*>(args_len);
5143 for (size_t i = 0; i < args_len; i += 1) {
5144 AstNode *arg_node = args_ptr[i];
5145
5146 IrInstruction *arg_index = ir_build_const_usize(irb, scope, arg_node, i);
5147 IrInstruction *arg_type = ir_build_arg_type(irb, scope, source_node, fn_type, arg_index, true);
5148 ResultLoc *no_result = no_result_loc();
5149 ir_build_reset_result(irb, scope, source_node, no_result);
5150 ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, arg_type, no_result);
5151
5152 IrInstruction *arg = ir_gen_node_extra(irb, arg_node, scope, LValNone, &result_loc_cast->base);
5153 if (arg == irb->codegen->invalid_instruction)
5154 return arg;
5155
5156 args[i] = ir_build_implicit_cast(irb, scope, arg_node, arg, result_loc_cast);
5157 }
5158
5159 IrInstruction *fn_call;
5160 if (options != nullptr) {
5161 fn_call = ir_build_call_src_args(irb, scope, source_node, options, fn_ref, args, args_len, result_loc);
5162 } else {
5163 fn_call = ir_build_call_src(irb, scope, source_node, nullptr, fn_ref, args_len, args, nullptr,
5164 modifier, false, nullptr, result_loc);
5165 }
5166 return ir_lval_wrap(irb, scope, fn_call, lval, result_loc);
5167}
5168
5078static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,5169static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
5079 ResultLoc *result_loc)5170 ResultLoc *result_loc)
5080{5171{
...@@ -5993,34 +6084,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -5993,34 +6084,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
5993 IrInstruction *offset_of = ir_build_bit_offset_of(irb, scope, node, arg0_value, arg1_value);6084 IrInstruction *offset_of = ir_build_bit_offset_of(irb, scope, node, arg0_value, arg1_value);
5994 return ir_lval_wrap(irb, scope, offset_of, lval, result_loc);6085 return ir_lval_wrap(irb, scope, offset_of, lval, result_loc);
5995 }6086 }
5996 case BuiltinFnIdInlineCall:
5997 case BuiltinFnIdNoInlineCall:
5998 {
5999 if (node->data.fn_call_expr.params.length == 0) {
6000 add_node_error(irb->codegen, node, buf_sprintf("expected at least 1 argument, found 0"));
6001 return irb->codegen->invalid_instruction;
6002 }
6003
6004 AstNode *fn_ref_node = node->data.fn_call_expr.params.at(0);
6005 IrInstruction *fn_ref = ir_gen_node(irb, fn_ref_node, scope);
6006 if (fn_ref == irb->codegen->invalid_instruction)
6007 return fn_ref;
6008
6009 size_t arg_count = node->data.fn_call_expr.params.length - 1;
6010
6011 IrInstruction **args = allocate<IrInstruction*>(arg_count);
6012 for (size_t i = 0; i < arg_count; i += 1) {
6013 AstNode *arg_node = node->data.fn_call_expr.params.at(i + 1);
6014 args[i] = ir_gen_node(irb, arg_node, scope);
6015 if (args[i] == irb->codegen->invalid_instruction)
6016 return args[i];
6017 }
6018 FnInline fn_inline = (builtin_fn->id == BuiltinFnIdInlineCall) ? FnInlineAlways : FnInlineNever;
6019
6020 IrInstruction *call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false,
6021 fn_inline, CallModifierNone, false, nullptr, result_loc);
6022 return ir_lval_wrap(irb, scope, call, lval, result_loc);
6023 }
6024 case BuiltinFnIdNewStackCall:6087 case BuiltinFnIdNewStackCall:
6025 {6088 {
6026 if (node->data.fn_call_expr.params.length < 2) {6089 if (node->data.fn_call_expr.params.length < 2) {
...@@ -6050,10 +6113,52 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -6050,10 +6113,52 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
6050 return args[i];6113 return args[i];
6051 }6114 }
60526115
6053 IrInstruction *call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false,6116 IrInstruction *call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args,
6054 FnInlineAuto, CallModifierNone, false, new_stack, result_loc);6117 nullptr, CallModifierNone, false, new_stack, result_loc);
6118 return ir_lval_wrap(irb, scope, call, lval, result_loc);
6119 }
6120 case BuiltinFnIdCall: {
6121 // Cast the options parameter to the options type
6122 ZigType *options_type = get_builtin_type(irb->codegen, "CallOptions");
6123 IrInstruction *options_type_inst = ir_build_const_type(irb, scope, node, options_type);
6124 ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, options_type_inst, no_result_loc());
6125
6126 AstNode *options_node = node->data.fn_call_expr.params.at(0);
6127 IrInstruction *options_inner = ir_gen_node_extra(irb, options_node, scope,
6128 LValNone, &result_loc_cast->base);
6129 if (options_inner == irb->codegen->invalid_instruction)
6130 return options_inner;
6131 IrInstruction *options = ir_build_implicit_cast(irb, scope, options_node, options_inner, result_loc_cast);
6132
6133 AstNode *fn_ref_node = node->data.fn_call_expr.params.at(1);
6134 AstNode *args_node = node->data.fn_call_expr.params.at(2);
6135 if (args_node->type == NodeTypeContainerInitExpr) {
6136 if (args_node->data.container_init_expr.kind == ContainerInitKindArray ||
6137 args_node->data.container_init_expr.entries.length == 0)
6138 {
6139 return ir_gen_fn_call_with_args(irb, scope, node,
6140 fn_ref_node, CallModifierNone, options,
6141 args_node->data.container_init_expr.entries.items,
6142 args_node->data.container_init_expr.entries.length,
6143 lval, result_loc);
6144 } else {
6145 exec_add_error_node(irb->codegen, irb->exec, args_node,
6146 buf_sprintf("TODO: @call with anon struct literal"));
6147 return irb->codegen->invalid_instruction;
6148 }
6149 } else {
6150 IrInstruction *fn_ref = ir_gen_node(irb, fn_ref_node, scope);
6151 if (fn_ref == irb->codegen->invalid_instruction)
6152 return fn_ref;
6153
6154 IrInstruction *args = ir_gen_node(irb, args_node, scope);
6155 if (args == irb->codegen->invalid_instruction)
6156 return args;
6157
6158 IrInstruction *call = ir_build_call_extra(irb, scope, node, options, fn_ref, args, result_loc);
6055 return ir_lval_wrap(irb, scope, call, lval, result_loc);6159 return ir_lval_wrap(irb, scope, call, lval, result_loc);
6056 }6160 }
6161 }
6057 case BuiltinFnIdAsyncCall:6162 case BuiltinFnIdAsyncCall:
6058 return ir_gen_async_call(irb, scope, nullptr, node, lval, result_loc);6163 return ir_gen_async_call(irb, scope, nullptr, node, lval, result_loc);
6059 case BuiltinFnIdTypeId:6164 case BuiltinFnIdTypeId:
...@@ -6371,33 +6476,8 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node...@@ -6371,33 +6476,8 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node
6371 return ir_gen_builtin_fn_call(irb, scope, node, lval, result_loc);6476 return ir_gen_builtin_fn_call(irb, scope, node, lval, result_loc);
63726477
6373 AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr;6478 AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr;
6374 IrInstruction *fn_ref = ir_gen_node(irb, fn_ref_node, scope);6479 return ir_gen_fn_call_with_args(irb, scope, node, fn_ref_node, node->data.fn_call_expr.modifier,
6375 if (fn_ref == irb->codegen->invalid_instruction)6480 nullptr, node->data.fn_call_expr.params.items, node->data.fn_call_expr.params.length, lval, result_loc);
6376 return fn_ref;
6377
6378 IrInstruction *fn_type = ir_build_typeof(irb, scope, node, fn_ref);
6379
6380 size_t arg_count = node->data.fn_call_expr.params.length;
6381 IrInstruction **args = allocate<IrInstruction*>(arg_count);
6382 for (size_t i = 0; i < arg_count; i += 1) {
6383 AstNode *arg_node = node->data.fn_call_expr.params.at(i);
6384
6385 IrInstruction *arg_index = ir_build_const_usize(irb, scope, arg_node, i);
6386 IrInstruction *arg_type = ir_build_arg_type(irb, scope, node, fn_type, arg_index, true);
6387 ResultLoc *no_result = no_result_loc();
6388 ir_build_reset_result(irb, scope, node, no_result);
6389 ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, arg_type, no_result);
6390
6391 IrInstruction *arg = ir_gen_node_extra(irb, arg_node, scope, LValNone, &result_loc_cast->base);
6392 if (arg == irb->codegen->invalid_instruction)
6393 return arg;
6394
6395 args[i] = ir_build_implicit_cast(irb, scope, arg_node, arg, result_loc_cast);
6396 }
6397
6398 IrInstruction *fn_call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false,
6399 FnInlineAuto, node->data.fn_call_expr.modifier, false, nullptr, result_loc);
6400 return ir_lval_wrap(irb, scope, fn_call, lval, result_loc);
6401}6481}
64026482
6403static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,6483static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
...@@ -13278,6 +13358,15 @@ static IrInstruction *ir_analyze_struct_value_field_value(IrAnalyze *ira, IrInst...@@ -13278,6 +13358,15 @@ static IrInstruction *ir_analyze_struct_value_field_value(IrAnalyze *ira, IrInst
13278 return ir_get_deref(ira, source_instr, field_ptr, nullptr);13358 return ir_get_deref(ira, source_instr, field_ptr, nullptr);
13279}13359}
1328013360
13361static IrInstruction *ir_analyze_optional_value_payload_value(IrAnalyze *ira, IrInstruction *source_instr,
13362 IrInstruction *optional_operand, bool safety_check_on)
13363{
13364 IrInstruction *opt_ptr = ir_get_ref(ira, source_instr, optional_operand, true, false);
13365 IrInstruction *payload_ptr = ir_analyze_unwrap_optional_payload(ira, source_instr, opt_ptr,
13366 safety_check_on, false);
13367 return ir_get_deref(ira, source_instr, payload_ptr, nullptr);
13368}
13369
13281static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,13370static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
13282 ZigType *wanted_type, IrInstruction *value)13371 ZigType *wanted_type, IrInstruction *value)
13283{13372{
...@@ -13911,6 +14000,20 @@ static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, Zig...@@ -13911,6 +14000,20 @@ static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, Zig
13911 return ir_implicit_cast2(ira, value, value, expected_type);14000 return ir_implicit_cast2(ira, value, value, expected_type);
13912}14001}
1391314002
14003static ZigType *get_ptr_elem_type(CodeGen *g, IrInstruction *ptr) {
14004 ir_assert(ptr->value->type->id == ZigTypeIdPointer, ptr);
14005 ZigType *elem_type = ptr->value->type->data.pointer.child_type;
14006 if (elem_type != g->builtin_types.entry_var)
14007 return elem_type;
14008
14009 if (ir_resolve_lazy(g, ptr->source_node, ptr->value))
14010 return g->builtin_types.entry_invalid;
14011
14012 assert(value_is_comptime(ptr->value));
14013 ZigValue *pointee = const_ptr_pointee_unchecked(g, ptr->value);
14014 return pointee->type;
14015}
14016
13914static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr,14017static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr,
13915 ResultLoc *result_loc)14018 ResultLoc *result_loc)
13916{14019{
...@@ -13927,6 +14030,8 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc...@@ -13927,6 +14030,8 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
13927 }14030 }
1392814031
13929 ZigType *child_type = ptr_type->data.pointer.child_type;14032 ZigType *child_type = ptr_type->data.pointer.child_type;
14033 if (type_is_invalid(child_type))
14034 return ira->codegen->invalid_instruction;
13930 // if the child type has one possible value, the deref is comptime14035 // if the child type has one possible value, the deref is comptime
13931 switch (type_has_one_possible_value(ira->codegen, child_type)) {14036 switch (type_has_one_possible_value(ira->codegen, child_type)) {
13932 case OnePossibleValueInvalid:14037 case OnePossibleValueInvalid:
...@@ -14102,9 +14207,7 @@ static bool ir_resolve_atomic_order(IrAnalyze *ira, IrInstruction *value, Atomic...@@ -14102,9 +14207,7 @@ static bool ir_resolve_atomic_order(IrAnalyze *ira, IrInstruction *value, Atomic
14102 if (type_is_invalid(value->value->type))14207 if (type_is_invalid(value->value->type))
14103 return false;14208 return false;
1410414209
14105 ZigValue *atomic_order_val = get_builtin_value(ira->codegen, "AtomicOrder");14210 ZigType *atomic_order_type = get_builtin_type(ira->codegen, "AtomicOrder");
14106 assert(atomic_order_val->type->id == ZigTypeIdMetaType);
14107 ZigType *atomic_order_type = atomic_order_val->data.x_type;
1410814211
14109 IrInstruction *casted_value = ir_implicit_cast(ira, value, atomic_order_type);14212 IrInstruction *casted_value = ir_implicit_cast(ira, value, atomic_order_type);
14110 if (type_is_invalid(casted_value->value->type))14213 if (type_is_invalid(casted_value->value->type))
...@@ -14122,9 +14225,7 @@ static bool ir_resolve_atomic_rmw_op(IrAnalyze *ira, IrInstruction *value, Atomi...@@ -14122,9 +14225,7 @@ static bool ir_resolve_atomic_rmw_op(IrAnalyze *ira, IrInstruction *value, Atomi
14122 if (type_is_invalid(value->value->type))14225 if (type_is_invalid(value->value->type))
14123 return false;14226 return false;
1412414227
14125 ZigValue *atomic_rmw_op_val = get_builtin_value(ira->codegen, "AtomicRmwOp");14228 ZigType *atomic_rmw_op_type = get_builtin_type(ira->codegen, "AtomicRmwOp");
14126 assert(atomic_rmw_op_val->type->id == ZigTypeIdMetaType);
14127 ZigType *atomic_rmw_op_type = atomic_rmw_op_val->data.x_type;
1412814229
14129 IrInstruction *casted_value = ir_implicit_cast(ira, value, atomic_rmw_op_type);14230 IrInstruction *casted_value = ir_implicit_cast(ira, value, atomic_rmw_op_type);
14130 if (type_is_invalid(casted_value->value->type))14231 if (type_is_invalid(casted_value->value->type))
...@@ -14142,9 +14243,7 @@ static bool ir_resolve_global_linkage(IrAnalyze *ira, IrInstruction *value, Glob...@@ -14142,9 +14243,7 @@ static bool ir_resolve_global_linkage(IrAnalyze *ira, IrInstruction *value, Glob
14142 if (type_is_invalid(value->value->type))14243 if (type_is_invalid(value->value->type))
14143 return false;14244 return false;
1414414245
14145 ZigValue *global_linkage_val = get_builtin_value(ira->codegen, "GlobalLinkage");14246 ZigType *global_linkage_type = get_builtin_type(ira->codegen, "GlobalLinkage");
14146 assert(global_linkage_val->type->id == ZigTypeIdMetaType);
14147 ZigType *global_linkage_type = global_linkage_val->data.x_type;
1414814247
14149 IrInstruction *casted_value = ir_implicit_cast(ira, value, global_linkage_type);14248 IrInstruction *casted_value = ir_implicit_cast(ira, value, global_linkage_type);
14150 if (type_is_invalid(casted_value->value->type))14249 if (type_is_invalid(casted_value->value->type))
...@@ -14162,9 +14261,7 @@ static bool ir_resolve_float_mode(IrAnalyze *ira, IrInstruction *value, FloatMod...@@ -14162,9 +14261,7 @@ static bool ir_resolve_float_mode(IrAnalyze *ira, IrInstruction *value, FloatMod
14162 if (type_is_invalid(value->value->type))14261 if (type_is_invalid(value->value->type))
14163 return false;14262 return false;
1416414263
14165 ZigValue *float_mode_val = get_builtin_value(ira->codegen, "FloatMode");14264 ZigType *float_mode_type = get_builtin_type(ira->codegen, "FloatMode");
14166 assert(float_mode_val->type->id == ZigTypeIdMetaType);
14167 ZigType *float_mode_type = float_mode_val->data.x_type;
1416814265
14169 IrInstruction *casted_value = ir_implicit_cast(ira, value, float_mode_type);14266 IrInstruction *casted_value = ir_implicit_cast(ira, value, float_mode_type);
14170 if (type_is_invalid(casted_value->value->type))14267 if (type_is_invalid(casted_value->value->type))
...@@ -16972,11 +17069,11 @@ static IrInstruction *ir_analyze_instruction_reset_result(IrAnalyze *ira, IrInst...@@ -16972,11 +17069,11 @@ static IrInstruction *ir_analyze_instruction_reset_result(IrAnalyze *ira, IrInst
16972 return ir_const_void(ira, &instruction->base);17069 return ir_const_void(ira, &instruction->base);
16973}17070}
1697417071
16975static IrInstruction *get_async_call_result_loc(IrAnalyze *ira, IrInstructionCallSrc *call_instruction,17072static IrInstruction *get_async_call_result_loc(IrAnalyze *ira, IrInstruction *source_instr,
16976 ZigType *fn_ret_type)17073 ZigType *fn_ret_type, bool is_async_call_builtin, IrInstruction **args_ptr, size_t args_len,
17074 IrInstruction *ret_ptr_uncasted)
16977{17075{
16978 ir_assert(call_instruction->is_async_call_builtin, &call_instruction->base);17076 ir_assert(is_async_call_builtin, source_instr);
16979 IrInstruction *ret_ptr_uncasted = call_instruction->args[call_instruction->arg_count]->child;
16980 if (type_is_invalid(ret_ptr_uncasted->value->type))17077 if (type_is_invalid(ret_ptr_uncasted->value->type))
16981 return ira->codegen->invalid_instruction;17078 return ira->codegen->invalid_instruction;
16982 if (ret_ptr_uncasted->value->type->id == ZigTypeIdVoid) {17079 if (ret_ptr_uncasted->value->type->id == ZigTypeIdVoid) {
...@@ -16986,9 +17083,10 @@ static IrInstruction *get_async_call_result_loc(IrAnalyze *ira, IrInstructionCal...@@ -16986,9 +17083,10 @@ static IrInstruction *get_async_call_result_loc(IrAnalyze *ira, IrInstructionCal
16986 return ir_implicit_cast(ira, ret_ptr_uncasted, get_pointer_to_type(ira->codegen, fn_ret_type, false));17083 return ir_implicit_cast(ira, ret_ptr_uncasted, get_pointer_to_type(ira->codegen, fn_ret_type, false));
16987}17084}
1698817085
16989static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction, ZigFn *fn_entry,17086static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstruction *source_instr, ZigFn *fn_entry,
16990 ZigType *fn_type, IrInstruction *fn_ref, IrInstruction **casted_args, size_t arg_count,17087 ZigType *fn_type, IrInstruction *fn_ref, IrInstruction **casted_args, size_t arg_count,
16991 IrInstruction *casted_new_stack)17088 IrInstruction *casted_new_stack, bool is_async_call_builtin, IrInstruction *ret_ptr_uncasted,
17089 ResultLoc *call_result_loc)
16992{17090{
16993 if (fn_entry == nullptr) {17091 if (fn_entry == nullptr) {
16994 if (fn_type->data.fn.fn_type_id.cc != CallingConventionAsync) {17092 if (fn_type->data.fn.fn_type_id.cc != CallingConventionAsync) {
...@@ -17003,19 +17101,20 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc...@@ -17003,19 +17101,20 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc
17003 }17101 }
17004 if (casted_new_stack != nullptr) {17102 if (casted_new_stack != nullptr) {
17005 ZigType *fn_ret_type = fn_type->data.fn.fn_type_id.return_type;17103 ZigType *fn_ret_type = fn_type->data.fn.fn_type_id.return_type;
17006 IrInstruction *ret_ptr = get_async_call_result_loc(ira, call_instruction, fn_ret_type);17104 IrInstruction *ret_ptr = get_async_call_result_loc(ira, source_instr, fn_ret_type, is_async_call_builtin,
17105 casted_args, arg_count, ret_ptr_uncasted);
17007 if (ret_ptr != nullptr && type_is_invalid(ret_ptr->value->type))17106 if (ret_ptr != nullptr && type_is_invalid(ret_ptr->value->type))
17008 return ira->codegen->invalid_instruction;17107 return ira->codegen->invalid_instruction;
1700917108
17010 ZigType *anyframe_type = get_any_frame_type(ira->codegen, fn_ret_type);17109 ZigType *anyframe_type = get_any_frame_type(ira->codegen, fn_ret_type);
1701117110
17012 IrInstructionCallGen *call_gen = ir_build_call_gen(ira, &call_instruction->base, fn_entry, fn_ref,17111 IrInstructionCallGen *call_gen = ir_build_call_gen(ira, source_instr, fn_entry, fn_ref,
17013 arg_count, casted_args, FnInlineAuto, CallModifierAsync, casted_new_stack,17112 arg_count, casted_args, CallModifierAsync, casted_new_stack,
17014 call_instruction->is_async_call_builtin, ret_ptr, anyframe_type);17113 is_async_call_builtin, ret_ptr, anyframe_type);
17015 return &call_gen->base;17114 return &call_gen->base;
17016 } else {17115 } else {
17017 ZigType *frame_type = get_fn_frame_type(ira->codegen, fn_entry);17116 ZigType *frame_type = get_fn_frame_type(ira->codegen, fn_entry);
17018 IrInstruction *result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,17117 IrInstruction *result_loc = ir_resolve_result(ira, source_instr, call_result_loc,
17019 frame_type, nullptr, true, true, false);17118 frame_type, nullptr, true, true, false);
17020 if (type_is_invalid(result_loc->value->type) || instr_is_unreachable(result_loc)) {17119 if (type_is_invalid(result_loc->value->type) || instr_is_unreachable(result_loc)) {
17021 return result_loc;17120 return result_loc;
...@@ -17023,9 +17122,9 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc...@@ -17023,9 +17122,9 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc
17023 result_loc = ir_implicit_cast(ira, result_loc, get_pointer_to_type(ira->codegen, frame_type, false));17122 result_loc = ir_implicit_cast(ira, result_loc, get_pointer_to_type(ira->codegen, frame_type, false));
17024 if (type_is_invalid(result_loc->value->type))17123 if (type_is_invalid(result_loc->value->type))
17025 return ira->codegen->invalid_instruction;17124 return ira->codegen->invalid_instruction;
17026 return &ir_build_call_gen(ira, &call_instruction->base, fn_entry, fn_ref, arg_count,17125 return &ir_build_call_gen(ira, source_instr, fn_entry, fn_ref, arg_count,
17027 casted_args, FnInlineAuto, CallModifierAsync, casted_new_stack,17126 casted_args, CallModifierAsync, casted_new_stack,
17028 call_instruction->is_async_call_builtin, result_loc, frame_type)->base;17127 is_async_call_builtin, result_loc, frame_type)->base;
17029 }17128 }
17030}17129}
17031static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node,17130static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node,
...@@ -17288,9 +17387,7 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source...@@ -17288,9 +17387,7 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
17288 copy_const_val(casted_ptr->value, ptr->value);17387 copy_const_val(casted_ptr->value, ptr->value);
17289 casted_ptr->value->type = struct_ptr_type;17388 casted_ptr->value->type = struct_ptr_type;
17290 } else {17389 } else {
17291 casted_ptr = ir_build_cast(&ira->new_irb, source_instr->scope,17390 casted_ptr = ptr;
17292 source_instr->source_node, struct_ptr_type, ptr, CastOpNoop);
17293 casted_ptr->value->type = struct_ptr_type;
17294 }17391 }
17295 if (instr_is_comptime(casted_ptr)) {17392 if (instr_is_comptime(casted_ptr)) {
17296 ZigValue *ptr_val = ir_resolve_const(ira, casted_ptr, UndefBad);17393 ZigValue *ptr_val = ir_resolve_const(ira, casted_ptr, UndefBad);
...@@ -17371,6 +17468,12 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source...@@ -17371,6 +17468,12 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
17371 }17468 }
17372 }17469 }
1737317470
17471 if (ptr->value->type->data.pointer.inferred_struct_field != nullptr &&
17472 child_type == ira->codegen->builtin_types.entry_var)
17473 {
17474 child_type = ptr->value->type->data.pointer.inferred_struct_field->inferred_struct_type;
17475 }
17476
17374 switch (type_requires_comptime(ira->codegen, child_type)) {17477 switch (type_requires_comptime(ira->codegen, child_type)) {
17375 case ReqCompTimeInvalid:17478 case ReqCompTimeInvalid:
17376 return ira->codegen->invalid_instruction;17479 return ira->codegen->invalid_instruction;
...@@ -17417,25 +17520,21 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source...@@ -17417,25 +17520,21 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
17417 return &store_ptr->base;17520 return &store_ptr->base;
17418}17521}
1741917522
17420static IrInstruction *analyze_casted_new_stack(IrAnalyze *ira, IrInstructionCallSrc *call_instruction,17523static IrInstruction *analyze_casted_new_stack(IrAnalyze *ira, IrInstruction *source_instr,
17421 ZigFn *fn_entry)17524 IrInstruction *new_stack, bool is_async_call_builtin, ZigFn *fn_entry)
17422{17525{
17423 if (call_instruction->new_stack == nullptr)17526 if (new_stack == nullptr)
17424 return nullptr;17527 return nullptr;
1742517528
17426 if (!call_instruction->is_async_call_builtin &&17529 if (!is_async_call_builtin &&
17427 arch_stack_pointer_register_name(ira->codegen->zig_target->arch) == nullptr)17530 arch_stack_pointer_register_name(ira->codegen->zig_target->arch) == nullptr)
17428 {17531 {
17429 ir_add_error(ira, &call_instruction->base,17532 ir_add_error(ira, source_instr,
17430 buf_sprintf("target arch '%s' does not support @newStackCall",17533 buf_sprintf("target arch '%s' does not support calling with a new stack",
17431 target_arch_name(ira->codegen->zig_target->arch)));17534 target_arch_name(ira->codegen->zig_target->arch)));
17432 }17535 }
1743317536
17434 IrInstruction *new_stack = call_instruction->new_stack->child;17537 if (is_async_call_builtin &&
17435 if (type_is_invalid(new_stack->value->type))
17436 return ira->codegen->invalid_instruction;
17437
17438 if (call_instruction->is_async_call_builtin &&
17439 fn_entry != nullptr && new_stack->value->type->id == ZigTypeIdPointer &&17538 fn_entry != nullptr && new_stack->value->type->id == ZigTypeIdPointer &&
17440 new_stack->value->type->data.pointer.child_type->id == ZigTypeIdFnFrame)17539 new_stack->value->type->data.pointer.child_type->id == ZigTypeIdFnFrame)
17441 {17540 {
...@@ -17451,9 +17550,11 @@ static IrInstruction *analyze_casted_new_stack(IrAnalyze *ira, IrInstructionCall...@@ -17451,9 +17550,11 @@ static IrInstruction *analyze_casted_new_stack(IrAnalyze *ira, IrInstructionCall
17451 }17550 }
17452}17551}
1745317552
17454static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction,17553static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstruction *source_instr,
17455 ZigFn *fn_entry, ZigType *fn_type, IrInstruction *fn_ref,17554 ZigFn *fn_entry, ZigType *fn_type, IrInstruction *fn_ref,
17456 IrInstruction *first_arg_ptr, bool comptime_fn_call, FnInline fn_inline)17555 IrInstruction *first_arg_ptr, CallModifier modifier,
17556 IrInstruction *new_stack, bool is_async_call_builtin,
17557 IrInstruction **args_ptr, size_t args_len, IrInstruction *ret_ptr, ResultLoc *call_result_loc)
17457{17558{
17458 Error err;17559 Error err;
17459 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;17560 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
...@@ -17469,16 +17570,16 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -17469,16 +17570,16 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
17469 }17570 }
17470 size_t src_param_count = fn_type_id->param_count - var_args_1_or_0;17571 size_t src_param_count = fn_type_id->param_count - var_args_1_or_0;
1747117572
17472 size_t call_param_count = call_instruction->arg_count + first_arg_1_or_0;17573 size_t call_param_count = args_len + first_arg_1_or_0;
17473 for (size_t i = 0; i < call_instruction->arg_count; i += 1) {17574 for (size_t i = 0; i < args_len; i += 1) {
17474 ZigValue *arg_tuple_value = call_instruction->args[i]->child->value;17575 ZigValue *arg_tuple_value = args_ptr[i]->value;
17475 if (arg_tuple_value->type->id == ZigTypeIdArgTuple) {17576 if (arg_tuple_value->type->id == ZigTypeIdArgTuple) {
17476 call_param_count -= 1;17577 call_param_count -= 1;
17477 call_param_count += arg_tuple_value->data.x_arg_tuple.end_index -17578 call_param_count += arg_tuple_value->data.x_arg_tuple.end_index -
17478 arg_tuple_value->data.x_arg_tuple.start_index;17579 arg_tuple_value->data.x_arg_tuple.start_index;
17479 }17580 }
17480 }17581 }
17481 AstNode *source_node = call_instruction->base.source_node;17582 AstNode *source_node = source_instr->source_node;
1748217583
17483 AstNode *fn_proto_node = fn_entry ? fn_entry->proto_node : nullptr;;17584 AstNode *fn_proto_node = fn_entry ? fn_entry->proto_node : nullptr;;
1748417585
...@@ -17511,14 +17612,14 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -17511,14 +17612,14 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
17511 return ira->codegen->invalid_instruction;17612 return ira->codegen->invalid_instruction;
17512 }17613 }
1751317614
17514 if (comptime_fn_call) {17615 if (modifier == CallModifierCompileTime) {
17515 // No special handling is needed for compile time evaluation of generic functions.17616 // No special handling is needed for compile time evaluation of generic functions.
17516 if (!fn_entry || fn_entry->body_node == nullptr) {17617 if (!fn_entry || fn_entry->body_node == nullptr) {
17517 ir_add_error(ira, fn_ref, buf_sprintf("unable to evaluate constant expression"));17618 ir_add_error(ira, fn_ref, buf_sprintf("unable to evaluate constant expression"));
17518 return ira->codegen->invalid_instruction;17619 return ira->codegen->invalid_instruction;
17519 }17620 }
1752017621
17521 if (!ir_emit_backward_branch(ira, &call_instruction->base))17622 if (!ir_emit_backward_branch(ira, source_instr))
17522 return ira->codegen->invalid_instruction;17623 return ira->codegen->invalid_instruction;
1752317624
17524 // Fork a scope of the function with known values for the parameters.17625 // Fork a scope of the function with known values for the parameters.
...@@ -17550,16 +17651,14 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -17550,16 +17651,14 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
17550 }17651 }
1755117652
17552 if (fn_proto_node->data.fn_proto.is_var_args) {17653 if (fn_proto_node->data.fn_proto.is_var_args) {
17553 ir_add_error(ira, &call_instruction->base,17654 ir_add_error(ira, source_instr,
17554 buf_sprintf("compiler bug: unable to call var args function at compile time. https://github.com/ziglang/zig/issues/313"));17655 buf_sprintf("compiler bug: unable to call var args function at compile time. https://github.com/ziglang/zig/issues/313"));
17555 return ira->codegen->invalid_instruction;17656 return ira->codegen->invalid_instruction;
17556 }17657 }
1755717658
1755817659
17559 for (size_t call_i = 0; call_i < call_instruction->arg_count; call_i += 1) {17660 for (size_t call_i = 0; call_i < args_len; call_i += 1) {
17560 IrInstruction *old_arg = call_instruction->args[call_i]->child;17661 IrInstruction *old_arg = args_ptr[call_i];
17561 if (type_is_invalid(old_arg->value->type))
17562 return ira->codegen->invalid_instruction;
1756317662
17564 if (!ir_analyze_fn_call_inline_arg(ira, fn_proto_node, old_arg, &exec_scope, &next_proto_i))17663 if (!ir_analyze_fn_call_inline_arg(ira, fn_proto_node, old_arg, &exec_scope, &next_proto_i))
17565 return ira->codegen->invalid_instruction;17664 return ira->codegen->invalid_instruction;
...@@ -17593,7 +17692,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -17593,7 +17692,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
17593 AstNode *body_node = fn_entry->body_node;17692 AstNode *body_node = fn_entry->body_node;
17594 result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type,17693 result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type,
17595 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry,17694 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry,
17596 nullptr, call_instruction->base.source_node, nullptr, ira->new_irb.exec, return_type_node,17695 nullptr, source_instr->source_node, nullptr, ira->new_irb.exec, return_type_node,
17597 UndefOk);17696 UndefOk);
1759817697
17599 if (inferred_err_set_type != nullptr) {17698 if (inferred_err_set_type != nullptr) {
...@@ -17623,24 +17722,21 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -17623,24 +17722,21 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
17623 }17722 }
17624 }17723 }
1762517724
17626 IrInstruction *new_instruction = ir_const_move(ira, &call_instruction->base, result);17725 IrInstruction *new_instruction = ir_const_move(ira, source_instr, result);
17627 return ir_finish_anal(ira, new_instruction);17726 return ir_finish_anal(ira, new_instruction);
17628 }17727 }
1762917728
17630 if (fn_type->data.fn.is_generic) {17729 if (fn_type->data.fn.is_generic) {
17631 if (!fn_entry) {17730 if (!fn_entry) {
17632 ir_add_error(ira, call_instruction->fn_ref,17731 ir_add_error(ira, fn_ref,
17633 buf_sprintf("calling a generic function requires compile-time known function value"));17732 buf_sprintf("calling a generic function requires compile-time known function value"));
17634 return ira->codegen->invalid_instruction;17733 return ira->codegen->invalid_instruction;
17635 }17734 }
1763617735
17637 // Count the arguments of the function type id we are creating17736 // Count the arguments of the function type id we are creating
17638 size_t new_fn_arg_count = first_arg_1_or_0;17737 size_t new_fn_arg_count = first_arg_1_or_0;
17639 for (size_t call_i = 0; call_i < call_instruction->arg_count; call_i += 1) {17738 for (size_t call_i = 0; call_i < args_len; call_i += 1) {
17640 IrInstruction *arg = call_instruction->args[call_i]->child;17739 IrInstruction *arg = args_ptr[call_i];
17641 if (type_is_invalid(arg->value->type))
17642 return ira->codegen->invalid_instruction;
17643
17644 if (arg->value->type->id == ZigTypeIdArgTuple) {17740 if (arg->value->type->id == ZigTypeIdArgTuple) {
17645 new_fn_arg_count += arg->value->data.x_arg_tuple.end_index - arg->value->data.x_arg_tuple.start_index;17741 new_fn_arg_count += arg->value->data.x_arg_tuple.end_index - arg->value->data.x_arg_tuple.start_index;
17646 } else {17742 } else {
...@@ -17702,10 +17798,8 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -17702,10 +17798,8 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
1770217798
17703 ZigFn *parent_fn_entry = exec_fn_entry(ira->new_irb.exec);17799 ZigFn *parent_fn_entry = exec_fn_entry(ira->new_irb.exec);
17704 assert(parent_fn_entry);17800 assert(parent_fn_entry);
17705 for (size_t call_i = 0; call_i < call_instruction->arg_count; call_i += 1) {17801 for (size_t call_i = 0; call_i < args_len; call_i += 1) {
17706 IrInstruction *arg = call_instruction->args[call_i]->child;17802 IrInstruction *arg = args_ptr[call_i];
17707 if (type_is_invalid(arg->value->type))
17708 return ira->codegen->invalid_instruction;
1770917803
17710 if (arg->value->type->id == ZigTypeIdArgTuple) {17804 if (arg->value->type->id == ZigTypeIdArgTuple) {
17711 for (size_t arg_tuple_i = arg->value->data.x_arg_tuple.start_index;17805 for (size_t arg_tuple_i = arg->value->data.x_arg_tuple.start_index;
...@@ -17804,8 +17898,9 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -17804,8 +17898,9 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
17804 switch (type_requires_comptime(ira->codegen, specified_return_type)) {17898 switch (type_requires_comptime(ira->codegen, specified_return_type)) {
17805 case ReqCompTimeYes:17899 case ReqCompTimeYes:
17806 // Throw out our work and call the function as if it were comptime.17900 // Throw out our work and call the function as if it were comptime.
17807 return ir_analyze_fn_call(ira, call_instruction, fn_entry, fn_type, fn_ref, first_arg_ptr,17901 return ir_analyze_fn_call(ira, source_instr, fn_entry, fn_type, fn_ref, first_arg_ptr,
17808 true, FnInlineAuto);17902 CallModifierCompileTime, new_stack, is_async_call_builtin, args_ptr, args_len,
17903 ret_ptr, call_result_loc);
17809 case ReqCompTimeInvalid:17904 case ReqCompTimeInvalid:
17810 return ira->codegen->invalid_instruction;17905 return ira->codegen->invalid_instruction;
17811 case ReqCompTimeNo:17906 case ReqCompTimeNo:
...@@ -17823,9 +17918,9 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -17823,9 +17918,9 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
17823 if (type_is_invalid(impl_fn->type_entry))17918 if (type_is_invalid(impl_fn->type_entry))
17824 return ira->codegen->invalid_instruction;17919 return ira->codegen->invalid_instruction;
1782517920
17826 impl_fn->ir_executable->source_node = call_instruction->base.source_node;17921 impl_fn->ir_executable->source_node = source_instr->source_node;
17827 impl_fn->ir_executable->parent_exec = ira->new_irb.exec;17922 impl_fn->ir_executable->parent_exec = ira->new_irb.exec;
17828 impl_fn->analyzed_executable.source_node = call_instruction->base.source_node;17923 impl_fn->analyzed_executable.source_node = source_instr->source_node;
17829 impl_fn->analyzed_executable.parent_exec = ira->new_irb.exec;17924 impl_fn->analyzed_executable.parent_exec = ira->new_irb.exec;
17830 impl_fn->analyzed_executable.backward_branch_quota = ira->new_irb.exec->backward_branch_quota;17925 impl_fn->analyzed_executable.backward_branch_quota = ira->new_irb.exec->backward_branch_quota;
17831 impl_fn->analyzed_executable.is_generic_instantiation = true;17926 impl_fn->analyzed_executable.is_generic_instantiation = true;
...@@ -17839,32 +17934,35 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -17839,32 +17934,35 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
17839 parent_fn_entry->calls_or_awaits_errorable_fn = true;17934 parent_fn_entry->calls_or_awaits_errorable_fn = true;
17840 }17935 }
1784117936
17842 IrInstruction *casted_new_stack = analyze_casted_new_stack(ira, call_instruction, impl_fn);17937 IrInstruction *casted_new_stack = analyze_casted_new_stack(ira, source_instr, new_stack,
17938 is_async_call_builtin, impl_fn);
17843 if (casted_new_stack != nullptr && type_is_invalid(casted_new_stack->value->type))17939 if (casted_new_stack != nullptr && type_is_invalid(casted_new_stack->value->type))
17844 return ira->codegen->invalid_instruction;17940 return ira->codegen->invalid_instruction;
1784517941
17846 size_t impl_param_count = impl_fn_type_id->param_count;17942 size_t impl_param_count = impl_fn_type_id->param_count;
17847 if (call_instruction->modifier == CallModifierAsync) {17943 if (modifier == CallModifierAsync) {
17848 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, impl_fn, impl_fn->type_entry,17944 IrInstruction *result = ir_analyze_async_call(ira, source_instr, impl_fn, impl_fn->type_entry,
17849 nullptr, casted_args, impl_param_count, casted_new_stack);17945 nullptr, casted_args, impl_param_count, casted_new_stack, is_async_call_builtin, ret_ptr,
17946 call_result_loc);
17850 return ir_finish_anal(ira, result);17947 return ir_finish_anal(ira, result);
17851 }17948 }
1785217949
17853 IrInstruction *result_loc;17950 IrInstruction *result_loc;
17854 if (handle_is_ptr(impl_fn_type_id->return_type)) {17951 if (handle_is_ptr(impl_fn_type_id->return_type)) {
17855 result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,17952 result_loc = ir_resolve_result(ira, source_instr, call_result_loc,
17856 impl_fn_type_id->return_type, nullptr, true, true, false);17953 impl_fn_type_id->return_type, nullptr, true, true, false);
17857 if (result_loc != nullptr) {17954 if (result_loc != nullptr) {
17858 if (type_is_invalid(result_loc->value->type) || instr_is_unreachable(result_loc)) {17955 if (type_is_invalid(result_loc->value->type) || instr_is_unreachable(result_loc)) {
17859 return result_loc;17956 return result_loc;
17860 }17957 }
17861 if (!handle_is_ptr(result_loc->value->type->data.pointer.child_type)) {17958 if (!handle_is_ptr(result_loc->value->type->data.pointer.child_type)) {
17862 ir_reset_result(call_instruction->result_loc);17959 ir_reset_result(call_result_loc);
17863 result_loc = nullptr;17960 result_loc = nullptr;
17864 }17961 }
17865 }17962 }
17866 } else if (call_instruction->is_async_call_builtin) {17963 } else if (is_async_call_builtin) {
17867 result_loc = get_async_call_result_loc(ira, call_instruction, impl_fn_type_id->return_type);17964 result_loc = get_async_call_result_loc(ira, source_instr, impl_fn_type_id->return_type,
17965 is_async_call_builtin, args_ptr, args_len, ret_ptr);
17868 if (result_loc != nullptr && type_is_invalid(result_loc->value->type))17966 if (result_loc != nullptr && type_is_invalid(result_loc->value->type))
17869 return ira->codegen->invalid_instruction;17967 return ira->codegen->invalid_instruction;
17870 } else {17968 } else {
...@@ -17873,18 +17971,17 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -17873,18 +17971,17 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
1787317971
17874 if (impl_fn_type_id->cc == CallingConventionAsync &&17972 if (impl_fn_type_id->cc == CallingConventionAsync &&
17875 parent_fn_entry->inferred_async_node == nullptr &&17973 parent_fn_entry->inferred_async_node == nullptr &&
17876 call_instruction->modifier != CallModifierNoAsync)17974 modifier != CallModifierNoAsync)
17877 {17975 {
17878 parent_fn_entry->inferred_async_node = fn_ref->source_node;17976 parent_fn_entry->inferred_async_node = fn_ref->source_node;
17879 parent_fn_entry->inferred_async_fn = impl_fn;17977 parent_fn_entry->inferred_async_fn = impl_fn;
17880 }17978 }
1788117979
17882 IrInstructionCallGen *new_call_instruction = ir_build_call_gen(ira, &call_instruction->base,17980 IrInstructionCallGen *new_call_instruction = ir_build_call_gen(ira, source_instr,
17883 impl_fn, nullptr, impl_param_count, casted_args, fn_inline,17981 impl_fn, nullptr, impl_param_count, casted_args, modifier, casted_new_stack,
17884 call_instruction->modifier, casted_new_stack, call_instruction->is_async_call_builtin, result_loc,17982 is_async_call_builtin, result_loc, impl_fn_type_id->return_type);
17885 impl_fn_type_id->return_type);
1788617983
17887 if (get_scope_typeof(call_instruction->base.scope) == nullptr) {17984 if (get_scope_typeof(source_instr->scope) == nullptr) {
17888 parent_fn_entry->call_list.append(new_call_instruction);17985 parent_fn_entry->call_list.append(new_call_instruction);
17889 }17986 }
1789017987
...@@ -17926,8 +18023,8 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -17926,8 +18023,8 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
17926 casted_args[next_arg_index] = casted_arg;18023 casted_args[next_arg_index] = casted_arg;
17927 next_arg_index += 1;18024 next_arg_index += 1;
17928 }18025 }
17929 for (size_t call_i = 0; call_i < call_instruction->arg_count; call_i += 1) {18026 for (size_t call_i = 0; call_i < args_len; call_i += 1) {
17930 IrInstruction *old_arg = call_instruction->args[call_i]->child;18027 IrInstruction *old_arg = args_ptr[call_i];
17931 if (type_is_invalid(old_arg->value->type))18028 if (type_is_invalid(old_arg->value->type))
17932 return ira->codegen->invalid_instruction;18029 return ira->codegen->invalid_instruction;
1793318030
...@@ -17988,25 +18085,26 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -17988,25 +18085,26 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
17988 if (type_is_invalid(return_type))18085 if (type_is_invalid(return_type))
17989 return ira->codegen->invalid_instruction;18086 return ira->codegen->invalid_instruction;
1799018087
17991 if (fn_entry != nullptr && fn_entry->fn_inline == FnInlineAlways && fn_inline == FnInlineNever) {18088 if (fn_entry != nullptr && fn_entry->fn_inline == FnInlineAlways && modifier == CallModifierNeverInline) {
17992 ir_add_error(ira, &call_instruction->base,18089 ir_add_error(ira, source_instr,
17993 buf_sprintf("no-inline call of inline function"));18090 buf_sprintf("no-inline call of inline function"));
17994 return ira->codegen->invalid_instruction;18091 return ira->codegen->invalid_instruction;
17995 }18092 }
1799618093
17997 IrInstruction *casted_new_stack = analyze_casted_new_stack(ira, call_instruction, fn_entry);18094 IrInstruction *casted_new_stack = analyze_casted_new_stack(ira, source_instr, new_stack,
18095 is_async_call_builtin, fn_entry);
17998 if (casted_new_stack != nullptr && type_is_invalid(casted_new_stack->value->type))18096 if (casted_new_stack != nullptr && type_is_invalid(casted_new_stack->value->type))
17999 return ira->codegen->invalid_instruction;18097 return ira->codegen->invalid_instruction;
1800018098
18001 if (call_instruction->modifier == CallModifierAsync) {18099 if (modifier == CallModifierAsync) {
18002 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, fn_entry, fn_type, fn_ref,18100 IrInstruction *result = ir_analyze_async_call(ira, source_instr, fn_entry, fn_type, fn_ref,
18003 casted_args, call_param_count, casted_new_stack);18101 casted_args, call_param_count, casted_new_stack, is_async_call_builtin, ret_ptr, call_result_loc);
18004 return ir_finish_anal(ira, result);18102 return ir_finish_anal(ira, result);
18005 }18103 }
1800618104
18007 if (fn_type_id->cc == CallingConventionAsync &&18105 if (fn_type_id->cc == CallingConventionAsync &&
18008 parent_fn_entry->inferred_async_node == nullptr &&18106 parent_fn_entry->inferred_async_node == nullptr &&
18009 call_instruction->modifier != CallModifierNoAsync)18107 modifier != CallModifierNoAsync)
18010 {18108 {
18011 parent_fn_entry->inferred_async_node = fn_ref->source_node;18109 parent_fn_entry->inferred_async_node = fn_ref->source_node;
18012 parent_fn_entry->inferred_async_fn = fn_entry;18110 parent_fn_entry->inferred_async_fn = fn_entry;
...@@ -18014,41 +18112,202 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -18014,41 +18112,202 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
1801418112
18015 IrInstruction *result_loc;18113 IrInstruction *result_loc;
18016 if (handle_is_ptr(return_type)) {18114 if (handle_is_ptr(return_type)) {
18017 result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,18115 result_loc = ir_resolve_result(ira, source_instr, call_result_loc,
18018 return_type, nullptr, true, true, false);18116 return_type, nullptr, true, true, false);
18019 if (result_loc != nullptr) {18117 if (result_loc != nullptr) {
18020 if (type_is_invalid(result_loc->value->type) || instr_is_unreachable(result_loc)) {18118 if (type_is_invalid(result_loc->value->type) || instr_is_unreachable(result_loc)) {
18021 return result_loc;18119 return result_loc;
18022 }18120 }
18023 if (!handle_is_ptr(result_loc->value->type->data.pointer.child_type)) {18121 if (!handle_is_ptr(result_loc->value->type->data.pointer.child_type)) {
18024 ir_reset_result(call_instruction->result_loc);18122 ir_reset_result(call_result_loc);
18025 result_loc = nullptr;18123 result_loc = nullptr;
18026 }18124 }
18027 }18125 }
18028 } else if (call_instruction->is_async_call_builtin) {18126 } else if (is_async_call_builtin) {
18029 result_loc = get_async_call_result_loc(ira, call_instruction, return_type);18127 result_loc = get_async_call_result_loc(ira, source_instr, return_type, is_async_call_builtin,
18128 args_ptr, args_len, ret_ptr);
18030 if (result_loc != nullptr && type_is_invalid(result_loc->value->type))18129 if (result_loc != nullptr && type_is_invalid(result_loc->value->type))
18031 return ira->codegen->invalid_instruction;18130 return ira->codegen->invalid_instruction;
18032 } else {18131 } else {
18033 result_loc = nullptr;18132 result_loc = nullptr;
18034 }18133 }
1803518134
18036 IrInstructionCallGen *new_call_instruction = ir_build_call_gen(ira, &call_instruction->base, fn_entry, fn_ref,18135 IrInstructionCallGen *new_call_instruction = ir_build_call_gen(ira, source_instr, fn_entry, fn_ref,
18037 call_param_count, casted_args, fn_inline, call_instruction->modifier, casted_new_stack,18136 call_param_count, casted_args, modifier, casted_new_stack,
18038 call_instruction->is_async_call_builtin, result_loc, return_type);18137 is_async_call_builtin, result_loc, return_type);
18039 if (get_scope_typeof(call_instruction->base.scope) == nullptr) {18138 if (get_scope_typeof(source_instr->scope) == nullptr) {
18040 parent_fn_entry->call_list.append(new_call_instruction);18139 parent_fn_entry->call_list.append(new_call_instruction);
18041 }18140 }
18042 return ir_finish_anal(ira, &new_call_instruction->base);18141 return ir_finish_anal(ira, &new_call_instruction->base);
18043}18142}
1804418143
18144static IrInstruction *ir_analyze_fn_call_src(IrAnalyze *ira, IrInstructionCallSrc *call_instruction,
18145 ZigFn *fn_entry, ZigType *fn_type, IrInstruction *fn_ref,
18146 IrInstruction *first_arg_ptr, CallModifier modifier)
18147{
18148 IrInstruction *new_stack = nullptr;
18149 if (call_instruction->new_stack) {
18150 new_stack = call_instruction->new_stack->child;
18151 if (type_is_invalid(new_stack->value->type))
18152 return ira->codegen->invalid_instruction;
18153 }
18154 IrInstruction **args_ptr = allocate<IrInstruction *>(call_instruction->arg_count, "IrInstruction *");
18155 for (size_t i = 0; i < call_instruction->arg_count; i += 1) {
18156 args_ptr[i] = call_instruction->args[i]->child;
18157 if (type_is_invalid(args_ptr[i]->value->type))
18158 return ira->codegen->invalid_instruction;
18159 }
18160 IrInstruction *ret_ptr = nullptr;
18161 if (call_instruction->ret_ptr != nullptr) {
18162 ret_ptr = call_instruction->ret_ptr->child;
18163 if (type_is_invalid(ret_ptr->value->type))
18164 return ira->codegen->invalid_instruction;
18165 }
18166 IrInstruction *result = ir_analyze_fn_call(ira, &call_instruction->base, fn_entry, fn_type, fn_ref,
18167 first_arg_ptr, modifier, new_stack, call_instruction->is_async_call_builtin,
18168 args_ptr, call_instruction->arg_count, ret_ptr, call_instruction->result_loc);
18169 deallocate(args_ptr, call_instruction->arg_count, "IrInstruction *");
18170 return result;
18171}
18172
18173static IrInstruction *ir_analyze_call_extra(IrAnalyze *ira, IrInstruction *source_instr,
18174 IrInstruction *pass1_options, IrInstruction *pass1_fn_ref, IrInstruction **args_ptr, size_t args_len,
18175 ResultLoc *result_loc)
18176{
18177 IrInstruction *options = pass1_options->child;
18178 if (type_is_invalid(options->value->type))
18179 return ira->codegen->invalid_instruction;
18180
18181 IrInstruction *fn_ref = pass1_fn_ref->child;
18182 if (type_is_invalid(fn_ref->value->type))
18183 return ira->codegen->invalid_instruction;
18184 IrInstruction *first_arg_ptr = nullptr;
18185 ZigFn *fn = nullptr;
18186 if (fn_ref->value->type->id == ZigTypeIdBoundFn) {
18187 assert(fn_ref->value->special == ConstValSpecialStatic);
18188 fn = fn_ref->value->data.x_bound_fn.fn;
18189 first_arg_ptr = fn_ref->value->data.x_bound_fn.first_arg;
18190 if (type_is_invalid(first_arg_ptr->value->type))
18191 return ira->codegen->invalid_instruction;
18192 } else {
18193 fn = ir_resolve_fn(ira, fn_ref);
18194 }
18195 ZigType *fn_type = (fn != nullptr) ? fn->type_entry : fn_ref->value->type;
18196
18197 TypeStructField *modifier_field = find_struct_type_field(options->value->type, buf_create_from_str("modifier"));
18198 ir_assert(modifier_field != nullptr, source_instr);
18199 IrInstruction *modifier_inst = ir_analyze_struct_value_field_value(ira, source_instr, options, modifier_field);
18200 ZigValue *modifier_val = ir_resolve_const(ira, modifier_inst, UndefBad);
18201 if (modifier_val == nullptr)
18202 return ira->codegen->invalid_instruction;
18203 CallModifier modifier = (CallModifier)bigint_as_u32(&modifier_val->data.x_enum_tag);
18204 if (modifier == CallModifierAsync) {
18205 ir_add_error(ira, source_instr, buf_sprintf("TODO: @call with async modifier"));
18206 return ira->codegen->invalid_instruction;
18207 }
18208 if (ir_should_inline(ira->new_irb.exec, source_instr->scope)) {
18209 switch (modifier) {
18210 case CallModifierBuiltin:
18211 zig_unreachable();
18212 case CallModifierAsync:
18213 ir_add_error(ira, source_instr, buf_sprintf("TODO: comptime @call with async modifier"));
18214 return ira->codegen->invalid_instruction;
18215 case CallModifierCompileTime:
18216 case CallModifierNone:
18217 case CallModifierAlwaysInline:
18218 case CallModifierAlwaysTail:
18219 case CallModifierNoAsync:
18220 modifier = CallModifierCompileTime;
18221 break;
18222 case CallModifierNeverInline:
18223 ir_add_error(ira, source_instr,
18224 buf_sprintf("unable to perform 'never_inline' call at compile-time"));
18225 return ira->codegen->invalid_instruction;
18226 case CallModifierNeverTail:
18227 ir_add_error(ira, source_instr,
18228 buf_sprintf("unable to perform 'never_tail' call at compile-time"));
18229 return ira->codegen->invalid_instruction;
18230 }
18231 }
18232
18233 TypeStructField *stack_field = find_struct_type_field(options->value->type, buf_create_from_str("stack"));
18234 ir_assert(stack_field != nullptr, source_instr);
18235 IrInstruction *opt_stack = ir_analyze_struct_value_field_value(ira, source_instr, options, stack_field);
18236 if (type_is_invalid(opt_stack->value->type))
18237 return ira->codegen->invalid_instruction;
18238 IrInstruction *stack_is_non_null_inst = ir_analyze_test_non_null(ira, source_instr, opt_stack);
18239 bool stack_is_non_null;
18240 if (!ir_resolve_bool(ira, stack_is_non_null_inst, &stack_is_non_null))
18241 return ira->codegen->invalid_instruction;
18242 IrInstruction *stack;
18243 if (stack_is_non_null) {
18244 stack = ir_analyze_optional_value_payload_value(ira, source_instr, opt_stack, false);
18245 if (type_is_invalid(stack->value->type))
18246 return ira->codegen->invalid_instruction;
18247 } else {
18248 stack = nullptr;
18249 }
18250
18251 return ir_analyze_fn_call(ira, source_instr, fn, fn_type, fn_ref, first_arg_ptr,
18252 modifier, stack, false, args_ptr, args_len, nullptr, result_loc);
18253}
18254
18255static IrInstruction *ir_analyze_instruction_call_extra(IrAnalyze *ira, IrInstructionCallExtra *instruction) {
18256 IrInstruction *args = instruction->args->child;
18257 ZigType *args_type = args->value->type;
18258 if (type_is_invalid(args_type))
18259 return ira->codegen->invalid_instruction;
18260
18261 if (args_type->id != ZigTypeIdStruct) {
18262 ir_add_error(ira, args,
18263 buf_sprintf("expected tuple or struct, found '%s'", buf_ptr(&args_type->name)));
18264 return ira->codegen->invalid_instruction;
18265 }
18266
18267 IrInstruction **args_ptr = nullptr;
18268 size_t args_len = 0;
18269
18270 if (is_tuple(args_type)) {
18271 args_len = args_type->data.structure.src_field_count;
18272 args_ptr = allocate<IrInstruction *>(args_len, "IrInstruction *");
18273 for (size_t i = 0; i < args_len; i += 1) {
18274 TypeStructField *arg_field = args_type->data.structure.fields[i];
18275 args_ptr[i] = ir_analyze_struct_value_field_value(ira, &instruction->base, args, arg_field);
18276 if (type_is_invalid(args_ptr[i]->value->type))
18277 return ira->codegen->invalid_instruction;
18278 }
18279 } else {
18280 ir_add_error(ira, args, buf_sprintf("TODO: struct args"));
18281 return ira->codegen->invalid_instruction;
18282 }
18283 IrInstruction *result = ir_analyze_call_extra(ira, &instruction->base, instruction->options,
18284 instruction->fn_ref, args_ptr, args_len, instruction->result_loc);
18285 deallocate(args_ptr, args_len, "IrInstruction *");
18286 return result;
18287}
18288
18289static IrInstruction *ir_analyze_instruction_call_args(IrAnalyze *ira, IrInstructionCallSrcArgs *instruction) {
18290 IrInstruction **args_ptr = allocate<IrInstruction *>(instruction->args_len, "IrInstruction *");
18291 for (size_t i = 0; i < instruction->args_len; i += 1) {
18292 args_ptr[i] = instruction->args_ptr[i]->child;
18293 if (type_is_invalid(args_ptr[i]->value->type))
18294 return ira->codegen->invalid_instruction;
18295 }
18296
18297 IrInstruction *result = ir_analyze_call_extra(ira, &instruction->base, instruction->options,
18298 instruction->fn_ref, args_ptr, instruction->args_len, instruction->result_loc);
18299 deallocate(args_ptr, instruction->args_len, "IrInstruction *");
18300 return result;
18301}
18302
18045static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction) {18303static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction) {
18046 IrInstruction *fn_ref = call_instruction->fn_ref->child;18304 IrInstruction *fn_ref = call_instruction->fn_ref->child;
18047 if (type_is_invalid(fn_ref->value->type))18305 if (type_is_invalid(fn_ref->value->type))
18048 return ira->codegen->invalid_instruction;18306 return ira->codegen->invalid_instruction;
1804918307
18050 bool is_comptime = call_instruction->is_comptime ||18308 bool is_comptime = (call_instruction->modifier == CallModifierCompileTime) ||
18051 ir_should_inline(ira->new_irb.exec, call_instruction->base.scope);18309 ir_should_inline(ira->new_irb.exec, call_instruction->base.scope);
18310 CallModifier modifier = is_comptime ? CallModifierCompileTime : call_instruction->modifier;
1805218311
18053 if (is_comptime || instr_is_comptime(fn_ref)) {18312 if (is_comptime || instr_is_comptime(fn_ref)) {
18054 if (fn_ref->value->type->id == ZigTypeIdMetaType) {18313 if (fn_ref->value->type->id == ZigTypeIdMetaType) {
...@@ -18063,14 +18322,16 @@ static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionC...@@ -18063,14 +18322,16 @@ static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionC
18063 } else if (fn_ref->value->type->id == ZigTypeIdFn) {18322 } else if (fn_ref->value->type->id == ZigTypeIdFn) {
18064 ZigFn *fn_table_entry = ir_resolve_fn(ira, fn_ref);18323 ZigFn *fn_table_entry = ir_resolve_fn(ira, fn_ref);
18065 ZigType *fn_type = fn_table_entry ? fn_table_entry->type_entry : fn_ref->value->type;18324 ZigType *fn_type = fn_table_entry ? fn_table_entry->type_entry : fn_ref->value->type;
18066 return ir_analyze_fn_call(ira, call_instruction, fn_table_entry, fn_type,18325 CallModifier modifier = is_comptime ? CallModifierCompileTime : call_instruction->modifier;
18067 fn_ref, nullptr, is_comptime, call_instruction->fn_inline);18326 return ir_analyze_fn_call_src(ira, call_instruction, fn_table_entry, fn_type,
18327 fn_ref, nullptr, modifier);
18068 } else if (fn_ref->value->type->id == ZigTypeIdBoundFn) {18328 } else if (fn_ref->value->type->id == ZigTypeIdBoundFn) {
18069 assert(fn_ref->value->special == ConstValSpecialStatic);18329 assert(fn_ref->value->special == ConstValSpecialStatic);
18070 ZigFn *fn_table_entry = fn_ref->value->data.x_bound_fn.fn;18330 ZigFn *fn_table_entry = fn_ref->value->data.x_bound_fn.fn;
18071 IrInstruction *first_arg_ptr = fn_ref->value->data.x_bound_fn.first_arg;18331 IrInstruction *first_arg_ptr = fn_ref->value->data.x_bound_fn.first_arg;
18072 return ir_analyze_fn_call(ira, call_instruction, fn_table_entry, fn_table_entry->type_entry,18332 CallModifier modifier = is_comptime ? CallModifierCompileTime : call_instruction->modifier;
18073 fn_ref, first_arg_ptr, is_comptime, call_instruction->fn_inline);18333 return ir_analyze_fn_call_src(ira, call_instruction, fn_table_entry, fn_table_entry->type_entry,
18334 fn_ref, first_arg_ptr, modifier);
18074 } else {18335 } else {
18075 ir_add_error_node(ira, fn_ref->source_node,18336 ir_add_error_node(ira, fn_ref->source_node,
18076 buf_sprintf("type '%s' not a function", buf_ptr(&fn_ref->value->type->name)));18337 buf_sprintf("type '%s' not a function", buf_ptr(&fn_ref->value->type->name)));
...@@ -18079,8 +18340,8 @@ static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionC...@@ -18079,8 +18340,8 @@ static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionC
18079 }18340 }
1808018341
18081 if (fn_ref->value->type->id == ZigTypeIdFn) {18342 if (fn_ref->value->type->id == ZigTypeIdFn) {
18082 return ir_analyze_fn_call(ira, call_instruction, nullptr, fn_ref->value->type,18343 return ir_analyze_fn_call_src(ira, call_instruction, nullptr, fn_ref->value->type,
18083 fn_ref, nullptr, false, call_instruction->fn_inline);18344 fn_ref, nullptr, modifier);
18084 } else {18345 } else {
18085 ir_add_error_node(ira, fn_ref->source_node,18346 ir_add_error_node(ira, fn_ref->source_node,
18086 buf_sprintf("type '%s' not a function", buf_ptr(&fn_ref->value->type->name)));18347 buf_sprintf("type '%s' not a function", buf_ptr(&fn_ref->value->type->name)));
...@@ -19356,8 +19617,18 @@ static IrInstruction *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_n...@@ -19356,8 +19617,18 @@ static IrInstruction *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_n
19356 PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE, inferred_struct_field, nullptr);19617 PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE, inferred_struct_field, nullptr);
1935719618
19358 if (instr_is_comptime(container_ptr)) {19619 if (instr_is_comptime(container_ptr)) {
19359 IrInstruction *result = ir_const(ira, source_instr, field_ptr_type);19620 ZigValue *ptr_val = ir_resolve_const(ira, container_ptr, UndefBad);
19360 copy_const_val(result->value, container_ptr->value);19621 if (ptr_val == nullptr)
19622 return ira->codegen->invalid_instruction;
19623
19624 IrInstruction *result;
19625 if (ptr_val->data.x_ptr.mut == ConstPtrMutInfer) {
19626 result = ir_build_cast(&ira->new_irb, source_instr->scope,
19627 source_instr->source_node, container_ptr_type, container_ptr, CastOpNoop);
19628 } else {
19629 result = ir_const(ira, source_instr, field_ptr_type);
19630 }
19631 copy_const_val(result->value, ptr_val);
19361 result->value->type = field_ptr_type;19632 result->value->type = field_ptr_type;
19362 return result;19633 return result;
19363 }19634 }
...@@ -20374,20 +20645,6 @@ static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrIns...@@ -20374,20 +20645,6 @@ static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrIns
20374 return ir_analyze_test_non_null(ira, &instruction->base, value);20645 return ir_analyze_test_non_null(ira, &instruction->base, value);
20375}20646}
2037620647
20377static ZigType *get_ptr_elem_type(CodeGen *g, IrInstruction *ptr) {
20378 ir_assert(ptr->value->type->id == ZigTypeIdPointer, ptr);
20379 ZigType *elem_type = ptr->value->type->data.pointer.child_type;
20380 if (elem_type != g->builtin_types.entry_var)
20381 return elem_type;
20382
20383 if (ir_resolve_lazy(g, ptr->source_node, ptr->value))
20384 return g->builtin_types.entry_invalid;
20385
20386 assert(value_is_comptime(ptr->value));
20387 ZigValue *pointee = const_ptr_pointee_unchecked(g, ptr->value);
20388 return pointee->type;
20389}
20390
20391static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr,20648static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr,
20392 IrInstruction *base_ptr, bool safety_check_on, bool initializing)20649 IrInstruction *base_ptr, bool safety_check_on, bool initializing)
20393{20650{
...@@ -21796,9 +22053,7 @@ static void ensure_field_index(ZigType *type, const char *field_name, size_t ind...@@ -21796,9 +22053,7 @@ static void ensure_field_index(ZigType *type, const char *field_name, size_t ind
2179622053
21797static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, ZigType *root) {22054static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, ZigType *root) {
21798 Error err;22055 Error err;
21799 ZigValue *type_info_var = get_builtin_value(ira->codegen, "TypeInfo");22056 ZigType *type_info_type = get_builtin_type(ira->codegen, "TypeInfo");
21800 assert(type_info_var->type->id == ZigTypeIdMetaType);
21801 ZigType *type_info_type = type_info_var->data.x_type;
21802 assert(type_info_type->id == ZigTypeIdUnion);22057 assert(type_info_type->id == ZigTypeIdUnion);
21803 if ((err = type_resolve(ira->codegen, type_info_type, ResolveStatusSizeKnown))) {22058 if ((err = type_resolve(ira->codegen, type_info_type, ResolveStatusSizeKnown))) {
21804 zig_unreachable();22059 zig_unreachable();
...@@ -23034,9 +23289,7 @@ static IrInstruction *ir_analyze_instruction_type_id(IrAnalyze *ira,...@@ -23034,9 +23289,7 @@ static IrInstruction *ir_analyze_instruction_type_id(IrAnalyze *ira,
23034 if (type_is_invalid(type_entry))23289 if (type_is_invalid(type_entry))
23035 return ira->codegen->invalid_instruction;23290 return ira->codegen->invalid_instruction;
2303623291
23037 ZigValue *var_value = get_builtin_value(ira->codegen, "TypeId");23292 ZigType *result_type = get_builtin_type(ira->codegen, "TypeId");
23038 assert(var_value->type->id == ZigTypeIdMetaType);
23039 ZigType *result_type = var_value->data.x_type;
2304023293
23041 IrInstruction *result = ir_const(ira, &instruction->base, result_type);23294 IrInstruction *result = ir_const(ira, &instruction->base, result_type);
23042 bigint_init_unsigned(&result->value->data.x_enum_tag, type_id_index(type_entry));23295 bigint_init_unsigned(&result->value->data.x_enum_tag, type_id_index(type_entry));
...@@ -27787,6 +28040,10 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction...@@ -27787,6 +28040,10 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
27787 return ir_analyze_instruction_field_ptr(ira, (IrInstructionFieldPtr *)instruction);28040 return ir_analyze_instruction_field_ptr(ira, (IrInstructionFieldPtr *)instruction);
27788 case IrInstructionIdCallSrc:28041 case IrInstructionIdCallSrc:
27789 return ir_analyze_instruction_call(ira, (IrInstructionCallSrc *)instruction);28042 return ir_analyze_instruction_call(ira, (IrInstructionCallSrc *)instruction);
28043 case IrInstructionIdCallSrcArgs:
28044 return ir_analyze_instruction_call_args(ira, (IrInstructionCallSrcArgs *)instruction);
28045 case IrInstructionIdCallExtra:
28046 return ir_analyze_instruction_call_extra(ira, (IrInstructionCallExtra *)instruction);
27790 case IrInstructionIdBr:28047 case IrInstructionIdBr:
27791 return ir_analyze_instruction_br(ira, (IrInstructionBr *)instruction);28048 return ir_analyze_instruction_br(ira, (IrInstructionBr *)instruction);
27792 case IrInstructionIdCondBr:28049 case IrInstructionIdCondBr:
...@@ -28184,7 +28441,9 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -28184,7 +28441,9 @@ bool ir_has_side_effects(IrInstruction *instruction) {
28184 case IrInstructionIdDeclVarGen:28441 case IrInstructionIdDeclVarGen:
28185 case IrInstructionIdStorePtr:28442 case IrInstructionIdStorePtr:
28186 case IrInstructionIdVectorStoreElem:28443 case IrInstructionIdVectorStoreElem:
28444 case IrInstructionIdCallExtra:
28187 case IrInstructionIdCallSrc:28445 case IrInstructionIdCallSrc:
28446 case IrInstructionIdCallSrcArgs:
28188 case IrInstructionIdCallGen:28447 case IrInstructionIdCallGen:
28189 case IrInstructionIdReturn:28448 case IrInstructionIdReturn:
28190 case IrInstructionIdUnreachable:28449 case IrInstructionIdUnreachable:
src/ir_print.cpp+71-4
...@@ -92,8 +92,12 @@ const char* ir_instruction_type_str(IrInstructionId id) {...@@ -92,8 +92,12 @@ const char* ir_instruction_type_str(IrInstructionId id) {
92 return "VarPtr";92 return "VarPtr";
93 case IrInstructionIdReturnPtr:93 case IrInstructionIdReturnPtr:
94 return "ReturnPtr";94 return "ReturnPtr";
95 case IrInstructionIdCallExtra:
96 return "CallExtra";
95 case IrInstructionIdCallSrc:97 case IrInstructionIdCallSrc:
96 return "CallSrc";98 return "CallSrc";
99 case IrInstructionIdCallSrcArgs:
100 return "CallSrcArgs";
97 case IrInstructionIdCallGen:101 case IrInstructionIdCallGen:
98 return "CallGen";102 return "CallGen";
99 case IrInstructionIdConst:103 case IrInstructionIdConst:
...@@ -636,15 +640,57 @@ static void ir_print_result_loc(IrPrint *irp, ResultLoc *result_loc) {...@@ -636,15 +640,57 @@ static void ir_print_result_loc(IrPrint *irp, ResultLoc *result_loc) {
636 zig_unreachable();640 zig_unreachable();
637}641}
638642
643static void ir_print_call_extra(IrPrint *irp, IrInstructionCallExtra *instruction) {
644 fprintf(irp->f, "opts=");
645 ir_print_other_instruction(irp, instruction->options);
646 fprintf(irp->f, ", fn=");
647 ir_print_other_instruction(irp, instruction->fn_ref);
648 fprintf(irp->f, ", args=");
649 ir_print_other_instruction(irp, instruction->args);
650 fprintf(irp->f, ", result=");
651 ir_print_result_loc(irp, instruction->result_loc);
652}
653
654static void ir_print_call_src_args(IrPrint *irp, IrInstructionCallSrcArgs *instruction) {
655 fprintf(irp->f, "opts=");
656 ir_print_other_instruction(irp, instruction->options);
657 fprintf(irp->f, ", fn=");
658 ir_print_other_instruction(irp, instruction->fn_ref);
659 fprintf(irp->f, ", args=(");
660 for (size_t i = 0; i < instruction->args_len; i += 1) {
661 IrInstruction *arg = instruction->args_ptr[i];
662 if (i != 0)
663 fprintf(irp->f, ", ");
664 ir_print_other_instruction(irp, arg);
665 }
666 fprintf(irp->f, "), result=");
667 ir_print_result_loc(irp, instruction->result_loc);
668}
669
639static void ir_print_call_src(IrPrint *irp, IrInstructionCallSrc *call_instruction) {670static void ir_print_call_src(IrPrint *irp, IrInstructionCallSrc *call_instruction) {
640 switch (call_instruction->modifier) {671 switch (call_instruction->modifier) {
641 case CallModifierNone:672 case CallModifierNone:
642 break;673 break;
674 case CallModifierNoAsync:
675 fprintf(irp->f, "noasync ");
676 break;
643 case CallModifierAsync:677 case CallModifierAsync:
644 fprintf(irp->f, "async ");678 fprintf(irp->f, "async ");
645 break;679 break;
646 case CallModifierNoAsync:680 case CallModifierNeverTail:
647 fprintf(irp->f, "noasync ");681 fprintf(irp->f, "notail ");
682 break;
683 case CallModifierNeverInline:
684 fprintf(irp->f, "noinline ");
685 break;
686 case CallModifierAlwaysTail:
687 fprintf(irp->f, "tail ");
688 break;
689 case CallModifierAlwaysInline:
690 fprintf(irp->f, "inline ");
691 break;
692 case CallModifierCompileTime:
693 fprintf(irp->f, "comptime ");
648 break;694 break;
649 case CallModifierBuiltin:695 case CallModifierBuiltin:
650 zig_unreachable();696 zig_unreachable();
...@@ -670,11 +716,26 @@ static void ir_print_call_gen(IrPrint *irp, IrInstructionCallGen *call_instructi...@@ -670,11 +716,26 @@ static void ir_print_call_gen(IrPrint *irp, IrInstructionCallGen *call_instructi
670 switch (call_instruction->modifier) {716 switch (call_instruction->modifier) {
671 case CallModifierNone:717 case CallModifierNone:
672 break;718 break;
719 case CallModifierNoAsync:
720 fprintf(irp->f, "noasync ");
721 break;
673 case CallModifierAsync:722 case CallModifierAsync:
674 fprintf(irp->f, "async ");723 fprintf(irp->f, "async ");
675 break;724 break;
676 case CallModifierNoAsync:725 case CallModifierNeverTail:
677 fprintf(irp->f, "noasync ");726 fprintf(irp->f, "notail ");
727 break;
728 case CallModifierNeverInline:
729 fprintf(irp->f, "noinline ");
730 break;
731 case CallModifierAlwaysTail:
732 fprintf(irp->f, "tail ");
733 break;
734 case CallModifierAlwaysInline:
735 fprintf(irp->f, "inline ");
736 break;
737 case CallModifierCompileTime:
738 fprintf(irp->f, "comptime ");
678 break;739 break;
679 case CallModifierBuiltin:740 case CallModifierBuiltin:
680 zig_unreachable();741 zig_unreachable();
...@@ -2082,9 +2143,15 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool...@@ -2082,9 +2143,15 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool
2082 case IrInstructionIdCast:2143 case IrInstructionIdCast:
2083 ir_print_cast(irp, (IrInstructionCast *)instruction);2144 ir_print_cast(irp, (IrInstructionCast *)instruction);
2084 break;2145 break;
2146 case IrInstructionIdCallExtra:
2147 ir_print_call_extra(irp, (IrInstructionCallExtra *)instruction);
2148 break;
2085 case IrInstructionIdCallSrc:2149 case IrInstructionIdCallSrc:
2086 ir_print_call_src(irp, (IrInstructionCallSrc *)instruction);2150 ir_print_call_src(irp, (IrInstructionCallSrc *)instruction);
2087 break;2151 break;
2152 case IrInstructionIdCallSrcArgs:
2153 ir_print_call_src_args(irp, (IrInstructionCallSrcArgs *)instruction);
2154 break;
2088 case IrInstructionIdCallGen:2155 case IrInstructionIdCallGen:
2089 ir_print_call_gen(irp, (IrInstructionCallGen *)instruction);2156 ir_print_call_gen(irp, (IrInstructionCallGen *)instruction);
2090 break;2157 break;
src/zig_llvm.cpp+12-6
...@@ -269,19 +269,25 @@ ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref) {...@@ -269,19 +269,25 @@ ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref) {
269}269}
270270
271LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,271LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,
272 unsigned NumArgs, unsigned CC, ZigLLVM_FnInline fn_inline, const char *Name)272 unsigned NumArgs, unsigned CC, ZigLLVM_CallAttr attr, const char *Name)
273{273{
274 CallInst *call_inst = CallInst::Create(unwrap(Fn), makeArrayRef(unwrap(Args), NumArgs), Name);274 CallInst *call_inst = CallInst::Create(unwrap(Fn), makeArrayRef(unwrap(Args), NumArgs), Name);
275 call_inst->setCallingConv(CC);275 call_inst->setCallingConv(CC);
276 switch (fn_inline) {276 switch (attr) {
277 case ZigLLVM_FnInlineAuto:277 case ZigLLVM_CallAttrAuto:
278 break;278 break;
279 case ZigLLVM_FnInlineAlways:279 case ZigLLVM_CallAttrNeverTail:
280 call_inst->addAttribute(AttributeList::FunctionIndex, Attribute::AlwaysInline);280 call_inst->setTailCallKind(CallInst::TCK_NoTail);
281 break;281 break;
282 case ZigLLVM_FnInlineNever:282 case ZigLLVM_CallAttrNeverInline:
283 call_inst->addAttribute(AttributeList::FunctionIndex, Attribute::NoInline);283 call_inst->addAttribute(AttributeList::FunctionIndex, Attribute::NoInline);
284 break;284 break;
285 case ZigLLVM_CallAttrAlwaysTail:
286 call_inst->setTailCallKind(CallInst::TCK_MustTail);
287 break;
288 case ZigLLVM_CallAttrAlwaysInline:
289 call_inst->addAttribute(AttributeList::FunctionIndex, Attribute::AlwaysInline);
290 break;
285 }291 }
286 return wrap(unwrap(B)->Insert(call_inst));292 return wrap(unwrap(B)->Insert(call_inst));
287}293}
src/zig_llvm.h+7-5
...@@ -64,13 +64,15 @@ ZIG_EXTERN_C LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, co...@@ -64,13 +64,15 @@ ZIG_EXTERN_C LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, co
6464
65ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref);65ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref);
6666
67enum ZigLLVM_FnInline {67enum ZigLLVM_CallAttr {
68 ZigLLVM_FnInlineAuto,68 ZigLLVM_CallAttrAuto,
69 ZigLLVM_FnInlineAlways,69 ZigLLVM_CallAttrNeverTail,
70 ZigLLVM_FnInlineNever,70 ZigLLVM_CallAttrNeverInline,
71 ZigLLVM_CallAttrAlwaysTail,
72 ZigLLVM_CallAttrAlwaysInline,
71};73};
72ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,74ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,
73 unsigned NumArgs, unsigned CC, enum ZigLLVM_FnInline fn_inline, const char *Name);75 unsigned NumArgs, unsigned CC, enum ZigLLVM_CallAttr attr, const char *Name);
7476
75ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign,77ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign,
76 LLVMValueRef Src, unsigned SrcAlign, LLVMValueRef Size, bool isVolatile);78 LLVMValueRef Src, unsigned SrcAlign, LLVMValueRef Size, bool isVolatile);
test/compile_errors.zig+34-15
...@@ -2,6 +2,36 @@ const tests = @import("tests.zig");...@@ -2,6 +2,36 @@ const tests = @import("tests.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
33
4pub fn addCases(cases: *tests.CompileErrorContext) void {4pub fn addCases(cases: *tests.CompileErrorContext) void {
5 cases.add(
6 "bad usage of @call",
7 \\export fn entry1() void {
8 \\ @call(.{}, foo, {});
9 \\}
10 \\export fn entry2() void {
11 \\ comptime @call(.{ .modifier = .never_inline }, foo, .{});
12 \\}
13 \\export fn entry3() void {
14 \\ comptime @call(.{ .modifier = .never_tail }, foo, .{});
15 \\}
16 \\export fn entry4() void {
17 \\ @call(.{ .modifier = .never_inline }, bar, .{});
18 \\}
19 \\export fn entry5(c: bool) void {
20 \\ var baz = if (c) baz1 else baz2;
21 \\ @call(.{ .modifier = .compile_time }, baz, .{});
22 \\}
23 \\fn foo() void {}
24 \\inline fn bar() void {}
25 \\fn baz1() void {}
26 \\fn baz2() void {}
27 ,
28 "tmp.zig:2:21: error: expected tuple or struct, found 'void'",
29 "tmp.zig:5:14: error: unable to perform 'never_inline' call at compile-time",
30 "tmp.zig:8:14: error: unable to perform 'never_tail' call at compile-time",
31 "tmp.zig:11:5: error: no-inline call of inline function",
32 "tmp.zig:15:43: error: unable to evaluate constant expression",
33 );
34
5 cases.add(35 cases.add(
6 \\export async fn foo() void {}36 \\export async fn foo() void {}
7 , "tmp.zig:1:1: error: exported function cannot be async");37 , "tmp.zig:1:1: error: exported function cannot be async");
...@@ -14,13 +44,13 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -14,13 +44,13 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
14 );44 );
1545
16 cases.addCase(x: {46 cases.addCase(x: {
17 var tc = cases.create("@newStackCall on unsupported target",47 var tc = cases.create("call with new stack on unsupported target",
48 \\var buf: [10]u8 align(16) = undefined;
18 \\export fn entry() void {49 \\export fn entry() void {
19 \\ var buf: [10]u8 align(16) = undefined;50 \\ @call(.{.stack = &buf}, foo, .{});
20 \\ @newStackCall(&buf, foo);
21 \\}51 \\}
22 \\fn foo() void {}52 \\fn foo() void {}
23 , "tmp.zig:3:5: error: target arch 'wasm32' does not support @newStackCall");53 , "tmp.zig:3:5: error: target arch 'wasm32' does not support calling with a new stack");
24 tc.target = tests.Target{54 tc.target = tests.Target{
25 .Cross = tests.CrossTarget{55 .Cross = tests.CrossTarget{
26 .arch = .wasm32,56 .arch = .wasm32,
...@@ -1927,17 +1957,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -1927,17 +1957,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
1927 "tmp.zig:2:12: error: use of undeclared identifier 'SomeNonexistentType'",1957 "tmp.zig:2:12: error: use of undeclared identifier 'SomeNonexistentType'",
1928 );1958 );
19291959
1930 cases.add(
1931 "@noInlineCall on an inline function",
1932 \\inline fn foo() void {}
1933 \\
1934 \\export fn entry() void {
1935 \\ @noInlineCall(foo);
1936 \\}
1937 ,
1938 "tmp.zig:4:5: error: no-inline call of inline function",
1939 );
1940
1941 cases.add(1960 cases.add(
1942 "comptime continue inside runtime catch",1961 "comptime continue inside runtime catch",
1943 \\export fn entry(c: bool) void {1962 \\export fn entry(c: bool) void {
test/stage1/behavior.zig+1
...@@ -52,6 +52,7 @@ comptime {...@@ -52,6 +52,7 @@ comptime {
52 _ = @import("behavior/bugs/920.zig");52 _ = @import("behavior/bugs/920.zig");
53 _ = @import("behavior/byteswap.zig");53 _ = @import("behavior/byteswap.zig");
54 _ = @import("behavior/byval_arg_var.zig");54 _ = @import("behavior/byval_arg_var.zig");
55 _ = @import("behavior/call.zig");
55 _ = @import("behavior/cast.zig");56 _ = @import("behavior/cast.zig");
56 _ = @import("behavior/const_slice_child.zig");57 _ = @import("behavior/const_slice_child.zig");
57 _ = @import("behavior/defer.zig");58 _ = @import("behavior/defer.zig");
test/stage1/behavior/call.zig created+48
...@@ -0,0 +1,48 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4test "basic invocations" {
5 const foo = struct {
6 fn foo() i32 {
7 return 1234;
8 }
9 }.foo;
10 expect(@call(.{}, foo, .{}) == 1234);
11 comptime {
12 // modifiers that allow comptime calls
13 expect(@call(.{}, foo, .{}) == 1234);
14 expect(@call(.{ .modifier = .no_async }, foo, .{}) == 1234);
15 expect(@call(.{ .modifier = .always_tail }, foo, .{}) == 1234);
16 expect(@call(.{ .modifier = .always_inline }, foo, .{}) == 1234);
17 }
18 {
19 // comptime call without comptime keyword
20 const result = @call(.{ .modifier = .compile_time }, foo, .{}) == 1234;
21 comptime expect(result);
22 }
23}
24
25test "tuple parameters" {
26 const add = struct {
27 fn add(a: i32, b: i32) i32 {
28 return a + b;
29 }
30 }.add;
31 var a: i32 = 12;
32 var b: i32 = 34;
33 expect(@call(.{}, add, .{ a, 34 }) == 46);
34 expect(@call(.{}, add, .{ 12, b }) == 46);
35 expect(@call(.{}, add, .{ a, b }) == 46);
36 expect(@call(.{}, add, .{ 12, 34 }) == 46);
37 comptime expect(@call(.{}, add, .{ 12, 34 }) == 46);
38 {
39 const separate_args0 = .{ a, b };
40 //TODO const separate_args1 = .{ a, 34 };
41 const separate_args2 = .{ 12, 34 };
42 //TODO const separate_args3 = .{ 12, b };
43 expect(@call(.{ .modifier = .always_inline }, add, separate_args0) == 46);
44 // TODO expect(@call(.{ .modifier = .always_inline }, add, separate_args1) == 46);
45 expect(@call(.{ .modifier = .always_inline }, add, separate_args2) == 46);
46 // TODO expect(@call(.{ .modifier = .always_inline }, add, separate_args3) == 46);
47 }
48}
test/stage1/behavior/fn.zig+1-9
...@@ -96,14 +96,6 @@ fn fn4() u32 {...@@ -96,14 +96,6 @@ fn fn4() u32 {
96 return 8;96 return 8;
97}97}
9898
99test "inline function call" {
100 expect(@inlineCall(add, 3, 9) == 12);
101}
102
103fn add(a: i32, b: i32) i32 {
104 return a + b;
105}
106
107test "number literal as an argument" {99test "number literal as an argument" {
108 numberLiteralArg(3);100 numberLiteralArg(3);
109 comptime numberLiteralArg(3);101 comptime numberLiteralArg(3);
...@@ -251,7 +243,7 @@ test "discard the result of a function that returns a struct" {...@@ -251,7 +243,7 @@ test "discard the result of a function that returns a struct" {
251test "function call with anon list literal" {243test "function call with anon list literal" {
252 const S = struct {244 const S = struct {
253 fn doTheTest() void {245 fn doTheTest() void {
254 consumeVec(.{9, 8, 7});246 consumeVec(.{ 9, 8, 7 });
255 }247 }
256248
257 fn consumeVec(vec: [3]f32) void {249 fn consumeVec(vec: [3]f32) void {
test/stage1/behavior/new_stack_call.zig+2-2
...@@ -18,8 +18,8 @@ test "calling a function with a new stack" {...@@ -18,8 +18,8 @@ test "calling a function with a new stack" {
1818
19 const arg = 1234;19 const arg = 1234;
2020
21 const a = @newStackCall(new_stack_bytes[0..512], targetFunction, arg);21 const a = @call(.{ .stack = new_stack_bytes[0..512] }, targetFunction, .{arg});
22 const b = @newStackCall(new_stack_bytes[512..], targetFunction, arg);22 const b = @call(.{ .stack = new_stack_bytes[512..] }, targetFunction, .{arg});
23 _ = targetFunction(arg);23 _ = targetFunction(arg);
2424
25 expect(arg == 1234);25 expect(arg == 1234);