From 8d8a5f973314cb692d543773db8d59a9001b91ad Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 27 Jun 2022 16:02:41 -0700 Subject: LLVM: support calls to varargs functions closes #11944 --- src/codegen/llvm.zig | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'src/codegen') diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index bf09ec0f35..29e25f1079 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -4197,7 +4197,7 @@ pub const FuncGen = struct { } var it = iterateParamTypes(self.dg, fn_info); - while (it.next()) |lowering| switch (lowering) { + while (it.nextCall(self, args)) |lowering| switch (lowering) { .no_bits => continue, .byval => { const arg = args[it.zig_index - 1]; @@ -9004,10 +9004,26 @@ const ParamTypeIterator = struct { slice, }; - fn next(it: *ParamTypeIterator) ?Lowering { + pub fn next(it: *ParamTypeIterator) ?Lowering { if (it.zig_index >= it.fn_info.param_types.len) return null; - const ty = it.fn_info.param_types[it.zig_index]; + return nextInner(it, ty); + } + + /// `airCall` uses this instead of `next` so that it can take into account variadic functions. + pub fn nextCall(it: *ParamTypeIterator, fg: *FuncGen, args: []const Air.Inst.Ref) ?Lowering { + if (it.zig_index >= it.fn_info.param_types.len) { + if (it.zig_index >= args.len) { + return null; + } else { + return nextInner(it, fg.air.typeOf(args[it.zig_index])); + } + } else { + return nextInner(it, it.fn_info.param_types[it.zig_index]); + } + } + + fn nextInner(it: *ParamTypeIterator, ty: Type) ?Lowering { if (!ty.hasRuntimeBitsIgnoreComptime()) { it.zig_index += 1; return .no_bits; -- cgit v1.2.3 From 3c1daf951cf72e454de18e70f84b9a896aa17dd0 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 27 Jun 2022 17:12:45 -0700 Subject: LLVM: fix invalid IR on `@returnAddress` of wasm/bpf see #11946 --- lib/std/x/os/net.zig | 2 +- src/codegen/llvm.zig | 11 +++++++++-- src/stage1/codegen.cpp | 4 ++-- src/target.zig | 8 ++++++++ 4 files changed, 20 insertions(+), 5 deletions(-) (limited to 'src/codegen') diff --git a/lib/std/x/os/net.zig b/lib/std/x/os/net.zig index a7cc8fbc4a..98d63969b9 100644 --- a/lib/std/x/os/net.zig +++ b/lib/std/x/os/net.zig @@ -433,7 +433,7 @@ pub const IPv6 = extern struct { '0'...'9' => fmt.parseInt(u32, scope_id_slice, 10), else => resolveScopeId(scope_id_slice) catch |err| switch (err) { error.InterfaceNotFound => return error.InterfaceNotFound, - else => err, + else => |e| return e, }, } catch return error.UnknownScopeId; diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 29e25f1079..2b320923ad 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -7212,11 +7212,17 @@ pub const FuncGen = struct { fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { if (self.liveness.isUnused(inst)) return null; + const llvm_usize = try self.dg.lowerType(Type.usize); + const target = self.dg.module.getTarget(); + if (!target_util.supportsReturnAddress(target)) { + // https://github.com/ziglang/zig/issues/11946 + return llvm_usize.constNull(); + } + const llvm_i32 = self.context.intType(32); const llvm_fn = self.getIntrinsic("llvm.returnaddress", &.{}); const params = [_]*const llvm.Value{llvm_i32.constNull()}; const ptr_val = self.builder.buildCall(llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); - const llvm_usize = try self.dg.lowerType(Type.usize); return self.builder.buildPtrToInt(ptr_val, llvm_usize, ""); } @@ -8021,7 +8027,6 @@ pub const FuncGen = struct { assert(union_obj.haveFieldTypes()); const field = union_obj.fields.values()[extra.field_index]; const field_llvm_ty = try self.dg.lowerType(field.ty); - const tag_llvm_ty = try self.dg.lowerType(union_obj.tag_ty); const field_size = field.ty.abiSize(target); const field_align = field.normalAlignment(target); @@ -8044,6 +8049,7 @@ pub const FuncGen = struct { const fields: [1]*const llvm.Type = .{payload}; break :t self.context.structType(&fields, fields.len, .False); } + const tag_llvm_ty = try self.dg.lowerType(union_obj.tag_ty); var fields: [3]*const llvm.Type = undefined; var fields_len: c_uint = 2; if (layout.tag_align >= layout.payload_align) { @@ -8100,6 +8106,7 @@ pub const FuncGen = struct { index_type.constInt(@boolToInt(layout.tag_align < layout.payload_align), .False), }; const field_ptr = self.builder.buildInBoundsGEP(casted_ptr, &indices, indices.len, ""); + const tag_llvm_ty = try self.dg.lowerType(union_obj.tag_ty); const llvm_tag = tag_llvm_ty.constInt(extra.field_index, .False); const store_inst = self.builder.buildStore(llvm_tag, field_ptr); store_inst.setAlignment(union_obj.tag_ty.abiAlignment(target)); diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp index d6fb6d4753..318a90732c 100644 --- a/src/stage1/codegen.cpp +++ b/src/stage1/codegen.cpp @@ -6764,8 +6764,8 @@ static LLVMValueRef ir_render_return_address(CodeGen *g, Stage1Air *executable, Stage1AirInstReturnAddress *instruction) { if ((target_is_wasm(g->zig_target) && g->zig_target->os != OsEmscripten) || target_is_bpf(g->zig_target)) { - // I got this error from LLVM 10: - // "Non-Emscripten WebAssembly hasn't implemented __builtin_return_address" + // LLVM 13 reports "Non-Emscripten WebAssembly hasn't implemented __builtin_return_address" + // https://github.com/ziglang/zig/issues/11946 return LLVMConstNull(get_llvm_type(g, instruction->base.value->type)); } diff --git a/src/target.zig b/src/target.zig index 14af2675d2..93c179b7f0 100644 --- a/src/target.zig +++ b/src/target.zig @@ -283,6 +283,14 @@ pub fn supportsStackProbing(target: std.Target) bool { (target.cpu.arch == .i386 or target.cpu.arch == .x86_64); } +pub fn supportsReturnAddress(target: std.Target) bool { + return switch (target.cpu.arch) { + .wasm32, .wasm64 => target.os.tag == .emscripten, + .bpfel, .bpfeb => false, + else => true, + }; +} + pub fn osToLLVM(os_tag: std.Target.Os.Tag) llvm.OSType { return switch (os_tag) { .freestanding, .other, .opencl, .glsl450, .vulkan, .plan9 => .UnknownOS, -- cgit v1.2.3