Skip to content

Commit b917d77

Browse files
authored
Merge pull request #21056 from alexrp/start-fix-precedence
`start`: Avoid string concatenation in inline asm.
2 parents 72bcc3b + 7a8e86e commit b917d77

File tree

2 files changed

+37
-45
lines changed

2 files changed

+37
-45
lines changed

lib/std/start.zig

Lines changed: 17 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,16 @@ fn _start() callconv(.Naked) noreturn {
232232
);
233233
}
234234

235+
// Move this to the riscv prong below when this is resolved: https://github.com/ziglang/zig/issues/20918
236+
if (builtin.cpu.arch.isRISCV() and builtin.zig_backend != .stage2_riscv64) asm volatile (
237+
\\ .weak __global_pointer$
238+
\\ .hidden __global_pointer$
239+
\\ .option push
240+
\\ .option norelax
241+
\\ lla gp, __global_pointer$
242+
\\ .option pop
243+
);
244+
235245
// Note that we maintain a very low level of trust with regards to ABI guarantees at this point.
236246
// We will redundantly align the stack, clear the link register, etc. While e.g. the Linux
237247
// kernel is usually good about upholding the ABI guarantees, the same cannot be said of dynamic
@@ -275,24 +285,19 @@ fn _start() callconv(.Naked) noreturn {
275285
\\ and sp, #-16
276286
\\ b %[posixCallMainAndExit]
277287
,
278-
// zig fmt: off
279288
.csky =>
280-
if (builtin.position_independent_code)
281-
// The CSKY ABI assumes that `gb` is set to the address of the GOT in order for
282-
// position-independent code to work. We depend on this in `std.os.linux.start_pie`
283-
// to locate `_DYNAMIC` as well.
284-
\\ grs t0, 1f
285-
\\ 1:
286-
\\ lrw gb, 1b@GOTPC
287-
\\ addu gb, t0
288-
else ""
289-
++
289+
// The CSKY ABI assumes that `gb` is set to the address of the GOT in order for
290+
// position-independent code to work. We depend on this in `std.os.linux.start_pie`
291+
// to locate `_DYNAMIC` as well.
292+
\\ grs t0, 1f
293+
\\ 1:
294+
\\ lrw gb, 1b@GOTPC
295+
\\ addu gb, t0
290296
\\ movi lr, 0
291297
\\ mov a0, sp
292298
\\ andi sp, sp, -8
293299
\\ jmpi %[posixCallMainAndExit]
294300
,
295-
// zig fmt: on
296301
.hexagon =>
297302
// r29 = SP, r30 = FP
298303
\\ r30 = #0
@@ -308,27 +313,13 @@ fn _start() callconv(.Naked) noreturn {
308313
\\ bstrins.d $sp, $zero, 3, 0
309314
\\ b %[posixCallMainAndExit]
310315
,
311-
// zig fmt: off
312316
.riscv32, .riscv64 =>
313-
// The self-hosted riscv64 backend is not able to assemble this yet.
314-
if (builtin.zig_backend != .stage2_riscv64)
315-
// The RISC-V ELF ABI assumes that `gp` is set to the value of `__global_pointer$` at
316-
// startup in order for GP relaxation to work, even in static builds.
317-
\\ .weak __global_pointer$
318-
\\ .hidden __global_pointer$
319-
\\ .option push
320-
\\ .option norelax
321-
\\ lla gp, __global_pointer$
322-
\\ .option pop
323-
else ""
324-
++
325317
\\ li s0, 0
326318
\\ li ra, 0
327319
\\ mv a0, sp
328320
\\ andi sp, sp, -16
329321
\\ tail %[posixCallMainAndExit]@plt
330322
,
331-
// zig fmt: on
332323
.m68k =>
333324
// Note that the - 8 is needed because pc in the jsr instruction points into the middle
334325
// of the jsr instruction. (The lea is 6 bytes, the jsr is 4 bytes.)

src/codegen/llvm.zig

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2909,7 +2909,17 @@ pub const Object = struct {
29092909
function_index.setAlignment(resolved.alignment.toLlvm(), &o.builder);
29102910

29112911
// Function attributes that are independent of analysis results of the function body.
2912-
try o.addCommonFnAttributes(&attributes, owner_mod);
2912+
try o.addCommonFnAttributes(
2913+
&attributes,
2914+
owner_mod,
2915+
// Some backends don't respect the `naked` attribute in `TargetFrameLowering::hasFP()`,
2916+
// so for these backends, LLVM will happily emit code that accesses the stack through
2917+
// the frame pointer. This is nonsensical since what the `naked` attribute does is
2918+
// suppress generation of the prologue and epilogue, and the prologue is where the
2919+
// frame pointer normally gets set up. At time of writing, this is the case for at
2920+
// least x86 and RISC-V.
2921+
owner_mod.omit_frame_pointer or fn_info.cc == .Naked,
2922+
);
29132923

29142924
if (fn_info.return_type == .noreturn_type) try attributes.addFnAttr(.noreturn, &o.builder);
29152925

@@ -2956,13 +2966,14 @@ pub const Object = struct {
29562966
o: *Object,
29572967
attributes: *Builder.FunctionAttributes.Wip,
29582968
owner_mod: *Package.Module,
2969+
omit_frame_pointer: bool,
29592970
) Allocator.Error!void {
29602971
const comp = o.pt.zcu.comp;
29612972

29622973
if (!owner_mod.red_zone) {
29632974
try attributes.addFnAttr(.noredzone, &o.builder);
29642975
}
2965-
if (owner_mod.omit_frame_pointer) {
2976+
if (omit_frame_pointer) {
29662977
try attributes.addFnAttr(.{ .string = .{
29672978
.kind = try o.builder.string("frame-pointer"),
29682979
.value = try o.builder.string("none"),
@@ -4528,7 +4539,7 @@ pub const Object = struct {
45284539

45294540
var attributes: Builder.FunctionAttributes.Wip = .{};
45304541
defer attributes.deinit(&o.builder);
4531-
try o.addCommonFnAttributes(&attributes, zcu.root_mod);
4542+
try o.addCommonFnAttributes(&attributes, zcu.root_mod, zcu.root_mod.omit_frame_pointer);
45324543

45334544
function_index.setLinkage(.internal, &o.builder);
45344545
function_index.setCallConv(.fastcc, &o.builder);
@@ -4557,7 +4568,7 @@ pub const Object = struct {
45574568

45584569
var attributes: Builder.FunctionAttributes.Wip = .{};
45594570
defer attributes.deinit(&o.builder);
4560-
try o.addCommonFnAttributes(&attributes, zcu.root_mod);
4571+
try o.addCommonFnAttributes(&attributes, zcu.root_mod, zcu.root_mod.omit_frame_pointer);
45614572

45624573
function_index.setLinkage(.internal, &o.builder);
45634574
function_index.setCallConv(.fastcc, &o.builder);
@@ -6709,8 +6720,6 @@ pub const FuncGen = struct {
67096720
const operand_ty = self.typeOf(pl_op.operand);
67106721
const name = self.air.nullTerminatedString(pl_op.payload);
67116722

6712-
if (needDbgVarWorkaround(o)) return .none;
6713-
67146723
const debug_local_var = try o.builder.debugLocalVar(
67156724
try o.builder.metadataString(name),
67166725
self.file,
@@ -6734,7 +6743,10 @@ pub const FuncGen = struct {
67346743
},
67356744
"",
67366745
);
6737-
} else if (owner_mod.optimize_mode == .Debug) {
6746+
} else if (owner_mod.optimize_mode == .Debug and !self.is_naked) {
6747+
// We avoid taking this path for naked functions because there's no guarantee that such
6748+
// functions even have a valid stack pointer, making the `alloca` + `store` unsafe.
6749+
67386750
const alignment = operand_ty.abiAlignment(pt).toLlvm();
67396751
const alloca = try self.buildAlloca(operand.typeOfWip(&self.wip), alignment);
67406752
_ = try self.wip.store(.normal, operand, alloca, alignment);
@@ -8815,7 +8827,6 @@ pub const FuncGen = struct {
88158827
if (self.is_naked) return arg_val;
88168828

88178829
const inst_ty = self.typeOfIndex(inst);
8818-
if (needDbgVarWorkaround(o)) return arg_val;
88198830

88208831
const name = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.name;
88218832
if (name == .none) return arg_val;
@@ -9676,7 +9687,7 @@ pub const FuncGen = struct {
96769687

96779688
var attributes: Builder.FunctionAttributes.Wip = .{};
96789689
defer attributes.deinit(&o.builder);
9679-
try o.addCommonFnAttributes(&attributes, zcu.root_mod);
9690+
try o.addCommonFnAttributes(&attributes, zcu.root_mod, zcu.root_mod.omit_frame_pointer);
96809691

96819692
function_index.setLinkage(.internal, &o.builder);
96829693
function_index.setCallConv(.fastcc, &o.builder);
@@ -11820,16 +11831,6 @@ const optional_layout_version = 3;
1182011831

1182111832
const lt_errors_fn_name = "__zig_lt_errors_len";
1182211833

11823-
/// Without this workaround, LLVM crashes with "unknown codeview register H1"
11824-
/// https://github.com/llvm/llvm-project/issues/56484
11825-
fn needDbgVarWorkaround(o: *Object) bool {
11826-
const target = o.pt.zcu.getTarget();
11827-
if (target.os.tag == .windows and target.cpu.arch == .aarch64) {
11828-
return true;
11829-
}
11830-
return false;
11831-
}
11832-
1183311834
fn compilerRtIntBits(bits: u16) u16 {
1183411835
inline for (.{ 32, 64, 128 }) |b| {
1183511836
if (bits <= b) {

0 commit comments

Comments
 (0)