| author | |
| committer | |
| log | 55811d8dac9109aa6357639908fb4f6c479480f9 |
| tree | 668f796e1c6feeb6972f178c4a9c1333c594cdce |
| parent | 609207801a570508e58d9e02b6ce551fbf1dca30 |
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 | 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 | 2970 | if (out_dep_path) |p| { |
| 2949 | 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 | } | |
| 2965 | 2973 | |
| 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 | 2978 | if (target_util.clangMightShellOutForAssembly(target)) { |
| 2967 | 2979 | try argv.append("-integrated-as"); |
| 2968 | 2980 | } |
src/target.zig+9| ... | ... | @@ -389,3 +389,12 @@ pub fn clangMightShellOutForAssembly(target: std.Target) bool { |
| 389 | 389 | // when targeting a non-BSD OS. |
| 390 | 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. | |
| 395 | pub 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 | 16 | cases.addBuildFile("test/standalone/link_interdependent_static_c_libs/build.zig"); |
| 17 | 17 | cases.addBuildFile("test/standalone/link_static_lib_as_system_lib/build.zig"); |
| 18 | 18 | cases.addBuildFile("test/standalone/issue_339/build.zig"); |
| 19 | cases.addBuildFile("test/standalone/issue_8550/build.zig"); | |
| 19 | 20 | cases.addBuildFile("test/standalone/issue_794/build.zig"); |
| 20 | 21 | cases.addBuildFile("test/standalone/issue_5825/build.zig"); |
| 21 | 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 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | pub 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 @@ |
| 1 | ENTRY(_start) | |
| 2 | ||
| 3 | SECTIONS | |
| 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 @@ |
| 1 | export fn main(r0: u32, r1: u32, atags: u32) callconv(.C) noreturn { | |
| 2 | unreachable; // never gets run so it doesn't matter | |
| 3 | } | |
| 4 | pub fn panic(msg: []const u8, error_return_trace: ?*@import("std").builtin.StackTrace) noreturn { | |
| 5 | while (true) {} | |
| 6 | } |