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 {...@@ -23,6 +23,7 @@ pub const Inst = struct {
23 unreach,23 unreach,
24 constant,24 constant,
25 assembly,25 assembly,
26 ptrtoint,
26 };27 };
2728
28 pub fn cast(base: *Inst, comptime T: type) ?*T {29 pub fn cast(base: *Inst, comptime T: type) ?*T {
...@@ -32,12 +33,19 @@ pub const Inst = struct {...@@ -32,12 +33,19 @@ pub const Inst = struct {
32 return @fieldParentPtr(T, "base", base);33 return @fieldParentPtr(T, "base", base);
33 }34 }
3435
36 pub fn Args(comptime T: type) type {
37 return std.meta.fieldInfo(T, "args").field_type;
38 }
39
35 /// Returns `null` if runtime-known.40 /// Returns `null` if runtime-known.
36 pub fn value(base: *Inst) ?Value {41 pub fn value(base: *Inst) ?Value {
37 return switch (base.tag) {42 return switch (base.tag) {
38 .unreach => Value.initTag(.noreturn_value),43 .unreach => Value.initTag(.noreturn_value),
39 .constant => base.cast(Constant).?.val,44 .constant => base.cast(Constant).?.val,
40 .assembly => null,45
46 .assembly,
47 .ptrtoint,
48 => null,
41 };49 };
42 }50 }
4351
...@@ -52,12 +60,23 @@ pub const Inst = struct {...@@ -52,12 +60,23 @@ pub const Inst = struct {
52 pub const base_tag = Tag.assembly;60 pub const base_tag = Tag.assembly;
53 base: Inst,61 base: Inst,
5462
55 asm_source: []const u8,63 args: struct {
56 is_volatile: bool,64 asm_source: []const u8,
57 output: []const u8,65 is_volatile: bool,
58 inputs: []const []const u8,66 output: []const u8,
59 clobbers: []const []const u8,67 inputs: []const []const u8,
60 args: []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 },
61 };80 };
62};81};
6382
...@@ -190,6 +209,10 @@ const Analyze = struct {...@@ -190,6 +209,10 @@ const Analyze = struct {
190 }209 }
191 }210 }
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
193 fn resolveInstConst(self: *Analyze, func: ?*Fn, old_inst: *text.Inst) InnerError!TypedValue {216 fn resolveInstConst(self: *Analyze, func: ?*Fn, old_inst: *text.Inst) InnerError!TypedValue {
194 const new_inst = try self.resolveInst(func, old_inst);217 const new_inst = try self.resolveInst(func, old_inst);
195 const val = try self.resolveConstValue(new_inst);218 const val = try self.resolveConstValue(new_inst);
...@@ -237,6 +260,33 @@ const Analyze = struct {...@@ -237,6 +260,33 @@ const Analyze = struct {
237 });260 });
238 }261 }
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
240 fn constInst(self: *Analyze, src: usize, typed_value: TypedValue) !*Inst {290 fn constInst(self: *Analyze, src: usize, typed_value: TypedValue) !*Inst {
241 const const_inst = try self.arena.allocator.create(Inst.Constant);291 const const_inst = try self.arena.allocator.create(Inst.Constant);
242 const_inst.* = .{292 const_inst.* = .{
...@@ -331,7 +381,7 @@ const Analyze = struct {...@@ -331,7 +381,7 @@ const Analyze = struct {
331 const big_int = old_inst.cast(text.Inst.Int).?.positionals.int;381 const big_int = old_inst.cast(text.Inst.Int).?.positionals.int;
332 return self.constIntBig(old_inst.src, Type.initTag(.comptime_int), big_int);382 return self.constIntBig(old_inst.src, Type.initTag(.comptime_int), big_int);
333 },383 },
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).?),
335 .fieldptr => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}),385 .fieldptr => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}),
336 .deref => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}),386 .deref => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}),
337 .as => return self.analyzeInstAs(func, old_inst.cast(text.Inst.As).?),387 .as => return self.analyzeInstAs(func, old_inst.cast(text.Inst.As).?),
...@@ -408,6 +458,18 @@ const Analyze = struct {...@@ -408,6 +458,18 @@ const Analyze = struct {
408 return self.coerce(dest_type, new_inst);458 return self.coerce(dest_type, new_inst);
409 }459 }
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
411 fn analyzeInstIntCast(self: *Analyze, func: ?*Fn, intcast: *text.Inst.IntCast) InnerError!*Inst {473 fn analyzeInstIntCast(self: *Analyze, func: ?*Fn, intcast: *text.Inst.IntCast) InnerError!*Inst {
412 const dest_type = try self.resolveType(func, intcast.positionals.dest_type);474 const dest_type = try self.resolveType(func, intcast.positionals.dest_type);
413 const new_inst = try self.resolveInst(func, intcast.positionals.value);475 const new_inst = try self.resolveInst(func, intcast.positionals.value);