aboutsummaryrefslogtreecommitdiff
path: root/src/codegen
diff options
context:
space:
mode:
Diffstat (limited to 'src/codegen')
-rw-r--r--src/codegen/c.zig76
-rw-r--r--src/codegen/llvm.zig117
-rw-r--r--src/codegen/llvm/bindings.zig3
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;