diff options
Diffstat (limited to 'src/Module.zig')
| -rw-r--r-- | src/Module.zig | 359 |
1 files changed, 30 insertions, 329 deletions
diff --git a/src/Module.zig b/src/Module.zig index 6273243ee2..8971a57487 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -1155,7 +1155,7 @@ pub const Scope = struct { /// This can vary during inline or comptime function calls. See `Sema.owner_decl` /// for the one that will be the same for all Block instances. src_decl: *Decl, - instructions: ArrayListUnmanaged(*ir.Inst), + instructions: ArrayListUnmanaged(Air.Inst.Index), label: ?*Label = null, inlining: ?*Inlining, /// If runtime_index is not 0 then one of these is guaranteed to be non null. @@ -1187,14 +1187,14 @@ pub const Scope = struct { }; pub const Merges = struct { - block_inst: *ir.Inst.Block, + block_inst: Air.Inst.Index, /// Separate array list from break_inst_list so that it can be passed directly /// to resolvePeerTypes. - results: ArrayListUnmanaged(*ir.Inst), + results: ArrayListUnmanaged(Air.Inst.Index), /// Keeps track of the break instructions so that the operand can be replaced /// if we need to add type coercion at the end of block analysis. /// Same indexes, capacity, length as `results`. - br_list: ArrayListUnmanaged(*ir.Inst.Br), + br_list: ArrayListUnmanaged(Air.Inst.Index), }; /// For debugging purposes. @@ -1230,187 +1230,6 @@ pub const Scope = struct { pub fn getFileScope(block: *Block) *Scope.File { return block.src_decl.namespace.file_scope; } - - pub fn addNoOp( - block: *Scope.Block, - src: LazySrcLoc, - ty: Type, - comptime tag: ir.Inst.Tag, - ) !*ir.Inst { - const inst = try block.sema.arena.create(tag.Type()); - inst.* = .{ - .base = .{ - .tag = tag, - .ty = ty, - .src = src, - }, - }; - try block.instructions.append(block.sema.gpa, &inst.base); - return &inst.base; - } - - pub fn addUnOp( - block: *Scope.Block, - src: LazySrcLoc, - ty: Type, - tag: ir.Inst.Tag, - operand: *ir.Inst, - ) !*ir.Inst { - const inst = try block.sema.arena.create(ir.Inst.UnOp); - inst.* = .{ - .base = .{ - .tag = tag, - .ty = ty, - .src = src, - }, - .operand = operand, - }; - try block.instructions.append(block.sema.gpa, &inst.base); - return &inst.base; - } - - pub fn addBinOp( - block: *Scope.Block, - src: LazySrcLoc, - ty: Type, - tag: ir.Inst.Tag, - lhs: *ir.Inst, - rhs: *ir.Inst, - ) !*ir.Inst { - const inst = try block.sema.arena.create(ir.Inst.BinOp); - inst.* = .{ - .base = .{ - .tag = tag, - .ty = ty, - .src = src, - }, - .lhs = lhs, - .rhs = rhs, - }; - try block.instructions.append(block.sema.gpa, &inst.base); - return &inst.base; - } - - pub fn addBr( - scope_block: *Scope.Block, - src: LazySrcLoc, - target_block: *ir.Inst.Block, - operand: *ir.Inst, - ) !*ir.Inst.Br { - const inst = try scope_block.sema.arena.create(ir.Inst.Br); - inst.* = .{ - .base = .{ - .tag = .br, - .ty = Type.initTag(.noreturn), - .src = src, - }, - .operand = operand, - .block = target_block, - }; - try scope_block.instructions.append(scope_block.sema.gpa, &inst.base); - return inst; - } - - pub fn addCondBr( - block: *Scope.Block, - src: LazySrcLoc, - condition: *ir.Inst, - then_body: ir.Body, - else_body: ir.Body, - ) !*ir.Inst { - const inst = try block.sema.arena.create(ir.Inst.CondBr); - inst.* = .{ - .base = .{ - .tag = .condbr, - .ty = Type.initTag(.noreturn), - .src = src, - }, - .condition = condition, - .then_body = then_body, - .else_body = else_body, - }; - try block.instructions.append(block.sema.gpa, &inst.base); - return &inst.base; - } - - pub fn addCall( - block: *Scope.Block, - src: LazySrcLoc, - ty: Type, - func: *ir.Inst, - args: []const *ir.Inst, - ) !*ir.Inst { - const inst = try block.sema.arena.create(ir.Inst.Call); - inst.* = .{ - .base = .{ - .tag = .call, - .ty = ty, - .src = src, - }, - .func = func, - .args = args, - }; - try block.instructions.append(block.sema.gpa, &inst.base); - return &inst.base; - } - - pub fn addSwitchBr( - block: *Scope.Block, - src: LazySrcLoc, - operand: *ir.Inst, - cases: []ir.Inst.SwitchBr.Case, - else_body: ir.Body, - ) !*ir.Inst { - const inst = try block.sema.arena.create(ir.Inst.SwitchBr); - inst.* = .{ - .base = .{ - .tag = .switchbr, - .ty = Type.initTag(.noreturn), - .src = src, - }, - .target = operand, - .cases = cases, - .else_body = else_body, - }; - try block.instructions.append(block.sema.gpa, &inst.base); - return &inst.base; - } - - pub fn addDbgStmt(block: *Scope.Block, src: LazySrcLoc, line: u32, column: u32) !*ir.Inst { - const inst = try block.sema.arena.create(ir.Inst.DbgStmt); - inst.* = .{ - .base = .{ - .tag = .dbg_stmt, - .ty = Type.initTag(.void), - .src = src, - }, - .line = line, - .column = column, - }; - try block.instructions.append(block.sema.gpa, &inst.base); - return &inst.base; - } - - pub fn addStructFieldPtr( - block: *Scope.Block, - src: LazySrcLoc, - ty: Type, - struct_ptr: *ir.Inst, - field_index: u32, - ) !*ir.Inst { - const inst = try block.sema.arena.create(ir.Inst.StructFieldPtr); - inst.* = .{ - .base = .{ - .tag = .struct_field_ptr, - .ty = ty, - .src = src, - }, - .struct_ptr = struct_ptr, - .field_index = field_index, - }; - try block.instructions.append(block.sema.gpa, &inst.base); - return &inst.base; - } }; }; @@ -3594,30 +3413,14 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) !Air { defer decl.value_arena.?.* = arena.state; const fn_ty = decl.ty; - const param_inst_list = try gpa.alloc(*ir.Inst, fn_ty.fnParamLen()); + const param_inst_list = try gpa.alloc(Air.Inst.Index, fn_ty.fnParamLen()); defer gpa.free(param_inst_list); - for (param_inst_list) |*param_inst, param_index| { - const param_type = fn_ty.fnParamType(param_index); - const arg_inst = try arena.allocator.create(ir.Inst.Arg); - arg_inst.* = .{ - .base = .{ - .tag = .arg, - .ty = param_type, - .src = .unneeded, - }, - .name = undefined, // Set in the semantic analysis of the arg instruction. - }; - param_inst.* = &arg_inst.base; - } - - const zir = decl.namespace.file_scope.zir; - var sema: Sema = .{ .mod = mod, .gpa = gpa, .arena = &arena.allocator, - .code = zir, + .code = decl.namespace.file_scope.zir, .owner_decl = decl, .namespace = decl.namespace, .func = func, @@ -3641,7 +3444,21 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) !Air { }; defer inner_block.instructions.deinit(gpa); - // AIR currently requires the arg parameters to be the first N instructions + // AIR requires the arg parameters to be the first N instructions. + for (param_inst_list) |*param_inst, param_index| { + const param_type = fn_ty.fnParamType(param_index); + const ty_ref = try sema.addType(param_type); + param_inst.* = @intCast(u32, sema.air_instructions.len); + try sema.air_instructions.append(gpa, .{ + .tag = .arg, + .data = .{ + .ty_str = .{ + .ty = ty_ref, + .str = undefined, // Set in the semantic analysis of the arg instruction. + }, + }, + }); + } try inner_block.instructions.appendSlice(gpa, param_inst_list); func.state = .in_progress; @@ -3650,17 +3467,21 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) !Air { try sema.analyzeFnBody(&inner_block, func.zir_body_inst); // Copy the block into place and mark that as the main block. - sema.air_extra.items[@enumToInt(Air.ExtraIndex.main_block)] = sema.air_extra.items.len; - try sema.air_extra.appendSlice(inner_block.instructions.items); + try sema.air_extra.ensureUnusedCapacity(gpa, inner_block.instructions.items.len + 1); + const main_block_index = sema.addExtraAssumeCapacity(Air.Block{ + .body_len = @intCast(u32, inner_block.instructions.items.len), + }); + sema.air_extra.appendSliceAssumeCapacity(inner_block.instructions.items); + sema.air_extra.items[@enumToInt(Air.ExtraIndex.main_block)] = main_block_index; func.state = .success; log.debug("set {s} to success", .{decl.name}); return Air{ .instructions = sema.air_instructions.toOwnedSlice(), - .extra = sema.air_extra.toOwnedSlice(), - .values = sema.air_values.toOwnedSlice(), - .variables = sema.air_variables.toOwnedSlice(), + .extra = sema.air_extra.toOwnedSlice(gpa), + .values = sema.air_values.toOwnedSlice(gpa), + .variables = sema.air_variables.toOwnedSlice(gpa), }; } @@ -3815,94 +3636,6 @@ pub fn analyzeExport( de_gop.value_ptr.*[de_gop.value_ptr.len - 1] = new_export; errdefer de_gop.value_ptr.* = mod.gpa.shrink(de_gop.value_ptr.*, de_gop.value_ptr.len - 1); } -pub fn constInst(mod: *Module, arena: *Allocator, src: LazySrcLoc, typed_value: TypedValue) !*ir.Inst { - _ = mod; - const const_inst = try arena.create(ir.Inst.Constant); - const_inst.* = .{ - .base = .{ - .tag = ir.Inst.Constant.base_tag, - .ty = typed_value.ty, - .src = src, - }, - .val = typed_value.val, - }; - return &const_inst.base; -} - -pub fn constType(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type) !*ir.Inst { - return mod.constInst(arena, src, .{ - .ty = Type.initTag(.type), - .val = try ty.toValue(arena), - }); -} - -pub fn constVoid(mod: *Module, arena: *Allocator, src: LazySrcLoc) !*ir.Inst { - return mod.constInst(arena, src, .{ - .ty = Type.initTag(.void), - .val = Value.initTag(.void_value), - }); -} - -pub fn constNoReturn(mod: *Module, arena: *Allocator, src: LazySrcLoc) !*ir.Inst { - return mod.constInst(arena, src, .{ - .ty = Type.initTag(.noreturn), - .val = Value.initTag(.unreachable_value), - }); -} - -pub fn constUndef(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type) !*ir.Inst { - return mod.constInst(arena, src, .{ - .ty = ty, - .val = Value.initTag(.undef), - }); -} - -pub fn constBool(mod: *Module, arena: *Allocator, src: LazySrcLoc, v: bool) !*ir.Inst { - return mod.constInst(arena, src, .{ - .ty = Type.initTag(.bool), - .val = ([2]Value{ Value.initTag(.bool_false), Value.initTag(.bool_true) })[@boolToInt(v)], - }); -} - -pub fn constIntUnsigned(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type, int: u64) !*ir.Inst { - return mod.constInst(arena, src, .{ - .ty = ty, - .val = try Value.Tag.int_u64.create(arena, int), - }); -} - -pub fn constIntSigned(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type, int: i64) !*ir.Inst { - return mod.constInst(arena, src, .{ - .ty = ty, - .val = try Value.Tag.int_i64.create(arena, int), - }); -} - -pub fn constIntBig(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type, big_int: BigIntConst) !*ir.Inst { - if (big_int.positive) { - if (big_int.to(u64)) |x| { - return mod.constIntUnsigned(arena, src, ty, x); - } else |err| switch (err) { - error.NegativeIntoUnsigned => unreachable, - error.TargetTooSmall => {}, // handled below - } - return mod.constInst(arena, src, .{ - .ty = ty, - .val = try Value.Tag.int_big_positive.create(arena, big_int.limbs), - }); - } else { - if (big_int.to(i64)) |x| { - return mod.constIntSigned(arena, src, ty, x); - } else |err| switch (err) { - error.NegativeIntoUnsigned => unreachable, - error.TargetTooSmall => {}, // handled below - } - return mod.constInst(arena, src, .{ - .ty = ty, - .val = try Value.Tag.int_big_negative.create(arena, big_int.limbs), - }); - } -} pub fn deleteAnonDecl(mod: *Module, scope: *Scope, decl: *Decl) void { const scope_decl = scope.ownerDecl().?; @@ -4438,38 +4171,6 @@ pub fn errorUnionType( }); } -pub fn dumpInst(mod: *Module, scope: *Scope, inst: *ir.Inst) void { - const zir_module = scope.namespace(); - const source = zir_module.getSource(mod) catch @panic("dumpInst failed to get source"); - const loc = std.zig.findLineColumn(source, inst.src); - if (inst.tag == .constant) { - std.debug.print("constant ty={} val={} src={s}:{d}:{d}\n", .{ - inst.ty, - inst.castTag(.constant).?.val, - zir_module.subFilePath(), - loc.line + 1, - loc.column + 1, - }); - } else if (inst.deaths == 0) { - std.debug.print("{s} ty={} src={s}:{d}:{d}\n", .{ - @tagName(inst.tag), - inst.ty, - zir_module.subFilePath(), - loc.line + 1, - loc.column + 1, - }); - } else { - std.debug.print("{s} ty={} deaths={b} src={s}:{d}:{d}\n", .{ - @tagName(inst.tag), - inst.ty, - inst.deaths, - zir_module.subFilePath(), - loc.line + 1, - loc.column + 1, - }); - } -} - pub fn getTarget(mod: Module) Target { return mod.comp.bin_file.options.target; } |
