authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-06-27 17:12:45-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-06-27 17:12:45-07:00
log3c1daf951cf72e454de18e70f84b9a896aa17dd0
tree1d7069eba60eedb08b8cf38eb6c2b1ade1752beb
parent8d8a5f973314cb692d543773db8d59a9001b91ad

LLVM: fix invalid IR on `@returnAddress` of wasm/bpf

see #11946

4 files changed, 20 insertions(+), 5 deletions(-)

lib/std/x/os/net.zig+1-1
...@@ -433,7 +433,7 @@ pub const IPv6 = extern struct {...@@ -433,7 +433,7 @@ pub const IPv6 = extern struct {
433 '0'...'9' => fmt.parseInt(u32, scope_id_slice, 10),433 '0'...'9' => fmt.parseInt(u32, scope_id_slice, 10),
434 else => resolveScopeId(scope_id_slice) catch |err| switch (err) {434 else => resolveScopeId(scope_id_slice) catch |err| switch (err) {
435 error.InterfaceNotFound => return error.InterfaceNotFound,435 error.InterfaceNotFound => return error.InterfaceNotFound,
436 else => err,436 else => |e| return e,
437 },437 },
438 } catch return error.UnknownScopeId;438 } catch return error.UnknownScopeId;
439439
src/codegen/llvm.zig+9-2
...@@ -7212,11 +7212,17 @@ pub const FuncGen = struct {...@@ -7212,11 +7212,17 @@ pub const FuncGen = struct {
7212 fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {7212 fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
7213 if (self.liveness.isUnused(inst)) return null;7213 if (self.liveness.isUnused(inst)) return null;
72147214
7215 const llvm_usize = try self.dg.lowerType(Type.usize);
7216 const target = self.dg.module.getTarget();
7217 if (!target_util.supportsReturnAddress(target)) {
7218 // https://github.com/ziglang/zig/issues/11946
7219 return llvm_usize.constNull();
7220 }
7221
7215 const llvm_i32 = self.context.intType(32);7222 const llvm_i32 = self.context.intType(32);
7216 const llvm_fn = self.getIntrinsic("llvm.returnaddress", &.{});7223 const llvm_fn = self.getIntrinsic("llvm.returnaddress", &.{});
7217 const params = [_]*const llvm.Value{llvm_i32.constNull()};7224 const params = [_]*const llvm.Value{llvm_i32.constNull()};
7218 const ptr_val = self.builder.buildCall(llvm_fn, &params, params.len, .Fast, .Auto, "");7225 const ptr_val = self.builder.buildCall(llvm_fn, &params, params.len, .Fast, .Auto, "");
7219 const llvm_usize = try self.dg.lowerType(Type.usize);
7220 return self.builder.buildPtrToInt(ptr_val, llvm_usize, "");7226 return self.builder.buildPtrToInt(ptr_val, llvm_usize, "");
7221 }7227 }
72227228
...@@ -8021,7 +8027,6 @@ pub const FuncGen = struct {...@@ -8021,7 +8027,6 @@ pub const FuncGen = struct {
8021 assert(union_obj.haveFieldTypes());8027 assert(union_obj.haveFieldTypes());
8022 const field = union_obj.fields.values()[extra.field_index];8028 const field = union_obj.fields.values()[extra.field_index];
8023 const field_llvm_ty = try self.dg.lowerType(field.ty);8029 const field_llvm_ty = try self.dg.lowerType(field.ty);
8024 const tag_llvm_ty = try self.dg.lowerType(union_obj.tag_ty);
8025 const field_size = field.ty.abiSize(target);8030 const field_size = field.ty.abiSize(target);
8026 const field_align = field.normalAlignment(target);8031 const field_align = field.normalAlignment(target);
80278032
...@@ -8044,6 +8049,7 @@ pub const FuncGen = struct {...@@ -8044,6 +8049,7 @@ pub const FuncGen = struct {
8044 const fields: [1]*const llvm.Type = .{payload};8049 const fields: [1]*const llvm.Type = .{payload};
8045 break :t self.context.structType(&fields, fields.len, .False);8050 break :t self.context.structType(&fields, fields.len, .False);
8046 }8051 }
8052 const tag_llvm_ty = try self.dg.lowerType(union_obj.tag_ty);
8047 var fields: [3]*const llvm.Type = undefined;8053 var fields: [3]*const llvm.Type = undefined;
8048 var fields_len: c_uint = 2;8054 var fields_len: c_uint = 2;
8049 if (layout.tag_align >= layout.payload_align) {8055 if (layout.tag_align >= layout.payload_align) {
...@@ -8100,6 +8106,7 @@ pub const FuncGen = struct {...@@ -8100,6 +8106,7 @@ pub const FuncGen = struct {
8100 index_type.constInt(@boolToInt(layout.tag_align < layout.payload_align), .False),8106 index_type.constInt(@boolToInt(layout.tag_align < layout.payload_align), .False),
8101 };8107 };
8102 const field_ptr = self.builder.buildInBoundsGEP(casted_ptr, &indices, indices.len, "");8108 const field_ptr = self.builder.buildInBoundsGEP(casted_ptr, &indices, indices.len, "");
8109 const tag_llvm_ty = try self.dg.lowerType(union_obj.tag_ty);
8103 const llvm_tag = tag_llvm_ty.constInt(extra.field_index, .False);8110 const llvm_tag = tag_llvm_ty.constInt(extra.field_index, .False);
8104 const store_inst = self.builder.buildStore(llvm_tag, field_ptr);8111 const store_inst = self.builder.buildStore(llvm_tag, field_ptr);
8105 store_inst.setAlignment(union_obj.tag_ty.abiAlignment(target));8112 store_inst.setAlignment(union_obj.tag_ty.abiAlignment(target));
src/stage1/codegen.cpp+2-2
...@@ -6764,8 +6764,8 @@ static LLVMValueRef ir_render_return_address(CodeGen *g, Stage1Air *executable,...@@ -6764,8 +6764,8 @@ static LLVMValueRef ir_render_return_address(CodeGen *g, Stage1Air *executable,
6764 Stage1AirInstReturnAddress *instruction)6764 Stage1AirInstReturnAddress *instruction)
6765{6765{
6766 if ((target_is_wasm(g->zig_target) && g->zig_target->os != OsEmscripten) || target_is_bpf(g->zig_target)) {6766 if ((target_is_wasm(g->zig_target) && g->zig_target->os != OsEmscripten) || target_is_bpf(g->zig_target)) {
6767 // I got this error from LLVM 10:6767 // LLVM 13 reports "Non-Emscripten WebAssembly hasn't implemented __builtin_return_address"
6768 // "Non-Emscripten WebAssembly hasn't implemented __builtin_return_address"6768 // https://github.com/ziglang/zig/issues/11946
6769 return LLVMConstNull(get_llvm_type(g, instruction->base.value->type));6769 return LLVMConstNull(get_llvm_type(g, instruction->base.value->type));
6770 }6770 }
67716771
src/target.zig+8
...@@ -283,6 +283,14 @@ pub fn supportsStackProbing(target: std.Target) bool {...@@ -283,6 +283,14 @@ pub fn supportsStackProbing(target: std.Target) bool {
283 (target.cpu.arch == .i386 or target.cpu.arch == .x86_64);283 (target.cpu.arch == .i386 or target.cpu.arch == .x86_64);
284}284}
285285
286pub fn supportsReturnAddress(target: std.Target) bool {
287 return switch (target.cpu.arch) {
288 .wasm32, .wasm64 => target.os.tag == .emscripten,
289 .bpfel, .bpfeb => false,
290 else => true,
291 };
292}
293
286pub fn osToLLVM(os_tag: std.Target.Os.Tag) llvm.OSType {294pub fn osToLLVM(os_tag: std.Target.Os.Tag) llvm.OSType {
287 return switch (os_tag) {295 return switch (os_tag) {
288 .freestanding, .other, .opencl, .glsl450, .vulkan, .plan9 => .UnknownOS,296 .freestanding, .other, .opencl, .glsl450, .vulkan, .plan9 => .UnknownOS,