| author | |
| committer | |
| log | 76870a2265410dc8790b9383cf39610f4b33e3ee |
| tree | f7612fcf903185880c5928d6b2ef16e34e8ac484 |
| parent | 148c887ace66ea829f7a7c45a2925532e7675e4f |
| parent | b1cfa923bee5210fd78c7508d1af92dde3361c8c |
| signature |
stage2: improvements to LLVM backend15 files changed, 1348 insertions(+), 1202 deletions(-)
CMakeLists.txt+2-2| ... | ... | @@ -541,6 +541,8 @@ set(ZIG_STAGE2_SOURCES |
| 541 | 541 | "${CMAKE_SOURCE_DIR}/src/codegen/aarch64.zig" |
| 542 | 542 | "${CMAKE_SOURCE_DIR}/src/codegen/arm.zig" |
| 543 | 543 | "${CMAKE_SOURCE_DIR}/src/codegen/c.zig" |
| 544 | "${CMAKE_SOURCE_DIR}/src/codegen/llvm.zig" | |
| 545 | "${CMAKE_SOURCE_DIR}/src/codegen/llvm/bindings.zig" | |
| 544 | 546 | "${CMAKE_SOURCE_DIR}/src/codegen/riscv64.zig" |
| 545 | 547 | "${CMAKE_SOURCE_DIR}/src/codegen/spu-mk2.zig" |
| 546 | 548 | "${CMAKE_SOURCE_DIR}/src/codegen/wasm.zig" |
| ... | ... | @@ -562,8 +564,6 @@ set(ZIG_STAGE2_SOURCES |
| 562 | 564 | "${CMAKE_SOURCE_DIR}/src/link/C/zig.h" |
| 563 | 565 | "${CMAKE_SOURCE_DIR}/src/link/msdos-stub.bin" |
| 564 | 566 | "${CMAKE_SOURCE_DIR}/src/liveness.zig" |
| 565 | "${CMAKE_SOURCE_DIR}/src/llvm_backend.zig" | |
| 566 | "${CMAKE_SOURCE_DIR}/src/llvm_bindings.zig" | |
| 567 | 567 | "${CMAKE_SOURCE_DIR}/src/main.zig" |
| 568 | 568 | "${CMAKE_SOURCE_DIR}/src/mingw.zig" |
| 569 | 569 | "${CMAKE_SOURCE_DIR}/src/musl.zig" |
src/Compilation.zig+1-1| ... | ... | @@ -2150,7 +2150,7 @@ pub fn addCCArgs( |
| 2150 | 2150 | try argv.append("-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS"); |
| 2151 | 2151 | } |
| 2152 | 2152 | |
| 2153 | const llvm_triple = try @import("llvm_backend.zig").targetTriple(arena, target); | |
| 2153 | const llvm_triple = try @import("codegen/llvm.zig").targetTriple(arena, target); | |
| 2154 | 2154 | try argv.appendSlice(&[_][]const u8{ "-target", llvm_triple }); |
| 2155 | 2155 | |
| 2156 | 2156 | switch (ext) { |
src/codegen/llvm.zig created+722| ... | ... | @@ -0,0 +1,722 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assert = std.debug.assert; | |
| 3 | const Allocator = std.mem.Allocator; | |
| 4 | const Compilation = @import("../Compilation.zig"); | |
| 5 | const llvm = @import("llvm/bindings.zig"); | |
| 6 | const link = @import("../link.zig"); | |
| 7 | const log = std.log.scoped(.codegen); | |
| 8 | ||
| 9 | const Module = @import("../Module.zig"); | |
| 10 | const TypedValue = @import("../TypedValue.zig"); | |
| 11 | const ir = @import("../ir.zig"); | |
| 12 | const Inst = ir.Inst; | |
| 13 | ||
| 14 | const Value = @import("../value.zig").Value; | |
| 15 | const Type = @import("../type.zig").Type; | |
| 16 | ||
| 17 | pub 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 | ||
| 140 | pub 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 | ||
| 4 | const LLVMBool = bool; | |
| 5 | pub const AttributeIndex = c_uint; | |
| 6 | ||
| 7 | /// Make sure to use the *InContext functions instead of the global ones. | |
| 8 | pub 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 | ||
| 34 | pub 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 | ||
| 45 | pub 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 | ||
| 71 | pub 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 | ||
| 100 | pub const lookupIntrinsicID = LLVMLookupIntrinsicID; | |
| 101 | extern fn LLVMLookupIntrinsicID(Name: [*]const u8, NameLen: usize) c_uint; | |
| 102 | ||
| 103 | pub const disposeMessage = LLVMDisposeMessage; | |
| 104 | extern fn LLVMDisposeMessage(Message: [*:0]const u8) void; | |
| 105 | ||
| 106 | pub const VerifierFailureAction = extern enum { | |
| 107 | AbortProcess, | |
| 108 | PrintMessage, | |
| 109 | ReturnStatus, | |
| 110 | }; | |
| 111 | ||
| 112 | pub const constNeg = LLVMConstNeg; | |
| 113 | extern fn LLVMConstNeg(ConstantVal: *const Value) *const Value; | |
| 114 | ||
| 115 | pub const setInitializer = LLVMSetInitializer; | |
| 116 | extern fn LLVMSetInitializer(GlobalVar: *const Value, ConstantVal: *const Value) void; | |
| 117 | ||
| 118 | pub const getParam = LLVMGetParam; | |
| 119 | extern fn LLVMGetParam(Fn: *const Value, Index: c_uint) *const Value; | |
| 120 | ||
| 121 | pub const getEnumAttributeKindForName = LLVMGetEnumAttributeKindForName; | |
| 122 | extern fn LLVMGetEnumAttributeKindForName(Name: [*]const u8, SLen: usize) c_uint; | |
| 123 | ||
| 124 | pub const Attribute = opaque {}; | |
| 125 | ||
| 126 | pub 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 | ||
| 188 | pub 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 | ||
| 196 | pub 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 | ||
| 215 | pub const CodeMode = extern enum { | |
| 216 | Default, | |
| 217 | JITDefault, | |
| 218 | Tiny, | |
| 219 | Small, | |
| 220 | Kernel, | |
| 221 | Medium, | |
| 222 | Large, | |
| 223 | }; | |
| 224 | ||
| 225 | pub const CodeGenOptLevel = extern enum { | |
| 226 | None, | |
| 227 | Less, | |
| 228 | Default, | |
| 229 | Aggressive, | |
| 230 | }; | |
| 231 | ||
| 232 | pub const RelocMode = extern enum { | |
| 233 | Default, | |
| 234 | Static, | |
| 235 | PIC, | |
| 236 | DynamicNoPic, | |
| 237 | ROPI, | |
| 238 | RWPI, | |
| 239 | ROPI_RWPI, | |
| 240 | }; | |
| 241 | ||
| 242 | pub const CodeGenFileType = extern enum { | |
| 243 | AssemblyFile, | |
| 244 | ObjectFile, | |
| 245 | }; | |
| 246 | ||
| 247 | pub 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 | ||
| 252 | extern fn LLVMInitializeAArch64TargetInfo() void; | |
| 253 | extern fn LLVMInitializeAMDGPUTargetInfo() void; | |
| 254 | extern fn LLVMInitializeARMTargetInfo() void; | |
| 255 | extern fn LLVMInitializeAVRTargetInfo() void; | |
| 256 | extern fn LLVMInitializeBPFTargetInfo() void; | |
| 257 | extern fn LLVMInitializeHexagonTargetInfo() void; | |
| 258 | extern fn LLVMInitializeLanaiTargetInfo() void; | |
| 259 | extern fn LLVMInitializeMipsTargetInfo() void; | |
| 260 | extern fn LLVMInitializeMSP430TargetInfo() void; | |
| 261 | extern fn LLVMInitializeNVPTXTargetInfo() void; | |
| 262 | extern fn LLVMInitializePowerPCTargetInfo() void; | |
| 263 | extern fn LLVMInitializeRISCVTargetInfo() void; | |
| 264 | extern fn LLVMInitializeSparcTargetInfo() void; | |
| 265 | extern fn LLVMInitializeSystemZTargetInfo() void; | |
| 266 | extern fn LLVMInitializeWebAssemblyTargetInfo() void; | |
| 267 | extern fn LLVMInitializeX86TargetInfo() void; | |
| 268 | extern fn LLVMInitializeXCoreTargetInfo() void; | |
| 269 | extern fn LLVMInitializeAArch64Target() void; | |
| 270 | extern fn LLVMInitializeAMDGPUTarget() void; | |
| 271 | extern fn LLVMInitializeARMTarget() void; | |
| 272 | extern fn LLVMInitializeAVRTarget() void; | |
| 273 | extern fn LLVMInitializeBPFTarget() void; | |
| 274 | extern fn LLVMInitializeHexagonTarget() void; | |
| 275 | extern fn LLVMInitializeLanaiTarget() void; | |
| 276 | extern fn LLVMInitializeMipsTarget() void; | |
| 277 | extern fn LLVMInitializeMSP430Target() void; | |
| 278 | extern fn LLVMInitializeNVPTXTarget() void; | |
| 279 | extern fn LLVMInitializePowerPCTarget() void; | |
| 280 | extern fn LLVMInitializeRISCVTarget() void; | |
| 281 | extern fn LLVMInitializeSparcTarget() void; | |
| 282 | extern fn LLVMInitializeSystemZTarget() void; | |
| 283 | extern fn LLVMInitializeWebAssemblyTarget() void; | |
| 284 | extern fn LLVMInitializeX86Target() void; | |
| 285 | extern fn LLVMInitializeXCoreTarget() void; | |
| 286 | extern fn LLVMInitializeAArch64TargetMC() void; | |
| 287 | extern fn LLVMInitializeAMDGPUTargetMC() void; | |
| 288 | extern fn LLVMInitializeARMTargetMC() void; | |
| 289 | extern fn LLVMInitializeAVRTargetMC() void; | |
| 290 | extern fn LLVMInitializeBPFTargetMC() void; | |
| 291 | extern fn LLVMInitializeHexagonTargetMC() void; | |
| 292 | extern fn LLVMInitializeLanaiTargetMC() void; | |
| 293 | extern fn LLVMInitializeMipsTargetMC() void; | |
| 294 | extern fn LLVMInitializeMSP430TargetMC() void; | |
| 295 | extern fn LLVMInitializeNVPTXTargetMC() void; | |
| 296 | extern fn LLVMInitializePowerPCTargetMC() void; | |
| 297 | extern fn LLVMInitializeRISCVTargetMC() void; | |
| 298 | extern fn LLVMInitializeSparcTargetMC() void; | |
| 299 | extern fn LLVMInitializeSystemZTargetMC() void; | |
| 300 | extern fn LLVMInitializeWebAssemblyTargetMC() void; | |
| 301 | extern fn LLVMInitializeX86TargetMC() void; | |
| 302 | extern fn LLVMInitializeXCoreTargetMC() void; | |
| 303 | extern fn LLVMInitializeAArch64AsmPrinter() void; | |
| 304 | extern fn LLVMInitializeAMDGPUAsmPrinter() void; | |
| 305 | extern fn LLVMInitializeARMAsmPrinter() void; | |
| 306 | extern fn LLVMInitializeAVRAsmPrinter() void; | |
| 307 | extern fn LLVMInitializeBPFAsmPrinter() void; | |
| 308 | extern fn LLVMInitializeHexagonAsmPrinter() void; | |
| 309 | extern fn LLVMInitializeLanaiAsmPrinter() void; | |
| 310 | extern fn LLVMInitializeMipsAsmPrinter() void; | |
| 311 | extern fn LLVMInitializeMSP430AsmPrinter() void; | |
| 312 | extern fn LLVMInitializeNVPTXAsmPrinter() void; | |
| 313 | extern fn LLVMInitializePowerPCAsmPrinter() void; | |
| 314 | extern fn LLVMInitializeRISCVAsmPrinter() void; | |
| 315 | extern fn LLVMInitializeSparcAsmPrinter() void; | |
| 316 | extern fn LLVMInitializeSystemZAsmPrinter() void; | |
| 317 | extern fn LLVMInitializeWebAssemblyAsmPrinter() void; | |
| 318 | extern fn LLVMInitializeX86AsmPrinter() void; | |
| 319 | extern fn LLVMInitializeXCoreAsmPrinter() void; | |
| 320 | extern fn LLVMInitializeAArch64AsmParser() void; | |
| 321 | extern fn LLVMInitializeAMDGPUAsmParser() void; | |
| 322 | extern fn LLVMInitializeARMAsmParser() void; | |
| 323 | extern fn LLVMInitializeAVRAsmParser() void; | |
| 324 | extern fn LLVMInitializeBPFAsmParser() void; | |
| 325 | extern fn LLVMInitializeHexagonAsmParser() void; | |
| 326 | extern fn LLVMInitializeLanaiAsmParser() void; | |
| 327 | extern fn LLVMInitializeMipsAsmParser() void; | |
| 328 | extern fn LLVMInitializeMSP430AsmParser() void; | |
| 329 | extern fn LLVMInitializePowerPCAsmParser() void; | |
| 330 | extern fn LLVMInitializeRISCVAsmParser() void; | |
| 331 | extern fn LLVMInitializeSparcAsmParser() void; | |
| 332 | extern fn LLVMInitializeSystemZAsmParser() void; | |
| 333 | extern fn LLVMInitializeWebAssemblyAsmParser() void; | |
| 334 | extern fn LLVMInitializeX86AsmParser() void; | |
| 335 | ||
| 336 | pub const initializeAllTargetInfos = LLVMInitializeAllTargetInfos; | |
| 337 | fn 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 | } | |
| 356 | pub const initializeAllTargets = LLVMInitializeAllTargets; | |
| 357 | fn 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 | } | |
| 376 | pub const initializeAllTargetMCs = LLVMInitializeAllTargetMCs; | |
| 377 | fn 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 | } | |
| 396 | pub const initializeAllAsmPrinters = LLVMInitializeAllAsmPrinters; | |
| 397 | fn 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 | } | |
| 416 | pub const initializeAllAsmParsers = LLVMInitializeAllAsmParsers; | |
| 417 | fn 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 | ||
| 435 | extern fn ZigLLDLinkCOFF(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int; | |
| 436 | extern fn ZigLLDLinkELF(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int; | |
| 437 | extern fn ZigLLDLinkMachO(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int; | |
| 438 | extern fn ZigLLDLinkWasm(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int; | |
| 439 | ||
| 440 | pub const LinkCOFF = ZigLLDLinkCOFF; | |
| 441 | pub const LinkELF = ZigLLDLinkELF; | |
| 442 | pub const LinkMachO = ZigLLDLinkMachO; | |
| 443 | pub const LinkWasm = ZigLLDLinkWasm; | |
| 444 | ||
| 445 | pub const ObjectFormatType = extern enum(c_int) { | |
| 446 | Unknown, | |
| 447 | COFF, | |
| 448 | ELF, | |
| 449 | MachO, | |
| 450 | Wasm, | |
| 451 | XCOFF, | |
| 452 | }; | |
| 453 | ||
| 454 | pub const GetHostCPUName = LLVMGetHostCPUName; | |
| 455 | extern fn LLVMGetHostCPUName() ?[*:0]u8; | |
| 456 | ||
| 457 | pub const GetNativeFeatures = ZigLLVMGetNativeFeatures; | |
| 458 | extern fn ZigLLVMGetNativeFeatures() ?[*:0]u8; | |
| 459 | ||
| 460 | pub const WriteArchive = ZigLLVMWriteArchive; | |
| 461 | extern 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 | ||
| 468 | pub 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 | ||
| 507 | pub 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 | ||
| 562 | pub const ParseCommandLineOptions = ZigLLVMParseCommandLineOptions; | |
| 563 | extern fn ZigLLVMParseCommandLineOptions(argc: usize, argv: [*]const [*:0]const u8) void; | |
| 564 | ||
| 565 | pub const WriteImportLibrary = ZigLLVMWriteImportLibrary; | |
| 566 | extern 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 { |
| 570 | 570 | std.debug.print("\n", .{}); |
| 571 | 571 | } |
| 572 | 572 | |
| 573 | const llvm = @import("llvm_bindings.zig"); | |
| 573 | const llvm = @import("codegen/llvm/bindings.zig"); | |
| 574 | 574 | const os_type = @import("target.zig").osToLLVM(base.options.target.os.tag); |
| 575 | 575 | const bad = llvm.WriteArchive(full_out_path_z, object_files.items.ptr, object_files.items.len, os_type); |
| 576 | 576 | if (bad) return error.UnableToWriteArchive; |
src/link/Coff.zig+1-1| ... | ... | @@ -16,7 +16,7 @@ const link = @import("../link.zig"); |
| 16 | 16 | const build_options = @import("build_options"); |
| 17 | 17 | const Cache = @import("../Cache.zig"); |
| 18 | 18 | const mingw = @import("../mingw.zig"); |
| 19 | const llvm_backend = @import("../llvm_backend.zig"); | |
| 19 | const llvm_backend = @import("../codegen/llvm.zig"); | |
| 20 | 20 | |
| 21 | 21 | const allocation_padding = 4 / 3; |
| 22 | 22 | const minimum_text_block_size = 64 * allocation_padding; |
src/link/Elf.zig+1-1| ... | ... | @@ -24,7 +24,7 @@ const build_options = @import("build_options"); |
| 24 | 24 | const target_util = @import("../target.zig"); |
| 25 | 25 | const glibc = @import("../glibc.zig"); |
| 26 | 26 | const Cache = @import("../Cache.zig"); |
| 27 | const llvm_backend = @import("../llvm_backend.zig"); | |
| 27 | const llvm_backend = @import("../codegen/llvm.zig"); | |
| 28 | 28 | |
| 29 | 29 | const default_entry_addr = 0x8000000; |
| 30 | 30 |
src/llvm_backend.zig deleted-605| ... | ... | @@ -1,605 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assert = std.debug.assert; | |
| 3 | const Allocator = std.mem.Allocator; | |
| 4 | const Compilation = @import("Compilation.zig"); | |
| 5 | const llvm = @import("llvm_bindings.zig"); | |
| 6 | const link = @import("link.zig"); | |
| 7 | ||
| 8 | const Module = @import("Module.zig"); | |
| 9 | const TypedValue = @import("TypedValue.zig"); | |
| 10 | const ir = @import("ir.zig"); | |
| 11 | const Inst = ir.Inst; | |
| 12 | ||
| 13 | const Value = @import("value.zig").Value; | |
| 14 | const Type = @import("type.zig").Type; | |
| 15 | ||
| 16 | pub 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 | ||
| 139 | pub 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 | ||
| 4 | const std = @import("std"); | |
| 5 | const assert = std.debug.assert; | |
| 6 | ||
| 7 | const LLVMBool = bool; | |
| 8 | pub const LLVMAttributeIndex = c_uint; | |
| 9 | ||
| 10 | pub 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 | ||
| 36 | pub 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 | ||
| 56 | pub 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 | ||
| 79 | pub const lookupIntrinsicID = LLVMLookupIntrinsicID; | |
| 80 | extern fn LLVMLookupIntrinsicID(Name: [*]const u8, NameLen: usize) c_uint; | |
| 81 | ||
| 82 | pub const disposeMessage = LLVMDisposeMessage; | |
| 83 | extern fn LLVMDisposeMessage(Message: [*:0]const u8) void; | |
| 84 | ||
| 85 | pub const VerifierFailureAction = extern enum { | |
| 86 | AbortProcess, | |
| 87 | PrintMessage, | |
| 88 | ReturnStatus, | |
| 89 | }; | |
| 90 | ||
| 91 | pub const constNeg = LLVMConstNeg; | |
| 92 | extern fn LLVMConstNeg(ConstantVal: *const ValueRef) *const ValueRef; | |
| 93 | ||
| 94 | pub const voidType = LLVMVoidType; | |
| 95 | extern fn LLVMVoidType() *const TypeRef; | |
| 96 | ||
| 97 | pub const getParam = LLVMGetParam; | |
| 98 | extern fn LLVMGetParam(Fn: *const ValueRef, Index: c_uint) *const ValueRef; | |
| 99 | ||
| 100 | pub const getEnumAttributeKindForName = LLVMGetEnumAttributeKindForName; | |
| 101 | extern fn LLVMGetEnumAttributeKindForName(Name: [*]const u8, SLen: usize) c_uint; | |
| 102 | ||
| 103 | pub const AttributeRef = opaque {}; | |
| 104 | ||
| 105 | pub 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 | ||
| 113 | pub const intType = LLVMIntType; | |
| 114 | extern fn LLVMIntType(NumBits: c_uint) *const TypeRef; | |
| 115 | ||
| 116 | pub 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 | ||
| 175 | pub const BasicBlockRef = opaque { | |
| 176 | pub const deleteBasicBlock = LLVMDeleteBasicBlock; | |
| 177 | extern fn LLVMDeleteBasicBlock(BB: *const BasicBlockRef) void; | |
| 178 | }; | |
| 179 | ||
| 180 | pub 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 | ||
| 199 | pub const CodeMode = extern enum { | |
| 200 | Default, | |
| 201 | JITDefault, | |
| 202 | Tiny, | |
| 203 | Small, | |
| 204 | Kernel, | |
| 205 | Medium, | |
| 206 | Large, | |
| 207 | }; | |
| 208 | ||
| 209 | pub const CodeGenOptLevel = extern enum { | |
| 210 | None, | |
| 211 | Less, | |
| 212 | Default, | |
| 213 | Aggressive, | |
| 214 | }; | |
| 215 | ||
| 216 | pub const RelocMode = extern enum { | |
| 217 | Default, | |
| 218 | Static, | |
| 219 | PIC, | |
| 220 | DynamicNoPic, | |
| 221 | ROPI, | |
| 222 | RWPI, | |
| 223 | ROPI_RWPI, | |
| 224 | }; | |
| 225 | ||
| 226 | pub const CodeGenFileType = extern enum { | |
| 227 | AssemblyFile, | |
| 228 | ObjectFile, | |
| 229 | }; | |
| 230 | ||
| 231 | pub 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 | ||
| 236 | extern fn LLVMInitializeAArch64TargetInfo() void; | |
| 237 | extern fn LLVMInitializeAMDGPUTargetInfo() void; | |
| 238 | extern fn LLVMInitializeARMTargetInfo() void; | |
| 239 | extern fn LLVMInitializeAVRTargetInfo() void; | |
| 240 | extern fn LLVMInitializeBPFTargetInfo() void; | |
| 241 | extern fn LLVMInitializeHexagonTargetInfo() void; | |
| 242 | extern fn LLVMInitializeLanaiTargetInfo() void; | |
| 243 | extern fn LLVMInitializeMipsTargetInfo() void; | |
| 244 | extern fn LLVMInitializeMSP430TargetInfo() void; | |
| 245 | extern fn LLVMInitializeNVPTXTargetInfo() void; | |
| 246 | extern fn LLVMInitializePowerPCTargetInfo() void; | |
| 247 | extern fn LLVMInitializeRISCVTargetInfo() void; | |
| 248 | extern fn LLVMInitializeSparcTargetInfo() void; | |
| 249 | extern fn LLVMInitializeSystemZTargetInfo() void; | |
| 250 | extern fn LLVMInitializeWebAssemblyTargetInfo() void; | |
| 251 | extern fn LLVMInitializeX86TargetInfo() void; | |
| 252 | extern fn LLVMInitializeXCoreTargetInfo() void; | |
| 253 | extern fn LLVMInitializeAArch64Target() void; | |
| 254 | extern fn LLVMInitializeAMDGPUTarget() void; | |
| 255 | extern fn LLVMInitializeARMTarget() void; | |
| 256 | extern fn LLVMInitializeAVRTarget() void; | |
| 257 | extern fn LLVMInitializeBPFTarget() void; | |
| 258 | extern fn LLVMInitializeHexagonTarget() void; | |
| 259 | extern fn LLVMInitializeLanaiTarget() void; | |
| 260 | extern fn LLVMInitializeMipsTarget() void; | |
| 261 | extern fn LLVMInitializeMSP430Target() void; | |
| 262 | extern fn LLVMInitializeNVPTXTarget() void; | |
| 263 | extern fn LLVMInitializePowerPCTarget() void; | |
| 264 | extern fn LLVMInitializeRISCVTarget() void; | |
| 265 | extern fn LLVMInitializeSparcTarget() void; | |
| 266 | extern fn LLVMInitializeSystemZTarget() void; | |
| 267 | extern fn LLVMInitializeWebAssemblyTarget() void; | |
| 268 | extern fn LLVMInitializeX86Target() void; | |
| 269 | extern fn LLVMInitializeXCoreTarget() void; | |
| 270 | extern fn LLVMInitializeAArch64TargetMC() void; | |
| 271 | extern fn LLVMInitializeAMDGPUTargetMC() void; | |
| 272 | extern fn LLVMInitializeARMTargetMC() void; | |
| 273 | extern fn LLVMInitializeAVRTargetMC() void; | |
| 274 | extern fn LLVMInitializeBPFTargetMC() void; | |
| 275 | extern fn LLVMInitializeHexagonTargetMC() void; | |
| 276 | extern fn LLVMInitializeLanaiTargetMC() void; | |
| 277 | extern fn LLVMInitializeMipsTargetMC() void; | |
| 278 | extern fn LLVMInitializeMSP430TargetMC() void; | |
| 279 | extern fn LLVMInitializeNVPTXTargetMC() void; | |
| 280 | extern fn LLVMInitializePowerPCTargetMC() void; | |
| 281 | extern fn LLVMInitializeRISCVTargetMC() void; | |
| 282 | extern fn LLVMInitializeSparcTargetMC() void; | |
| 283 | extern fn LLVMInitializeSystemZTargetMC() void; | |
| 284 | extern fn LLVMInitializeWebAssemblyTargetMC() void; | |
| 285 | extern fn LLVMInitializeX86TargetMC() void; | |
| 286 | extern fn LLVMInitializeXCoreTargetMC() void; | |
| 287 | extern fn LLVMInitializeAArch64AsmPrinter() void; | |
| 288 | extern fn LLVMInitializeAMDGPUAsmPrinter() void; | |
| 289 | extern fn LLVMInitializeARMAsmPrinter() void; | |
| 290 | extern fn LLVMInitializeAVRAsmPrinter() void; | |
| 291 | extern fn LLVMInitializeBPFAsmPrinter() void; | |
| 292 | extern fn LLVMInitializeHexagonAsmPrinter() void; | |
| 293 | extern fn LLVMInitializeLanaiAsmPrinter() void; | |
| 294 | extern fn LLVMInitializeMipsAsmPrinter() void; | |
| 295 | extern fn LLVMInitializeMSP430AsmPrinter() void; | |
| 296 | extern fn LLVMInitializeNVPTXAsmPrinter() void; | |
| 297 | extern fn LLVMInitializePowerPCAsmPrinter() void; | |
| 298 | extern fn LLVMInitializeRISCVAsmPrinter() void; | |
| 299 | extern fn LLVMInitializeSparcAsmPrinter() void; | |
| 300 | extern fn LLVMInitializeSystemZAsmPrinter() void; | |
| 301 | extern fn LLVMInitializeWebAssemblyAsmPrinter() void; | |
| 302 | extern fn LLVMInitializeX86AsmPrinter() void; | |
| 303 | extern fn LLVMInitializeXCoreAsmPrinter() void; | |
| 304 | extern fn LLVMInitializeAArch64AsmParser() void; | |
| 305 | extern fn LLVMInitializeAMDGPUAsmParser() void; | |
| 306 | extern fn LLVMInitializeARMAsmParser() void; | |
| 307 | extern fn LLVMInitializeAVRAsmParser() void; | |
| 308 | extern fn LLVMInitializeBPFAsmParser() void; | |
| 309 | extern fn LLVMInitializeHexagonAsmParser() void; | |
| 310 | extern fn LLVMInitializeLanaiAsmParser() void; | |
| 311 | extern fn LLVMInitializeMipsAsmParser() void; | |
| 312 | extern fn LLVMInitializeMSP430AsmParser() void; | |
| 313 | extern fn LLVMInitializePowerPCAsmParser() void; | |
| 314 | extern fn LLVMInitializeRISCVAsmParser() void; | |
| 315 | extern fn LLVMInitializeSparcAsmParser() void; | |
| 316 | extern fn LLVMInitializeSystemZAsmParser() void; | |
| 317 | extern fn LLVMInitializeWebAssemblyAsmParser() void; | |
| 318 | extern fn LLVMInitializeX86AsmParser() void; | |
| 319 | ||
| 320 | pub const initializeAllTargetInfos = LLVMInitializeAllTargetInfos; | |
| 321 | fn 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 | } | |
| 340 | pub const initializeAllTargets = LLVMInitializeAllTargets; | |
| 341 | fn 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 | } | |
| 360 | pub const initializeAllTargetMCs = LLVMInitializeAllTargetMCs; | |
| 361 | fn 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 | } | |
| 380 | pub const initializeAllAsmPrinters = LLVMInitializeAllAsmPrinters; | |
| 381 | fn 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 | } | |
| 400 | pub const initializeAllAsmParsers = LLVMInitializeAllAsmParsers; | |
| 401 | fn 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 | ||
| 419 | extern fn ZigLLDLinkCOFF(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int; | |
| 420 | extern fn ZigLLDLinkELF(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int; | |
| 421 | extern fn ZigLLDLinkMachO(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int; | |
| 422 | extern fn ZigLLDLinkWasm(argc: c_int, argv: [*:null]const ?[*:0]const u8, can_exit_early: bool) c_int; | |
| 423 | ||
| 424 | pub const LinkCOFF = ZigLLDLinkCOFF; | |
| 425 | pub const LinkELF = ZigLLDLinkELF; | |
| 426 | pub const LinkMachO = ZigLLDLinkMachO; | |
| 427 | pub const LinkWasm = ZigLLDLinkWasm; | |
| 428 | ||
| 429 | pub const ObjectFormatType = extern enum(c_int) { | |
| 430 | Unknown, | |
| 431 | COFF, | |
| 432 | ELF, | |
| 433 | MachO, | |
| 434 | Wasm, | |
| 435 | XCOFF, | |
| 436 | }; | |
| 437 | ||
| 438 | pub const GetHostCPUName = LLVMGetHostCPUName; | |
| 439 | extern fn LLVMGetHostCPUName() ?[*:0]u8; | |
| 440 | ||
| 441 | pub const GetNativeFeatures = ZigLLVMGetNativeFeatures; | |
| 442 | extern fn ZigLLVMGetNativeFeatures() ?[*:0]u8; | |
| 443 | ||
| 444 | pub const WriteArchive = ZigLLVMWriteArchive; | |
| 445 | extern 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 | ||
| 452 | pub 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 | ||
| 491 | pub 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 | ||
| 546 | pub const ParseCommandLineOptions = ZigLLVMParseCommandLineOptions; | |
| 547 | extern fn ZigLLVMParseCommandLineOptions(argc: usize, argv: [*]const [*:0]const u8) void; | |
| 548 | ||
| 549 | pub const WriteImportLibrary = ZigLLVMWriteImportLibrary; | |
| 550 | extern 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( |
| 1703 | 1703 | if (build_options.have_llvm and emit_asm != .no) { |
| 1704 | 1704 | // LLVM has no way to set this non-globally. |
| 1705 | 1705 | const argv = [_][*:0]const u8{ "zig (LLVM option parsing)", "--x86-asm-syntax=intel" }; |
| 1706 | @import("llvm_bindings.zig").ParseCommandLineOptions(argv.len, &argv); | |
| 1706 | @import("codegen/llvm/bindings.zig").ParseCommandLineOptions(argv.len, &argv); | |
| 1707 | 1707 | } |
| 1708 | 1708 | |
| 1709 | 1709 | gimmeMoreOfThoseSweetSweetFileDescriptors(); |
| ... | ... | @@ -2890,7 +2890,7 @@ pub fn punt_to_lld(arena: *Allocator, args: []const []const u8) error{OutOfMemor |
| 2890 | 2890 | argv[i] = try arena.dupeZ(u8, arg); // TODO If there was an argsAllocZ we could avoid this allocation. |
| 2891 | 2891 | } |
| 2892 | 2892 | const exit_code = rc: { |
| 2893 | const llvm = @import("llvm_bindings.zig"); | |
| 2893 | const llvm = @import("codegen/llvm/bindings.zig"); | |
| 2894 | 2894 | const argc = @intCast(c_int, argv.len); |
| 2895 | 2895 | if (mem.eql(u8, args[1], "ld.lld")) { |
| 2896 | 2896 | break :rc llvm.LinkELF(argc, argv.ptr, true); |
| ... | ... | @@ -3275,7 +3275,7 @@ fn detectNativeTargetInfo(gpa: *Allocator, cross_target: std.zig.CrossTarget) !s |
| 3275 | 3275 | if (!build_options.have_llvm) |
| 3276 | 3276 | fatal("CPU features detection is not yet available for {s} without LLVM extensions", .{@tagName(arch)}); |
| 3277 | 3277 | |
| 3278 | const llvm = @import("llvm_bindings.zig"); | |
| 3278 | const llvm = @import("codegen/llvm/bindings.zig"); | |
| 3279 | 3279 | const llvm_cpu_name = llvm.GetHostCPUName(); |
| 3280 | 3280 | const llvm_cpu_features = llvm.GetNativeFeatures(); |
| 3281 | 3281 | info.target.cpu = try detectNativeCpuWithLLVM(arch, llvm_cpu_name, llvm_cpu_features); |
src/mingw.zig+1-1| ... | ... | @@ -405,7 +405,7 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { |
| 405 | 405 | }); |
| 406 | 406 | errdefer comp.gpa.free(lib_final_path); |
| 407 | 407 | |
| 408 | const llvm = @import("llvm_bindings.zig"); | |
| 408 | const llvm = @import("codegen/llvm/bindings.zig"); | |
| 409 | 409 | const arch_type = @import("target.zig").archToLLVM(target.cpu.arch); |
| 410 | 410 | const def_final_path_z = try arena.dupeZ(u8, def_final_path); |
| 411 | 411 | const lib_final_path_z = try arena.dupeZ(u8, lib_final_path); |
src/target.zig+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | const llvm = @import("llvm_bindings.zig"); | |
| 2 | const llvm = @import("codegen/llvm/bindings.zig"); | |
| 3 | 3 | |
| 4 | 4 | pub const ArchOsAbi = struct { |
| 5 | 5 | arch: std.Target.Cpu.Arch, |
test/stage2/llvm.zig created+43| ... | ... | @@ -0,0 +1,43 @@ |
| 1 | const std = @import("std"); | |
| 2 | const TestContext = @import("../../src/test.zig").TestContext; | |
| 3 | const 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. | |
| 7 | const linux_x64 = std.zig.CrossTarget{ | |
| 8 | .cpu_arch = .x86_64, | |
| 9 | .os_tag = .linux, | |
| 10 | }; | |
| 11 | ||
| 12 | pub 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 @@ |
| 1 | const std = @import("std"); | |
| 2 | const TestContext = @import("../../src/test.zig").TestContext; | |
| 3 | const 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. | |
| 7 | const linux_x64 = std.zig.CrossTarget{ | |
| 8 | .cpu_arch = .x86_64, | |
| 9 | .os_tag = .linux, | |
| 10 | }; | |
| 11 | ||
| 12 | pub 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 { |
| 31 | 31 | try @import("spu-ii.zig").addCases(ctx); |
| 32 | 32 | try @import("arm.zig").addCases(ctx); |
| 33 | 33 | try @import("aarch64.zig").addCases(ctx); |
| 34 | try @import("llvm_backend.zig").addCases(ctx); | |
| 34 | try @import("llvm.zig").addCases(ctx); | |
| 35 | 35 | |
| 36 | 36 | { |
| 37 | 37 | var case = ctx.exe("hello world with updates", linux_x64); |