authorgravatar for timonkruiper@gmail.comTimon Kruiper <timonkruiper@gmail.com> 2021-01-06 01:27:06+01:00
committergravatar for timonkruiper@gmail.comTimon Kruiper <timonkruiper@gmail.com> 2021-01-06 10:52:20+01:00
logb1cfa923bee5210fd78c7508d1af92dde3361c8c
tree78269824764b068cec780d0947e1e64f8c0abc8b
parent31d1ec4c2fd0d1e07e0020b19b7bca8196d7879c

stage2: rename and move files related to LLVM backend


15 files changed, 1348 insertions(+), 1351 deletions(-)

CMakeLists.txt+2-2
...@@ -541,6 +541,8 @@ set(ZIG_STAGE2_SOURCES...@@ -541,6 +541,8 @@ set(ZIG_STAGE2_SOURCES
541 "${CMAKE_SOURCE_DIR}/src/codegen/aarch64.zig"541 "${CMAKE_SOURCE_DIR}/src/codegen/aarch64.zig"
542 "${CMAKE_SOURCE_DIR}/src/codegen/arm.zig"542 "${CMAKE_SOURCE_DIR}/src/codegen/arm.zig"
543 "${CMAKE_SOURCE_DIR}/src/codegen/c.zig"543 "${CMAKE_SOURCE_DIR}/src/codegen/c.zig"
544 "${CMAKE_SOURCE_DIR}/src/codegen/llvm.zig"
545 "${CMAKE_SOURCE_DIR}/src/codegen/llvm/bindings.zig"
544 "${CMAKE_SOURCE_DIR}/src/codegen/riscv64.zig"546 "${CMAKE_SOURCE_DIR}/src/codegen/riscv64.zig"
545 "${CMAKE_SOURCE_DIR}/src/codegen/spu-mk2.zig"547 "${CMAKE_SOURCE_DIR}/src/codegen/spu-mk2.zig"
546 "${CMAKE_SOURCE_DIR}/src/codegen/wasm.zig"548 "${CMAKE_SOURCE_DIR}/src/codegen/wasm.zig"
...@@ -562,8 +564,6 @@ set(ZIG_STAGE2_SOURCES...@@ -562,8 +564,6 @@ set(ZIG_STAGE2_SOURCES
562 "${CMAKE_SOURCE_DIR}/src/link/cbe.h"564 "${CMAKE_SOURCE_DIR}/src/link/cbe.h"
563 "${CMAKE_SOURCE_DIR}/src/link/msdos-stub.bin"565 "${CMAKE_SOURCE_DIR}/src/link/msdos-stub.bin"
564 "${CMAKE_SOURCE_DIR}/src/liveness.zig"566 "${CMAKE_SOURCE_DIR}/src/liveness.zig"
565 "${CMAKE_SOURCE_DIR}/src/llvm_backend.zig"
566 "${CMAKE_SOURCE_DIR}/src/llvm_bindings.zig"
567 "${CMAKE_SOURCE_DIR}/src/main.zig"567 "${CMAKE_SOURCE_DIR}/src/main.zig"
568 "${CMAKE_SOURCE_DIR}/src/mingw.zig"568 "${CMAKE_SOURCE_DIR}/src/mingw.zig"
569 "${CMAKE_SOURCE_DIR}/src/musl.zig"569 "${CMAKE_SOURCE_DIR}/src/musl.zig"
src/Compilation.zig+1-1
...@@ -2116,7 +2116,7 @@ pub fn addCCArgs(...@@ -2116,7 +2116,7 @@ pub fn addCCArgs(
2116 try argv.append("-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS");2116 try argv.append("-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS");
2117 }2117 }
21182118
2119 const llvm_triple = try @import("llvm_backend.zig").targetTriple(arena, target);2119 const llvm_triple = try @import("codegen/llvm.zig").targetTriple(arena, target);
2120 try argv.appendSlice(&[_][]const u8{ "-target", llvm_triple });2120 try argv.appendSlice(&[_][]const u8{ "-target", llvm_triple });
21212121
2122 switch (ext) {2122 switch (ext) {
src/codegen/llvm.zig created+722
...@@ -0,0 +1,722 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const Allocator = std.mem.Allocator;
4const Compilation = @import("../Compilation.zig");
5const llvm = @import("llvm/bindings.zig");
6const link = @import("../link.zig");
7const log = std.log.scoped(.codegen);
8
9const Module = @import("../Module.zig");
10const TypedValue = @import("../TypedValue.zig");
11const ir = @import("../ir.zig");
12const Inst = ir.Inst;
13
14const Value = @import("../value.zig").Value;
15const Type = @import("../type.zig").Type;
16
17pub fn targetTriple(allocator: *Allocator, target: std.Target) ![:0]u8 {
18 const llvm_arch = switch (target.cpu.arch) {
19 .arm => "arm",
20 .armeb => "armeb",
21 .aarch64 => "aarch64",
22 .aarch64_be => "aarch64_be",
23 .aarch64_32 => "aarch64_32",
24 .arc => "arc",
25 .avr => "avr",
26 .bpfel => "bpfel",
27 .bpfeb => "bpfeb",
28 .hexagon => "hexagon",
29 .mips => "mips",
30 .mipsel => "mipsel",
31 .mips64 => "mips64",
32 .mips64el => "mips64el",
33 .msp430 => "msp430",
34 .powerpc => "powerpc",
35 .powerpc64 => "powerpc64",
36 .powerpc64le => "powerpc64le",
37 .r600 => "r600",
38 .amdgcn => "amdgcn",
39 .riscv32 => "riscv32",
40 .riscv64 => "riscv64",
41 .sparc => "sparc",
42 .sparcv9 => "sparcv9",
43 .sparcel => "sparcel",
44 .s390x => "s390x",
45 .tce => "tce",
46 .tcele => "tcele",
47 .thumb => "thumb",
48 .thumbeb => "thumbeb",
49 .i386 => "i386",
50 .x86_64 => "x86_64",
51 .xcore => "xcore",
52 .nvptx => "nvptx",
53 .nvptx64 => "nvptx64",
54 .le32 => "le32",
55 .le64 => "le64",
56 .amdil => "amdil",
57 .amdil64 => "amdil64",
58 .hsail => "hsail",
59 .hsail64 => "hsail64",
60 .spir => "spir",
61 .spir64 => "spir64",
62 .kalimba => "kalimba",
63 .shave => "shave",
64 .lanai => "lanai",
65 .wasm32 => "wasm32",
66 .wasm64 => "wasm64",
67 .renderscript32 => "renderscript32",
68 .renderscript64 => "renderscript64",
69 .ve => "ve",
70 .spu_2 => return error.LLVMBackendDoesNotSupportSPUMarkII,
71 };
72 // TODO Add a sub-arch for some architectures depending on CPU features.
73
74 const llvm_os = switch (target.os.tag) {
75 .freestanding => "unknown",
76 .ananas => "ananas",
77 .cloudabi => "cloudabi",
78 .dragonfly => "dragonfly",
79 .freebsd => "freebsd",
80 .fuchsia => "fuchsia",
81 .ios => "ios",
82 .kfreebsd => "kfreebsd",
83 .linux => "linux",
84 .lv2 => "lv2",
85 .macos => "macosx",
86 .netbsd => "netbsd",
87 .openbsd => "openbsd",
88 .solaris => "solaris",
89 .windows => "windows",
90 .haiku => "haiku",
91 .minix => "minix",
92 .rtems => "rtems",
93 .nacl => "nacl",
94 .cnk => "cnk",
95 .aix => "aix",
96 .cuda => "cuda",
97 .nvcl => "nvcl",
98 .amdhsa => "amdhsa",
99 .ps4 => "ps4",
100 .elfiamcu => "elfiamcu",
101 .tvos => "tvos",
102 .watchos => "watchos",
103 .mesa3d => "mesa3d",
104 .contiki => "contiki",
105 .amdpal => "amdpal",
106 .hermit => "hermit",
107 .hurd => "hurd",
108 .wasi => "wasi",
109 .emscripten => "emscripten",
110 .uefi => "windows",
111 .other => "unknown",
112 };
113
114 const llvm_abi = switch (target.abi) {
115 .none => "unknown",
116 .gnu => "gnu",
117 .gnuabin32 => "gnuabin32",
118 .gnuabi64 => "gnuabi64",
119 .gnueabi => "gnueabi",
120 .gnueabihf => "gnueabihf",
121 .gnux32 => "gnux32",
122 .code16 => "code16",
123 .eabi => "eabi",
124 .eabihf => "eabihf",
125 .android => "android",
126 .musl => "musl",
127 .musleabi => "musleabi",
128 .musleabihf => "musleabihf",
129 .msvc => "msvc",
130 .itanium => "itanium",
131 .cygnus => "cygnus",
132 .coreclr => "coreclr",
133 .simulator => "simulator",
134 .macabi => "macabi",
135 };
136
137 return std.fmt.allocPrintZ(allocator, "{s}-unknown-{s}-{s}", .{ llvm_arch, llvm_os, llvm_abi });
138}
139
140pub const LLVMIRModule = struct {
141 module: *Module,
142 llvm_module: *const llvm.Module,
143 context: *const llvm.Context,
144 target_machine: *const llvm.TargetMachine,
145 builder: *const llvm.Builder,
146
147 object_path: []const u8,
148
149 gpa: *Allocator,
150 err_msg: ?*Compilation.ErrorMsg = null,
151
152 // TODO: The fields below should really move into a different struct,
153 // because they are only valid when generating a function
154
155 /// This stores the LLVM values used in a function, such that they can be
156 /// referred to in other instructions. This table is cleared before every function is generated.
157 func_inst_table: std.AutoHashMapUnmanaged(*Inst, *const llvm.Value) = .{},
158
159 /// These fields are used to refer to the LLVM value of the function paramaters in an Arg instruction.
160 args: []*const llvm.Value = &[_]*const llvm.Value{},
161 arg_index: usize = 0,
162
163 entry_block: *const llvm.BasicBlock = undefined,
164 /// This fields stores the last alloca instruction, such that we can append more alloca instructions
165 /// to the top of the function.
166 latest_alloca_inst: ?*const llvm.Value = null,
167
168 pub fn create(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*LLVMIRModule {
169 const self = try allocator.create(LLVMIRModule);
170 errdefer allocator.destroy(self);
171
172 const gpa = options.module.?.gpa;
173
174 const obj_basename = try std.zig.binNameAlloc(gpa, .{
175 .root_name = options.root_name,
176 .target = options.target,
177 .output_mode = .Obj,
178 });
179 defer gpa.free(obj_basename);
180
181 const o_directory = options.module.?.zig_cache_artifact_directory;
182 const object_path = try o_directory.join(gpa, &[_][]const u8{obj_basename});
183 errdefer gpa.free(object_path);
184
185 const context = llvm.Context.create();
186 errdefer context.dispose();
187
188 initializeLLVMTargets();
189
190 const root_nameZ = try gpa.dupeZ(u8, options.root_name);
191 defer gpa.free(root_nameZ);
192 const llvm_module = llvm.Module.createWithName(root_nameZ.ptr, context);
193 errdefer llvm_module.dispose();
194
195 const llvm_target_triple = try targetTriple(gpa, options.target);
196 defer gpa.free(llvm_target_triple);
197
198 var error_message: [*:0]const u8 = undefined;
199 var target: *const llvm.Target = undefined;
200 if (llvm.Target.getFromTriple(llvm_target_triple.ptr, &target, &error_message)) {
201 defer llvm.disposeMessage(error_message);
202
203 const stderr = std.io.getStdErr().outStream();
204 try stderr.print(
205 \\Zig is expecting LLVM to understand this target: '{s}'
206 \\However LLVM responded with: "{s}"
207 \\Zig is unable to continue. This is a bug in Zig:
208 \\https://github.com/ziglang/zig/issues/438
209 \\
210 ,
211 .{
212 llvm_target_triple,
213 error_message,
214 },
215 );
216 return error.InvalidLLVMTriple;
217 }
218
219 const opt_level: llvm.CodeGenOptLevel = if (options.optimize_mode == .Debug) .None else .Aggressive;
220 const target_machine = llvm.TargetMachine.create(
221 target,
222 llvm_target_triple.ptr,
223 "",
224 "",
225 opt_level,
226 .Static,
227 .Default,
228 );
229 errdefer target_machine.dispose();
230
231 const builder = context.createBuilder();
232 errdefer builder.dispose();
233
234 self.* = .{
235 .module = options.module.?,
236 .llvm_module = llvm_module,
237 .context = context,
238 .target_machine = target_machine,
239 .builder = builder,
240 .object_path = object_path,
241 .gpa = gpa,
242 };
243 return self;
244 }
245
246 pub fn deinit(self: *LLVMIRModule, allocator: *Allocator) void {
247 self.builder.dispose();
248 self.target_machine.dispose();
249 self.llvm_module.dispose();
250 self.context.dispose();
251
252 self.func_inst_table.deinit(self.gpa);
253 self.gpa.free(self.object_path);
254
255 allocator.destroy(self);
256 }
257
258 fn initializeLLVMTargets() void {
259 llvm.initializeAllTargets();
260 llvm.initializeAllTargetInfos();
261 llvm.initializeAllTargetMCs();
262 llvm.initializeAllAsmPrinters();
263 llvm.initializeAllAsmParsers();
264 }
265
266 pub fn flushModule(self: *LLVMIRModule, comp: *Compilation) !void {
267 if (comp.verbose_llvm_ir) {
268 const dump = self.llvm_module.printToString();
269 defer llvm.disposeMessage(dump);
270
271 const stderr = std.io.getStdErr().outStream();
272 try stderr.writeAll(std.mem.spanZ(dump));
273 }
274
275 {
276 var error_message: [*:0]const u8 = undefined;
277 // verifyModule always allocs the error_message even if there is no error
278 defer llvm.disposeMessage(error_message);
279
280 if (self.llvm_module.verify(.ReturnStatus, &error_message)) {
281 const stderr = std.io.getStdErr().outStream();
282 try stderr.print("broken LLVM module found: {s}\nThis is a bug in the Zig compiler.", .{error_message});
283 return error.BrokenLLVMModule;
284 }
285 }
286
287 const object_pathZ = try self.gpa.dupeZ(u8, self.object_path);
288 defer self.gpa.free(object_pathZ);
289
290 var error_message: [*:0]const u8 = undefined;
291 if (self.target_machine.emitToFile(
292 self.llvm_module,
293 object_pathZ.ptr,
294 .ObjectFile,
295 &error_message,
296 )) {
297 defer llvm.disposeMessage(error_message);
298
299 const stderr = std.io.getStdErr().outStream();
300 try stderr.print("LLVM failed to emit file: {s}\n", .{error_message});
301 return error.FailedToEmit;
302 }
303 }
304
305 pub fn updateDecl(self: *LLVMIRModule, module: *Module, decl: *Module.Decl) !void {
306 self.gen(module, decl) catch |err| switch (err) {
307 error.CodegenFail => {
308 decl.analysis = .codegen_failure;
309 try module.failed_decls.put(module.gpa, decl, self.err_msg.?);
310 self.err_msg = null;
311 return;
312 },
313 else => |e| return e,
314 };
315 }
316
317 fn gen(self: *LLVMIRModule, module: *Module, decl: *Module.Decl) !void {
318 const typed_value = decl.typed_value.most_recent.typed_value;
319 const src = decl.src();
320
321 log.debug("gen: {s} type: {}, value: {}", .{ decl.name, typed_value.ty, typed_value.val });
322
323 if (typed_value.val.castTag(.function)) |func_payload| {
324 const func = func_payload.data;
325
326 const llvm_func = try self.resolveLLVMFunction(func.owner_decl, src);
327
328 // This gets the LLVM values from the function and stores them in `self.args`.
329 const fn_param_len = func.owner_decl.typed_value.most_recent.typed_value.ty.fnParamLen();
330 var args = try self.gpa.alloc(*const llvm.Value, fn_param_len);
331 defer self.gpa.free(args);
332
333 for (args) |*arg, i| {
334 arg.* = llvm.getParam(llvm_func, @intCast(c_uint, i));
335 }
336 self.args = args;
337 self.arg_index = 0;
338
339 // Make sure no other LLVM values from other functions can be referenced
340 self.func_inst_table.clearRetainingCapacity();
341
342 // We remove all the basic blocks of a function to support incremental
343 // compilation!
344 // TODO: remove all basic blocks if functions can have more than one
345 if (llvm_func.getFirstBasicBlock()) |bb| {
346 bb.deleteBasicBlock();
347 }
348
349 self.entry_block = self.context.appendBasicBlock(llvm_func, "Entry");
350 self.builder.positionBuilderAtEnd(self.entry_block);
351 self.latest_alloca_inst = null;
352
353 const instructions = func.body.instructions;
354 for (instructions) |inst| {
355 const opt_llvm_val: ?*const llvm.Value = switch (inst.tag) {
356 .add => try self.genAdd(inst.castTag(.add).?),
357 .alloc => try self.genAlloc(inst.castTag(.alloc).?),
358 .arg => try self.genArg(inst.castTag(.arg).?),
359 .bitcast => try self.genBitCast(inst.castTag(.bitcast).?),
360 .breakpoint => try self.genBreakpoint(inst.castTag(.breakpoint).?),
361 .call => try self.genCall(inst.castTag(.call).?),
362 .intcast => try self.genIntCast(inst.castTag(.intcast).?),
363 .load => try self.genLoad(inst.castTag(.load).?),
364 .not => try self.genNot(inst.castTag(.not).?),
365 .ret => try self.genRet(inst.castTag(.ret).?),
366 .retvoid => self.genRetVoid(inst.castTag(.retvoid).?),
367 .store => try self.genStore(inst.castTag(.store).?),
368 .sub => try self.genSub(inst.castTag(.sub).?),
369 .unreach => self.genUnreach(inst.castTag(.unreach).?),
370 .dbg_stmt => blk: {
371 // TODO: implement debug info
372 break :blk null;
373 },
374 else => |tag| return self.fail(src, "TODO implement LLVM codegen for Zir instruction: {}", .{tag}),
375 };
376 if (opt_llvm_val) |llvm_val| try self.func_inst_table.putNoClobber(self.gpa, inst, llvm_val);
377 }
378 } else if (typed_value.val.castTag(.extern_fn)) |extern_fn| {
379 _ = try self.resolveLLVMFunction(extern_fn.data, src);
380 } else {
381 _ = try self.resolveGlobalDecl(decl, src);
382 }
383 }
384
385 fn genCall(self: *LLVMIRModule, inst: *Inst.Call) !?*const llvm.Value {
386 if (inst.func.value()) |func_value| {
387 const fn_decl = if (func_value.castTag(.extern_fn)) |extern_fn|
388 extern_fn.data
389 else if (func_value.castTag(.function)) |func_payload|
390 func_payload.data.owner_decl
391 else
392 unreachable;
393
394 const zig_fn_type = fn_decl.typed_value.most_recent.typed_value.ty;
395 const llvm_fn = try self.resolveLLVMFunction(fn_decl, inst.base.src);
396
397 const num_args = inst.args.len;
398
399 const llvm_param_vals = try self.gpa.alloc(*const llvm.Value, num_args);
400 defer self.gpa.free(llvm_param_vals);
401
402 for (inst.args) |arg, i| {
403 llvm_param_vals[i] = try self.resolveInst(arg);
404 }
405
406 // TODO: LLVMBuildCall2 handles opaque function pointers, according to llvm docs
407 // Do we need that?
408 const call = self.builder.buildCall(
409 llvm_fn,
410 if (num_args == 0) null else llvm_param_vals.ptr,
411 @intCast(c_uint, num_args),
412 "",
413 );
414
415 const return_type = zig_fn_type.fnReturnType();
416 if (return_type.tag() == .noreturn) {
417 _ = self.builder.buildUnreachable();
418 }
419
420 // No need to store the LLVM value if the return type is void or noreturn
421 if (!return_type.hasCodeGenBits()) return null;
422
423 return call;
424 } else {
425 return self.fail(inst.base.src, "TODO implement calling runtime known function pointer LLVM backend", .{});
426 }
427 }
428
429 fn genRetVoid(self: *LLVMIRModule, inst: *Inst.NoOp) ?*const llvm.Value {
430 _ = self.builder.buildRetVoid();
431 return null;
432 }
433
434 fn genRet(self: *LLVMIRModule, inst: *Inst.UnOp) !?*const llvm.Value {
435 _ = self.builder.buildRet(try self.resolveInst(inst.operand));
436 return null;
437 }
438
439 fn genNot(self: *LLVMIRModule, inst: *Inst.UnOp) !?*const llvm.Value {
440 return self.builder.buildNot(try self.resolveInst(inst.operand), "");
441 }
442
443 fn genUnreach(self: *LLVMIRModule, inst: *Inst.NoOp) ?*const llvm.Value {
444 _ = self.builder.buildUnreachable();
445 return null;
446 }
447
448 fn genAdd(self: *LLVMIRModule, inst: *Inst.BinOp) !?*const llvm.Value {
449 const lhs = try self.resolveInst(inst.lhs);
450 const rhs = try self.resolveInst(inst.rhs);
451
452 if (!inst.base.ty.isInt())
453 return self.fail(inst.base.src, "TODO implement 'genAdd' for type {}", .{inst.base.ty});
454
455 return if (inst.base.ty.isSignedInt())
456 self.builder.buildNSWAdd(lhs, rhs, "")
457 else
458 self.builder.buildNUWAdd(lhs, rhs, "");
459 }
460
461 fn genSub(self: *LLVMIRModule, inst: *Inst.BinOp) !?*const llvm.Value {
462 const lhs = try self.resolveInst(inst.lhs);
463 const rhs = try self.resolveInst(inst.rhs);
464
465 if (!inst.base.ty.isInt())
466 return self.fail(inst.base.src, "TODO implement 'genSub' for type {}", .{inst.base.ty});
467
468 return if (inst.base.ty.isSignedInt())
469 self.builder.buildNSWSub(lhs, rhs, "")
470 else
471 self.builder.buildNUWSub(lhs, rhs, "");
472 }
473
474 fn genIntCast(self: *LLVMIRModule, inst: *Inst.UnOp) !?*const llvm.Value {
475 const val = try self.resolveInst(inst.operand);
476
477 const signed = inst.base.ty.isSignedInt();
478 // TODO: Should we use intcast here or just a simple bitcast?
479 // LLVM does truncation vs bitcast (+signed extension) in the intcast depending on the sizes
480 return self.builder.buildIntCast2(val, try self.getLLVMType(inst.base.ty, inst.base.src), signed, "");
481 }
482
483 fn genBitCast(self: *LLVMIRModule, inst: *Inst.UnOp) !?*const llvm.Value {
484 const val = try self.resolveInst(inst.operand);
485 const dest_type = try self.getLLVMType(inst.base.ty, inst.base.src);
486
487 return self.builder.buildBitCast(val, dest_type, "");
488 }
489
490 fn genArg(self: *LLVMIRModule, inst: *Inst.Arg) !?*const llvm.Value {
491 const arg_val = self.args[self.arg_index];
492 self.arg_index += 1;
493
494 const ptr_val = self.buildAlloca(try self.getLLVMType(inst.base.ty, inst.base.src));
495 _ = self.builder.buildStore(arg_val, ptr_val);
496 return self.builder.buildLoad(ptr_val, "");
497 }
498
499 fn genAlloc(self: *LLVMIRModule, inst: *Inst.NoOp) !?*const llvm.Value {
500 // buildAlloca expects the pointee type, not the pointer type, so assert that
501 // a Payload.PointerSimple is passed to the alloc instruction.
502 const pointee_type = inst.base.ty.castPointer().?.data;
503
504 // TODO: figure out a way to get the name of the var decl.
505 // TODO: set alignment and volatile
506 return self.buildAlloca(try self.getLLVMType(pointee_type, inst.base.src));
507 }
508
509 /// Use this instead of builder.buildAlloca, because this function makes sure to
510 /// put the alloca instruction at the top of the function!
511 fn buildAlloca(self: *LLVMIRModule, t: *const llvm.Type) *const llvm.Value {
512 if (self.latest_alloca_inst) |latest_alloc| {
513 // builder.positionBuilder adds it before the instruction,
514 // but we want to put it after the last alloca instruction.
515 self.builder.positionBuilder(self.entry_block, latest_alloc.getNextInstruction().?);
516 } else {
517 // There might have been other instructions emitted before the
518 // first alloca has been generated. However the alloca should still
519 // be first in the function.
520 if (self.entry_block.getFirstInstruction()) |first_inst| {
521 self.builder.positionBuilder(self.entry_block, first_inst);
522 }
523 }
524 defer self.builder.positionBuilderAtEnd(self.entry_block);
525
526 const val = self.builder.buildAlloca(t, "");
527 self.latest_alloca_inst = val;
528 return val;
529 }
530
531 fn genStore(self: *LLVMIRModule, inst: *Inst.BinOp) !?*const llvm.Value {
532 const val = try self.resolveInst(inst.rhs);
533 const ptr = try self.resolveInst(inst.lhs);
534 _ = self.builder.buildStore(val, ptr);
535 return null;
536 }
537
538 fn genLoad(self: *LLVMIRModule, inst: *Inst.UnOp) !?*const llvm.Value {
539 const ptr_val = try self.resolveInst(inst.operand);
540 return self.builder.buildLoad(ptr_val, "");
541 }
542
543 fn genBreakpoint(self: *LLVMIRModule, inst: *Inst.NoOp) !?*const llvm.Value {
544 const llvn_fn = self.getIntrinsic("llvm.debugtrap");
545 _ = self.builder.buildCall(llvn_fn, null, 0, "");
546 return null;
547 }
548
549 fn getIntrinsic(self: *LLVMIRModule, name: []const u8) *const llvm.Value {
550 const id = llvm.lookupIntrinsicID(name.ptr, name.len);
551 assert(id != 0);
552 // TODO: add support for overload intrinsics by passing the prefix of the intrinsic
553 // to `lookupIntrinsicID` and then passing the correct types to
554 // `getIntrinsicDeclaration`
555 return self.llvm_module.getIntrinsicDeclaration(id, null, 0);
556 }
557
558 fn resolveInst(self: *LLVMIRModule, inst: *ir.Inst) !*const llvm.Value {
559 if (inst.value()) |val| {
560 return self.genTypedValue(inst.src, .{ .ty = inst.ty, .val = val });
561 }
562 if (self.func_inst_table.get(inst)) |value| return value;
563
564 return self.fail(inst.src, "TODO implement global llvm values (or the value is not in the func_inst_table table)", .{});
565 }
566
567 fn genTypedValue(self: *LLVMIRModule, src: usize, tv: TypedValue) error{ OutOfMemory, CodegenFail }!*const llvm.Value {
568 const llvm_type = try self.getLLVMType(tv.ty, src);
569
570 if (tv.val.isUndef())
571 return llvm_type.getUndef();
572
573 switch (tv.ty.zigTypeTag()) {
574 .Bool => return if (tv.val.toBool()) llvm_type.constAllOnes() else llvm_type.constNull(),
575 .Int => {
576 var bigint_space: Value.BigIntSpace = undefined;
577 const bigint = tv.val.toBigInt(&bigint_space);
578
579 if (bigint.eqZero()) return llvm_type.constNull();
580
581 if (bigint.limbs.len != 1) {
582 return self.fail(src, "TODO implement bigger bigint", .{});
583 }
584 const llvm_int = llvm_type.constInt(bigint.limbs[0], false);
585 if (!bigint.positive) {
586 return llvm.constNeg(llvm_int);
587 }
588 return llvm_int;
589 },
590 .Pointer => switch (tv.val.tag()) {
591 .decl_ref => {
592 const decl = tv.val.castTag(.decl_ref).?.data;
593 const val = try self.resolveGlobalDecl(decl, src);
594
595 const usize_type = try self.getLLVMType(Type.initTag(.usize), src);
596
597 // TODO: second index should be the index into the memory!
598 var indices: [2]*const llvm.Value = .{
599 usize_type.constNull(),
600 usize_type.constNull(),
601 };
602
603 // TODO: consider using buildInBoundsGEP2 for opaque pointers
604 return self.builder.buildInBoundsGEP(val, &indices, 2, "");
605 },
606 else => return self.fail(src, "TODO implement const of pointer type '{}'", .{tv.ty}),
607 },
608 .Array => {
609 if (tv.val.castTag(.bytes)) |payload| {
610 const zero_sentinel = if (tv.ty.sentinel()) |sentinel| blk: {
611 if (sentinel.tag() == .zero) break :blk true;
612 return self.fail(src, "TODO handle other sentinel values", .{});
613 } else false;
614
615 return self.context.constString(payload.data.ptr, @intCast(c_uint, payload.data.len), !zero_sentinel);
616 } else {
617 return self.fail(src, "TODO handle more array values", .{});
618 }
619 },
620 else => return self.fail(src, "TODO implement const of type '{}'", .{tv.ty}),
621 }
622 }
623
624 fn getLLVMType(self: *LLVMIRModule, t: Type, src: usize) error{ OutOfMemory, CodegenFail }!*const llvm.Type {
625 switch (t.zigTypeTag()) {
626 .Void => return self.context.voidType(),
627 .NoReturn => return self.context.voidType(),
628 .Int => {
629 const info = t.intInfo(self.module.getTarget());
630 return self.context.intType(info.bits);
631 },
632 .Bool => return self.context.intType(1),
633 .Pointer => {
634 if (t.isSlice()) {
635 return self.fail(src, "TODO: LLVM backend: implement slices", .{});
636 } else {
637 const elem_type = try self.getLLVMType(t.elemType(), src);
638 return elem_type.pointerType(0);
639 }
640 },
641 .Array => {
642 const elem_type = try self.getLLVMType(t.elemType(), src);
643 return elem_type.arrayType(@intCast(c_uint, t.abiSize(self.module.getTarget())));
644 },
645 else => return self.fail(src, "TODO implement getLLVMType for type '{}'", .{t}),
646 }
647 }
648
649 fn resolveGlobalDecl(self: *LLVMIRModule, decl: *Module.Decl, src: usize) error{ OutOfMemory, CodegenFail }!*const llvm.Value {
650 // TODO: do we want to store this in our own datastructure?
651 if (self.llvm_module.getNamedGlobal(decl.name)) |val| return val;
652
653 const typed_value = decl.typed_value.most_recent.typed_value;
654
655 // TODO: remove this redundant `getLLVMType`, it is also called in `genTypedValue`.
656 const llvm_type = try self.getLLVMType(typed_value.ty, src);
657 const val = try self.genTypedValue(src, typed_value);
658 const global = self.llvm_module.addGlobal(llvm_type, decl.name);
659 llvm.setInitializer(global, val);
660
661 // TODO ask the Decl if it is const
662 // https://github.com/ziglang/zig/issues/7582
663
664 return global;
665 }
666
667 /// If the llvm function does not exist, create it
668 fn resolveLLVMFunction(self: *LLVMIRModule, func: *Module.Decl, src: usize) !*const llvm.Value {
669 // TODO: do we want to store this in our own datastructure?
670 if (self.llvm_module.getNamedFunction(func.name)) |llvm_fn| return llvm_fn;
671
672 const zig_fn_type = func.typed_value.most_recent.typed_value.ty;
673 const return_type = zig_fn_type.fnReturnType();
674
675 const fn_param_len = zig_fn_type.fnParamLen();
676
677 const fn_param_types = try self.gpa.alloc(Type, fn_param_len);
678 defer self.gpa.free(fn_param_types);
679 zig_fn_type.fnParamTypes(fn_param_types);
680
681 const llvm_param = try self.gpa.alloc(*const llvm.Type, fn_param_len);
682 defer self.gpa.free(llvm_param);
683
684 for (fn_param_types) |fn_param, i| {
685 llvm_param[i] = try self.getLLVMType(fn_param, src);
686 }
687
688 const fn_type = llvm.Type.functionType(
689 try self.getLLVMType(return_type, src),
690 if (fn_param_len == 0) null else llvm_param.ptr,
691 @intCast(c_uint, fn_param_len),
692 false,
693 );
694 const llvm_fn = self.llvm_module.addFunction(func.name, fn_type);
695
696 if (return_type.tag() == .noreturn) {
697 self.addFnAttr(llvm_fn, "noreturn");
698 }
699
700 return llvm_fn;
701 }
702
703 // Helper functions
704 fn addAttr(self: LLVMIRModule, val: *const llvm.Value, index: llvm.AttributeIndex, name: []const u8) void {
705 const kind_id = llvm.getEnumAttributeKindForName(name.ptr, name.len);
706 assert(kind_id != 0);
707 const llvm_attr = self.context.createEnumAttribute(kind_id, 0);
708 val.addAttributeAtIndex(index, llvm_attr);
709 }
710
711 fn addFnAttr(self: *LLVMIRModule, val: *const llvm.Value, attr_name: []const u8) void {
712 // TODO: improve this API, `addAttr(-1, attr_name)`
713 self.addAttr(val, std.math.maxInt(llvm.AttributeIndex), attr_name);
714 }
715
716 pub fn fail(self: *LLVMIRModule, src: usize, comptime format: []const u8, args: anytype) error{ OutOfMemory, CodegenFail } {
717 @setCold(true);
718 assert(self.err_msg == null);
719 self.err_msg = try Compilation.ErrorMsg.create(self.gpa, src, format, args);
720 return error.CodegenFail;
721 }
722};
src/codegen/llvm/bindings.zig created+571
...@@ -0,0 +1,571 @@
1//! We do this instead of @cImport because the self-hosted compiler is easier
2//! to bootstrap if it does not depend on translate-c.
3
4const LLVMBool = bool;
5pub const AttributeIndex = c_uint;
6
7/// Make sure to use the *InContext functions instead of the global ones.
8pub const Context = opaque {
9 pub const create = LLVMContextCreate;
10 extern fn LLVMContextCreate() *const Context;
11
12 pub const dispose = LLVMContextDispose;
13 extern fn LLVMContextDispose(C: *const Context) void;
14
15 pub const createEnumAttribute = LLVMCreateEnumAttribute;
16 extern fn LLVMCreateEnumAttribute(*const Context, KindID: c_uint, Val: u64) *const Attribute;
17
18 pub const intType = LLVMIntTypeInContext;
19 extern fn LLVMIntTypeInContext(C: *const Context, NumBits: c_uint) *const Type;
20
21 pub const voidType = LLVMVoidTypeInContext;
22 extern fn LLVMVoidTypeInContext(C: *const Context) *const Type;
23
24 pub const constString = LLVMConstStringInContext;
25 extern fn LLVMConstStringInContext(C: *const Context, Str: [*]const u8, Length: c_uint, DontNullTerminate: LLVMBool) *const Value;
26
27 pub const appendBasicBlock = LLVMAppendBasicBlockInContext;
28 extern fn LLVMAppendBasicBlockInContext(C: *const Context, Fn: *const Value, Name: [*:0]const u8) *const BasicBlock;
29
30 pub const createBuilder = LLVMCreateBuilderInContext;
31 extern fn LLVMCreateBuilderInContext(C: *const Context) *const Builder;
32};
33
34pub const Value = opaque {
35 pub const addAttributeAtIndex = LLVMAddAttributeAtIndex;
36 extern fn LLVMAddAttributeAtIndex(*const Value, Idx: AttributeIndex, A: *const Attribute) void;
37
38 pub const getFirstBasicBlock = LLVMGetFirstBasicBlock;
39 extern fn LLVMGetFirstBasicBlock(Fn: *const Value) ?*const BasicBlock;
40
41 pub const getNextInstruction = LLVMGetNextInstruction;
42 extern fn LLVMGetNextInstruction(Inst: *const Value) ?*const Value;
43};
44
45pub const Type = opaque {
46 pub const functionType = LLVMFunctionType;
47 extern fn LLVMFunctionType(ReturnType: *const Type, ParamTypes: ?[*]*const Type, ParamCount: c_uint, IsVarArg: LLVMBool) *const Type;
48
49 pub const constNull = LLVMConstNull;
50 extern fn LLVMConstNull(Ty: *const Type) *const Value;
51
52 pub const constAllOnes = LLVMConstAllOnes;
53 extern fn LLVMConstAllOnes(Ty: *const Type) *const Value;
54
55 pub const constInt = LLVMConstInt;
56 extern fn LLVMConstInt(IntTy: *const Type, N: c_ulonglong, SignExtend: LLVMBool) *const Value;
57
58 pub const constArray = LLVMConstArray;
59 extern fn LLVMConstArray(ElementTy: *const Type, ConstantVals: ?[*]*const Value, Length: c_uint) *const Value;
60
61 pub const getUndef = LLVMGetUndef;
62 extern fn LLVMGetUndef(Ty: *const Type) *const Value;
63
64 pub const pointerType = LLVMPointerType;
65 extern fn LLVMPointerType(ElementType: *const Type, AddressSpace: c_uint) *const Type;
66
67 pub const arrayType = LLVMArrayType;
68 extern fn LLVMArrayType(ElementType: *const Type, ElementCount: c_uint) *const Type;
69};
70
71pub const Module = opaque {
72 pub const createWithName = LLVMModuleCreateWithNameInContext;
73 extern fn LLVMModuleCreateWithNameInContext(ModuleID: [*:0]const u8, C: *const Context) *const Module;
74
75 pub const dispose = LLVMDisposeModule;
76 extern fn LLVMDisposeModule(*const Module) void;
77
78 pub const verify = LLVMVerifyModule;
79 extern fn LLVMVerifyModule(*const Module, Action: VerifierFailureAction, OutMessage: *[*:0]const u8) LLVMBool;
80
81 pub const addFunction = LLVMAddFunction;
82 extern fn LLVMAddFunction(*const Module, Name: [*:0]const u8, FunctionTy: *const Type) *const Value;
83
84 pub const getNamedFunction = LLVMGetNamedFunction;
85 extern fn LLVMGetNamedFunction(*const Module, Name: [*:0]const u8) ?*const Value;
86
87 pub const getIntrinsicDeclaration = LLVMGetIntrinsicDeclaration;
88 extern fn LLVMGetIntrinsicDeclaration(Mod: *const Module, ID: c_uint, ParamTypes: ?[*]*const Type, ParamCount: usize) *const Value;
89
90 pub const printToString = LLVMPrintModuleToString;
91 extern fn LLVMPrintModuleToString(*const Module) [*:0]const u8;
92
93 pub const addGlobal = LLVMAddGlobal;
94 extern fn LLVMAddGlobal(M: *const Module, Ty: *const Type, Name: [*:0]const u8) *const Value;
95
96 pub const getNamedGlobal = LLVMGetNamedGlobal;
97 extern fn LLVMGetNamedGlobal(M: *const Module, Name: [*:0]const u8) ?*const Value;
98};
99
100pub const lookupIntrinsicID = LLVMLookupIntrinsicID;
101extern fn LLVMLookupIntrinsicID(Name: [*]const u8, NameLen: usize) c_uint;
102
103pub const disposeMessage = LLVMDisposeMessage;
104extern fn LLVMDisposeMessage(Message: [*:0]const u8) void;
105
106pub const VerifierFailureAction = extern enum {
107 AbortProcess,
108 PrintMessage,
109 ReturnStatus,
110};
111
112pub const constNeg = LLVMConstNeg;
113extern fn LLVMConstNeg(ConstantVal: *const Value) *const Value;
114
115pub const setInitializer = LLVMSetInitializer;
116extern fn LLVMSetInitializer(GlobalVar: *const Value, ConstantVal: *const Value) void;
117
118pub const getParam = LLVMGetParam;
119extern fn LLVMGetParam(Fn: *const Value, Index: c_uint) *const Value;
120
121pub const getEnumAttributeKindForName = LLVMGetEnumAttributeKindForName;
122extern fn LLVMGetEnumAttributeKindForName(Name: [*]const u8, SLen: usize) c_uint;
123
124pub const Attribute = opaque {};
125
126pub const Builder = opaque {
127 pub const dispose = LLVMDisposeBuilder;
128 extern fn LLVMDisposeBuilder(Builder: *const Builder) void;
129
130 pub const positionBuilder = LLVMPositionBuilder;
131 extern fn LLVMPositionBuilder(Builder: *const Builder, Block: *const BasicBlock, Instr: *const Value) void;
132
133 pub const positionBuilderAtEnd = LLVMPositionBuilderAtEnd;
134 extern fn LLVMPositionBuilderAtEnd(Builder: *const Builder, Block: *const BasicBlock) void;
135
136 pub const getInsertBlock = LLVMGetInsertBlock;
137 extern fn LLVMGetInsertBlock(Builder: *const Builder) *const BasicBlock;
138
139 pub const buildCall = LLVMBuildCall;
140 extern fn LLVMBuildCall(*const Builder, Fn: *const Value, Args: ?[*]*const Value, NumArgs: c_uint, Name: [*:0]const u8) *const Value;
141
142 pub const buildCall2 = LLVMBuildCall2;
143 extern fn LLVMBuildCall2(*const Builder, *const Type, Fn: *const Value, Args: [*]*const Value, NumArgs: c_uint, Name: [*:0]const u8) *const Value;
144
145 pub const buildRetVoid = LLVMBuildRetVoid;
146 extern fn LLVMBuildRetVoid(*const Builder) *const Value;
147
148 pub const buildRet = LLVMBuildRet;
149 extern fn LLVMBuildRet(*const Builder, V: *const Value) *const Value;
150
151 pub const buildUnreachable = LLVMBuildUnreachable;
152 extern fn LLVMBuildUnreachable(*const Builder) *const Value;
153
154 pub const buildAlloca = LLVMBuildAlloca;
155 extern fn LLVMBuildAlloca(*const Builder, Ty: *const Type, Name: [*:0]const u8) *const Value;
156
157 pub const buildStore = LLVMBuildStore;
158 extern fn LLVMBuildStore(*const Builder, Val: *const Value, Ptr: *const Value) *const Value;
159
160 pub const buildLoad = LLVMBuildLoad;
161 extern fn LLVMBuildLoad(*const Builder, PointerVal: *const Value, Name: [*:0]const u8) *const Value;
162
163 pub const buildNot = LLVMBuildNot;
164 extern fn LLVMBuildNot(*const Builder, V: *const Value, Name: [*:0]const u8) *const Value;
165
166 pub const buildNSWAdd = LLVMBuildNSWAdd;
167 extern fn LLVMBuildNSWAdd(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value;
168
169 pub const buildNUWAdd = LLVMBuildNUWAdd;
170 extern fn LLVMBuildNUWAdd(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value;
171
172 pub const buildNSWSub = LLVMBuildNSWSub;
173 extern fn LLVMBuildNSWSub(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value;
174
175 pub const buildNUWSub = LLVMBuildNUWSub;
176 extern fn LLVMBuildNUWSub(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value;
177
178 pub const buildIntCast2 = LLVMBuildIntCast2;
179 extern fn LLVMBuildIntCast2(*const Builder, Val: *const Value, DestTy: *const Type, IsSigned: LLVMBool, Name: [*:0]const u8) *const Value;
180
181 pub const buildBitCast = LLVMBuildBitCast;
182 extern fn LLVMBuildBitCast(*const Builder, Val: *const Value, DestTy: *const Type, Name: [*:0]const u8) *const Value;
183
184 pub const buildInBoundsGEP = LLVMBuildInBoundsGEP;
185 extern fn LLVMBuildInBoundsGEP(B: *const Builder, Pointer: *const Value, Indices: [*]*const Value, NumIndices: c_uint, Name: [*:0]const u8) *const Value;
186};
187
188pub const BasicBlock = opaque {
189 pub const deleteBasicBlock = LLVMDeleteBasicBlock;
190 extern fn LLVMDeleteBasicBlock(BB: *const BasicBlock) void;
191
192 pub const getFirstInstruction = LLVMGetFirstInstruction;
193 extern fn LLVMGetFirstInstruction(BB: *const BasicBlock) ?*const Value;
194};
195
196pub const TargetMachine = opaque {
197 pub const create = LLVMCreateTargetMachine;
198 extern fn LLVMCreateTargetMachine(
199 T: *const Target,
200 Triple: [*:0]const u8,
201 CPU: [*:0]const u8,
202 Features: [*:0]const u8,
203 Level: CodeGenOptLevel,
204 Reloc: RelocMode,
205 CodeModel: CodeMode,
206 ) *const TargetMachine;
207
208 pub const dispose = LLVMDisposeTargetMachine;
209 extern fn LLVMDisposeTargetMachine(T: *const TargetMachine) void;
210
211 pub const emitToFile = LLVMTargetMachineEmitToFile;
212 extern fn LLVMTargetMachineEmitToFile(*const TargetMachine, M: *const Module, Filename: [*:0]const u8, codegen: CodeGenFileType, ErrorMessage: *[*:0]const u8) LLVMBool;
213};
214
215pub const CodeMode = extern enum {
216 Default,
217 JITDefault,
218 Tiny,
219 Small,
220 Kernel,
221 Medium,
222 Large,
223};
224
225pub const CodeGenOptLevel = extern enum {
226 None,
227 Less,
228 Default,
229 Aggressive,
230};
231
232pub const RelocMode = extern enum {
233 Default,
234 Static,
235 PIC,
236 DynamicNoPic,
237 ROPI,
238 RWPI,
239 ROPI_RWPI,
240};
241
242pub const CodeGenFileType = extern enum {
243 AssemblyFile,
244 ObjectFile,
245};
246
247pub const Target = opaque {
248 pub const getFromTriple = LLVMGetTargetFromTriple;
249 extern fn LLVMGetTargetFromTriple(Triple: [*:0]const u8, T: **const Target, ErrorMessage: *[*:0]const u8) LLVMBool;
250};
251
252extern fn LLVMInitializeAArch64TargetInfo() void;
253extern fn LLVMInitializeAMDGPUTargetInfo() void;
254extern fn LLVMInitializeARMTargetInfo() void;
255extern fn LLVMInitializeAVRTargetInfo() void;
256extern fn LLVMInitializeBPFTargetInfo() void;
257extern fn LLVMInitializeHexagonTargetInfo() void;
258extern fn LLVMInitializeLanaiTargetInfo() void;
259extern fn LLVMInitializeMipsTargetInfo() void;
260extern fn LLVMInitializeMSP430TargetInfo() void;
261extern fn LLVMInitializeNVPTXTargetInfo() void;
262extern fn LLVMInitializePowerPCTargetInfo() void;
263extern fn LLVMInitializeRISCVTargetInfo() void;
264extern fn LLVMInitializeSparcTargetInfo() void;
265extern fn LLVMInitializeSystemZTargetInfo() void;
266extern fn LLVMInitializeWebAssemblyTargetInfo() void;
267extern fn LLVMInitializeX86TargetInfo() void;
268extern fn LLVMInitializeXCoreTargetInfo() void;
269extern fn LLVMInitializeAArch64Target() void;
270extern fn LLVMInitializeAMDGPUTarget() void;
271extern fn LLVMInitializeARMTarget() void;
272extern fn LLVMInitializeAVRTarget() void;
273extern fn LLVMInitializeBPFTarget() void;
274extern fn LLVMInitializeHexagonTarget() void;
275extern fn LLVMInitializeLanaiTarget() void;
276extern fn LLVMInitializeMipsTarget() void;
277extern fn LLVMInitializeMSP430Target() void;
278extern fn LLVMInitializeNVPTXTarget() void;
279extern fn LLVMInitializePowerPCTarget() void;
280extern fn LLVMInitializeRISCVTarget() void;
281extern fn LLVMInitializeSparcTarget() void;
282extern fn LLVMInitializeSystemZTarget() void;
283extern fn LLVMInitializeWebAssemblyTarget() void;
284extern fn LLVMInitializeX86Target() void;
285extern fn LLVMInitializeXCoreTarget() void;
286extern fn LLVMInitializeAArch64TargetMC() void;
287extern fn LLVMInitializeAMDGPUTargetMC() void;
288extern fn LLVMInitializeARMTargetMC() void;
289extern fn LLVMInitializeAVRTargetMC() void;
290extern fn LLVMInitializeBPFTargetMC() void;
291extern fn LLVMInitializeHexagonTargetMC() void;
292extern fn LLVMInitializeLanaiTargetMC() void;
293extern fn LLVMInitializeMipsTargetMC() void;
294extern fn LLVMInitializeMSP430TargetMC() void;
295extern fn LLVMInitializeNVPTXTargetMC() void;
296extern fn LLVMInitializePowerPCTargetMC() void;
297extern fn LLVMInitializeRISCVTargetMC() void;
298extern fn LLVMInitializeSparcTargetMC() void;
299extern fn LLVMInitializeSystemZTargetMC() void;
300extern fn LLVMInitializeWebAssemblyTargetMC() void;
301extern fn LLVMInitializeX86TargetMC() void;
302extern fn LLVMInitializeXCoreTargetMC() void;
303extern fn LLVMInitializeAArch64AsmPrinter() void;
304extern fn LLVMInitializeAMDGPUAsmPrinter() void;
305extern fn LLVMInitializeARMAsmPrinter() void;
306extern fn LLVMInitializeAVRAsmPrinter() void;
307extern fn LLVMInitializeBPFAsmPrinter() void;
308extern fn LLVMInitializeHexagonAsmPrinter() void;
309extern fn LLVMInitializeLanaiAsmPrinter() void;
310extern fn LLVMInitializeMipsAsmPrinter() void;
311extern fn LLVMInitializeMSP430AsmPrinter() void;
312extern fn LLVMInitializeNVPTXAsmPrinter() void;
313extern fn LLVMInitializePowerPCAsmPrinter() void;
314extern fn LLVMInitializeRISCVAsmPrinter() void;
315extern fn LLVMInitializeSparcAsmPrinter() void;
316extern fn LLVMInitializeSystemZAsmPrinter() void;
317extern fn LLVMInitializeWebAssemblyAsmPrinter() void;
318extern fn LLVMInitializeX86AsmPrinter() void;
319extern fn LLVMInitializeXCoreAsmPrinter() void;
320extern fn LLVMInitializeAArch64AsmParser() void;
321extern fn LLVMInitializeAMDGPUAsmParser() void;
322extern fn LLVMInitializeARMAsmParser() void;
323extern fn LLVMInitializeAVRAsmParser() void;
324extern fn LLVMInitializeBPFAsmParser() void;
325extern fn LLVMInitializeHexagonAsmParser() void;
326extern fn LLVMInitializeLanaiAsmParser() void;
327extern fn LLVMInitializeMipsAsmParser() void;
328extern fn LLVMInitializeMSP430AsmParser() void;
329extern fn LLVMInitializePowerPCAsmParser() void;
330extern fn LLVMInitializeRISCVAsmParser() void;
331extern fn LLVMInitializeSparcAsmParser() void;
332extern fn LLVMInitializeSystemZAsmParser() void;
333extern fn LLVMInitializeWebAssemblyAsmParser() void;
334extern fn LLVMInitializeX86AsmParser() void;
335
336pub const initializeAllTargetInfos = LLVMInitializeAllTargetInfos;
337fn LLVMInitializeAllTargetInfos() callconv(.C) void {
338 LLVMInitializeAArch64TargetInfo();
339 LLVMInitializeAMDGPUTargetInfo();
340 LLVMInitializeARMTargetInfo();
341 LLVMInitializeAVRTargetInfo();
342 LLVMInitializeBPFTargetInfo();
343 LLVMInitializeHexagonTargetInfo();
344 LLVMInitializeLanaiTargetInfo();
345 LLVMInitializeMipsTargetInfo();
346 LLVMInitializeMSP430TargetInfo();
347 LLVMInitializeNVPTXTargetInfo();
348 LLVMInitializePowerPCTargetInfo();
349 LLVMInitializeRISCVTargetInfo();
350 LLVMInitializeSparcTargetInfo();
351 LLVMInitializeSystemZTargetInfo();
352 LLVMInitializeWebAssemblyTargetInfo();
353 LLVMInitializeX86TargetInfo();
354 LLVMInitializeXCoreTargetInfo();
355}
356pub const initializeAllTargets = LLVMInitializeAllTargets;
357fn LLVMInitializeAllTargets() callconv(.C) void {
358 LLVMInitializeAArch64Target();
359 LLVMInitializeAMDGPUTarget();
360 LLVMInitializeARMTarget();
361 LLVMInitializeAVRTarget();
362 LLVMInitializeBPFTarget();
363 LLVMInitializeHexagonTarget();
364 LLVMInitializeLanaiTarget();
365 LLVMInitializeMipsTarget();
366 LLVMInitializeMSP430Target();
367 LLVMInitializeNVPTXTarget();
368 LLVMInitializePowerPCTarget();
369 LLVMInitializeRISCVTarget();
370 LLVMInitializeSparcTarget();
371 LLVMInitializeSystemZTarget();
372 LLVMInitializeWebAssemblyTarget();
373 LLVMInitializeX86Target();
374 LLVMInitializeXCoreTarget();
375}
376pub const initializeAllTargetMCs = LLVMInitializeAllTargetMCs;
377fn LLVMInitializeAllTargetMCs() callconv(.C) void {
378 LLVMInitializeAArch64TargetMC();
379 LLVMInitializeAMDGPUTargetMC();
380 LLVMInitializeARMTargetMC();
381 LLVMInitializeAVRTargetMC();
382 LLVMInitializeBPFTargetMC();
383 LLVMInitializeHexagonTargetMC();
384 LLVMInitializeLanaiTargetMC();
385 LLVMInitializeMipsTargetMC();
386 LLVMInitializeMSP430TargetMC();
387 LLVMInitializeNVPTXTargetMC();
388 LLVMInitializePowerPCTargetMC();
389 LLVMInitializeRISCVTargetMC();
390 LLVMInitializeSparcTargetMC();
391 LLVMInitializeSystemZTargetMC();
392 LLVMInitializeWebAssemblyTargetMC();
393 LLVMInitializeX86TargetMC();
394 LLVMInitializeXCoreTargetMC();
395}
396pub const initializeAllAsmPrinters = LLVMInitializeAllAsmPrinters;
397fn LLVMInitializeAllAsmPrinters() callconv(.C) void {
398 LLVMInitializeAArch64AsmPrinter();
399 LLVMInitializeAMDGPUAsmPrinter();
400 LLVMInitializeARMAsmPrinter();
401 LLVMInitializeAVRAsmPrinter();
402 LLVMInitializeBPFAsmPrinter();
403 LLVMInitializeHexagonAsmPrinter();
404 LLVMInitializeLanaiAsmPrinter();
405 LLVMInitializeMipsAsmPrinter();
406 LLVMInitializeMSP430AsmPrinter();
407 LLVMInitializeNVPTXAsmPrinter();
408 LLVMInitializePowerPCAsmPrinter();
409 LLVMInitializeRISCVAsmPrinter();
410 LLVMInitializeSparcAsmPrinter();
411 LLVMInitializeSystemZAsmPrinter();
412 LLVMInitializeWebAssemblyAsmPrinter();
413 LLVMInitializeX86AsmPrinter();
414 LLVMInitializeXCoreAsmPrinter();
415}
416pub const initializeAllAsmParsers = LLVMInitializeAllAsmParsers;
417fn LLVMInitializeAllAsmParsers() callconv(.C) void {
418 LLVMInitializeAArch64AsmParser();
419 LLVMInitializeAMDGPUAsmParser();
420 LLVMInitializeARMAsmParser();
421 LLVMInitializeAVRAsmParser();
422 LLVMInitializeBPFAsmParser();
423 LLVMInitializeHexagonAsmParser();
424 LLVMInitializeLanaiAsmParser();
425 LLVMInitializeMipsAsmParser();
426 LLVMInitializeMSP430AsmParser();
427 LLVMInitializePowerPCAsmParser();
428 LLVMInitializeRISCVAsmParser();
429 LLVMInitializeSparcAsmParser();
430 LLVMInitializeSystemZAsmParser();
431 LLVMInitializeWebAssemblyAsmParser();
432 LLVMInitializeX86AsmParser();
433}
434
435extern fn ZigLLDLinkCOFF(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int;
436extern fn ZigLLDLinkELF(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int;
437extern fn ZigLLDLinkMachO(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int;
438extern fn ZigLLDLinkWasm(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int;
439
440pub const LinkCOFF = ZigLLDLinkCOFF;
441pub const LinkELF = ZigLLDLinkELF;
442pub const LinkMachO = ZigLLDLinkMachO;
443pub const LinkWasm = ZigLLDLinkWasm;
444
445pub const ObjectFormatType = extern enum(c_int) {
446 Unknown,
447 COFF,
448 ELF,
449 MachO,
450 Wasm,
451 XCOFF,
452};
453
454pub const GetHostCPUName = LLVMGetHostCPUName;
455extern fn LLVMGetHostCPUName() ?[*:0]u8;
456
457pub const GetNativeFeatures = ZigLLVMGetNativeFeatures;
458extern fn ZigLLVMGetNativeFeatures() ?[*:0]u8;
459
460pub const WriteArchive = ZigLLVMWriteArchive;
461extern fn ZigLLVMWriteArchive(
462 archive_name: [*:0]const u8,
463 file_names_ptr: [*]const [*:0]const u8,
464 file_names_len: usize,
465 os_type: OSType,
466) bool;
467
468pub const OSType = extern enum(c_int) {
469 UnknownOS = 0,
470 Ananas = 1,
471 CloudABI = 2,
472 Darwin = 3,
473 DragonFly = 4,
474 FreeBSD = 5,
475 Fuchsia = 6,
476 IOS = 7,
477 KFreeBSD = 8,
478 Linux = 9,
479 Lv2 = 10,
480 MacOSX = 11,
481 NetBSD = 12,
482 OpenBSD = 13,
483 Solaris = 14,
484 Win32 = 15,
485 Haiku = 16,
486 Minix = 17,
487 RTEMS = 18,
488 NaCl = 19,
489 CNK = 20,
490 AIX = 21,
491 CUDA = 22,
492 NVCL = 23,
493 AMDHSA = 24,
494 PS4 = 25,
495 ELFIAMCU = 26,
496 TvOS = 27,
497 WatchOS = 28,
498 Mesa3D = 29,
499 Contiki = 30,
500 AMDPAL = 31,
501 HermitCore = 32,
502 Hurd = 33,
503 WASI = 34,
504 Emscripten = 35,
505};
506
507pub const ArchType = extern enum(c_int) {
508 UnknownArch = 0,
509 arm = 1,
510 armeb = 2,
511 aarch64 = 3,
512 aarch64_be = 4,
513 aarch64_32 = 5,
514 arc = 6,
515 avr = 7,
516 bpfel = 8,
517 bpfeb = 9,
518 hexagon = 10,
519 mips = 11,
520 mipsel = 12,
521 mips64 = 13,
522 mips64el = 14,
523 msp430 = 15,
524 ppc = 16,
525 ppc64 = 17,
526 ppc64le = 18,
527 r600 = 19,
528 amdgcn = 20,
529 riscv32 = 21,
530 riscv64 = 22,
531 sparc = 23,
532 sparcv9 = 24,
533 sparcel = 25,
534 systemz = 26,
535 tce = 27,
536 tcele = 28,
537 thumb = 29,
538 thumbeb = 30,
539 x86 = 31,
540 x86_64 = 32,
541 xcore = 33,
542 nvptx = 34,
543 nvptx64 = 35,
544 le32 = 36,
545 le64 = 37,
546 amdil = 38,
547 amdil64 = 39,
548 hsail = 40,
549 hsail64 = 41,
550 spir = 42,
551 spir64 = 43,
552 kalimba = 44,
553 shave = 45,
554 lanai = 46,
555 wasm32 = 47,
556 wasm64 = 48,
557 renderscript32 = 49,
558 renderscript64 = 50,
559 ve = 51,
560};
561
562pub const ParseCommandLineOptions = ZigLLVMParseCommandLineOptions;
563extern fn ZigLLVMParseCommandLineOptions(argc: usize, argv: [*]const [*:0]const u8) void;
564
565pub const WriteImportLibrary = ZigLLVMWriteImportLibrary;
566extern fn ZigLLVMWriteImportLibrary(
567 def_path: [*:0]const u8,
568 arch: ArchType,
569 output_lib_path: [*c]const u8,
570 kill_at: bool,
571) bool;
src/link.zig+1-1
...@@ -567,7 +567,7 @@ pub const File = struct {...@@ -567,7 +567,7 @@ pub const File = struct {
567 std.debug.print("\n", .{});567 std.debug.print("\n", .{});
568 }568 }
569569
570 const llvm = @import("llvm_bindings.zig");570 const llvm = @import("codegen/llvm/bindings.zig");
571 const os_type = @import("target.zig").osToLLVM(base.options.target.os.tag);571 const os_type = @import("target.zig").osToLLVM(base.options.target.os.tag);
572 const bad = llvm.WriteArchive(full_out_path_z, object_files.items.ptr, object_files.items.len, os_type);572 const bad = llvm.WriteArchive(full_out_path_z, object_files.items.ptr, object_files.items.len, os_type);
573 if (bad) return error.UnableToWriteArchive;573 if (bad) return error.UnableToWriteArchive;
src/link/Coff.zig+1-1
...@@ -16,7 +16,7 @@ const link = @import("../link.zig");...@@ -16,7 +16,7 @@ const link = @import("../link.zig");
16const build_options = @import("build_options");16const build_options = @import("build_options");
17const Cache = @import("../Cache.zig");17const Cache = @import("../Cache.zig");
18const mingw = @import("../mingw.zig");18const mingw = @import("../mingw.zig");
19const llvm_backend = @import("../llvm_backend.zig");19const llvm_backend = @import("../codegen/llvm.zig");
2020
21const allocation_padding = 4 / 3;21const allocation_padding = 4 / 3;
22const minimum_text_block_size = 64 * allocation_padding;22const minimum_text_block_size = 64 * allocation_padding;
src/link/Elf.zig+1-1
...@@ -24,7 +24,7 @@ const build_options = @import("build_options");...@@ -24,7 +24,7 @@ const build_options = @import("build_options");
24const target_util = @import("../target.zig");24const target_util = @import("../target.zig");
25const glibc = @import("../glibc.zig");25const glibc = @import("../glibc.zig");
26const Cache = @import("../Cache.zig");26const Cache = @import("../Cache.zig");
27const llvm_backend = @import("../llvm_backend.zig");27const llvm_backend = @import("../codegen/llvm.zig");
2828
29const default_entry_addr = 0x8000000;29const default_entry_addr = 0x8000000;
3030
src/llvm_backend.zig deleted-722
...@@ -1,722 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const Allocator = std.mem.Allocator;
4const Compilation = @import("Compilation.zig");
5const llvm = @import("llvm_bindings.zig");
6const link = @import("link.zig");
7const log = std.log.scoped(.codegen);
8
9const Module = @import("Module.zig");
10const TypedValue = @import("TypedValue.zig");
11const ir = @import("ir.zig");
12const Inst = ir.Inst;
13
14const Value = @import("value.zig").Value;
15const Type = @import("type.zig").Type;
16
17pub fn targetTriple(allocator: *Allocator, target: std.Target) ![:0]u8 {
18 const llvm_arch = switch (target.cpu.arch) {
19 .arm => "arm",
20 .armeb => "armeb",
21 .aarch64 => "aarch64",
22 .aarch64_be => "aarch64_be",
23 .aarch64_32 => "aarch64_32",
24 .arc => "arc",
25 .avr => "avr",
26 .bpfel => "bpfel",
27 .bpfeb => "bpfeb",
28 .hexagon => "hexagon",
29 .mips => "mips",
30 .mipsel => "mipsel",
31 .mips64 => "mips64",
32 .mips64el => "mips64el",
33 .msp430 => "msp430",
34 .powerpc => "powerpc",
35 .powerpc64 => "powerpc64",
36 .powerpc64le => "powerpc64le",
37 .r600 => "r600",
38 .amdgcn => "amdgcn",
39 .riscv32 => "riscv32",
40 .riscv64 => "riscv64",
41 .sparc => "sparc",
42 .sparcv9 => "sparcv9",
43 .sparcel => "sparcel",
44 .s390x => "s390x",
45 .tce => "tce",
46 .tcele => "tcele",
47 .thumb => "thumb",
48 .thumbeb => "thumbeb",
49 .i386 => "i386",
50 .x86_64 => "x86_64",
51 .xcore => "xcore",
52 .nvptx => "nvptx",
53 .nvptx64 => "nvptx64",
54 .le32 => "le32",
55 .le64 => "le64",
56 .amdil => "amdil",
57 .amdil64 => "amdil64",
58 .hsail => "hsail",
59 .hsail64 => "hsail64",
60 .spir => "spir",
61 .spir64 => "spir64",
62 .kalimba => "kalimba",
63 .shave => "shave",
64 .lanai => "lanai",
65 .wasm32 => "wasm32",
66 .wasm64 => "wasm64",
67 .renderscript32 => "renderscript32",
68 .renderscript64 => "renderscript64",
69 .ve => "ve",
70 .spu_2 => return error.LLVMBackendDoesNotSupportSPUMarkII,
71 };
72 // TODO Add a sub-arch for some architectures depending on CPU features.
73
74 const llvm_os = switch (target.os.tag) {
75 .freestanding => "unknown",
76 .ananas => "ananas",
77 .cloudabi => "cloudabi",
78 .dragonfly => "dragonfly",
79 .freebsd => "freebsd",
80 .fuchsia => "fuchsia",
81 .ios => "ios",
82 .kfreebsd => "kfreebsd",
83 .linux => "linux",
84 .lv2 => "lv2",
85 .macos => "macosx",
86 .netbsd => "netbsd",
87 .openbsd => "openbsd",
88 .solaris => "solaris",
89 .windows => "windows",
90 .haiku => "haiku",
91 .minix => "minix",
92 .rtems => "rtems",
93 .nacl => "nacl",
94 .cnk => "cnk",
95 .aix => "aix",
96 .cuda => "cuda",
97 .nvcl => "nvcl",
98 .amdhsa => "amdhsa",
99 .ps4 => "ps4",
100 .elfiamcu => "elfiamcu",
101 .tvos => "tvos",
102 .watchos => "watchos",
103 .mesa3d => "mesa3d",
104 .contiki => "contiki",
105 .amdpal => "amdpal",
106 .hermit => "hermit",
107 .hurd => "hurd",
108 .wasi => "wasi",
109 .emscripten => "emscripten",
110 .uefi => "windows",
111 .other => "unknown",
112 };
113
114 const llvm_abi = switch (target.abi) {
115 .none => "unknown",
116 .gnu => "gnu",
117 .gnuabin32 => "gnuabin32",
118 .gnuabi64 => "gnuabi64",
119 .gnueabi => "gnueabi",
120 .gnueabihf => "gnueabihf",
121 .gnux32 => "gnux32",
122 .code16 => "code16",
123 .eabi => "eabi",
124 .eabihf => "eabihf",
125 .android => "android",
126 .musl => "musl",
127 .musleabi => "musleabi",
128 .musleabihf => "musleabihf",
129 .msvc => "msvc",
130 .itanium => "itanium",
131 .cygnus => "cygnus",
132 .coreclr => "coreclr",
133 .simulator => "simulator",
134 .macabi => "macabi",
135 };
136
137 return std.fmt.allocPrintZ(allocator, "{s}-unknown-{s}-{s}", .{ llvm_arch, llvm_os, llvm_abi });
138}
139
140pub const LLVMIRModule = struct {
141 module: *Module,
142 llvm_module: *const llvm.Module,
143 context: *const llvm.Context,
144 target_machine: *const llvm.TargetMachine,
145 builder: *const llvm.Builder,
146
147 object_path: []const u8,
148
149 gpa: *Allocator,
150 err_msg: ?*Compilation.ErrorMsg = null,
151
152 // TODO: The fields below should really move into a different struct,
153 // because they are only valid when generating a function
154
155 /// This stores the LLVM values used in a function, such that they can be
156 /// referred to in other instructions. This table is cleared before every function is generated.
157 func_inst_table: std.AutoHashMapUnmanaged(*Inst, *const llvm.Value) = .{},
158
159 /// These fields are used to refer to the LLVM value of the function paramaters in an Arg instruction.
160 args: []*const llvm.Value = &[_]*const llvm.Value{},
161 arg_index: usize = 0,
162
163 entry_block: *const llvm.BasicBlock = undefined,
164 /// This fields stores the last alloca instruction, such that we can append more alloca instructions
165 /// to the top of the function.
166 latest_alloca_inst: ?*const llvm.Value = null,
167
168 pub fn create(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*LLVMIRModule {
169 const self = try allocator.create(LLVMIRModule);
170 errdefer allocator.destroy(self);
171
172 const gpa = options.module.?.gpa;
173
174 const obj_basename = try std.zig.binNameAlloc(gpa, .{
175 .root_name = options.root_name,
176 .target = options.target,
177 .output_mode = .Obj,
178 });
179 defer gpa.free(obj_basename);
180
181 const o_directory = options.module.?.zig_cache_artifact_directory;
182 const object_path = try o_directory.join(gpa, &[_][]const u8{obj_basename});
183 errdefer gpa.free(object_path);
184
185 const context = llvm.Context.create();
186 errdefer context.dispose();
187
188 initializeLLVMTargets();
189
190 const root_nameZ = try gpa.dupeZ(u8, options.root_name);
191 defer gpa.free(root_nameZ);
192 const llvm_module = llvm.Module.createWithName(root_nameZ.ptr, context);
193 errdefer llvm_module.dispose();
194
195 const llvm_target_triple = try targetTriple(gpa, options.target);
196 defer gpa.free(llvm_target_triple);
197
198 var error_message: [*:0]const u8 = undefined;
199 var target: *const llvm.Target = undefined;
200 if (llvm.Target.getFromTriple(llvm_target_triple.ptr, &target, &error_message)) {
201 defer llvm.disposeMessage(error_message);
202
203 const stderr = std.io.getStdErr().outStream();
204 try stderr.print(
205 \\Zig is expecting LLVM to understand this target: '{s}'
206 \\However LLVM responded with: "{s}"
207 \\Zig is unable to continue. This is a bug in Zig:
208 \\https://github.com/ziglang/zig/issues/438
209 \\
210 ,
211 .{
212 llvm_target_triple,
213 error_message,
214 },
215 );
216 return error.InvalidLLVMTriple;
217 }
218
219 const opt_level: llvm.CodeGenOptLevel = if (options.optimize_mode == .Debug) .None else .Aggressive;
220 const target_machine = llvm.TargetMachine.create(
221 target,
222 llvm_target_triple.ptr,
223 "",
224 "",
225 opt_level,
226 .Static,
227 .Default,
228 );
229 errdefer target_machine.dispose();
230
231 const builder = context.createBuilder();
232 errdefer builder.dispose();
233
234 self.* = .{
235 .module = options.module.?,
236 .llvm_module = llvm_module,
237 .context = context,
238 .target_machine = target_machine,
239 .builder = builder,
240 .object_path = object_path,
241 .gpa = gpa,
242 };
243 return self;
244 }
245
246 pub fn deinit(self: *LLVMIRModule, allocator: *Allocator) void {
247 self.builder.dispose();
248 self.target_machine.dispose();
249 self.llvm_module.dispose();
250 self.context.dispose();
251
252 self.func_inst_table.deinit(self.gpa);
253 self.gpa.free(self.object_path);
254
255 allocator.destroy(self);
256 }
257
258 fn initializeLLVMTargets() void {
259 llvm.initializeAllTargets();
260 llvm.initializeAllTargetInfos();
261 llvm.initializeAllTargetMCs();
262 llvm.initializeAllAsmPrinters();
263 llvm.initializeAllAsmParsers();
264 }
265
266 pub fn flushModule(self: *LLVMIRModule, comp: *Compilation) !void {
267 if (comp.verbose_llvm_ir) {
268 const dump = self.llvm_module.printToString();
269 defer llvm.disposeMessage(dump);
270
271 const stderr = std.io.getStdErr().outStream();
272 try stderr.writeAll(std.mem.spanZ(dump));
273 }
274
275 {
276 var error_message: [*:0]const u8 = undefined;
277 // verifyModule always allocs the error_message even if there is no error
278 defer llvm.disposeMessage(error_message);
279
280 if (self.llvm_module.verify(.ReturnStatus, &error_message)) {
281 const stderr = std.io.getStdErr().outStream();
282 try stderr.print("broken LLVM module found: {s}\nThis is a bug in the Zig compiler.", .{error_message});
283 return error.BrokenLLVMModule;
284 }
285 }
286
287 const object_pathZ = try self.gpa.dupeZ(u8, self.object_path);
288 defer self.gpa.free(object_pathZ);
289
290 var error_message: [*:0]const u8 = undefined;
291 if (self.target_machine.emitToFile(
292 self.llvm_module,
293 object_pathZ.ptr,
294 .ObjectFile,
295 &error_message,
296 )) {
297 defer llvm.disposeMessage(error_message);
298
299 const stderr = std.io.getStdErr().outStream();
300 try stderr.print("LLVM failed to emit file: {s}\n", .{error_message});
301 return error.FailedToEmit;
302 }
303 }
304
305 pub fn updateDecl(self: *LLVMIRModule, module: *Module, decl: *Module.Decl) !void {
306 self.gen(module, decl) catch |err| switch (err) {
307 error.CodegenFail => {
308 decl.analysis = .codegen_failure;
309 try module.failed_decls.put(module.gpa, decl, self.err_msg.?);
310 self.err_msg = null;
311 return;
312 },
313 else => |e| return e,
314 };
315 }
316
317 fn gen(self: *LLVMIRModule, module: *Module, decl: *Module.Decl) !void {
318 const typed_value = decl.typed_value.most_recent.typed_value;
319 const src = decl.src();
320
321 log.debug("gen: {s} type: {}, value: {}", .{ decl.name, typed_value.ty, typed_value.val });
322
323 if (typed_value.val.castTag(.function)) |func_payload| {
324 const func = func_payload.data;
325
326 const llvm_func = try self.resolveLLVMFunction(func.owner_decl, src);
327
328 // This gets the LLVM values from the function and stores them in `self.args`.
329 const fn_param_len = func.owner_decl.typed_value.most_recent.typed_value.ty.fnParamLen();
330 var args = try self.gpa.alloc(*const llvm.Value, fn_param_len);
331 defer self.gpa.free(args);
332
333 for (args) |*arg, i| {
334 arg.* = llvm.getParam(llvm_func, @intCast(c_uint, i));
335 }
336 self.args = args;
337 self.arg_index = 0;
338
339 // Make sure no other LLVM values from other functions can be referenced
340 self.func_inst_table.clearRetainingCapacity();
341
342 // We remove all the basic blocks of a function to support incremental
343 // compilation!
344 // TODO: remove all basic blocks if functions can have more than one
345 if (llvm_func.getFirstBasicBlock()) |bb| {
346 bb.deleteBasicBlock();
347 }
348
349 self.entry_block = self.context.appendBasicBlock(llvm_func, "Entry");
350 self.builder.positionBuilderAtEnd(self.entry_block);
351 self.latest_alloca_inst = null;
352
353 const instructions = func.body.instructions;
354 for (instructions) |inst| {
355 const opt_llvm_val: ?*const llvm.Value = switch (inst.tag) {
356 .add => try self.genAdd(inst.castTag(.add).?),
357 .alloc => try self.genAlloc(inst.castTag(.alloc).?),
358 .arg => try self.genArg(inst.castTag(.arg).?),
359 .bitcast => try self.genBitCast(inst.castTag(.bitcast).?),
360 .breakpoint => try self.genBreakpoint(inst.castTag(.breakpoint).?),
361 .call => try self.genCall(inst.castTag(.call).?),
362 .intcast => try self.genIntCast(inst.castTag(.intcast).?),
363 .load => try self.genLoad(inst.castTag(.load).?),
364 .not => try self.genNot(inst.castTag(.not).?),
365 .ret => try self.genRet(inst.castTag(.ret).?),
366 .retvoid => self.genRetVoid(inst.castTag(.retvoid).?),
367 .store => try self.genStore(inst.castTag(.store).?),
368 .sub => try self.genSub(inst.castTag(.sub).?),
369 .unreach => self.genUnreach(inst.castTag(.unreach).?),
370 .dbg_stmt => blk: {
371 // TODO: implement debug info
372 break :blk null;
373 },
374 else => |tag| return self.fail(src, "TODO implement LLVM codegen for Zir instruction: {}", .{tag}),
375 };
376 if (opt_llvm_val) |llvm_val| try self.func_inst_table.putNoClobber(self.gpa, inst, llvm_val);
377 }
378 } else if (typed_value.val.castTag(.extern_fn)) |extern_fn| {
379 _ = try self.resolveLLVMFunction(extern_fn.data, src);
380 } else {
381 _ = try self.resolveGlobalDecl(decl, src);
382 }
383 }
384
385 fn genCall(self: *LLVMIRModule, inst: *Inst.Call) !?*const llvm.Value {
386 if (inst.func.value()) |func_value| {
387 const fn_decl = if (func_value.castTag(.extern_fn)) |extern_fn|
388 extern_fn.data
389 else if (func_value.castTag(.function)) |func_payload|
390 func_payload.data.owner_decl
391 else
392 unreachable;
393
394 const zig_fn_type = fn_decl.typed_value.most_recent.typed_value.ty;
395 const llvm_fn = try self.resolveLLVMFunction(fn_decl, inst.base.src);
396
397 const num_args = inst.args.len;
398
399 const llvm_param_vals = try self.gpa.alloc(*const llvm.Value, num_args);
400 defer self.gpa.free(llvm_param_vals);
401
402 for (inst.args) |arg, i| {
403 llvm_param_vals[i] = try self.resolveInst(arg);
404 }
405
406 // TODO: LLVMBuildCall2 handles opaque function pointers, according to llvm docs
407 // Do we need that?
408 const call = self.builder.buildCall(
409 llvm_fn,
410 if (num_args == 0) null else llvm_param_vals.ptr,
411 @intCast(c_uint, num_args),
412 "",
413 );
414
415 const return_type = zig_fn_type.fnReturnType();
416 if (return_type.tag() == .noreturn) {
417 _ = self.builder.buildUnreachable();
418 }
419
420 // No need to store the LLVM value if the return type is void or noreturn
421 if (!return_type.hasCodeGenBits()) return null;
422
423 return call;
424 } else {
425 return self.fail(inst.base.src, "TODO implement calling runtime known function pointer LLVM backend", .{});
426 }
427 }
428
429 fn genRetVoid(self: *LLVMIRModule, inst: *Inst.NoOp) ?*const llvm.Value {
430 _ = self.builder.buildRetVoid();
431 return null;
432 }
433
434 fn genRet(self: *LLVMIRModule, inst: *Inst.UnOp) !?*const llvm.Value {
435 _ = self.builder.buildRet(try self.resolveInst(inst.operand));
436 return null;
437 }
438
439 fn genNot(self: *LLVMIRModule, inst: *Inst.UnOp) !?*const llvm.Value {
440 return self.builder.buildNot(try self.resolveInst(inst.operand), "");
441 }
442
443 fn genUnreach(self: *LLVMIRModule, inst: *Inst.NoOp) ?*const llvm.Value {
444 _ = self.builder.buildUnreachable();
445 return null;
446 }
447
448 fn genAdd(self: *LLVMIRModule, inst: *Inst.BinOp) !?*const llvm.Value {
449 const lhs = try self.resolveInst(inst.lhs);
450 const rhs = try self.resolveInst(inst.rhs);
451
452 if (!inst.base.ty.isInt())
453 return self.fail(inst.base.src, "TODO implement 'genAdd' for type {}", .{inst.base.ty});
454
455 return if (inst.base.ty.isSignedInt())
456 self.builder.buildNSWAdd(lhs, rhs, "")
457 else
458 self.builder.buildNUWAdd(lhs, rhs, "");
459 }
460
461 fn genSub(self: *LLVMIRModule, inst: *Inst.BinOp) !?*const llvm.Value {
462 const lhs = try self.resolveInst(inst.lhs);
463 const rhs = try self.resolveInst(inst.rhs);
464
465 if (!inst.base.ty.isInt())
466 return self.fail(inst.base.src, "TODO implement 'genSub' for type {}", .{inst.base.ty});
467
468 return if (inst.base.ty.isSignedInt())
469 self.builder.buildNSWSub(lhs, rhs, "")
470 else
471 self.builder.buildNUWSub(lhs, rhs, "");
472 }
473
474 fn genIntCast(self: *LLVMIRModule, inst: *Inst.UnOp) !?*const llvm.Value {
475 const val = try self.resolveInst(inst.operand);
476
477 const signed = inst.base.ty.isSignedInt();
478 // TODO: Should we use intcast here or just a simple bitcast?
479 // LLVM does truncation vs bitcast (+signed extension) in the intcast depending on the sizes
480 return self.builder.buildIntCast2(val, try self.getLLVMType(inst.base.ty, inst.base.src), signed, "");
481 }
482
483 fn genBitCast(self: *LLVMIRModule, inst: *Inst.UnOp) !?*const llvm.Value {
484 const val = try self.resolveInst(inst.operand);
485 const dest_type = try self.getLLVMType(inst.base.ty, inst.base.src);
486
487 return self.builder.buildBitCast(val, dest_type, "");
488 }
489
490 fn genArg(self: *LLVMIRModule, inst: *Inst.Arg) !?*const llvm.Value {
491 const arg_val = self.args[self.arg_index];
492 self.arg_index += 1;
493
494 const ptr_val = self.buildAlloca(try self.getLLVMType(inst.base.ty, inst.base.src));
495 _ = self.builder.buildStore(arg_val, ptr_val);
496 return self.builder.buildLoad(ptr_val, "");
497 }
498
499 fn genAlloc(self: *LLVMIRModule, inst: *Inst.NoOp) !?*const llvm.Value {
500 // buildAlloca expects the pointee type, not the pointer type, so assert that
501 // a Payload.PointerSimple is passed to the alloc instruction.
502 const pointee_type = inst.base.ty.castPointer().?.data;
503
504 // TODO: figure out a way to get the name of the var decl.
505 // TODO: set alignment and volatile
506 return self.buildAlloca(try self.getLLVMType(pointee_type, inst.base.src));
507 }
508
509 /// Use this instead of builder.buildAlloca, because this function makes sure to
510 /// put the alloca instruction at the top of the function!
511 fn buildAlloca(self: *LLVMIRModule, t: *const llvm.Type) *const llvm.Value {
512 if (self.latest_alloca_inst) |latest_alloc| {
513 // builder.positionBuilder adds it before the instruction,
514 // but we want to put it after the last alloca instruction.
515 self.builder.positionBuilder(self.entry_block, latest_alloc.getNextInstruction().?);
516 } else {
517 // There might have been other instructions emitted before the
518 // first alloca has been generated. However the alloca should still
519 // be first in the function.
520 if (self.entry_block.getFirstInstruction()) |first_inst| {
521 self.builder.positionBuilder(self.entry_block, first_inst);
522 }
523 }
524 defer self.builder.positionBuilderAtEnd(self.entry_block);
525
526 const val = self.builder.buildAlloca(t, "");
527 self.latest_alloca_inst = val;
528 return val;
529 }
530
531 fn genStore(self: *LLVMIRModule, inst: *Inst.BinOp) !?*const llvm.Value {
532 const val = try self.resolveInst(inst.rhs);
533 const ptr = try self.resolveInst(inst.lhs);
534 _ = self.builder.buildStore(val, ptr);
535 return null;
536 }
537
538 fn genLoad(self: *LLVMIRModule, inst: *Inst.UnOp) !?*const llvm.Value {
539 const ptr_val = try self.resolveInst(inst.operand);
540 return self.builder.buildLoad(ptr_val, "");
541 }
542
543 fn genBreakpoint(self: *LLVMIRModule, inst: *Inst.NoOp) !?*const llvm.Value {
544 const llvn_fn = self.getIntrinsic("llvm.debugtrap");
545 _ = self.builder.buildCall(llvn_fn, null, 0, "");
546 return null;
547 }
548
549 fn getIntrinsic(self: *LLVMIRModule, name: []const u8) *const llvm.Value {
550 const id = llvm.lookupIntrinsicID(name.ptr, name.len);
551 assert(id != 0);
552 // TODO: add support for overload intrinsics by passing the prefix of the intrinsic
553 // to `lookupIntrinsicID` and then passing the correct types to
554 // `getIntrinsicDeclaration`
555 return self.llvm_module.getIntrinsicDeclaration(id, null, 0);
556 }
557
558 fn resolveInst(self: *LLVMIRModule, inst: *ir.Inst) !*const llvm.Value {
559 if (inst.value()) |val| {
560 return self.genTypedValue(inst.src, .{ .ty = inst.ty, .val = val });
561 }
562 if (self.func_inst_table.get(inst)) |value| return value;
563
564 return self.fail(inst.src, "TODO implement global llvm values (or the value is not in the func_inst_table table)", .{});
565 }
566
567 fn genTypedValue(self: *LLVMIRModule, src: usize, tv: TypedValue) error{ OutOfMemory, CodegenFail }!*const llvm.Value {
568 const llvm_type = try self.getLLVMType(tv.ty, src);
569
570 if (tv.val.isUndef())
571 return llvm_type.getUndef();
572
573 switch (tv.ty.zigTypeTag()) {
574 .Bool => return if (tv.val.toBool()) llvm_type.constAllOnes() else llvm_type.constNull(),
575 .Int => {
576 var bigint_space: Value.BigIntSpace = undefined;
577 const bigint = tv.val.toBigInt(&bigint_space);
578
579 if (bigint.eqZero()) return llvm_type.constNull();
580
581 if (bigint.limbs.len != 1) {
582 return self.fail(src, "TODO implement bigger bigint", .{});
583 }
584 const llvm_int = llvm_type.constInt(bigint.limbs[0], false);
585 if (!bigint.positive) {
586 return llvm.constNeg(llvm_int);
587 }
588 return llvm_int;
589 },
590 .Pointer => switch (tv.val.tag()) {
591 .decl_ref => {
592 const decl = tv.val.castTag(.decl_ref).?.data;
593 const val = try self.resolveGlobalDecl(decl, src);
594
595 const usize_type = try self.getLLVMType(Type.initTag(.usize), src);
596
597 // TODO: second index should be the index into the memory!
598 var indices: [2]*const llvm.Value = .{
599 usize_type.constNull(),
600 usize_type.constNull(),
601 };
602
603 // TODO: consider using buildInBoundsGEP2 for opaque pointers
604 return self.builder.buildInBoundsGEP(val, &indices, 2, "");
605 },
606 else => return self.fail(src, "TODO implement const of pointer type '{}'", .{tv.ty}),
607 },
608 .Array => {
609 if (tv.val.castTag(.bytes)) |payload| {
610 const zero_sentinel = if (tv.ty.sentinel()) |sentinel| blk: {
611 if (sentinel.tag() == .zero) break :blk true;
612 return self.fail(src, "TODO handle other sentinel values", .{});
613 } else false;
614
615 return self.context.constString(payload.data.ptr, @intCast(c_uint, payload.data.len), !zero_sentinel);
616 } else {
617 return self.fail(src, "TODO handle more array values", .{});
618 }
619 },
620 else => return self.fail(src, "TODO implement const of type '{}'", .{tv.ty}),
621 }
622 }
623
624 fn getLLVMType(self: *LLVMIRModule, t: Type, src: usize) error{ OutOfMemory, CodegenFail }!*const llvm.Type {
625 switch (t.zigTypeTag()) {
626 .Void => return self.context.voidType(),
627 .NoReturn => return self.context.voidType(),
628 .Int => {
629 const info = t.intInfo(self.module.getTarget());
630 return self.context.intType(info.bits);
631 },
632 .Bool => return self.context.intType(1),
633 .Pointer => {
634 if (t.isSlice()) {
635 return self.fail(src, "TODO: LLVM backend: implement slices", .{});
636 } else {
637 const elem_type = try self.getLLVMType(t.elemType(), src);
638 return elem_type.pointerType(0);
639 }
640 },
641 .Array => {
642 const elem_type = try self.getLLVMType(t.elemType(), src);
643 return elem_type.arrayType(@intCast(c_uint, t.abiSize(self.module.getTarget())));
644 },
645 else => return self.fail(src, "TODO implement getLLVMType for type '{}'", .{t}),
646 }
647 }
648
649 fn resolveGlobalDecl(self: *LLVMIRModule, decl: *Module.Decl, src: usize) error{ OutOfMemory, CodegenFail }!*const llvm.Value {
650 // TODO: do we want to store this in our own datastructure?
651 if (self.llvm_module.getNamedGlobal(decl.name)) |val| return val;
652
653 const typed_value = decl.typed_value.most_recent.typed_value;
654
655 // TODO: remove this redundant `getLLVMType`, it is also called in `genTypedValue`.
656 const llvm_type = try self.getLLVMType(typed_value.ty, src);
657 const val = try self.genTypedValue(src, typed_value);
658 const global = self.llvm_module.addGlobal(llvm_type, decl.name);
659 llvm.setInitializer(global, val);
660
661 // TODO ask the Decl if it is const
662 // https://github.com/ziglang/zig/issues/7582
663
664 return global;
665 }
666
667 /// If the llvm function does not exist, create it
668 fn resolveLLVMFunction(self: *LLVMIRModule, func: *Module.Decl, src: usize) !*const llvm.Value {
669 // TODO: do we want to store this in our own datastructure?
670 if (self.llvm_module.getNamedFunction(func.name)) |llvm_fn| return llvm_fn;
671
672 const zig_fn_type = func.typed_value.most_recent.typed_value.ty;
673 const return_type = zig_fn_type.fnReturnType();
674
675 const fn_param_len = zig_fn_type.fnParamLen();
676
677 const fn_param_types = try self.gpa.alloc(Type, fn_param_len);
678 defer self.gpa.free(fn_param_types);
679 zig_fn_type.fnParamTypes(fn_param_types);
680
681 const llvm_param = try self.gpa.alloc(*const llvm.Type, fn_param_len);
682 defer self.gpa.free(llvm_param);
683
684 for (fn_param_types) |fn_param, i| {
685 llvm_param[i] = try self.getLLVMType(fn_param, src);
686 }
687
688 const fn_type = llvm.Type.functionType(
689 try self.getLLVMType(return_type, src),
690 if (fn_param_len == 0) null else llvm_param.ptr,
691 @intCast(c_uint, fn_param_len),
692 false,
693 );
694 const llvm_fn = self.llvm_module.addFunction(func.name, fn_type);
695
696 if (return_type.tag() == .noreturn) {
697 self.addFnAttr(llvm_fn, "noreturn");
698 }
699
700 return llvm_fn;
701 }
702
703 // Helper functions
704 fn addAttr(self: LLVMIRModule, val: *const llvm.Value, index: llvm.AttributeIndex, name: []const u8) void {
705 const kind_id = llvm.getEnumAttributeKindForName(name.ptr, name.len);
706 assert(kind_id != 0);
707 const llvm_attr = self.context.createEnumAttribute(kind_id, 0);
708 val.addAttributeAtIndex(index, llvm_attr);
709 }
710
711 fn addFnAttr(self: *LLVMIRModule, val: *const llvm.Value, attr_name: []const u8) void {
712 // TODO: improve this API, `addAttr(-1, attr_name)`
713 self.addAttr(val, std.math.maxInt(llvm.AttributeIndex), attr_name);
714 }
715
716 pub fn fail(self: *LLVMIRModule, src: usize, comptime format: []const u8, args: anytype) error{ OutOfMemory, CodegenFail } {
717 @setCold(true);
718 assert(self.err_msg == null);
719 self.err_msg = try Compilation.ErrorMsg.create(self.gpa, src, format, args);
720 return error.CodegenFail;
721 }
722};
src/llvm_bindings.zig deleted-574
...@@ -1,574 +0,0 @@
1//! We do this instead of @cImport because the self-hosted compiler is easier
2//! to bootstrap if it does not depend on translate-c.
3
4const std = @import("std");
5const assert = std.debug.assert;
6
7const LLVMBool = bool;
8pub const AttributeIndex = c_uint;
9
10/// Make sure to use the *InContext functions instead of the global ones.
11pub const Context = opaque {
12 pub const create = LLVMContextCreate;
13 extern fn LLVMContextCreate() *const Context;
14
15 pub const dispose = LLVMContextDispose;
16 extern fn LLVMContextDispose(C: *const Context) void;
17
18 pub const createEnumAttribute = LLVMCreateEnumAttribute;
19 extern fn LLVMCreateEnumAttribute(*const Context, KindID: c_uint, Val: u64) *const Attribute;
20
21 pub const intType = LLVMIntTypeInContext;
22 extern fn LLVMIntTypeInContext(C: *const Context, NumBits: c_uint) *const Type;
23
24 pub const voidType = LLVMVoidTypeInContext;
25 extern fn LLVMVoidTypeInContext(C: *const Context) *const Type;
26
27 pub const constString = LLVMConstStringInContext;
28 extern fn LLVMConstStringInContext(C: *const Context, Str: [*]const u8, Length: c_uint, DontNullTerminate: LLVMBool) *const Value;
29
30 pub const appendBasicBlock = LLVMAppendBasicBlockInContext;
31 extern fn LLVMAppendBasicBlockInContext(C: *const Context, Fn: *const Value, Name: [*:0]const u8) *const BasicBlock;
32
33 pub const createBuilder = LLVMCreateBuilderInContext;
34 extern fn LLVMCreateBuilderInContext(C: *const Context) *const Builder;
35};
36
37pub const Value = opaque {
38 pub const addAttributeAtIndex = LLVMAddAttributeAtIndex;
39 extern fn LLVMAddAttributeAtIndex(*const Value, Idx: AttributeIndex, A: *const Attribute) void;
40
41 pub const getFirstBasicBlock = LLVMGetFirstBasicBlock;
42 extern fn LLVMGetFirstBasicBlock(Fn: *const Value) ?*const BasicBlock;
43
44 pub const getNextInstruction = LLVMGetNextInstruction;
45 extern fn LLVMGetNextInstruction(Inst: *const Value) ?*const Value;
46};
47
48pub const Type = opaque {
49 pub const functionType = LLVMFunctionType;
50 extern fn LLVMFunctionType(ReturnType: *const Type, ParamTypes: ?[*]*const Type, ParamCount: c_uint, IsVarArg: LLVMBool) *const Type;
51
52 pub const constNull = LLVMConstNull;
53 extern fn LLVMConstNull(Ty: *const Type) *const Value;
54
55 pub const constAllOnes = LLVMConstAllOnes;
56 extern fn LLVMConstAllOnes(Ty: *const Type) *const Value;
57
58 pub const constInt = LLVMConstInt;
59 extern fn LLVMConstInt(IntTy: *const Type, N: c_ulonglong, SignExtend: LLVMBool) *const Value;
60
61 pub const constArray = LLVMConstArray;
62 extern fn LLVMConstArray(ElementTy: *const Type, ConstantVals: ?[*]*const Value, Length: c_uint) *const Value;
63
64 pub const getUndef = LLVMGetUndef;
65 extern fn LLVMGetUndef(Ty: *const Type) *const Value;
66
67 pub const pointerType = LLVMPointerType;
68 extern fn LLVMPointerType(ElementType: *const Type, AddressSpace: c_uint) *const Type;
69
70 pub const arrayType = LLVMArrayType;
71 extern fn LLVMArrayType(ElementType: *const Type, ElementCount: c_uint) *const Type;
72};
73
74pub const Module = opaque {
75 pub const createWithName = LLVMModuleCreateWithNameInContext;
76 extern fn LLVMModuleCreateWithNameInContext(ModuleID: [*:0]const u8, C: *const Context) *const Module;
77
78 pub const dispose = LLVMDisposeModule;
79 extern fn LLVMDisposeModule(*const Module) void;
80
81 pub const verify = LLVMVerifyModule;
82 extern fn LLVMVerifyModule(*const Module, Action: VerifierFailureAction, OutMessage: *[*:0]const u8) LLVMBool;
83
84 pub const addFunction = LLVMAddFunction;
85 extern fn LLVMAddFunction(*const Module, Name: [*:0]const u8, FunctionTy: *const Type) *const Value;
86
87 pub const getNamedFunction = LLVMGetNamedFunction;
88 extern fn LLVMGetNamedFunction(*const Module, Name: [*:0]const u8) ?*const Value;
89
90 pub const getIntrinsicDeclaration = LLVMGetIntrinsicDeclaration;
91 extern fn LLVMGetIntrinsicDeclaration(Mod: *const Module, ID: c_uint, ParamTypes: ?[*]*const Type, ParamCount: usize) *const Value;
92
93 pub const printToString = LLVMPrintModuleToString;
94 extern fn LLVMPrintModuleToString(*const Module) [*:0]const u8;
95
96 pub const addGlobal = LLVMAddGlobal;
97 extern fn LLVMAddGlobal(M: *const Module, Ty: *const Type, Name: [*:0]const u8) *const Value;
98
99 pub const getNamedGlobal = LLVMGetNamedGlobal;
100 extern fn LLVMGetNamedGlobal(M: *const Module, Name: [*:0]const u8) ?*const Value;
101};
102
103pub const lookupIntrinsicID = LLVMLookupIntrinsicID;
104extern fn LLVMLookupIntrinsicID(Name: [*]const u8, NameLen: usize) c_uint;
105
106pub const disposeMessage = LLVMDisposeMessage;
107extern fn LLVMDisposeMessage(Message: [*:0]const u8) void;
108
109pub const VerifierFailureAction = extern enum {
110 AbortProcess,
111 PrintMessage,
112 ReturnStatus,
113};
114
115pub const constNeg = LLVMConstNeg;
116extern fn LLVMConstNeg(ConstantVal: *const Value) *const Value;
117
118pub const setInitializer = LLVMSetInitializer;
119extern fn LLVMSetInitializer(GlobalVar: *const Value, ConstantVal: *const Value) void;
120
121pub const getParam = LLVMGetParam;
122extern fn LLVMGetParam(Fn: *const Value, Index: c_uint) *const Value;
123
124pub const getEnumAttributeKindForName = LLVMGetEnumAttributeKindForName;
125extern fn LLVMGetEnumAttributeKindForName(Name: [*]const u8, SLen: usize) c_uint;
126
127pub const Attribute = opaque {};
128
129pub const Builder = opaque {
130 pub const dispose = LLVMDisposeBuilder;
131 extern fn LLVMDisposeBuilder(Builder: *const Builder) void;
132
133 pub const positionBuilder = LLVMPositionBuilder;
134 extern fn LLVMPositionBuilder(Builder: *const Builder, Block: *const BasicBlock, Instr: *const Value) void;
135
136 pub const positionBuilderAtEnd = LLVMPositionBuilderAtEnd;
137 extern fn LLVMPositionBuilderAtEnd(Builder: *const Builder, Block: *const BasicBlock) void;
138
139 pub const getInsertBlock = LLVMGetInsertBlock;
140 extern fn LLVMGetInsertBlock(Builder: *const Builder) *const BasicBlock;
141
142 pub const buildCall = LLVMBuildCall;
143 extern fn LLVMBuildCall(*const Builder, Fn: *const Value, Args: ?[*]*const Value, NumArgs: c_uint, Name: [*:0]const u8) *const Value;
144
145 pub const buildCall2 = LLVMBuildCall2;
146 extern fn LLVMBuildCall2(*const Builder, *const Type, Fn: *const Value, Args: [*]*const Value, NumArgs: c_uint, Name: [*:0]const u8) *const Value;
147
148 pub const buildRetVoid = LLVMBuildRetVoid;
149 extern fn LLVMBuildRetVoid(*const Builder) *const Value;
150
151 pub const buildRet = LLVMBuildRet;
152 extern fn LLVMBuildRet(*const Builder, V: *const Value) *const Value;
153
154 pub const buildUnreachable = LLVMBuildUnreachable;
155 extern fn LLVMBuildUnreachable(*const Builder) *const Value;
156
157 pub const buildAlloca = LLVMBuildAlloca;
158 extern fn LLVMBuildAlloca(*const Builder, Ty: *const Type, Name: [*:0]const u8) *const Value;
159
160 pub const buildStore = LLVMBuildStore;
161 extern fn LLVMBuildStore(*const Builder, Val: *const Value, Ptr: *const Value) *const Value;
162
163 pub const buildLoad = LLVMBuildLoad;
164 extern fn LLVMBuildLoad(*const Builder, PointerVal: *const Value, Name: [*:0]const u8) *const Value;
165
166 pub const buildNot = LLVMBuildNot;
167 extern fn LLVMBuildNot(*const Builder, V: *const Value, Name: [*:0]const u8) *const Value;
168
169 pub const buildNSWAdd = LLVMBuildNSWAdd;
170 extern fn LLVMBuildNSWAdd(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value;
171
172 pub const buildNUWAdd = LLVMBuildNUWAdd;
173 extern fn LLVMBuildNUWAdd(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value;
174
175 pub const buildNSWSub = LLVMBuildNSWSub;
176 extern fn LLVMBuildNSWSub(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value;
177
178 pub const buildNUWSub = LLVMBuildNUWSub;
179 extern fn LLVMBuildNUWSub(*const Builder, LHS: *const Value, RHS: *const Value, Name: [*:0]const u8) *const Value;
180
181 pub const buildIntCast2 = LLVMBuildIntCast2;
182 extern fn LLVMBuildIntCast2(*const Builder, Val: *const Value, DestTy: *const Type, IsSigned: LLVMBool, Name: [*:0]const u8) *const Value;
183
184 pub const buildBitCast = LLVMBuildBitCast;
185 extern fn LLVMBuildBitCast(*const Builder, Val: *const Value, DestTy: *const Type, Name: [*:0]const u8) *const Value;
186
187 pub const buildInBoundsGEP = LLVMBuildInBoundsGEP;
188 extern fn LLVMBuildInBoundsGEP(B: *const Builder, Pointer: *const Value, Indices: [*]*const Value, NumIndices: c_uint, Name: [*:0]const u8) *const Value;
189};
190
191pub const BasicBlock = opaque {
192 pub const deleteBasicBlock = LLVMDeleteBasicBlock;
193 extern fn LLVMDeleteBasicBlock(BB: *const BasicBlock) void;
194
195 pub const getFirstInstruction = LLVMGetFirstInstruction;
196 extern fn LLVMGetFirstInstruction(BB: *const BasicBlock) ?*const Value;
197};
198
199pub const TargetMachine = opaque {
200 pub const create = LLVMCreateTargetMachine;
201 extern fn LLVMCreateTargetMachine(
202 T: *const Target,
203 Triple: [*:0]const u8,
204 CPU: [*:0]const u8,
205 Features: [*:0]const u8,
206 Level: CodeGenOptLevel,
207 Reloc: RelocMode,
208 CodeModel: CodeMode,
209 ) *const TargetMachine;
210
211 pub const dispose = LLVMDisposeTargetMachine;
212 extern fn LLVMDisposeTargetMachine(T: *const TargetMachine) void;
213
214 pub const emitToFile = LLVMTargetMachineEmitToFile;
215 extern fn LLVMTargetMachineEmitToFile(*const TargetMachine, M: *const Module, Filename: [*:0]const u8, codegen: CodeGenFileType, ErrorMessage: *[*:0]const u8) LLVMBool;
216};
217
218pub const CodeMode = extern enum {
219 Default,
220 JITDefault,
221 Tiny,
222 Small,
223 Kernel,
224 Medium,
225 Large,
226};
227
228pub const CodeGenOptLevel = extern enum {
229 None,
230 Less,
231 Default,
232 Aggressive,
233};
234
235pub const RelocMode = extern enum {
236 Default,
237 Static,
238 PIC,
239 DynamicNoPic,
240 ROPI,
241 RWPI,
242 ROPI_RWPI,
243};
244
245pub const CodeGenFileType = extern enum {
246 AssemblyFile,
247 ObjectFile,
248};
249
250pub const Target = opaque {
251 pub const getFromTriple = LLVMGetTargetFromTriple;
252 extern fn LLVMGetTargetFromTriple(Triple: [*:0]const u8, T: **const Target, ErrorMessage: *[*:0]const u8) LLVMBool;
253};
254
255extern fn LLVMInitializeAArch64TargetInfo() void;
256extern fn LLVMInitializeAMDGPUTargetInfo() void;
257extern fn LLVMInitializeARMTargetInfo() void;
258extern fn LLVMInitializeAVRTargetInfo() void;
259extern fn LLVMInitializeBPFTargetInfo() void;
260extern fn LLVMInitializeHexagonTargetInfo() void;
261extern fn LLVMInitializeLanaiTargetInfo() void;
262extern fn LLVMInitializeMipsTargetInfo() void;
263extern fn LLVMInitializeMSP430TargetInfo() void;
264extern fn LLVMInitializeNVPTXTargetInfo() void;
265extern fn LLVMInitializePowerPCTargetInfo() void;
266extern fn LLVMInitializeRISCVTargetInfo() void;
267extern fn LLVMInitializeSparcTargetInfo() void;
268extern fn LLVMInitializeSystemZTargetInfo() void;
269extern fn LLVMInitializeWebAssemblyTargetInfo() void;
270extern fn LLVMInitializeX86TargetInfo() void;
271extern fn LLVMInitializeXCoreTargetInfo() void;
272extern fn LLVMInitializeAArch64Target() void;
273extern fn LLVMInitializeAMDGPUTarget() void;
274extern fn LLVMInitializeARMTarget() void;
275extern fn LLVMInitializeAVRTarget() void;
276extern fn LLVMInitializeBPFTarget() void;
277extern fn LLVMInitializeHexagonTarget() void;
278extern fn LLVMInitializeLanaiTarget() void;
279extern fn LLVMInitializeMipsTarget() void;
280extern fn LLVMInitializeMSP430Target() void;
281extern fn LLVMInitializeNVPTXTarget() void;
282extern fn LLVMInitializePowerPCTarget() void;
283extern fn LLVMInitializeRISCVTarget() void;
284extern fn LLVMInitializeSparcTarget() void;
285extern fn LLVMInitializeSystemZTarget() void;
286extern fn LLVMInitializeWebAssemblyTarget() void;
287extern fn LLVMInitializeX86Target() void;
288extern fn LLVMInitializeXCoreTarget() void;
289extern fn LLVMInitializeAArch64TargetMC() void;
290extern fn LLVMInitializeAMDGPUTargetMC() void;
291extern fn LLVMInitializeARMTargetMC() void;
292extern fn LLVMInitializeAVRTargetMC() void;
293extern fn LLVMInitializeBPFTargetMC() void;
294extern fn LLVMInitializeHexagonTargetMC() void;
295extern fn LLVMInitializeLanaiTargetMC() void;
296extern fn LLVMInitializeMipsTargetMC() void;
297extern fn LLVMInitializeMSP430TargetMC() void;
298extern fn LLVMInitializeNVPTXTargetMC() void;
299extern fn LLVMInitializePowerPCTargetMC() void;
300extern fn LLVMInitializeRISCVTargetMC() void;
301extern fn LLVMInitializeSparcTargetMC() void;
302extern fn LLVMInitializeSystemZTargetMC() void;
303extern fn LLVMInitializeWebAssemblyTargetMC() void;
304extern fn LLVMInitializeX86TargetMC() void;
305extern fn LLVMInitializeXCoreTargetMC() void;
306extern fn LLVMInitializeAArch64AsmPrinter() void;
307extern fn LLVMInitializeAMDGPUAsmPrinter() void;
308extern fn LLVMInitializeARMAsmPrinter() void;
309extern fn LLVMInitializeAVRAsmPrinter() void;
310extern fn LLVMInitializeBPFAsmPrinter() void;
311extern fn LLVMInitializeHexagonAsmPrinter() void;
312extern fn LLVMInitializeLanaiAsmPrinter() void;
313extern fn LLVMInitializeMipsAsmPrinter() void;
314extern fn LLVMInitializeMSP430AsmPrinter() void;
315extern fn LLVMInitializeNVPTXAsmPrinter() void;
316extern fn LLVMInitializePowerPCAsmPrinter() void;
317extern fn LLVMInitializeRISCVAsmPrinter() void;
318extern fn LLVMInitializeSparcAsmPrinter() void;
319extern fn LLVMInitializeSystemZAsmPrinter() void;
320extern fn LLVMInitializeWebAssemblyAsmPrinter() void;
321extern fn LLVMInitializeX86AsmPrinter() void;
322extern fn LLVMInitializeXCoreAsmPrinter() void;
323extern fn LLVMInitializeAArch64AsmParser() void;
324extern fn LLVMInitializeAMDGPUAsmParser() void;
325extern fn LLVMInitializeARMAsmParser() void;
326extern fn LLVMInitializeAVRAsmParser() void;
327extern fn LLVMInitializeBPFAsmParser() void;
328extern fn LLVMInitializeHexagonAsmParser() void;
329extern fn LLVMInitializeLanaiAsmParser() void;
330extern fn LLVMInitializeMipsAsmParser() void;
331extern fn LLVMInitializeMSP430AsmParser() void;
332extern fn LLVMInitializePowerPCAsmParser() void;
333extern fn LLVMInitializeRISCVAsmParser() void;
334extern fn LLVMInitializeSparcAsmParser() void;
335extern fn LLVMInitializeSystemZAsmParser() void;
336extern fn LLVMInitializeWebAssemblyAsmParser() void;
337extern fn LLVMInitializeX86AsmParser() void;
338
339pub const initializeAllTargetInfos = LLVMInitializeAllTargetInfos;
340fn LLVMInitializeAllTargetInfos() callconv(.C) void {
341 LLVMInitializeAArch64TargetInfo();
342 LLVMInitializeAMDGPUTargetInfo();
343 LLVMInitializeARMTargetInfo();
344 LLVMInitializeAVRTargetInfo();
345 LLVMInitializeBPFTargetInfo();
346 LLVMInitializeHexagonTargetInfo();
347 LLVMInitializeLanaiTargetInfo();
348 LLVMInitializeMipsTargetInfo();
349 LLVMInitializeMSP430TargetInfo();
350 LLVMInitializeNVPTXTargetInfo();
351 LLVMInitializePowerPCTargetInfo();
352 LLVMInitializeRISCVTargetInfo();
353 LLVMInitializeSparcTargetInfo();
354 LLVMInitializeSystemZTargetInfo();
355 LLVMInitializeWebAssemblyTargetInfo();
356 LLVMInitializeX86TargetInfo();
357 LLVMInitializeXCoreTargetInfo();
358}
359pub const initializeAllTargets = LLVMInitializeAllTargets;
360fn LLVMInitializeAllTargets() callconv(.C) void {
361 LLVMInitializeAArch64Target();
362 LLVMInitializeAMDGPUTarget();
363 LLVMInitializeARMTarget();
364 LLVMInitializeAVRTarget();
365 LLVMInitializeBPFTarget();
366 LLVMInitializeHexagonTarget();
367 LLVMInitializeLanaiTarget();
368 LLVMInitializeMipsTarget();
369 LLVMInitializeMSP430Target();
370 LLVMInitializeNVPTXTarget();
371 LLVMInitializePowerPCTarget();
372 LLVMInitializeRISCVTarget();
373 LLVMInitializeSparcTarget();
374 LLVMInitializeSystemZTarget();
375 LLVMInitializeWebAssemblyTarget();
376 LLVMInitializeX86Target();
377 LLVMInitializeXCoreTarget();
378}
379pub const initializeAllTargetMCs = LLVMInitializeAllTargetMCs;
380fn LLVMInitializeAllTargetMCs() callconv(.C) void {
381 LLVMInitializeAArch64TargetMC();
382 LLVMInitializeAMDGPUTargetMC();
383 LLVMInitializeARMTargetMC();
384 LLVMInitializeAVRTargetMC();
385 LLVMInitializeBPFTargetMC();
386 LLVMInitializeHexagonTargetMC();
387 LLVMInitializeLanaiTargetMC();
388 LLVMInitializeMipsTargetMC();
389 LLVMInitializeMSP430TargetMC();
390 LLVMInitializeNVPTXTargetMC();
391 LLVMInitializePowerPCTargetMC();
392 LLVMInitializeRISCVTargetMC();
393 LLVMInitializeSparcTargetMC();
394 LLVMInitializeSystemZTargetMC();
395 LLVMInitializeWebAssemblyTargetMC();
396 LLVMInitializeX86TargetMC();
397 LLVMInitializeXCoreTargetMC();
398}
399pub const initializeAllAsmPrinters = LLVMInitializeAllAsmPrinters;
400fn LLVMInitializeAllAsmPrinters() callconv(.C) void {
401 LLVMInitializeAArch64AsmPrinter();
402 LLVMInitializeAMDGPUAsmPrinter();
403 LLVMInitializeARMAsmPrinter();
404 LLVMInitializeAVRAsmPrinter();
405 LLVMInitializeBPFAsmPrinter();
406 LLVMInitializeHexagonAsmPrinter();
407 LLVMInitializeLanaiAsmPrinter();
408 LLVMInitializeMipsAsmPrinter();
409 LLVMInitializeMSP430AsmPrinter();
410 LLVMInitializeNVPTXAsmPrinter();
411 LLVMInitializePowerPCAsmPrinter();
412 LLVMInitializeRISCVAsmPrinter();
413 LLVMInitializeSparcAsmPrinter();
414 LLVMInitializeSystemZAsmPrinter();
415 LLVMInitializeWebAssemblyAsmPrinter();
416 LLVMInitializeX86AsmPrinter();
417 LLVMInitializeXCoreAsmPrinter();
418}
419pub const initializeAllAsmParsers = LLVMInitializeAllAsmParsers;
420fn LLVMInitializeAllAsmParsers() callconv(.C) void {
421 LLVMInitializeAArch64AsmParser();
422 LLVMInitializeAMDGPUAsmParser();
423 LLVMInitializeARMAsmParser();
424 LLVMInitializeAVRAsmParser();
425 LLVMInitializeBPFAsmParser();
426 LLVMInitializeHexagonAsmParser();
427 LLVMInitializeLanaiAsmParser();
428 LLVMInitializeMipsAsmParser();
429 LLVMInitializeMSP430AsmParser();
430 LLVMInitializePowerPCAsmParser();
431 LLVMInitializeRISCVAsmParser();
432 LLVMInitializeSparcAsmParser();
433 LLVMInitializeSystemZAsmParser();
434 LLVMInitializeWebAssemblyAsmParser();
435 LLVMInitializeX86AsmParser();
436}
437
438extern fn ZigLLDLinkCOFF(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int;
439extern fn ZigLLDLinkELF(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int;
440extern fn ZigLLDLinkMachO(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int;
441extern fn ZigLLDLinkWasm(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int;
442
443pub const LinkCOFF = ZigLLDLinkCOFF;
444pub const LinkELF = ZigLLDLinkELF;
445pub const LinkMachO = ZigLLDLinkMachO;
446pub const LinkWasm = ZigLLDLinkWasm;
447
448pub const ObjectFormatType = extern enum(c_int) {
449 Unknown,
450 COFF,
451 ELF,
452 MachO,
453 Wasm,
454 XCOFF,
455};
456
457pub const GetHostCPUName = LLVMGetHostCPUName;
458extern fn LLVMGetHostCPUName() ?[*:0]u8;
459
460pub const GetNativeFeatures = ZigLLVMGetNativeFeatures;
461extern fn ZigLLVMGetNativeFeatures() ?[*:0]u8;
462
463pub const WriteArchive = ZigLLVMWriteArchive;
464extern fn ZigLLVMWriteArchive(
465 archive_name: [*:0]const u8,
466 file_names_ptr: [*]const [*:0]const u8,
467 file_names_len: usize,
468 os_type: OSType,
469) bool;
470
471pub const OSType = extern enum(c_int) {
472 UnknownOS = 0,
473 Ananas = 1,
474 CloudABI = 2,
475 Darwin = 3,
476 DragonFly = 4,
477 FreeBSD = 5,
478 Fuchsia = 6,
479 IOS = 7,
480 KFreeBSD = 8,
481 Linux = 9,
482 Lv2 = 10,
483 MacOSX = 11,
484 NetBSD = 12,
485 OpenBSD = 13,
486 Solaris = 14,
487 Win32 = 15,
488 Haiku = 16,
489 Minix = 17,
490 RTEMS = 18,
491 NaCl = 19,
492 CNK = 20,
493 AIX = 21,
494 CUDA = 22,
495 NVCL = 23,
496 AMDHSA = 24,
497 PS4 = 25,
498 ELFIAMCU = 26,
499 TvOS = 27,
500 WatchOS = 28,
501 Mesa3D = 29,
502 Contiki = 30,
503 AMDPAL = 31,
504 HermitCore = 32,
505 Hurd = 33,
506 WASI = 34,
507 Emscripten = 35,
508};
509
510pub const ArchType = extern enum(c_int) {
511 UnknownArch = 0,
512 arm = 1,
513 armeb = 2,
514 aarch64 = 3,
515 aarch64_be = 4,
516 aarch64_32 = 5,
517 arc = 6,
518 avr = 7,
519 bpfel = 8,
520 bpfeb = 9,
521 hexagon = 10,
522 mips = 11,
523 mipsel = 12,
524 mips64 = 13,
525 mips64el = 14,
526 msp430 = 15,
527 ppc = 16,
528 ppc64 = 17,
529 ppc64le = 18,
530 r600 = 19,
531 amdgcn = 20,
532 riscv32 = 21,
533 riscv64 = 22,
534 sparc = 23,
535 sparcv9 = 24,
536 sparcel = 25,
537 systemz = 26,
538 tce = 27,
539 tcele = 28,
540 thumb = 29,
541 thumbeb = 30,
542 x86 = 31,
543 x86_64 = 32,
544 xcore = 33,
545 nvptx = 34,
546 nvptx64 = 35,
547 le32 = 36,
548 le64 = 37,
549 amdil = 38,
550 amdil64 = 39,
551 hsail = 40,
552 hsail64 = 41,
553 spir = 42,
554 spir64 = 43,
555 kalimba = 44,
556 shave = 45,
557 lanai = 46,
558 wasm32 = 47,
559 wasm64 = 48,
560 renderscript32 = 49,
561 renderscript64 = 50,
562 ve = 51,
563};
564
565pub const ParseCommandLineOptions = ZigLLVMParseCommandLineOptions;
566extern fn ZigLLVMParseCommandLineOptions(argc: usize, argv: [*]const [*:0]const u8) void;
567
568pub const WriteImportLibrary = ZigLLVMWriteImportLibrary;
569extern fn ZigLLVMWriteImportLibrary(
570 def_path: [*:0]const u8,
571 arch: ArchType,
572 output_lib_path: [*c]const u8,
573 kill_at: bool,
574) bool;
src/main.zig+3-3
...@@ -1703,7 +1703,7 @@ fn buildOutputType(...@@ -1703,7 +1703,7 @@ fn buildOutputType(
1703 if (build_options.have_llvm and emit_asm != .no) {1703 if (build_options.have_llvm and emit_asm != .no) {
1704 // LLVM has no way to set this non-globally.1704 // LLVM has no way to set this non-globally.
1705 const argv = [_][*:0]const u8{ "zig (LLVM option parsing)", "--x86-asm-syntax=intel" };1705 const argv = [_][*:0]const u8{ "zig (LLVM option parsing)", "--x86-asm-syntax=intel" };
1706 @import("llvm_bindings.zig").ParseCommandLineOptions(argv.len, &argv);1706 @import("codegen/llvm/bindings.zig").ParseCommandLineOptions(argv.len, &argv);
1707 }1707 }
17081708
1709 gimmeMoreOfThoseSweetSweetFileDescriptors();1709 gimmeMoreOfThoseSweetSweetFileDescriptors();
...@@ -2890,7 +2890,7 @@ pub fn punt_to_lld(arena: *Allocator, args: []const []const u8) error{OutOfMemor...@@ -2890,7 +2890,7 @@ pub fn punt_to_lld(arena: *Allocator, args: []const []const u8) error{OutOfMemor
2890 argv[i] = try arena.dupeZ(u8, arg); // TODO If there was an argsAllocZ we could avoid this allocation.2890 argv[i] = try arena.dupeZ(u8, arg); // TODO If there was an argsAllocZ we could avoid this allocation.
2891 }2891 }
2892 const exit_code = rc: {2892 const exit_code = rc: {
2893 const llvm = @import("llvm_bindings.zig");2893 const llvm = @import("codegen/llvm/bindings.zig");
2894 const argc = @intCast(c_int, argv.len);2894 const argc = @intCast(c_int, argv.len);
2895 if (mem.eql(u8, args[1], "ld.lld")) {2895 if (mem.eql(u8, args[1], "ld.lld")) {
2896 break :rc llvm.LinkELF(argc, argv.ptr, true);2896 break :rc llvm.LinkELF(argc, argv.ptr, true);
...@@ -3275,7 +3275,7 @@ fn detectNativeTargetInfo(gpa: *Allocator, cross_target: std.zig.CrossTarget) !s...@@ -3275,7 +3275,7 @@ fn detectNativeTargetInfo(gpa: *Allocator, cross_target: std.zig.CrossTarget) !s
3275 if (!build_options.have_llvm)3275 if (!build_options.have_llvm)
3276 fatal("CPU features detection is not yet available for {s} without LLVM extensions", .{@tagName(arch)});3276 fatal("CPU features detection is not yet available for {s} without LLVM extensions", .{@tagName(arch)});
32773277
3278 const llvm = @import("llvm_bindings.zig");3278 const llvm = @import("codegen/llvm/bindings.zig");
3279 const llvm_cpu_name = llvm.GetHostCPUName();3279 const llvm_cpu_name = llvm.GetHostCPUName();
3280 const llvm_cpu_features = llvm.GetNativeFeatures();3280 const llvm_cpu_features = llvm.GetNativeFeatures();
3281 info.target.cpu = try detectNativeCpuWithLLVM(arch, llvm_cpu_name, llvm_cpu_features);3281 info.target.cpu = try detectNativeCpuWithLLVM(arch, llvm_cpu_name, llvm_cpu_features);
src/mingw.zig+1-1
...@@ -405,7 +405,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {...@@ -405,7 +405,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
405 });405 });
406 errdefer comp.gpa.free(lib_final_path);406 errdefer comp.gpa.free(lib_final_path);
407407
408 const llvm = @import("llvm_bindings.zig");408 const llvm = @import("codegen/llvm/bindings.zig");
409 const arch_type = @import("target.zig").archToLLVM(target.cpu.arch);409 const arch_type = @import("target.zig").archToLLVM(target.cpu.arch);
410 const def_final_path_z = try arena.dupeZ(u8, def_final_path);410 const def_final_path_z = try arena.dupeZ(u8, def_final_path);
411 const lib_final_path_z = try arena.dupeZ(u8, lib_final_path);411 const lib_final_path_z = try arena.dupeZ(u8, lib_final_path);
src/target.zig+1-1
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const std = @import("std");1const std = @import("std");
2const llvm = @import("llvm_bindings.zig");2const llvm = @import("codegen/llvm/bindings.zig");
33
4pub const ArchOsAbi = struct {4pub const ArchOsAbi = struct {
5 arch: std.Target.Cpu.Arch,5 arch: std.Target.Cpu.Arch,
test/stage2/llvm.zig created+43
...@@ -0,0 +1,43 @@
1const std = @import("std");
2const TestContext = @import("../../src/test.zig").TestContext;
3const build_options = @import("build_options");
4
5// These tests should work with all platforms, but we're using linux_x64 for
6// now for consistency. Will be expanded eventually.
7const linux_x64 = std.zig.CrossTarget{
8 .cpu_arch = .x86_64,
9 .os_tag = .linux,
10};
11
12pub fn addCases(ctx: *TestContext) !void {
13 {
14 var case = ctx.exeUsingLlvmBackend("simple addition and subtraction", linux_x64);
15
16 case.addCompareOutput(
17 \\fn add(a: i32, b: i32) i32 {
18 \\ return a + b;
19 \\}
20 \\
21 \\export fn main() c_int {
22 \\ var a: i32 = -5;
23 \\ const x = add(a, 7);
24 \\ var y = add(2, 0);
25 \\ y -= x;
26 \\ return y;
27 \\}
28 , "");
29 }
30
31 {
32 var case = ctx.exeUsingLlvmBackend("hello world", linux_x64);
33
34 case.addCompareOutput(
35 \\extern fn puts(s: [*:0]const u8) c_int;
36 \\
37 \\export fn main() c_int {
38 \\ _ = puts("hello world!");
39 \\ return 0;
40 \\}
41 , "hello world!" ++ std.cstr.line_sep);
42 }
43}
test/stage2/llvm_backend.zig deleted-43
...@@ -1,43 +0,0 @@
1const std = @import("std");
2const TestContext = @import("../../src/test.zig").TestContext;
3const build_options = @import("build_options");
4
5// These tests should work with all platforms, but we're using linux_x64 for
6// now for consistency. Will be expanded eventually.
7const linux_x64 = std.zig.CrossTarget{
8 .cpu_arch = .x86_64,
9 .os_tag = .linux,
10};
11
12pub fn addCases(ctx: *TestContext) !void {
13 {
14 var case = ctx.exeUsingLlvmBackend("simple addition and subtraction", linux_x64);
15
16 case.addCompareOutput(
17 \\fn add(a: i32, b: i32) i32 {
18 \\ return a + b;
19 \\}
20 \\
21 \\export fn main() c_int {
22 \\ var a: i32 = -5;
23 \\ const x = add(a, 7);
24 \\ var y = add(2, 0);
25 \\ y -= x;
26 \\ return y;
27 \\}
28 , "");
29 }
30
31 {
32 var case = ctx.exeUsingLlvmBackend("hello world", linux_x64);
33
34 case.addCompareOutput(
35 \\extern fn puts(s: [*:0]const u8) c_int;
36 \\
37 \\export fn main() c_int {
38 \\ _ = puts("hello world!");
39 \\ return 0;
40 \\}
41 , "hello world!" ++ std.cstr.line_sep);
42 }
43}
test/stage2/test.zig+1-1
...@@ -31,7 +31,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -31,7 +31,7 @@ pub fn addCases(ctx: *TestContext) !void {
31 try @import("spu-ii.zig").addCases(ctx);31 try @import("spu-ii.zig").addCases(ctx);
32 try @import("arm.zig").addCases(ctx);32 try @import("arm.zig").addCases(ctx);
33 try @import("aarch64.zig").addCases(ctx);33 try @import("aarch64.zig").addCases(ctx);
34 try @import("llvm_backend.zig").addCases(ctx);34 try @import("llvm.zig").addCases(ctx);
3535
36 {36 {
37 var case = ctx.exe("hello world with updates", linux_x64);37 var case = ctx.exe("hello world with updates", linux_x64);