stage2: codegen.zig updated to new AIR memory layout

This commit is contained in:
Andrew Kelley
2021-07-16 18:22:18 -07:00
parent eadbee2041
commit 8082660118
7 changed files with 960 additions and 823 deletions

View File

@@ -13,9 +13,9 @@ const Air = @This();
instructions: std.MultiArrayList(Inst).Slice,
/// The meaning of this data is determined by `Inst.Tag` value.
/// The first few indexes are reserved. See `ExtraIndex` for the values.
extra: []u32,
values: []Value,
variables: []*Module.Var,
extra: []const u32,
values: []const Value,
variables: []const *Module.Var,
pub const ExtraIndex = enum(u32) {
/// Payload index of the main `Block` in the `extra` array.
@@ -378,22 +378,109 @@ pub fn getMainBody(air: Air) []const Air.Inst.Index {
return air.extra[extra.end..][0..extra.data.body_len];
}
pub fn getType(air: Air, inst: Air.Inst.Index) Type {
_ = air;
_ = inst;
@panic("TODO Air getType");
pub fn typeOf(air: Air, inst: Air.Inst.Ref) Type {
const ref_int = @enumToInt(inst);
if (ref_int < Air.Inst.Ref.typed_value_map.len) {
return Air.Inst.Ref.typed_value_map[ref_int].ty;
}
return air.typeOfIndex(@intCast(Air.Inst.Index, ref_int - Air.Inst.Ref.typed_value_map.len));
}
pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
const datas = air.instructions.items(.data);
switch (air.instructions.items(.tag)[inst]) {
.arg => return air.getRefType(datas[inst].ty_str.ty),
.add,
.addwrap,
.sub,
.subwrap,
.mul,
.mulwrap,
.div,
.bit_and,
.bit_or,
.xor,
=> return air.typeOf(datas[inst].bin_op.lhs),
.cmp_lt,
.cmp_lte,
.cmp_eq,
.cmp_gte,
.cmp_gt,
.cmp_neq,
.is_null,
.is_non_null,
.is_null_ptr,
.is_non_null_ptr,
.is_err,
.is_non_err,
.is_err_ptr,
.is_non_err_ptr,
.bool_and,
.bool_or,
=> return Type.initTag(.bool),
.const_ty => return Type.initTag(.type),
.alloc => return datas[inst].ty,
.assembly,
.block,
.constant,
.varptr,
.struct_field_ptr,
=> return air.getRefType(datas[inst].ty_pl.ty),
.not,
.bitcast,
.load,
.ref,
.floatcast,
.intcast,
.optional_payload,
.optional_payload_ptr,
.wrap_optional,
.unwrap_errunion_payload,
.unwrap_errunion_err,
.unwrap_errunion_payload_ptr,
.unwrap_errunion_err_ptr,
.wrap_errunion_payload,
.wrap_errunion_err,
=> return air.getRefType(datas[inst].ty_op.ty),
.loop,
.br,
.cond_br,
.switch_br,
.ret,
.unreach,
=> return Type.initTag(.noreturn),
.breakpoint,
.dbg_stmt,
.store,
=> return Type.initTag(.void),
.ptrtoint => return Type.initTag(.usize),
.call => {
const callee_ty = air.typeOf(datas[inst].pl_op.operand);
return callee_ty.fnReturnType();
},
}
}
pub fn getRefType(air: Air, ref: Air.Inst.Ref) Type {
var i: usize = @enumToInt(ref);
if (i < Air.Inst.Ref.typed_value_map.len) {
return Air.Inst.Ref.typed_value_map[i].val.toType(undefined) catch unreachable;
const ref_int = @enumToInt(ref);
if (ref_int < Air.Inst.Ref.typed_value_map.len) {
return Air.Inst.Ref.typed_value_map[ref_int].val.toType(undefined) catch unreachable;
}
i -= Air.Inst.Ref.typed_value_map.len;
const inst_index = ref_int - Air.Inst.Ref.typed_value_map.len;
const air_tags = air.instructions.items(.tag);
const air_datas = air.instructions.items(.data);
assert(air_tags[i] == .const_ty);
return air_datas[i].ty;
assert(air_tags[inst_index] == .const_ty);
return air_datas[inst_index].ty;
}
/// Returns the requested data, as well as the new index which is at the start of the
@@ -424,3 +511,33 @@ pub fn deinit(air: *Air, gpa: *std.mem.Allocator) void {
gpa.free(air.variables);
air.* = undefined;
}
const ref_start_index: u32 = Air.Inst.Ref.typed_value_map.len;
pub fn indexToRef(inst: Air.Inst.Index) Air.Inst.Ref {
return @intToEnum(Air.Inst.Ref, ref_start_index + inst);
}
pub fn refToIndex(inst: Air.Inst.Ref) ?Air.Inst.Index {
const ref_int = @enumToInt(inst);
if (ref_int >= ref_start_index) {
return ref_int - ref_start_index;
} else {
return null;
}
}
/// Returns `null` if runtime-known.
pub fn value(air: Air, inst: Air.Inst.Ref) ?Value {
const ref_int = @enumToInt(inst);
if (ref_int < Air.Inst.Ref.typed_value_map.len) {
return Air.Inst.Ref.typed_value_map[ref_int].val;
}
const inst_index = @intCast(Air.Inst.Index, ref_int - Air.Inst.Ref.typed_value_map.len);
const air_datas = air.instructions.items(.data);
switch (air.instructions.items(.tag)[inst_index]) {
.constant => return air.values[air_datas[inst_index].ty_pl.payload],
.const_ty => unreachable,
else => return air.typeOfIndex(inst_index).onePossibleValue(),
}
}

View File

@@ -6412,37 +6412,12 @@ fn multilineStringLiteral(
node: ast.Node.Index,
) InnerError!Zir.Inst.Ref {
const astgen = gz.astgen;
const tree = astgen.tree;
const node_datas = tree.nodes.items(.data);
const start = node_datas[node].lhs;
const end = node_datas[node].rhs;
const gpa = gz.astgen.gpa;
const string_bytes = &gz.astgen.string_bytes;
const str_index = string_bytes.items.len;
// First line: do not append a newline.
var tok_i = start;
{
const slice = tree.tokenSlice(tok_i);
const line_bytes = slice[2 .. slice.len - 1];
try string_bytes.appendSlice(gpa, line_bytes);
tok_i += 1;
}
// Following lines: each line prepends a newline.
while (tok_i <= end) : (tok_i += 1) {
const slice = tree.tokenSlice(tok_i);
const line_bytes = slice[2 .. slice.len - 1];
try string_bytes.ensureCapacity(gpa, string_bytes.items.len + line_bytes.len + 1);
string_bytes.appendAssumeCapacity('\n');
string_bytes.appendSliceAssumeCapacity(line_bytes);
}
const str = try astgen.strLitNodeAsString(node);
const result = try gz.add(.{
.tag = .str,
.data = .{ .str = .{
.start = @intCast(u32, str_index),
.len = @intCast(u32, string_bytes.items.len - str_index),
.start = str.index,
.len = str.len,
} },
});
return rvalue(gz, rl, result, node);
@@ -6620,9 +6595,14 @@ fn asmExpr(
const tree = astgen.tree;
const main_tokens = tree.nodes.items(.main_token);
const node_datas = tree.nodes.items(.data);
const node_tags = tree.nodes.items(.tag);
const token_tags = tree.tokens.items(.tag);
const asm_source = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, full.ast.template);
const asm_source = switch (node_tags[full.ast.template]) {
.string_literal => try astgen.strLitAsString(main_tokens[full.ast.template]),
.multiline_string_literal => try astgen.strLitNodeAsString(full.ast.template),
else => return astgen.failNode(node, "assembly code must use string literal syntax", .{}),
};
// See https://github.com/ziglang/zig/issues/215 and related issues discussing
// possible inline assembly improvements. Until then here is status quo AstGen
@@ -6752,7 +6732,7 @@ fn asmExpr(
const result = try gz.addAsm(.{
.node = node,
.asm_source = asm_source,
.asm_source = asm_source.index,
.is_volatile = full.volatile_token != null,
.output_type_bits = output_type_bits,
.outputs = outputs,
@@ -8579,6 +8559,41 @@ fn strLitAsString(astgen: *AstGen, str_lit_token: ast.TokenIndex) !IndexSlice {
}
}
fn strLitNodeAsString(astgen: *AstGen, node: ast.Node.Index) !IndexSlice {
const tree = astgen.tree;
const node_datas = tree.nodes.items(.data);
const start = node_datas[node].lhs;
const end = node_datas[node].rhs;
const gpa = astgen.gpa;
const string_bytes = &astgen.string_bytes;
const str_index = string_bytes.items.len;
// First line: do not append a newline.
var tok_i = start;
{
const slice = tree.tokenSlice(tok_i);
const line_bytes = slice[2 .. slice.len - 1];
try string_bytes.appendSlice(gpa, line_bytes);
tok_i += 1;
}
// Following lines: each line prepends a newline.
while (tok_i <= end) : (tok_i += 1) {
const slice = tree.tokenSlice(tok_i);
const line_bytes = slice[2 .. slice.len - 1];
try string_bytes.ensureCapacity(gpa, string_bytes.items.len + line_bytes.len + 1);
string_bytes.appendAssumeCapacity('\n');
string_bytes.appendSliceAssumeCapacity(line_bytes);
}
const len = string_bytes.items.len - str_index;
try string_bytes.append(gpa, 0);
return IndexSlice{
.index = @intCast(u32, str_index),
.len = @intCast(u32, len),
};
}
fn testNameString(astgen: *AstGen, str_lit_token: ast.TokenIndex) !u32 {
const gpa = astgen.gpa;
const string_bytes = &astgen.string_bytes;
@@ -9440,7 +9455,7 @@ const GenZir = struct {
args: struct {
/// Absolute node index. This function does the conversion to offset from Decl.
node: ast.Node.Index,
asm_source: Zir.Inst.Ref,
asm_source: u32,
output_type_bits: u32,
is_volatile: bool,
outputs: []const Zir.Inst.Asm.Output,

View File

@@ -21,7 +21,7 @@ const Log2Int = std.math.Log2Int;
/// operand dies after this instruction.
/// Instructions which need more data to track liveness have special handling via the
/// `special` table.
tomb_bits: []const usize,
tomb_bits: []usize,
/// Sparse table of specially handled instructions. The value is an index into the `extra`
/// array. The meaning of the data depends on the AIR tag.
special: std.AutoHashMapUnmanaged(Air.Inst.Index, u32),
@@ -98,7 +98,7 @@ pub fn operandDies(l: Liveness, inst: Air.Inst.Index, operand: OperandInt) bool
return (l.tomb_bits[usize_index] & mask) != 0;
}
pub fn clearOperandDeath(l: *Liveness, inst: Air.Inst.Index, operand: OperandInt) void {
pub fn clearOperandDeath(l: Liveness, inst: Air.Inst.Index, operand: OperandInt) void {
assert(operand < bpi - 1);
const usize_index = (inst * bpi) / @bitSizeOf(usize);
const mask = @as(usize, 1) <<
@@ -106,16 +106,40 @@ pub fn clearOperandDeath(l: *Liveness, inst: Air.Inst.Index, operand: OperandInt
l.tomb_bits[usize_index] |= mask;
}
/// Higher level API.
pub const CondBrSlices = struct {
then_deaths: []const Air.Inst.Index,
else_deaths: []const Air.Inst.Index,
};
pub fn getCondBr(l: Liveness, inst: Air.Inst.Index) CondBrSlices {
var index: usize = l.special.get(inst) orelse return .{
.then_deaths = &.{},
.else_deaths = &.{},
};
const then_death_count = l.extra[index];
index += 1;
const else_death_count = l.extra[index];
index += 1;
const then_deaths = l.extra[index..][0..then_death_count];
index += then_death_count;
return .{
.then_deaths = then_deaths,
.else_deaths = l.extra[index..][0..else_death_count],
};
}
pub fn deinit(l: *Liveness, gpa: *Allocator) void {
gpa.free(l.tomb_bits);
gpa.free(l.extra);
l.special.deinit(gpa);
l.* = undefined;
}
/// How many tomb bits per AIR instruction.
const bpi = 4;
const Bpi = std.meta.Int(.unsigned, bpi);
const OperandInt = std.math.Log2Int(Bpi);
pub const bpi = 4;
pub const Bpi = std.meta.Int(.unsigned, bpi);
pub const OperandInt = std.math.Log2Int(Bpi);
/// In-progress data; on successful analysis converted into `Liveness`.
const Analysis = struct {
@@ -267,14 +291,14 @@ fn analyzeInst(
const inst_data = inst_datas[inst].pl_op;
const callee = inst_data.operand;
const extra = a.air.extraData(Air.Call, inst_data.payload);
const args = a.air.extra[extra.end..][0..extra.data.args_len];
const args = @bitCast([]const Air.Inst.Ref, a.air.extra[extra.end..][0..extra.data.args_len]);
if (args.len <= bpi - 2) {
var buf: [bpi - 1]Air.Inst.Ref = undefined;
var buf = [1]Air.Inst.Ref{.none} ** (bpi - 1);
buf[0] = callee;
std.mem.copy(Air.Inst.Ref, buf[1..], @bitCast([]const Air.Inst.Ref, args));
std.mem.copy(Air.Inst.Ref, buf[1..], args);
return trackOperands(a, new_set, inst, main_tomb, buf);
}
@panic("TODO: liveness analysis for function with greater than 2 args");
@panic("TODO: liveness analysis for function call with greater than 2 args");
},
.struct_field_ptr => {
const extra = a.air.extraData(Air.StructField, inst_datas[inst].ty_pl.payload).data;
@@ -285,12 +309,12 @@ fn analyzeInst(
const extended = a.zir.instructions.items(.data)[extra.data.zir_index].extended;
const outputs_len = @truncate(u5, extended.small);
const inputs_len = @truncate(u5, extended.small >> 5);
const outputs = a.air.extra[extra.end..][0..outputs_len];
const inputs = a.air.extra[extra.end + outputs.len ..][0..inputs_len];
if (outputs.len + inputs.len <= bpi - 1) {
var buf: [bpi - 1]Air.Inst.Ref = undefined;
std.mem.copy(Air.Inst.Ref, &buf, @bitCast([]const Air.Inst.Ref, outputs));
std.mem.copy(Air.Inst.Ref, buf[outputs.len..], @bitCast([]const Air.Inst.Ref, inputs));
const outputs = @bitCast([]const Air.Inst.Ref, a.air.extra[extra.end..][0..outputs_len]);
const args = @bitCast([]const Air.Inst.Ref, a.air.extra[extra.end + outputs.len ..][0..inputs_len]);
if (outputs.len + args.len <= bpi - 1) {
var buf = [1]Air.Inst.Ref{.none} ** (bpi - 1);
std.mem.copy(Air.Inst.Ref, &buf, outputs);
std.mem.copy(Air.Inst.Ref, buf[outputs.len..], args);
return trackOperands(a, new_set, inst, main_tomb, buf);
}
@panic("TODO: liveness analysis for asm with greater than 3 args");

View File

@@ -1309,7 +1309,7 @@ pub const Scope = struct {
const result_index = @intCast(Air.Inst.Index, sema.air_instructions.len);
sema.air_instructions.appendAssumeCapacity(inst);
block.instructions.appendAssumeCapacity(result_index);
return Sema.indexToRef(result_index);
return Air.indexToRef(result_index);
}
};
};
@@ -3533,7 +3533,7 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) SemaError!Air {
const ty_ref = try sema.addType(param_type);
const arg_index = @intCast(u32, sema.air_instructions.len);
inner_block.instructions.appendAssumeCapacity(arg_index);
param_inst.* = Sema.indexToRef(arg_index);
param_inst.* = Air.indexToRef(arg_index);
try sema.air_instructions.append(gpa, .{
.tag = .arg,
.data = .{

View File

@@ -1301,7 +1301,7 @@ fn zirArg(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!A
// Set the name of the Air.Arg instruction for use by codegen debug info.
const air_arg = sema.param_inst_list[arg_index];
sema.air_instructions.items(.data)[refToIndex(air_arg).?].ty_str.str = inst_data.start;
sema.air_instructions.items(.data)[Air.refToIndex(air_arg).?].ty_str.str = inst_data.start;
return air_arg;
}
@@ -1389,7 +1389,7 @@ fn zirAllocInferred(
// to the block even though it is currently a `.constant`.
const result = try sema.addConstant(inferred_alloc_ty, Value.initPayload(&val_payload.base));
try sema.requireFunctionBlock(block, src);
try block.instructions.append(sema.gpa, refToIndex(result).?);
try block.instructions.append(sema.gpa, Air.refToIndex(result).?);
return result;
}
@@ -1400,7 +1400,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Inde
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node };
const ptr = sema.resolveInst(inst_data.operand);
const ptr_inst = refToIndex(ptr).?;
const ptr_inst = Air.refToIndex(ptr).?;
assert(sema.air_instructions.items(.tag)[ptr_inst] == .constant);
const air_datas = sema.air_instructions.items(.data);
const ptr_val = sema.air_values.items[air_datas[ptr_inst].ty_pl.payload];
@@ -1586,7 +1586,7 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index)
const bin_inst = sema.code.instructions.items(.data)[inst].bin;
const ptr = sema.resolveInst(bin_inst.lhs);
const value = sema.resolveInst(bin_inst.rhs);
const ptr_inst = refToIndex(ptr).?;
const ptr_inst = Air.refToIndex(ptr).?;
assert(sema.air_instructions.items(.tag)[ptr_inst] == .constant);
const air_datas = sema.air_instructions.items(.data);
const ptr_val = sema.air_values.items[air_datas[ptr_inst].ty_pl.payload];
@@ -1968,13 +1968,13 @@ fn analyzeBlockBody(
// Blocks must terminate with noreturn instruction.
assert(child_block.instructions.items.len != 0);
assert(sema.typeOf(indexToRef(child_block.instructions.items[child_block.instructions.items.len - 1])).isNoReturn());
assert(sema.typeOf(Air.indexToRef(child_block.instructions.items[child_block.instructions.items.len - 1])).isNoReturn());
if (merges.results.items.len == 0) {
// No need for a block instruction. We can put the new instructions
// directly into the parent block.
try parent_block.instructions.appendSlice(gpa, child_block.instructions.items);
return indexToRef(child_block.instructions.items[child_block.instructions.items.len - 1]);
return Air.indexToRef(child_block.instructions.items[child_block.instructions.items.len - 1]);
}
if (merges.results.items.len == 1) {
const last_inst_index = child_block.instructions.items.len - 1;
@@ -2025,7 +2025,7 @@ fn analyzeBlockBody(
continue;
}
assert(coerce_block.instructions.items[coerce_block.instructions.items.len - 1] ==
refToIndex(coerced_operand).?);
Air.refToIndex(coerced_operand).?);
// Convert the br operand to a block.
const br_operand_ty_ref = try sema.addType(br_operand_ty);
@@ -2034,7 +2034,7 @@ fn analyzeBlockBody(
try sema.air_instructions.ensureUnusedCapacity(gpa, 2);
const sub_block_inst = @intCast(Air.Inst.Index, sema.air_instructions.len);
const sub_br_inst = sub_block_inst + 1;
sema.air_instructions.items(.data)[br].br.operand = indexToRef(sub_block_inst);
sema.air_instructions.items(.data)[br].br.operand = Air.indexToRef(sub_block_inst);
sema.air_instructions.appendAssumeCapacity(.{
.tag = .block,
.data = .{ .ty_pl = .{
@@ -2054,7 +2054,7 @@ fn analyzeBlockBody(
} },
});
}
return indexToRef(merges.block_inst);
return Air.indexToRef(merges.block_inst);
}
fn zirExport(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!void {
@@ -2149,7 +2149,7 @@ fn zirBreak(sema: *Sema, start_block: *Scope.Block, inst: Zir.Inst.Index) Compil
if (label.zir_block == zir_block) {
const br_ref = try start_block.addBr(label.merges.block_inst, operand);
try label.merges.results.append(sema.gpa, operand);
try label.merges.br_list.append(sema.gpa, refToIndex(br_ref).?);
try label.merges.br_list.append(sema.gpa, Air.refToIndex(br_ref).?);
return inst;
}
}
@@ -5310,7 +5310,7 @@ fn zirBoolBr(
} } });
try parent_block.instructions.append(gpa, block_inst);
return indexToRef(block_inst);
return Air.indexToRef(block_inst);
}
fn zirIsNonNull(
@@ -7204,7 +7204,7 @@ fn analyzeVarRef(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, tv: TypedVal
} },
});
try block.instructions.append(gpa, result_inst);
return indexToRef(result_inst);
return Air.indexToRef(result_inst);
}
fn analyzeRef(
@@ -8021,107 +8021,18 @@ fn enumFieldSrcLoc(
} else unreachable;
}
/// This is only meant to be called by `typeOf`.
fn analyzeAsTypeInfallible(sema: *Sema, inst: Air.Inst.Ref) Type {
var i: usize = @enumToInt(inst);
if (i < Air.Inst.Ref.typed_value_map.len) {
return Air.Inst.Ref.typed_value_map[i].val.toType(undefined) catch unreachable;
}
i -= Air.Inst.Ref.typed_value_map.len;
assert(sema.air_instructions.items(.tag)[i] == .const_ty);
return sema.air_instructions.items(.data)[i].ty;
}
/// Returns the type of the AIR instruction.
fn typeOf(sema: *Sema, inst: Air.Inst.Ref) Type {
var i: usize = @enumToInt(inst);
if (i < Air.Inst.Ref.typed_value_map.len) {
return Air.Inst.Ref.typed_value_map[i].ty;
}
i -= Air.Inst.Ref.typed_value_map.len;
return sema.getTmpAir().typeOf(inst);
}
const air_datas = sema.air_instructions.items(.data);
switch (sema.air_instructions.items(.tag)[i]) {
.arg => return sema.analyzeAsTypeInfallible(air_datas[i].ty_str.ty),
.add,
.addwrap,
.sub,
.subwrap,
.mul,
.mulwrap,
.div,
.bit_and,
.bit_or,
.xor,
=> return sema.typeOf(air_datas[i].bin_op.lhs),
.cmp_lt,
.cmp_lte,
.cmp_eq,
.cmp_gte,
.cmp_gt,
.cmp_neq,
.is_null,
.is_non_null,
.is_null_ptr,
.is_non_null_ptr,
.is_err,
.is_non_err,
.is_err_ptr,
.is_non_err_ptr,
.bool_and,
.bool_or,
=> return Type.initTag(.bool),
.const_ty => return Type.initTag(.type),
.alloc => return air_datas[i].ty,
.assembly,
.block,
.constant,
.varptr,
.struct_field_ptr,
=> return sema.analyzeAsTypeInfallible(air_datas[i].ty_pl.ty),
.not,
.bitcast,
.load,
.ref,
.floatcast,
.intcast,
.optional_payload,
.optional_payload_ptr,
.wrap_optional,
.unwrap_errunion_payload,
.unwrap_errunion_err,
.unwrap_errunion_payload_ptr,
.unwrap_errunion_err_ptr,
.wrap_errunion_payload,
.wrap_errunion_err,
=> return sema.analyzeAsTypeInfallible(air_datas[i].ty_op.ty),
.loop,
.br,
.cond_br,
.switch_br,
.ret,
.unreach,
=> return Type.initTag(.noreturn),
.breakpoint,
.dbg_stmt,
.store,
=> return Type.initTag(.void),
.ptrtoint => return Type.initTag(.usize),
.call => {
const callee_ty = sema.typeOf(air_datas[i].pl_op.operand);
return callee_ty.fnReturnType();
},
}
fn getTmpAir(sema: Sema) Air {
return .{
.instructions = sema.air_instructions.slice(),
.extra = sema.air_extra.items,
.values = sema.air_values.items,
.variables = sema.air_variables.items,
};
}
pub fn addType(sema: *Sema, ty: Type) !Air.Inst.Ref {
@@ -8185,7 +8096,7 @@ pub fn addType(sema: *Sema, ty: Type) !Air.Inst.Ref {
.tag = .const_ty,
.data = .{ .ty = ty },
});
return indexToRef(@intCast(u32, sema.air_instructions.len - 1));
return Air.indexToRef(@intCast(u32, sema.air_instructions.len - 1));
}
fn addIntUnsigned(sema: *Sema, ty: Type, int: u64) CompileError!Air.Inst.Ref {
@@ -8207,22 +8118,7 @@ fn addConstant(sema: *Sema, ty: Type, val: Value) CompileError!Air.Inst.Ref {
.payload = @intCast(u32, sema.air_values.items.len - 1),
} },
});
return indexToRef(@intCast(u32, sema.air_instructions.len - 1));
}
const ref_start_index: u32 = Air.Inst.Ref.typed_value_map.len;
pub fn indexToRef(inst: Air.Inst.Index) Air.Inst.Ref {
return @intToEnum(Air.Inst.Ref, ref_start_index + inst);
}
pub fn refToIndex(inst: Air.Inst.Ref) ?Air.Inst.Index {
const ref_int = @enumToInt(inst);
if (ref_int >= ref_start_index) {
return ref_int - ref_start_index;
} else {
return null;
}
return Air.indexToRef(@intCast(u32, sema.air_instructions.len - 1));
}
pub fn addExtra(sema: *Sema, extra: anytype) Allocator.Error!u32 {

View File

@@ -2176,7 +2176,8 @@ pub const Inst = struct {
/// 2. clobber: u32 // index into string_bytes (null terminated) for every clobbers_len.
pub const Asm = struct {
src_node: i32,
asm_source: Ref,
// null-terminated string index
asm_source: u32,
/// 1 bit for each outputs_len: whether it uses `-> T` or not.
/// 0b0 - operand is a pointer to where to store the output.
/// 0b1 - operand is a type; asm expression has the output as the result.
@@ -3383,9 +3384,10 @@ const Writer = struct {
const inputs_len = @truncate(u5, extended.small >> 5);
const clobbers_len = @truncate(u5, extended.small >> 10);
const is_volatile = @truncate(u1, extended.small >> 15) != 0;
const asm_source = self.code.nullTerminatedString(extra.data.asm_source);
try self.writeFlag(stream, "volatile, ", is_volatile);
try self.writeInstRef(stream, extra.data.asm_source);
try stream.print("\"{}\", ", .{std.zig.fmtEscapes(asm_source)});
try stream.writeAll(", ");
var extra_i: usize = extra.end;

File diff suppressed because it is too large Load Diff