diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2020-04-21 22:19:32 -0400 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2020-04-21 22:19:32 -0400 |
| commit | 2e6ccec1007199d651bf89216c4af53f80c5c15a (patch) | |
| tree | 6ed2d2f29ef26b07f974c944b3b0665b20368d60 | |
| parent | 8d3e4147d591342d6ec4ce54c5e14da98c1a692a (diff) | |
| download | zig-2e6ccec1007199d651bf89216c4af53f80c5c15a.tar.gz zig-2e6ccec1007199d651bf89216c4af53f80c5c15a.zip | |
ir: analyze asm instruction
| -rw-r--r-- | src-self-hosted/ir.zig | 63 | ||||
| -rw-r--r-- | src-self-hosted/ir/text.zig | 4 | ||||
| -rw-r--r-- | src-self-hosted/value.zig | 2 |
3 files changed, 61 insertions, 8 deletions
diff --git a/src-self-hosted/ir.zig b/src-self-hosted/ir.zig index ec08dcf6a5..103ea88d77 100644 --- a/src-self-hosted/ir.zig +++ b/src-self-hosted/ir.zig @@ -49,6 +49,12 @@ pub const Inst = struct { }; } + pub const Unreach = struct { + pub const base_tag = Tag.unreach; + base: Inst, + args: void, + }; + pub const Constant = struct { pub const base_tag = Tag.constant; base: Inst, @@ -63,7 +69,7 @@ pub const Inst = struct { args: struct { asm_source: []const u8, is_volatile: bool, - output: []const u8, + output: ?[]const u8, inputs: []const []const u8, clobbers: []const []const u8, args: []const *Inst, @@ -260,6 +266,7 @@ const Analyze = struct { }); } + /// TODO should not need the cast on the last parameter at the callsites fn addNewInstArgs( self: *Analyze, func: *Fn, @@ -318,11 +325,18 @@ const Analyze = struct { fn constType(self: *Analyze, src: usize, ty: Type) !*Inst { return self.constInst(src, .{ - .ty = Type.initTag(.@"type"), + .ty = Type.initTag(.type), .val = try ty.toValue(&self.arena.allocator), }); } + fn constVoid(self: *Analyze, src: usize) !*Inst { + return self.constInst(src, .{ + .ty = Type.initTag(.void), + .val = Value.initTag(.void_value), + }); + } + fn constIntUnsigned(self: *Analyze, src: usize, ty: Type, int: u64) !*Inst { const int_payload = try self.arena.allocator.create(Value.Payload.Int_u64); int_payload.* = .{ .int = int }; @@ -385,10 +399,13 @@ const Analyze = struct { .fieldptr => return self.analyzeInstFieldPtr(func, old_inst.cast(text.Inst.FieldPtr).?), .deref => return self.analyzeInstDeref(func, old_inst.cast(text.Inst.Deref).?), .as => return self.analyzeInstAs(func, old_inst.cast(text.Inst.As).?), - .@"asm" => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}), - .@"unreachable" => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}), + .@"asm" => return self.analyzeInstAsm(func, old_inst.cast(text.Inst.Asm).?), + .@"unreachable" => return self.analyzeInstUnreachable(func, old_inst.cast(text.Inst.Unreachable).?), .@"fn" => return self.analyzeInstFn(func, old_inst.cast(text.Inst.Fn).?), - .@"export" => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}), + .@"export" => { + try self.analyzeExport(func, old_inst.cast(text.Inst.Export).?); + return self.constVoid(old_inst.src); + }, .primitive => return self.analyzeInstPrimitive(func, old_inst.cast(text.Inst.Primitive).?), .fntype => return self.analyzeInstFnType(func, old_inst.cast(text.Inst.FnType).?), .intcast => return self.analyzeInstIntCast(func, old_inst.cast(text.Inst.IntCast).?), @@ -466,7 +483,6 @@ const Analyze = struct { // TODO handle known-pointer-address const f = try self.requireFunctionBody(func, ptrtoint.base.src); const ty = Type.initTag(.usize); - // TODO should not need the cast on the last parameter return self.addNewInstArgs(f, ptrtoint.base.src, ty, Inst.PtrToInt, Inst.Args(Inst.PtrToInt){ .ptr = ptr }); } @@ -551,6 +567,41 @@ const Analyze = struct { return self.fail(deref.base.src, "TODO implement runtime deref", .{}); } + fn analyzeInstAsm(self: *Analyze, func: ?*Fn, assembly: *text.Inst.Asm) InnerError!*Inst { + const return_type = try self.resolveType(func, assembly.positionals.return_type); + const asm_source = try self.resolveConstString(func, assembly.positionals.asm_source); + const output = if (assembly.kw_args.output) |o| try self.resolveConstString(func, o) else null; + + const inputs = try self.arena.allocator.alloc([]const u8, assembly.kw_args.inputs.len); + const clobbers = try self.arena.allocator.alloc([]const u8, assembly.kw_args.clobbers.len); + const args = try self.arena.allocator.alloc(*Inst, assembly.kw_args.args.len); + + for (inputs) |*elem, i| { + elem.* = try self.resolveConstString(func, assembly.kw_args.inputs[i]); + } + for (clobbers) |*elem, i| { + elem.* = try self.resolveConstString(func, assembly.kw_args.clobbers[i]); + } + for (args) |*elem, i| { + elem.* = try self.resolveInst(func, assembly.kw_args.args[i]); + } + + const f = try self.requireFunctionBody(func, assembly.base.src); + return self.addNewInstArgs(f, assembly.base.src, return_type, Inst.Assembly, Inst.Args(Inst.Assembly){ + .asm_source = asm_source, + .is_volatile = assembly.kw_args.@"volatile", + .output = output, + .inputs = inputs, + .clobbers = clobbers, + .args = args, + }); + } + + fn analyzeInstUnreachable(self: *Analyze, func: ?*Fn, unreach: *text.Inst.Unreachable) InnerError!*Inst { + const f = try self.requireFunctionBody(func, unreach.base.src); + return self.addNewInstArgs(f, unreach.base.src, Type.initTag(.noreturn), Inst.Unreach, {}); + } + fn coerce(self: *Analyze, dest_type: Type, inst: *Inst) !*Inst { const in_memory_result = coerceInMemoryAllowed(dest_type, inst.ty); if (in_memory_result == .ok) { diff --git a/src-self-hosted/ir/text.zig b/src-self-hosted/ir/text.zig index 5a2181f882..909bc7aaa4 100644 --- a/src-self-hosted/ir/text.zig +++ b/src-self-hosted/ir/text.zig @@ -39,7 +39,7 @@ pub const Inst = struct { .fieldptr => FieldPtr, .deref => Deref, .as => As, - .@"asm" => Assembly, + .@"asm" => Asm, .@"unreachable" => Unreachable, .@"fn" => Fn, .@"export" => Export, @@ -118,7 +118,7 @@ pub const Inst = struct { kw_args: struct {}, }; - pub const Assembly = struct { + pub const Asm = struct { pub const base_tag = Tag.@"asm"; base: Inst, diff --git a/src-self-hosted/value.zig b/src-self-hosted/value.zig index 44c44df2d4..ea6e0fede2 100644 --- a/src-self-hosted/value.zig +++ b/src-self-hosted/value.zig @@ -255,6 +255,7 @@ pub const Value = extern union { .int_u64 => switch (ty.zigTypeTag()) { .Int => { const x = self.cast(Payload.Int_u64).?.int; + if (x == 0) return true; const info = ty.intInfo(target); const needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signed); return info.bits >= needed_bits; @@ -265,6 +266,7 @@ pub const Value = extern union { .int_i64 => switch (ty.zigTypeTag()) { .Int => { const x = self.cast(Payload.Int_i64).?.int; + if (x == 0) return true; const info = ty.intInfo(target); if (!info.signed and x < 0) return false; |
