authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-01-06 16:06:32-08:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-01-06 16:06:32-08:00
log76870a2265410dc8790b9383cf39610f4b33e3ee
treef7612fcf903185880c5928d6b2ef16e34e8ac484
parent148c887ace66ea829f7a7c45a2925532e7675e4f
parentb1cfa923bee5210fd78c7508d1af92dde3361c8c
signature Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #7700 from FireFox317/more-stage2-stuff-llvm

stage2: improvements to LLVM backend

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

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