aboutsummaryrefslogtreecommitdiff
path: root/src/codegen/llvm.zig
diff options
context:
space:
mode:
authorTimon Kruiper <timonkruiper@gmail.com>2021-03-23 14:23:51 +0100
committerAndrew Kelley <andrew@ziglang.org>2021-03-23 11:42:46 -0700
commitd73b0473a1df98703d5c742d59e57e225cfa7ba4 (patch)
tree0610e8c2ed10434c315e4c89b0d2ce102944792e /src/codegen/llvm.zig
parent668148549a822c7fa680cf08999dd845bde765aa (diff)
downloadzig-d73b0473a1df98703d5c742d59e57e225cfa7ba4.tar.gz
zig-d73b0473a1df98703d5c742d59e57e225cfa7ba4.zip
stage2: rename fail to todo in LLVM backend
This way we don't have to pass src to every function and we can simply use the first node as the lazy source location for all the todo errors.
Diffstat (limited to 'src/codegen/llvm.zig')
-rw-r--r--src/codegen/llvm.zig98
1 files changed, 48 insertions, 50 deletions
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index 06f70db665..e78bd8d103 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -305,11 +305,11 @@ pub const DeclGen = struct {
gpa: *Allocator,
- fn fail(self: *DeclGen, src: LazySrcLoc, comptime format: []const u8, args: anytype) error{ OutOfMemory, CodegenFail } {
+ fn todo(self: *DeclGen, comptime format: []const u8, args: anytype) error{ OutOfMemory, CodegenFail } {
@setCold(true);
assert(self.err_msg == null);
- const src_loc = src.toSrcLocWithDecl(self.decl);
- self.err_msg = try Module.ErrorMsg.create(self.gpa, src_loc, format, args);
+ const src_loc = @as(LazySrcLoc, .{ .node_offset = 0 }).toSrcLocWithDecl(self.decl);
+ self.err_msg = try Module.ErrorMsg.create(self.gpa, src_loc, "TODO (LLVM): " ++ format, args);
return error.CodegenFail;
}
@@ -325,14 +325,12 @@ pub const DeclGen = struct {
const decl = self.decl;
const typed_value = decl.typed_value.most_recent.typed_value;
- const src = decl.srcLoc().lazy;
-
log.debug("gen: {s} type: {}, value: {}", .{ decl.name, typed_value.ty, typed_value.val });
if (typed_value.val.castTag(.function)) |func_payload| {
const func = func_payload.data;
- const llvm_func = try self.resolveLLVMFunction(func.owner_decl, src);
+ const llvm_func = try self.resolveLLVMFunction(func.owner_decl);
// This gets the LLVM values from the function and stores them in `self.args`.
const fn_param_len = func.owner_decl.typed_value.most_recent.typed_value.ty.fnParamLen();
@@ -369,14 +367,14 @@ pub const DeclGen = struct {
try fg.genBody(func.body);
} else if (typed_value.val.castTag(.extern_fn)) |extern_fn| {
- _ = try self.resolveLLVMFunction(extern_fn.data, src);
+ _ = try self.resolveLLVMFunction(extern_fn.data);
} else {
- _ = try self.resolveGlobalDecl(decl, src);
+ _ = try self.resolveGlobalDecl(decl);
}
}
/// If the llvm function does not exist, create it
- fn resolveLLVMFunction(self: *DeclGen, func: *Module.Decl, src: LazySrcLoc) !*const llvm.Value {
+ fn resolveLLVMFunction(self: *DeclGen, func: *Module.Decl) !*const llvm.Value {
// TODO: do we want to store this in our own datastructure?
if (self.llvmModule().getNamedFunction(func.name)) |llvm_fn| return llvm_fn;
@@ -393,11 +391,11 @@ pub const DeclGen = struct {
defer self.gpa.free(llvm_param);
for (fn_param_types) |fn_param, i| {
- llvm_param[i] = try self.getLLVMType(fn_param, src);
+ llvm_param[i] = try self.getLLVMType(fn_param);
}
const fn_type = llvm.Type.functionType(
- try self.getLLVMType(return_type, src),
+ try self.getLLVMType(return_type),
if (fn_param_len == 0) null else llvm_param.ptr,
@intCast(c_uint, fn_param_len),
.False,
@@ -411,15 +409,15 @@ pub const DeclGen = struct {
return llvm_fn;
}
- fn resolveGlobalDecl(self: *DeclGen, decl: *Module.Decl, src: LazySrcLoc) error{ OutOfMemory, CodegenFail }!*const llvm.Value {
+ fn resolveGlobalDecl(self: *DeclGen, decl: *Module.Decl) error{ OutOfMemory, CodegenFail }!*const llvm.Value {
// TODO: do we want to store this in our own datastructure?
if (self.llvmModule().getNamedGlobal(decl.name)) |val| return val;
const typed_value = decl.typed_value.most_recent.typed_value;
// TODO: remove this redundant `getLLVMType`, it is also called in `genTypedValue`.
- const llvm_type = try self.getLLVMType(typed_value.ty, src);
- const val = try self.genTypedValue(src, typed_value, null);
+ const llvm_type = try self.getLLVMType(typed_value.ty);
+ const val = try self.genTypedValue(typed_value, null);
const global = self.llvmModule().addGlobal(llvm_type, decl.name);
llvm.setInitializer(global, val);
@@ -429,7 +427,7 @@ pub const DeclGen = struct {
return global;
}
- fn getLLVMType(self: *DeclGen, t: Type, src: LazySrcLoc) error{ OutOfMemory, CodegenFail }!*const llvm.Type {
+ fn getLLVMType(self: *DeclGen, t: Type) error{ OutOfMemory, CodegenFail }!*const llvm.Type {
switch (t.zigTypeTag()) {
.Void => return self.context().voidType(),
.NoReturn => return self.context().voidType(),
@@ -440,14 +438,14 @@ pub const DeclGen = struct {
.Bool => return self.context().intType(1),
.Pointer => {
if (t.isSlice()) {
- return self.fail(src, "TODO: LLVM backend: implement slices", .{});
+ return self.todo("implement slices", .{});
} else {
- const elem_type = try self.getLLVMType(t.elemType(), src);
+ const elem_type = try self.getLLVMType(t.elemType());
return elem_type.pointerType(0);
}
},
.Array => {
- const elem_type = try self.getLLVMType(t.elemType(), src);
+ const elem_type = try self.getLLVMType(t.elemType());
return elem_type.arrayType(@intCast(c_uint, t.abiSize(self.module.getTarget())));
},
.Optional => {
@@ -456,21 +454,21 @@ pub const DeclGen = struct {
const child_type = t.optionalChild(&buf);
var optional_types: [2]*const llvm.Type = .{
- try self.getLLVMType(child_type, src),
+ try self.getLLVMType(child_type),
self.context().intType(1),
};
return self.context().structType(&optional_types, 2, .False);
} else {
- return self.fail(src, "TODO implement optional pointers as actual pointers", .{});
+ return self.todo("implement optional pointers as actual pointers", .{});
}
},
- else => return self.fail(src, "TODO implement getLLVMType for type '{}'", .{t}),
+ else => return self.todo("implement getLLVMType for type '{}'", .{t}),
}
}
// TODO: figure out a way to remove the FuncGen argument
- fn genTypedValue(self: *DeclGen, src: LazySrcLoc, tv: TypedValue, fg: ?*FuncGen) error{ OutOfMemory, CodegenFail }!*const llvm.Value {
- const llvm_type = try self.getLLVMType(tv.ty, src);
+ fn genTypedValue(self: *DeclGen, tv: TypedValue, fg: ?*FuncGen) error{ OutOfMemory, CodegenFail }!*const llvm.Value {
+ const llvm_type = try self.getLLVMType(tv.ty);
if (tv.val.isUndef())
return llvm_type.getUndef();
@@ -484,7 +482,7 @@ pub const DeclGen = struct {
if (bigint.eqZero()) return llvm_type.constNull();
if (bigint.limbs.len != 1) {
- return self.fail(src, "TODO implement bigger bigint", .{});
+ return self.todo("implement bigger bigint", .{});
}
const llvm_int = llvm_type.constInt(bigint.limbs[0], .False);
if (!bigint.positive) {
@@ -495,9 +493,9 @@ pub const DeclGen = struct {
.Pointer => switch (tv.val.tag()) {
.decl_ref => {
const decl = tv.val.castTag(.decl_ref).?.data;
- const val = try self.resolveGlobalDecl(decl, src);
+ const val = try self.resolveGlobalDecl(decl);
- const usize_type = try self.getLLVMType(Type.initTag(.usize), src);
+ const usize_type = try self.getLLVMType(Type.initTag(.usize));
// TODO: second index should be the index into the memory!
var indices: [2]*const llvm.Value = .{
@@ -511,29 +509,29 @@ pub const DeclGen = struct {
.ref_val => {
const elem_value = tv.val.castTag(.ref_val).?.data;
const elem_type = tv.ty.castPointer().?.data;
- const alloca = fg.?.buildAlloca(try self.getLLVMType(elem_type, src));
- _ = fg.?.builder.buildStore(try self.genTypedValue(src, .{ .ty = elem_type, .val = elem_value }, fg), alloca);
+ const alloca = fg.?.buildAlloca(try self.getLLVMType(elem_type));
+ _ = fg.?.builder.buildStore(try self.genTypedValue(.{ .ty = elem_type, .val = elem_value }, fg), alloca);
return alloca;
},
- else => return self.fail(src, "TODO implement const of pointer type '{}'", .{tv.ty}),
+ else => return self.todo("implement const of pointer type '{}'", .{tv.ty}),
},
.Array => {
if (tv.val.castTag(.bytes)) |payload| {
const zero_sentinel = if (tv.ty.sentinel()) |sentinel| blk: {
if (sentinel.tag() == .zero) break :blk true;
- return self.fail(src, "TODO handle other sentinel values", .{});
+ return self.todo("handle other sentinel values", .{});
} else false;
return self.context().constString(payload.data.ptr, @intCast(c_uint, payload.data.len), llvm.Bool.fromBool(!zero_sentinel));
} else {
- return self.fail(src, "TODO handle more array values", .{});
+ return self.todo("handle more array values", .{});
}
},
.Optional => {
if (!tv.ty.isPtrLikeOptional()) {
var buf: Type.Payload.ElemType = undefined;
const child_type = tv.ty.optionalChild(&buf);
- const llvm_child_type = try self.getLLVMType(child_type, src);
+ const llvm_child_type = try self.getLLVMType(child_type);
if (tv.val.tag() == .null_value) {
var optional_values: [2]*const llvm.Value = .{
@@ -543,16 +541,16 @@ pub const DeclGen = struct {
return self.context().constStruct(&optional_values, 2, .False);
} else {
var optional_values: [2]*const llvm.Value = .{
- try self.genTypedValue(src, .{ .ty = child_type, .val = tv.val }, fg),
+ try self.genTypedValue(.{ .ty = child_type, .val = tv.val }, fg),
self.context().intType(1).constAllOnes(),
};
return self.context().constStruct(&optional_values, 2, .False);
}
} else {
- return self.fail(src, "TODO implement const of optional pointer", .{});
+ return self.todo("implement const of optional pointer", .{});
}
},
- else => return self.fail(src, "TODO implement const of type '{}'", .{tv.ty}),
+ else => return self.todo("implement const of type '{}'", .{tv.ty}),
}
}
@@ -609,9 +607,9 @@ pub const FuncGen = struct {
self.blocks.deinit(self.gpa());
}
- fn fail(self: *FuncGen, src: LazySrcLoc, comptime format: []const u8, args: anytype) error{ OutOfMemory, CodegenFail } {
+ fn todo(self: *FuncGen, comptime format: []const u8, args: anytype) error{ OutOfMemory, CodegenFail } {
@setCold(true);
- return self.dg.fail(src, format, args);
+ return self.dg.todo(format, args);
}
fn llvmModule(self: *FuncGen) *const llvm.Module {
@@ -628,11 +626,11 @@ pub const FuncGen = struct {
fn resolveInst(self: *FuncGen, inst: *ir.Inst) !*const llvm.Value {
if (inst.value()) |val| {
- return self.dg.genTypedValue(inst.src, .{ .ty = inst.ty, .val = val }, self);
+ return self.dg.genTypedValue(.{ .ty = inst.ty, .val = val }, self);
}
if (self.func_inst_table.get(inst)) |value| return value;
- return self.fail(inst.src, "TODO implement global llvm values (or the value is not in the func_inst_table table)", .{});
+ return self.todo("implement global llvm values (or the value is not in the func_inst_table table)", .{});
}
fn genBody(self: *FuncGen, body: ir.Body) error{ OutOfMemory, CodegenFail }!void {
@@ -673,7 +671,7 @@ pub const FuncGen = struct {
// TODO: implement debug info
break :blk null;
},
- else => |tag| return self.fail(inst.src, "TODO implement LLVM codegen for Zir instruction: {}", .{tag}),
+ else => |tag| return self.todo("implement TZIR instruction: {}", .{tag}),
};
if (opt_value) |val| try self.func_inst_table.putNoClobber(self.gpa(), inst, val);
}
@@ -689,7 +687,7 @@ pub const FuncGen = struct {
unreachable;
const zig_fn_type = fn_decl.typed_value.most_recent.typed_value.ty;
- const llvm_fn = try self.dg.resolveLLVMFunction(fn_decl, inst.base.src);
+ const llvm_fn = try self.dg.resolveLLVMFunction(fn_decl);
const num_args = inst.args.len;
@@ -719,7 +717,7 @@ pub const FuncGen = struct {
return call;
} else {
- return self.fail(inst.base.src, "TODO implement calling runtime known function pointer LLVM backend", .{});
+ return self.todo("implement calling runtime known function pointer", .{});
}
}
@@ -739,7 +737,7 @@ pub const FuncGen = struct {
if (!inst.base.ty.isInt())
if (inst.base.ty.tag() != .bool)
- return self.fail(inst.base.src, "TODO implement 'genCmp' for type {}", .{inst.base.ty});
+ return self.todo("implement 'genCmp' for type {}", .{inst.base.ty});
const is_signed = inst.base.ty.isSignedInt();
const operation = switch (op) {
@@ -779,7 +777,7 @@ pub const FuncGen = struct {
// If the block does not return a value, we dont have to create a phi node.
if (!inst.base.ty.hasCodeGenBits()) return null;
- const phi_node = self.builder.buildPhi(try self.dg.getLLVMType(inst.base.ty, inst.base.src), "");
+ const phi_node = self.builder.buildPhi(try self.dg.getLLVMType(inst.base.ty), "");
phi_node.addIncoming(
break_vals.items.ptr,
break_bbs.items.ptr,
@@ -897,7 +895,7 @@ pub const FuncGen = struct {
const rhs = try self.resolveInst(inst.rhs);
if (!inst.base.ty.isInt())
- return self.fail(inst.base.src, "TODO implement 'genAdd' for type {}", .{inst.base.ty});
+ return self.todo("implement 'genAdd' for type {}", .{inst.base.ty});
return if (inst.base.ty.isSignedInt())
self.builder.buildNSWAdd(lhs, rhs, "")
@@ -910,7 +908,7 @@ pub const FuncGen = struct {
const rhs = try self.resolveInst(inst.rhs);
if (!inst.base.ty.isInt())
- return self.fail(inst.base.src, "TODO implement 'genSub' for type {}", .{inst.base.ty});
+ return self.todo("implement 'genSub' for type {}", .{inst.base.ty});
return if (inst.base.ty.isSignedInt())
self.builder.buildNSWSub(lhs, rhs, "")
@@ -924,12 +922,12 @@ pub const FuncGen = struct {
const signed = inst.base.ty.isSignedInt();
// TODO: Should we use intcast here or just a simple bitcast?
// LLVM does truncation vs bitcast (+signed extension) in the intcast depending on the sizes
- return self.builder.buildIntCast2(val, try self.dg.getLLVMType(inst.base.ty, inst.base.src), llvm.Bool.fromBool(signed), "");
+ return self.builder.buildIntCast2(val, try self.dg.getLLVMType(inst.base.ty), llvm.Bool.fromBool(signed), "");
}
fn genBitCast(self: *FuncGen, inst: *Inst.UnOp) !?*const llvm.Value {
const val = try self.resolveInst(inst.operand);
- const dest_type = try self.dg.getLLVMType(inst.base.ty, inst.base.src);
+ const dest_type = try self.dg.getLLVMType(inst.base.ty);
return self.builder.buildBitCast(val, dest_type, "");
}
@@ -938,7 +936,7 @@ pub const FuncGen = struct {
const arg_val = self.args[self.arg_index];
self.arg_index += 1;
- const ptr_val = self.buildAlloca(try self.dg.getLLVMType(inst.base.ty, inst.base.src));
+ const ptr_val = self.buildAlloca(try self.dg.getLLVMType(inst.base.ty));
_ = self.builder.buildStore(arg_val, ptr_val);
return self.builder.buildLoad(ptr_val, "");
}
@@ -950,7 +948,7 @@ pub const FuncGen = struct {
// TODO: figure out a way to get the name of the var decl.
// TODO: set alignment and volatile
- return self.buildAlloca(try self.dg.getLLVMType(pointee_type, inst.base.src));
+ return self.buildAlloca(try self.dg.getLLVMType(pointee_type));
}
/// Use this instead of builder.buildAlloca, because this function makes sure to