| author | |
| committer | |
| log | 8ee629aa4c7fb0127c71aec0b2c81353c4291ebb |
| tree | 221c6b97638b189d66e328c300d013292e0227f6 |
| parent | 7a1a92478878f591abbadcd5735f03c817c6eb53 |
4 files changed, 298 insertions(+), 325 deletions(-)
src-self-hosted/Module.zig+142-70| ... | ... | @@ -1215,7 +1215,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { |
| 1215 | 1215 | .return_type = return_type_inst, |
| 1216 | 1216 | .param_types = param_types, |
| 1217 | 1217 | }, .{}); |
| 1218 | _ = try self.addZIRInst(&fn_type_scope.base, fn_src, zir.Inst.Return, .{ .operand = fn_type_inst }, .{}); | |
| 1218 | _ = try self.addZIRUnOp(&fn_type_scope.base, fn_src, .@"return", fn_type_inst); | |
| 1219 | 1219 | |
| 1220 | 1220 | // We need the memory for the Type to go into the arena for the Decl |
| 1221 | 1221 | var decl_arena = std.heap.ArenaAllocator.init(self.gpa); |
| ... | ... | @@ -1256,7 +1256,15 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { |
| 1256 | 1256 | const name_token = param.name_token.?; |
| 1257 | 1257 | const src = tree.token_locs[name_token].start; |
| 1258 | 1258 | const param_name = tree.tokenSlice(name_token); |
| 1259 | const arg = try newZIRInst(&gen_scope_arena.allocator, src, zir.Inst.Arg, .{}, .{}); | |
| 1259 | const arg = try gen_scope_arena.allocator.create(zir.Inst.NoOp); | |
| 1260 | arg.* = .{ | |
| 1261 | .base = .{ | |
| 1262 | .tag = .arg, | |
| 1263 | .src = src, | |
| 1264 | }, | |
| 1265 | .positionals = .{}, | |
| 1266 | .kw_args = .{}, | |
| 1267 | }; | |
| 1260 | 1268 | gen_scope.instructions.items[i] = &arg.base; |
| 1261 | 1269 | const sub_scope = try gen_scope_arena.allocator.create(Scope.LocalVar); |
| 1262 | 1270 | sub_scope.* = .{ |
| ... | ... | @@ -1276,7 +1284,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { |
| 1276 | 1284 | !gen_scope.instructions.items[gen_scope.instructions.items.len - 1].tag.isNoReturn())) |
| 1277 | 1285 | { |
| 1278 | 1286 | const src = tree.token_locs[body_block.rbrace].start; |
| 1279 | _ = try self.addZIRInst(&gen_scope.base, src, zir.Inst.ReturnVoid, .{}, .{}); | |
| 1287 | _ = try self.addZIRNoOp(&gen_scope.base, src, .returnvoid); | |
| 1280 | 1288 | } |
| 1281 | 1289 | |
| 1282 | 1290 | const fn_zir = try gen_scope_arena.allocator.create(Fn.ZIR); |
| ... | ... | @@ -2067,14 +2075,17 @@ fn addCall( |
| 2067 | 2075 | return &inst.base; |
| 2068 | 2076 | } |
| 2069 | 2077 | |
| 2070 | fn newZIRInst( | |
| 2071 | gpa: *Allocator, | |
| 2078 | pub fn addZIRInstSpecial( | |
| 2079 | self: *Module, | |
| 2080 | scope: *Scope, | |
| 2072 | 2081 | src: usize, |
| 2073 | 2082 | comptime T: type, |
| 2074 | 2083 | positionals: std.meta.fieldInfo(T, "positionals").field_type, |
| 2075 | 2084 | kw_args: std.meta.fieldInfo(T, "kw_args").field_type, |
| 2076 | 2085 | ) !*T { |
| 2077 | const inst = try gpa.create(T); | |
| 2086 | const gen_zir = scope.getGenZIR(); | |
| 2087 | try gen_zir.instructions.ensureCapacity(self.gpa, gen_zir.instructions.items.len + 1); | |
| 2088 | const inst = try gen_zir.arena.create(T); | |
| 2078 | 2089 | inst.* = .{ |
| 2079 | 2090 | .base = .{ |
| 2080 | 2091 | .tag = T.base_tag, |
| ... | ... | @@ -2083,22 +2094,79 @@ fn newZIRInst( |
| 2083 | 2094 | .positionals = positionals, |
| 2084 | 2095 | .kw_args = kw_args, |
| 2085 | 2096 | }; |
| 2097 | gen_zir.instructions.appendAssumeCapacity(&inst.base); | |
| 2086 | 2098 | return inst; |
| 2087 | 2099 | } |
| 2088 | 2100 | |
| 2089 | pub fn addZIRInstSpecial( | |
| 2101 | pub fn addZIRNoOp( | |
| 2090 | 2102 | self: *Module, |
| 2091 | 2103 | scope: *Scope, |
| 2092 | 2104 | src: usize, |
| 2093 | comptime T: type, | |
| 2094 | positionals: std.meta.fieldInfo(T, "positionals").field_type, | |
| 2095 | kw_args: std.meta.fieldInfo(T, "kw_args").field_type, | |
| 2096 | ) !*T { | |
| 2105 | tag: zir.Inst.Tag, | |
| 2106 | ) !*zir.Inst { | |
| 2097 | 2107 | const gen_zir = scope.getGenZIR(); |
| 2098 | 2108 | try gen_zir.instructions.ensureCapacity(self.gpa, gen_zir.instructions.items.len + 1); |
| 2099 | const inst = try newZIRInst(gen_zir.arena, src, T, positionals, kw_args); | |
| 2109 | const inst = try gen_zir.arena.create(zir.Inst.NoOp); | |
| 2110 | inst.* = .{ | |
| 2111 | .base = .{ | |
| 2112 | .tag = tag, | |
| 2113 | .src = src, | |
| 2114 | }, | |
| 2115 | .positionals = .{}, | |
| 2116 | .kw_args = .{}, | |
| 2117 | }; | |
| 2100 | 2118 | gen_zir.instructions.appendAssumeCapacity(&inst.base); |
| 2101 | return inst; | |
| 2119 | return &inst.base; | |
| 2120 | } | |
| 2121 | ||
| 2122 | pub fn addZIRUnOp( | |
| 2123 | self: *Module, | |
| 2124 | scope: *Scope, | |
| 2125 | src: usize, | |
| 2126 | tag: zir.Inst.Tag, | |
| 2127 | operand: *zir.Inst, | |
| 2128 | ) !*zir.Inst { | |
| 2129 | const gen_zir = scope.getGenZIR(); | |
| 2130 | try gen_zir.instructions.ensureCapacity(self.gpa, gen_zir.instructions.items.len + 1); | |
| 2131 | const inst = try gen_zir.arena.create(zir.Inst.UnOp); | |
| 2132 | inst.* = .{ | |
| 2133 | .base = .{ | |
| 2134 | .tag = tag, | |
| 2135 | .src = src, | |
| 2136 | }, | |
| 2137 | .positionals = .{ | |
| 2138 | .operand = operand, | |
| 2139 | }, | |
| 2140 | .kw_args = .{}, | |
| 2141 | }; | |
| 2142 | gen_zir.instructions.appendAssumeCapacity(&inst.base); | |
| 2143 | return &inst.base; | |
| 2144 | } | |
| 2145 | ||
| 2146 | pub fn addZIRBinOp( | |
| 2147 | self: *Module, | |
| 2148 | scope: *Scope, | |
| 2149 | src: usize, | |
| 2150 | tag: zir.Inst.Tag, | |
| 2151 | lhs: *zir.Inst, | |
| 2152 | rhs: *zir.Inst, | |
| 2153 | ) !*zir.Inst { | |
| 2154 | const gen_zir = scope.getGenZIR(); | |
| 2155 | try gen_zir.instructions.ensureCapacity(self.gpa, gen_zir.instructions.items.len + 1); | |
| 2156 | const inst = try gen_zir.arena.create(zir.Inst.BinOp); | |
| 2157 | inst.* = .{ | |
| 2158 | .base = .{ | |
| 2159 | .tag = tag, | |
| 2160 | .src = src, | |
| 2161 | }, | |
| 2162 | .positionals = .{ | |
| 2163 | .lhs = lhs, | |
| 2164 | .rhs = rhs, | |
| 2165 | }, | |
| 2166 | .kw_args = .{}, | |
| 2167 | }; | |
| 2168 | gen_zir.instructions.appendAssumeCapacity(&inst.base); | |
| 2169 | return &inst.base; | |
| 2102 | 2170 | } |
| 2103 | 2171 | |
| 2104 | 2172 | pub fn addZIRInst( |
| ... | ... | @@ -2252,46 +2320,51 @@ fn analyzeInstConst(self: *Module, scope: *Scope, const_inst: *zir.Inst.Const) I |
| 2252 | 2320 | |
| 2253 | 2321 | fn analyzeInst(self: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!*Inst { |
| 2254 | 2322 | switch (old_inst.tag) { |
| 2255 | .arg => return self.analyzeInstArg(scope, old_inst.cast(zir.Inst.Arg).?), | |
| 2256 | .block => return self.analyzeInstBlock(scope, old_inst.cast(zir.Inst.Block).?), | |
| 2257 | .@"break" => return self.analyzeInstBreak(scope, old_inst.cast(zir.Inst.Break).?), | |
| 2258 | .breakpoint => return self.analyzeInstBreakpoint(scope, old_inst.cast(zir.Inst.Breakpoint).?), | |
| 2259 | .breakvoid => return self.analyzeInstBreakVoid(scope, old_inst.cast(zir.Inst.BreakVoid).?), | |
| 2260 | .call => return self.analyzeInstCall(scope, old_inst.cast(zir.Inst.Call).?), | |
| 2261 | .compileerror => return self.analyzeInstCompileError(scope, old_inst.cast(zir.Inst.CompileError).?), | |
| 2262 | .@"const" => return self.analyzeInstConst(scope, old_inst.cast(zir.Inst.Const).?), | |
| 2263 | .declref => return self.analyzeInstDeclRef(scope, old_inst.cast(zir.Inst.DeclRef).?), | |
| 2264 | .declref_str => return self.analyzeInstDeclRefStr(scope, old_inst.cast(zir.Inst.DeclRefStr).?), | |
| 2265 | .declval => return self.analyzeInstDeclVal(scope, old_inst.cast(zir.Inst.DeclVal).?), | |
| 2266 | .declval_in_module => return self.analyzeInstDeclValInModule(scope, old_inst.cast(zir.Inst.DeclValInModule).?), | |
| 2267 | .str => return self.analyzeInstStr(scope, old_inst.cast(zir.Inst.Str).?), | |
| 2323 | .arg => return self.analyzeInstArg(scope, old_inst.castTag(.arg).?), | |
| 2324 | .block => return self.analyzeInstBlock(scope, old_inst.castTag(.block).?), | |
| 2325 | .@"break" => return self.analyzeInstBreak(scope, old_inst.castTag(.@"break").?), | |
| 2326 | .breakpoint => return self.analyzeInstBreakpoint(scope, old_inst.castTag(.breakpoint).?), | |
| 2327 | .breakvoid => return self.analyzeInstBreakVoid(scope, old_inst.castTag(.breakvoid).?), | |
| 2328 | .call => return self.analyzeInstCall(scope, old_inst.castTag(.call).?), | |
| 2329 | .compileerror => return self.analyzeInstCompileError(scope, old_inst.castTag(.compileerror).?), | |
| 2330 | .@"const" => return self.analyzeInstConst(scope, old_inst.castTag(.@"const").?), | |
| 2331 | .declref => return self.analyzeInstDeclRef(scope, old_inst.castTag(.declref).?), | |
| 2332 | .declref_str => return self.analyzeInstDeclRefStr(scope, old_inst.castTag(.declref_str).?), | |
| 2333 | .declval => return self.analyzeInstDeclVal(scope, old_inst.castTag(.declval).?), | |
| 2334 | .declval_in_module => return self.analyzeInstDeclValInModule(scope, old_inst.castTag(.declval_in_module).?), | |
| 2335 | .str => return self.analyzeInstStr(scope, old_inst.castTag(.str).?), | |
| 2268 | 2336 | .int => { |
| 2269 | const big_int = old_inst.cast(zir.Inst.Int).?.positionals.int; | |
| 2337 | const big_int = old_inst.castTag(.int).?.positionals.int; | |
| 2270 | 2338 | return self.constIntBig(scope, old_inst.src, Type.initTag(.comptime_int), big_int); |
| 2271 | 2339 | }, |
| 2272 | .inttype => return self.analyzeInstIntType(scope, old_inst.cast(zir.Inst.IntType).?), | |
| 2273 | .ptrtoint => return self.analyzeInstPtrToInt(scope, old_inst.cast(zir.Inst.PtrToInt).?), | |
| 2274 | .fieldptr => return self.analyzeInstFieldPtr(scope, old_inst.cast(zir.Inst.FieldPtr).?), | |
| 2275 | .deref => return self.analyzeInstDeref(scope, old_inst.cast(zir.Inst.Deref).?), | |
| 2276 | .as => return self.analyzeInstAs(scope, old_inst.cast(zir.Inst.As).?), | |
| 2277 | .@"asm" => return self.analyzeInstAsm(scope, old_inst.cast(zir.Inst.Asm).?), | |
| 2278 | .@"unreachable" => return self.analyzeInstUnreachable(scope, old_inst.cast(zir.Inst.Unreachable).?), | |
| 2279 | .@"return" => return self.analyzeInstRet(scope, old_inst.cast(zir.Inst.Return).?), | |
| 2280 | .returnvoid => return self.analyzeInstRetVoid(scope, old_inst.cast(zir.Inst.ReturnVoid).?), | |
| 2281 | .@"fn" => return self.analyzeInstFn(scope, old_inst.cast(zir.Inst.Fn).?), | |
| 2282 | .@"export" => return self.analyzeInstExport(scope, old_inst.cast(zir.Inst.Export).?), | |
| 2283 | .primitive => return self.analyzeInstPrimitive(scope, old_inst.cast(zir.Inst.Primitive).?), | |
| 2284 | .fntype => return self.analyzeInstFnType(scope, old_inst.cast(zir.Inst.FnType).?), | |
| 2285 | .intcast => return self.analyzeInstIntCast(scope, old_inst.cast(zir.Inst.IntCast).?), | |
| 2286 | .bitcast => return self.analyzeInstBitCast(scope, old_inst.cast(zir.Inst.BitCast).?), | |
| 2287 | .elemptr => return self.analyzeInstElemPtr(scope, old_inst.cast(zir.Inst.ElemPtr).?), | |
| 2288 | .add => return self.analyzeInstAdd(scope, old_inst.cast(zir.Inst.Add).?), | |
| 2289 | .sub => return self.analyzeInstSub(scope, old_inst.cast(zir.Inst.Sub).?), | |
| 2290 | .cmp => return self.analyzeInstCmp(scope, old_inst.cast(zir.Inst.Cmp).?), | |
| 2291 | .condbr => return self.analyzeInstCondBr(scope, old_inst.cast(zir.Inst.CondBr).?), | |
| 2292 | .isnull => return self.analyzeInstIsNull(scope, old_inst.cast(zir.Inst.IsNull).?), | |
| 2293 | .isnonnull => return self.analyzeInstIsNonNull(scope, old_inst.cast(zir.Inst.IsNonNull).?), | |
| 2294 | .boolnot => return self.analyzeInstBoolNot(scope, old_inst.cast(zir.Inst.BoolNot).?), | |
| 2340 | .inttype => return self.analyzeInstIntType(scope, old_inst.castTag(.inttype).?), | |
| 2341 | .ptrtoint => return self.analyzeInstPtrToInt(scope, old_inst.castTag(.ptrtoint).?), | |
| 2342 | .fieldptr => return self.analyzeInstFieldPtr(scope, old_inst.castTag(.fieldptr).?), | |
| 2343 | .deref => return self.analyzeInstDeref(scope, old_inst.castTag(.deref).?), | |
| 2344 | .as => return self.analyzeInstAs(scope, old_inst.castTag(.as).?), | |
| 2345 | .@"asm" => return self.analyzeInstAsm(scope, old_inst.castTag(.@"asm").?), | |
| 2346 | .@"unreachable" => return self.analyzeInstUnreachable(scope, old_inst.castTag(.@"unreachable").?), | |
| 2347 | .@"return" => return self.analyzeInstRet(scope, old_inst.castTag(.@"return").?), | |
| 2348 | .returnvoid => return self.analyzeInstRetVoid(scope, old_inst.castTag(.returnvoid).?), | |
| 2349 | .@"fn" => return self.analyzeInstFn(scope, old_inst.castTag(.@"fn").?), | |
| 2350 | .@"export" => return self.analyzeInstExport(scope, old_inst.castTag(.@"export").?), | |
| 2351 | .primitive => return self.analyzeInstPrimitive(scope, old_inst.castTag(.primitive).?), | |
| 2352 | .fntype => return self.analyzeInstFnType(scope, old_inst.castTag(.fntype).?), | |
| 2353 | .intcast => return self.analyzeInstIntCast(scope, old_inst.castTag(.intcast).?), | |
| 2354 | .bitcast => return self.analyzeInstBitCast(scope, old_inst.castTag(.bitcast).?), | |
| 2355 | .elemptr => return self.analyzeInstElemPtr(scope, old_inst.castTag(.elemptr).?), | |
| 2356 | .add => return self.analyzeInstAdd(scope, old_inst.castTag(.add).?), | |
| 2357 | .sub => return self.analyzeInstSub(scope, old_inst.castTag(.sub).?), | |
| 2358 | .cmp_lt => return self.analyzeInstCmp(scope, old_inst.castTag(.cmp_lt).?, .lt), | |
| 2359 | .cmp_lte => return self.analyzeInstCmp(scope, old_inst.castTag(.cmp_lte).?, .lte), | |
| 2360 | .cmp_eq => return self.analyzeInstCmp(scope, old_inst.castTag(.cmp_eq).?, .eq), | |
| 2361 | .cmp_gte => return self.analyzeInstCmp(scope, old_inst.castTag(.cmp_gte).?, .gte), | |
| 2362 | .cmp_gt => return self.analyzeInstCmp(scope, old_inst.castTag(.cmp_gt).?, .gt), | |
| 2363 | .cmp_neq => return self.analyzeInstCmp(scope, old_inst.castTag(.cmp_neq).?, .neq), | |
| 2364 | .condbr => return self.analyzeInstCondBr(scope, old_inst.castTag(.condbr).?), | |
| 2365 | .isnull => return self.analyzeInstIsNonNull(scope, old_inst.castTag(.isnull).?, true), | |
| 2366 | .isnonnull => return self.analyzeInstIsNonNull(scope, old_inst.castTag(.isnonnull).?, false), | |
| 2367 | .boolnot => return self.analyzeInstBoolNot(scope, old_inst.castTag(.boolnot).?), | |
| 2295 | 2368 | } |
| 2296 | 2369 | } |
| 2297 | 2370 | |
| ... | ... | @@ -2372,7 +2445,7 @@ fn analyzeInstCompileError(self: *Module, scope: *Scope, inst: *zir.Inst.Compile |
| 2372 | 2445 | return self.fail(scope, inst.base.src, "{}", .{inst.positionals.msg}); |
| 2373 | 2446 | } |
| 2374 | 2447 | |
| 2375 | fn analyzeInstArg(self: *Module, scope: *Scope, inst: *zir.Inst.Arg) InnerError!*Inst { | |
| 2448 | fn analyzeInstArg(self: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst { | |
| 2376 | 2449 | const b = try self.requireRuntimeBlock(scope, inst.base.src); |
| 2377 | 2450 | const fn_ty = b.func.?.owner_decl.typed_value.most_recent.typed_value.ty; |
| 2378 | 2451 | const param_index = b.instructions.items.len; |
| ... | ... | @@ -2435,7 +2508,7 @@ fn analyzeInstBlock(self: *Module, scope: *Scope, inst: *zir.Inst.Block) InnerEr |
| 2435 | 2508 | return &block_inst.base; |
| 2436 | 2509 | } |
| 2437 | 2510 | |
| 2438 | fn analyzeInstBreakpoint(self: *Module, scope: *Scope, inst: *zir.Inst.Breakpoint) InnerError!*Inst { | |
| 2511 | fn analyzeInstBreakpoint(self: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst { | |
| 2439 | 2512 | const b = try self.requireRuntimeBlock(scope, inst.base.src); |
| 2440 | 2513 | return self.addNoOp(b, inst.base.src, Type.initTag(.void), .breakpoint); |
| 2441 | 2514 | } |
| ... | ... | @@ -2791,11 +2864,11 @@ fn analyzeInstElemPtr(self: *Module, scope: *Scope, inst: *zir.Inst.ElemPtr) Inn |
| 2791 | 2864 | return self.fail(scope, inst.base.src, "TODO implement more analyze elemptr", .{}); |
| 2792 | 2865 | } |
| 2793 | 2866 | |
| 2794 | fn analyzeInstSub(self: *Module, scope: *Scope, inst: *zir.Inst.Sub) InnerError!*Inst { | |
| 2867 | fn analyzeInstSub(self: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst { | |
| 2795 | 2868 | return self.fail(scope, inst.base.src, "TODO implement analysis of sub", .{}); |
| 2796 | 2869 | } |
| 2797 | 2870 | |
| 2798 | fn analyzeInstAdd(self: *Module, scope: *Scope, inst: *zir.Inst.Add) InnerError!*Inst { | |
| 2871 | fn analyzeInstAdd(self: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst { | |
| 2799 | 2872 | const tracy = trace(@src()); |
| 2800 | 2873 | defer tracy.end(); |
| 2801 | 2874 | |
| ... | ... | @@ -2848,9 +2921,9 @@ fn analyzeInstAdd(self: *Module, scope: *Scope, inst: *zir.Inst.Add) InnerError! |
| 2848 | 2921 | return self.fail(scope, inst.base.src, "TODO analyze add for {} + {}", .{ lhs.ty.zigTypeTag(), rhs.ty.zigTypeTag() }); |
| 2849 | 2922 | } |
| 2850 | 2923 | |
| 2851 | fn analyzeInstDeref(self: *Module, scope: *Scope, deref: *zir.Inst.Deref) InnerError!*Inst { | |
| 2852 | const ptr = try self.resolveInst(scope, deref.positionals.ptr); | |
| 2853 | return self.analyzeDeref(scope, deref.base.src, ptr, deref.positionals.ptr.src); | |
| 2924 | fn analyzeInstDeref(self: *Module, scope: *Scope, deref: *zir.Inst.UnOp) InnerError!*Inst { | |
| 2925 | const ptr = try self.resolveInst(scope, deref.positionals.operand); | |
| 2926 | return self.analyzeDeref(scope, deref.base.src, ptr, deref.positionals.operand.src); | |
| 2854 | 2927 | } |
| 2855 | 2928 | |
| 2856 | 2929 | fn analyzeDeref(self: *Module, scope: *Scope, src: usize, ptr: *Inst, ptr_src: usize) InnerError!*Inst { |
| ... | ... | @@ -2907,10 +2980,14 @@ fn analyzeInstAsm(self: *Module, scope: *Scope, assembly: *zir.Inst.Asm) InnerEr |
| 2907 | 2980 | return &inst.base; |
| 2908 | 2981 | } |
| 2909 | 2982 | |
| 2910 | fn analyzeInstCmp(self: *Module, scope: *Scope, inst: *zir.Inst.Cmp) InnerError!*Inst { | |
| 2983 | fn analyzeInstCmp( | |
| 2984 | self: *Module, | |
| 2985 | scope: *Scope, | |
| 2986 | inst: *zir.Inst.BinOp, | |
| 2987 | op: std.math.CompareOperator, | |
| 2988 | ) InnerError!*Inst { | |
| 2911 | 2989 | const lhs = try self.resolveInst(scope, inst.positionals.lhs); |
| 2912 | 2990 | const rhs = try self.resolveInst(scope, inst.positionals.rhs); |
| 2913 | const op = inst.positionals.op; | |
| 2914 | 2991 | |
| 2915 | 2992 | const is_equality_cmp = switch (op) { |
| 2916 | 2993 | .eq, .neq => true, |
| ... | ... | @@ -2964,7 +3041,7 @@ fn analyzeInstCmp(self: *Module, scope: *Scope, inst: *zir.Inst.Cmp) InnerError! |
| 2964 | 3041 | return self.fail(scope, inst.base.src, "TODO implement more cmp analysis", .{}); |
| 2965 | 3042 | } |
| 2966 | 3043 | |
| 2967 | fn analyzeInstBoolNot(self: *Module, scope: *Scope, inst: *zir.Inst.BoolNot) InnerError!*Inst { | |
| 3044 | fn analyzeInstBoolNot(self: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst { | |
| 2968 | 3045 | const uncasted_operand = try self.resolveInst(scope, inst.positionals.operand); |
| 2969 | 3046 | const bool_type = Type.initTag(.bool); |
| 2970 | 3047 | const operand = try self.coerce(scope, bool_type, uncasted_operand); |
| ... | ... | @@ -2975,14 +3052,9 @@ fn analyzeInstBoolNot(self: *Module, scope: *Scope, inst: *zir.Inst.BoolNot) Inn |
| 2975 | 3052 | return self.addUnOp(b, inst.base.src, bool_type, .not, operand); |
| 2976 | 3053 | } |
| 2977 | 3054 | |
| 2978 | fn analyzeInstIsNull(self: *Module, scope: *Scope, inst: *zir.Inst.IsNull) InnerError!*Inst { | |
| 2979 | const operand = try self.resolveInst(scope, inst.positionals.operand); | |
| 2980 | return self.analyzeIsNull(scope, inst.base.src, operand, true); | |
| 2981 | } | |
| 2982 | ||
| 2983 | fn analyzeInstIsNonNull(self: *Module, scope: *Scope, inst: *zir.Inst.IsNonNull) InnerError!*Inst { | |
| 3055 | fn analyzeInstIsNonNull(self: *Module, scope: *Scope, inst: *zir.Inst.UnOp, invert_logic: bool) InnerError!*Inst { | |
| 2984 | 3056 | const operand = try self.resolveInst(scope, inst.positionals.operand); |
| 2985 | return self.analyzeIsNull(scope, inst.base.src, operand, false); | |
| 3057 | return self.analyzeIsNull(scope, inst.base.src, operand, invert_logic); | |
| 2986 | 3058 | } |
| 2987 | 3059 | |
| 2988 | 3060 | fn analyzeInstCondBr(self: *Module, scope: *Scope, inst: *zir.Inst.CondBr) InnerError!*Inst { |
| ... | ... | @@ -3031,7 +3103,7 @@ fn wantSafety(self: *Module, scope: *Scope) bool { |
| 3031 | 3103 | }; |
| 3032 | 3104 | } |
| 3033 | 3105 | |
| 3034 | fn analyzeInstUnreachable(self: *Module, scope: *Scope, unreach: *zir.Inst.Unreachable) InnerError!*Inst { | |
| 3106 | fn analyzeInstUnreachable(self: *Module, scope: *Scope, unreach: *zir.Inst.NoOp) InnerError!*Inst { | |
| 3035 | 3107 | const b = try self.requireRuntimeBlock(scope, unreach.base.src); |
| 3036 | 3108 | if (self.wantSafety(scope)) { |
| 3037 | 3109 | // TODO Once we have a panic function to call, call it here instead of this. |
| ... | ... | @@ -3040,13 +3112,13 @@ fn analyzeInstUnreachable(self: *Module, scope: *Scope, unreach: *zir.Inst.Unrea |
| 3040 | 3112 | return self.addNoOp(b, unreach.base.src, Type.initTag(.noreturn), .unreach); |
| 3041 | 3113 | } |
| 3042 | 3114 | |
| 3043 | fn analyzeInstRet(self: *Module, scope: *Scope, inst: *zir.Inst.Return) InnerError!*Inst { | |
| 3115 | fn analyzeInstRet(self: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst { | |
| 3044 | 3116 | const operand = try self.resolveInst(scope, inst.positionals.operand); |
| 3045 | 3117 | const b = try self.requireRuntimeBlock(scope, inst.base.src); |
| 3046 | 3118 | return self.addUnOp(b, inst.base.src, Type.initTag(.noreturn), .ret, operand); |
| 3047 | 3119 | } |
| 3048 | 3120 | |
| 3049 | fn analyzeInstRetVoid(self: *Module, scope: *Scope, inst: *zir.Inst.ReturnVoid) InnerError!*Inst { | |
| 3121 | fn analyzeInstRetVoid(self: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst { | |
| 3050 | 3122 | const b = try self.requireRuntimeBlock(scope, inst.base.src); |
| 3051 | 3123 | return self.addNoOp(b, inst.base.src, Type.initTag(.noreturn), .retvoid); |
| 3052 | 3124 | } |
src-self-hosted/astgen.zig+18-40| ... | ... | @@ -16,6 +16,15 @@ pub fn expr(mod: *Module, scope: *Scope, node: *ast.Node) InnerError!*zir.Inst { |
| 16 | 16 | switch (node.tag) { |
| 17 | 17 | .VarDecl => unreachable, // Handled in `blockExpr`. |
| 18 | 18 | |
| 19 | .Add => return simpleInfixOp(mod, scope, node.castTag(.Add).?, .add), | |
| 20 | .Sub => return simpleInfixOp(mod, scope, node.castTag(.Sub).?, .sub), | |
| 21 | .BangEqual => return simpleInfixOp(mod, scope, node.castTag(.BangEqual).?, .cmp_neq), | |
| 22 | .EqualEqual => return simpleInfixOp(mod, scope, node.castTag(.EqualEqual).?, .cmp_eq), | |
| 23 | .GreaterThan => return simpleInfixOp(mod, scope, node.castTag(.GreaterThan).?, .cmp_gt), | |
| 24 | .GreaterOrEqual => return simpleInfixOp(mod, scope, node.castTag(.GreaterOrEqual).?, .cmp_gte), | |
| 25 | .LessThan => return simpleInfixOp(mod, scope, node.castTag(.LessThan).?, .cmp_lt), | |
| 26 | .LessOrEqual => return simpleInfixOp(mod, scope, node.castTag(.LessOrEqual).?, .cmp_lte), | |
| 27 | ||
| 19 | 28 | .Identifier => return identifier(mod, scope, node.castTag(.Identifier).?), |
| 20 | 29 | .Asm => return assembly(mod, scope, node.castTag(.Asm).?), |
| 21 | 30 | .StringLiteral => return stringLiteral(mod, scope, node.castTag(.StringLiteral).?), |
| ... | ... | @@ -26,13 +35,6 @@ pub fn expr(mod: *Module, scope: *Scope, node: *ast.Node) InnerError!*zir.Inst { |
| 26 | 35 | .ControlFlowExpression => return controlFlowExpr(mod, scope, node.castTag(.ControlFlowExpression).?), |
| 27 | 36 | .If => return ifExpr(mod, scope, node.castTag(.If).?), |
| 28 | 37 | .Assign => return assign(mod, scope, node.castTag(.Assign).?), |
| 29 | .Add => return add(mod, scope, node.castTag(.Add).?), | |
| 30 | .BangEqual => return cmp(mod, scope, node.castTag(.BangEqual).?, .neq), | |
| 31 | .EqualEqual => return cmp(mod, scope, node.castTag(.EqualEqual).?, .eq), | |
| 32 | .GreaterThan => return cmp(mod, scope, node.castTag(.GreaterThan).?, .gt), | |
| 33 | .GreaterOrEqual => return cmp(mod, scope, node.castTag(.GreaterOrEqual).?, .gte), | |
| 34 | .LessThan => return cmp(mod, scope, node.castTag(.LessThan).?, .lt), | |
| 35 | .LessOrEqual => return cmp(mod, scope, node.castTag(.LessOrEqual).?, .lte), | |
| 36 | 38 | .Period => return field(mod, scope, node.castTag(.Period).?), |
| 37 | 39 | .Deref => return deref(mod, scope, node.castTag(.Deref).?), |
| 38 | 40 | .BoolNot => return boolNot(mod, scope, node.castTag(.BoolNot).?), |
| ... | ... | @@ -97,14 +99,6 @@ fn varDecl(mod: *Module, scope: *Scope, node: *ast.Node.VarDecl) InnerError!Scop |
| 97 | 99 | }, |
| 98 | 100 | .Keyword_var => { |
| 99 | 101 | return mod.failNode(scope, &node.base, "TODO implement local vars", .{}); |
| 100 | //const src = tree.token_locs[node.name_token].start; | |
| 101 | //const alloc = mod.addZIRInst(scope, src, zir.Inst.Alloc, .{}, .{}); | |
| 102 | //if (node.getTrailer("type_node")) |type_node| { | |
| 103 | // const type_inst = try expr(mod, scope, type_node); | |
| 104 | // return mod.failNode(scope, type_node, "TODO implement typed var locals", .{}); | |
| 105 | //} else { | |
| 106 | // return mod.failTok(scope, node.mut_token, "TODO implement mutable type-inferred locals", .{}); | |
| 107 | //} | |
| 108 | 102 | }, |
| 109 | 103 | else => unreachable, |
| 110 | 104 | } |
| ... | ... | @@ -114,7 +108,7 @@ fn boolNot(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerErr |
| 114 | 108 | const operand = try expr(mod, scope, node.rhs); |
| 115 | 109 | const tree = scope.tree(); |
| 116 | 110 | const src = tree.token_locs[node.op_token].start; |
| 117 | return mod.addZIRInst(scope, src, zir.Inst.BoolNot, .{ .operand = operand }, .{}); | |
| 111 | return mod.addZIRUnOp(scope, src, .boolnot, operand); | |
| 118 | 112 | } |
| 119 | 113 | |
| 120 | 114 | fn assign(mod: *Module, scope: *Scope, infix_node: *ast.Node.SimpleInfixOp) InnerError!*zir.Inst { |
| ... | ... | @@ -169,33 +163,21 @@ fn field(mod: *Module, scope: *Scope, node: *ast.Node.SimpleInfixOp) InnerError! |
| 169 | 163 | const field_name = try identifierStringInst(mod, scope, node.rhs.castTag(.Identifier).?); |
| 170 | 164 | |
| 171 | 165 | const pointer = try mod.addZIRInst(scope, src, zir.Inst.FieldPtr, .{ .object_ptr = lhs, .field_name = field_name }, .{}); |
| 172 | return mod.addZIRInst(scope, src, zir.Inst.Deref, .{ .ptr = pointer }, .{}); | |
| 166 | return mod.addZIRUnOp(scope, src, .deref, pointer); | |
| 173 | 167 | } |
| 174 | 168 | |
| 175 | 169 | fn deref(mod: *Module, scope: *Scope, node: *ast.Node.SimpleSuffixOp) InnerError!*zir.Inst { |
| 176 | 170 | const tree = scope.tree(); |
| 177 | 171 | const src = tree.token_locs[node.rtoken].start; |
| 178 | ||
| 179 | 172 | const lhs = try expr(mod, scope, node.lhs); |
| 180 | ||
| 181 | return mod.addZIRInst(scope, src, zir.Inst.Deref, .{ .ptr = lhs }, .{}); | |
| 182 | } | |
| 183 | ||
| 184 | fn add(mod: *Module, scope: *Scope, infix_node: *ast.Node.SimpleInfixOp) InnerError!*zir.Inst { | |
| 185 | const lhs = try expr(mod, scope, infix_node.lhs); | |
| 186 | const rhs = try expr(mod, scope, infix_node.rhs); | |
| 187 | ||
| 188 | const tree = scope.tree(); | |
| 189 | const src = tree.token_locs[infix_node.op_token].start; | |
| 190 | ||
| 191 | return mod.addZIRInst(scope, src, zir.Inst.Add, .{ .lhs = lhs, .rhs = rhs }, .{}); | |
| 173 | return mod.addZIRUnOp(scope, src, .deref, lhs); | |
| 192 | 174 | } |
| 193 | 175 | |
| 194 | fn cmp( | |
| 176 | fn simpleInfixOp( | |
| 195 | 177 | mod: *Module, |
| 196 | 178 | scope: *Scope, |
| 197 | 179 | infix_node: *ast.Node.SimpleInfixOp, |
| 198 | op: std.math.CompareOperator, | |
| 180 | op_inst_tag: zir.Inst.Tag, | |
| 199 | 181 | ) InnerError!*zir.Inst { |
| 200 | 182 | const lhs = try expr(mod, scope, infix_node.lhs); |
| 201 | 183 | const rhs = try expr(mod, scope, infix_node.rhs); |
| ... | ... | @@ -203,11 +185,7 @@ fn cmp( |
| 203 | 185 | const tree = scope.tree(); |
| 204 | 186 | const src = tree.token_locs[infix_node.op_token].start; |
| 205 | 187 | |
| 206 | return mod.addZIRInst(scope, src, zir.Inst.Cmp, .{ | |
| 207 | .lhs = lhs, | |
| 208 | .op = op, | |
| 209 | .rhs = rhs, | |
| 210 | }, .{}); | |
| 188 | return mod.addZIRBinOp(scope, src, op_inst_tag, lhs, rhs); | |
| 211 | 189 | } |
| 212 | 190 | |
| 213 | 191 | fn ifExpr(mod: *Module, scope: *Scope, if_node: *ast.Node.If) InnerError!*zir.Inst { |
| ... | ... | @@ -306,9 +284,9 @@ fn controlFlowExpr( |
| 306 | 284 | const src = tree.token_locs[cfe.ltoken].start; |
| 307 | 285 | if (cfe.rhs) |rhs_node| { |
| 308 | 286 | const operand = try expr(mod, scope, rhs_node); |
| 309 | return mod.addZIRInst(scope, src, zir.Inst.Return, .{ .operand = operand }, .{}); | |
| 287 | return mod.addZIRUnOp(scope, src, .@"return", operand); | |
| 310 | 288 | } else { |
| 311 | return mod.addZIRInst(scope, src, zir.Inst.ReturnVoid, .{}, .{}); | |
| 289 | return mod.addZIRNoOp(scope, src, .returnvoid); | |
| 312 | 290 | } |
| 313 | 291 | } |
| 314 | 292 | |
| ... | ... | @@ -519,7 +497,7 @@ fn callExpr(mod: *Module, scope: *Scope, node: *ast.Node.Call) InnerError!*zir.I |
| 519 | 497 | fn unreach(mod: *Module, scope: *Scope, unreach_node: *ast.Node.Unreachable) InnerError!*zir.Inst { |
| 520 | 498 | const tree = scope.tree(); |
| 521 | 499 | const src = tree.token_locs[unreach_node.token].start; |
| 522 | return mod.addZIRInst(scope, src, zir.Inst.Unreachable, .{}, .{}); | |
| 500 | return mod.addZIRNoOp(scope, src, .@"unreachable"); | |
| 523 | 501 | } |
| 524 | 502 | |
| 525 | 503 | fn getSimplePrimitiveValue(name: []const u8) ?TypedValue { |
src-self-hosted/zir.zig+137-214| ... | ... | @@ -79,11 +79,69 @@ pub const Inst = struct { |
| 79 | 79 | elemptr, |
| 80 | 80 | add, |
| 81 | 81 | sub, |
| 82 | cmp, | |
| 82 | cmp_lt, | |
| 83 | cmp_lte, | |
| 84 | cmp_eq, | |
| 85 | cmp_gte, | |
| 86 | cmp_gt, | |
| 87 | cmp_neq, | |
| 83 | 88 | condbr, |
| 84 | 89 | isnull, |
| 85 | 90 | isnonnull, |
| 86 | 91 | |
| 92 | pub fn Type(tag: Tag) type { | |
| 93 | return switch (tag) { | |
| 94 | .arg, | |
| 95 | .breakpoint, | |
| 96 | .@"unreachable", | |
| 97 | .returnvoid, | |
| 98 | => NoOp, | |
| 99 | ||
| 100 | .boolnot, | |
| 101 | .deref, | |
| 102 | .@"return", | |
| 103 | .isnull, | |
| 104 | .isnonnull, | |
| 105 | => UnOp, | |
| 106 | ||
| 107 | .add, | |
| 108 | .sub, | |
| 109 | .cmp_lt, | |
| 110 | .cmp_lte, | |
| 111 | .cmp_eq, | |
| 112 | .cmp_gte, | |
| 113 | .cmp_gt, | |
| 114 | .cmp_neq, | |
| 115 | => BinOp, | |
| 116 | ||
| 117 | .block => Block, | |
| 118 | .@"break" => Break, | |
| 119 | .breakvoid => BreakVoid, | |
| 120 | .call => Call, | |
| 121 | .declref => DeclRef, | |
| 122 | .declref_str => DeclRefStr, | |
| 123 | .declval => DeclVal, | |
| 124 | .declval_in_module => DeclValInModule, | |
| 125 | .compileerror => CompileError, | |
| 126 | .@"const" => Const, | |
| 127 | .str => Str, | |
| 128 | .int => Int, | |
| 129 | .inttype => IntType, | |
| 130 | .ptrtoint => PtrToInt, | |
| 131 | .fieldptr => FieldPtr, | |
| 132 | .as => As, | |
| 133 | .@"asm" => Asm, | |
| 134 | .@"fn" => Fn, | |
| 135 | .@"export" => Export, | |
| 136 | .primitive => Primitive, | |
| 137 | .fntype => FnType, | |
| 138 | .intcast => IntCast, | |
| 139 | .bitcast => BitCast, | |
| 140 | .elemptr => ElemPtr, | |
| 141 | .condbr => CondBr, | |
| 142 | }; | |
| 143 | } | |
| 144 | ||
| 87 | 145 | /// Returns whether the instruction is one of the control flow "noreturn" types. |
| 88 | 146 | /// Function calls do not count. |
| 89 | 147 | pub fn isNoReturn(tag: Tag) bool { |
| ... | ... | @@ -114,7 +172,12 @@ pub const Inst = struct { |
| 114 | 172 | .elemptr, |
| 115 | 173 | .add, |
| 116 | 174 | .sub, |
| 117 | .cmp, | |
| 175 | .cmp_lt, | |
| 176 | .cmp_lte, | |
| 177 | .cmp_eq, | |
| 178 | .cmp_gte, | |
| 179 | .cmp_gt, | |
| 180 | .cmp_neq, | |
| 118 | 181 | .isnull, |
| 119 | 182 | .isnonnull, |
| 120 | 183 | .boolnot, |
| ... | ... | @@ -132,63 +195,56 @@ pub const Inst = struct { |
| 132 | 195 | } |
| 133 | 196 | }; |
| 134 | 197 | |
| 135 | pub fn TagToType(tag: Tag) type { | |
| 136 | return switch (tag) { | |
| 137 | .arg => Arg, | |
| 138 | .block => Block, | |
| 139 | .@"break" => Break, | |
| 140 | .breakpoint => Breakpoint, | |
| 141 | .breakvoid => BreakVoid, | |
| 142 | .call => Call, | |
| 143 | .declref => DeclRef, | |
| 144 | .declref_str => DeclRefStr, | |
| 145 | .declval => DeclVal, | |
| 146 | .declval_in_module => DeclValInModule, | |
| 147 | .compileerror => CompileError, | |
| 148 | .@"const" => Const, | |
| 149 | .boolnot => BoolNot, | |
| 150 | .str => Str, | |
| 151 | .int => Int, | |
| 152 | .inttype => IntType, | |
| 153 | .ptrtoint => PtrToInt, | |
| 154 | .fieldptr => FieldPtr, | |
| 155 | .deref => Deref, | |
| 156 | .as => As, | |
| 157 | .@"asm" => Asm, | |
| 158 | .@"unreachable" => Unreachable, | |
| 159 | .@"return" => Return, | |
| 160 | .returnvoid => ReturnVoid, | |
| 161 | .@"fn" => Fn, | |
| 162 | .@"export" => Export, | |
| 163 | .primitive => Primitive, | |
| 164 | .fntype => FnType, | |
| 165 | .intcast => IntCast, | |
| 166 | .bitcast => BitCast, | |
| 167 | .elemptr => ElemPtr, | |
| 168 | .add => Add, | |
| 169 | .sub => Sub, | |
| 170 | .cmp => Cmp, | |
| 171 | .condbr => CondBr, | |
| 172 | .isnull => IsNull, | |
| 173 | .isnonnull => IsNonNull, | |
| 174 | }; | |
| 175 | } | |
| 176 | ||
| 198 | /// Prefer `castTag` to this. | |
| 177 | 199 | pub fn cast(base: *Inst, comptime T: type) ?*T { |
| 178 | if (base.tag != T.base_tag) | |
| 179 | return null; | |
| 200 | if (@hasField(T, "base_tag")) { | |
| 201 | return base.castTag(T.base_tag); | |
| 202 | } | |
| 203 | inline for (@typeInfo(Tag).Enum.fields) |field| { | |
| 204 | const tag = @intToEnum(Tag, field.value); | |
| 205 | if (base.tag == tag) { | |
| 206 | if (T == tag.Type()) { | |
| 207 | return @fieldParentPtr(T, "base", base); | |
| 208 | } | |
| 209 | return null; | |
| 210 | } | |
| 211 | } | |
| 212 | unreachable; | |
| 213 | } | |
| 180 | 214 | |
| 181 | return @fieldParentPtr(T, "base", base); | |
| 215 | pub fn castTag(base: *Inst, comptime tag: Tag) ?*tag.Type() { | |
| 216 | if (base.tag == tag) { | |
| 217 | return @fieldParentPtr(tag.Type(), "base", base); | |
| 218 | } | |
| 219 | return null; | |
| 182 | 220 | } |
| 183 | 221 | |
| 184 | pub const Arg = struct { | |
| 185 | pub const base_tag = Tag.arg; | |
| 222 | pub const NoOp = struct { | |
| 186 | 223 | base: Inst, |
| 187 | 224 | |
| 188 | 225 | positionals: struct {}, |
| 189 | 226 | kw_args: struct {}, |
| 190 | 227 | }; |
| 191 | 228 | |
| 229 | pub const UnOp = struct { | |
| 230 | base: Inst, | |
| 231 | ||
| 232 | positionals: struct { | |
| 233 | operand: *Inst, | |
| 234 | }, | |
| 235 | kw_args: struct {}, | |
| 236 | }; | |
| 237 | ||
| 238 | pub const BinOp = struct { | |
| 239 | base: Inst, | |
| 240 | ||
| 241 | positionals: struct { | |
| 242 | lhs: *Inst, | |
| 243 | rhs: *Inst, | |
| 244 | }, | |
| 245 | kw_args: struct {}, | |
| 246 | }; | |
| 247 | ||
| 192 | 248 | pub const Block = struct { |
| 193 | 249 | pub const base_tag = Tag.block; |
| 194 | 250 | base: Inst, |
| ... | ... | @@ -210,14 +266,6 @@ pub const Inst = struct { |
| 210 | 266 | kw_args: struct {}, |
| 211 | 267 | }; |
| 212 | 268 | |
| 213 | pub const Breakpoint = struct { | |
| 214 | pub const base_tag = Tag.breakpoint; | |
| 215 | base: Inst, | |
| 216 | ||
| 217 | positionals: struct {}, | |
| 218 | kw_args: struct {}, | |
| 219 | }; | |
| 220 | ||
| 221 | 269 | pub const BreakVoid = struct { |
| 222 | 270 | pub const base_tag = Tag.breakvoid; |
| 223 | 271 | base: Inst, |
| ... | ... | @@ -301,16 +349,6 @@ pub const Inst = struct { |
| 301 | 349 | kw_args: struct {}, |
| 302 | 350 | }; |
| 303 | 351 | |
| 304 | pub const BoolNot = struct { | |
| 305 | pub const base_tag = Tag.boolnot; | |
| 306 | base: Inst, | |
| 307 | ||
| 308 | positionals: struct { | |
| 309 | operand: *Inst, | |
| 310 | }, | |
| 311 | kw_args: struct {}, | |
| 312 | }; | |
| 313 | ||
| 314 | 352 | pub const Str = struct { |
| 315 | 353 | pub const base_tag = Tag.str; |
| 316 | 354 | base: Inst, |
| ... | ... | @@ -353,16 +391,6 @@ pub const Inst = struct { |
| 353 | 391 | kw_args: struct {}, |
| 354 | 392 | }; |
| 355 | 393 | |
| 356 | pub const Deref = struct { | |
| 357 | pub const base_tag = Tag.deref; | |
| 358 | base: Inst, | |
| 359 | ||
| 360 | positionals: struct { | |
| 361 | ptr: *Inst, | |
| 362 | }, | |
| 363 | kw_args: struct {}, | |
| 364 | }; | |
| 365 | ||
| 366 | 394 | pub const As = struct { |
| 367 | 395 | pub const base_tag = Tag.as; |
| 368 | 396 | pub const builtin_name = "@as"; |
| ... | ... | @@ -392,32 +420,6 @@ pub const Inst = struct { |
| 392 | 420 | }, |
| 393 | 421 | }; |
| 394 | 422 | |
| 395 | pub const Unreachable = struct { | |
| 396 | pub const base_tag = Tag.@"unreachable"; | |
| 397 | base: Inst, | |
| 398 | ||
| 399 | positionals: struct {}, | |
| 400 | kw_args: struct {}, | |
| 401 | }; | |
| 402 | ||
| 403 | pub const Return = struct { | |
| 404 | pub const base_tag = Tag.@"return"; | |
| 405 | base: Inst, | |
| 406 | ||
| 407 | positionals: struct { | |
| 408 | operand: *Inst, | |
| 409 | }, | |
| 410 | kw_args: struct {}, | |
| 411 | }; | |
| 412 | ||
| 413 | pub const ReturnVoid = struct { | |
| 414 | pub const base_tag = Tag.returnvoid; | |
| 415 | base: Inst, | |
| 416 | ||
| 417 | positionals: struct {}, | |
| 418 | kw_args: struct {}, | |
| 419 | }; | |
| 420 | ||
| 421 | 423 | pub const Fn = struct { |
| 422 | 424 | pub const base_tag = Tag.@"fn"; |
| 423 | 425 | base: Inst, |
| ... | ... | @@ -587,42 +589,6 @@ pub const Inst = struct { |
| 587 | 589 | kw_args: struct {}, |
| 588 | 590 | }; |
| 589 | 591 | |
| 590 | pub const Add = struct { | |
| 591 | pub const base_tag = Tag.add; | |
| 592 | base: Inst, | |
| 593 | ||
| 594 | positionals: struct { | |
| 595 | lhs: *Inst, | |
| 596 | rhs: *Inst, | |
| 597 | }, | |
| 598 | kw_args: struct {}, | |
| 599 | }; | |
| 600 | ||
| 601 | pub const Sub = struct { | |
| 602 | pub const base_tag = Tag.sub; | |
| 603 | base: Inst, | |
| 604 | ||
| 605 | positionals: struct { | |
| 606 | lhs: *Inst, | |
| 607 | rhs: *Inst, | |
| 608 | }, | |
| 609 | kw_args: struct {}, | |
| 610 | }; | |
| 611 | ||
| 612 | /// TODO get rid of the op positional arg and make that data part of | |
| 613 | /// the base Inst tag. | |
| 614 | pub const Cmp = struct { | |
| 615 | pub const base_tag = Tag.cmp; | |
| 616 | base: Inst, | |
| 617 | ||
| 618 | positionals: struct { | |
| 619 | lhs: *Inst, | |
| 620 | op: std.math.CompareOperator, | |
| 621 | rhs: *Inst, | |
| 622 | }, | |
| 623 | kw_args: struct {}, | |
| 624 | }; | |
| 625 | ||
| 626 | 592 | pub const CondBr = struct { |
| 627 | 593 | pub const base_tag = Tag.condbr; |
| 628 | 594 | base: Inst, |
| ... | ... | @@ -634,26 +600,6 @@ pub const Inst = struct { |
| 634 | 600 | }, |
| 635 | 601 | kw_args: struct {}, |
| 636 | 602 | }; |
| 637 | ||
| 638 | pub const IsNull = struct { | |
| 639 | pub const base_tag = Tag.isnull; | |
| 640 | base: Inst, | |
| 641 | ||
| 642 | positionals: struct { | |
| 643 | operand: *Inst, | |
| 644 | }, | |
| 645 | kw_args: struct {}, | |
| 646 | }; | |
| 647 | ||
| 648 | pub const IsNonNull = struct { | |
| 649 | pub const base_tag = Tag.isnonnull; | |
| 650 | base: Inst, | |
| 651 | ||
| 652 | positionals: struct { | |
| 653 | operand: *Inst, | |
| 654 | }, | |
| 655 | kw_args: struct {}, | |
| 656 | }; | |
| 657 | 603 | }; |
| 658 | 604 | |
| 659 | 605 | pub const ErrorMsg = struct { |
| ... | ... | @@ -775,7 +721,7 @@ const Writer = struct { |
| 775 | 721 | comptime inst_tag: Inst.Tag, |
| 776 | 722 | base: *Inst, |
| 777 | 723 | ) (@TypeOf(stream).Error || error{OutOfMemory})!void { |
| 778 | const SpecificInst = Inst.TagToType(inst_tag); | |
| 724 | const SpecificInst = inst_tag.Type(); | |
| 779 | 725 | const inst = @fieldParentPtr(SpecificInst, "base", base); |
| 780 | 726 | const Positionals = @TypeOf(inst.positionals); |
| 781 | 727 | try stream.writeAll("= " ++ @tagName(inst_tag) ++ "("); |
| ... | ... | @@ -1102,7 +1048,7 @@ const Parser = struct { |
| 1102 | 1048 | inline for (@typeInfo(Inst.Tag).Enum.fields) |field| { |
| 1103 | 1049 | if (mem.eql(u8, field.name, fn_name)) { |
| 1104 | 1050 | const tag = @field(Inst.Tag, field.name); |
| 1105 | return parseInstructionGeneric(self, field.name, Inst.TagToType(tag), body_ctx, name, contents_start); | |
| 1051 | return parseInstructionGeneric(self, field.name, tag.Type(), tag, body_ctx, name, contents_start); | |
| 1106 | 1052 | } |
| 1107 | 1053 | } |
| 1108 | 1054 | return self.fail("unknown instruction '{}'", .{fn_name}); |
| ... | ... | @@ -1112,6 +1058,7 @@ const Parser = struct { |
| 1112 | 1058 | self: *Parser, |
| 1113 | 1059 | comptime fn_name: []const u8, |
| 1114 | 1060 | comptime InstType: type, |
| 1061 | tag: Inst.Tag, | |
| 1115 | 1062 | body_ctx: ?*Body, |
| 1116 | 1063 | inst_name: []const u8, |
| 1117 | 1064 | contents_start: usize, |
| ... | ... | @@ -1119,7 +1066,7 @@ const Parser = struct { |
| 1119 | 1066 | const inst_specific = try self.arena.allocator.create(InstType); |
| 1120 | 1067 | inst_specific.base = .{ |
| 1121 | 1068 | .src = self.i, |
| 1122 | .tag = InstType.base_tag, | |
| 1069 | .tag = tag, | |
| 1123 | 1070 | }; |
| 1124 | 1071 | |
| 1125 | 1072 | if (InstType == Inst.Block) { |
| ... | ... | @@ -1615,12 +1562,12 @@ const EmitZIR = struct { |
| 1615 | 1562 | } |
| 1616 | 1563 | } |
| 1617 | 1564 | |
| 1618 | fn emitNoOp(self: *EmitZIR, src: usize, comptime T: type) Allocator.Error!*Inst { | |
| 1619 | const new_inst = try self.arena.allocator.create(T); | |
| 1565 | fn emitNoOp(self: *EmitZIR, src: usize, tag: Inst.Tag) Allocator.Error!*Inst { | |
| 1566 | const new_inst = try self.arena.allocator.create(Inst.NoOp); | |
| 1620 | 1567 | new_inst.* = .{ |
| 1621 | 1568 | .base = .{ |
| 1622 | 1569 | .src = src, |
| 1623 | .tag = T.base_tag, | |
| 1570 | .tag = tag, | |
| 1624 | 1571 | }, |
| 1625 | 1572 | .positionals = .{}, |
| 1626 | 1573 | .kw_args = .{}, |
| ... | ... | @@ -1628,41 +1575,18 @@ const EmitZIR = struct { |
| 1628 | 1575 | return &new_inst.base; |
| 1629 | 1576 | } |
| 1630 | 1577 | |
| 1631 | fn emitCmp( | |
| 1632 | self: *EmitZIR, | |
| 1633 | src: usize, | |
| 1634 | new_body: ZirBody, | |
| 1635 | old_inst: *ir.Inst.BinOp, | |
| 1636 | op: std.math.CompareOperator, | |
| 1637 | ) Allocator.Error!*Inst { | |
| 1638 | const new_inst = try self.arena.allocator.create(Inst.Cmp); | |
| 1639 | new_inst.* = .{ | |
| 1640 | .base = .{ | |
| 1641 | .src = src, | |
| 1642 | .tag = Inst.Cmp.base_tag, | |
| 1643 | }, | |
| 1644 | .positionals = .{ | |
| 1645 | .lhs = try self.resolveInst(new_body, old_inst.lhs), | |
| 1646 | .rhs = try self.resolveInst(new_body, old_inst.rhs), | |
| 1647 | .op = op, | |
| 1648 | }, | |
| 1649 | .kw_args = .{}, | |
| 1650 | }; | |
| 1651 | return &new_inst.base; | |
| 1652 | } | |
| 1653 | ||
| 1654 | 1578 | fn emitUnOp( |
| 1655 | 1579 | self: *EmitZIR, |
| 1656 | 1580 | src: usize, |
| 1657 | 1581 | new_body: ZirBody, |
| 1658 | 1582 | old_inst: *ir.Inst.UnOp, |
| 1659 | comptime I: type, | |
| 1583 | tag: Inst.Tag, | |
| 1660 | 1584 | ) Allocator.Error!*Inst { |
| 1661 | const new_inst = try self.arena.allocator.create(I); | |
| 1585 | const new_inst = try self.arena.allocator.create(Inst.UnOp); | |
| 1662 | 1586 | new_inst.* = .{ |
| 1663 | 1587 | .base = .{ |
| 1664 | 1588 | .src = src, |
| 1665 | .tag = I.base_tag, | |
| 1589 | .tag = tag, | |
| 1666 | 1590 | }, |
| 1667 | 1591 | .positionals = .{ |
| 1668 | 1592 | .operand = try self.resolveInst(new_body, old_inst.operand), |
| ... | ... | @@ -1677,13 +1601,13 @@ const EmitZIR = struct { |
| 1677 | 1601 | src: usize, |
| 1678 | 1602 | new_body: ZirBody, |
| 1679 | 1603 | old_inst: *ir.Inst.BinOp, |
| 1680 | comptime I: type, | |
| 1604 | tag: Inst.Tag, | |
| 1681 | 1605 | ) Allocator.Error!*Inst { |
| 1682 | const new_inst = try self.arena.allocator.create(I); | |
| 1606 | const new_inst = try self.arena.allocator.create(Inst.BinOp); | |
| 1683 | 1607 | new_inst.* = .{ |
| 1684 | 1608 | .base = .{ |
| 1685 | 1609 | .src = src, |
| 1686 | .tag = I.base_tag, | |
| 1610 | .tag = tag, | |
| 1687 | 1611 | }, |
| 1688 | 1612 | .positionals = .{ |
| 1689 | 1613 | .lhs = try self.resolveInst(new_body, old_inst.lhs), |
| ... | ... | @@ -1708,26 +1632,25 @@ const EmitZIR = struct { |
| 1708 | 1632 | const new_inst = switch (inst.tag) { |
| 1709 | 1633 | .constant => unreachable, // excluded from function bodies |
| 1710 | 1634 | |
| 1711 | .arg => try self.emitNoOp(inst.src, Inst.Arg), | |
| 1712 | .breakpoint => try self.emitNoOp(inst.src, Inst.Breakpoint), | |
| 1713 | .unreach => try self.emitNoOp(inst.src, Inst.Unreachable), | |
| 1714 | .retvoid => try self.emitNoOp(inst.src, Inst.ReturnVoid), | |
| 1715 | ||
| 1716 | .not => try self.emitUnOp(inst.src, new_body, inst.castTag(.not).?, Inst.BoolNot), | |
| 1717 | .ret => try self.emitUnOp(inst.src, new_body, inst.castTag(.ret).?, Inst.Return), | |
| 1718 | .ptrtoint => try self.emitUnOp(inst.src, new_body, inst.castTag(.ptrtoint).?, Inst.PtrToInt), | |
| 1719 | .isnull => try self.emitUnOp(inst.src, new_body, inst.castTag(.isnull).?, Inst.IsNull), | |
| 1720 | .isnonnull => try self.emitUnOp(inst.src, new_body, inst.castTag(.isnonnull).?, Inst.IsNonNull), | |
| 1721 | ||
| 1722 | .add => try self.emitBinOp(inst.src, new_body, inst.castTag(.add).?, Inst.Add), | |
| 1723 | .sub => try self.emitBinOp(inst.src, new_body, inst.castTag(.sub).?, Inst.Sub), | |
| 1724 | ||
| 1725 | .cmp_lt => try self.emitCmp(inst.src, new_body, inst.castTag(.cmp_lt).?, .lt), | |
| 1726 | .cmp_lte => try self.emitCmp(inst.src, new_body, inst.castTag(.cmp_lte).?, .lte), | |
| 1727 | .cmp_eq => try self.emitCmp(inst.src, new_body, inst.castTag(.cmp_eq).?, .eq), | |
| 1728 | .cmp_gte => try self.emitCmp(inst.src, new_body, inst.castTag(.cmp_gte).?, .gte), | |
| 1729 | .cmp_gt => try self.emitCmp(inst.src, new_body, inst.castTag(.cmp_gt).?, .gt), | |
| 1730 | .cmp_neq => try self.emitCmp(inst.src, new_body, inst.castTag(.cmp_neq).?, .neq), | |
| 1635 | .arg => try self.emitNoOp(inst.src, .arg), | |
| 1636 | .breakpoint => try self.emitNoOp(inst.src, .breakpoint), | |
| 1637 | .unreach => try self.emitNoOp(inst.src, .@"unreachable"), | |
| 1638 | .retvoid => try self.emitNoOp(inst.src, .returnvoid), | |
| 1639 | ||
| 1640 | .not => try self.emitUnOp(inst.src, new_body, inst.castTag(.not).?, .boolnot), | |
| 1641 | .ret => try self.emitUnOp(inst.src, new_body, inst.castTag(.ret).?, .@"return"), | |
| 1642 | .ptrtoint => try self.emitUnOp(inst.src, new_body, inst.castTag(.ptrtoint).?, .ptrtoint), | |
| 1643 | .isnull => try self.emitUnOp(inst.src, new_body, inst.castTag(.isnull).?, .isnull), | |
| 1644 | .isnonnull => try self.emitUnOp(inst.src, new_body, inst.castTag(.isnonnull).?, .isnonnull), | |
| 1645 | ||
| 1646 | .add => try self.emitBinOp(inst.src, new_body, inst.castTag(.add).?, .add), | |
| 1647 | .sub => try self.emitBinOp(inst.src, new_body, inst.castTag(.sub).?, .sub), | |
| 1648 | .cmp_lt => try self.emitBinOp(inst.src, new_body, inst.castTag(.cmp_lt).?, .cmp_lt), | |
| 1649 | .cmp_lte => try self.emitBinOp(inst.src, new_body, inst.castTag(.cmp_lte).?, .cmp_lte), | |
| 1650 | .cmp_eq => try self.emitBinOp(inst.src, new_body, inst.castTag(.cmp_eq).?, .cmp_eq), | |
| 1651 | .cmp_gte => try self.emitBinOp(inst.src, new_body, inst.castTag(.cmp_gte).?, .cmp_gte), | |
| 1652 | .cmp_gt => try self.emitBinOp(inst.src, new_body, inst.castTag(.cmp_gt).?, .cmp_gt), | |
| 1653 | .cmp_neq => try self.emitBinOp(inst.src, new_body, inst.castTag(.cmp_neq).?, .cmp_neq), | |
| 1731 | 1654 | |
| 1732 | 1655 | .bitcast => blk: { |
| 1733 | 1656 | const old_inst = inst.castTag(.bitcast).?; |
test/stage2/zir.zig+1-1| ... | ... | @@ -56,7 +56,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 56 | 56 | \\ %result = add(%x0, %x1) |
| 57 | 57 | \\ |
| 58 | 58 | \\ %expected = int(69) |
| 59 | \\ %ok = cmp(%result, eq, %expected) | |
| 59 | \\ %ok = cmp_eq(%result, %expected) | |
| 60 | 60 | \\ %10 = condbr(%ok, { |
| 61 | 61 | \\ %11 = returnvoid() |
| 62 | 62 | \\ }, { |