mirror of
https://github.com/ziglang/zig.git
synced 2024-12-11 21:56:27 +00:00
CBE: implement c varargs
Removed some backend test skip checks for things disabled in std.
This commit is contained in:
parent
597e8011f7
commit
57f6adf85d
@ -5,6 +5,7 @@
|
||||
#endif
|
||||
#include <float.h>
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
@ -211,6 +211,15 @@ const reserved_idents = std.ComptimeStringMap(void, .{
|
||||
.{ "volatile", {} },
|
||||
.{ "while ", {} },
|
||||
|
||||
// stdarg.h
|
||||
.{ "va_start", {} },
|
||||
.{ "va_arg", {} },
|
||||
.{ "va_end", {} },
|
||||
.{ "va_copy", {} },
|
||||
|
||||
// stddef.h
|
||||
.{ "offsetof", {} },
|
||||
|
||||
// windows.h
|
||||
.{ "max", {} },
|
||||
.{ "min", {} },
|
||||
@ -2952,10 +2961,10 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
|
||||
.error_set_has_value => return f.fail("TODO: C backend: implement error_set_has_value", .{}),
|
||||
.vector_store_elem => return f.fail("TODO: C backend: implement vector_store_elem", .{}),
|
||||
|
||||
.c_va_arg => return f.fail("TODO implement c_va_arg", .{}),
|
||||
.c_va_copy => return f.fail("TODO implement c_va_copy", .{}),
|
||||
.c_va_end => return f.fail("TODO implement c_va_end", .{}),
|
||||
.c_va_start => return f.fail("TODO implement c_va_start", .{}),
|
||||
.c_va_start => try airCVaStart(f, inst),
|
||||
.c_va_arg => try airCVaArg(f, inst),
|
||||
.c_va_end => try airCVaEnd(f, inst),
|
||||
.c_va_copy => try airCVaCopy(f, inst),
|
||||
// zig fmt: on
|
||||
};
|
||||
if (result_value == .new_local) {
|
||||
@ -6862,6 +6871,82 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
return local;
|
||||
}
|
||||
|
||||
fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
if (f.liveness.isUnused(inst)) return .none;
|
||||
|
||||
const inst_ty = f.air.typeOfIndex(inst);
|
||||
const fn_cty = try f.typeToCType(f.object.dg.decl.?.ty, .complete);
|
||||
|
||||
const param_len = fn_cty.castTag(.varargs_function).?.data.param_types.len;
|
||||
if (param_len == 0)
|
||||
return f.fail("CBE: C requires at least one runtime argument for varargs functions", .{});
|
||||
|
||||
const writer = f.object.writer();
|
||||
const local = try f.allocLocal(inst, inst_ty);
|
||||
try writer.writeAll("va_start(*(va_list *)&");
|
||||
try f.writeCValue(writer, local, .Other);
|
||||
try writer.writeAll(", ");
|
||||
try f.writeCValue(writer, .{ .arg = param_len - 1 }, .FunctionArgument);
|
||||
try writer.writeAll(");\n");
|
||||
return local;
|
||||
}
|
||||
|
||||
fn airCVaArg(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
const ty_op = f.air.instructions.items(.data)[inst].ty_op;
|
||||
if (f.liveness.isUnused(inst)) {
|
||||
try reap(f, inst, &.{ty_op.operand});
|
||||
return .none;
|
||||
}
|
||||
|
||||
const inst_ty = f.air.typeOfIndex(inst);
|
||||
const va_list = try f.resolveInst(ty_op.operand);
|
||||
try reap(f, inst, &.{ty_op.operand});
|
||||
|
||||
const writer = f.object.writer();
|
||||
const local = try f.allocLocal(inst, inst_ty);
|
||||
try f.writeCValue(writer, local, .Other);
|
||||
try writer.writeAll(" = va_arg(*(va_list *)");
|
||||
try f.writeCValue(writer, va_list, .Other);
|
||||
try writer.writeAll(", ");
|
||||
try f.renderType(writer, f.air.getRefType(ty_op.ty));
|
||||
try writer.writeAll(");\n");
|
||||
return local;
|
||||
}
|
||||
|
||||
fn airCVaEnd(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
const un_op = f.air.instructions.items(.data)[inst].un_op;
|
||||
|
||||
const va_list = try f.resolveInst(un_op);
|
||||
try reap(f, inst, &.{un_op});
|
||||
|
||||
const writer = f.object.writer();
|
||||
try writer.writeAll("va_end(*(va_list *)");
|
||||
try f.writeCValue(writer, va_list, .Other);
|
||||
try writer.writeAll(");\n");
|
||||
return .none;
|
||||
}
|
||||
|
||||
fn airCVaCopy(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
const ty_op = f.air.instructions.items(.data)[inst].ty_op;
|
||||
if (f.liveness.isUnused(inst)) {
|
||||
try reap(f, inst, &.{ty_op.operand});
|
||||
return .none;
|
||||
}
|
||||
|
||||
const inst_ty = f.air.typeOfIndex(inst);
|
||||
const va_list = try f.resolveInst(ty_op.operand);
|
||||
try reap(f, inst, &.{ty_op.operand});
|
||||
|
||||
const writer = f.object.writer();
|
||||
const local = try f.allocLocal(inst, inst_ty);
|
||||
try writer.writeAll("va_copy(*(va_list *)&");
|
||||
try f.writeCValue(writer, local, .Other);
|
||||
try writer.writeAll(", *(va_list *)");
|
||||
try f.writeCValue(writer, va_list, .Other);
|
||||
try writer.writeAll(");\n");
|
||||
return local;
|
||||
}
|
||||
|
||||
fn toMemoryOrder(order: std.builtin.AtomicOrder) [:0]const u8 {
|
||||
return switch (order) {
|
||||
// Note: unordered is actually even less atomic than relaxed
|
||||
|
@ -96,10 +96,9 @@ fn doNothingWithFirstArg(args: anytype) void {
|
||||
test "simple variadic function" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.cpu.arch == .aarch64 and builtin.os.tag != .macos and builtin.zig_backend == .stage2_llvm) {
|
||||
if (builtin.cpu.arch == .aarch64 and builtin.os.tag != .macos) {
|
||||
// https://github.com/ziglang/zig/issues/14096
|
||||
return error.SkipZigTest;
|
||||
}
|
||||
@ -124,8 +123,10 @@ test "simple variadic function" {
|
||||
}
|
||||
};
|
||||
|
||||
try std.testing.expectEqual(@as(c_int, 0), S.simple(@as(c_int, 0)));
|
||||
try std.testing.expectEqual(@as(c_int, 1024), S.simple(@as(c_int, 1024)));
|
||||
if (builtin.zig_backend != .stage2_c) { // C doesn't support varargs without a preceding runtime arg.
|
||||
try std.testing.expectEqual(@as(c_int, 0), S.simple(@as(c_int, 0)));
|
||||
try std.testing.expectEqual(@as(c_int, 1024), S.simple(@as(c_int, 1024)));
|
||||
}
|
||||
try std.testing.expectEqual(@as(c_int, 0), S.add(0));
|
||||
try std.testing.expectEqual(@as(c_int, 1), S.add(1, @as(c_int, 1)));
|
||||
try std.testing.expectEqual(@as(c_int, 3), S.add(2, @as(c_int, 1), @as(c_int, 2)));
|
||||
@ -134,10 +135,9 @@ test "simple variadic function" {
|
||||
test "variadic functions" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.cpu.arch == .aarch64 and builtin.os.tag != .macos and builtin.zig_backend == .stage2_llvm) {
|
||||
if (builtin.cpu.arch == .aarch64 and builtin.os.tag != .macos) {
|
||||
// https://github.com/ziglang/zig/issues/14096
|
||||
return error.SkipZigTest;
|
||||
}
|
||||
@ -178,10 +178,9 @@ test "variadic functions" {
|
||||
test "copy VaList" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.cpu.arch == .aarch64 and builtin.os.tag != .macos and builtin.zig_backend == .stage2_llvm) {
|
||||
if (builtin.cpu.arch == .aarch64 and builtin.os.tag != .macos) {
|
||||
// https://github.com/ziglang/zig/issues/14096
|
||||
return error.SkipZigTest;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user