std.Target.parse gives parsing diagnostics

This commit is contained in:
Andrew Kelley 2020-02-21 13:34:55 -05:00
parent 7da7fbb912
commit 71573584cd
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
2 changed files with 68 additions and 7 deletions

View File

@ -727,18 +727,47 @@ pub const Target = union(enum) {
/// are examples of CPU features to add to the set, and "c" and "d" are examples of CPU features
/// to remove from the set.
cpu_features: []const u8 = "baseline",
/// If this is provided, the function will populate some information about parsing failures,
/// so that user-friendly error messages can be delivered.
diagnostics: ?*Diagnostics = null,
pub const Diagnostics = struct {
/// If the architecture was determined, this will be populated.
arch: ?Cpu.Arch = null,
/// If the OS was determined, this will be populated.
os: ?Os = null,
/// If the ABI was determined, this will be populated.
abi: ?Abi = null,
/// If the CPU name was determined, this will be populated.
cpu_name: ?[]const u8 = null,
/// If error.UnknownCpuFeature is returned, this will be populated.
unknown_feature_name: ?[]const u8 = null,
};
};
pub fn parse(args: ParseOptions) !Target {
var dummy_diags: ParseOptions.Diagnostics = undefined;
var diags = args.diagnostics orelse &dummy_diags;
var it = mem.separate(args.arch_os_abi, "-");
const arch_name = it.next() orelse return error.MissingArchitecture;
const os_name = it.next() orelse return error.MissingOperatingSystem;
const abi_name = it.next();
if (it.next() != null) return error.UnexpectedExtraField;
const arch = try Cpu.Arch.parse(arch_name);
diags.arch = arch;
const os_name = it.next() orelse return error.MissingOperatingSystem;
const os = try Os.parse(os_name);
diags.os = os;
const abi_name = it.next();
const abi = if (abi_name) |n| try Abi.parse(n) else Abi.default(arch, os);
diags.abi = abi;
if (it.next() != null) return error.UnexpectedExtraField;
const all_features = arch.allFeaturesList();
var index: usize = 0;
@ -749,6 +778,8 @@ pub const Target = union(enum) {
index += 1;
}
const cpu_name = args.cpu_features[0..index];
diags.cpu_name = cpu_name;
const cpu: Cpu = if (mem.eql(u8, cpu_name, "baseline")) Cpu.baseline(arch) else blk: {
const cpu_model = try arch.parseCpuModel(cpu_name);
@ -775,6 +806,7 @@ pub const Target = union(enum) {
break;
}
} else {
diags.unknown_feature_name = feature_name;
return error.UnknownCpuFeature;
}
}

View File

@ -661,9 +661,7 @@ export fn stage2_target_parse(
error.MissingOperatingSystem => return .MissingOperatingSystem,
error.MissingArchitecture => return .MissingArchitecture,
error.InvalidLlvmCpuFeaturesFormat => return .InvalidLlvmCpuFeaturesFormat,
error.UnknownCpu => return .UnknownCpu,
error.UnexpectedExtraField => return .SemanticAnalyzeFail,
error.UnknownCpuFeature => return .UnknownCpuFeature,
};
return .None;
}
@ -676,7 +674,38 @@ fn stage2TargetParse(
const target: Target = if (zig_triple_oz) |zig_triple_z| blk: {
const zig_triple = mem.toSliceConst(u8, zig_triple_z);
const mcpu = if (mcpu_oz) |mcpu_z| mem.toSliceConst(u8, mcpu_z) else "baseline";
break :blk try Target.parse(.{ .arch_os_abi = zig_triple, .cpu_features = mcpu });
var diags: std.Target.ParseOptions.Diagnostics = .{};
break :blk Target.parse(.{
.arch_os_abi = zig_triple,
.cpu_features = mcpu,
.diagnostics = &diags,
}) catch |err| switch (err) {
error.UnknownCpu => {
std.debug.warn("Unknown CPU: '{}'\nAvailable CPUs for architecture '{}':\n", .{
diags.cpu_name.?,
@tagName(diags.arch.?),
});
for (diags.arch.?.allCpuModels()) |cpu| {
std.debug.warn(" {}\n", .{cpu.name});
}
process.exit(1);
},
error.UnknownCpuFeature => {
std.debug.warn(
\\Unknown CPU feature: '{}'
\\Available CPU features for architecture '{}':
\\
, .{
diags.unknown_feature_name,
@tagName(diags.arch.?),
});
for (diags.arch.?.allFeaturesList()) |feature| {
std.debug.warn(" {}: {}\n", .{ feature.name, feature.description });
}
process.exit(1);
},
else => |e| return e,
};
} else Target.Native;
try stage1_target.fromTarget(target);