mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-10-28 10:45:48 +08:00
compiler: add -flegalize-all option
This option is intended for compiler development and testing. It forces all `Air.Legalize` passes to be enabled, so we can exhaustively test the functionality of legalization passes even before any backend enables them. The option is limited to the LLVM backend, because enabling legalizations often requires some level of backend support (e.g. support for the `legalize_compiler_rt_call` instruction tag), and it's usually fairly simple to support these in the LLVM backend *and* gets us a lot of test coverage (in particular, it lets us test on both big-endian and little-endian targets).
This commit is contained in:
5 files changed
+77
-2
No files matched your search
@@ -325,6 +325,23 @@ pub const Feature = enum {
|
||||
|
||||
pub const Features = std.enums.EnumSet(Feature);
|
||||
|
||||
/// The maximal set of `Features` which may be simultaneously enabled.
|
||||
pub const all_features: Features = .complement(.initMany(&.{
|
||||
// There are a few features that conflict with others, so we need to enable the more useful one.
|
||||
.scalarize_add_safe, // conflicts with `.expand_add_safe`
|
||||
.scalarize_sub_safe, // conflicts with `.expand_sub_safe`
|
||||
.scalarize_mul_safe, // conflicts with `.expand_mul_safe`
|
||||
.scalarize_int_cast_safe, // conflicts with `.expand_int_cast_safe`
|
||||
.scalarize_div_ceil, // conflicts with `.expand_div_ceil`
|
||||
.scalarize_div_ceil_optimized, // conflicts with `.expand_div_ceil_optimized`
|
||||
.scalarize_int_from_float_safe, // conflicts with `.expand_int_from_float_safe`
|
||||
.scalarize_int_from_float_optimized_safe, // conflicts with `.expand_int_from_float_optimized_safe`
|
||||
|
||||
// This feature introduces a new AIR form, and acts solely as an optimization (I'm not actually
|
||||
// sure if it should be here at all), so is excluded from `-flegalize-all`.
|
||||
.unsplat_shift_rhs,
|
||||
}));
|
||||
|
||||
pub const Error = std.mem.Allocator.Error;
|
||||
|
||||
pub fn legalize(air: *Air, pt: Zcu.PerThread, features: *const Features) Error!void {
|
||||
|
||||
@@ -58,6 +58,7 @@ import_memory: bool,
|
||||
export_memory: bool,
|
||||
shared_memory: bool,
|
||||
is_test: bool,
|
||||
legalize_all: bool,
|
||||
debug_format: DebugFormat,
|
||||
root_optimize_mode: std.lang.Optimize,
|
||||
root_strip: bool,
|
||||
@@ -111,6 +112,7 @@ pub const Options = struct {
|
||||
use_new_linker: ?bool = null,
|
||||
pie: ?bool = null,
|
||||
lto: ?std.zig.LtoMode = null,
|
||||
legalize_all: bool = false,
|
||||
incremental: bool = false,
|
||||
/// WASI-only. Type of WASI execution model ("command" or "reactor").
|
||||
wasi_exec_model: ?std.lang.WasiExecModel = null,
|
||||
@@ -161,6 +163,7 @@ pub const ResolveError = error{
|
||||
DllExportFnsRequiresWindows,
|
||||
NewLinkerIncompatibleWithLld,
|
||||
NewLinkerIncompatibleObjectFormat,
|
||||
LegalizeAllRequiresLlvm,
|
||||
};
|
||||
|
||||
pub fn resolve(options: Options) ResolveError!Config {
|
||||
@@ -395,6 +398,10 @@ pub fn resolve(options: Options) ResolveError!Config {
|
||||
// There is no compiler backend available for this target.
|
||||
return error.ZigLacksTargetSupport;
|
||||
}
|
||||
|
||||
if (options.legalize_all and !use_llvm) {
|
||||
return error.LegalizeAllRequiresLlvm;
|
||||
}
|
||||
}
|
||||
|
||||
// Make a decision on whether to use LLD or our own linker.
|
||||
@@ -613,6 +620,7 @@ pub fn resolve(options: Options) ResolveError!Config {
|
||||
.output_mode = options.output_mode,
|
||||
.have_zcu = options.have_zcu,
|
||||
.is_test = options.is_test,
|
||||
.legalize_all = options.legalize_all,
|
||||
.link_mode = link_mode,
|
||||
.link_libc = link_libc,
|
||||
.link_libcpp = link_libcpp,
|
||||
|
||||
@@ -68,6 +68,9 @@ fn importBackend(comptime backend: std.lang.CompilerBackend) type {
|
||||
|
||||
pub fn legalizeFeatures(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) ?*const Air.Legalize.Features {
|
||||
const zcu = pt.zcu;
|
||||
if (zcu.comp.config.legalize_all) {
|
||||
return &Air.Legalize.all_features;
|
||||
}
|
||||
const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result;
|
||||
switch (target_util.zigBackend(target, zcu.comp.config.use_llvm)) {
|
||||
else => unreachable,
|
||||
|
||||
@@ -350,8 +350,9 @@ fn genBody(self: *FuncGen, body: []const Air.Inst.Index, coverage_point: Air.Cov
|
||||
.legalize_vec_elem_val => try self.airLegalizeVecElemVal(inst),
|
||||
.legalize_vec_store_elem => try self.airLegalizeVecStoreElem(inst),
|
||||
|
||||
// No soft float legalizations are enabled.
|
||||
.legalize_compiler_rt_call => unreachable,
|
||||
// No soft float legalizations are requested, but for testing we sometimes enable *all*
|
||||
// legalizations in this backend (`-flegalize-all`), so we still need to handle this.
|
||||
.legalize_compiler_rt_call => try self.airLegalizeCompilerRtCall(inst),
|
||||
|
||||
.add => try self.airAdd(inst, .normal),
|
||||
.add_optimized => try self.airAdd(inst, .fast),
|
||||
@@ -2290,6 +2291,48 @@ fn airLegalizeVecStoreElem(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!B
|
||||
return .none;
|
||||
}
|
||||
|
||||
fn airLegalizeCompilerRtCall(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
|
||||
const zcu = fg.object.zcu;
|
||||
const comp = zcu.comp;
|
||||
const gpa = comp.gpa;
|
||||
const target = comp.getTarget();
|
||||
const builder = &fg.object.builder;
|
||||
|
||||
const compiler_rt_call = fg.air.unwrapCompilerRtCall(inst);
|
||||
|
||||
const param_types = try gpa.alloc(InternPool.Index, compiler_rt_call.args.len);
|
||||
defer gpa.free(param_types);
|
||||
|
||||
const llvm_args = try gpa.alloc(Builder.Value, compiler_rt_call.args.len);
|
||||
defer gpa.free(llvm_args);
|
||||
|
||||
for (param_types, llvm_args, compiler_rt_call.args) |*param_ty, *llvm_arg, arg_ref| {
|
||||
param_ty.* = fg.typeOf(arg_ref).toIntern();
|
||||
llvm_arg.* = try fg.resolveInst(arg_ref);
|
||||
}
|
||||
|
||||
const fn_info: Object.FuncInfo = .{
|
||||
.cc = compiler_rt_call.func.@"callconv"(target),
|
||||
.param_types = param_types,
|
||||
.return_type = compiler_rt_call.func.returnType().toIntern(),
|
||||
};
|
||||
|
||||
const llvm_fn = try fg.object.getLibcFunction(
|
||||
fg.pt,
|
||||
try builder.strtabString(compiler_rt_call.func.name(target)),
|
||||
fn_info,
|
||||
);
|
||||
|
||||
return fg.buildCall(
|
||||
.{},
|
||||
llvm_fn.typeOf(builder),
|
||||
llvm_fn.toValue(builder),
|
||||
fn_info,
|
||||
fn_info.param_types,
|
||||
llvm_args,
|
||||
);
|
||||
}
|
||||
|
||||
fn airPtrElemVal(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value {
|
||||
const zcu = self.object.zcu;
|
||||
const bin_op = self.air.instructions.items(.data)[@backingInt(inst)].bin_op;
|
||||
|
||||
@@ -793,6 +793,7 @@ const compile_usage =
|
||||
\\Debug Options (Zig Compiler Development):
|
||||
\\ -fopt-bisect-limit=[limit] Only run [limit] first LLVM optimization passes
|
||||
\\ -fstack-report Print stack size diagnostics
|
||||
\\ -flegalize-all Force-enable all codegen legalizations for testing
|
||||
\\ --debug-log [scope] Enable printing debug/info log messages for scope
|
||||
\\ --debug-compile-errors Crash with helpful diagnostics at the first compile error
|
||||
\\ --debug-link-snapshot Dump linker state and output file information for troubleshooting
|
||||
@@ -1498,6 +1499,8 @@ fn buildOutputType(
|
||||
test_execve = true;
|
||||
} else if (mem.eql(u8, arg, "-fstack-report")) {
|
||||
stack_report = true;
|
||||
} else if (mem.eql(u8, arg, "-flegalize-all")) {
|
||||
create_module.opts.legalize_all = true;
|
||||
} else if (mem.eql(u8, arg, "-fPIC")) {
|
||||
mod_opts.pic = true;
|
||||
} else if (mem.eql(u8, arg, "-fno-PIC")) {
|
||||
@@ -4328,6 +4331,7 @@ fn createModule(
|
||||
error.DllExportFnsRequiresWindows => fatal("only Windows OS targets support DLLs", .{}),
|
||||
error.NewLinkerIncompatibleWithLld => fatal("using the new linker is incompatible with using lld", .{}),
|
||||
error.NewLinkerIncompatibleObjectFormat => fatal("no new linker available for '{t}' files", .{target.ofmt}),
|
||||
error.LegalizeAllRequiresLlvm => fatal("'-flegalize-all' requires the LLVM backend", .{}),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user