authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-04-21 17:33:41-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-04-21 17:33:41-04:00
log69878207e7b49efca2cf9d7eaef6a345b741946f
tree20fae048acfbe9e915e489ea49ade6583992cba9
parent25679b63eb01b7f4b1fb031afb9e355b90b2ea86

ir: analyze `as` instruction


1 files changed, 24 insertions(+), 9 deletions(-)

src-self-hosted/ir.zig+24-9
...@@ -141,7 +141,8 @@ const Analyze = struct {...@@ -141,7 +141,8 @@ const Analyze = struct {
141 };141 };
142142
143 const NewInst = struct {143 const NewInst = struct {
144 ptr: *Inst,144 /// null means a semantic analysis error happened
145 ptr: ?*Inst,
145 };146 };
146147
147 const Fn = struct {148 const Fn = struct {
...@@ -163,9 +164,12 @@ const Analyze = struct {...@@ -163,9 +164,12 @@ const Analyze = struct {
163164
164 fn resolveInst(self: *Analyze, opt_func: ?*Fn, old_inst: *text.Inst) InnerError!*Inst {165 fn resolveInst(self: *Analyze, opt_func: ?*Fn, old_inst: *text.Inst) InnerError!*Inst {
165 if (opt_func) |func| {166 if (opt_func) |func| {
166 const kv = func.inst_table.get(old_inst) orelse return error.AnalysisFail;167 if (func.inst_table.get(old_inst)) |kv| {
167 return kv.value.ptr;168 return kv.value.ptr orelse return error.AnalysisFail;
168 } else if (self.decl_table.get(old_inst)) |kv| {169 }
170 }
171
172 if (self.decl_table.get(old_inst)) |kv| {
169 return kv.value.ptr orelse return error.AnalysisFail;173 return kv.value.ptr orelse return error.AnalysisFail;
170 } else {174 } else {
171 const new_inst = self.analyzeInst(null, old_inst) catch |err| switch (err) {175 const new_inst = self.analyzeInst(null, old_inst) catch |err| switch (err) {
...@@ -275,7 +279,7 @@ const Analyze = struct {...@@ -275,7 +279,7 @@ const Analyze = struct {
275 .ptrtoint => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}),279 .ptrtoint => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}),
276 .fieldptr => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}),280 .fieldptr => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}),
277 .deref => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}),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 .@"asm" => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}),283 .@"asm" => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}),
280 .@"unreachable" => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}),284 .@"unreachable" => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}),
281 .@"fn" => return self.analyzeInstFn(func, old_inst.cast(text.Inst.Fn).?),285 .@"fn" => return self.analyzeInstFn(func, old_inst.cast(text.Inst.Fn).?),
...@@ -305,6 +309,7 @@ const Analyze = struct {...@@ -305,6 +309,7 @@ const Analyze = struct {
305 for (fn_inst.positionals.body.instructions) |src_inst| {309 for (fn_inst.positionals.body.instructions) |src_inst| {
306 const new_inst = self.analyzeInst(&new_func, src_inst) catch |err| {310 const new_inst = self.analyzeInst(&new_func, src_inst) catch |err| {
307 self.fns.items[new_func.fn_index].analysis_status = .failure;311 self.fns.items[new_func.fn_index].analysis_status = .failure;
312 try new_func.inst_table.putNoClobber(src_inst, .{ .ptr = null });
308 return err;313 return err;
309 };314 };
310 try new_func.inst_table.putNoClobber(src_inst, .{ .ptr = new_inst });315 try new_func.inst_table.putNoClobber(src_inst, .{ .ptr = new_inst });
...@@ -324,8 +329,8 @@ const Analyze = struct {...@@ -324,8 +329,8 @@ const Analyze = struct {
324 });329 });
325 }330 }
326331
327 fn analyzeInstFnType(self: *Analyze, opt_func: ?*Fn, fntype: *text.Inst.FnType) InnerError!*Inst {332 fn analyzeInstFnType(self: *Analyze, func: ?*Fn, fntype: *text.Inst.FnType) InnerError!*Inst {
328 const return_type = try self.resolveType(opt_func, fntype.positionals.return_type);333 const return_type = try self.resolveType(func, fntype.positionals.return_type);
329334
330 if (return_type.zigTypeTag() == .NoReturn and335 if (return_type.zigTypeTag() == .NoReturn and
331 fntype.positionals.param_types.len == 0 and336 fntype.positionals.param_types.len == 0 and
...@@ -337,10 +342,16 @@ const Analyze = struct {...@@ -337,10 +342,16 @@ const Analyze = struct {
337 return self.fail(fntype.base.src, "TODO implement fntype instruction more", .{});342 return self.fail(fntype.base.src, "TODO implement fntype instruction more", .{});
338 }343 }
339344
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 return self.constType(primitive.base.src, primitive.positionals.tag.toType());346 return self.constType(primitive.base.src, primitive.positionals.tag.toType());
342 }347 }
343348
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 fn coerce(self: *Analyze, dest_type: Type, inst: *Inst) !*Inst {355 fn coerce(self: *Analyze, dest_type: Type, inst: *Inst) !*Inst {
345 const in_memory_result = coerceInMemoryAllowed(dest_type, inst.ty);356 const in_memory_result = coerceInMemoryAllowed(dest_type, inst.ty);
346 if (in_memory_result == .ok) {357 if (in_memory_result == .ok) {
...@@ -363,7 +374,11 @@ const Analyze = struct {...@@ -363,7 +374,11 @@ const Analyze = struct {
363 }374 }
364375
365 fn bitcast(self: *Analyze, dest_type: Type, inst: *Inst) !*Inst {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 }
368383
369 fn coerceArrayPtrToSlice(self: *Analyze, dest_type: Type, inst: *Inst) !*Inst {384 fn coerceArrayPtrToSlice(self: *Analyze, dest_type: Type, inst: *Inst) !*Inst {