diff options
Diffstat (limited to 'src/codegen')
| -rw-r--r-- | src/codegen/c.zig | 76 | ||||
| -rw-r--r-- | src/codegen/llvm.zig | 117 | ||||
| -rw-r--r-- | src/codegen/llvm/bindings.zig | 3 |
3 files changed, 65 insertions, 131 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 45191f3107..949e2a67f2 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -752,12 +752,6 @@ pub const DeclGen = struct { const error_type = ty.errorUnionSet(); const payload_type = ty.errorUnionPayload(); - if (error_type.errorSetCardinality() == .zero) { - // We use the payload directly as the type. - const payload_val = val.castTag(.eu_payload).?.data; - return dg.renderValue(writer, payload_type, payload_val, location); - } - if (!payload_type.hasRuntimeBits()) { // We use the error type directly as the type. const err_val = if (val.errorUnionIsPayload()) Value.initTag(.zero) else val; @@ -1381,13 +1375,8 @@ pub const DeclGen = struct { return w.writeAll("uint16_t"); }, .ErrorUnion => { - const error_ty = t.errorUnionSet(); const payload_ty = t.errorUnionPayload(); - if (error_ty.errorSetCardinality() == .zero) { - return dg.renderType(w, payload_ty); - } - if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { return dg.renderType(w, Type.anyerror); } @@ -2892,41 +2881,36 @@ fn lowerTry( operand_is_ptr: bool, result_ty: Type, ) !CValue { - if (err_union_ty.errorUnionSet().errorSetCardinality() == .zero) { - // If the error set has no fields, then the payload and the error - // union are the same value. - return err_union; - } - + const writer = f.object.writer(); const payload_ty = err_union_ty.errorUnionPayload(); const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(); - const writer = f.object.writer(); - - err: { - if (!payload_has_bits) { - if (operand_is_ptr) { - try writer.writeAll("if(*"); - } else { + if (!err_union_ty.errorUnionSet().errorSetIsEmpty()) { + err: { + if (!payload_has_bits) { + if (operand_is_ptr) { + try writer.writeAll("if(*"); + } else { + try writer.writeAll("if("); + } + try f.writeCValue(writer, err_union); + try writer.writeAll(")"); + break :err; + } + if (operand_is_ptr or isByRef(err_union_ty)) { try writer.writeAll("if("); + try f.writeCValue(writer, err_union); + try writer.writeAll("->error)"); + break :err; } - try f.writeCValue(writer, err_union); - try writer.writeAll(")"); - break :err; - } - if (operand_is_ptr or isByRef(err_union_ty)) { try writer.writeAll("if("); try f.writeCValue(writer, err_union); - try writer.writeAll("->error)"); - break :err; + try writer.writeAll(".error)"); } - try writer.writeAll("if("); - try f.writeCValue(writer, err_union); - try writer.writeAll(".error)"); - } - try genBody(f, body); - try f.object.indent_writer.insertNewline(); + try genBody(f, body); + try f.object.indent_writer.insertNewline(); + } if (!payload_has_bits) { if (!operand_is_ptr) { @@ -3466,7 +3450,7 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { if (operand_ty.zigTypeTag() == .Pointer) { const err_union_ty = operand_ty.childType(); - if (err_union_ty.errorUnionSet().errorSetCardinality() == .zero) { + if (err_union_ty.errorUnionSet().errorSetIsEmpty()) { return CValue{ .bytes = "0" }; } if (!err_union_ty.errorUnionPayload().hasRuntimeBits()) { @@ -3478,7 +3462,7 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll(";\n"); return local; } - if (operand_ty.errorUnionSet().errorSetCardinality() == .zero) { + if (operand_ty.errorUnionSet().errorSetIsEmpty()) { return CValue{ .bytes = "0" }; } if (!operand_ty.errorUnionPayload().hasRuntimeBits()) { @@ -3507,10 +3491,6 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, maybe_addrof: [*:0]c const operand_is_ptr = operand_ty.zigTypeTag() == .Pointer; const error_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty; - if (error_union_ty.errorUnionSet().errorSetCardinality() == .zero) { - return operand; - } - if (!error_union_ty.errorUnionPayload().hasRuntimeBits()) { return CValue.none; } @@ -3575,11 +3555,6 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { const error_ty = error_union_ty.errorUnionSet(); const payload_ty = error_union_ty.errorUnionPayload(); - if (error_ty.errorSetCardinality() == .zero) { - // TODO: write undefined bytes through the pointer here - return operand; - } - // First, set the non-error value. if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { try f.writeCValueDeref(writer, operand); @@ -3623,9 +3598,6 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { const operand = try f.resolveInst(ty_op.operand); const inst_ty = f.air.typeOfIndex(inst); - if (inst_ty.errorUnionSet().errorSetCardinality() == .zero) { - return operand; - } const local = try f.allocLocal(inst_ty, .Const); try writer.writeAll(" = { .error = 0, .payload = "); try f.writeCValue(writer, operand); @@ -3652,7 +3624,7 @@ fn airIsErr( try writer.writeAll(" = "); - if (error_ty.errorSetCardinality() == .zero) { + if (error_ty.errorSetIsEmpty()) { try writer.print("0 {s} 0;\n", .{op_str}); } else { if (is_ptr) { diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 19a6917be4..efe6a754b6 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -599,6 +599,13 @@ pub const Object = struct { self.llvm_module.dump(); } + var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa); + defer arena_allocator.deinit(); + const arena = arena_allocator.allocator(); + + const mod = comp.bin_file.options.module.?; + const cache_dir = mod.zig_cache_artifact_directory; + if (std.debug.runtime_safety) { var error_message: [*:0]const u8 = undefined; // verifyModule always allocs the error_message even if there is no error @@ -606,17 +613,15 @@ pub const Object = struct { if (self.llvm_module.verify(.ReturnStatus, &error_message).toBool()) { std.debug.print("\n{s}\n", .{error_message}); + + if (try locPath(arena, comp.emit_llvm_ir, cache_dir)) |emit_llvm_ir_path| { + _ = self.llvm_module.printModuleToFile(emit_llvm_ir_path, &error_message); + } + @panic("LLVM module verification failed"); } } - var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa); - defer arena_allocator.deinit(); - const arena = arena_allocator.allocator(); - - const mod = comp.bin_file.options.module.?; - const cache_dir = mod.zig_cache_artifact_directory; - var emit_bin_path: ?[*:0]const u8 = if (comp.bin_file.options.emit) |emit| try emit.basenamePath(arena, try arena.dupeZ(u8, comp.bin_file.intermediary_basename.?)) else @@ -1566,22 +1571,6 @@ pub const Object = struct { }, .ErrorUnion => { const payload_ty = ty.errorUnionPayload(); - switch (ty.errorUnionSet().errorSetCardinality()) { - .zero => { - const payload_di_ty = try o.lowerDebugType(payload_ty, .full); - // The recursive call to `lowerDebugType` means we can't use `gop` anymore. - try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(payload_di_ty), .{ .mod = o.module }); - return payload_di_ty; - }, - .one => { - if (payload_ty.isNoReturn()) { - const di_type = dib.createBasicType("void", 0, DW.ATE.signed); - gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_type); - return di_type; - } - }, - .many => {}, - } if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { const err_set_di_ty = try o.lowerDebugType(Type.anyerror, .full); // The recursive call to `lowerDebugType` means we can't use `gop` anymore. @@ -2549,15 +2538,6 @@ pub const DeclGen = struct { }, .ErrorUnion => { const payload_ty = t.errorUnionPayload(); - switch (t.errorUnionSet().errorSetCardinality()) { - .zero => return dg.lowerType(payload_ty), - .one => { - if (payload_ty.isNoReturn()) { - return dg.context.voidType(); - } - }, - .many => {}, - } if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { return try dg.lowerType(Type.anyerror); } @@ -3217,10 +3197,6 @@ pub const DeclGen = struct { }, .ErrorUnion => { const payload_type = tv.ty.errorUnionPayload(); - if (tv.ty.errorUnionSet().errorSetCardinality() == .zero) { - const payload_val = tv.val.castTag(.eu_payload).?.data; - return dg.lowerValue(.{ .ty = payload_type, .val = payload_val }); - } const is_pl = tv.val.errorUnionIsPayload(); if (!payload_type.hasRuntimeBitsIgnoreComptime()) { @@ -4790,40 +4766,37 @@ pub const FuncGen = struct { } fn lowerTry(fg: *FuncGen, err_union: *const llvm.Value, body: []const Air.Inst.Index, err_union_ty: Type, operand_is_ptr: bool, result_ty: Type) !?*const llvm.Value { - if (err_union_ty.errorUnionSet().errorSetCardinality() == .zero) { - // If the error set has no fields, then the payload and the error - // union are the same value. - return err_union; - } - const payload_ty = err_union_ty.errorUnionPayload(); const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(); const target = fg.dg.module.getTarget(); - const is_err = err: { - const err_set_ty = try fg.dg.lowerType(Type.anyerror); - const zero = err_set_ty.constNull(); - if (!payload_has_bits) { - const loaded = if (operand_is_ptr) fg.builder.buildLoad(err_union, "") else err_union; - break :err fg.builder.buildICmp(.NE, loaded, zero, ""); - } - const err_field_index = errUnionErrorOffset(payload_ty, target); - if (operand_is_ptr or isByRef(err_union_ty)) { - const err_field_ptr = fg.builder.buildStructGEP(err_union, err_field_index, ""); - const loaded = fg.builder.buildLoad(err_field_ptr, ""); + + if (!err_union_ty.errorUnionSet().errorSetIsEmpty()) { + const is_err = err: { + const err_set_ty = try fg.dg.lowerType(Type.anyerror); + const zero = err_set_ty.constNull(); + if (!payload_has_bits) { + const loaded = if (operand_is_ptr) fg.builder.buildLoad(err_union, "") else err_union; + break :err fg.builder.buildICmp(.NE, loaded, zero, ""); + } + const err_field_index = errUnionErrorOffset(payload_ty, target); + if (operand_is_ptr or isByRef(err_union_ty)) { + const err_field_ptr = fg.builder.buildStructGEP(err_union, err_field_index, ""); + const loaded = fg.builder.buildLoad(err_field_ptr, ""); + break :err fg.builder.buildICmp(.NE, loaded, zero, ""); + } + const loaded = fg.builder.buildExtractValue(err_union, err_field_index, ""); break :err fg.builder.buildICmp(.NE, loaded, zero, ""); - } - const loaded = fg.builder.buildExtractValue(err_union, err_field_index, ""); - break :err fg.builder.buildICmp(.NE, loaded, zero, ""); - }; + }; - const return_block = fg.context.appendBasicBlock(fg.llvm_func, "TryRet"); - const continue_block = fg.context.appendBasicBlock(fg.llvm_func, "TryCont"); - _ = fg.builder.buildCondBr(is_err, return_block, continue_block); + const return_block = fg.context.appendBasicBlock(fg.llvm_func, "TryRet"); + const continue_block = fg.context.appendBasicBlock(fg.llvm_func, "TryCont"); + _ = fg.builder.buildCondBr(is_err, return_block, continue_block); - fg.builder.positionBuilderAtEnd(return_block); - try fg.genBody(body); + fg.builder.positionBuilderAtEnd(return_block); + try fg.genBody(body); - fg.builder.positionBuilderAtEnd(continue_block); + fg.builder.positionBuilderAtEnd(continue_block); + } if (!payload_has_bits) { if (!operand_is_ptr) return null; @@ -5660,7 +5633,7 @@ pub const FuncGen = struct { const err_set_ty = try self.dg.lowerType(Type.initTag(.anyerror)); const zero = err_set_ty.constNull(); - if (err_union_ty.errorUnionSet().errorSetCardinality() == .zero) { + if (err_union_ty.errorUnionSet().errorSetIsEmpty()) { const llvm_i1 = self.context.intType(1); switch (op) { .EQ => return llvm_i1.constInt(1, .False), // 0 == 0 @@ -5783,13 +5756,6 @@ pub const FuncGen = struct { const ty_op = self.air.instructions.items(.data)[inst].ty_op; const operand = try self.resolveInst(ty_op.operand); - const operand_ty = self.air.typeOf(ty_op.operand); - const error_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty; - if (error_union_ty.errorUnionSet().errorSetCardinality() == .zero) { - // If the error set has no fields, then the payload and the error - // union are the same value. - return operand; - } const result_ty = self.air.typeOfIndex(inst); const payload_ty = if (operand_is_ptr) result_ty.childType() else result_ty; const target = self.dg.module.getTarget(); @@ -5820,7 +5786,7 @@ pub const FuncGen = struct { const operand = try self.resolveInst(ty_op.operand); const operand_ty = self.air.typeOf(ty_op.operand); const err_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty; - if (err_union_ty.errorUnionSet().errorSetCardinality() == .zero) { + if (err_union_ty.errorUnionSet().errorSetIsEmpty()) { const err_llvm_ty = try self.dg.lowerType(Type.anyerror); if (operand_is_ptr) { return self.builder.buildBitCast(operand, err_llvm_ty.pointerType(0), ""); @@ -5851,10 +5817,6 @@ pub const FuncGen = struct { const operand = try self.resolveInst(ty_op.operand); const error_union_ty = self.air.typeOf(ty_op.operand).childType(); - if (error_union_ty.errorUnionSet().errorSetCardinality() == .zero) { - // TODO: write undefined bytes through the pointer here - return operand; - } const payload_ty = error_union_ty.errorUnionPayload(); const non_error_val = try self.dg.lowerValue(.{ .ty = Type.anyerror, .val = Value.zero }); if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { @@ -5933,9 +5895,6 @@ pub const FuncGen = struct { const ty_op = self.air.instructions.items(.data)[inst].ty_op; const inst_ty = self.air.typeOfIndex(inst); const operand = try self.resolveInst(ty_op.operand); - if (inst_ty.errorUnionSet().errorSetCardinality() == .zero) { - return operand; - } const payload_ty = self.air.typeOf(ty_op.operand); if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { return operand; diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig index ca748d3ce3..671014ba3b 100644 --- a/src/codegen/llvm/bindings.zig +++ b/src/codegen/llvm/bindings.zig @@ -390,6 +390,9 @@ pub const Module = opaque { pub const setModuleInlineAsm2 = LLVMSetModuleInlineAsm2; extern fn LLVMSetModuleInlineAsm2(M: *const Module, Asm: [*]const u8, Len: usize) void; + + pub const printModuleToFile = LLVMPrintModuleToFile; + extern fn LLVMPrintModuleToFile(M: *const Module, Filename: [*:0]const u8, ErrorMessage: *[*:0]const u8) Bool; }; pub const lookupIntrinsicID = LLVMLookupIntrinsicID; |
