diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-07-15 13:36:46 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-07-20 12:19:16 -0700 |
| commit | 12c10139e3e0166e91d2dbb1801c2054ca12d413 (patch) | |
| tree | f084c36fecb08bd36eb0733263647b12ac1fbb05 /src/Sema.zig | |
| parent | 0da66339096c21d9ca524ff7a0c11a5707b60041 (diff) | |
| download | zig-12c10139e3e0166e91d2dbb1801c2054ca12d413.tar.gz zig-12c10139e3e0166e91d2dbb1801c2054ca12d413.zip | |
Sema: finish reworking for AIR memory layout except switch
Diffstat (limited to 'src/Sema.zig')
| -rw-r--r-- | src/Sema.zig | 615 |
1 files changed, 331 insertions, 284 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index 268f7bc903..ac6755d24e 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -276,101 +276,101 @@ pub fn analyzeBody( //.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), - //.typeof => try sema.zirTypeof(block, inst), - //.typeof_elem => try sema.zirTypeofElem(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, false), - //.struct_init_ref => try sema.zirStructInit(block, inst, true), - //.struct_init_anon => try sema.zirStructInitAnon(block, inst, false), - //.struct_init_anon_ref => try sema.zirStructInitAnon(block, inst, true), - //.array_init => try sema.zirArrayInit(block, inst, false), - //.array_init_ref => try sema.zirArrayInit(block, inst, true), - //.array_init_anon => try sema.zirArrayInitAnon(block, inst, false), - //.array_init_anon_ref => try sema.zirArrayInitAnon(block, inst, true), - //.union_init_ptr => try sema.zirUnionInitPtr(block, inst), - //.field_type => try sema.zirFieldType(block, inst), - //.field_type_ref => try sema.zirFieldTypeRef(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), - //.offset_of => try sema.zirOffsetOf(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), - //.@"resume" => try sema.zirResume(block, inst), - //.@"await" => try sema.zirAwait(block, inst, false), - //.await_nosuspend => try sema.zirAwait(block, inst, true), - //.extended => try sema.zirExtended(block, inst), - - //.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), - - //.opaque_decl => try sema.zirOpaqueDecl(block, inst, .parent), - //.opaque_decl_anon => try sema.zirOpaqueDecl(block, inst, .anon), - //.opaque_decl_func => try sema.zirOpaqueDecl(block, inst, .func), - //.error_set_decl => try sema.zirErrorSetDecl(block, inst, .parent), - //.error_set_decl_anon => try sema.zirErrorSetDecl(block, inst, .anon), - //.error_set_decl_func => try sema.zirErrorSetDecl(block, inst, .func), + .type_info => try sema.zirTypeInfo(block, inst), + .size_of => try sema.zirSizeOf(block, inst), + .bit_size_of => try sema.zirBitSizeOf(block, inst), + .typeof => try sema.zirTypeof(block, inst), + .typeof_elem => try sema.zirTypeofElem(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, false), + .struct_init_ref => try sema.zirStructInit(block, inst, true), + .struct_init_anon => try sema.zirStructInitAnon(block, inst, false), + .struct_init_anon_ref => try sema.zirStructInitAnon(block, inst, true), + .array_init => try sema.zirArrayInit(block, inst, false), + .array_init_ref => try sema.zirArrayInit(block, inst, true), + .array_init_anon => try sema.zirArrayInitAnon(block, inst, false), + .array_init_anon_ref => try sema.zirArrayInitAnon(block, inst, true), + .union_init_ptr => try sema.zirUnionInitPtr(block, inst), + .field_type => try sema.zirFieldType(block, inst), + .field_type_ref => try sema.zirFieldTypeRef(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), + .offset_of => try sema.zirOffsetOf(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), + .@"resume" => try sema.zirResume(block, inst), + .@"await" => try sema.zirAwait(block, inst, false), + .await_nosuspend => try sema.zirAwait(block, inst, true), + .extended => try sema.zirExtended(block, inst), + + .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), + + .opaque_decl => try sema.zirOpaqueDecl(block, inst, .parent), + .opaque_decl_anon => try sema.zirOpaqueDecl(block, inst, .anon), + .opaque_decl_func => try sema.zirOpaqueDecl(block, inst, .func), + .error_set_decl => try sema.zirErrorSetDecl(block, inst, .parent), + .error_set_decl_anon => try sema.zirErrorSetDecl(block, inst, .anon), + .error_set_decl_func => try sema.zirErrorSetDecl(block, inst, .func), .add => try sema.zirArithmetic(block, inst), .addwrap => try sema.zirArithmetic(block, inst), @@ -396,106 +396,106 @@ pub fn analyzeBody( .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 - //// continue the loop. - //// We also know that they cannot be referenced later, so we avoid - //// putting them into the map. - //.breakpoint => { - // try sema.zirBreakpoint(block, inst); - // i += 1; - // continue; - //}, - //.fence => { - // try sema.zirFence(block, inst); - // i += 1; - // continue; - //}, - //.dbg_stmt => { - // try sema.zirDbgStmt(block, inst); - // i += 1; - // continue; - //}, - //.ensure_err_payload_void => { - // try sema.zirEnsureErrPayloadVoid(block, inst); - // i += 1; - // continue; - //}, - //.ensure_result_non_error => { - // try sema.zirEnsureResultNonError(block, inst); - // i += 1; - // continue; - //}, - //.ensure_result_used => { - // try sema.zirEnsureResultUsed(block, inst); - // i += 1; - // continue; - //}, - //.set_eval_branch_quota => { - // try sema.zirSetEvalBranchQuota(block, inst); - // i += 1; - // continue; - //}, - //.store => { - // try sema.zirStore(block, inst); - // i += 1; - // continue; - //}, - //.store_node => { - // try sema.zirStoreNode(block, inst); - // i += 1; - // continue; - //}, - //.store_to_block_ptr => { - // try sema.zirStoreToBlockPtr(block, inst); - // i += 1; - // continue; - //}, - //.store_to_inferred_ptr => { - // try sema.zirStoreToInferredPtr(block, inst); - // i += 1; - // continue; - //}, - //.resolve_inferred_alloc => { - // try sema.zirResolveInferredAlloc(block, inst); - // i += 1; - // continue; - //}, - //.validate_struct_init_ptr => { - // try sema.zirValidateStructInitPtr(block, inst); - // i += 1; - // continue; - //}, - //.validate_array_init_ptr => { - // try sema.zirValidateArrayInitPtr(block, inst); - // i += 1; - // continue; - //}, - //.@"export" => { - // try sema.zirExport(block, inst); - // i += 1; - // continue; - //}, - //.set_align_stack => { - // try sema.zirSetAlignStack(block, inst); - // i += 1; - // continue; - //}, - //.set_cold => { - // try sema.zirSetCold(block, inst); - // i += 1; - // continue; - //}, - //.set_float_mode => { - // try sema.zirSetFloatMode(block, inst); - // i += 1; - // continue; - //}, - //.set_runtime_safety => { - // try sema.zirSetRuntimeSafety(block, inst); - // i += 1; - // continue; - //}, + // Instructions that we know can *never* be noreturn based solely on + // their tag. We avoid needlessly checking if they are noreturn and + // continue the loop. + // We also know that they cannot be referenced later, so we avoid + // putting them into the map. + .breakpoint => { + try sema.zirBreakpoint(block, inst); + i += 1; + continue; + }, + .fence => { + try sema.zirFence(block, inst); + i += 1; + continue; + }, + .dbg_stmt => { + try sema.zirDbgStmt(block, inst); + i += 1; + continue; + }, + .ensure_err_payload_void => { + try sema.zirEnsureErrPayloadVoid(block, inst); + i += 1; + continue; + }, + .ensure_result_non_error => { + try sema.zirEnsureResultNonError(block, inst); + i += 1; + continue; + }, + .ensure_result_used => { + try sema.zirEnsureResultUsed(block, inst); + i += 1; + continue; + }, + .set_eval_branch_quota => { + try sema.zirSetEvalBranchQuota(block, inst); + i += 1; + continue; + }, + .store => { + try sema.zirStore(block, inst); + i += 1; + continue; + }, + .store_node => { + try sema.zirStoreNode(block, inst); + i += 1; + continue; + }, + .store_to_block_ptr => { + try sema.zirStoreToBlockPtr(block, inst); + i += 1; + continue; + }, + .store_to_inferred_ptr => { + try sema.zirStoreToInferredPtr(block, inst); + i += 1; + continue; + }, + .resolve_inferred_alloc => { + try sema.zirResolveInferredAlloc(block, inst); + i += 1; + continue; + }, + .validate_struct_init_ptr => { + try sema.zirValidateStructInitPtr(block, inst); + i += 1; + continue; + }, + .validate_array_init_ptr => { + try sema.zirValidateArrayInitPtr(block, inst); + i += 1; + continue; + }, + .@"export" => { + try sema.zirExport(block, inst); + i += 1; + continue; + }, + .set_align_stack => { + try sema.zirSetAlignStack(block, inst); + i += 1; + continue; + }, + .set_cold => { + try sema.zirSetCold(block, inst); + i += 1; + continue; + }, + .set_float_mode => { + try sema.zirSetFloatMode(block, inst); + i += 1; + continue; + }, + .set_runtime_safety => { + try sema.zirSetRuntimeSafety(block, inst); + i += 1; + continue; + }, // Special case instructions to handle comptime control flow. .repeat_inline => { @@ -562,7 +562,7 @@ fn zirExtended(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr .frame_address => return sema.zirFrameAddress( block, extended), .alloc => return sema.zirAllocExtended( block, extended), .builtin_extern => return sema.zirBuiltinExtern( block, extended), - .@"asm" => return sema.zirAsm( block, extended), + .@"asm" => return sema.zirAsm( block, extended, inst), .typeof_peer => return sema.zirTypeofPeer( block, extended), .compile_log => return sema.zirCompileLog( block, extended), .add_with_overflow => return sema.zirOverflowArithmetic(block, extended), @@ -1400,11 +1400,14 @@ 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_val = ptr.castTag(.constant).?.val; + const ptr_inst = 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]; const inferred_alloc = ptr_val.castTag(.inferred_alloc).?; const peer_inst_list = inferred_alloc.data.stored_inst_list.items; const final_elem_ty = try sema.resolvePeerTypes(block, ty_src, peer_inst_list); - const var_is_mut = switch (ptr.ty.tag()) { + const var_is_mut = switch (sema.typeOf(ptr).tag()) { .inferred_alloc_const => false, .inferred_alloc_mut => true, else => unreachable, @@ -1415,8 +1418,10 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Inde const final_ptr_ty = try Module.simplePtrType(sema.arena, final_elem_ty, true, .One); // Change it to a normal alloc. - ptr.ty = final_ptr_ty; - ptr.tag = .alloc; + sema.air_instructions.set(ptr_inst, .{ + .tag = .alloc, + .data = .{ .ty = final_ptr_ty }, + }); } fn zirValidateStructInitPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!void { @@ -1434,7 +1439,7 @@ fn zirValidateStructInitPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Ind const field_ptr_data = sema.code.instructions.items(.data)[instrs[0]].pl_node; const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data; const object_ptr = sema.resolveInst(field_ptr_extra.lhs); - break :s object_ptr.ty.elemType().castTag(.@"struct").?.data; + break :s sema.typeOf(object_ptr).elemType().castTag(.@"struct").?.data; }; // Maps field index to field_ptr index of where it was already initialized. @@ -1564,7 +1569,7 @@ fn zirStoreToBlockPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Co } const ptr = sema.resolveInst(bin_inst.lhs); const value = sema.resolveInst(bin_inst.rhs); - const ptr_ty = try Module.simplePtrType(sema.arena, value.ty, true, .One); + const ptr_ty = try Module.simplePtrType(sema.arena, sema.typeOf(value), true, .One); // TODO detect when this store should be done at compile-time. For example, // if expressions should force it when the condition is compile-time known. const src: LazySrcLoc = .unneeded; @@ -1581,12 +1586,16 @@ 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 inferred_alloc = ptr.castTag(.constant).?.val.castTag(.inferred_alloc).?; + const ptr_inst = 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]; + const inferred_alloc = ptr_val.castTag(.inferred_alloc).?; // Add the stored instruction to the set we will use to resolve peer types // for the inferred allocation. try inferred_alloc.data.stored_inst_list.append(sema.arena, value); // Create a runtime bitcast instruction with exactly the type the pointer wants. - const ptr_ty = try Module.simplePtrType(sema.arena, value.ty, true, .One); + const ptr_ty = try Module.simplePtrType(sema.arena, sema.typeOf(value), true, .One); try sema.requireRuntimeBlock(block, src); const bitcasted_ptr = try block.addTyOp(.bitcast, ptr_ty, ptr); return sema.storePtr(block, src, bitcasted_ptr, value); @@ -1767,10 +1776,11 @@ fn zirCompileLog( if (i != 0) try writer.print(", ", .{}); const arg = sema.resolveInst(arg_ref); + const arg_ty = sema.typeOf(arg); if (try sema.resolvePossiblyUndefinedValue(block, src, arg)) |val| { - try writer.print("@as({}, {})", .{ arg.ty, val }); + try writer.print("@as({}, {})", .{ arg_ty, val }); } else { - try writer.print("@as({}, [runtime value])", .{arg.ty}); + try writer.print("@as({}, [runtime value])", .{arg_ty}); } } try writer.print("\n", .{}); @@ -2157,7 +2167,13 @@ fn zirDbgStmt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr if (block.is_comptime) return; const inst_data = sema.code.instructions.items(.data)[inst].dbg_stmt; - _ = try block.addDbgStmt(.unneeded, inst_data.line, inst_data.column); + _ = try block.addInst(.{ + .tag = .dbg_stmt, + .data = .{ .dbg_stmt = .{ + .line = inst_data.line, + .column = inst_data.column, + } }, + }); } fn zirDeclRef(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { @@ -3263,9 +3279,10 @@ fn zirPtrToInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr const inst_data = sema.code.instructions.items(.data)[inst].un_node; const ptr = sema.resolveInst(inst_data.operand); - if (ptr.ty.zigTypeTag() != .Pointer) { + const ptr_ty = sema.typeOf(ptr); + if (ptr_ty.zigTypeTag() != .Pointer) { const ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; - return sema.mod.fail(&block.base, ptr_src, "expected pointer, found '{}'", .{ptr.ty}); + return sema.mod.fail(&block.base, ptr_src, "expected pointer, found '{}'", .{ptr_ty}); } // TODO handle known-pointer-address const src = inst_data.src(); @@ -3368,7 +3385,7 @@ fn zirIntCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr ), } - if (operand.value() != null) { + if (try sema.isComptimeKnown(block, operand_src, operand)) { return sema.coerce(block, dest_type, operand, operand_src); } else if (dest_is_comptime_int) { return sema.mod.fail(&block.base, src, "unable to cast runtime value to 'comptime_int'", .{}); @@ -3426,7 +3443,7 @@ fn zirFloatCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileE ), } - if (operand.value() != null) { + if (try sema.isComptimeKnown(block, operand_src, operand)) { return sema.coerce(block, dest_type, operand, operand_src); } else if (dest_is_comptime_float) { return sema.mod.fail(&block.base, src, "unable to cast runtime value to 'comptime_float'", .{}); @@ -4843,19 +4860,17 @@ fn zirAsm( sema: *Sema, block: *Scope.Block, extended: Zir.Inst.Extended.InstData, + inst: Zir.Inst.Index, ) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); const extra = sema.code.extraData(Zir.Inst.Asm, extended.operand); const src: LazySrcLoc = .{ .node_offset = extra.data.src_node }; - const asm_source_src: LazySrcLoc = .{ .node_offset_asm_source = extra.data.src_node }; const ret_ty_src: LazySrcLoc = .{ .node_offset_asm_ret_ty = extra.data.src_node }; - const asm_source = try sema.resolveConstString(block, asm_source_src, extra.data.asm_source); const outputs_len = @truncate(u5, extended.small); 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; if (outputs_len > 1) { return sema.mod.fail(&block.base, src, "TODO implement Sema for asm with more than 1 output", .{}); @@ -4883,7 +4898,7 @@ fn zirAsm( }; }; - const args = try sema.arena.alloc(Air.Inst.Index, inputs_len); + const args = try sema.arena.alloc(Air.Inst.Ref, inputs_len); const inputs = try sema.arena.alloc([]const u8, inputs_len); for (args) |*arg, arg_i| { @@ -4904,22 +4919,19 @@ fn zirAsm( } try sema.requireRuntimeBlock(block, src); - const asm_air = try sema.arena.create(Inst.Assembly); - asm_air.* = .{ - .base = .{ - .tag = .assembly, - .ty = if (output) |o| o.ty else Type.initTag(.void), - .src = src, - }, - .asm_source = asm_source, - .is_volatile = is_volatile, - .output_constraint = if (output) |o| o.constraint else null, - .inputs = inputs, - .clobbers = clobbers, - .args = args, - }; - try block.instructions.append(sema.gpa, &asm_air.base); - return &asm_air.base; + const gpa = sema.gpa; + try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Asm).Struct.fields.len + args.len); + const asm_air = try block.addInst(.{ + .tag = .assembly, + .data = .{ .ty_pl = .{ + .ty = if (output) |o| try sema.addType(o.ty) else Air.Inst.Ref.void_type, + .payload = sema.addExtraAssumeCapacity(Air.Asm{ + .zir_index = inst, + }), + } }, + }); + sema.appendRefsAssumeCapacity(args); + return asm_air; } fn zirCmp( @@ -5153,7 +5165,7 @@ fn zirTypeofElem(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compile _ = block; const inst_data = sema.code.instructions.items(.data)[inst].un_node; const operand_ptr = sema.resolveInst(inst_data.operand); - const elem_ty = operand_ptr.ty.elemType(); + const elem_ty = sema.typeOf(operand_ptr).elemType(); return sema.addType(elem_ty); } @@ -5181,7 +5193,7 @@ fn zirTypeofPeer( const src: LazySrcLoc = .{ .node_offset = extra.data.src_node }; const args = sema.code.refSlice(extra.end, extended.small); - const inst_list = try sema.gpa.alloc(Air.Inst.Index, args.len); + const inst_list = try sema.gpa.alloc(Air.Inst.Ref, args.len); defer sema.gpa.free(inst_list); for (args) |arg_ref, i| { @@ -5623,7 +5635,7 @@ fn zirStructInit(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, is_ref: mem.set(Zir.Inst.Index, found_fields, 0); // The init values to use for the struct instance. - const field_inits = try gpa.alloc(Air.Inst.Index, struct_obj.fields.count()); + const field_inits = try gpa.alloc(Air.Inst.Ref, struct_obj.fields.count()); defer gpa.free(field_inits); var field_i: u32 = 0; @@ -5692,7 +5704,7 @@ fn zirStructInit(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, is_ref: } const is_comptime = for (field_inits) |field_init| { - if (field_init.value() == null) { + if (!(try sema.isComptimeKnown(block, src, field_init))) { break false; } } else true; @@ -5700,7 +5712,7 @@ fn zirStructInit(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, is_ref: if (is_comptime) { const values = try sema.arena.alloc(Value, field_inits.len); for (field_inits) |field_init, i| { - values[i] = field_init.value().?; + values[i] = (sema.resolvePossiblyUndefinedValue(block, src, field_init) catch unreachable).?; } return sema.addConstant(struct_ty, try Value.Tag.@"struct".create(sema.arena, values.ptr)); } @@ -6835,17 +6847,13 @@ fn coerce( } assert(inst_ty.zigTypeTag() != .Undefined); - if (true) { - @panic("TODO finish AIR memory layout rework"); - } - // T to E!T or E to E!T if (dest_type.tag() == .error_union) { return try sema.wrapErrorUnion(block, dest_type, inst, inst_src); } // comptime known number to other number - if (try sema.coerceNum(block, dest_type, inst)) |some| + if (try sema.coerceNum(block, dest_type, inst, inst_src)) |some| return some; const target = mod.getTarget(); @@ -6861,9 +6869,9 @@ fn coerce( var buf: Type.Payload.ElemType = undefined; const child_type = dest_type.optionalChild(&buf); if (child_type.eql(inst_ty)) { - return sema.wrapOptional(block, dest_type, inst); - } else if (try sema.coerceNum(block, child_type, inst)) |some| { - return sema.wrapOptional(block, dest_type, some); + return sema.wrapOptional(block, dest_type, inst, inst_src); + } else if (try sema.coerceNum(block, child_type, inst, inst_src)) |some| { + return sema.wrapOptional(block, dest_type, some, inst_src); } }, .Pointer => { @@ -6885,11 +6893,11 @@ fn coerce( switch (dest_type.ptrSize()) { .Slice => { // *[N]T to []T - return sema.coerceArrayPtrToSlice(block, dest_type, inst); + return sema.coerceArrayPtrToSlice(block, dest_type, inst, inst_src); }, .C => { // *[N]T to [*c]T - return sema.coerceArrayPtrToMany(block, dest_type, inst); + return sema.coerceArrayPtrToMany(block, dest_type, inst, inst_src); }, .Many => { // *[N]T to [*]T @@ -6897,12 +6905,12 @@ fn coerce( const src_sentinel = array_type.sentinel(); const dst_sentinel = dest_type.sentinel(); if (src_sentinel == null and dst_sentinel == null) - return sema.coerceArrayPtrToMany(block, dest_type, inst); + return sema.coerceArrayPtrToMany(block, dest_type, inst, inst_src); if (src_sentinel) |src_s| { if (dst_sentinel) |dst_s| { if (src_s.eql(dst_s)) { - return sema.coerceArrayPtrToMany(block, dest_type, inst); + return sema.coerceArrayPtrToMany(block, dest_type, inst, inst_src); } } } @@ -6914,7 +6922,7 @@ fn coerce( .Int => { // integer widening if (inst_ty.zigTypeTag() == .Int) { - assert(inst.value() == null); // handled above + assert(!(try sema.isComptimeKnown(block, inst_src, inst))); // handled above const dst_info = dest_type.intInfo(target); const src_info = inst_ty.intInfo(target); @@ -6930,7 +6938,7 @@ fn coerce( .Float => { // float widening if (inst_ty.zigTypeTag() == .Float) { - assert(inst.value() == null); // handled above + assert(!(try sema.isComptimeKnown(block, inst_src, inst))); // handled above const src_bits = inst_ty.floatBits(target); const dst_bits = dest_type.floatBits(target); @@ -6991,9 +6999,16 @@ fn coerceInMemoryAllowed(dest_type: Type, src_type: Type) InMemoryCoercionResult return .no_match; } -fn coerceNum(sema: *Sema, block: *Scope.Block, dest_type: Type, inst: Air.Inst.Ref) CompileError!?Air.Inst.Index { - const val = inst.value() orelse return null; - const src_zig_tag = inst.ty.zigTypeTag(); +fn coerceNum( + sema: *Sema, + block: *Scope.Block, + dest_type: Type, + inst: Air.Inst.Ref, + inst_src: LazySrcLoc, +) CompileError!?Air.Inst.Ref { + const val = (try sema.resolveDefinedValue(block, inst_src, inst)) orelse return null; + const inst_ty = sema.typeOf(inst); + const src_zig_tag = inst_ty.zigTypeTag(); const dst_zig_tag = dest_type.zigTypeTag(); const target = sema.mod.getTarget(); @@ -7001,29 +7016,29 @@ fn coerceNum(sema: *Sema, block: *Scope.Block, dest_type: Type, inst: Air.Inst.R if (dst_zig_tag == .ComptimeInt or dst_zig_tag == .Int) { if (src_zig_tag == .Float or src_zig_tag == .ComptimeFloat) { if (val.floatHasFraction()) { - return sema.mod.fail(&block.base, inst.src, "fractional component prevents float value {} from being casted to type '{}'", .{ val, inst.ty }); + return sema.mod.fail(&block.base, inst_src, "fractional component prevents float value {} from being casted to type '{}'", .{ val, inst_ty }); } - return sema.mod.fail(&block.base, inst.src, "TODO float to int", .{}); + return sema.mod.fail(&block.base, inst_src, "TODO float to int", .{}); } else if (src_zig_tag == .Int or src_zig_tag == .ComptimeInt) { if (!val.intFitsInType(dest_type, target)) { - return sema.mod.fail(&block.base, inst.src, "type {} cannot represent integer value {}", .{ inst.ty, val }); + return sema.mod.fail(&block.base, inst_src, "type {} cannot represent integer value {}", .{ inst_ty, val }); } - return sema.addConstant(dest_type, val); + return try sema.addConstant(dest_type, val); } } else if (dst_zig_tag == .ComptimeFloat or dst_zig_tag == .Float) { if (src_zig_tag == .Float or src_zig_tag == .ComptimeFloat) { const res = val.floatCast(sema.arena, dest_type, target) catch |err| switch (err) { error.Overflow => return sema.mod.fail( &block.base, - inst.src, + inst_src, "cast of value {} to type '{}' loses information", .{ val, dest_type }, ), error.OutOfMemory => return error.OutOfMemory, }; - return sema.addConstant(dest_type, res); + return try sema.addConstant(dest_type, res); } else if (src_zig_tag == .Int or src_zig_tag == .ComptimeInt) { - return sema.mod.fail(&block.base, inst.src, "TODO int to float", .{}); + return sema.mod.fail(&block.base, inst_src, "TODO int to float", .{}); } } return null; @@ -7051,10 +7066,11 @@ fn storePtr( ptr: Air.Inst.Ref, uncasted_value: Air.Inst.Ref, ) !void { - if (ptr.ty.isConstPtr()) + const ptr_ty = sema.typeOf(ptr); + if (ptr_ty.isConstPtr()) return sema.mod.fail(&block.base, src, "cannot assign to constant", .{}); - const elem_ty = ptr.ty.elemType(); + const elem_ty = ptr_ty.elemType(); const value = try sema.coerce(block, elem_ty, uncasted_value, src); if ((try sema.typeHasOnePossibleValue(block, src, elem_ty)) != null) return; @@ -7113,20 +7129,32 @@ fn bitcast( return block.addTyOp(.bitcast, dest_type, inst); } -fn coerceArrayPtrToSlice(sema: *Sema, block: *Scope.Block, dest_type: Type, inst: Air.Inst.Ref) CompileError!Air.Inst.Ref { - if (inst.value()) |val| { +fn coerceArrayPtrToSlice( + sema: *Sema, + block: *Scope.Block, + dest_type: Type, + inst: Air.Inst.Ref, + inst_src: LazySrcLoc, +) CompileError!Air.Inst.Ref { + if (try sema.resolveDefinedValue(block, inst_src, inst)) |val| { // The comptime Value representation is compatible with both types. return sema.addConstant(dest_type, val); } - return sema.mod.fail(&block.base, inst.src, "TODO implement coerceArrayPtrToSlice runtime instruction", .{}); + return sema.mod.fail(&block.base, inst_src, "TODO implement coerceArrayPtrToSlice runtime instruction", .{}); } -fn coerceArrayPtrToMany(sema: *Sema, block: *Scope.Block, dest_type: Type, inst: Air.Inst.Ref) !Air.Inst.Ref { - if (inst.value()) |val| { +fn coerceArrayPtrToMany( + sema: *Sema, + block: *Scope.Block, + dest_type: Type, + inst: Air.Inst.Ref, + inst_src: LazySrcLoc, +) !Air.Inst.Ref { + if (try sema.resolveDefinedValue(block, inst_src, inst)) |val| { // The comptime Value representation is compatible with both types. return sema.addConstant(dest_type, val); } - return sema.mod.fail(&block.base, inst.src, "TODO implement coerceArrayPtrToMany runtime instruction", .{}); + return sema.mod.fail(&block.base, inst_src, "TODO implement coerceArrayPtrToMany runtime instruction", .{}); } fn analyzeDeclVal(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, decl: *Decl) CompileError!Air.Inst.Ref { @@ -7531,12 +7559,18 @@ fn cmpNumeric( return block.addBinOp(Air.Inst.Tag.fromCmpOp(op), casted_lhs, casted_rhs); } -fn wrapOptional(sema: *Sema, block: *Scope.Block, dest_type: Type, inst: Air.Inst.Ref) !Air.Inst.Index { +fn wrapOptional( + sema: *Sema, + block: *Scope.Block, + dest_type: Type, + inst: Air.Inst.Ref, + inst_src: LazySrcLoc, +) !Air.Inst.Ref { if (try sema.resolvePossiblyUndefinedValue(block, inst_src, inst)) |val| { return sema.addConstant(dest_type, val); } - try sema.requireRuntimeBlock(block, inst.src); + try sema.requireRuntimeBlock(block, inst_src); return block.addTyOp(.wrap_optional, dest_type, inst); } @@ -7546,11 +7580,12 @@ fn wrapErrorUnion( dest_type: Type, inst: Air.Inst.Ref, inst_src: LazySrcLoc, -) !Air.Inst.Index { +) !Air.Inst.Ref { + const inst_ty = sema.typeOf(inst); const err_union = dest_type.castTag(.error_union).?; if (try sema.resolvePossiblyUndefinedValue(block, inst_src, inst)) |val| { - if (inst.ty.zigTypeTag() != .ErrorSet) { - _ = try sema.coerce(block, err_union.data.payload, inst, inst.src); + if (inst_ty.zigTypeTag() != .ErrorSet) { + _ = try sema.coerce(block, err_union.data.payload, inst, inst_src); } else switch (err_union.data.error_set.tag()) { .anyerror => {}, .error_set_single => { @@ -7559,9 +7594,9 @@ fn wrapErrorUnion( if (!mem.eql(u8, expected_name, n)) { return sema.mod.fail( &block.base, - inst.src, + inst_src, "expected type '{}', found type '{}'", - .{ err_union.data.error_set, inst.ty }, + .{ err_union.data.error_set, inst_ty }, ); } }, @@ -7577,9 +7612,9 @@ fn wrapErrorUnion( if (!found) { return sema.mod.fail( &block.base, - inst.src, + inst_src, "expected type '{}', found type '{}'", - .{ err_union.data.error_set, inst.ty }, + .{ err_union.data.error_set, inst_ty }, ); } }, @@ -7589,9 +7624,9 @@ fn wrapErrorUnion( if (!map.contains(expected_name)) { return sema.mod.fail( &block.base, - inst.src, + inst_src, "expected type '{}', found type '{}'", - .{ err_union.data.error_set, inst.ty }, + .{ err_union.data.error_set, inst_ty }, ); } }, @@ -7602,14 +7637,14 @@ fn wrapErrorUnion( return sema.addConstant(dest_type, try Value.Tag.error_union.create(sema.arena, val)); } - try sema.requireRuntimeBlock(block, inst.src); + try sema.requireRuntimeBlock(block, inst_src); // we are coercing from E to E!T - if (inst.ty.zigTypeTag() == .ErrorSet) { - var coerced = try sema.coerce(block, err_union.data.error_set, inst, inst.src); + if (inst_ty.zigTypeTag() == .ErrorSet) { + var coerced = try sema.coerce(block, err_union.data.error_set, inst, inst_src); return block.addTyOp(.wrap_errunion_err, dest_type, coerced); } else { - var coerced = try sema.coerce(block, err_union.data.payload, inst, inst.src); + var coerced = try sema.coerce(block, err_union.data.payload, inst, inst_src); return block.addTyOp(.wrap_errunion_payload, dest_type, coerced); } } @@ -8081,7 +8116,10 @@ fn typeOf(sema: *Sema, inst: Air.Inst.Ref) Type { .ptrtoint => return Type.initTag(.usize), - .call => @panic("TODO Sema.typeOf call"), + .call => { + const callee_ty = sema.typeOf(air_datas[i].pl_op.operand); + return callee_ty.fnReturnType(); + }, } } @@ -8219,3 +8257,12 @@ fn getBreakBlock(sema: *Sema, inst_index: Air.Inst.Index) ?Air.Inst.Index { else => return null, } } + +fn isComptimeKnown( + sema: *Sema, + block: *Scope.Block, + src: LazySrcLoc, + inst: Air.Inst.Ref, +) !bool { + return (try sema.resolvePossiblyUndefinedValue(block, src, inst)) != null; +} |
