diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2022-02-19 02:57:48 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-02-19 02:57:48 -0500 |
| commit | 2e1c16d64979c15604b90128fbd63d26ab4b796d (patch) | |
| tree | a6cea3b541c8902a8a6b63a17e2b4a2b076a1b08 /src/codegen/llvm.zig | |
| parent | 09d93ec845f2f1adaefc512fccaeaa0ea8beed61 (diff) | |
| parent | 4e1e5ab6221b72ef2be9f1fb40c2e6d1235718fe (diff) | |
| download | zig-2e1c16d64979c15604b90128fbd63d26ab4b796d.tar.gz zig-2e1c16d64979c15604b90128fbd63d26ab4b796d.zip | |
Merge pull request #10924 from ziglang/air-independence-day
AIR independence day
Diffstat (limited to 'src/codegen/llvm.zig')
| -rw-r--r-- | src/codegen/llvm.zig | 101 |
1 files changed, 51 insertions, 50 deletions
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 4fdd462dba..ed57562e4c 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -2,24 +2,21 @@ const std = @import("std"); const builtin = @import("builtin"); const assert = std.debug.assert; const Allocator = std.mem.Allocator; -const Compilation = @import("../Compilation.zig"); -const llvm = @import("llvm/bindings.zig"); -const link = @import("../link.zig"); const log = std.log.scoped(.codegen); const math = std.math; const native_endian = builtin.cpu.arch.endian(); +const llvm = @import("llvm/bindings.zig"); +const link = @import("../link.zig"); +const Compilation = @import("../Compilation.zig"); const build_options = @import("build_options"); const Module = @import("../Module.zig"); const TypedValue = @import("../TypedValue.zig"); -const Zir = @import("../Zir.zig"); const Air = @import("../Air.zig"); const Liveness = @import("../Liveness.zig"); const target_util = @import("../target.zig"); - const Value = @import("../value.zig").Value; const Type = @import("../type.zig").Type; - const LazySrcLoc = Module.LazySrcLoc; const Error = error{ OutOfMemory, CodegenFail }; @@ -2895,33 +2892,21 @@ pub const FuncGen = struct { // as stage1. const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; - const air_asm = self.air.extraData(Air.Asm, ty_pl.payload); - const zir = self.dg.decl.getFileScope().zir; - const extended = zir.instructions.items(.data)[air_asm.data.zir_index].extended; - const is_volatile = @truncate(u1, extended.small >> 15) != 0; - if (!is_volatile and self.liveness.isUnused(inst)) { - return null; - } - const outputs_len = @truncate(u5, extended.small); - if (outputs_len > 1) { + const extra = self.air.extraData(Air.Asm, ty_pl.payload); + const is_volatile = @truncate(u1, extra.data.flags >> 31) != 0; + const clobbers_len = @truncate(u31, extra.data.flags); + var extra_i: usize = extra.end; + + if (!is_volatile and self.liveness.isUnused(inst)) return null; + + const outputs = @bitCast([]const Air.Inst.Ref, self.air.extra[extra_i..][0..extra.data.outputs_len]); + extra_i += outputs.len; + const inputs = @bitCast([]const Air.Inst.Ref, self.air.extra[extra_i..][0..extra.data.inputs_len]); + extra_i += inputs.len; + + if (outputs.len > 1) { return self.todo("implement llvm codegen for asm with more than 1 output", .{}); } - const args_len = @truncate(u5, extended.small >> 5); - const clobbers_len = @truncate(u5, extended.small >> 10); - const zir_extra = zir.extraData(Zir.Inst.Asm, extended.operand); - const asm_source = zir.nullTerminatedString(zir_extra.data.asm_source); - const args = @bitCast([]const Air.Inst.Ref, self.air.extra[air_asm.end..][0..args_len]); - - var extra_i: usize = zir_extra.end; - const output_constraint: ?[]const u8 = out: { - var i: usize = 0; - while (i < outputs_len) : (i += 1) { - const output = zir.extraData(Zir.Inst.Asm.Output, extra_i); - extra_i = output.end; - break :out zir.nullTerminatedString(output.data.constraint); - } - break :out null; - }; var llvm_constraints: std.ArrayListUnmanaged(u8) = .{}; defer llvm_constraints.deinit(self.gpa); @@ -2930,14 +2915,21 @@ pub const FuncGen = struct { defer arena_allocator.deinit(); const arena = arena_allocator.allocator(); - const llvm_params_len = args.len; + const llvm_params_len = inputs.len; const llvm_param_types = try arena.alloc(*const llvm.Type, llvm_params_len); const llvm_param_values = try arena.alloc(*const llvm.Value, llvm_params_len); - var llvm_param_i: usize = 0; var total_i: usize = 0; - if (output_constraint) |constraint| { + for (outputs) |output| { + if (output != .none) { + return self.todo("implement inline asm with non-returned output", .{}); + } + const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0); + // This equation accounts for the fact that even if we have exactly 4 bytes + // for the string, we still use the next u32 for the null terminator. + extra_i += constraint.len / 4 + 1; + try llvm_constraints.ensureUnusedCapacity(self.gpa, constraint.len + 1); if (total_i != 0) { llvm_constraints.appendAssumeCapacity(','); @@ -2948,11 +2940,13 @@ pub const FuncGen = struct { total_i += 1; } - for (args) |arg| { - const input = zir.extraData(Zir.Inst.Asm.Input, extra_i); - extra_i = input.end; - const constraint = zir.nullTerminatedString(input.data.constraint); - const arg_llvm_value = try self.resolveInst(arg); + for (inputs) |input| { + const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0); + // This equation accounts for the fact that even if we have exactly 4 bytes + // for the string, we still use the next u32 for the null terminator. + extra_i += constraint.len / 4 + 1; + + const arg_llvm_value = try self.resolveInst(input); llvm_param_values[llvm_param_i] = arg_llvm_value; llvm_param_types[llvm_param_i] = arg_llvm_value.typeOf(); @@ -2967,19 +2961,26 @@ pub const FuncGen = struct { total_i += 1; } - const clobbers = zir.extra[extra_i..][0..clobbers_len]; - for (clobbers) |clobber_index| { - const clobber = zir.nullTerminatedString(clobber_index); - try llvm_constraints.ensureUnusedCapacity(self.gpa, clobber.len + 4); - if (total_i != 0) { - llvm_constraints.appendAssumeCapacity(','); - } - llvm_constraints.appendSliceAssumeCapacity("~{"); - llvm_constraints.appendSliceAssumeCapacity(clobber); - llvm_constraints.appendSliceAssumeCapacity("}"); + { + var clobber_i: u32 = 0; + while (clobber_i < clobbers_len) : (clobber_i += 1) { + const clobber = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0); + // This equation accounts for the fact that even if we have exactly 4 bytes + // for the string, we still use the next u32 for the null terminator. + extra_i += clobber.len / 4 + 1; + + try llvm_constraints.ensureUnusedCapacity(self.gpa, clobber.len + 4); + if (total_i != 0) { + llvm_constraints.appendAssumeCapacity(','); + } + llvm_constraints.appendSliceAssumeCapacity("~{"); + llvm_constraints.appendSliceAssumeCapacity(clobber); + llvm_constraints.appendSliceAssumeCapacity("}"); - total_i += 1; + total_i += 1; + } } + const asm_source = std.mem.sliceAsBytes(self.air.extra[extra_i..])[0..extra.data.source_len]; const ret_ty = self.air.typeOfIndex(inst); const ret_llvm_ty = try self.dg.llvmType(ret_ty); |
