| ... | @@ -12371,7 +12371,7 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -12371,7 +12371,7 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12371 | const type_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 12371 | const type_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 12372 | const type_res = try sema.resolveType(block, src, extra.lhs); | 12372 | const type_res = try sema.resolveType(block, src, extra.lhs); |
| 12373 | try sema.checkPtrType(block, type_src, type_res); | 12373 | try sema.checkPtrType(block, type_src, type_res); |
| 12374 | _ = try sema.resolveTypeLayout(block, src, type_res.childType()); | 12374 | try sema.resolveTypeLayout(block, src, type_res.elemType2()); |
| 12375 | const ptr_align = type_res.ptrAlignment(sema.mod.getTarget()); | 12375 | const ptr_align = type_res.ptrAlignment(sema.mod.getTarget()); |
| 12376 | | 12376 | |
| 12377 | if (try sema.resolveDefinedValue(block, operand_src, operand_coerced)) |val| { | 12377 | if (try sema.resolveDefinedValue(block, operand_src, operand_coerced)) |val| { |
| ... | @@ -13019,20 +13019,24 @@ fn resolveExportOptions( | ... | @@ -13019,20 +13019,24 @@ fn resolveExportOptions( |
| 13019 | ) CompileError!std.builtin.ExportOptions { | 13019 | ) CompileError!std.builtin.ExportOptions { |
| 13020 | const export_options_ty = try sema.getBuiltinType(block, src, "ExportOptions"); | 13020 | const export_options_ty = try sema.getBuiltinType(block, src, "ExportOptions"); |
| 13021 | const air_ref = sema.resolveInst(zir_ref); | 13021 | const air_ref = sema.resolveInst(zir_ref); |
| 13022 | const coerced = try sema.coerce(block, export_options_ty, air_ref, src); | 13022 | const options = try sema.coerce(block, export_options_ty, air_ref, src); |
| 13023 | const val = try sema.resolveConstValue(block, src, coerced); | 13023 | |
| 13024 | const fields = val.castTag(.@"struct").?.data; | 13024 | const name = try sema.fieldVal(block, src, options, "name", src); |
| 13025 | const struct_obj = export_options_ty.castTag(.@"struct").?.data; | 13025 | const name_val = try sema.resolveConstValue(block, src, name); |
| 13026 | const name_index = struct_obj.fields.getIndex("name").?; | 13026 | |
| 13027 | const linkage_index = struct_obj.fields.getIndex("linkage").?; | 13027 | const linkage = try sema.fieldVal(block, src, options, "linkage", src); |
| 13028 | const section_index = struct_obj.fields.getIndex("section").?; | 13028 | const linkage_val = try sema.resolveConstValue(block, src, linkage); |
| 13029 | if (!fields[section_index].isNull()) { | 13029 | |
| | 13030 | const section = try sema.fieldVal(block, src, options, "section", src); |
| | 13031 | const section_val = try sema.resolveConstValue(block, src, section); |
| | 13032 | |
| | 13033 | if (!section_val.isNull()) { |
| 13030 | return sema.fail(block, src, "TODO: implement exporting with linksection", .{}); | 13034 | return sema.fail(block, src, "TODO: implement exporting with linksection", .{}); |
| 13031 | } | 13035 | } |
| 13032 | const name_ty = Type.initTag(.const_slice_u8); | 13036 | const name_ty = Type.initTag(.const_slice_u8); |
| 13033 | return std.builtin.ExportOptions{ | 13037 | return std.builtin.ExportOptions{ |
| 13034 | .name = try fields[name_index].toAllocatedBytes(name_ty, sema.arena), | 13038 | .name = try name_val.toAllocatedBytes(name_ty, sema.arena), |
| 13035 | .linkage = fields[linkage_index].toEnum(std.builtin.GlobalLinkage), | 13039 | .linkage = linkage_val.toEnum(std.builtin.GlobalLinkage), |
| 13036 | .section = null, // TODO | 13040 | .section = null, // TODO |
| 13037 | }; | 13041 | }; |
| 13038 | } | 13042 | } |
| ... | @@ -13384,17 +13388,19 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -13384,17 +13388,19 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 13384 | const args = sema.resolveInst(extra.data.args); | 13388 | const args = sema.resolveInst(extra.data.args); |
| 13385 | | 13389 | |
| 13386 | const modifier: std.builtin.CallOptions.Modifier = modifier: { | 13390 | const modifier: std.builtin.CallOptions.Modifier = modifier: { |
| 13387 | const export_options_ty = try sema.getBuiltinType(block, options_src, "CallOptions"); | 13391 | const call_options_ty = try sema.getBuiltinType(block, options_src, "CallOptions"); |
| 13388 | const coerced_options = try sema.coerce(block, export_options_ty, options, options_src); | 13392 | const coerced_options = try sema.coerce(block, call_options_ty, options, options_src); |
| 13389 | const options_val = try sema.resolveConstValue(block, options_src, coerced_options); | 13393 | |
| 13390 | const fields = options_val.castTag(.@"struct").?.data; | 13394 | const modifier = try sema.fieldVal(block, options_src, coerced_options, "modifier", options_src); |
| 13391 | const struct_obj = export_options_ty.castTag(.@"struct").?.data; | 13395 | const modifier_val = try sema.resolveConstValue(block, options_src, modifier); |
| 13392 | const modifier_index = struct_obj.fields.getIndex("modifier").?; | 13396 | |
| 13393 | const stack_index = struct_obj.fields.getIndex("stack").?; | 13397 | const stack = try sema.fieldVal(block, options_src, coerced_options, "stack", options_src); |
| 13394 | if (!fields[stack_index].isNull()) { | 13398 | const stack_val = try sema.resolveConstValue(block, options_src, stack); |
| | 13399 | |
| | 13400 | if (!stack_val.isNull()) { |
| 13395 | return sema.fail(block, options_src, "TODO: implement @call with stack", .{}); | 13401 | return sema.fail(block, options_src, "TODO: implement @call with stack", .{}); |
| 13396 | } | 13402 | } |
| 13397 | break :modifier fields[modifier_index].toEnum(std.builtin.CallOptions.Modifier); | 13403 | break :modifier modifier_val.toEnum(std.builtin.CallOptions.Modifier); |
| 13398 | }; | 13404 | }; |
| 13399 | | 13405 | |
| 13400 | const args_ty = sema.typeOf(args); | 13406 | const args_ty = sema.typeOf(args); |
| ... | @@ -13743,6 +13749,7 @@ fn zirVarExtended( | ... | @@ -13743,6 +13749,7 @@ fn zirVarExtended( |
| 13743 | .is_extern = small.is_extern, | 13749 | .is_extern = small.is_extern, |
| 13744 | .is_mutable = true, // TODO get rid of this unused field | 13750 | .is_mutable = true, // TODO get rid of this unused field |
| 13745 | .is_threadlocal = small.is_threadlocal, | 13751 | .is_threadlocal = small.is_threadlocal, |
| | 13752 | .is_weak_linkage = false, |
| 13746 | .lib_name = null, | 13753 | .lib_name = null, |
| 13747 | }; | 13754 | }; |
| 13748 | | 13755 | |
| ... | @@ -13937,7 +13944,103 @@ fn zirBuiltinExtern( | ... | @@ -13937,7 +13944,103 @@ fn zirBuiltinExtern( |
| 13937 | ) CompileError!Air.Inst.Ref { | 13944 | ) CompileError!Air.Inst.Ref { |
| 13938 | const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; | 13945 | const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; |
| 13939 | const src: LazySrcLoc = .{ .node_offset = extra.node }; | 13946 | const src: LazySrcLoc = .{ .node_offset = extra.node }; |
| 13940 | return sema.fail(block, src, "TODO: implement Sema.zirBuiltinExtern", .{}); | 13947 | const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node }; |
| | 13948 | const options_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node }; |
| | 13949 | |
| | 13950 | var ty = try sema.resolveType(block, ty_src, extra.lhs); |
| | 13951 | const options_inst = sema.resolveInst(extra.rhs); |
| | 13952 | |
| | 13953 | const options = options: { |
| | 13954 | const extern_options_ty = try sema.getBuiltinType(block, options_src, "ExternOptions"); |
| | 13955 | const options = try sema.coerce(block, extern_options_ty, options_inst, options_src); |
| | 13956 | |
| | 13957 | const name = try sema.fieldVal(block, options_src, options, "name", options_src); |
| | 13958 | const name_val = try sema.resolveConstValue(block, options_src, name); |
| | 13959 | |
| | 13960 | const library_name_inst = try sema.fieldVal(block, options_src, options, "library_name", options_src); |
| | 13961 | const library_name_val = try sema.resolveConstValue(block, options_src, library_name_inst); |
| | 13962 | |
| | 13963 | const linkage = try sema.fieldVal(block, options_src, options, "linkage", options_src); |
| | 13964 | const linkage_val = try sema.resolveConstValue(block, options_src, linkage); |
| | 13965 | |
| | 13966 | const is_thread_local = try sema.fieldVal(block, options_src, options, "is_thread_local", options_src); |
| | 13967 | const is_thread_local_val = try sema.resolveConstValue(block, options_src, is_thread_local); |
| | 13968 | |
| | 13969 | var library_name: ?[]const u8 = null; |
| | 13970 | if (!library_name_val.isNull()) { |
| | 13971 | const payload = library_name_val.castTag(.opt_payload).?.data; |
| | 13972 | library_name = try payload.toAllocatedBytes(Type.initTag(.const_slice_u8), sema.arena); |
| | 13973 | } |
| | 13974 | |
| | 13975 | break :options std.builtin.ExternOptions{ |
| | 13976 | .name = try name_val.toAllocatedBytes(Type.initTag(.const_slice_u8), sema.arena), |
| | 13977 | .library_name = library_name, |
| | 13978 | .linkage = linkage_val.toEnum(std.builtin.GlobalLinkage), |
| | 13979 | .is_thread_local = is_thread_local_val.toBool(), |
| | 13980 | }; |
| | 13981 | }; |
| | 13982 | |
| | 13983 | if (!ty.isPtrAtRuntime()) { |
| | 13984 | return sema.fail(block, options_src, "expected (optional) pointer", .{}); |
| | 13985 | } |
| | 13986 | |
| | 13987 | if (options.name.len == 0) { |
| | 13988 | return sema.fail(block, options_src, "extern symbol name cannot be empty", .{}); |
| | 13989 | } |
| | 13990 | |
| | 13991 | if (options.linkage != .Weak and options.linkage != .Strong) { |
| | 13992 | return sema.fail(block, options_src, "extern symbol must use strong or weak linkage", .{}); |
| | 13993 | } |
| | 13994 | |
| | 13995 | if (options.linkage == .Weak and !ty.ptrAllowsZero()) { |
| | 13996 | ty = try Type.optional(sema.arena, ty); |
| | 13997 | } |
| | 13998 | |
| | 13999 | // TODO check duplicate extern |
| | 14000 | |
| | 14001 | const new_decl = try sema.mod.allocateNewDecl(try sema.gpa.dupeZ(u8, options.name), sema.owner_decl.src_namespace, sema.owner_decl.src_node, null); |
| | 14002 | errdefer new_decl.destroy(sema.mod); |
| | 14003 | |
| | 14004 | var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa); |
| | 14005 | errdefer new_decl_arena.deinit(); |
| | 14006 | const new_decl_arena_allocator = new_decl_arena.allocator(); |
| | 14007 | |
| | 14008 | const new_var = try new_decl_arena_allocator.create(Module.Var); |
| | 14009 | errdefer new_decl_arena_allocator.destroy(new_var); |
| | 14010 | |
| | 14011 | new_var.* = .{ |
| | 14012 | .owner_decl = sema.owner_decl, |
| | 14013 | .init = Value.initTag(.unreachable_value), |
| | 14014 | .is_extern = true, |
| | 14015 | .is_mutable = false, // TODO get rid of this unused field |
| | 14016 | .is_threadlocal = options.is_thread_local, |
| | 14017 | .is_weak_linkage = options.linkage == .Weak, |
| | 14018 | .lib_name = null, |
| | 14019 | }; |
| | 14020 | |
| | 14021 | if (options.library_name) |library_name| { |
| | 14022 | if (library_name.len == 0) { |
| | 14023 | return sema.fail(block, options_src, "library name name cannot be empty", .{}); |
| | 14024 | } |
| | 14025 | new_var.lib_name = try sema.handleExternLibName(block, options_src, library_name); |
| | 14026 | } |
| | 14027 | |
| | 14028 | new_decl.src_line = sema.owner_decl.src_line; |
| | 14029 | new_decl.ty = try ty.copy(new_decl_arena_allocator); |
| | 14030 | new_decl.val = try Value.Tag.variable.create(new_decl_arena_allocator, new_var); |
| | 14031 | new_decl.align_val = Value.@"null"; |
| | 14032 | new_decl.linksection_val = Value.@"null"; |
| | 14033 | new_decl.has_tv = true; |
| | 14034 | new_decl.analysis = .complete; |
| | 14035 | new_decl.generation = sema.mod.generation; |
| | 14036 | |
| | 14037 | const arena_state = try new_decl_arena_allocator.create(std.heap.ArenaAllocator.State); |
| | 14038 | arena_state.* = new_decl_arena.state; |
| | 14039 | new_decl.value_arena = arena_state; |
| | 14040 | |
| | 14041 | const ref = try sema.analyzeDeclRef(new_decl); |
| | 14042 | try sema.requireRuntimeBlock(block, src); |
| | 14043 | return block.addBitCast(ty, ref); |
| 13941 | } | 14044 | } |
| 13942 | | 14045 | |
| 13943 | fn requireFunctionBlock(sema: *Sema, block: *Block, src: LazySrcLoc) !void { | 14046 | fn requireFunctionBlock(sema: *Sema, block: *Block, src: LazySrcLoc) !void { |
| ... | @@ -15409,6 +15512,14 @@ fn coerce( | ... | @@ -15409,6 +15512,14 @@ fn coerce( |
| 15409 | return sema.addConstant(dest_ty, Value.@"null"); | 15512 | return sema.addConstant(dest_ty, Value.@"null"); |
| 15410 | } | 15513 | } |
| 15411 | | 15514 | |
| | 15515 | // cast from ?*T and ?[*]T to ?*anyopaque |
| | 15516 | // but don't do it if the source type is a double pointer |
| | 15517 | if (dest_ty.isPtrLikeOptional() and dest_ty.elemType2().tag() == .anyopaque and |
| | 15518 | inst_ty.isPtrLikeOptional() and inst_ty.elemType2().zigTypeTag() != .Pointer) |
| | 15519 | { |
| | 15520 | return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src); |
| | 15521 | } |
| | 15522 | |
| 15412 | // T to ?T | 15523 | // T to ?T |
| 15413 | const child_type = try dest_ty.optionalChildAlloc(sema.arena); | 15524 | const child_type = try dest_ty.optionalChildAlloc(sema.arena); |
| 15414 | const intermediate = try sema.coerce(block, child_type, inst, inst_src); | 15525 | const intermediate = try sema.coerce(block, child_type, inst, inst_src); |
| ... | @@ -16688,6 +16799,7 @@ fn coerceCompatiblePtrs( | ... | @@ -16688,6 +16799,7 @@ fn coerceCompatiblePtrs( |
| 16688 | inst: Air.Inst.Ref, | 16799 | inst: Air.Inst.Ref, |
| 16689 | inst_src: LazySrcLoc, | 16800 | inst_src: LazySrcLoc, |
| 16690 | ) !Air.Inst.Ref { | 16801 | ) !Air.Inst.Ref { |
| | 16802 | // TODO check const/volatile/alignment |
| 16691 | if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| { | 16803 | if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| { |
| 16692 | // The comptime Value representation is compatible with both types. | 16804 | // The comptime Value representation is compatible with both types. |
| 16693 | return sema.addConstant(dest_ty, val); | 16805 | return sema.addConstant(dest_ty, val); |
| ... | @@ -18403,6 +18515,7 @@ fn resolveInferredErrorSet(sema: *Sema, inferred_error_set: *Module.Fn.InferredE | ... | @@ -18403,6 +18515,7 @@ fn resolveInferredErrorSet(sema: *Sema, inferred_error_set: *Module.Fn.InferredE |
| 18403 | if (inferred_error_set.is_resolved) { | 18515 | if (inferred_error_set.is_resolved) { |
| 18404 | return; | 18516 | return; |
| 18405 | } | 18517 | } |
| | 18518 | inferred_error_set.is_resolved = true; |
| 18406 | | 18519 | |
| 18407 | var it = inferred_error_set.inferred_error_sets.keyIterator(); | 18520 | var it = inferred_error_set.inferred_error_sets.keyIterator(); |
| 18408 | while (it.next()) |other_error_set_ptr| { | 18521 | while (it.next()) |other_error_set_ptr| { |
| ... | @@ -18423,8 +18536,6 @@ fn resolveInferredErrorSet(sema: *Sema, inferred_error_set: *Module.Fn.InferredE | ... | @@ -18423,8 +18536,6 @@ fn resolveInferredErrorSet(sema: *Sema, inferred_error_set: *Module.Fn.InferredE |
| 18423 | if (other_error_set_ptr.*.is_anyerror) | 18536 | if (other_error_set_ptr.*.is_anyerror) |
| 18424 | inferred_error_set.is_anyerror = true; | 18537 | inferred_error_set.is_anyerror = true; |
| 18425 | } | 18538 | } |
| 18426 | | | |
| 18427 | inferred_error_set.is_resolved = true; | | |
| 18428 | } | 18539 | } |
| 18429 | | 18540 | |
| 18430 | fn resolveInferredErrorSetTy(sema: *Sema, ty: Type) CompileError!void { | 18541 | fn resolveInferredErrorSetTy(sema: *Sema, ty: Type) CompileError!void { |