authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-07-18 22:49:46-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-07-20 12:19:16-07:00
log95756299af77a83564c2dbae09884be20ffe0c5c
treeab55797fbb3d4989abece061ccd7156aaed8f391
parentbf8e347b1b99ab711036c76df44a4eed2f6677d5

stage2: fix compile errors in LLVM backend


3 files changed, 95 insertions(+), 51 deletions(-)

src/codegen/llvm.zig+74-47
...@@ -276,10 +276,71 @@ pub const Object = struct {...@@ -276,10 +276,71 @@ pub const Object = struct {
276 }276 }
277 }277 }
278278
279 pub fn updateDecl(self: *Object, module: *Module, decl: *Module.Decl) !void {279 pub fn updateFunc(
280 const tracy = trace(@src());280 self: *Object,
281 defer tracy.end();281 module: *Module,
282 func: *Module.Fn,
283 air: Air,
284 liveness: Liveness,
285 ) !void {
286 var dg: DeclGen = .{
287 .object = self,
288 .module = module,
289 .decl = func.owner_decl,
290 .err_msg = null,
291 .gpa = module.gpa,
292 };
293
294 const llvm_func = try dg.resolveLLVMFunction(func.owner_decl);
295
296 // This gets the LLVM values from the function and stores them in `dg.args`.
297 const fn_param_len = func.owner_decl.ty.fnParamLen();
298 var args = try dg.gpa.alloc(*const llvm.Value, fn_param_len);
282299
300 for (args) |*arg, i| {
301 arg.* = llvm.getParam(llvm_func, @intCast(c_uint, i));
302 }
303
304 // We remove all the basic blocks of a function to support incremental
305 // compilation!
306 // TODO: remove all basic blocks if functions can have more than one
307 if (llvm_func.getFirstBasicBlock()) |bb| {
308 bb.deleteBasicBlock();
309 }
310
311 const builder = dg.context().createBuilder();
312
313 const entry_block = dg.context().appendBasicBlock(llvm_func, "Entry");
314 builder.positionBuilderAtEnd(entry_block);
315
316 var fg: FuncGen = .{
317 .gpa = dg.gpa,
318 .air = air,
319 .liveness = liveness,
320 .dg = &dg,
321 .builder = builder,
322 .args = args,
323 .arg_index = 0,
324 .func_inst_table = .{},
325 .entry_block = entry_block,
326 .latest_alloca_inst = null,
327 .llvm_func = llvm_func,
328 .blocks = .{},
329 };
330 defer fg.deinit();
331
332 fg.genBody(air.getMainBody()) catch |err| switch (err) {
333 error.CodegenFail => {
334 func.owner_decl.analysis = .codegen_failure;
335 try module.failed_decls.put(module.gpa, func.owner_decl, dg.err_msg.?);
336 dg.err_msg = null;
337 return;
338 },
339 else => |e| return e,
340 };
341 }
342
343 pub fn updateDecl(self: *Object, module: *Module, decl: *Module.Decl) !void {
283 var dg: DeclGen = .{344 var dg: DeclGen = .{
284 .object = self,345 .object = self,
285 .module = module,346 .module = module,
...@@ -330,45 +391,8 @@ pub const DeclGen = struct {...@@ -330,45 +391,8 @@ pub const DeclGen = struct {
330 log.debug("gen: {s} type: {}, value: {}", .{ decl.name, decl.ty, decl.val });391 log.debug("gen: {s} type: {}, value: {}", .{ decl.name, decl.ty, decl.val });
331392
332 if (decl.val.castTag(.function)) |func_payload| {393 if (decl.val.castTag(.function)) |func_payload| {
333 const func = func_payload.data;394 _ = func_payload;
334395 @panic("TODO llvm backend genDecl function pointer");
335 const llvm_func = try self.resolveLLVMFunction(func.owner_decl);
336
337 // This gets the LLVM values from the function and stores them in `self.args`.
338 const fn_param_len = func.owner_decl.ty.fnParamLen();
339 var args = try self.gpa.alloc(*const llvm.Value, fn_param_len);
340
341 for (args) |*arg, i| {
342 arg.* = llvm.getParam(llvm_func, @intCast(c_uint, i));
343 }
344
345 // We remove all the basic blocks of a function to support incremental
346 // compilation!
347 // TODO: remove all basic blocks if functions can have more than one
348 if (llvm_func.getFirstBasicBlock()) |bb| {
349 bb.deleteBasicBlock();
350 }
351
352 const builder = self.context().createBuilder();
353
354 const entry_block = self.context().appendBasicBlock(llvm_func, "Entry");
355 builder.positionBuilderAtEnd(entry_block);
356
357 var fg: FuncGen = .{
358 .gpa = self.gpa,
359 .dg = self,
360 .builder = builder,
361 .args = args,
362 .arg_index = 0,
363 .func_inst_table = .{},
364 .entry_block = entry_block,
365 .latest_alloca_inst = null,
366 .llvm_func = llvm_func,
367 .blocks = .{},
368 };
369 defer fg.deinit();
370
371 try fg.genBody(func.body);
372 } else if (decl.val.castTag(.extern_fn)) |extern_fn| {396 } else if (decl.val.castTag(.extern_fn)) |extern_fn| {
373 _ = try self.resolveLLVMFunction(extern_fn.data);397 _ = try self.resolveLLVMFunction(extern_fn.data);
374 } else {398 } else {
...@@ -596,6 +620,8 @@ pub const DeclGen = struct {...@@ -596,6 +620,8 @@ pub const DeclGen = struct {
596pub const FuncGen = struct {620pub const FuncGen = struct {
597 gpa: *Allocator,621 gpa: *Allocator,
598 dg: *DeclGen,622 dg: *DeclGen,
623 air: Air,
624 liveness: Liveness,
599625
600 builder: *const llvm.Builder,626 builder: *const llvm.Builder,
601627
...@@ -649,14 +675,15 @@ pub const FuncGen = struct {...@@ -649,14 +675,15 @@ pub const FuncGen = struct {
649 if (self.air.value(inst)) |val| {675 if (self.air.value(inst)) |val| {
650 return self.dg.genTypedValue(.{ .ty = self.air.typeOf(inst), .val = val }, self);676 return self.dg.genTypedValue(.{ .ty = self.air.typeOf(inst), .val = val }, self);
651 }677 }
652 if (self.func_inst_table.get(inst)) |value| return value;678 const inst_index = Air.refToIndex(inst).?;
679 if (self.func_inst_table.get(inst_index)) |value| return value;
653680
654 return self.todo("implement global llvm values (or the value is not in the func_inst_table table)", .{});681 return self.todo("implement global llvm values (or the value is not in the func_inst_table table)", .{});
655 }682 }
656683
657 fn genBody(self: *FuncGen, body: ir.Body) error{ OutOfMemory, CodegenFail }!void {684 fn genBody(self: *FuncGen, body: []const Air.Inst.Index) error{ OutOfMemory, CodegenFail }!void {
658 const air_tags = self.air.instructions.items(.tag);685 const air_tags = self.air.instructions.items(.tag);
659 for (body.instructions) |inst| {686 for (body) |inst| {
660 const opt_value = switch (air_tags[inst]) {687 const opt_value = switch (air_tags[inst]) {
661 .add => try self.airAdd(inst),688 .add => try self.airAdd(inst),
662 .sub => try self.airSub(inst),689 .sub => try self.airSub(inst),
...@@ -828,8 +855,8 @@ pub const FuncGen = struct {...@@ -828,8 +855,8 @@ pub const FuncGen = struct {
828855
829 // If the break doesn't break a value, then we don't have to add856 // If the break doesn't break a value, then we don't have to add
830 // the values to the lists.857 // the values to the lists.
831 if (self.air.typeOf(branch.result).hasCodeGenBits()) {858 if (self.air.typeOf(branch.operand).hasCodeGenBits()) {
832 const val = try self.resolveInst(branch.result);859 const val = try self.resolveInst(branch.operand);
833860
834 // For the phi node, we need the basic blocks and the values of the861 // For the phi node, we need the basic blocks and the values of the
835 // break instructions.862 // break instructions.
src/link/MachO.zig+11-2
...@@ -30,6 +30,7 @@ const DebugSymbols = @import("MachO/DebugSymbols.zig");...@@ -30,6 +30,7 @@ const DebugSymbols = @import("MachO/DebugSymbols.zig");
30const Trie = @import("MachO/Trie.zig");30const Trie = @import("MachO/Trie.zig");
31const CodeSignature = @import("MachO/CodeSignature.zig");31const CodeSignature = @import("MachO/CodeSignature.zig");
32const Zld = @import("MachO/Zld.zig");32const Zld = @import("MachO/Zld.zig");
33const llvm_backend = @import("../codegen/llvm.zig");
3334
34usingnamespace @import("MachO/commands.zig");35usingnamespace @import("MachO/commands.zig");
3536
...@@ -37,6 +38,9 @@ pub const base_tag: File.Tag = File.Tag.macho;...@@ -37,6 +38,9 @@ pub const base_tag: File.Tag = File.Tag.macho;
3738
38base: File,39base: File,
3940
41/// If this is not null, an object file is created by LLVM and linked with LLD afterwards.
42llvm_object: ?*llvm_backend.Object = null,
43
40/// Debug symbols bundle (or dSym).44/// Debug symbols bundle (or dSym).
41d_sym: ?DebugSymbols = null,45d_sym: ?DebugSymbols = null,
4246
...@@ -347,8 +351,13 @@ pub const SrcFn = struct {...@@ -347,8 +351,13 @@ pub const SrcFn = struct {
347pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*MachO {351pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*MachO {
348 assert(options.object_format == .macho);352 assert(options.object_format == .macho);
349353
350 if (options.use_llvm) return error.LLVM_BackendIsTODO_ForMachO; // TODO354 if (build_options.have_llvm and options.use_llvm) {
351 if (options.use_lld) return error.LLD_LinkingIsTODO_ForMachO; // TODO355 const self = try createEmpty(allocator, options);
356 errdefer self.base.destroy();
357
358 self.llvm_object = try llvm_backend.Object.create(allocator, sub_path, options);
359 return self;
360 }
352361
353 const file = try options.emit.?.directory.handle.createFile(sub_path, .{362 const file = try options.emit.?.directory.handle.createFile(sub_path, .{
354 .truncate = false,363 .truncate = false,
src/link/Wasm.zig+10-2
...@@ -19,12 +19,15 @@ const build_options = @import("build_options");...@@ -19,12 +19,15 @@ const build_options = @import("build_options");
19const wasi_libc = @import("../wasi_libc.zig");19const wasi_libc = @import("../wasi_libc.zig");
20const Cache = @import("../Cache.zig");20const Cache = @import("../Cache.zig");
21const TypedValue = @import("../TypedValue.zig");21const TypedValue = @import("../TypedValue.zig");
22const llvm_backend = @import("../codegen/llvm.zig");
22const Air = @import("../Air.zig");23const Air = @import("../Air.zig");
23const Liveness = @import("../Liveness.zig");24const Liveness = @import("../Liveness.zig");
2425
25pub const base_tag = link.File.Tag.wasm;26pub const base_tag = link.File.Tag.wasm;
2627
27base: link.File,28base: link.File,
29/// If this is not null, an object file is created by LLVM and linked with LLD afterwards.
30llvm_object: ?*llvm_backend.Object = null,
28/// List of all function Decls to be written to the output file. The index of31/// List of all function Decls to be written to the output file. The index of
29/// each Decl in this list at the time of writing the binary is used as the32/// each Decl in this list at the time of writing the binary is used as the
30/// function index. In the event where ext_funcs' size is not 0, the index of33/// function index. In the event where ext_funcs' size is not 0, the index of
...@@ -114,8 +117,13 @@ pub const DeclBlock = struct {...@@ -114,8 +117,13 @@ pub const DeclBlock = struct {
114pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*Wasm {117pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*Wasm {
115 assert(options.object_format == .wasm);118 assert(options.object_format == .wasm);
116119
117 if (options.use_llvm) return error.LLVM_BackendIsTODO_ForWasm; // TODO120 if (build_options.have_llvm and options.use_llvm) {
118 if (options.use_lld) return error.LLD_LinkingIsTODO_ForWasm; // TODO121 const self = try createEmpty(allocator, options);
122 errdefer self.base.destroy();
123
124 self.llvm_object = try llvm_backend.Object.create(allocator, sub_path, options);
125 return self;
126 }
119127
120 // TODO: read the file and keep valid parts instead of truncating128 // TODO: read the file and keep valid parts instead of truncating
121 const file = try options.emit.?.directory.handle.createFile(sub_path, .{ .truncate = true, .read = true });129 const file = try options.emit.?.directory.handle.createFile(sub_path, .{ .truncate = true, .read = true });