| ... | ... | @@ -12371,7 +12371,7 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12371 | 12371 | const type_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 12372 | 12372 | const type_res = try sema.resolveType(block, src, extra.lhs); |
| 12373 | 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 | 12375 | const ptr_align = type_res.ptrAlignment(sema.mod.getTarget()); |
| 12376 | 12376 | |
| 12377 | 12377 | if (try sema.resolveDefinedValue(block, operand_src, operand_coerced)) |val| { |
| ... | ... | @@ -13019,20 +13019,24 @@ fn resolveExportOptions( |
| 13019 | 13019 | ) CompileError!std.builtin.ExportOptions { |
| 13020 | 13020 | const export_options_ty = try sema.getBuiltinType(block, src, "ExportOptions"); |
| 13021 | 13021 | const air_ref = sema.resolveInst(zir_ref); |
| 13022 | | const coerced = try sema.coerce(block, export_options_ty, air_ref, src); |
| 13023 | | const val = try sema.resolveConstValue(block, src, coerced); |
| 13024 | | const fields = val.castTag(.@"struct").?.data; |
| 13025 | | const struct_obj = export_options_ty.castTag(.@"struct").?.data; |
| 13026 | | const name_index = struct_obj.fields.getIndex("name").?; |
| 13027 | | const linkage_index = struct_obj.fields.getIndex("linkage").?; |
| 13028 | | const section_index = struct_obj.fields.getIndex("section").?; |
| 13029 | | if (!fields[section_index].isNull()) { |
| 13022 | const options = try sema.coerce(block, export_options_ty, air_ref, src); |
| 13023 | |
| 13024 | const name = try sema.fieldVal(block, src, options, "name", src); |
| 13025 | const name_val = try sema.resolveConstValue(block, src, name); |
| 13026 | |
| 13027 | const linkage = try sema.fieldVal(block, src, options, "linkage", src); |
| 13028 | const linkage_val = try sema.resolveConstValue(block, src, linkage); |
| 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 | 13034 | return sema.fail(block, src, "TODO: implement exporting with linksection", .{}); |
| 13031 | 13035 | } |
| 13032 | 13036 | const name_ty = Type.initTag(.const_slice_u8); |
| 13033 | 13037 | return std.builtin.ExportOptions{ |
| 13034 | | .name = try fields[name_index].toAllocatedBytes(name_ty, sema.arena), |
| 13035 | | .linkage = fields[linkage_index].toEnum(std.builtin.GlobalLinkage), |
| 13038 | .name = try name_val.toAllocatedBytes(name_ty, sema.arena), |
| 13039 | .linkage = linkage_val.toEnum(std.builtin.GlobalLinkage), |
| 13036 | 13040 | .section = null, // TODO |
| 13037 | 13041 | }; |
| 13038 | 13042 | } |
| ... | ... | @@ -13384,17 +13388,19 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 13384 | 13388 | const args = sema.resolveInst(extra.data.args); |
| 13385 | 13389 | |
| 13386 | 13390 | const modifier: std.builtin.CallOptions.Modifier = modifier: { |
| 13387 | | const export_options_ty = try sema.getBuiltinType(block, options_src, "CallOptions"); |
| 13388 | | const coerced_options = try sema.coerce(block, export_options_ty, options, options_src); |
| 13389 | | const options_val = try sema.resolveConstValue(block, options_src, coerced_options); |
| 13390 | | const fields = options_val.castTag(.@"struct").?.data; |
| 13391 | | const struct_obj = export_options_ty.castTag(.@"struct").?.data; |
| 13392 | | const modifier_index = struct_obj.fields.getIndex("modifier").?; |
| 13393 | | const stack_index = struct_obj.fields.getIndex("stack").?; |
| 13394 | | if (!fields[stack_index].isNull()) { |
| 13391 | const call_options_ty = try sema.getBuiltinType(block, options_src, "CallOptions"); |
| 13392 | const coerced_options = try sema.coerce(block, call_options_ty, options, options_src); |
| 13393 | |
| 13394 | const modifier = try sema.fieldVal(block, options_src, coerced_options, "modifier", options_src); |
| 13395 | const modifier_val = try sema.resolveConstValue(block, options_src, modifier); |
| 13396 | |
| 13397 | const stack = try sema.fieldVal(block, options_src, coerced_options, "stack", options_src); |
| 13398 | const stack_val = try sema.resolveConstValue(block, options_src, stack); |
| 13399 | |
| 13400 | if (!stack_val.isNull()) { |
| 13395 | 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 | 13406 | const args_ty = sema.typeOf(args); |
| ... | ... | @@ -13743,6 +13749,7 @@ fn zirVarExtended( |
| 13743 | 13749 | .is_extern = small.is_extern, |
| 13744 | 13750 | .is_mutable = true, // TODO get rid of this unused field |
| 13745 | 13751 | .is_threadlocal = small.is_threadlocal, |
| 13752 | .is_weak_linkage = false, |
| 13746 | 13753 | .lib_name = null, |
| 13747 | 13754 | }; |
| 13748 | 13755 | |
| ... | ... | @@ -13937,7 +13944,103 @@ fn zirBuiltinExtern( |
| 13937 | 13944 | ) CompileError!Air.Inst.Ref { |
| 13938 | 13945 | const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; |
| 13939 | 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 | 14046 | fn requireFunctionBlock(sema: *Sema, block: *Block, src: LazySrcLoc) !void { |
| ... | ... | @@ -15409,6 +15512,14 @@ fn coerce( |
| 15409 | 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 | 15523 | // T to ?T |
| 15413 | 15524 | const child_type = try dest_ty.optionalChildAlloc(sema.arena); |
| 15414 | 15525 | const intermediate = try sema.coerce(block, child_type, inst, inst_src); |
| ... | ... | @@ -16688,6 +16799,7 @@ fn coerceCompatiblePtrs( |
| 16688 | 16799 | inst: Air.Inst.Ref, |
| 16689 | 16800 | inst_src: LazySrcLoc, |
| 16690 | 16801 | ) !Air.Inst.Ref { |
| 16802 | // TODO check const/volatile/alignment |
| 16691 | 16803 | if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| { |
| 16692 | 16804 | // The comptime Value representation is compatible with both types. |
| 16693 | 16805 | return sema.addConstant(dest_ty, val); |
| ... | ... | @@ -18403,6 +18515,7 @@ fn resolveInferredErrorSet(sema: *Sema, inferred_error_set: *Module.Fn.InferredE |
| 18403 | 18515 | if (inferred_error_set.is_resolved) { |
| 18404 | 18516 | return; |
| 18405 | 18517 | } |
| 18518 | inferred_error_set.is_resolved = true; |
| 18406 | 18519 | |
| 18407 | 18520 | var it = inferred_error_set.inferred_error_sets.keyIterator(); |
| 18408 | 18521 | while (it.next()) |other_error_set_ptr| { |
| ... | ... | @@ -18423,8 +18536,6 @@ fn resolveInferredErrorSet(sema: *Sema, inferred_error_set: *Module.Fn.InferredE |
| 18423 | 18536 | if (other_error_set_ptr.*.is_anyerror) |
| 18424 | 18537 | inferred_error_set.is_anyerror = true; |
| 18425 | 18538 | } |
| 18426 | | |
| 18427 | | inferred_error_set.is_resolved = true; |
| 18428 | 18539 | } |
| 18429 | 18540 | |
| 18430 | 18541 | fn resolveInferredErrorSetTy(sema: *Sema, ty: Type) CompileError!void { |