authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-06 14:12:01-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-06 14:12:01-05:00
log343987cd057c5f2f0aad197518d7d573579d0d08
tree733e506597f80f4aeb040dc7c931d77c2d0dbcaf
parentef83358eb6702e8541816817e98c3e7279033672
signature Commit is signed but in an unrecognized format.

remove `@inlineCall` from zig


25 files changed, 372 insertions(+), 226 deletions(-)

doc/langref.html.in-21
...@@ -7492,27 +7492,6 @@ test "@hasDecl" {...@@ -7492,27 +7492,6 @@ test "@hasDecl" {
7492 {#see_also|Compile Variables|@embedFile#}7492 {#see_also|Compile Variables|@embedFile#}
7493 {#header_close#}7493 {#header_close#}
74947494
7495 {#header_open|@inlineCall#}
7496 <pre>{#syntax#}@inlineCall(function: X, args: ...) Y{#endsyntax#}</pre>
7497 <p>
7498 This calls a function, in the same way that invoking an expression with parentheses does:
7499 </p>
7500 {#code_begin|test#}
7501const assert = @import("std").debug.assert;
7502
7503test "inline function call" {
7504 assert(@inlineCall(add, 3, 9) == 12);
7505}
7506
7507fn add(a: i32, b: i32) i32 { return a + b; }
7508 {#code_end#}
7509 <p>
7510 Unlike a normal function call, however, {#syntax#}@inlineCall{#endsyntax#} guarantees that the call
7511 will be inlined. If the call cannot be inlined, a compile error is emitted.
7512 </p>
7513 {#see_also|@call#}
7514 {#header_close#}
7515
7516 {#header_open|@intCast#}7495 {#header_open|@intCast#}
7517 <pre>{#syntax#}@intCast(comptime DestType: type, int: var) DestType{#endsyntax#}</pre>7496 <pre>{#syntax#}@intCast(comptime DestType: type, int: var) DestType{#endsyntax#}</pre>
7518 <p>7497 <p>
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+5-5
...@@ -59,7 +59,7 @@ stdcallcc fn _DllMainCRTStartup(...@@ -59,7 +59,7 @@ stdcallcc fn _DllMainCRTStartup(
59extern fn wasm_freestanding_start() void {59extern fn wasm_freestanding_start() void {
60 // This is marked inline because for some reason LLVM in release mode fails to inline it,60 // This is marked inline because for some reason LLVM in release mode fails to inline it,
61 // and we want fewer call frames in stack traces.61 // and we want fewer call frames in stack traces.
62 _ = @inlineCall(callMain);62 _ = @call(.{ .modifier = .always_inline }, callMain, .{});
63}63}
6464
65extern fn EfiMain(handle: uefi.Handle, system_table: *uefi.tables.SystemTable) usize {65extern fn EfiMain(handle: uefi.Handle, system_table: *uefi.tables.SystemTable) usize {
...@@ -89,7 +89,7 @@ nakedcc fn _start() noreturn {...@@ -89,7 +89,7 @@ nakedcc fn _start() noreturn {
89 if (builtin.os == builtin.Os.wasi) {89 if (builtin.os == builtin.Os.wasi) {
90 // This is marked inline because for some reason LLVM in release mode fails to inline it,90 // This is marked inline because for some reason LLVM in release mode fails to inline it,
91 // and we want fewer call frames in stack traces.91 // and we want fewer call frames in stack traces.
92 std.os.wasi.proc_exit(@inlineCall(callMain));92 std.os.wasi.proc_exit(@call(.{ .modifier = .always_inline }, callMain, .{}));
93 }93 }
9494
95 switch (builtin.arch) {95 switch (builtin.arch) {
...@@ -187,7 +187,7 @@ fn posixCallMainAndExit() noreturn {...@@ -187,7 +187,7 @@ fn posixCallMainAndExit() noreturn {
187 //std.os.exit(@newStackCall(new_stack, callMainWithArgs, argc, argv, envp));187 //std.os.exit(@newStackCall(new_stack, callMainWithArgs, argc, argv, envp));
188 }188 }
189189
190 std.os.exit(@inlineCall(callMainWithArgs, argc, argv, envp));190 std.os.exit(@call(.{ .modifier = .always_inline }, callMainWithArgs, .{ argc, argv, envp }));
191}191}
192192
193fn callMainWithArgs(argc: usize, argv: [*][*:0]u8, envp: [][*:0]u8) u8 {193fn callMainWithArgs(argc: usize, argv: [*][*:0]u8, envp: [][*:0]u8) u8 {
...@@ -203,7 +203,7 @@ extern fn main(c_argc: i32, c_argv: [*][*:0]u8, c_envp: [*:null]?[*:0]u8) i32 {...@@ -203,7 +203,7 @@ extern fn main(c_argc: i32, c_argv: [*][*:0]u8, c_envp: [*:null]?[*:0]u8) i32 {
203 var env_count: usize = 0;203 var env_count: usize = 0;
204 while (c_envp[env_count] != null) : (env_count += 1) {}204 while (c_envp[env_count] != null) : (env_count += 1) {}
205 const envp = @ptrCast([*][*:0]u8, c_envp)[0..env_count];205 const envp = @ptrCast([*][*:0]u8, c_envp)[0..env_count];
206 return @inlineCall(callMainWithArgs, @intCast(usize, c_argc), c_argv, envp);206 return @call(.{ .modifier = .always_inline }, callMainWithArgs, .{ @intCast(usize, c_argc), c_argv, envp });
207}207}
208208
209// General error message for a malformed return type209// General error message for a malformed return type
...@@ -233,7 +233,7 @@ inline fn initEventLoopAndCallMain() u8 {...@@ -233,7 +233,7 @@ inline fn initEventLoopAndCallMain() u8 {
233233
234 // This is marked inline because for some reason LLVM in release mode fails to inline it,234 // This is marked inline because for some reason LLVM in release mode fails to inline it,
235 // and we want fewer call frames in stack traces.235 // and we want fewer call frames in stack traces.
236 return @inlineCall(callMain);236 return @call(.{ .modifier = .always_inline }, callMain, .{});
237}237}
238238
239async fn callMainAsync(loop: *std.event.Loop) u8 {239async fn callMainAsync(loop: *std.event.Loop) u8 {
src/all_types.hpp+16-3
...@@ -1700,7 +1700,6 @@ enum BuiltinFnId {...@@ -1700,7 +1700,6 @@ enum BuiltinFnId {
1700 BuiltinFnIdFieldParentPtr,1700 BuiltinFnIdFieldParentPtr,
1701 BuiltinFnIdByteOffsetOf,1701 BuiltinFnIdByteOffsetOf,
1702 BuiltinFnIdBitOffsetOf,1702 BuiltinFnIdBitOffsetOf,
1703 BuiltinFnIdInlineCall,
1704 BuiltinFnIdNewStackCall,1703 BuiltinFnIdNewStackCall,
1705 BuiltinFnIdAsyncCall,1704 BuiltinFnIdAsyncCall,
1706 BuiltinFnIdTypeId,1705 BuiltinFnIdTypeId,
...@@ -2487,6 +2486,7 @@ enum IrInstructionId {...@@ -2487,6 +2486,7 @@ enum IrInstructionId {
2487 IrInstructionIdVarPtr,2486 IrInstructionIdVarPtr,
2488 IrInstructionIdReturnPtr,2487 IrInstructionIdReturnPtr,
2489 IrInstructionIdCallSrc,2488 IrInstructionIdCallSrc,
2489 IrInstructionIdCallSrcArgs,
2490 IrInstructionIdCallExtra,2490 IrInstructionIdCallExtra,
2491 IrInstructionIdCallGen,2491 IrInstructionIdCallGen,
2492 IrInstructionIdConst,2492 IrInstructionIdConst,
...@@ -2904,8 +2904,21 @@ struct IrInstructionCallSrc {...@@ -2904,8 +2904,21 @@ struct IrInstructionCallSrc {
2904 bool is_async_call_builtin;2904 bool is_async_call_builtin;
2905};2905};
29062906
2907/// This is a pass1 instruction, used by @call.2907// This is a pass1 instruction, used by @call when the args node is
2908/// `args` is expected to be either a struct or a tuple.2908// a tuple or struct literal.
2909struct IrInstructionCallSrcArgs {
2910 IrInstruction base;
2911
2912 IrInstruction *options;
2913 IrInstruction *fn_ref;
2914 IrInstruction **args_ptr;
2915 size_t args_len;
2916 ResultLoc *result_loc;
2917};
2918
2919// This is a pass1 instruction, used by @call, when the args node
2920// is not a literal.
2921// `args` is expected to be either a struct or a tuple.
2909struct IrInstructionCallExtra {2922struct IrInstructionCallExtra {
2910 IrInstruction base;2923 IrInstruction base;
29112924
src/analyze.cpp+5-2
...@@ -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;
src/codegen.cpp+13-4
...@@ -3062,7 +3062,7 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,...@@ -3062,7 +3062,7 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
3062 ZigType *actual_type = cast_instruction->value->value->type;3062 ZigType *actual_type = cast_instruction->value->value->type;
3063 ZigType *wanted_type = cast_instruction->base.value->type;3063 ZigType *wanted_type = cast_instruction->base.value->type;
3064 LLVMValueRef expr_val = ir_llvm_value(g, cast_instruction->value);3064 LLVMValueRef expr_val = ir_llvm_value(g, cast_instruction->value);
3065 assert(expr_val);3065 ir_assert(expr_val, &cast_instruction->base);
30663066
3067 switch (cast_instruction->cast_op) {3067 switch (cast_instruction->cast_op) {
3068 case CastOpNoCast:3068 case CastOpNoCast:
...@@ -4330,8 +4330,17 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa...@@ -4330,8 +4330,17 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa
4330 return struct_ptr;4330 return struct_ptr;
4331 }4331 }
43324332
4333 ZigType *struct_type = (struct_ptr_type->id == ZigTypeIdPointer) ?4333 ZigType *struct_type;
4334 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
4335 if ((err = type_resolve(g, struct_type, ResolveStatusLLVMFull)))4344 if ((err = type_resolve(g, struct_type, ResolveStatusLLVMFull)))
4336 codegen_report_errors_and_exit(g);4345 codegen_report_errors_and_exit(g);
43374346
...@@ -6152,6 +6161,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -6152,6 +6161,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
6152 case IrInstructionIdUndeclaredIdent:6161 case IrInstructionIdUndeclaredIdent:
6153 case IrInstructionIdCallExtra:6162 case IrInstructionIdCallExtra:
6154 case IrInstructionIdCallSrc:6163 case IrInstructionIdCallSrc:
6164 case IrInstructionIdCallSrcArgs:
6155 case IrInstructionIdAllocaSrc:6165 case IrInstructionIdAllocaSrc:
6156 case IrInstructionIdEndExpr:6166 case IrInstructionIdEndExpr:
6157 case IrInstructionIdImplicitCast:6167 case IrInstructionIdImplicitCast:
...@@ -8132,7 +8142,6 @@ static void define_builtin_fns(CodeGen *g) {...@@ -8132,7 +8142,6 @@ static void define_builtin_fns(CodeGen *g) {
8132 create_builtin_fn(g, BuiltinFnIdNearbyInt, "nearbyInt", 2);8142 create_builtin_fn(g, BuiltinFnIdNearbyInt, "nearbyInt", 2);
8133 create_builtin_fn(g, BuiltinFnIdRound, "round", 2);8143 create_builtin_fn(g, BuiltinFnIdRound, "round", 2);
8134 create_builtin_fn(g, BuiltinFnIdMulAdd, "mulAdd", 4);8144 create_builtin_fn(g, BuiltinFnIdMulAdd, "mulAdd", 4);
8135 create_builtin_fn(g, BuiltinFnIdInlineCall, "inlineCall", SIZE_MAX);
8136 create_builtin_fn(g, BuiltinFnIdNewStackCall, "newStackCall", SIZE_MAX);8145 create_builtin_fn(g, BuiltinFnIdNewStackCall, "newStackCall", SIZE_MAX);
8137 create_builtin_fn(g, BuiltinFnIdAsyncCall, "asyncCall", SIZE_MAX);8146 create_builtin_fn(g, BuiltinFnIdAsyncCall, "asyncCall", SIZE_MAX);
8138 create_builtin_fn(g, BuiltinFnIdTypeId, "typeId", 1);8147 create_builtin_fn(g, BuiltinFnIdTypeId, "typeId", 1);
src/ir.cpp+210-124
...@@ -290,6 +290,8 @@ static void destroy_instruction(IrInstruction *inst) {...@@ -290,6 +290,8 @@ static void destroy_instruction(IrInstruction *inst) {
290 return destroy(reinterpret_cast<IrInstructionCast *>(inst), name);290 return destroy(reinterpret_cast<IrInstructionCast *>(inst), name);
291 case IrInstructionIdCallSrc:291 case IrInstructionIdCallSrc:
292 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);
293 case IrInstructionIdCallExtra:295 case IrInstructionIdCallExtra:
294 return destroy(reinterpret_cast<IrInstructionCallExtra *>(inst), name);296 return destroy(reinterpret_cast<IrInstructionCallExtra *>(inst), name);
295 case IrInstructionIdCallGen:297 case IrInstructionIdCallGen:
...@@ -649,6 +651,15 @@ static ZigValue *const_ptr_pointee_unchecked(CodeGen *g, ZigValue *const_val) {...@@ -649,6 +651,15 @@ static ZigValue *const_ptr_pointee_unchecked(CodeGen *g, ZigValue *const_val) {
649 assert(const_val->special == ConstValSpecialStatic);651 assert(const_val->special == ConstValSpecialStatic);
650 ZigValue *result;652 ZigValue *result;
651653
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
652 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)) {
653 case OnePossibleValueInvalid:664 case OnePossibleValueInvalid:
654 zig_unreachable();665 zig_unreachable();
...@@ -978,6 +989,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCallSrc *) {...@@ -978,6 +989,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCallSrc *) {
978 return IrInstructionIdCallSrc;989 return IrInstructionIdCallSrc;
979}990}
980991
992static constexpr IrInstructionId ir_instruction_id(IrInstructionCallSrcArgs *) {
993 return IrInstructionIdCallSrcArgs;
994}
995
981static constexpr IrInstructionId ir_instruction_id(IrInstructionCallExtra *) {996static constexpr IrInstructionId ir_instruction_id(IrInstructionCallExtra *) {
982 return IrInstructionIdCallExtra;997 return IrInstructionIdCallExtra;
983}998}
...@@ -1921,6 +1936,25 @@ static IrInstruction *ir_build_call_extra(IrBuilder *irb, Scope *scope, AstNode...@@ -1921,6 +1936,25 @@ static IrInstruction *ir_build_call_extra(IrBuilder *irb, Scope *scope, AstNode
1921 return &call_instruction->base;1936 return &call_instruction->base;
1922}1937}
19231938
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
1924static 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,
1925 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,
1926 IrInstruction *ret_ptr, CallModifier modifier, bool is_async_call_builtin,1960 IrInstruction *ret_ptr, CallModifier modifier, bool is_async_call_builtin,
...@@ -5095,6 +5129,43 @@ static IrInstruction *ir_gen_async_call(IrBuilder *irb, Scope *scope, AstNode *a...@@ -5095,6 +5129,43 @@ static IrInstruction *ir_gen_async_call(IrBuilder *irb, Scope *scope, AstNode *a
5095 return ir_lval_wrap(irb, scope, call, lval, result_loc);5129 return ir_lval_wrap(irb, scope, call, lval, result_loc);
5096}5130}
50975131
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
5098static 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,
5099 ResultLoc *result_loc)5170 ResultLoc *result_loc)
5100{5171{
...@@ -6013,32 +6084,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -6013,32 +6084,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
6013 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);
6014 return ir_lval_wrap(irb, scope, offset_of, lval, result_loc);6085 return ir_lval_wrap(irb, scope, offset_of, lval, result_loc);
6015 }6086 }
6016 case BuiltinFnIdInlineCall:
6017 {
6018 if (node->data.fn_call_expr.params.length == 0) {
6019 add_node_error(irb->codegen, node, buf_sprintf("expected at least 1 argument, found 0"));
6020 return irb->codegen->invalid_instruction;
6021 }
6022
6023 AstNode *fn_ref_node = node->data.fn_call_expr.params.at(0);
6024 IrInstruction *fn_ref = ir_gen_node(irb, fn_ref_node, scope);
6025 if (fn_ref == irb->codegen->invalid_instruction)
6026 return fn_ref;
6027
6028 size_t arg_count = node->data.fn_call_expr.params.length - 1;
6029
6030 IrInstruction **args = allocate<IrInstruction*>(arg_count);
6031 for (size_t i = 0; i < arg_count; i += 1) {
6032 AstNode *arg_node = node->data.fn_call_expr.params.at(i + 1);
6033 args[i] = ir_gen_node(irb, arg_node, scope);
6034 if (args[i] == irb->codegen->invalid_instruction)
6035 return args[i];
6036 }
6037
6038 IrInstruction *call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args,
6039 nullptr, CallModifierAlwaysInline, false, nullptr, result_loc);
6040 return ir_lval_wrap(irb, scope, call, lval, result_loc);
6041 }
6042 case BuiltinFnIdNewStackCall:6087 case BuiltinFnIdNewStackCall:
6043 {6088 {
6044 if (node->data.fn_call_expr.params.length < 2) {6089 if (node->data.fn_call_expr.params.length < 2) {
...@@ -6086,17 +6131,33 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -6086,17 +6131,33 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
6086 IrInstruction *options = ir_build_implicit_cast(irb, scope, options_node, options_inner, result_loc_cast);6131 IrInstruction *options = ir_build_implicit_cast(irb, scope, options_node, options_inner, result_loc_cast);
60876132
6088 AstNode *fn_ref_node = node->data.fn_call_expr.params.at(1);6133 AstNode *fn_ref_node = node->data.fn_call_expr.params.at(1);
6089 IrInstruction *fn_ref = ir_gen_node(irb, fn_ref_node, scope);
6090 if (fn_ref == irb->codegen->invalid_instruction)
6091 return fn_ref;
6092
6093 AstNode *args_node = node->data.fn_call_expr.params.at(2);6134 AstNode *args_node = node->data.fn_call_expr.params.at(2);
6094 IrInstruction *args = ir_gen_node(irb, args_node, scope);6135 if (args_node->type == NodeTypeContainerInitExpr) {
6095 if (args == irb->codegen->invalid_instruction)6136 if (args_node->data.container_init_expr.kind == ContainerInitKindArray ||
6096 return args;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;
60976153
6098 IrInstruction *call = ir_build_call_extra(irb, scope, node, options, fn_ref, args, result_loc);6154 IrInstruction *args = ir_gen_node(irb, args_node, scope);
6099 return ir_lval_wrap(irb, scope, call, lval, result_loc);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);
6159 return ir_lval_wrap(irb, scope, call, lval, result_loc);
6160 }
6100 }6161 }
6101 case BuiltinFnIdAsyncCall:6162 case BuiltinFnIdAsyncCall:
6102 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);
...@@ -6415,33 +6476,8 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node...@@ -6415,33 +6476,8 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node
6415 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);
64166477
6417 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;
6418 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,
6419 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);
6420 return fn_ref;
6421
6422 IrInstruction *fn_type = ir_build_typeof(irb, scope, node, fn_ref);
6423
6424 size_t arg_count = node->data.fn_call_expr.params.length;
6425 IrInstruction **args = allocate<IrInstruction*>(arg_count);
6426 for (size_t i = 0; i < arg_count; i += 1) {
6427 AstNode *arg_node = node->data.fn_call_expr.params.at(i);
6428
6429 IrInstruction *arg_index = ir_build_const_usize(irb, scope, arg_node, i);
6430 IrInstruction *arg_type = ir_build_arg_type(irb, scope, node, fn_type, arg_index, true);
6431 ResultLoc *no_result = no_result_loc();
6432 ir_build_reset_result(irb, scope, node, no_result);
6433 ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, arg_type, no_result);
6434
6435 IrInstruction *arg = ir_gen_node_extra(irb, arg_node, scope, LValNone, &result_loc_cast->base);
6436 if (arg == irb->codegen->invalid_instruction)
6437 return arg;
6438
6439 args[i] = ir_build_implicit_cast(irb, scope, arg_node, arg, result_loc_cast);
6440 }
6441
6442 IrInstruction *fn_call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, nullptr,
6443 node->data.fn_call_expr.modifier, false, nullptr, result_loc);
6444 return ir_lval_wrap(irb, scope, fn_call, lval, result_loc);
6445}6481}
64466482
6447static 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,
...@@ -13955,6 +13991,20 @@ static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, Zig...@@ -13955,6 +13991,20 @@ static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, Zig
13955 return ir_implicit_cast2(ira, value, value, expected_type);13991 return ir_implicit_cast2(ira, value, value, expected_type);
13956}13992}
1395713993
13994static ZigType *get_ptr_elem_type(CodeGen *g, IrInstruction *ptr) {
13995 ir_assert(ptr->value->type->id == ZigTypeIdPointer, ptr);
13996 ZigType *elem_type = ptr->value->type->data.pointer.child_type;
13997 if (elem_type != g->builtin_types.entry_var)
13998 return elem_type;
13999
14000 if (ir_resolve_lazy(g, ptr->source_node, ptr->value))
14001 return g->builtin_types.entry_invalid;
14002
14003 assert(value_is_comptime(ptr->value));
14004 ZigValue *pointee = const_ptr_pointee_unchecked(g, ptr->value);
14005 return pointee->type;
14006}
14007
13958static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr,14008static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr,
13959 ResultLoc *result_loc)14009 ResultLoc *result_loc)
13960{14010{
...@@ -13971,6 +14021,8 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc...@@ -13971,6 +14021,8 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
13971 }14021 }
1397214022
13973 ZigType *child_type = ptr_type->data.pointer.child_type;14023 ZigType *child_type = ptr_type->data.pointer.child_type;
14024 if (type_is_invalid(child_type))
14025 return ira->codegen->invalid_instruction;
13974 // if the child type has one possible value, the deref is comptime14026 // if the child type has one possible value, the deref is comptime
13975 switch (type_has_one_possible_value(ira->codegen, child_type)) {14027 switch (type_has_one_possible_value(ira->codegen, child_type)) {
13976 case OnePossibleValueInvalid:14028 case OnePossibleValueInvalid:
...@@ -17326,9 +17378,7 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source...@@ -17326,9 +17378,7 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
17326 copy_const_val(casted_ptr->value, ptr->value);17378 copy_const_val(casted_ptr->value, ptr->value);
17327 casted_ptr->value->type = struct_ptr_type;17379 casted_ptr->value->type = struct_ptr_type;
17328 } else {17380 } else {
17329 casted_ptr = ir_build_cast(&ira->new_irb, source_instr->scope,17381 casted_ptr = ptr;
17330 source_instr->source_node, struct_ptr_type, ptr, CastOpNoop);
17331 casted_ptr->value->type = struct_ptr_type;
17332 }17382 }
17333 if (instr_is_comptime(casted_ptr)) {17383 if (instr_is_comptime(casted_ptr)) {
17334 ZigValue *ptr_val = ir_resolve_const(ira, casted_ptr, UndefBad);17384 ZigValue *ptr_val = ir_resolve_const(ira, casted_ptr, UndefBad);
...@@ -17409,6 +17459,12 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source...@@ -17409,6 +17459,12 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
17409 }17459 }
17410 }17460 }
1741117461
17462 if (ptr->value->type->data.pointer.inferred_struct_field != nullptr &&
17463 child_type == ira->codegen->builtin_types.entry_var)
17464 {
17465 child_type = ptr->value->type->data.pointer.inferred_struct_field->inferred_struct_type;
17466 }
17467
17412 switch (type_requires_comptime(ira->codegen, child_type)) {17468 switch (type_requires_comptime(ira->codegen, child_type)) {
17413 case ReqCompTimeInvalid:17469 case ReqCompTimeInvalid:
17414 return ira->codegen->invalid_instruction;17470 return ira->codegen->invalid_instruction;
...@@ -18105,62 +18161,47 @@ static IrInstruction *ir_analyze_fn_call_src(IrAnalyze *ira, IrInstructionCallSr...@@ -18105,62 +18161,47 @@ static IrInstruction *ir_analyze_fn_call_src(IrAnalyze *ira, IrInstructionCallSr
18105 return result;18161 return result;
18106}18162}
1810718163
18108static IrInstruction *ir_analyze_instruction_call_extra(IrAnalyze *ira, IrInstructionCallExtra *instruction) {18164static IrInstruction *ir_analyze_call_extra(IrAnalyze *ira, IrInstruction *source_instr,
18109 IrInstruction *options = instruction->options->child;18165 IrInstruction *pass1_options, IrInstruction *pass1_fn_ref, IrInstruction **args_ptr, size_t args_len,
18166 ResultLoc *result_loc)
18167{
18168 IrInstruction *options = pass1_options->child;
18110 if (type_is_invalid(options->value->type))18169 if (type_is_invalid(options->value->type))
18111 return ira->codegen->invalid_instruction;18170 return ira->codegen->invalid_instruction;
1811218171
18113 IrInstruction *fn_ref = instruction->fn_ref->child;18172 IrInstruction *fn_ref = pass1_fn_ref->child;
18114 if (type_is_invalid(fn_ref->value->type))18173 if (type_is_invalid(fn_ref->value->type))
18115 return ira->codegen->invalid_instruction;18174 return ira->codegen->invalid_instruction;
18116 ZigFn *fn = ir_resolve_fn(ira, fn_ref);18175 IrInstruction *first_arg_ptr = nullptr;
18117 ZigType *fn_type = (fn != nullptr) ? fn->type_entry : fn_ref->value->type;18176 ZigFn *fn = nullptr;
1811818177 if (fn_ref->value->type->id == ZigTypeIdBoundFn) {
18119 IrInstruction *args = instruction->args->child;18178 assert(fn_ref->value->special == ConstValSpecialStatic);
18120 ZigType *args_type = args->value->type;18179 fn = fn_ref->value->data.x_bound_fn.fn;
18121 if (type_is_invalid(args_type))18180 first_arg_ptr = fn_ref->value->data.x_bound_fn.first_arg;
18122 return ira->codegen->invalid_instruction;18181 if (type_is_invalid(first_arg_ptr->value->type))
1812318182 return ira->codegen->invalid_instruction;
18124 if (args_type->id != ZigTypeIdStruct) {
18125 ir_add_error(ira, args,
18126 buf_sprintf("expected tuple or struct, found '%s'", buf_ptr(&args_type->name)));
18127 return ira->codegen->invalid_instruction;
18128 }
18129
18130 IrInstruction **args_ptr = nullptr;
18131 size_t args_len = 0;
18132
18133 if (is_tuple(args_type)) {
18134 args_len = args_type->data.structure.src_field_count;
18135 args_ptr = allocate<IrInstruction *>(args_len, "IrInstruction *");
18136 for (size_t i = 0; i < args_len; i += 1) {
18137 TypeStructField *arg_field = args_type->data.structure.fields[i];
18138 args_ptr[i] = ir_analyze_struct_value_field_value(ira, &instruction->base, args, arg_field);
18139 if (type_is_invalid(args_ptr[i]->value->type))
18140 return ira->codegen->invalid_instruction;
18141 }
18142 } else {18183 } else {
18143 ir_add_error(ira, args, buf_sprintf("TODO: struct args"));18184 fn = ir_resolve_fn(ira, fn_ref);
18144 return ira->codegen->invalid_instruction;
18145 }18185 }
18186 ZigType *fn_type = (fn != nullptr) ? fn->type_entry : fn_ref->value->type;
1814618187
18147 TypeStructField *modifier_field = find_struct_type_field(options->value->type, buf_create_from_str("modifier"));18188 TypeStructField *modifier_field = find_struct_type_field(options->value->type, buf_create_from_str("modifier"));
18148 ir_assert(modifier_field != nullptr, &instruction->base);18189 ir_assert(modifier_field != nullptr, source_instr);
18149 IrInstruction *modifier_inst = ir_analyze_struct_value_field_value(ira, &instruction->base, options, modifier_field);18190 IrInstruction *modifier_inst = ir_analyze_struct_value_field_value(ira, source_instr, options, modifier_field);
18150 ZigValue *modifier_val = ir_resolve_const(ira, modifier_inst, UndefBad);18191 ZigValue *modifier_val = ir_resolve_const(ira, modifier_inst, UndefBad);
18151 if (modifier_val == nullptr)18192 if (modifier_val == nullptr)
18152 return ira->codegen->invalid_instruction;18193 return ira->codegen->invalid_instruction;
18153 CallModifier modifier = (CallModifier)bigint_as_u32(&modifier_val->data.x_enum_tag);18194 CallModifier modifier = (CallModifier)bigint_as_u32(&modifier_val->data.x_enum_tag);
18154 if (modifier == CallModifierAsync) {18195 if (modifier == CallModifierAsync) {
18155 ir_add_error(ira, args, buf_sprintf("TODO: @call with async modifier"));18196 ir_add_error(ira, source_instr, buf_sprintf("TODO: @call with async modifier"));
18156 return ira->codegen->invalid_instruction;18197 return ira->codegen->invalid_instruction;
18157 }18198 }
18158 if (ir_should_inline(ira->new_irb.exec, instruction->base.scope)) {18199 if (ir_should_inline(ira->new_irb.exec, source_instr->scope)) {
18159 switch (modifier) {18200 switch (modifier) {
18160 case CallModifierBuiltin:18201 case CallModifierBuiltin:
18161 zig_unreachable();18202 zig_unreachable();
18162 case CallModifierAsync:18203 case CallModifierAsync:
18163 ir_add_error(ira, args, buf_sprintf("TODO: comptime @call with async modifier"));18204 ir_add_error(ira, source_instr, buf_sprintf("TODO: comptime @call with async modifier"));
18164 return ira->codegen->invalid_instruction;18205 return ira->codegen->invalid_instruction;
18165 case CallModifierCompileTime:18206 case CallModifierCompileTime:
18166 case CallModifierNone:18207 case CallModifierNone:
...@@ -18170,32 +18211,78 @@ static IrInstruction *ir_analyze_instruction_call_extra(IrAnalyze *ira, IrInstru...@@ -18170,32 +18211,78 @@ static IrInstruction *ir_analyze_instruction_call_extra(IrAnalyze *ira, IrInstru
18170 modifier = CallModifierCompileTime;18211 modifier = CallModifierCompileTime;
18171 break;18212 break;
18172 case CallModifierNeverInline:18213 case CallModifierNeverInline:
18173 ir_add_error(ira, args,18214 ir_add_error(ira, source_instr,
18174 buf_sprintf("unable to perform 'never_inline' call at compile-time"));18215 buf_sprintf("unable to perform 'never_inline' call at compile-time"));
18175 return ira->codegen->invalid_instruction;18216 return ira->codegen->invalid_instruction;
18176 case CallModifierNeverTail:18217 case CallModifierNeverTail:
18177 ir_add_error(ira, args,18218 ir_add_error(ira, source_instr,
18178 buf_sprintf("unable to perform 'never_tail' call at compile-time"));18219 buf_sprintf("unable to perform 'never_tail' call at compile-time"));
18179 return ira->codegen->invalid_instruction;18220 return ira->codegen->invalid_instruction;
18180 }18221 }
18181 }18222 }
1818218223
18183 TypeStructField *stack_field = find_struct_type_field(options->value->type, buf_create_from_str("stack"));18224 TypeStructField *stack_field = find_struct_type_field(options->value->type, buf_create_from_str("stack"));
18184 ir_assert(stack_field != nullptr, &instruction->base);18225 ir_assert(stack_field != nullptr, source_instr);
18185 IrInstruction *stack = ir_analyze_struct_value_field_value(ira, &instruction->base, options, stack_field);18226 IrInstruction *stack = ir_analyze_struct_value_field_value(ira, source_instr, options, stack_field);
18186 IrInstruction *stack_is_non_null_inst = ir_analyze_test_non_null(ira, &instruction->base, stack);18227 IrInstruction *stack_is_non_null_inst = ir_analyze_test_non_null(ira, source_instr, stack);
18187 bool stack_is_non_null;18228 bool stack_is_non_null;
18188 if (!ir_resolve_bool(ira, stack_is_non_null_inst, &stack_is_non_null))18229 if (!ir_resolve_bool(ira, stack_is_non_null_inst, &stack_is_non_null))
18189 return ira->codegen->invalid_instruction;18230 return ira->codegen->invalid_instruction;
18190 if (!stack_is_non_null)18231 if (!stack_is_non_null)
18191 stack = nullptr;18232 stack = nullptr;
1819218233
18193 IrInstruction *result = ir_analyze_fn_call(ira, &instruction->base, fn, fn_type, fn_ref, nullptr,18234 return ir_analyze_fn_call(ira, source_instr, fn, fn_type, fn_ref, first_arg_ptr,
18194 modifier, stack, false, args_ptr, args_len, nullptr, instruction->result_loc);18235 modifier, stack, false, args_ptr, args_len, nullptr, result_loc);
18236}
18237
18238static IrInstruction *ir_analyze_instruction_call_extra(IrAnalyze *ira, IrInstructionCallExtra *instruction) {
18239 IrInstruction *args = instruction->args->child;
18240 ZigType *args_type = args->value->type;
18241 if (type_is_invalid(args_type))
18242 return ira->codegen->invalid_instruction;
18243
18244 if (args_type->id != ZigTypeIdStruct) {
18245 ir_add_error(ira, args,
18246 buf_sprintf("expected tuple or struct, found '%s'", buf_ptr(&args_type->name)));
18247 return ira->codegen->invalid_instruction;
18248 }
18249
18250 IrInstruction **args_ptr = nullptr;
18251 size_t args_len = 0;
18252
18253 if (is_tuple(args_type)) {
18254 args_len = args_type->data.structure.src_field_count;
18255 args_ptr = allocate<IrInstruction *>(args_len, "IrInstruction *");
18256 for (size_t i = 0; i < args_len; i += 1) {
18257 TypeStructField *arg_field = args_type->data.structure.fields[i];
18258 args_ptr[i] = ir_analyze_struct_value_field_value(ira, &instruction->base, args, arg_field);
18259 if (type_is_invalid(args_ptr[i]->value->type))
18260 return ira->codegen->invalid_instruction;
18261 }
18262 } else {
18263 ir_add_error(ira, args, buf_sprintf("TODO: struct args"));
18264 return ira->codegen->invalid_instruction;
18265 }
18266 IrInstruction *result = ir_analyze_call_extra(ira, &instruction->base, instruction->options,
18267 instruction->fn_ref, args_ptr, args_len, instruction->result_loc);
18195 deallocate(args_ptr, args_len, "IrInstruction *");18268 deallocate(args_ptr, args_len, "IrInstruction *");
18196 return result;18269 return result;
18197}18270}
1819818271
18272static IrInstruction *ir_analyze_instruction_call_args(IrAnalyze *ira, IrInstructionCallSrcArgs *instruction) {
18273 IrInstruction **args_ptr = allocate<IrInstruction *>(instruction->args_len, "IrInstruction *");
18274 for (size_t i = 0; i < instruction->args_len; i += 1) {
18275 args_ptr[i] = instruction->args_ptr[i]->child;
18276 if (type_is_invalid(args_ptr[i]->value->type))
18277 return ira->codegen->invalid_instruction;
18278 }
18279
18280 IrInstruction *result = ir_analyze_call_extra(ira, &instruction->base, instruction->options,
18281 instruction->fn_ref, args_ptr, instruction->args_len, instruction->result_loc);
18282 deallocate(args_ptr, instruction->args_len, "IrInstruction *");
18283 return result;
18284}
18285
18199static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction) {18286static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction) {
18200 IrInstruction *fn_ref = call_instruction->fn_ref->child;18287 IrInstruction *fn_ref = call_instruction->fn_ref->child;
18201 if (type_is_invalid(fn_ref->value->type))18288 if (type_is_invalid(fn_ref->value->type))
...@@ -19513,8 +19600,18 @@ static IrInstruction *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_n...@@ -19513,8 +19600,18 @@ static IrInstruction *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_n
19513 PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE, inferred_struct_field, nullptr);19600 PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE, inferred_struct_field, nullptr);
1951419601
19515 if (instr_is_comptime(container_ptr)) {19602 if (instr_is_comptime(container_ptr)) {
19516 IrInstruction *result = ir_const(ira, source_instr, field_ptr_type);19603 ZigValue *ptr_val = ir_resolve_const(ira, container_ptr, UndefBad);
19517 copy_const_val(result->value, container_ptr->value);19604 if (ptr_val == nullptr)
19605 return ira->codegen->invalid_instruction;
19606
19607 IrInstruction *result;
19608 if (ptr_val->data.x_ptr.mut == ConstPtrMutInfer) {
19609 result = ir_build_cast(&ira->new_irb, source_instr->scope,
19610 source_instr->source_node, container_ptr_type, container_ptr, CastOpNoop);
19611 } else {
19612 result = ir_const(ira, source_instr, field_ptr_type);
19613 }
19614 copy_const_val(result->value, ptr_val);
19518 result->value->type = field_ptr_type;19615 result->value->type = field_ptr_type;
19519 return result;19616 return result;
19520 }19617 }
...@@ -20531,20 +20628,6 @@ static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrIns...@@ -20531,20 +20628,6 @@ static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrIns
20531 return ir_analyze_test_non_null(ira, &instruction->base, value);20628 return ir_analyze_test_non_null(ira, &instruction->base, value);
20532}20629}
2053320630
20534static ZigType *get_ptr_elem_type(CodeGen *g, IrInstruction *ptr) {
20535 ir_assert(ptr->value->type->id == ZigTypeIdPointer, ptr);
20536 ZigType *elem_type = ptr->value->type->data.pointer.child_type;
20537 if (elem_type != g->builtin_types.entry_var)
20538 return elem_type;
20539
20540 if (ir_resolve_lazy(g, ptr->source_node, ptr->value))
20541 return g->builtin_types.entry_invalid;
20542
20543 assert(value_is_comptime(ptr->value));
20544 ZigValue *pointee = const_ptr_pointee_unchecked(g, ptr->value);
20545 return pointee->type;
20546}
20547
20548static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr,20631static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr,
20549 IrInstruction *base_ptr, bool safety_check_on, bool initializing)20632 IrInstruction *base_ptr, bool safety_check_on, bool initializing)
20550{20633{
...@@ -27932,6 +28015,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction...@@ -27932,6 +28015,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
27932 return ir_analyze_instruction_field_ptr(ira, (IrInstructionFieldPtr *)instruction);28015 return ir_analyze_instruction_field_ptr(ira, (IrInstructionFieldPtr *)instruction);
27933 case IrInstructionIdCallSrc:28016 case IrInstructionIdCallSrc:
27934 return ir_analyze_instruction_call(ira, (IrInstructionCallSrc *)instruction);28017 return ir_analyze_instruction_call(ira, (IrInstructionCallSrc *)instruction);
28018 case IrInstructionIdCallSrcArgs:
28019 return ir_analyze_instruction_call_args(ira, (IrInstructionCallSrcArgs *)instruction);
27935 case IrInstructionIdCallExtra:28020 case IrInstructionIdCallExtra:
27936 return ir_analyze_instruction_call_extra(ira, (IrInstructionCallExtra *)instruction);28021 return ir_analyze_instruction_call_extra(ira, (IrInstructionCallExtra *)instruction);
27937 case IrInstructionIdBr:28022 case IrInstructionIdBr:
...@@ -28333,6 +28418,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -28333,6 +28418,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
28333 case IrInstructionIdVectorStoreElem:28418 case IrInstructionIdVectorStoreElem:
28334 case IrInstructionIdCallExtra:28419 case IrInstructionIdCallExtra:
28335 case IrInstructionIdCallSrc:28420 case IrInstructionIdCallSrc:
28421 case IrInstructionIdCallSrcArgs:
28336 case IrInstructionIdCallGen:28422 case IrInstructionIdCallGen:
28337 case IrInstructionIdReturn:28423 case IrInstructionIdReturn:
28338 case IrInstructionIdUnreachable:28424 case IrInstructionIdUnreachable:
src/ir_print.cpp+21
...@@ -96,6 +96,8 @@ const char* ir_instruction_type_str(IrInstructionId id) {...@@ -96,6 +96,8 @@ const char* ir_instruction_type_str(IrInstructionId id) {
96 return "CallExtra";96 return "CallExtra";
97 case IrInstructionIdCallSrc:97 case IrInstructionIdCallSrc:
98 return "CallSrc";98 return "CallSrc";
99 case IrInstructionIdCallSrcArgs:
100 return "CallSrcArgs";
99 case IrInstructionIdCallGen:101 case IrInstructionIdCallGen:
100 return "CallGen";102 return "CallGen";
101 case IrInstructionIdConst:103 case IrInstructionIdConst:
...@@ -649,6 +651,22 @@ static void ir_print_call_extra(IrPrint *irp, IrInstructionCallExtra *instructio...@@ -649,6 +651,22 @@ static void ir_print_call_extra(IrPrint *irp, IrInstructionCallExtra *instructio
649 ir_print_result_loc(irp, instruction->result_loc);651 ir_print_result_loc(irp, instruction->result_loc);
650}652}
651653
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
652static void ir_print_call_src(IrPrint *irp, IrInstructionCallSrc *call_instruction) {670static void ir_print_call_src(IrPrint *irp, IrInstructionCallSrc *call_instruction) {
653 switch (call_instruction->modifier) {671 switch (call_instruction->modifier) {
654 case CallModifierNone:672 case CallModifierNone:
...@@ -2131,6 +2149,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool...@@ -2131,6 +2149,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool
2131 case IrInstructionIdCallSrc:2149 case IrInstructionIdCallSrc:
2132 ir_print_call_src(irp, (IrInstructionCallSrc *)instruction);2150 ir_print_call_src(irp, (IrInstructionCallSrc *)instruction);
2133 break;2151 break;
2152 case IrInstructionIdCallSrcArgs:
2153 ir_print_call_src_args(irp, (IrInstructionCallSrcArgs *)instruction);
2154 break;
2134 case IrInstructionIdCallGen:2155 case IrInstructionIdCallGen:
2135 ir_print_call_gen(irp, (IrInstructionCallGen *)instruction);2156 ir_print_call_gen(irp, (IrInstructionCallGen *)instruction);
2136 break;2157 break;
test/stage1/behavior/call.zig+13-2
...@@ -28,10 +28,21 @@ test "tuple parameters" {...@@ -28,10 +28,21 @@ test "tuple parameters" {
28 return a + b;28 return a + b;
29 }29 }
30 }.add;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);
31 expect(@call(.{}, add, .{ 12, 34 }) == 46);36 expect(@call(.{}, add, .{ 12, 34 }) == 46);
32 comptime expect(@call(.{}, add, .{ 12, 34 }) == 46);37 comptime expect(@call(.{}, add, .{ 12, 34 }) == 46);
33 {38 {
34 const separate_args = .{ 12, 34 };39 const separate_args0 = .{ a, b };
35 expect(@call(.{ .modifier = .always_inline }, add, separate_args) == 46);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);
36 }47 }
37}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 {