AstGen: implement all the builtin functions

This commit is contained in:
Andrew Kelley 2021-04-18 22:38:41 -07:00
parent 5a3045b5de
commit ae495de54d
7 changed files with 2183 additions and 428 deletions

View File

@ -737,5 +737,3 @@ fn errorSetDecl(
try mod.analyzeExport(&decl_scope.base, export_src, name, decl);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1198,6 +1198,30 @@ pub const Scope = struct {
gz.astgen.extra.appendSliceAssumeCapacity(gz.instructions.items);
}
/// Same as `setBlockBody` except we don't copy instructions which are
/// `store_to_block_ptr` instructions with lhs set to .none.
pub fn setBlockBodyEliding(gz: GenZir, inst: Zir.Inst.Index) !void {
const gpa = gz.astgen.gpa;
try gz.astgen.extra.ensureCapacity(gpa, gz.astgen.extra.items.len +
@typeInfo(Zir.Inst.Block).Struct.fields.len + gz.instructions.items.len);
const zir_datas = gz.astgen.instructions.items(.data);
const zir_tags = gz.astgen.instructions.items(.tag);
const block_pl_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Block{
.body_len = @intCast(u32, gz.instructions.items.len),
});
zir_datas[inst].pl_node.payload_index = block_pl_index;
for (gz.instructions.items) |sub_inst| {
if (zir_tags[sub_inst] == .store_to_block_ptr and
zir_datas[sub_inst].bin.lhs == .none)
{
// Decrement `body_len`.
gz.astgen.extra.items[block_pl_index] -= 1;
continue;
}
gz.astgen.extra.appendAssumeCapacity(sub_inst);
}
}
pub fn identAsString(gz: *GenZir, ident_token: ast.TokenIndex) !u32 {
const astgen = gz.astgen;
const gpa = astgen.gpa;
@ -1445,6 +1469,30 @@ pub const Scope = struct {
return gz.indexToRef(new_index);
}
pub fn addExtendedPayload(
gz: *GenZir,
opcode: Zir.Inst.Extended,
extra: anytype,
) !Zir.Inst.Ref {
const gpa = gz.astgen.gpa;
try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
try gz.astgen.instructions.ensureCapacity(gpa, gz.astgen.instructions.len + 1);
const payload_index = try gz.astgen.addExtra(extra);
const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
gz.astgen.instructions.appendAssumeCapacity(.{
.tag = .extended,
.data = .{ .extended = .{
.opcode = opcode,
.small = undefined,
.operand = payload_index,
} },
});
gz.instructions.appendAssumeCapacity(new_index);
return gz.indexToRef(new_index);
}
pub fn addArrayTypeSentinel(
gz: *GenZir,
len: Zir.Inst.Ref,

View File

@ -131,159 +131,227 @@ pub fn analyzeBody(
while (true) : (i += 1) {
const inst = body[i];
map[inst] = switch (tags[inst]) {
.elided => continue,
.alloc => try sema.zirAlloc(block, inst),
.alloc_inferred => try sema.zirAllocInferred(block, inst, Type.initTag(.inferred_alloc_const)),
.alloc_inferred_mut => try sema.zirAllocInferred(block, inst, Type.initTag(.inferred_alloc_mut)),
.alloc_mut => try sema.zirAllocMut(block, inst),
.array_cat => try sema.zirArrayCat(block, inst),
.array_mul => try sema.zirArrayMul(block, inst),
.array_type => try sema.zirArrayType(block, inst),
.array_type_sentinel => try sema.zirArrayTypeSentinel(block, inst),
.as => try sema.zirAs(block, inst),
.as_node => try sema.zirAsNode(block, inst),
.@"asm" => try sema.zirAsm(block, inst, false),
.asm_volatile => try sema.zirAsm(block, inst, true),
.bit_and => try sema.zirBitwise(block, inst, .bit_and),
.bit_not => try sema.zirBitNot(block, inst),
.bit_or => try sema.zirBitwise(block, inst, .bit_or),
.bitcast => try sema.zirBitcast(block, inst),
.bitcast_result_ptr => try sema.zirBitcastResultPtr(block, inst),
.block => try sema.zirBlock(block, inst),
.bool_not => try sema.zirBoolNot(block, inst),
.bool_and => try sema.zirBoolOp(block, inst, false),
.bool_or => try sema.zirBoolOp(block, inst, true),
.bool_br_and => try sema.zirBoolBr(block, inst, false),
.bool_br_or => try sema.zirBoolBr(block, inst, true),
.call => try sema.zirCall(block, inst, .auto, false),
.call_chkused => try sema.zirCall(block, inst, .auto, true),
.call_compile_time => try sema.zirCall(block, inst, .compile_time, false),
.call_none => try sema.zirCallNone(block, inst, false),
.call_none_chkused => try sema.zirCallNone(block, inst, true),
.cmp_eq => try sema.zirCmp(block, inst, .eq),
.cmp_gt => try sema.zirCmp(block, inst, .gt),
.cmp_gte => try sema.zirCmp(block, inst, .gte),
.cmp_lt => try sema.zirCmp(block, inst, .lt),
.cmp_lte => try sema.zirCmp(block, inst, .lte),
.cmp_neq => try sema.zirCmp(block, inst, .neq),
.coerce_result_ptr => try sema.zirCoerceResultPtr(block, inst),
.decl_ref => try sema.zirDeclRef(block, inst),
.decl_val => try sema.zirDeclVal(block, inst),
.load => try sema.zirLoad(block, inst),
.elem_ptr => try sema.zirElemPtr(block, inst),
.elem_ptr_node => try sema.zirElemPtrNode(block, inst),
.elem_val => try sema.zirElemVal(block, inst),
.elem_val_node => try sema.zirElemValNode(block, inst),
.enum_literal => try sema.zirEnumLiteral(block, inst),
.enum_literal_small => try sema.zirEnumLiteralSmall(block, inst),
.enum_to_int => try sema.zirEnumToInt(block, inst),
.int_to_enum => try sema.zirIntToEnum(block, inst),
.err_union_code => try sema.zirErrUnionCode(block, inst),
.err_union_code_ptr => try sema.zirErrUnionCodePtr(block, inst),
.err_union_payload_safe => try sema.zirErrUnionPayload(block, inst, true),
.err_union_payload_safe_ptr => try sema.zirErrUnionPayloadPtr(block, inst, true),
.err_union_payload_unsafe => try sema.zirErrUnionPayload(block, inst, false),
// zig fmt: off
.alloc => try sema.zirAlloc(block, inst),
.alloc_inferred => try sema.zirAllocInferred(block, inst, Type.initTag(.inferred_alloc_const)),
.alloc_inferred_mut => try sema.zirAllocInferred(block, inst, Type.initTag(.inferred_alloc_mut)),
.alloc_mut => try sema.zirAllocMut(block, inst),
.array_cat => try sema.zirArrayCat(block, inst),
.array_mul => try sema.zirArrayMul(block, inst),
.array_type => try sema.zirArrayType(block, inst),
.array_type_sentinel => try sema.zirArrayTypeSentinel(block, inst),
.as => try sema.zirAs(block, inst),
.as_node => try sema.zirAsNode(block, inst),
.@"asm" => try sema.zirAsm(block, inst, false),
.asm_volatile => try sema.zirAsm(block, inst, true),
.bit_and => try sema.zirBitwise(block, inst, .bit_and),
.bit_not => try sema.zirBitNot(block, inst),
.bit_or => try sema.zirBitwise(block, inst, .bit_or),
.bitcast => try sema.zirBitcast(block, inst),
.bitcast_result_ptr => try sema.zirBitcastResultPtr(block, inst),
.block => try sema.zirBlock(block, inst),
.bool_not => try sema.zirBoolNot(block, inst),
.bool_and => try sema.zirBoolOp(block, inst, false),
.bool_or => try sema.zirBoolOp(block, inst, true),
.bool_br_and => try sema.zirBoolBr(block, inst, false),
.bool_br_or => try sema.zirBoolBr(block, inst, true),
.c_import => try sema.zirCImport(block, inst),
.call => try sema.zirCall(block, inst, .auto, false),
.call_chkused => try sema.zirCall(block, inst, .auto, true),
.call_compile_time => try sema.zirCall(block, inst, .compile_time, false),
.call_none => try sema.zirCallNone(block, inst, false),
.call_none_chkused => try sema.zirCallNone(block, inst, true),
.cmp_eq => try sema.zirCmp(block, inst, .eq),
.cmp_gt => try sema.zirCmp(block, inst, .gt),
.cmp_gte => try sema.zirCmp(block, inst, .gte),
.cmp_lt => try sema.zirCmp(block, inst, .lt),
.cmp_lte => try sema.zirCmp(block, inst, .lte),
.cmp_neq => try sema.zirCmp(block, inst, .neq),
.coerce_result_ptr => try sema.zirCoerceResultPtr(block, inst),
.decl_ref => try sema.zirDeclRef(block, inst),
.decl_val => try sema.zirDeclVal(block, inst),
.load => try sema.zirLoad(block, inst),
.elem_ptr => try sema.zirElemPtr(block, inst),
.elem_ptr_node => try sema.zirElemPtrNode(block, inst),
.elem_val => try sema.zirElemVal(block, inst),
.elem_val_node => try sema.zirElemValNode(block, inst),
.enum_literal => try sema.zirEnumLiteral(block, inst),
.enum_literal_small => try sema.zirEnumLiteralSmall(block, inst),
.enum_to_int => try sema.zirEnumToInt(block, inst),
.int_to_enum => try sema.zirIntToEnum(block, inst),
.err_union_code => try sema.zirErrUnionCode(block, inst),
.err_union_code_ptr => try sema.zirErrUnionCodePtr(block, inst),
.err_union_payload_safe => try sema.zirErrUnionPayload(block, inst, true),
.err_union_payload_safe_ptr => try sema.zirErrUnionPayloadPtr(block, inst, true),
.err_union_payload_unsafe => try sema.zirErrUnionPayload(block, inst, false),
.err_union_payload_unsafe_ptr => try sema.zirErrUnionPayloadPtr(block, inst, false),
.error_union_type => try sema.zirErrorUnionType(block, inst),
.error_value => try sema.zirErrorValue(block, inst),
.error_to_int => try sema.zirErrorToInt(block, inst),
.int_to_error => try sema.zirIntToError(block, inst),
.field_ptr => try sema.zirFieldPtr(block, inst),
.field_ptr_named => try sema.zirFieldPtrNamed(block, inst),
.field_val => try sema.zirFieldVal(block, inst),
.field_val_named => try sema.zirFieldValNamed(block, inst),
.floatcast => try sema.zirFloatcast(block, inst),
.func => try sema.zirFunc(block, inst, false),
.func_extra => try sema.zirFuncExtra(block, inst, false),
.func_extra_var_args => try sema.zirFuncExtra(block, inst, true),
.func_var_args => try sema.zirFunc(block, inst, true),
.has_decl => try sema.zirHasDecl(block, inst),
.import => try sema.zirImport(block, inst),
.indexable_ptr_len => try sema.zirIndexablePtrLen(block, inst),
.int => try sema.zirInt(block, inst),
.float => try sema.zirFloat(block, inst),
.float128 => try sema.zirFloat128(block, inst),
.int_type => try sema.zirIntType(block, inst),
.intcast => try sema.zirIntcast(block, inst),
.is_err => try sema.zirIsErr(block, inst),
.is_err_ptr => try sema.zirIsErrPtr(block, inst),
.is_non_null => try sema.zirIsNull(block, inst, true),
.is_non_null_ptr => try sema.zirIsNullPtr(block, inst, true),
.is_null => try sema.zirIsNull(block, inst, false),
.is_null_ptr => try sema.zirIsNullPtr(block, inst, false),
.loop => try sema.zirLoop(block, inst),
.merge_error_sets => try sema.zirMergeErrorSets(block, inst),
.negate => try sema.zirNegate(block, inst, .sub),
.negate_wrap => try sema.zirNegate(block, inst, .subwrap),
.optional_payload_safe => try sema.zirOptionalPayload(block, inst, true),
.optional_payload_safe_ptr => try sema.zirOptionalPayloadPtr(block, inst, true),
.optional_payload_unsafe => try sema.zirOptionalPayload(block, inst, false),
.optional_payload_unsafe_ptr => try sema.zirOptionalPayloadPtr(block, inst, false),
.optional_type => try sema.zirOptionalType(block, inst),
.optional_type_from_ptr_elem => try sema.zirOptionalTypeFromPtrElem(block, inst),
.param_type => try sema.zirParamType(block, inst),
.ptr_type => try sema.zirPtrType(block, inst),
.ptr_type_simple => try sema.zirPtrTypeSimple(block, inst),
.ptrtoint => try sema.zirPtrtoint(block, inst),
.ref => try sema.zirRef(block, inst),
.ret_ptr => try sema.zirRetPtr(block, inst),
.ret_type => try sema.zirRetType(block, inst),
.shl => try sema.zirShl(block, inst),
.shr => try sema.zirShr(block, inst),
.slice_end => try sema.zirSliceEnd(block, inst),
.slice_sentinel => try sema.zirSliceSentinel(block, inst),
.slice_start => try sema.zirSliceStart(block, inst),
.str => try sema.zirStr(block, inst),
.switch_block => try sema.zirSwitchBlock(block, inst, false, .none),
.switch_block_multi => try sema.zirSwitchBlockMulti(block, inst, false, .none),
.switch_block_else => try sema.zirSwitchBlock(block, inst, false, .@"else"),
.switch_block_else_multi => try sema.zirSwitchBlockMulti(block, inst, false, .@"else"),
.switch_block_under => try sema.zirSwitchBlock(block, inst, false, .under),
.switch_block_under_multi => try sema.zirSwitchBlockMulti(block, inst, false, .under),
.switch_block_ref => try sema.zirSwitchBlock(block, inst, true, .none),
.switch_block_ref_multi => try sema.zirSwitchBlockMulti(block, inst, true, .none),
.switch_block_ref_else => try sema.zirSwitchBlock(block, inst, true, .@"else"),
.switch_block_ref_else_multi => try sema.zirSwitchBlockMulti(block, inst, true, .@"else"),
.switch_block_ref_under => try sema.zirSwitchBlock(block, inst, true, .under),
.error_union_type => try sema.zirErrorUnionType(block, inst),
.error_value => try sema.zirErrorValue(block, inst),
.error_to_int => try sema.zirErrorToInt(block, inst),
.int_to_error => try sema.zirIntToError(block, inst),
.field_ptr => try sema.zirFieldPtr(block, inst),
.field_ptr_named => try sema.zirFieldPtrNamed(block, inst),
.field_val => try sema.zirFieldVal(block, inst),
.field_val_named => try sema.zirFieldValNamed(block, inst),
.floatcast => try sema.zirFloatcast(block, inst),
.func => try sema.zirFunc(block, inst, false),
.func_extra => try sema.zirFuncExtra(block, inst, false),
.func_extra_var_args => try sema.zirFuncExtra(block, inst, true),
.func_var_args => try sema.zirFunc(block, inst, true),
.import => try sema.zirImport(block, inst),
.indexable_ptr_len => try sema.zirIndexablePtrLen(block, inst),
.int => try sema.zirInt(block, inst),
.float => try sema.zirFloat(block, inst),
.float128 => try sema.zirFloat128(block, inst),
.int_type => try sema.zirIntType(block, inst),
.intcast => try sema.zirIntcast(block, inst),
.is_err => try sema.zirIsErr(block, inst),
.is_err_ptr => try sema.zirIsErrPtr(block, inst),
.is_non_null => try sema.zirIsNull(block, inst, true),
.is_non_null_ptr => try sema.zirIsNullPtr(block, inst, true),
.is_null => try sema.zirIsNull(block, inst, false),
.is_null_ptr => try sema.zirIsNullPtr(block, inst, false),
.loop => try sema.zirLoop(block, inst),
.merge_error_sets => try sema.zirMergeErrorSets(block, inst),
.negate => try sema.zirNegate(block, inst, .sub),
.negate_wrap => try sema.zirNegate(block, inst, .subwrap),
.optional_payload_safe => try sema.zirOptionalPayload(block, inst, true),
.optional_payload_safe_ptr => try sema.zirOptionalPayloadPtr(block, inst, true),
.optional_payload_unsafe => try sema.zirOptionalPayload(block, inst, false),
.optional_payload_unsafe_ptr => try sema.zirOptionalPayloadPtr(block, inst, false),
.optional_type => try sema.zirOptionalType(block, inst),
.optional_type_from_ptr_elem => try sema.zirOptionalTypeFromPtrElem(block, inst),
.param_type => try sema.zirParamType(block, inst),
.ptr_type => try sema.zirPtrType(block, inst),
.ptr_type_simple => try sema.zirPtrTypeSimple(block, inst),
.ptrtoint => try sema.zirPtrtoint(block, inst),
.ref => try sema.zirRef(block, inst),
.ret_ptr => try sema.zirRetPtr(block, inst),
.ret_type => try sema.zirRetType(block, inst),
.shl => try sema.zirShl(block, inst),
.shr => try sema.zirShr(block, inst),
.slice_end => try sema.zirSliceEnd(block, inst),
.slice_sentinel => try sema.zirSliceSentinel(block, inst),
.slice_start => try sema.zirSliceStart(block, inst),
.str => try sema.zirStr(block, inst),
.switch_block => try sema.zirSwitchBlock(block, inst, false, .none),
.switch_block_multi => try sema.zirSwitchBlockMulti(block, inst, false, .none),
.switch_block_else => try sema.zirSwitchBlock(block, inst, false, .@"else"),
.switch_block_else_multi => try sema.zirSwitchBlockMulti(block, inst, false, .@"else"),
.switch_block_under => try sema.zirSwitchBlock(block, inst, false, .under),
.switch_block_under_multi => try sema.zirSwitchBlockMulti(block, inst, false, .under),
.switch_block_ref => try sema.zirSwitchBlock(block, inst, true, .none),
.switch_block_ref_multi => try sema.zirSwitchBlockMulti(block, inst, true, .none),
.switch_block_ref_else => try sema.zirSwitchBlock(block, inst, true, .@"else"),
.switch_block_ref_else_multi => try sema.zirSwitchBlockMulti(block, inst, true, .@"else"),
.switch_block_ref_under => try sema.zirSwitchBlock(block, inst, true, .under),
.switch_block_ref_under_multi => try sema.zirSwitchBlockMulti(block, inst, true, .under),
.switch_capture => try sema.zirSwitchCapture(block, inst, false, false),
.switch_capture_ref => try sema.zirSwitchCapture(block, inst, false, true),
.switch_capture_multi => try sema.zirSwitchCapture(block, inst, true, false),
.switch_capture_multi_ref => try sema.zirSwitchCapture(block, inst, true, true),
.switch_capture_else => try sema.zirSwitchCaptureElse(block, inst, false),
.switch_capture_else_ref => try sema.zirSwitchCaptureElse(block, inst, true),
.type_info => try sema.zirTypeInfo(block, inst),
.size_of => try sema.zirSizeOf(block, inst),
.bit_size_of => try sema.zirBitSizeOf(block, inst),
.this => try sema.zirThis(block, inst),
.fence => try sema.zirFence(block, inst),
.ret_addr => try sema.zirRetAddr(block, inst),
.builtin_src => try sema.zirBuiltinSrc(block, inst),
.typeof => try sema.zirTypeof(block, inst),
.typeof_elem => try sema.zirTypeofElem(block, inst),
.typeof_peer => try sema.zirTypeofPeer(block, inst),
.log2_int_type => try sema.zirLog2IntType(block, inst),
.xor => try sema.zirBitwise(block, inst, .xor),
.struct_init_empty => try sema.zirStructInitEmpty(block, inst),
.struct_init => try sema.zirStructInit(block, inst),
.field_type => try sema.zirFieldType(block, inst),
.switch_capture => try sema.zirSwitchCapture(block, inst, false, false),
.switch_capture_ref => try sema.zirSwitchCapture(block, inst, false, true),
.switch_capture_multi => try sema.zirSwitchCapture(block, inst, true, false),
.switch_capture_multi_ref => try sema.zirSwitchCapture(block, inst, true, true),
.switch_capture_else => try sema.zirSwitchCaptureElse(block, inst, false),
.switch_capture_else_ref => try sema.zirSwitchCaptureElse(block, inst, true),
.type_info => try sema.zirTypeInfo(block, inst),
.size_of => try sema.zirSizeOf(block, inst),
.bit_size_of => try sema.zirBitSizeOf(block, inst),
.this => try sema.zirThis(block, inst),
.ret_addr => try sema.zirRetAddr(block, inst),
.builtin_src => try sema.zirBuiltinSrc(block, inst),
.typeof => try sema.zirTypeof(block, inst),
.typeof_elem => try sema.zirTypeofElem(block, inst),
.typeof_peer => try sema.zirTypeofPeer(block, inst),
.log2_int_type => try sema.zirLog2IntType(block, inst),
.typeof_log2_int_type => try sema.zirTypeofLog2IntType(block, inst),
.xor => try sema.zirBitwise(block, inst, .xor),
.struct_init_empty => try sema.zirStructInitEmpty(block, inst),
.struct_init => try sema.zirStructInit(block, inst),
.union_init_ptr => try sema.zirUnionInitPtr(block, inst),
.field_type => try sema.zirFieldType(block, inst),
.error_return_trace => try sema.zirErrorReturnTrace(block, inst),
.frame => try sema.zirFrame(block, inst),
.frame_address => try sema.zirFrameAddress(block, inst),
.ptr_to_int => try sema.zirPtrToInt(block, inst),
.align_of => try sema.zirAlignOf(block, inst),
.bool_to_int => try sema.zirBoolToInt(block, inst),
.embed_file => try sema.zirEmbedFile(block, inst),
.error_name => try sema.zirErrorName(block, inst),
.tag_name => try sema.zirTagName(block, inst),
.reify => try sema.zirReify(block, inst),
.type_name => try sema.zirTypeName(block, inst),
.frame_type => try sema.zirFrameType(block, inst),
.frame_size => try sema.zirFrameSize(block, inst),
.float_to_int => try sema.zirFloatToInt(block, inst),
.int_to_float => try sema.zirIntToFloat(block, inst),
.int_to_ptr => try sema.zirIntToPtr(block, inst),
.float_cast => try sema.zirFloatCast(block, inst),
.int_cast => try sema.zirIntCast(block, inst),
.err_set_cast => try sema.zirErrSetCast(block, inst),
.ptr_cast => try sema.zirPtrCast(block, inst),
.truncate => try sema.zirTruncate(block, inst),
.align_cast => try sema.zirAlignCast(block, inst),
.has_decl => try sema.zirHasDecl(block, inst),
.has_field => try sema.zirHasField(block, inst),
.clz => try sema.zirClz(block, inst),
.ctz => try sema.zirCtz(block, inst),
.pop_count => try sema.zirPopCount(block, inst),
.byte_swap => try sema.zirByteSwap(block, inst),
.bit_reverse => try sema.zirBitReverse(block, inst),
.div_exact => try sema.zirDivExact(block, inst),
.div_floor => try sema.zirDivFloor(block, inst),
.div_trunc => try sema.zirDivTrunc(block, inst),
.mod => try sema.zirMod(block, inst),
.rem => try sema.zirRem(block, inst),
.shl_exact => try sema.zirShlExact(block, inst),
.shr_exact => try sema.zirShrExact(block, inst),
.bit_offset_of => try sema.zirBitOffsetOf(block, inst),
.byte_offset_of => try sema.zirByteOffsetOf(block, inst),
.cmpxchg_strong => try sema.zirCmpxchg(block, inst),
.cmpxchg_weak => try sema.zirCmpxchg(block, inst),
.splat => try sema.zirSplat(block, inst),
.reduce => try sema.zirReduce(block, inst),
.shuffle => try sema.zirShuffle(block, inst),
.atomic_load => try sema.zirAtomicLoad(block, inst),
.atomic_rmw => try sema.zirAtomicRmw(block, inst),
.atomic_store => try sema.zirAtomicStore(block, inst),
.mul_add => try sema.zirMulAdd(block, inst),
.builtin_call => try sema.zirBuiltinCall(block, inst),
.field_ptr_type => try sema.zirFieldPtrType(block, inst),
.field_parent_ptr => try sema.zirFieldParentPtr(block, inst),
.memcpy => try sema.zirMemcpy(block, inst),
.memset => try sema.zirMemset(block, inst),
.builtin_async_call => try sema.zirBuiltinAsyncCall(block, inst),
.extended => try sema.zirExtended(block, inst),
.struct_decl => try sema.zirStructDecl(block, inst, .Auto),
.struct_decl_packed => try sema.zirStructDecl(block, inst, .Packed),
.struct_decl_extern => try sema.zirStructDecl(block, inst, .Extern),
.enum_decl => try sema.zirEnumDecl(block, inst, false),
.sqrt => try sema.zirUnaryMath(block, inst),
.sin => try sema.zirUnaryMath(block, inst),
.cos => try sema.zirUnaryMath(block, inst),
.exp => try sema.zirUnaryMath(block, inst),
.exp2 => try sema.zirUnaryMath(block, inst),
.log => try sema.zirUnaryMath(block, inst),
.log2 => try sema.zirUnaryMath(block, inst),
.log10 => try sema.zirUnaryMath(block, inst),
.fabs => try sema.zirUnaryMath(block, inst),
.floor => try sema.zirUnaryMath(block, inst),
.ceil => try sema.zirUnaryMath(block, inst),
.trunc => try sema.zirUnaryMath(block, inst),
.round => try sema.zirUnaryMath(block, inst),
.struct_decl => try sema.zirStructDecl(block, inst, .Auto),
.struct_decl_packed => try sema.zirStructDecl(block, inst, .Packed),
.struct_decl_extern => try sema.zirStructDecl(block, inst, .Extern),
.enum_decl => try sema.zirEnumDecl(block, inst, false),
.enum_decl_nonexhaustive => try sema.zirEnumDecl(block, inst, true),
.union_decl => try sema.zirUnionDecl(block, inst),
.opaque_decl => try sema.zirOpaqueDecl(block, inst),
.union_decl => try sema.zirUnionDecl(block, inst),
.opaque_decl => try sema.zirOpaqueDecl(block, inst),
.add => try sema.zirArithmetic(block, inst),
.add => try sema.zirArithmetic(block, inst),
.addwrap => try sema.zirArithmetic(block, inst),
.div => try sema.zirArithmetic(block, inst),
.div => try sema.zirArithmetic(block, inst),
.mod_rem => try sema.zirArithmetic(block, inst),
.mul => try sema.zirArithmetic(block, inst),
.mul => try sema.zirArithmetic(block, inst),
.mulwrap => try sema.zirArithmetic(block, inst),
.sub => try sema.zirArithmetic(block, inst),
.sub => try sema.zirArithmetic(block, inst),
.subwrap => try sema.zirArithmetic(block, inst),
.add_with_overflow => try sema.zirOverflowArithmetic(block, inst),
@ -294,15 +362,17 @@ pub fn analyzeBody(
// Instructions that we know to *always* be noreturn based solely on their tag.
// These functions match the return type of analyzeBody so that we can
// tail call them here.
.condbr => return sema.zirCondbr(block, inst),
.@"break" => return sema.zirBreak(block, inst),
.break_inline => return inst,
.compile_error => return sema.zirCompileError(block, inst),
.ret_coerce => return sema.zirRetTok(block, inst, true),
.ret_node => return sema.zirRetNode(block, inst),
.ret_tok => return sema.zirRetTok(block, inst, false),
.break_inline => return inst,
.condbr => return sema.zirCondbr(block, inst),
.@"break" => return sema.zirBreak(block, inst),
.compile_error => return sema.zirCompileError(block, inst),
.ret_coerce => return sema.zirRetTok(block, inst, true),
.ret_node => return sema.zirRetNode(block, inst),
.ret_tok => return sema.zirRetTok(block, inst, false),
.@"unreachable" => return sema.zirUnreachable(block, inst),
.repeat => return sema.zirRepeat(block, inst),
.repeat => return sema.zirRepeat(block, inst),
.panic => return sema.zirPanic(block, inst),
// zig fmt: on
// Instructions that we know can *never* be noreturn based solely on
// their tag. We avoid needlessly checking if they are noreturn and
@ -313,6 +383,10 @@ pub fn analyzeBody(
try sema.zirBreakpoint(block, inst);
continue;
},
.fence => {
try sema.zirFence(block, inst);
continue;
},
.dbg_stmt_node => {
try sema.zirDbgStmtNode(block, inst);
continue;
@ -365,6 +439,22 @@ pub fn analyzeBody(
try sema.zirExport(block, inst);
continue;
},
.set_align_stack => {
try sema.zirSetAlignStack(block, inst);
continue;
},
.set_cold => {
try sema.zirSetAlignStack(block, inst);
continue;
},
.set_float_mode => {
try sema.zirSetFloatMode(block, inst);
continue;
},
.set_runtime_safety => {
try sema.zirSetRuntimeSafety(block, inst);
continue;
},
// Special case instructions to handle comptime control flow.
.repeat_inline => {
@ -1382,6 +1472,13 @@ fn zirRepeat(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!
return always_noreturn;
}
fn zirPanic(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Zir.Inst.Index {
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const src: LazySrcLoc = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirPanic", .{});
//return always_noreturn;
}
fn zirLoop(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const tracy = trace(@src());
defer tracy.end();
@ -1443,6 +1540,16 @@ fn zirLoop(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) InnerE
return sema.analyzeBlockBody(parent_block, src, &child_block, merges);
}
fn zirCImport(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const tracy = trace(@src());
defer tracy.end();
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
return sema.mod.fail(&parent_block.base, src, "TODO: implement Sema.zirCImport", .{});
}
fn zirBlock(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const tracy = trace(@src());
defer tracy.end();
@ -1597,6 +1704,30 @@ fn zirExport(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!
try sema.mod.analyzeExport(&block.base, src, export_name, actual_fn.owner_decl);
}
fn zirSetAlignStack(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!void {
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const src: LazySrcLoc = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirSetAlignStack", .{});
}
fn zirSetCold(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!void {
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const src: LazySrcLoc = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirSetCold", .{});
}
fn zirSetFloatMode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!void {
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const src: LazySrcLoc = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirSetFloatMode", .{});
}
fn zirSetRuntimeSafety(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!void {
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const src: LazySrcLoc = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirSetRuntimeSafety", .{});
}
fn zirBreakpoint(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!void {
const tracy = trace(@src());
defer tracy.end();
@ -1607,6 +1738,12 @@ fn zirBreakpoint(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerEr
_ = try block.addNoOp(src, Type.initTag(.void), .breakpoint);
}
fn zirFence(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!void {
const src_node = sema.code.instructions.items(.data)[inst].node;
const src: LazySrcLoc = .{ .node_offset = src_node };
return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirFence", .{});
}
fn zirBreak(sema: *Sema, start_block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Zir.Inst.Index {
const tracy = trace(@src());
defer tracy.end();
@ -3874,10 +4011,15 @@ fn validateSwitchNoRange(
return sema.mod.failWithOwnedErrorMsg(&block.base, msg);
}
fn zirHasDecl(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const tracy = trace(@src());
defer tracy.end();
fn zirHasField(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO implement zirHasField", .{});
}
fn zirHasDecl(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
const src = inst_data.src();
@ -4382,16 +4524,13 @@ fn zirThis(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*I
const src: LazySrcLoc = .{ .node_offset = src_node };
return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirThis", .{});
}
fn zirFence(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const src_node = sema.code.instructions.items(.data)[inst].node;
const src: LazySrcLoc = .{ .node_offset = src_node };
return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirFence", .{});
}
fn zirRetAddr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const src_node = sema.code.instructions.items(.data)[inst].node;
const src: LazySrcLoc = .{ .node_offset = src_node };
return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirRetAddr", .{});
}
fn zirBuiltinSrc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const src_node = sema.code.instructions.items(.data)[inst].node;
const src: LazySrcLoc = .{ .node_offset = src_node };
@ -4419,6 +4558,12 @@ fn zirTypeofElem(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerEr
return sema.mod.constType(sema.arena, src, elem_ty);
}
fn zirTypeofLog2IntType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirTypeofLog2IntType", .{});
}
fn zirLog2IntType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const src = inst_data.src();
@ -4827,6 +4972,12 @@ fn zirStructInitEmpty(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) In
});
}
fn zirUnionInitPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirUnionInitPtr", .{});
}
fn zirStructInit(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
@ -4839,6 +4990,380 @@ fn zirFieldType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerErr
return sema.mod.fail(&block.base, src, "TODO: Sema.zirFieldType", .{});
}
fn zirErrorReturnTrace(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirErrorReturnTrace", .{});
}
fn zirFrame(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirFrame", .{});
}
fn zirFrameAddress(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirFrameAddress", .{});
}
fn zirPtrToInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirPtrToInt", .{});
}
fn zirAlignOf(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirAlignOf", .{});
}
fn zirBoolToInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirBoolToInt", .{});
}
fn zirEmbedFile(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirEmbedFile", .{});
}
fn zirErrorName(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirErrorName", .{});
}
fn zirUnaryMath(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirUnaryMath", .{});
}
fn zirTagName(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirTagName", .{});
}
fn zirReify(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirReify", .{});
}
fn zirTypeName(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirTypeName", .{});
}
fn zirFrameType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirFrameType", .{});
}
fn zirFrameSize(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirFrameSize", .{});
}
fn zirFloatToInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirFloatToInt", .{});
}
fn zirIntToFloat(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirIntToFloat", .{});
}
fn zirIntToPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirIntToPtr", .{});
}
fn zirFloatCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirFloatCast", .{});
}
fn zirIntCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirIntCast", .{});
}
fn zirErrSetCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirErrSetCast", .{});
}
fn zirPtrCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirPtrCast", .{});
}
fn zirTruncate(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirTruncate", .{});
}
fn zirAlignCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirAlignCast", .{});
}
fn zirClz(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirClz", .{});
}
fn zirCtz(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirCtz", .{});
}
fn zirPopCount(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirPopCount", .{});
}
fn zirByteSwap(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirByteSwap", .{});
}
fn zirBitReverse(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirBitReverse", .{});
}
fn zirDivExact(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirDivExact", .{});
}
fn zirDivFloor(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirDivFloor", .{});
}
fn zirDivTrunc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirDivTrunc", .{});
}
fn zirMod(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirMod", .{});
}
fn zirRem(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirRem", .{});
}
fn zirShlExact(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirShlExact", .{});
}
fn zirShrExact(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirShrExact", .{});
}
fn zirBitOffsetOf(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirBitOffsetOf", .{});
}
fn zirByteOffsetOf(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirByteOffsetOf", .{});
}
fn zirCmpxchg(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirCmpxchg", .{});
}
fn zirSplat(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirSplat", .{});
}
fn zirReduce(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirReduce", .{});
}
fn zirShuffle(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirShuffle", .{});
}
fn zirAtomicLoad(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirAtomicLoad", .{});
}
fn zirAtomicRmw(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirAtomicRmw", .{});
}
fn zirAtomicStore(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirAtomicStore", .{});
}
fn zirMulAdd(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirMulAdd", .{});
}
fn zirBuiltinCall(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirBuiltinCall", .{});
}
fn zirFieldPtrType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirFieldPtrType", .{});
}
fn zirFieldParentPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirFieldParentPtr", .{});
}
fn zirMemcpy(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirMemcpy", .{});
}
fn zirMemset(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirMemset", .{});
}
fn zirBuiltinAsyncCall(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO: Sema.zirBuiltinAsyncCall", .{});
}
fn zirExtended(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const extended = sema.code.instructions.items(.data)[inst].extended;
switch (extended.opcode) {
// zig fmt: off
.c_undef => return sema.zirCUndef( block, inst, extended),
.c_include => return sema.zirCInclude( block, inst, extended),
.c_define => return sema.zirCDefine( block, inst, extended),
.wasm_memory_size => return sema.zirWasmMemorySize( block, inst, extended),
.wasm_memory_grow => return sema.zirWasmMemoryGrow( block, inst, extended),
// zig fmt: on
}
}
fn zirCUndef(
sema: *Sema,
block: *Scope.Block,
inst: Zir.Inst.Index,
extended: Zir.Inst.Extended.InstData,
) InnerError!*Inst {
const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
const src: LazySrcLoc = .{ .node_offset = extra.node };
return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirCUndef", .{});
}
fn zirCInclude(
sema: *Sema,
block: *Scope.Block,
inst: Zir.Inst.Index,
extended: Zir.Inst.Extended.InstData,
) InnerError!*Inst {
const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
const src: LazySrcLoc = .{ .node_offset = extra.node };
return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirCInclude", .{});
}
fn zirCDefine(
sema: *Sema,
block: *Scope.Block,
inst: Zir.Inst.Index,
extended: Zir.Inst.Extended.InstData,
) InnerError!*Inst {
const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
const src: LazySrcLoc = .{ .node_offset = extra.node };
return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirCDefine", .{});
}
fn zirWasmMemorySize(
sema: *Sema,
block: *Scope.Block,
inst: Zir.Inst.Index,
extended: Zir.Inst.Extended.InstData,
) InnerError!*Inst {
const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
const src: LazySrcLoc = .{ .node_offset = extra.node };
return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirWasmMemorySize", .{});
}
fn zirWasmMemoryGrow(
sema: *Sema,
block: *Scope.Block,
inst: Zir.Inst.Index,
extended: Zir.Inst.Extended.InstData,
) InnerError!*Inst {
const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
const src: LazySrcLoc = .{ .node_offset = extra.node };
return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirWasmMemoryGrow", .{});
}
fn requireFunctionBlock(sema: *Sema, block: *Scope.Block, src: LazySrcLoc) !void {
if (sema.func == null) {
return sema.mod.fail(&block.base, src, "instruction illegal outside function body", .{});

View File

@ -274,9 +274,6 @@ pub const Inst = struct {
/// Uses the `bin` union field.
/// LHS is destination element type, RHS is result pointer.
coerce_result_ptr,
/// Emit an error message and fail compilation.
/// Uses the `un_node` field.
compile_error,
/// Log compile time variables and emit an error message.
/// Uses the `pl_node` union field. The AST node is the compile log builtin call.
/// The payload is `MultiOp`.
@ -339,9 +336,6 @@ pub const Inst = struct {
/// Same as `elem_val` except also stores a source location node.
/// Uses the `pl_node` union field. AST node is a[b] syntax. Payload is `Bin`.
elem_val_node,
/// This instruction has been deleted late in the astgen phase. It must
/// be ignored, and the corresponding `Data` is undefined.
elided,
/// Emits a compile error if the operand is not `void`.
/// Uses the `un_node` field.
ensure_result_used,
@ -391,9 +385,6 @@ pub const Inst = struct {
func_extra,
/// Same as `func_extra` but the function is variadic.
func_extra_var_args,
/// Implements the `@hasDecl` builtin.
/// Uses the `pl_node` union field. Payload is `Bin`.
has_decl,
/// Implements the `@import` builtin.
/// Uses the `str_tok` field.
import,
@ -412,10 +403,6 @@ pub const Inst = struct {
/// Make an integer type out of signedness and bit count.
/// Payload is `int_type`
int_type,
/// Convert an error type to `u16`
error_to_int,
/// Convert a `u16` to `anyerror`
int_to_error,
/// Return a boolean false if an optional is null. `x != null`
/// Uses the `un_node` field.
is_non_null,
@ -498,16 +485,6 @@ pub const Inst = struct {
/// Same as `ret_tok` except the operand needs to get coerced to the function's
/// return type.
ret_coerce,
/// Changes the maximum number of backwards branches that compile-time
/// code execution can use before giving up and making a compile error.
/// Uses the `un_node` union field.
set_eval_branch_quota,
/// Integer shift-left. Zeroes are shifted in from the right hand side.
/// Uses the `pl_node` union field. Payload is `Bin`.
shl,
/// Integer shift-right. Arithmetic or logical depending on the signedness of the integer type.
/// Uses the `pl_node` union field. Payload is `Bin`.
shr,
/// Create a pointer type that does not have a sentinel, alignment, or bit range specified.
/// Uses the `ptr_type_simple` union field.
ptr_type_simple,
@ -573,6 +550,10 @@ pub const Inst = struct {
/// of one or more params.
/// Uses the `pl_node` field. AST node is the `@TypeOf` call. Payload is `MultiOp`.
typeof_peer,
/// Given a value, look at the type of it, which must be an integer type.
/// Returns the integer type for the RHS of a shift operation.
/// Uses the `un_node` field.
typeof_log2_int_type,
/// Given an integer type, returns the integer type for the RHS of a shift operation.
/// Uses the `un_node` field.
log2_int_type,
@ -712,12 +693,10 @@ pub const Inst = struct {
/// struct value.
/// Uses the `pl_node` field. Payload is `StructInit`.
struct_init,
/// Converts an integer into an enum value.
/// Uses `pl_node` with payload `Bin`. `lhs` is enum type, `rhs` is operand.
int_to_enum,
/// Converts an enum value into an integer. Resulting type will be the tag type
/// of the enum. Uses `un_node`.
enum_to_int,
/// Given a pointer to a union and a comptime known field name, activates that field
/// and returns a pointer to it.
/// Uses the `pl_node` field. Payload is `UnionInitPtr`.
union_init_ptr,
/// Implements the `@typeInfo` builtin. Uses `un_node`.
type_info,
/// Implements the `@sizeOf` builtin. Uses `un_node`.
@ -741,6 +720,224 @@ pub const Inst = struct {
/// Implements the `@shlWithOverflow` builtin. Uses `pl_node` with `OverflowArithmetic`.
shl_with_overflow,
/// Implements the `@errorReturnTrace` builtin.
/// Uses the `un_node` field.
error_return_trace,
/// Implements the `@frame` builtin.
/// Uses the `un_node` field.
frame,
/// Implements the `@frameAddress` builtin.
/// Uses the `un_node` field.
frame_address,
/// Implement builtin `@ptrToInt`. Uses `un_node`.
ptr_to_int,
/// Implement builtin `@errToInt`. Uses `un_node`.
error_to_int,
/// Implement builtin `@intToError`. Uses `un_node`.
int_to_error,
/// Emit an error message and fail compilation.
/// Uses the `un_node` field.
compile_error,
/// Changes the maximum number of backwards branches that compile-time
/// code execution can use before giving up and making a compile error.
/// Uses the `un_node` union field.
set_eval_branch_quota,
/// Converts an enum value into an integer. Resulting type will be the tag type
/// of the enum. Uses `un_node`.
enum_to_int,
/// Implement builtin `@alignOf`. Uses `un_node`.
align_of,
/// Implement builtin `@boolToInt`. Uses `un_node`.
bool_to_int,
/// Implement builtin `@embedFile`. Uses `un_node`.
embed_file,
/// Implement builtin `@errorName`. Uses `un_node`.
error_name,
/// Implement builtin `@panic`. Uses `un_node`.
panic,
/// Implement builtin `@setAlignStack`. Uses `un_node`.
set_align_stack,
/// Implement builtin `@setCold`. Uses `un_node`.
set_cold,
/// Implement builtin `@setFloatMode`. Uses `un_node`.
set_float_mode,
/// Implement builtin `@setRuntimeSafety`. Uses `un_node`.
set_runtime_safety,
/// Implement builtin `@sqrt`. Uses `un_node`.
sqrt,
/// Implement builtin `@sin`. Uses `un_node`.
sin,
/// Implement builtin `@cos`. Uses `un_node`.
cos,
/// Implement builtin `@exp`. Uses `un_node`.
exp,
/// Implement builtin `@exp2`. Uses `un_node`.
exp2,
/// Implement builtin `@log`. Uses `un_node`.
log,
/// Implement builtin `@log2`. Uses `un_node`.
log2,
/// Implement builtin `@log10`. Uses `un_node`.
log10,
/// Implement builtin `@fabs`. Uses `un_node`.
fabs,
/// Implement builtin `@floor`. Uses `un_node`.
floor,
/// Implement builtin `@ceil`. Uses `un_node`.
ceil,
/// Implement builtin `@trunc`. Uses `un_node`.
trunc,
/// Implement builtin `@round`. Uses `un_node`.
round,
/// Implement builtin `@tagName`. Uses `un_node`.
tag_name,
/// Implement builtin `@Type`. Uses `un_node`.
reify,
/// Implement builtin `@typeName`. Uses `un_node`.
type_name,
/// Implement builtin `@Frame`. Uses `un_node`.
frame_type,
/// Implement builtin `@frameSize`. Uses `un_node`.
frame_size,
/// Implements the `@floatToInt` builtin.
/// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
float_to_int,
/// Implements the `@intToFloat` builtin.
/// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
int_to_float,
/// Implements the `@intToPtr` builtin.
/// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
int_to_ptr,
/// Converts an integer into an enum value.
/// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
int_to_enum,
/// Implements the `@floatCast` builtin.
/// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
float_cast,
/// Implements the `@intCast` builtin.
/// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
int_cast,
/// Implements the `@errSetCast` builtin.
/// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
err_set_cast,
/// Implements the `@ptrCast` builtin.
/// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
ptr_cast,
/// Implements the `@truncate` builtin.
/// Uses `pl_node` with payload `Bin`. `lhs` is dest type, `rhs` is operand.
truncate,
/// Implements the `@alignCast` builtin.
/// Uses `pl_node` with payload `Bin`. `lhs` is dest alignment, `rhs` is operand.
align_cast,
/// Implements the `@hasDecl` builtin.
/// Uses the `pl_node` union field. Payload is `Bin`.
has_decl,
/// Implements the `@hasField` builtin.
/// Uses the `pl_node` union field. Payload is `Bin`.
has_field,
/// Implements the `@clz` builtin. Uses the `un_node` union field.
clz,
/// Implements the `@ctz` builtin. Uses the `un_node` union field.
ctz,
/// Implements the `@popCount` builtin. Uses the `un_node` union field.
pop_count,
/// Implements the `@byteSwap` builtin. Uses the `un_node` union field.
byte_swap,
/// Implements the `@bitReverse` builtin. Uses the `un_node` union field.
bit_reverse,
/// Implements the `@divExact` builtin.
/// Uses the `pl_node` union field with payload `Bin`.
div_exact,
/// Implements the `@divFloor` builtin.
/// Uses the `pl_node` union field with payload `Bin`.
div_floor,
/// Implements the `@divTrunc` builtin.
/// Uses the `pl_node` union field with payload `Bin`.
div_trunc,
/// Implements the `@mod` builtin.
/// Uses the `pl_node` union field with payload `Bin`.
mod,
/// Implements the `@rem` builtin.
/// Uses the `pl_node` union field with payload `Bin`.
rem,
/// Integer shift-left. Zeroes are shifted in from the right hand side.
/// Uses the `pl_node` union field. Payload is `Bin`.
shl,
/// Implements the `@shlExact` builtin.
/// Uses the `pl_node` union field with payload `Bin`.
shl_exact,
/// Integer shift-right. Arithmetic or logical depending on the signedness of the integer type.
/// Uses the `pl_node` union field. Payload is `Bin`.
shr,
/// Implements the `@shrExact` builtin.
/// Uses the `pl_node` union field with payload `Bin`.
shr_exact,
/// Implements the `@bitOffsetOf` builtin.
/// Uses the `pl_node` union field with payload `Bin`.
bit_offset_of,
/// Implements the `@byteOffsetOf` builtin.
/// Uses the `pl_node` union field with payload `Bin`.
byte_offset_of,
/// Implements the `@cmpxchgStrong` builtin.
/// Uses the `pl_node` union field with payload `Cmpxchg`.
cmpxchg_strong,
/// Implements the `@cmpxchgWeak` builtin.
/// Uses the `pl_node` union field with payload `Cmpxchg`.
cmpxchg_weak,
/// Implements the `@splat` builtin.
/// Uses the `pl_node` union field with payload `Bin`.
splat,
/// Implements the `@reduce` builtin.
/// Uses the `pl_node` union field with payload `Bin`.
reduce,
/// Implements the `@shuffle` builtin.
/// Uses the `pl_node` union field with payload `Shuffle`.
shuffle,
/// Implements the `@atomicLoad` builtin.
/// Uses the `pl_node` union field with payload `Bin`.
atomic_load,
/// Implements the `@atomicRmw` builtin.
/// Uses the `pl_node` union field with payload `AtomicRmw`.
atomic_rmw,
/// Implements the `@atomicStore` builtin.
/// Uses the `pl_node` union field with payload `AtomicStore`.
atomic_store,
/// Implements the `@mulAdd` builtin.
/// Uses the `pl_node` union field with payload `MulAdd`.
mul_add,
/// Implements the `@call` builtin.
/// Uses the `pl_node` union field with payload `BuiltinCall`.
builtin_call,
/// Given a type and a field name, returns a pointer to the field type.
/// Assumed to be part of a `@fieldParentPtr` builtin call.
/// Uses the `bin` union field. LHS is type, RHS is field name.
field_ptr_type,
/// Implements the `@fieldParentPtr` builtin.
/// Uses the `pl_node` union field with payload `FieldParentPtr`.
field_parent_ptr,
/// Implements the `@memcpy` builtin.
/// Uses the `pl_node` union field with payload `Memcpy`.
memcpy,
/// Implements the `@memset` builtin.
/// Uses the `pl_node` union field with payload `Memset`.
memset,
/// Implements the `@asyncCall` builtin.
/// Uses the `pl_node` union field with payload `AsyncCall`.
builtin_async_call,
/// Implements the `@cImport` builtin.
/// Uses the `pl_node` union field with payload `Block`.
c_import,
/// The ZIR instruction tag is one of the `Extended` ones.
/// Uses the `extended` union field.
extended,
/// Returns whether the instruction is one of the control flow "noreturn" types.
/// Function calls do not count.
pub fn isNoReturn(tag: Tag) bool {
@ -876,11 +1073,11 @@ pub const Inst = struct {
.slice_sentinel,
.import,
.typeof_peer,
.typeof_log2_int_type,
.log2_int_type,
.resolve_inferred_alloc,
.set_eval_branch_quota,
.compile_log,
.elided,
.switch_capture,
.switch_capture_ref,
.switch_capture_multi,
@ -902,6 +1099,7 @@ pub const Inst = struct {
.validate_struct_init_ptr,
.struct_init_empty,
.struct_init,
.union_init_ptr,
.field_type,
.int_to_enum,
.enum_to_int,
@ -916,6 +1114,77 @@ pub const Inst = struct {
.sub_with_overflow,
.mul_with_overflow,
.shl_with_overflow,
.error_return_trace,
.frame,
.frame_address,
.ptr_to_int,
.align_of,
.bool_to_int,
.embed_file,
.error_name,
.set_align_stack,
.set_cold,
.set_float_mode,
.set_runtime_safety,
.sqrt,
.sin,
.cos,
.exp,
.exp2,
.log,
.log2,
.log10,
.fabs,
.floor,
.ceil,
.trunc,
.round,
.tag_name,
.reify,
.type_name,
.frame_type,
.frame_size,
.float_to_int,
.int_to_float,
.int_to_ptr,
.float_cast,
.int_cast,
.err_set_cast,
.ptr_cast,
.truncate,
.align_cast,
.has_field,
.clz,
.ctz,
.pop_count,
.byte_swap,
.bit_reverse,
.div_exact,
.div_floor,
.div_trunc,
.mod,
.rem,
.shl_exact,
.shr_exact,
.bit_offset_of,
.byte_offset_of,
.cmpxchg_strong,
.cmpxchg_weak,
.splat,
.reduce,
.shuffle,
.atomic_load,
.atomic_rmw,
.atomic_store,
.mul_add,
.builtin_call,
.field_ptr_type,
.field_parent_ptr,
.memcpy,
.memset,
.builtin_async_call,
.c_import,
.extended,
=> false,
.@"break",
@ -929,11 +1198,33 @@ pub const Inst = struct {
.@"unreachable",
.repeat,
.repeat_inline,
.panic,
=> true,
};
}
};
/// Rarer instructions are here; ones that do not fit in the 8-bit `Tag` enum.
/// `noreturn` instructions may not go here; they must be part of the main `Tag` enum.
pub const Extended = enum(u16) {
/// `operand` is payload index to `UnNode`.
c_undef,
/// `operand` is payload index to `UnNode`.
c_include,
/// `operand` is payload index to `BinNode`.
c_define,
/// `operand` is payload index to `UnNode`.
wasm_memory_size,
/// `operand` is payload index to `BinNode`.
wasm_memory_grow,
pub const InstData = struct {
opcode: Extended,
small: u16,
operand: u32,
};
};
/// The position of a ZIR instruction within the `Zir` instructions array.
pub const Index = u32;
@ -1002,6 +1293,14 @@ pub const Inst = struct {
single_const_pointer_to_comptime_int_type,
const_slice_u8_type,
enum_literal_type,
manyptr_u8_type,
manyptr_const_u8_type,
atomic_ordering_type,
atomic_rmw_op_type,
calling_convention_type,
float_mode_type,
reduce_op_type,
call_options_type,
/// `undefined` (untyped)
undef,
@ -1025,6 +1324,8 @@ pub const Inst = struct {
zero_usize,
/// `1` (usize)
one_usize,
/// `std.builtin.CallingConvention.C`
calling_convention_c,
_,
@ -1191,6 +1492,38 @@ pub const Inst = struct {
.ty = Type.initTag(.type),
.val = Value.initTag(.enum_literal_type),
},
.manyptr_u8_type = .{
.ty = Type.initTag(.type),
.val = Value.initTag(.manyptr_u8_type),
},
.manyptr_const_u8_type = .{
.ty = Type.initTag(.type),
.val = Value.initTag(.manyptr_const_u8_type),
},
.atomic_ordering_type = .{
.ty = Type.initTag(.type),
.val = Value.initTag(.atomic_ordering_type),
},
.atomic_rmw_op_type = .{
.ty = Type.initTag(.type),
.val = Value.initTag(.atomic_rmw_op_type),
},
.calling_convention_type = .{
.ty = Type.initTag(.type),
.val = Value.initTag(.calling_convention_type),
},
.float_mode_type = .{
.ty = Type.initTag(.type),
.val = Value.initTag(.float_mode_type),
},
.reduce_op_type = .{
.ty = Type.initTag(.type),
.val = Value.initTag(.reduce_op_type),
},
.call_options_type = .{
.ty = Type.initTag(.type),
.val = Value.initTag(.call_options_type),
},
.undef = .{
.ty = Type.initTag(.@"undefined"),
@ -1236,13 +1569,27 @@ pub const Inst = struct {
.ty = Type.initTag(.empty_struct_literal),
.val = Value.initTag(.empty_struct_value),
},
.calling_convention_c = .{
.ty = Type.initTag(.calling_convention),
.val = .{ .ptr_otherwise = &calling_convention_c_payload.base },
},
});
};
/// We would like this to be const but `Value` wants a mutable pointer for
/// its payload field. Nothing should mutate this though.
var calling_convention_c_payload: Value.Payload.U32 = .{
.base = .{ .tag = .enum_field_index },
.data = @enumToInt(std.builtin.CallingConvention.C),
};
/// All instructions have an 8-byte payload, which is contained within
/// this union. `Tag` determines which union field is active, as well as
/// how to interpret the data within.
pub const Data = union {
/// Used for `Tag.extended`. The extended opcode determines the meaning
/// of the `small` and `operand` fields.
extended: Extended.InstData,
/// Used for unary operators, with an AST node source location.
un_node: struct {
/// Offset from Decl AST node index.
@ -1462,6 +1809,12 @@ pub const Inst = struct {
args_len: u32,
};
pub const BuiltinCall = struct {
options: Ref,
callee: Ref,
args: Ref,
};
/// This data is stored inside extra, with two sets of trailing `Ref`:
/// * 0. the then body, according to `then_body_len`.
/// * 1. the else body, according to `else_body_len`.
@ -1510,6 +1863,17 @@ pub const Inst = struct {
rhs: Ref,
};
pub const BinNode = struct {
node: i32,
lhs: Ref,
rhs: Ref,
};
pub const UnNode = struct {
node: i32,
operand: Ref,
};
/// This form is supported when there are no ranges, and exactly 1 item per block.
/// Depending on zir tag and len fields, extra fields trail
/// this one in the extra array.
@ -1679,6 +2043,70 @@ pub const Inst = struct {
ptr: Ref,
};
pub const Cmpxchg = struct {
ptr: Ref,
expected_value: Ref,
new_value: Ref,
success_order: Ref,
fail_order: Ref,
};
pub const AtomicRmw = struct {
ptr: Ref,
operation: Ref,
operand: Ref,
ordering: Ref,
};
pub const UnionInitPtr = struct {
union_type: Ref,
field_name: Ref,
};
pub const AtomicStore = struct {
ptr: Ref,
operand: Ref,
ordering: Ref,
};
pub const MulAdd = struct {
mulend1: Ref,
mulend2: Ref,
addend: Ref,
};
pub const FieldParentPtr = struct {
parent_type: Ref,
field_name: Ref,
field_ptr: Ref,
};
pub const Memcpy = struct {
dest: Ref,
source: Ref,
byte_count: Ref,
};
pub const Memset = struct {
dest: Ref,
byte: Ref,
byte_count: Ref,
};
pub const Shuffle = struct {
elem_type: Ref,
a: Ref,
b: Ref,
mask: Ref,
};
pub const AsyncCall = struct {
frame_buffer: Ref,
result_ptr: Ref,
fn_ptr: Ref,
args: Ref,
};
/// Trailing: `CompileErrors.Item` for each `items_len`.
pub const CompileErrors = struct {
items_len: u32,
@ -1749,13 +2177,11 @@ const Writer = struct {
.negate_wrap,
.call_none,
.call_none_chkused,
.compile_error,
.load,
.ensure_result_used,
.ensure_result_non_error,
.ptrtoint,
.ret_node,
.set_eval_branch_quota,
.resolve_inferred_alloc,
.optional_type,
.optional_type_from_ptr_elem,
@ -1769,8 +2195,6 @@ const Writer = struct {
.err_union_payload_unsafe_ptr,
.err_union_code,
.err_union_code_ptr,
.int_to_error,
.error_to_int,
.is_non_null,
.is_null,
.is_non_null_ptr,
@ -1780,11 +2204,49 @@ const Writer = struct {
.typeof,
.typeof_elem,
.struct_init_empty,
.enum_to_int,
.type_info,
.size_of,
.bit_size_of,
.typeof_log2_int_type,
.log2_int_type,
.ptr_to_int,
.error_to_int,
.int_to_error,
.compile_error,
.set_eval_branch_quota,
.enum_to_int,
.align_of,
.bool_to_int,
.embed_file,
.error_name,
.panic,
.set_align_stack,
.set_cold,
.set_float_mode,
.set_runtime_safety,
.sqrt,
.sin,
.cos,
.exp,
.exp2,
.log,
.log2,
.log10,
.fabs,
.floor,
.ceil,
.trunc,
.round,
.tag_name,
.reify,
.type_name,
.frame_type,
.frame_size,
.clz,
.ctz,
.pop_count,
.byte_swap,
.bit_reverse,
=> try self.writeUnNode(stream, inst),
.ref,
@ -1805,7 +2267,6 @@ const Writer = struct {
.float => try self.writeFloat(stream, inst),
.float128 => try self.writeFloat128(stream, inst),
.str => try self.writeStr(stream, inst),
.elided => try stream.writeAll(")"),
.int_type => try self.writeIntType(stream, inst),
.@"break",
@ -1824,7 +2285,20 @@ const Writer = struct {
.slice_sentinel,
.union_decl,
.struct_init,
.union_init_ptr,
.field_type,
.cmpxchg_strong,
.cmpxchg_weak,
.shuffle,
.atomic_rmw,
.atomic_store,
.mul_add,
.builtin_call,
.field_ptr_type,
.field_parent_ptr,
.memcpy,
.memset,
.builtin_async_call,
=> try self.writePlNode(stream, inst),
.add_with_overflow,
@ -1851,9 +2325,12 @@ const Writer = struct {
.cmp_neq,
.div,
.has_decl,
.has_field,
.mod_rem,
.shl,
.shl_exact,
.shr,
.shr_exact,
.xor,
.store_node,
.error_union_type,
@ -1861,7 +2338,26 @@ const Writer = struct {
.merge_error_sets,
.bit_and,
.bit_or,
.float_to_int,
.int_to_float,
.int_to_ptr,
.int_to_enum,
.float_cast,
.int_cast,
.err_set_cast,
.ptr_cast,
.truncate,
.align_cast,
.div_exact,
.div_floor,
.div_trunc,
.mod,
.rem,
.bit_offset_of,
.byte_offset_of,
.splat,
.reduce,
.atomic_load,
=> try self.writePlNodeBin(stream, inst),
.call,
@ -1874,6 +2370,7 @@ const Writer = struct {
.block_inline_var,
.loop,
.validate_struct_init_ptr,
.c_import,
=> try self.writePlNodeBlock(stream, inst),
.condbr,
@ -1926,6 +2423,9 @@ const Writer = struct {
.fence,
.ret_addr,
.builtin_src,
.error_return_trace,
.frame,
.frame_address,
=> try self.writeNode(stream, inst),
.error_value,
@ -1954,6 +2454,7 @@ const Writer = struct {
.bitcast,
.bitcast_result_ptr,
.extended,
=> try stream.writeAll("TODO)"),
}
}

View File

@ -83,6 +83,8 @@ pub const Type = extern union {
.pointer,
.inferred_alloc_const,
.inferred_alloc_mut,
.manyptr_u8,
.manyptr_const_u8,
=> return .Pointer,
.optional,
@ -96,11 +98,17 @@ pub const Type = extern union {
.empty_struct,
.empty_struct_literal,
.@"struct",
.call_options,
=> return .Struct,
.enum_full,
.enum_nonexhaustive,
.enum_simple,
.atomic_ordering,
.atomic_rmw_op,
.calling_convention,
.float_mode,
.reduce_op,
=> return .Enum,
.var_args_param => unreachable, // can be any type
@ -205,6 +213,8 @@ pub const Type = extern union {
.mut_slice,
.optional_single_const_pointer,
.optional_single_mut_pointer,
.manyptr_u8,
.manyptr_const_u8,
=> self.cast(Payload.ElemType),
.inferred_alloc_const => unreachable,
@ -271,6 +281,17 @@ pub const Type = extern union {
.@"volatile" = false,
.size = .Many,
} },
.manyptr_const_u8 => return .{ .data = .{
.pointee_type = Type.initTag(.u8),
.sentinel = null,
.@"align" = 0,
.bit_offset = 0,
.host_size = 0,
.@"allowzero" = false,
.mutable = false,
.@"volatile" = false,
.size = .Many,
} },
.many_mut_pointer => return .{ .data = .{
.pointee_type = self.castPointer().?.data,
.sentinel = null,
@ -282,6 +303,17 @@ pub const Type = extern union {
.@"volatile" = false,
.size = .Many,
} },
.manyptr_u8 => return .{ .data = .{
.pointee_type = Type.initTag(.u8),
.sentinel = null,
.@"align" = 0,
.bit_offset = 0,
.host_size = 0,
.@"allowzero" = false,
.mutable = true,
.@"volatile" = false,
.size = .Many,
} },
.c_const_pointer => return .{ .data = .{
.pointee_type = self.castPointer().?.data,
.sentinel = null,
@ -576,6 +608,14 @@ pub const Type = extern union {
.inferred_alloc_mut,
.var_args_param,
.empty_struct_literal,
.manyptr_u8,
.manyptr_const_u8,
.atomic_ordering,
.atomic_rmw_op,
.calling_convention,
.float_mode,
.reduce_op,
.call_options,
=> unreachable,
.array_u8,
@ -746,6 +786,14 @@ pub const Type = extern union {
.fn_naked_noreturn_no_args => return writer.writeAll("fn() callconv(.Naked) noreturn"),
.fn_ccc_void_no_args => return writer.writeAll("fn() callconv(.C) void"),
.single_const_pointer_to_comptime_int => return writer.writeAll("*const comptime_int"),
.manyptr_u8 => return writer.writeAll("[*]u8"),
.manyptr_const_u8 => return writer.writeAll("[*]const u8"),
.atomic_ordering => return writer.writeAll("std.builtin.AtomicOrdering"),
.atomic_rmw_op => return writer.writeAll("std.builtin.AtomicRmwOp"),
.calling_convention => return writer.writeAll("std.builtin.CallingConvention"),
.float_mode => return writer.writeAll("std.builtin.FloatMode"),
.reduce_op => return writer.writeAll("std.builtin.ReduceOp"),
.call_options => return writer.writeAll("std.builtin.CallOptions"),
.function => {
const payload = ty.castTag(.function).?.data;
try writer.writeAll("fn(");
@ -952,6 +1000,14 @@ pub const Type = extern union {
.single_const_pointer_to_comptime_int => return Value.initTag(.single_const_pointer_to_comptime_int_type),
.const_slice_u8 => return Value.initTag(.const_slice_u8_type),
.enum_literal => return Value.initTag(.enum_literal_type),
.manyptr_u8 => return Value.initTag(.manyptr_u8_type),
.manyptr_const_u8 => return Value.initTag(.manyptr_const_u8_type),
.atomic_ordering => return Value.initTag(.atomic_ordering_type),
.atomic_rmw_op => return Value.initTag(.atomic_rmw_op_type),
.calling_convention => return Value.initTag(.calling_convention_type),
.float_mode => return Value.initTag(.float_mode_type),
.reduce_op => return Value.initTag(.reduce_op_type),
.call_options => return Value.initTag(.call_options_type),
.inferred_alloc_const => unreachable,
.inferred_alloc_mut => unreachable,
else => return Value.Tag.ty.create(allocator, self),
@ -1001,6 +1057,14 @@ pub const Type = extern union {
.anyerror_void_error_union,
.error_set,
.error_set_single,
.manyptr_u8,
.manyptr_const_u8,
.atomic_ordering,
.atomic_rmw_op,
.calling_convention,
.float_mode,
.reduce_op,
.call_options,
=> true,
.@"struct" => {
@ -1079,7 +1143,10 @@ pub const Type = extern union {
.optional_single_mut_pointer,
=> return self.cast(Payload.ElemType).?.data.abiAlignment(target),
.const_slice_u8 => return 1,
.manyptr_u8,
.manyptr_const_u8,
.const_slice_u8,
=> return 1,
.pointer => {
const ptr_info = self.castTag(.pointer).?.data;
@ -1102,6 +1169,12 @@ pub const Type = extern union {
.bool,
.array_u8_sentinel_0,
.array_u8,
.atomic_ordering,
.atomic_rmw_op,
.calling_convention,
.float_mode,
.reduce_op,
.call_options,
=> return 1,
.fn_noreturn_no_args, // represents machine code; not a pointer
@ -1136,6 +1209,8 @@ pub const Type = extern union {
.optional_single_const_pointer,
.optional_single_mut_pointer,
.pointer,
.manyptr_u8,
.manyptr_const_u8,
=> return @divExact(target.cpu.arch.ptrBitWidth(), 8),
.c_short => return @divExact(CType.short.sizeInBits(target), 8),
@ -1271,6 +1346,12 @@ pub const Type = extern union {
.u8,
.i8,
.bool,
.atomic_ordering,
.atomic_rmw_op,
.calling_convention,
.float_mode,
.reduce_op,
.call_options,
=> return 1,
.array_u8 => self.castTag(.array_u8).?.data,
@ -1322,6 +1403,10 @@ pub const Type = extern union {
return @divExact(target.cpu.arch.ptrBitWidth(), 8);
},
.manyptr_u8,
.manyptr_const_u8,
=> return @divExact(target.cpu.arch.ptrBitWidth(), 8),
.c_short => return @divExact(CType.short.sizeInBits(target), 8),
.c_ushort => return @divExact(CType.ushort.sizeInBits(target), 8),
.c_int => return @divExact(CType.int.sizeInBits(target), 8),
@ -1475,6 +1560,10 @@ pub const Type = extern union {
}
},
.manyptr_u8,
.manyptr_const_u8,
=> return target.cpu.arch.ptrBitWidth(),
.c_short => return CType.short.sizeInBits(target),
.c_ushort => return CType.ushort.sizeInBits(target),
.c_int => return CType.int.sizeInBits(target),
@ -1517,8 +1606,16 @@ pub const Type = extern union {
} else if (!payload.payload.hasCodeGenBits()) {
return payload.error_set.bitSize(target);
}
@panic("TODO abiSize error union");
@panic("TODO bitSize error union");
},
.atomic_ordering,
.atomic_rmw_op,
.calling_convention,
.float_mode,
.reduce_op,
.call_options,
=> @panic("TODO at some point we gotta resolve builtin types"),
};
}
@ -1564,6 +1661,8 @@ pub const Type = extern union {
.many_const_pointer,
.many_mut_pointer,
.manyptr_u8,
.manyptr_const_u8,
=> .Many,
.c_const_pointer,
@ -1604,6 +1703,7 @@ pub const Type = extern union {
.single_const_pointer_to_comptime_int,
.const_slice_u8,
.const_slice,
.manyptr_const_u8,
=> true,
.pointer => !self.castTag(.pointer).?.data.mutable,
@ -1718,7 +1818,13 @@ pub const Type = extern union {
.mut_slice,
=> self.castPointer().?.data,
.array_u8, .array_u8_sentinel_0, .const_slice_u8 => Type.initTag(.u8),
.array_u8,
.array_u8_sentinel_0,
.const_slice_u8,
.manyptr_u8,
.manyptr_const_u8,
=> Type.initTag(.u8),
.single_const_pointer_to_comptime_int => Type.initTag(.comptime_int),
.pointer => self.castTag(.pointer).?.data.pointee_type,
@ -1811,6 +1917,8 @@ pub const Type = extern union {
.single_const_pointer_to_comptime_int,
.array,
.array_u8,
.manyptr_u8,
.manyptr_const_u8,
=> return null,
.pointer => return self.castTag(.pointer).?.data.sentinel,
@ -2122,6 +2230,14 @@ pub const Type = extern union {
.error_set_single,
.@"opaque",
.var_args_param,
.manyptr_u8,
.manyptr_const_u8,
.atomic_ordering,
.atomic_rmw_op,
.calling_convention,
.float_mode,
.reduce_op,
.call_options,
=> return null,
.@"struct" => {
@ -2281,6 +2397,14 @@ pub const Type = extern union {
const enum_simple = ty.castTag(.enum_simple).?.data;
return enum_simple.fields.count();
},
.atomic_ordering,
.atomic_rmw_op,
.calling_convention,
.float_mode,
.reduce_op,
.call_options,
=> @panic("TODO resolve std.builtin types"),
else => unreachable,
}
}
@ -2295,6 +2419,13 @@ pub const Type = extern union {
const enum_simple = ty.castTag(.enum_simple).?.data;
return enum_simple.fields.entries.items[field_index].key;
},
.atomic_ordering,
.atomic_rmw_op,
.calling_convention,
.float_mode,
.reduce_op,
.call_options,
=> @panic("TODO resolve std.builtin types"),
else => unreachable,
}
}
@ -2309,6 +2440,13 @@ pub const Type = extern union {
const enum_simple = ty.castTag(.enum_simple).?.data;
return enum_simple.fields.getIndex(field_name);
},
.atomic_ordering,
.atomic_rmw_op,
.calling_convention,
.float_mode,
.reduce_op,
.call_options,
=> @panic("TODO resolve std.builtin types"),
else => unreachable,
}
}
@ -2345,6 +2483,13 @@ pub const Type = extern union {
const enum_simple = ty.castTag(.enum_simple).?.data;
return S.fieldWithRange(enum_tag, enum_simple.fields.count());
},
.atomic_ordering,
.atomic_rmw_op,
.calling_convention,
.float_mode,
.reduce_op,
.call_options,
=> @panic("TODO resolve std.builtin types"),
else => unreachable,
}
}
@ -2367,6 +2512,13 @@ pub const Type = extern union {
const error_set = ty.castTag(.error_set).?.data;
return error_set.srcLoc();
},
.atomic_ordering,
.atomic_rmw_op,
.calling_convention,
.float_mode,
.reduce_op,
.call_options,
=> @panic("TODO resolve std.builtin types"),
else => unreachable,
}
}
@ -2390,6 +2542,13 @@ pub const Type = extern union {
return error_set.owner_decl;
},
.@"opaque" => @panic("TODO"),
.atomic_ordering,
.atomic_rmw_op,
.calling_convention,
.float_mode,
.reduce_op,
.call_options,
=> @panic("TODO resolve std.builtin types"),
else => unreachable,
}
}
@ -2422,6 +2581,13 @@ pub const Type = extern union {
const enum_simple = ty.castTag(.enum_simple).?.data;
return S.intInRange(int, enum_simple.fields.count());
},
.atomic_ordering,
.atomic_rmw_op,
.calling_convention,
.float_mode,
.reduce_op,
.call_options,
=> @panic("TODO resolve std.builtin types"),
else => unreachable,
}
@ -2469,6 +2635,14 @@ pub const Type = extern union {
comptime_float,
noreturn,
enum_literal,
manyptr_u8,
manyptr_const_u8,
atomic_ordering,
atomic_rmw_op,
calling_convention,
float_mode,
reduce_op,
call_options,
@"null",
@"undefined",
fn_noreturn_no_args,
@ -2572,6 +2746,14 @@ pub const Type = extern union {
.inferred_alloc_mut,
.var_args_param,
.empty_struct_literal,
.manyptr_u8,
.manyptr_const_u8,
.atomic_ordering,
.atomic_rmw_op,
.calling_convention,
.float_mode,
.reduce_op,
.call_options,
=> @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"),
.array_u8,

View File

@ -64,6 +64,14 @@ pub const Value = extern union {
single_const_pointer_to_comptime_int_type,
const_slice_u8_type,
enum_literal_type,
manyptr_u8_type,
manyptr_const_u8_type,
atomic_ordering_type,
atomic_rmw_op_type,
calling_convention_type,
float_mode_type,
reduce_op_type,
call_options_type,
undef,
zero,
@ -169,6 +177,14 @@ pub const Value = extern union {
.bool_true,
.bool_false,
.abi_align_default,
.manyptr_u8_type,
.manyptr_const_u8_type,
.atomic_ordering_type,
.atomic_rmw_op_type,
.calling_convention_type,
.float_mode_type,
.reduce_op_type,
.call_options_type,
=> @compileError("Value Tag " ++ @tagName(t) ++ " has no payload"),
.int_big_positive,
@ -327,6 +343,14 @@ pub const Value = extern union {
.bool_false,
.empty_struct_value,
.abi_align_default,
.manyptr_u8_type,
.manyptr_const_u8_type,
.atomic_ordering_type,
.atomic_rmw_op_type,
.calling_convention_type,
.float_mode_type,
.reduce_op_type,
.call_options_type,
=> unreachable,
.ty => {
@ -474,6 +498,14 @@ pub const Value = extern union {
.single_const_pointer_to_comptime_int_type => return out_stream.writeAll("*const comptime_int"),
.const_slice_u8_type => return out_stream.writeAll("[]const u8"),
.enum_literal_type => return out_stream.writeAll("@Type(.EnumLiteral)"),
.manyptr_u8_type => return out_stream.writeAll("[*]u8"),
.manyptr_const_u8_type => return out_stream.writeAll("[*]const u8"),
.atomic_ordering_type => return out_stream.writeAll("std.builtin.AtomicOrdering"),
.atomic_rmw_op_type => return out_stream.writeAll("std.builtin.AtomicRmwOp"),
.calling_convention_type => return out_stream.writeAll("std.builtin.CallingConvention"),
.float_mode_type => return out_stream.writeAll("std.builtin.FloatMode"),
.reduce_op_type => return out_stream.writeAll("std.builtin.ReduceOp"),
.call_options_type => return out_stream.writeAll("std.builtin.CallOptions"),
.abi_align_default => return out_stream.writeAll("(default ABI alignment)"),
.empty_struct_value => return out_stream.writeAll("struct {}{}"),
@ -595,6 +627,14 @@ pub const Value = extern union {
.single_const_pointer_to_comptime_int_type => Type.initTag(.single_const_pointer_to_comptime_int),
.const_slice_u8_type => Type.initTag(.const_slice_u8),
.enum_literal_type => Type.initTag(.enum_literal),
.manyptr_u8_type => Type.initTag(.manyptr_u8),
.manyptr_const_u8_type => Type.initTag(.manyptr_const_u8),
.atomic_ordering_type => Type.initTag(.atomic_ordering),
.atomic_rmw_op_type => Type.initTag(.atomic_rmw_op),
.calling_convention_type => Type.initTag(.calling_convention),
.float_mode_type => Type.initTag(.float_mode),
.reduce_op_type => Type.initTag(.reduce_op),
.call_options_type => Type.initTag(.call_options),
.int_type => {
const payload = self.castTag(.int_type).?.data;
@ -1132,6 +1172,16 @@ pub const Value = extern union {
std.hash.autoHash(&hasher, payload.hash());
},
.inferred_alloc => unreachable,
.manyptr_u8_type,
.manyptr_const_u8_type,
.atomic_ordering_type,
.atomic_rmw_op_type,
.calling_convention_type,
.float_mode_type,
.reduce_op_type,
.call_options_type,
=> @panic("TODO this hash function looks pretty broken. audit it"),
}
return hasher.final();
}
@ -1278,6 +1328,14 @@ pub const Value = extern union {
.single_const_pointer_to_comptime_int_type,
.const_slice_u8_type,
.enum_literal_type,
.manyptr_u8_type,
.manyptr_const_u8_type,
.atomic_ordering_type,
.atomic_rmw_op_type,
.calling_convention_type,
.float_mode_type,
.reduce_op_type,
.call_options_type,
=> true,
.zero,