| ... | ... | @@ -141,7 +141,8 @@ const Analyze = struct { |
| 141 | 141 | }; |
| 142 | 142 | |
| 143 | 143 | const NewInst = struct { |
| 144 | | ptr: *Inst, |
| 144 | /// null means a semantic analysis error happened |
| 145 | ptr: ?*Inst, |
| 145 | 146 | }; |
| 146 | 147 | |
| 147 | 148 | const Fn = struct { |
| ... | ... | @@ -163,9 +164,12 @@ const Analyze = struct { |
| 163 | 164 | |
| 164 | 165 | fn resolveInst(self: *Analyze, opt_func: ?*Fn, old_inst: *text.Inst) InnerError!*Inst { |
| 165 | 166 | if (opt_func) |func| { |
| 166 | | const kv = func.inst_table.get(old_inst) orelse return error.AnalysisFail; |
| 167 | | return kv.value.ptr; |
| 168 | | } else if (self.decl_table.get(old_inst)) |kv| { |
| 167 | if (func.inst_table.get(old_inst)) |kv| { |
| 168 | return kv.value.ptr orelse return error.AnalysisFail; |
| 169 | } |
| 170 | } |
| 171 | |
| 172 | if (self.decl_table.get(old_inst)) |kv| { |
| 169 | 173 | return kv.value.ptr orelse return error.AnalysisFail; |
| 170 | 174 | } else { |
| 171 | 175 | const new_inst = self.analyzeInst(null, old_inst) catch |err| switch (err) { |
| ... | ... | @@ -275,7 +279,7 @@ const Analyze = struct { |
| 275 | 279 | .ptrtoint => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}), |
| 276 | 280 | .fieldptr => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}), |
| 277 | 281 | .deref => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}), |
| 278 | | .as => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}), |
| 282 | .as => return self.analyzeInstAs(func, old_inst.cast(text.Inst.As).?), |
| 279 | 283 | .@"asm" => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}), |
| 280 | 284 | .@"unreachable" => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}), |
| 281 | 285 | .@"fn" => return self.analyzeInstFn(func, old_inst.cast(text.Inst.Fn).?), |
| ... | ... | @@ -305,6 +309,7 @@ const Analyze = struct { |
| 305 | 309 | for (fn_inst.positionals.body.instructions) |src_inst| { |
| 306 | 310 | const new_inst = self.analyzeInst(&new_func, src_inst) catch |err| { |
| 307 | 311 | self.fns.items[new_func.fn_index].analysis_status = .failure; |
| 312 | try new_func.inst_table.putNoClobber(src_inst, .{ .ptr = null }); |
| 308 | 313 | return err; |
| 309 | 314 | }; |
| 310 | 315 | try new_func.inst_table.putNoClobber(src_inst, .{ .ptr = new_inst }); |
| ... | ... | @@ -324,8 +329,8 @@ const Analyze = struct { |
| 324 | 329 | }); |
| 325 | 330 | } |
| 326 | 331 | |
| 327 | | fn analyzeInstFnType(self: *Analyze, opt_func: ?*Fn, fntype: *text.Inst.FnType) InnerError!*Inst { |
| 328 | | const return_type = try self.resolveType(opt_func, fntype.positionals.return_type); |
| 332 | fn analyzeInstFnType(self: *Analyze, func: ?*Fn, fntype: *text.Inst.FnType) InnerError!*Inst { |
| 333 | const return_type = try self.resolveType(func, fntype.positionals.return_type); |
| 329 | 334 | |
| 330 | 335 | if (return_type.zigTypeTag() == .NoReturn and |
| 331 | 336 | fntype.positionals.param_types.len == 0 and |
| ... | ... | @@ -337,10 +342,16 @@ const Analyze = struct { |
| 337 | 342 | return self.fail(fntype.base.src, "TODO implement fntype instruction more", .{}); |
| 338 | 343 | } |
| 339 | 344 | |
| 340 | | fn analyzeInstPrimitive(self: *Analyze, opt_func: ?*Fn, primitive: *text.Inst.Primitive) InnerError!*Inst { |
| 345 | fn analyzeInstPrimitive(self: *Analyze, func: ?*Fn, primitive: *text.Inst.Primitive) InnerError!*Inst { |
| 341 | 346 | return self.constType(primitive.base.src, primitive.positionals.tag.toType()); |
| 342 | 347 | } |
| 343 | 348 | |
| 349 | fn analyzeInstAs(self: *Analyze, func: ?*Fn, as: *text.Inst.As) InnerError!*Inst { |
| 350 | const dest_type = try self.resolveType(func, as.positionals.dest_type); |
| 351 | const new_inst = try self.resolveInst(func, as.positionals.value); |
| 352 | return self.coerce(dest_type, new_inst); |
| 353 | } |
| 354 | |
| 344 | 355 | fn coerce(self: *Analyze, dest_type: Type, inst: *Inst) !*Inst { |
| 345 | 356 | const in_memory_result = coerceInMemoryAllowed(dest_type, inst.ty); |
| 346 | 357 | if (in_memory_result == .ok) { |
| ... | ... | @@ -363,7 +374,11 @@ const Analyze = struct { |
| 363 | 374 | } |
| 364 | 375 | |
| 365 | 376 | fn bitcast(self: *Analyze, dest_type: Type, inst: *Inst) !*Inst { |
| 366 | | return self.fail(inst.src, "TODO implement bitcast analysis", .{}); |
| 377 | if (inst.value()) |val| { |
| 378 | // Keep the comptime Value representation; take the new type. |
| 379 | return self.constInst(inst.src, .{ .ty = dest_type, .val = val }); |
| 380 | } |
| 381 | return self.fail(inst.src, "TODO implement runtime bitcast", .{}); |
| 367 | 382 | } |
| 368 | 383 | |
| 369 | 384 | fn coerceArrayPtrToSlice(self: *Analyze, dest_type: Type, inst: *Inst) !*Inst { |