authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-23 21:51:10-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-23 21:51:10-07:00
log55811d8dac9109aa6357639908fb4f6c479480f9
tree668f796e1c6feeb6972f178c4a9c1333c594cdce
parent609207801a570508e58d9e02b6ce551fbf1dca30

stage2: introduce clangAssemblerSupportsMcpuArg

Clang has a completely inconsistent CLI for its integrated assembler for each target architecture. For x86_64, for example, it does not accept an -mcpu parameter, and emits "warning: unused parameter". However, for ARM, -mcpu is needed in order to properly lower assembly to machine code instructions (see new standalone test case provided thanks to @g-w1). This is a compromise between b8f85a805bf61ae11d6ee2bd6d8356fbc98ee3ba and afb9f695b1bdbf81185e7d55d5783bcbab880989.

7 files changed, 139 insertions(+), 15 deletions(-)

src/Compilation.zig+27-15
...@@ -2943,26 +2943,38 @@ pub fn addCCArgs(...@@ -2943,26 +2943,38 @@ pub fn addCCArgs(
2943 try argv.append("-fPIC");2943 try argv.append("-fPIC");
2944 }2944 }
2945 },2945 },
2946 .shared_library, .assembly, .ll, .bc, .unknown, .static_library, .object, .zig => {},2946 .shared_library, .ll, .bc, .unknown, .static_library, .object, .zig => {},
2947 .assembly => {
2948 // The Clang assembler does not accept the list of CPU features like the
2949 // compiler frontend does. Therefore we must hard-code the -m flags for
2950 // all CPU features here.
2951 switch (target.cpu.arch) {
2952 .riscv32, .riscv64 => {
2953 if (std.Target.riscv.featureSetHas(target.cpu.features, .relax)) {
2954 try argv.append("-mrelax");
2955 } else {
2956 try argv.append("-mno-relax");
2957 }
2958 },
2959 else => {
2960 // TODO
2961 },
2962 }
2963 if (target_util.clangAssemblerSupportsMcpuArg(target)) {
2964 if (target.cpu.model.llvm_name) |llvm_name| {
2965 try argv.append(try std.fmt.allocPrint(arena, "-mcpu={s}", .{llvm_name}));
2966 }
2967 }
2968 },
2947 }2969 }
2948 if (out_dep_path) |p| {2970 if (out_dep_path) |p| {
2949 try argv.appendSlice(&[_][]const u8{ "-MD", "-MV", "-MF", p });2971 try argv.appendSlice(&[_][]const u8{ "-MD", "-MV", "-MF", p });
2950 }2972 }
2951 // Argh, why doesn't the assembler accept the list of CPU features?!
2952 // I don't see a way to do this other than hard coding everything.
2953 switch (target.cpu.arch) {
2954 .riscv32, .riscv64 => {
2955 if (std.Target.riscv.featureSetHas(target.cpu.features, .relax)) {
2956 try argv.append("-mrelax");
2957 } else {
2958 try argv.append("-mno-relax");
2959 }
2960 },
2961 else => {
2962 // TODO
2963 },
2964 }
29652973
2974 // We never want clang to invoke the system assembler for anything. So we would want
2975 // this option always enabled. However, it only matters for some targets. To avoid
2976 // "unused parameter" warnings, and to keep CLI spam to a minimum, we only put this
2977 // flag on the command line if it is necessary.
2966 if (target_util.clangMightShellOutForAssembly(target)) {2978 if (target_util.clangMightShellOutForAssembly(target)) {
2967 try argv.append("-integrated-as");2979 try argv.append("-integrated-as");
2968 }2980 }
src/target.zig+9
...@@ -389,3 +389,12 @@ pub fn clangMightShellOutForAssembly(target: std.Target) bool {...@@ -389,3 +389,12 @@ pub fn clangMightShellOutForAssembly(target: std.Target) bool {
389 // when targeting a non-BSD OS.389 // when targeting a non-BSD OS.
390 return target.cpu.arch.isSPARC();390 return target.cpu.arch.isSPARC();
391}391}
392
393/// Each backend architecture in Clang has a different codepath which may or may not
394/// support an -mcpu flag.
395pub fn clangAssemblerSupportsMcpuArg(target: std.Target) bool {
396 return switch (target.cpu.arch) {
397 .arm, .armeb, .thumb, .thumbeb => true,
398 else => false,
399 };
400}
test/standalone.zig+1
...@@ -16,6 +16,7 @@ pub fn addCases(cases: *tests.StandaloneContext) void {...@@ -16,6 +16,7 @@ pub fn addCases(cases: *tests.StandaloneContext) void {
16 cases.addBuildFile("test/standalone/link_interdependent_static_c_libs/build.zig");16 cases.addBuildFile("test/standalone/link_interdependent_static_c_libs/build.zig");
17 cases.addBuildFile("test/standalone/link_static_lib_as_system_lib/build.zig");17 cases.addBuildFile("test/standalone/link_static_lib_as_system_lib/build.zig");
18 cases.addBuildFile("test/standalone/issue_339/build.zig");18 cases.addBuildFile("test/standalone/issue_339/build.zig");
19 cases.addBuildFile("test/standalone/issue_8550/build.zig");
19 cases.addBuildFile("test/standalone/issue_794/build.zig");20 cases.addBuildFile("test/standalone/issue_794/build.zig");
20 cases.addBuildFile("test/standalone/issue_5825/build.zig");21 cases.addBuildFile("test/standalone/issue_5825/build.zig");
21 cases.addBuildFile("test/standalone/pkg_import/build.zig");22 cases.addBuildFile("test/standalone/pkg_import/build.zig");
test/standalone/issue_8550/boot.S created+33
...@@ -0,0 +1,33 @@
1 .section ".text.boot"
2
3 .global _start
4
5 _start:
6 mrc p15, #0, r1, c0, c0, #5
7 and r1, r1, #3
8 cmp r1, #0
9 bne halt
10
11 mov sp, #0x8000
12
13 ldr r4, =__bss_start
14 ldr r9, =__bss_end
15 mov r5, #0
16 mov r6, #0
17 mov r7, #0
18 mov r8, #0
19 b 2f
20
21 1:
22 stmia r4!, {r5-r8}
23
24 2:
25 cmp r4, r9
26 blo 1b
27
28 ldr r3, =main
29 blx r3
30
31 halt:
32 wfe
33 b halt
test/standalone/issue_8550/build.zig created+21
...@@ -0,0 +1,21 @@
1const std = @import("std");
2
3pub fn build(b: *std.build.Builder) !void {
4 const target = std.zig.CrossTarget{
5 .os_tag = .freestanding,
6 .cpu_arch = .arm,
7 .cpu_model = .{
8 .explicit = &std.Target.arm.cpu.arm1176jz_s,
9 },
10 };
11 const mode = b.standardReleaseOptions();
12 const kernel = b.addExecutable("kernel", "./main.zig");
13 kernel.addObjectFile("./boot.S");
14 kernel.setLinkerScriptPath("./linker.ld");
15 kernel.setBuildMode(mode);
16 kernel.setTarget(target);
17 kernel.install();
18
19 const test_step = b.step("test", "Test it");
20 test_step.dependOn(&kernel.step);
21}
test/standalone/issue_8550/linker.ld created+42
...@@ -0,0 +1,42 @@
1ENTRY(_start)
2
3SECTIONS
4{
5 /* Starts at LOADER_ADDR. */
6 . = 0x8000;
7 __start = .;
8 __text_start = .;
9 .text :
10 {
11 KEEP(*(.text.boot))
12 *(.text)
13 }
14 . = ALIGN(4096); /* align to page size */
15 __text_end = .;
16
17 __rodata_start = .;
18 .rodata :
19 {
20 *(.rodata)
21 }
22 . = ALIGN(4096); /* align to page size */
23 __rodata_end = .;
24
25 __data_start = .;
26 .data :
27 {
28 *(.data)
29 }
30 . = ALIGN(4096); /* align to page size */
31 __data_end = .;
32
33 __bss_start = .;
34 .bss :
35 {
36 bss = .;
37 *(.bss)
38 }
39 . = ALIGN(4096); /* align to page size */
40 __bss_end = .;
41 __end = .;
42}
test/standalone/issue_8550/main.zig created+6
...@@ -0,0 +1,6 @@
1export fn main(r0: u32, r1: u32, atags: u32) callconv(.C) noreturn {
2 unreachable; // never gets run so it doesn't matter
3}
4pub fn panic(msg: []const u8, error_return_trace: ?*@import("std").builtin.StackTrace) noreturn {
5 while (true) {}
6}