aboutsummaryrefslogtreecommitdiff
path: root/src/codegen
diff options
context:
space:
mode:
Diffstat (limited to 'src/codegen')
-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