authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-16 12:26:06-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-16 12:26:06-07:00
log4d6d6977b05571e6d164dbf5f26c7a48ee3541a3
treebeb25554dc6e6f9f238ee84d0096f89a557f4ea5
parent82ec56e47e004176cc380cc69764602c4a8d0768

stage2: fixes to extern variables

* Relax compile error for "unable to export type foo" to allow integers, structs, arrays, and floats. This will need to be further improved to do the same checks as we do for C ABI struct field types. * LLVM backend: fix extern variables * LLVM backend: implement AIR instruction `wrap_err_union_payload`

3 files changed, 63 insertions(+), 22 deletions(-)

src/Module.zig+9
......@@ -754,6 +754,15 @@ pub const Decl = struct {
754754 fn removeDependency(decl: *Decl, other: *Decl) void {
755755 assert(decl.dependencies.swapRemove(other));
756756 }
757
758 pub fn isExtern(decl: Decl) bool {
759 assert(decl.has_tv);
760 return switch (decl.val.tag()) {
761 .extern_fn => true,
762 .variable => decl.val.castTag(.variable).?.data.init.tag() == .unreachable_value,
763 else => false,
764 };
765 }
757766};
758767
759768/// This state is attached to every Decl when Module emit_h is non-null.
src/Sema.zig+2-1
......@@ -3020,8 +3020,9 @@ pub fn analyzeExport(
30203020 const mod = sema.mod;
30213021
30223022 try mod.ensureDeclAnalyzed(exported_decl);
3023 // TODO run the same checks as we do for C ABI struct fields
30233024 switch (exported_decl.ty.zigTypeTag()) {
3024 .Fn => {},
3025 .Fn, .Int, .Struct, .Array, .Float => {},
30253026 else => return sema.fail(block, src, "unable to export type '{}'", .{exported_decl.ty}),
30263027 }
30273028
src/codegen/llvm.zig+52-21
......@@ -498,21 +498,21 @@ pub const Object = struct {
498498 ) !void {
499499 // If the module does not already have the function, we ignore this function call
500500 // because we call `updateDeclExports` at the end of `updateFunc` and `updateDecl`.
501 const llvm_fn = self.decl_map.get(decl) orelse return;
502 const is_extern = decl.val.tag() == .extern_fn;
501 const llvm_global = self.decl_map.get(decl) orelse return;
502 const is_extern = decl.isExtern();
503503 if (is_extern) {
504 llvm_fn.setValueName(decl.name);
505 llvm_fn.setUnnamedAddr(.False);
506 llvm_fn.setLinkage(.External);
504 llvm_global.setValueName(decl.name);
505 llvm_global.setUnnamedAddr(.False);
506 llvm_global.setLinkage(.External);
507507 } else if (exports.len != 0) {
508508 const exp_name = exports[0].options.name;
509 llvm_fn.setValueName2(exp_name.ptr, exp_name.len);
510 llvm_fn.setUnnamedAddr(.False);
509 llvm_global.setValueName2(exp_name.ptr, exp_name.len);
510 llvm_global.setUnnamedAddr(.False);
511511 switch (exports[0].options.linkage) {
512512 .Internal => unreachable,
513 .Strong => llvm_fn.setLinkage(.External),
514 .Weak => llvm_fn.setLinkage(.WeakODR),
515 .LinkOnce => llvm_fn.setLinkage(.LinkOnceODR),
513 .Strong => llvm_global.setLinkage(.External),
514 .Weak => llvm_global.setLinkage(.WeakODR),
515 .LinkOnce => llvm_global.setLinkage(.LinkOnceODR),
516516 }
517517 // If a Decl is exported more than one time (which is rare),
518518 // we add aliases for all but the first export.
......@@ -525,9 +525,9 @@ pub const Object = struct {
525525 defer module.gpa.free(exp_name_z);
526526
527527 if (self.llvm_module.getNamedGlobalAlias(exp_name_z.ptr, exp_name_z.len)) |alias| {
528 alias.setAliasee(llvm_fn);
528 alias.setAliasee(llvm_global);
529529 } else {
530 const alias = self.llvm_module.addAlias(llvm_fn.typeOf(), llvm_fn, exp_name_z);
530 const alias = self.llvm_module.addAlias(llvm_global.typeOf(), llvm_global, exp_name_z);
531531 switch (exp.options.linkage) {
532532 .Internal => alias.setLinkage(.Internal),
533533 .Strong => alias.setLinkage(.External),
......@@ -545,9 +545,9 @@ pub const Object = struct {
545545 } else {
546546 const fqn = try decl.getFullyQualifiedName(module.gpa);
547547 defer module.gpa.free(fqn);
548 llvm_fn.setValueName2(fqn.ptr, fqn.len);
549 llvm_fn.setLinkage(.Internal);
550 llvm_fn.setUnnamedAddr(.True);
548 llvm_global.setValueName2(fqn.ptr, fqn.len);
549 llvm_global.setLinkage(.Internal);
550 llvm_global.setUnnamedAddr(.True);
551551 }
552552 }
553553
......@@ -598,9 +598,10 @@ pub const DeclGen = struct {
598598 global.setGlobalConstant(.True);
599599 break :init_val decl.val;
600600 };
601
602 const llvm_init = try self.genTypedValue(.{ .ty = decl.ty, .val = init_val });
603 global.setInitializer(llvm_init);
601 if (init_val.tag() != .unreachable_value) {
602 const llvm_init = try self.genTypedValue(.{ .ty = decl.ty, .val = init_val });
603 global.setInitializer(llvm_init);
604 }
604605 }
605606 }
606607
......@@ -704,6 +705,13 @@ pub const DeclGen = struct {
704705 const llvm_addrspace = dg.llvmAddressSpace(decl.@"addrspace");
705706 const llvm_global = dg.object.llvm_module.addGlobalInAddressSpace(llvm_type, fqn, llvm_addrspace);
706707 gop.value_ptr.* = llvm_global;
708
709 const is_extern = decl.val.tag() == .unreachable_value;
710 if (!is_extern) {
711 llvm_global.setLinkage(.Internal);
712 llvm_global.setUnnamedAddr(.True);
713 }
714
707715 return llvm_global;
708716 }
709717
......@@ -2431,10 +2439,33 @@ pub const FuncGen = struct {
24312439 }
24322440
24332441 fn airWrapErrUnionPayload(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
2434 if (self.liveness.isUnused(inst))
2435 return null;
2442 if (self.liveness.isUnused(inst)) return null;
2443
2444 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2445 const payload_ty = self.air.typeOf(ty_op.operand);
2446 const operand = try self.resolveInst(ty_op.operand);
2447 if (!payload_ty.hasCodeGenBits()) {
2448 return operand;
2449 }
2450 const inst_ty = self.air.typeOfIndex(inst);
2451 const ok_err_code = self.context.intType(16).constNull();
2452 const err_un_llvm_ty = try self.dg.llvmType(inst_ty);
2453 if (isByRef(inst_ty)) {
2454 const result_ptr = self.buildAlloca(err_un_llvm_ty);
2455 const err_ptr = self.builder.buildStructGEP(result_ptr, 0, "");
2456 _ = self.builder.buildStore(ok_err_code, err_ptr);
2457 const payload_ptr = self.builder.buildStructGEP(result_ptr, 1, "");
2458 var ptr_ty_payload: Type.Payload.ElemType = .{
2459 .base = .{ .tag = .single_mut_pointer },
2460 .data = payload_ty,
2461 };
2462 const payload_ptr_ty = Type.initPayload(&ptr_ty_payload.base);
2463 self.store(payload_ptr, payload_ptr_ty, operand, .NotAtomic);
2464 return result_ptr;
2465 }
24362466
2437 return self.todo("implement llvm codegen for 'airWrapErrUnionPayload'", .{});
2467 const partial = self.builder.buildInsertValue(err_un_llvm_ty.getUndef(), ok_err_code, 0, "");
2468 return self.builder.buildInsertValue(partial, operand, 1, "");
24382469 }
24392470
24402471 fn airWrapErrUnionErr(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {