@@ -1409,11 +1409,6 @@ fn analyzeBodyInner(
1409
1409
i += 1;
1410
1410
continue;
1411
1411
},
1412
- .export_value => {
1413
- try sema.zirExportValue(block, inst);
1414
- i += 1;
1415
- continue;
1416
- },
1417
1412
.set_runtime_safety => {
1418
1413
try sema.zirSetRuntimeSafety(block, inst);
1419
1414
i += 1;
@@ -6358,85 +6353,89 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
6358
6353
const tracy = trace(@src());
6359
6354
defer tracy.end();
6360
6355
6361
- const mod = sema.mod;
6356
+ const zcu = sema.mod;
6362
6357
const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
6363
- const extra = sema.code.extraData(Zir.Inst.Export , inst_data.payload_index).data;
6358
+ const extra = sema.code.extraData(Zir.Inst.Bin , inst_data.payload_index).data;
6364
6359
const src = inst_data.src();
6365
6360
const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
6366
6361
const options_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
6367
- const decl_name = try mod.intern_pool.getOrPutString(mod.gpa, sema.code.nullTerminatedString(extra.decl_name));
6368
- const decl_index = if (extra.namespace != .none) index_blk: {
6369
- const container_ty = try sema.resolveType(block, operand_src, extra.namespace);
6370
- const container_namespace = container_ty.getNamespaceIndex(mod);
6371
-
6372
- const maybe_index = try sema.lookupInNamespace(block, operand_src, container_namespace, decl_name, false);
6373
- break :index_blk maybe_index orelse
6374
- return sema.failWithBadMemberAccess(block, container_ty, operand_src, decl_name);
6375
- } else try sema.lookupIdentifier(block, operand_src, decl_name);
6376
- const options = sema.resolveExportOptions(block, .unneeded, extra.options) catch |err| switch (err) {
6377
- error.NeededSourceLocation => {
6378
- _ = try sema.resolveExportOptions(block, options_src, extra.options);
6379
- unreachable;
6380
- },
6381
- else => |e| return e,
6382
- };
6383
- {
6384
- try mod.ensureDeclAnalyzed(decl_index);
6385
- const exported_decl = mod.declPtr(decl_index);
6386
- if (exported_decl.val.getFunction(mod)) |function| {
6387
- return sema.analyzeExport(block, src, options, function.owner_decl);
6388
- }
6362
+
6363
+ const operand = try sema.resolveInst(extra.lhs);
6364
+ const ptr_val = try sema.resolveConstDefinedValue(block, operand_src, operand, .{
6365
+ .needed_comptime_reason = "export pointer must be comptime-known",
6366
+ });
6367
+ const ptr_ty = ptr_val.typeOf(zcu);
6368
+
6369
+ switch (ptr_ty.zigTypeTag(zcu)) {
6370
+ .Pointer => if (ptr_ty.isSlice(zcu)) return sema.failWithOwnedErrorMsg(block, msg: {
6371
+ const msg = try sema.errMsg(block, operand_src, "expected pointer, found '{}'", .{ptr_ty.fmt(zcu)});
6372
+ errdefer msg.destroy(sema.gpa);
6373
+ try sema.errNote(block, operand_src, msg, "use 'ptr' field to convert slice to many pointer", .{});
6374
+ break :msg msg;
6375
+ }),
6376
+ else => return sema.failWithOwnedErrorMsg(block, msg: {
6377
+ const msg = try sema.errMsg(block, operand_src, "expected pointer, found '{}'", .{ptr_ty.fmt(zcu)});
6378
+ errdefer msg.destroy(sema.gpa);
6379
+ try sema.errNote(block, operand_src, msg, "take the address of a value to export it", .{});
6380
+ break :msg msg;
6381
+ }),
6389
6382
}
6390
- try sema.analyzeExport(block, src, options, decl_index);
6391
- }
6392
6383
6393
- fn zirExportValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
6394
- const tracy = trace(@src());
6395
- defer tracy.end();
6384
+ const options = try sema.resolveExportOptions(block, options_src, extra.rhs);
6396
6385
6397
- const mod = sema.mod;
6398
- const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
6399
- const extra = sema.code.extraData(Zir.Inst.ExportValue, inst_data.payload_index).data;
6400
- const src = inst_data.src();
6401
- const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
6402
- const options_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
6403
- const operand = try sema.resolveInstConst(block, operand_src, extra.operand, .{
6404
- .needed_comptime_reason = "export target must be comptime-known",
6405
- });
6406
- const options = try sema.resolveExportOptions(block, options_src, extra.options);
6407
- if (options.linkage == .internal)
6408
- return;
6409
- if (operand.getFunction(mod)) |function| {
6410
- const decl_index = function.owner_decl;
6411
- return sema.analyzeExport(block, src, options, decl_index);
6386
+ if (ptr_val.canMutateComptimeVarState(zcu)) {
6387
+ return sema.failWithOwnedErrorMsg(block, msg: {
6388
+ const msg = try sema.errMsg(block, operand_src, "export pointer contains reference to comptime var", .{});
6389
+ errdefer msg.destroy(sema.gpa);
6390
+ try sema.errNote(block, operand_src, msg, "comptime var pointers are not available at runtime", .{});
6391
+ break :msg msg;
6392
+ });
6412
6393
}
6413
6394
6414
- try addExport(mod, .{
6415
- .opts = options,
6416
- .src = src,
6417
- .owner_decl = sema.owner_decl_index,
6418
- .src_decl = block.src_decl,
6419
- .exported = .{ .value = operand.toIntern() },
6420
- .status = .in_progress,
6421
- });
6395
+ // TODO: support exporting part of Decl, so always use Decl if `ptr_val.pointerDecl(zcu) != .none`
6396
+ const exported: Module.Exported = switch (zcu.intern_pool.indexToKey(ptr_val.toIntern()).ptr.addr) {
6397
+ .decl => |decl_index| .{ .decl_index = decl_index },
6398
+ else => e: {
6399
+ const val = try sema.pointerDeref(block, operand_src, ptr_val, ptr_val.typeOf(zcu)) orelse
6400
+ return sema.failWithOwnedErrorMsg(block, msg: {
6401
+ const msg = try sema.errMsg(block, operand_src, "export target is not comptime-known", .{});
6402
+ errdefer msg.destroy(sema.gpa);
6403
+ try sema.errNote(block, operand_src, msg, "export must refer to global declaration or comptime-known value", .{});
6404
+ break :msg msg;
6405
+ });
6406
+ break :e .{ .value = val.toIntern() };
6407
+ },
6408
+ };
6409
+ try sema.analyzeExport(block, src, options, exported);
6422
6410
}
6423
6411
6424
6412
pub fn analyzeExport(
6425
6413
sema: *Sema,
6426
6414
block: *Block,
6427
6415
src: LazySrcLoc,
6428
6416
options: Module.Export.Options,
6429
- exported_decl_index: InternPool.DeclIndex ,
6417
+ exported: Module.Exported ,
6430
6418
) !void {
6431
6419
const gpa = sema.gpa;
6432
6420
const mod = sema.mod;
6433
6421
6434
6422
if (options.linkage == .internal)
6435
6423
return;
6436
6424
6437
- try mod.ensureDeclAnalyzed(exported_decl_index);
6438
- const exported_decl = mod.declPtr(exported_decl_index);
6439
- const export_ty = exported_decl.typeOf(mod);
6425
+ const export_val = switch (exported) {
6426
+ .decl_index => |decl_index| ty: {
6427
+ try mod.ensureDeclAnalyzed(decl_index);
6428
+ const exported_decl = mod.declPtr(decl_index);
6429
+ break :ty exported_decl.val;
6430
+ },
6431
+ .value => |ip_index| Value.fromInterned(ip_index),
6432
+ };
6433
+ if (export_val.getFunction(mod)) |func| {
6434
+ if (exported != .decl_index or exported.decl_index != func.owner_decl) {
6435
+ return sema.analyzeExport(block, src, options, .{ .decl_index = func.owner_decl });
6436
+ }
6437
+ }
6438
+ const export_ty = export_val.typeOf(mod);
6440
6439
6441
6440
if (!try sema.validateExternType(export_ty, .other)) {
6442
6441
const msg = msg: {
@@ -6452,19 +6451,29 @@ pub fn analyzeExport(
6452
6451
return sema.failWithOwnedErrorMsg(block, msg);
6453
6452
}
6454
6453
6455
- // TODO: some backends might support re-exporting extern decls
6456
- if (exported_decl.isExtern(mod)) {
6457
- return sema.fail(block, src, "export target cannot be extern", .{});
6454
+ switch (exported) {
6455
+ .decl_index => |decl_index| {
6456
+ const exported_decl = mod.declPtr(decl_index);
6457
+ // TODO: some backends might support re-exporting extern decls
6458
+ if (exported_decl.isExtern(mod)) {
6459
+ return sema.fail(block, src, "export target cannot be extern", .{});
6460
+ }
6461
+ },
6462
+ .value => {},
6458
6463
}
6459
6464
6460
- try sema.maybeQueueFuncBodyAnalysis(exported_decl_index);
6465
+ if (mod.intern_pool.isFuncBody(export_val.toIntern()) and
6466
+ try sema.fnHasRuntimeBits(export_ty))
6467
+ {
6468
+ try mod.ensureFuncBodyAnalysisQueued(export_val.toIntern());
6469
+ }
6461
6470
6462
6471
try addExport(mod, .{
6463
6472
.opts = options,
6464
6473
.src = src,
6465
6474
.owner_decl = sema.owner_decl_index,
6466
6475
.src_decl = block.src_decl,
6467
- .exported = .{ .decl_index = exported_decl_index } ,
6476
+ .exported = exported ,
6468
6477
.status = .in_progress,
6469
6478
});
6470
6479
}
0 commit comments