Skip to content

Commit 5f5a20e

Browse files
authored
Merge pull request #13093 from jacobly0/backend-fixes
C backend fixes
2 parents 09a96cd + 4364f51 commit 5f5a20e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

99 files changed

+4277
-3390
lines changed

lib/include/zig.h

Lines changed: 1219 additions & 1319 deletions
Large diffs are not rendered by default.

lib/std/debug.zig

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1222,7 +1222,13 @@ pub const DebugInfo = struct {
12221222
}
12231223

12241224
pub fn getModuleForAddress(self: *DebugInfo, address: usize) !*ModuleDebugInfo {
1225-
if (comptime builtin.target.isDarwin()) {
1225+
if (builtin.zig_backend == .stage2_c) {
1226+
return @as(error{
1227+
InvalidDebugInfo,
1228+
MissingDebugInfo,
1229+
UnsupportedBackend,
1230+
}, error.UnsupportedBackend);
1231+
} else if (comptime builtin.target.isDarwin()) {
12261232
return self.lookupModuleDyld(address);
12271233
} else if (native_os == .windows) {
12281234
return self.lookupModuleWin32(address);

lib/std/os/linux/arm64.zig

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,20 @@ pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *
106106
pub const restore = restore_rt;
107107

108108
pub fn restore_rt() callconv(.Naked) void {
109-
return asm volatile ("svc #0"
110-
:
111-
: [number] "{x8}" (@enumToInt(SYS.rt_sigreturn)),
112-
: "memory", "cc"
113-
);
109+
switch (@import("builtin").zig_backend) {
110+
.stage2_c => return asm volatile (
111+
\\ mov x8, %[number]
112+
\\ svc #0
113+
:
114+
: [number] "i" (@enumToInt(SYS.rt_sigreturn)),
115+
: "memory", "cc"
116+
),
117+
else => return asm volatile ("svc #0"
118+
:
119+
: [number] "{x8}" (@enumToInt(SYS.rt_sigreturn)),
120+
: "memory", "cc"
121+
),
122+
}
114123
}
115124

116125
pub const O = struct {

lib/std/os/linux/i386.zig

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -124,19 +124,37 @@ const CloneFn = std.meta.FnPtr(fn (arg: usize) callconv(.C) u8);
124124
pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
125125

126126
pub fn restore() callconv(.Naked) void {
127-
return asm volatile ("int $0x80"
128-
:
129-
: [number] "{eax}" (@enumToInt(SYS.sigreturn)),
130-
: "memory"
131-
);
127+
switch (@import("builtin").zig_backend) {
128+
.stage2_c => return asm volatile (
129+
\\ movl %[number], %%eax
130+
\\ int $0x80
131+
:
132+
: [number] "i" (@enumToInt(SYS.sigreturn)),
133+
: "memory"
134+
),
135+
else => return asm volatile ("int $0x80"
136+
:
137+
: [number] "{eax}" (@enumToInt(SYS.sigreturn)),
138+
: "memory"
139+
),
140+
}
132141
}
133142

134143
pub fn restore_rt() callconv(.Naked) void {
135-
return asm volatile ("int $0x80"
136-
:
137-
: [number] "{eax}" (@enumToInt(SYS.rt_sigreturn)),
138-
: "memory"
139-
);
144+
switch (@import("builtin").zig_backend) {
145+
.stage2_c => return asm volatile (
146+
\\ movl %[number], %%eax
147+
\\ int $0x80
148+
:
149+
: [number] "i" (@enumToInt(SYS.rt_sigreturn)),
150+
: "memory"
151+
),
152+
else => return asm volatile ("int $0x80"
153+
:
154+
: [number] "{eax}" (@enumToInt(SYS.rt_sigreturn)),
155+
: "memory"
156+
),
157+
}
140158
}
141159

142160
pub const O = struct {

lib/std/os/linux/x86_64.zig

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -108,11 +108,21 @@ pub extern fn clone(func: CloneFn, stack: usize, flags: usize, arg: usize, ptid:
108108
pub const restore = restore_rt;
109109

110110
pub fn restore_rt() callconv(.Naked) void {
111-
return asm volatile ("syscall"
112-
:
113-
: [number] "{rax}" (@enumToInt(SYS.rt_sigreturn)),
114-
: "rcx", "r11", "memory"
115-
);
111+
switch (@import("builtin").zig_backend) {
112+
.stage2_c => return asm volatile (
113+
\\ movl %[number], %%eax
114+
\\ syscall
115+
\\ retq
116+
:
117+
: [number] "i" (@enumToInt(SYS.rt_sigreturn)),
118+
: "rcx", "r11", "memory"
119+
),
120+
else => return asm volatile ("syscall"
121+
:
122+
: [number] "{rax}" (@enumToInt(SYS.rt_sigreturn)),
123+
: "rcx", "r11", "memory"
124+
),
125+
}
116126
}
117127

118128
pub const mode_t = usize;

lib/std/start.zig

Lines changed: 101 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ comptime {
2323
// Until then, we have simplified logic here for self-hosted. TODO remove this once
2424
// self-hosted is capable enough to handle all of the real start.zig logic.
2525
if (builtin.zig_backend == .stage2_wasm or
26-
builtin.zig_backend == .stage2_c or
2726
builtin.zig_backend == .stage2_x86_64 or
2827
builtin.zig_backend == .stage2_x86 or
2928
builtin.zig_backend == .stage2_aarch64 or
@@ -265,75 +264,104 @@ fn EfiMain(handle: uefi.Handle, system_table: *uefi.tables.SystemTable) callconv
265264
}
266265

267266
fn _start() callconv(.Naked) noreturn {
268-
switch (native_arch) {
269-
.x86_64 => {
270-
argc_argv_ptr = asm volatile (
271-
\\ xor %%rbp, %%rbp
272-
: [argc] "={rsp}" (-> [*]usize),
273-
);
274-
},
275-
.i386 => {
276-
argc_argv_ptr = asm volatile (
277-
\\ xor %%ebp, %%ebp
278-
: [argc] "={esp}" (-> [*]usize),
279-
);
280-
},
281-
.aarch64, .aarch64_be, .arm, .armeb, .thumb => {
282-
argc_argv_ptr = asm volatile (
283-
\\ mov fp, #0
284-
\\ mov lr, #0
285-
: [argc] "={sp}" (-> [*]usize),
286-
);
287-
},
288-
.riscv64 => {
289-
argc_argv_ptr = asm volatile (
290-
\\ li s0, 0
291-
\\ li ra, 0
292-
: [argc] "={sp}" (-> [*]usize),
293-
);
294-
},
295-
.mips, .mipsel => {
296-
// The lr is already zeroed on entry, as specified by the ABI.
297-
argc_argv_ptr = asm volatile (
298-
\\ move $fp, $0
299-
: [argc] "={sp}" (-> [*]usize),
300-
);
301-
},
302-
.powerpc => {
303-
// Setup the initial stack frame and clear the back chain pointer.
304-
argc_argv_ptr = asm volatile (
305-
\\ mr 4, 1
306-
\\ li 0, 0
307-
\\ stwu 1,-16(1)
308-
\\ stw 0, 0(1)
309-
\\ mtlr 0
310-
: [argc] "={r4}" (-> [*]usize),
311-
:
312-
: "r0"
313-
);
314-
},
315-
.powerpc64le => {
316-
// Setup the initial stack frame and clear the back chain pointer.
317-
// TODO: Support powerpc64 (big endian) on ELFv2.
318-
argc_argv_ptr = asm volatile (
319-
\\ mr 4, 1
320-
\\ li 0, 0
321-
\\ stdu 0, -32(1)
322-
\\ mtlr 0
323-
: [argc] "={r4}" (-> [*]usize),
324-
:
325-
: "r0"
326-
);
267+
switch (builtin.zig_backend) {
268+
.stage2_c => {
269+
@export(argc_argv_ptr, .{ .name = "argc_argv_ptr" });
270+
@export(posixCallMainAndExit, .{ .name = "_posixCallMainAndExit" });
271+
switch (native_arch) {
272+
.x86_64 => asm volatile (
273+
\\ xorl %%ebp, %%ebp
274+
\\ movq %%rsp, argc_argv_ptr
275+
\\ andq $-16, %%rsp
276+
\\ call _posixCallMainAndExit
277+
),
278+
.i386 => asm volatile (
279+
\\ xorl %%ebp, %%ebp
280+
\\ movl %%esp, argc_argv_ptr
281+
\\ andl $-16, %%esp
282+
\\ jmp _posixCallMainAndExit
283+
),
284+
.aarch64, .aarch64_be, .arm, .armeb, .thumb => asm volatile (
285+
\\ mov fp, #0
286+
\\ mov lr, #0
287+
\\ str sp, argc_argv_ptr
288+
\\ and sp, #-16
289+
\\ b _posixCallMainAndExit
290+
),
291+
else => @compileError("unsupported arch"),
292+
}
293+
unreachable;
327294
},
328-
.sparc64 => {
329-
// argc is stored after a register window (16 registers) plus stack bias
330-
argc_argv_ptr = asm (
331-
\\ mov %%g0, %%i6
332-
\\ add %%o6, 2175, %[argc]
333-
: [argc] "=r" (-> [*]usize),
334-
);
295+
else => switch (native_arch) {
296+
.x86_64 => {
297+
argc_argv_ptr = asm volatile (
298+
\\ xor %%ebp, %%ebp
299+
: [argc] "={rsp}" (-> [*]usize),
300+
);
301+
},
302+
.i386 => {
303+
argc_argv_ptr = asm volatile (
304+
\\ xor %%ebp, %%ebp
305+
: [argc] "={esp}" (-> [*]usize),
306+
);
307+
},
308+
.aarch64, .aarch64_be, .arm, .armeb, .thumb => {
309+
argc_argv_ptr = asm volatile (
310+
\\ mov fp, #0
311+
\\ mov lr, #0
312+
: [argc] "={sp}" (-> [*]usize),
313+
);
314+
},
315+
.riscv64 => {
316+
argc_argv_ptr = asm volatile (
317+
\\ li s0, 0
318+
\\ li ra, 0
319+
: [argc] "={sp}" (-> [*]usize),
320+
);
321+
},
322+
.mips, .mipsel => {
323+
// The lr is already zeroed on entry, as specified by the ABI.
324+
argc_argv_ptr = asm volatile (
325+
\\ move $fp, $0
326+
: [argc] "={sp}" (-> [*]usize),
327+
);
328+
},
329+
.powerpc => {
330+
// Setup the initial stack frame and clear the back chain pointer.
331+
argc_argv_ptr = asm volatile (
332+
\\ mr 4, 1
333+
\\ li 0, 0
334+
\\ stwu 1,-16(1)
335+
\\ stw 0, 0(1)
336+
\\ mtlr 0
337+
: [argc] "={r4}" (-> [*]usize),
338+
:
339+
: "r0"
340+
);
341+
},
342+
.powerpc64le => {
343+
// Setup the initial stack frame and clear the back chain pointer.
344+
// TODO: Support powerpc64 (big endian) on ELFv2.
345+
argc_argv_ptr = asm volatile (
346+
\\ mr 4, 1
347+
\\ li 0, 0
348+
\\ stdu 0, -32(1)
349+
\\ mtlr 0
350+
: [argc] "={r4}" (-> [*]usize),
351+
:
352+
: "r0"
353+
);
354+
},
355+
.sparc64 => {
356+
// argc is stored after a register window (16 registers) plus stack bias
357+
argc_argv_ptr = asm (
358+
\\ mov %%g0, %%i6
359+
\\ add %%o6, 2175, %[argc]
360+
: [argc] "=r" (-> [*]usize),
361+
);
362+
},
363+
else => @compileError("unsupported arch"),
335364
},
336-
else => @compileError("unsupported arch"),
337365
}
338366
// If LLVM inlines stack variables into _start, they will overwrite
339367
// the command line argument data.
@@ -363,7 +391,7 @@ fn wWinMainCRTStartup() callconv(std.os.windows.WINAPI) noreturn {
363391
std.os.windows.kernel32.ExitProcess(@bitCast(std.os.windows.UINT, result));
364392
}
365393

366-
fn posixCallMainAndExit() noreturn {
394+
fn posixCallMainAndExit() callconv(.C) noreturn {
367395
@setAlignStack(16);
368396

369397
const argc = argc_argv_ptr[0];
@@ -462,7 +490,7 @@ fn callMainWithArgs(argc: usize, argv: [*][*:0]u8, envp: [][*:0]u8) u8 {
462490
return initEventLoopAndCallMain();
463491
}
464492

465-
fn main(c_argc: i32, c_argv: [*][*:0]u8, c_envp: [*:null]?[*:0]u8) callconv(.C) i32 {
493+
fn main(c_argc: c_int, c_argv: [*c][*c]u8, c_envp: [*c][*c]u8) callconv(.C) c_int {
466494
var env_count: usize = 0;
467495
while (c_envp[env_count] != null) : (env_count += 1) {}
468496
const envp = @ptrCast([*][*:0]u8, c_envp)[0..env_count];
@@ -474,11 +502,11 @@ fn main(c_argc: i32, c_argv: [*][*:0]u8, c_envp: [*:null]?[*:0]u8) callconv(.C)
474502
expandStackSize(phdrs);
475503
}
476504

477-
return @call(.{ .modifier = .always_inline }, callMainWithArgs, .{ @intCast(usize, c_argc), c_argv, envp });
505+
return @call(.{ .modifier = .always_inline }, callMainWithArgs, .{ @intCast(usize, c_argc), @ptrCast([*][*:0]u8, c_argv), envp });
478506
}
479507

480-
fn mainWithoutEnv(c_argc: i32, c_argv: [*][*:0]u8) callconv(.C) usize {
481-
std.os.argv = c_argv[0..@intCast(usize, c_argc)];
508+
fn mainWithoutEnv(c_argc: c_int, c_argv: [*c][*c]u8) callconv(.C) c_int {
509+
std.os.argv = @ptrCast([*][*:0]u8, c_argv)[0..@intCast(usize, c_argc)];
482510
return @call(.{ .modifier = .always_inline }, callMain, .{});
483511
}
484512

lib/test_runner.zig

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ var log_err_count: usize = 0;
88

99
pub fn main() void {
1010
if (builtin.zig_backend != .stage1 and
11-
(builtin.zig_backend != .stage2_llvm or builtin.cpu.arch == .wasm32))
11+
(builtin.zig_backend != .stage2_llvm or builtin.cpu.arch == .wasm32) and
12+
builtin.zig_backend != .stage2_c)
1213
{
1314
return main2() catch @panic("test failure");
1415
}

src/Compilation.zig

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3103,13 +3103,16 @@ fn processOneJob(comp: *Compilation, job: Job) !void {
31033103
.decl_index = decl_index,
31043104
.decl = decl,
31053105
.fwd_decl = fwd_decl.toManaged(gpa),
3106-
.typedefs = c_codegen.TypedefMap.initContext(gpa, .{
3107-
.mod = module,
3108-
}),
3106+
.typedefs = c_codegen.TypedefMap.initContext(gpa, .{ .mod = module }),
31093107
.typedefs_arena = typedefs_arena.allocator(),
31103108
};
3111-
defer dg.fwd_decl.deinit();
3112-
defer dg.typedefs.deinit();
3109+
defer {
3110+
for (dg.typedefs.values()) |typedef| {
3111+
module.gpa.free(typedef.rendered);
3112+
}
3113+
dg.typedefs.deinit();
3114+
dg.fwd_decl.deinit();
3115+
}
31133116

31143117
c_codegen.genHeader(&dg) catch |err| switch (err) {
31153118
error.AnalysisFail => {

0 commit comments

Comments
 (0)