| ... | ... | @@ -21,16 +21,17 @@ pub const Inst = struct { |
| 21 | 21 | src: usize, |
| 22 | 22 | |
| 23 | 23 | pub const Tag = enum { |
| 24 | | unreach, |
| 25 | | ret, |
| 26 | | constant, |
| 27 | 24 | assembly, |
| 28 | | ptrtoint, |
| 29 | 25 | bitcast, |
| 26 | breakpoint, |
| 30 | 27 | cmp, |
| 31 | 28 | condbr, |
| 32 | | isnull, |
| 29 | constant, |
| 33 | 30 | isnonnull, |
| 31 | isnull, |
| 32 | ptrtoint, |
| 33 | ret, |
| 34 | unreach, |
| 34 | 35 | }; |
| 35 | 36 | |
| 36 | 37 | pub fn cast(base: *Inst, comptime T: type) ?*T { |
| ... | ... | @@ -53,25 +54,6 @@ pub const Inst = struct { |
| 53 | 54 | return inst.val; |
| 54 | 55 | } |
| 55 | 56 | |
| 56 | | pub const Unreach = struct { |
| 57 | | pub const base_tag = Tag.unreach; |
| 58 | | base: Inst, |
| 59 | | args: void, |
| 60 | | }; |
| 61 | | |
| 62 | | pub const Ret = struct { |
| 63 | | pub const base_tag = Tag.ret; |
| 64 | | base: Inst, |
| 65 | | args: void, |
| 66 | | }; |
| 67 | | |
| 68 | | pub const Constant = struct { |
| 69 | | pub const base_tag = Tag.constant; |
| 70 | | base: Inst, |
| 71 | | |
| 72 | | val: Value, |
| 73 | | }; |
| 74 | | |
| 75 | 57 | pub const Assembly = struct { |
| 76 | 58 | pub const base_tag = Tag.assembly; |
| 77 | 59 | base: Inst, |
| ... | ... | @@ -86,15 +68,6 @@ pub const Inst = struct { |
| 86 | 68 | }, |
| 87 | 69 | }; |
| 88 | 70 | |
| 89 | | pub const PtrToInt = struct { |
| 90 | | pub const base_tag = Tag.ptrtoint; |
| 91 | | |
| 92 | | base: Inst, |
| 93 | | args: struct { |
| 94 | | ptr: *Inst, |
| 95 | | }, |
| 96 | | }; |
| 97 | | |
| 98 | 71 | pub const BitCast = struct { |
| 99 | 72 | pub const base_tag = Tag.bitcast; |
| 100 | 73 | |
| ... | ... | @@ -104,6 +77,12 @@ pub const Inst = struct { |
| 104 | 77 | }, |
| 105 | 78 | }; |
| 106 | 79 | |
| 80 | pub const Breakpoint = struct { |
| 81 | pub const base_tag = Tag.breakpoint; |
| 82 | base: Inst, |
| 83 | args: void, |
| 84 | }; |
| 85 | |
| 107 | 86 | pub const Cmp = struct { |
| 108 | 87 | pub const base_tag = Tag.cmp; |
| 109 | 88 | |
| ... | ... | @@ -126,6 +105,22 @@ pub const Inst = struct { |
| 126 | 105 | }, |
| 127 | 106 | }; |
| 128 | 107 | |
| 108 | pub const Constant = struct { |
| 109 | pub const base_tag = Tag.constant; |
| 110 | base: Inst, |
| 111 | |
| 112 | val: Value, |
| 113 | }; |
| 114 | |
| 115 | pub const IsNonNull = struct { |
| 116 | pub const base_tag = Tag.isnonnull; |
| 117 | |
| 118 | base: Inst, |
| 119 | args: struct { |
| 120 | operand: *Inst, |
| 121 | }, |
| 122 | }; |
| 123 | |
| 129 | 124 | pub const IsNull = struct { |
| 130 | 125 | pub const base_tag = Tag.isnull; |
| 131 | 126 | |
| ... | ... | @@ -135,14 +130,26 @@ pub const Inst = struct { |
| 135 | 130 | }, |
| 136 | 131 | }; |
| 137 | 132 | |
| 138 | | pub const IsNonNull = struct { |
| 139 | | pub const base_tag = Tag.isnonnull; |
| 133 | pub const PtrToInt = struct { |
| 134 | pub const base_tag = Tag.ptrtoint; |
| 140 | 135 | |
| 141 | 136 | base: Inst, |
| 142 | 137 | args: struct { |
| 143 | | operand: *Inst, |
| 138 | ptr: *Inst, |
| 144 | 139 | }, |
| 145 | 140 | }; |
| 141 | |
| 142 | pub const Ret = struct { |
| 143 | pub const base_tag = Tag.ret; |
| 144 | base: Inst, |
| 145 | args: void, |
| 146 | }; |
| 147 | |
| 148 | pub const Unreach = struct { |
| 149 | pub const base_tag = Tag.unreach; |
| 150 | base: Inst, |
| 151 | args: void, |
| 152 | }; |
| 146 | 153 | }; |
| 147 | 154 | |
| 148 | 155 | pub const TypedValue = struct { |
| ... | ... | @@ -159,6 +166,7 @@ pub const Module = struct { |
| 159 | 166 | link_mode: std.builtin.LinkMode, |
| 160 | 167 | output_mode: std.builtin.OutputMode, |
| 161 | 168 | object_format: std.Target.ObjectFormat, |
| 169 | optimize_mode: std.builtin.Mode, |
| 162 | 170 | |
| 163 | 171 | pub const Export = struct { |
| 164 | 172 | name: []const u8, |
| ... | ... | @@ -198,6 +206,7 @@ pub const AnalyzeOptions = struct { |
| 198 | 206 | output_mode: std.builtin.OutputMode, |
| 199 | 207 | link_mode: std.builtin.LinkMode, |
| 200 | 208 | object_format: ?std.Target.ObjectFormat = null, |
| 209 | optimize_mode: std.builtin.Mode, |
| 201 | 210 | }; |
| 202 | 211 | |
| 203 | 212 | pub fn analyze(allocator: *Allocator, old_module: text.Module, options: AnalyzeOptions) !Module { |
| ... | ... | @@ -210,6 +219,9 @@ pub fn analyze(allocator: *Allocator, old_module: text.Module, options: AnalyzeO |
| 210 | 219 | .exports = std.ArrayList(Module.Export).init(allocator), |
| 211 | 220 | .fns = std.ArrayList(Module.Fn).init(allocator), |
| 212 | 221 | .target = options.target, |
| 222 | .optimize_mode = options.optimize_mode, |
| 223 | .link_mode = options.link_mode, |
| 224 | .output_mode = options.output_mode, |
| 213 | 225 | }; |
| 214 | 226 | defer ctx.errors.deinit(); |
| 215 | 227 | defer ctx.decl_table.deinit(); |
| ... | ... | @@ -229,9 +241,10 @@ pub fn analyze(allocator: *Allocator, old_module: text.Module, options: AnalyzeO |
| 229 | 241 | .fns = ctx.fns.toOwnedSlice(), |
| 230 | 242 | .arena = ctx.arena, |
| 231 | 243 | .target = ctx.target, |
| 232 | | .link_mode = options.link_mode, |
| 233 | | .output_mode = options.output_mode, |
| 244 | .link_mode = ctx.link_mode, |
| 245 | .output_mode = ctx.output_mode, |
| 234 | 246 | .object_format = options.object_format orelse ctx.target.getObjectFormat(), |
| 247 | .optimize_mode = ctx.optimize_mode, |
| 235 | 248 | }; |
| 236 | 249 | } |
| 237 | 250 | |
| ... | ... | @@ -244,6 +257,9 @@ const Analyze = struct { |
| 244 | 257 | exports: std.ArrayList(Module.Export), |
| 245 | 258 | fns: std.ArrayList(Module.Fn), |
| 246 | 259 | target: Target, |
| 260 | link_mode: std.builtin.LinkMode, |
| 261 | optimize_mode: std.builtin.Mode, |
| 262 | output_mode: std.builtin.OutputMode, |
| 247 | 263 | |
| 248 | 264 | const NewDecl = struct { |
| 249 | 265 | /// null means a semantic analysis error happened |
| ... | ... | @@ -495,6 +511,7 @@ const Analyze = struct { |
| 495 | 511 | |
| 496 | 512 | fn analyzeInst(self: *Analyze, block: ?*Block, old_inst: *text.Inst) InnerError!*Inst { |
| 497 | 513 | switch (old_inst.tag) { |
| 514 | .breakpoint => return self.analyzeInstBreakpoint(block, old_inst.cast(text.Inst.Breakpoint).?), |
| 498 | 515 | .str => { |
| 499 | 516 | // We can use this reference because Inst.Const's Value is arena-allocated. |
| 500 | 517 | // The value would get copied to a MemoryCell before the `text.Inst.Str` lifetime ends. |
| ... | ... | @@ -530,6 +547,11 @@ const Analyze = struct { |
| 530 | 547 | } |
| 531 | 548 | } |
| 532 | 549 | |
| 550 | fn analyzeInstBreakpoint(self: *Analyze, block: ?*Block, inst: *text.Inst.Breakpoint) InnerError!*Inst { |
| 551 | const b = try self.requireRuntimeBlock(block, inst.base.src); |
| 552 | return self.addNewInstArgs(b, inst.base.src, Type.initTag(.void), Inst.Breakpoint, Inst.Args(Inst.Breakpoint){}); |
| 553 | } |
| 554 | |
| 533 | 555 | fn analyzeInstFn(self: *Analyze, block: ?*Block, fn_inst: *text.Inst.Fn) InnerError!*Inst { |
| 534 | 556 | const fn_type = try self.resolveType(block, fn_inst.positionals.fn_type); |
| 535 | 557 | |
| ... | ... | @@ -909,8 +931,21 @@ const Analyze = struct { |
| 909 | 931 | }); |
| 910 | 932 | } |
| 911 | 933 | |
| 934 | fn wantSafety(self: *Analyze, block: ?*Block) bool { |
| 935 | return switch (self.optimize_mode) { |
| 936 | .Debug => true, |
| 937 | .ReleaseSafe => true, |
| 938 | .ReleaseFast => false, |
| 939 | .ReleaseSmall => false, |
| 940 | }; |
| 941 | } |
| 942 | |
| 912 | 943 | fn analyzeInstUnreachable(self: *Analyze, block: ?*Block, unreach: *text.Inst.Unreachable) InnerError!*Inst { |
| 913 | 944 | const b = try self.requireRuntimeBlock(block, unreach.base.src); |
| 945 | if (self.wantSafety(block)) { |
| 946 | // TODO Once we have a panic function to call, call it here instead of this. |
| 947 | _ = try self.addNewInstArgs(b, unreach.base.src, Type.initTag(.void), Inst.Breakpoint, {}); |
| 948 | } |
| 914 | 949 | return self.addNewInstArgs(b, unreach.base.src, Type.initTag(.noreturn), Inst.Unreach, {}); |
| 915 | 950 | } |
| 916 | 951 | |
| ... | ... | @@ -1258,6 +1293,7 @@ pub fn main() anyerror!void { |
| 1258 | 1293 | .target = native_info.target, |
| 1259 | 1294 | .output_mode = .Obj, |
| 1260 | 1295 | .link_mode = .Static, |
| 1296 | .optimize_mode = .Debug, |
| 1261 | 1297 | }); |
| 1262 | 1298 | defer analyzed_module.deinit(allocator); |
| 1263 | 1299 | |