authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-04-21 20:34:40-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-04-21 20:34:40-04:00
logc12bc8652ed45dd143932ef0d3a2540c0ef057a4
treef46df4ea526ea0c6bf4f864d2cfea23e2af459c4
parent2cdbb5f47260d2510ce478c77fa9c3c7c29fb671

ir: analyze ptrtoint


1 files changed, 70 insertions(+), 8 deletions(-)

src-self-hosted/ir.zig+70-8
......@@ -23,6 +23,7 @@ pub const Inst = struct {
2323 unreach,
2424 constant,
2525 assembly,
26 ptrtoint,
2627 };
2728
2829 pub fn cast(base: *Inst, comptime T: type) ?*T {
......@@ -32,12 +33,19 @@ pub const Inst = struct {
3233 return @fieldParentPtr(T, "base", base);
3334 }
3435
36 pub fn Args(comptime T: type) type {
37 return std.meta.fieldInfo(T, "args").field_type;
38 }
39
3540 /// Returns `null` if runtime-known.
3641 pub fn value(base: *Inst) ?Value {
3742 return switch (base.tag) {
3843 .unreach => Value.initTag(.noreturn_value),
3944 .constant => base.cast(Constant).?.val,
40 .assembly => null,
45
46 .assembly,
47 .ptrtoint,
48 => null,
4149 };
4250 }
4351
......@@ -52,12 +60,23 @@ pub const Inst = struct {
5260 pub const base_tag = Tag.assembly;
5361 base: Inst,
5462
55 asm_source: []const u8,
56 is_volatile: bool,
57 output: []const u8,
58 inputs: []const []const u8,
59 clobbers: []const []const u8,
60 args: []const []const u8,
63 args: struct {
64 asm_source: []const u8,
65 is_volatile: bool,
66 output: []const u8,
67 inputs: []const []const u8,
68 clobbers: []const []const u8,
69 args: []const *Inst,
70 },
71 };
72
73 pub const PtrToInt = struct {
74 pub const base_tag = Tag.ptrtoint;
75
76 base: Inst,
77 args: struct {
78 ptr: *Inst,
79 },
6180 };
6281};
6382
......@@ -190,6 +209,10 @@ const Analyze = struct {
190209 }
191210 }
192211
212 fn requireFunctionBody(self: *Analyze, func: ?*Fn, src: usize) !*Fn {
213 return func orelse return self.fail(src, "instruction illegal outside function body", .{});
214 }
215
193216 fn resolveInstConst(self: *Analyze, func: ?*Fn, old_inst: *text.Inst) InnerError!TypedValue {
194217 const new_inst = try self.resolveInst(func, old_inst);
195218 const val = try self.resolveConstValue(new_inst);
......@@ -237,6 +260,33 @@ const Analyze = struct {
237260 });
238261 }
239262
263 fn addNewInstArgs(
264 self: *Analyze,
265 func: *Fn,
266 src: usize,
267 ty: Type,
268 comptime T: type,
269 args: Inst.Args(T),
270 ) !*Inst {
271 const inst = try self.addNewInst(func, src, ty, T);
272 inst.args = args;
273 return &inst.base;
274 }
275
276 fn addNewInst(self: *Analyze, func: *Fn, src: usize, ty: Type, comptime T: type) !*T {
277 const inst = try self.arena.allocator.create(T);
278 inst.* = .{
279 .base = .{
280 .tag = T.base_tag,
281 .ty = ty,
282 .src = src,
283 },
284 .args = undefined,
285 };
286 try func.body.append(&inst.base);
287 return inst;
288 }
289
240290 fn constInst(self: *Analyze, src: usize, typed_value: TypedValue) !*Inst {
241291 const const_inst = try self.arena.allocator.create(Inst.Constant);
242292 const_inst.* = .{
......@@ -331,7 +381,7 @@ const Analyze = struct {
331381 const big_int = old_inst.cast(text.Inst.Int).?.positionals.int;
332382 return self.constIntBig(old_inst.src, Type.initTag(.comptime_int), big_int);
333383 },
334 .ptrtoint => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}),
384 .ptrtoint => return self.analyzeInstPtrToInt(func, old_inst.cast(text.Inst.PtrToInt).?),
335385 .fieldptr => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}),
336386 .deref => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}),
337387 .as => return self.analyzeInstAs(func, old_inst.cast(text.Inst.As).?),
......@@ -408,6 +458,18 @@ const Analyze = struct {
408458 return self.coerce(dest_type, new_inst);
409459 }
410460
461 fn analyzeInstPtrToInt(self: *Analyze, func: ?*Fn, ptrtoint: *text.Inst.PtrToInt) InnerError!*Inst {
462 const ptr = try self.resolveInst(func, ptrtoint.positionals.ptr);
463 if (ptr.ty.zigTypeTag() != .Pointer) {
464 return self.fail(ptrtoint.positionals.ptr.src, "expected pointer, found '{}'", .{ptr.ty});
465 }
466 // TODO handle known-pointer-address
467 const f = try self.requireFunctionBody(func, ptrtoint.base.src);
468 const ty = Type.initTag(.usize);
469 // TODO should not need the cast on the last parameter
470 return self.addNewInstArgs(f, ptrtoint.base.src, ty, Inst.PtrToInt, Inst.Args(Inst.PtrToInt){ .ptr = ptr });
471 }
472
411473 fn analyzeInstIntCast(self: *Analyze, func: ?*Fn, intcast: *text.Inst.IntCast) InnerError!*Inst {
412474 const dest_type = try self.resolveType(func, intcast.positionals.dest_type);
413475 const new_inst = try self.resolveInst(func, intcast.positionals.value);