authorgravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-04-22 21:10:52-07:00
committergravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-06-13 02:19:39-07:00
logf34dcd067b6e9783a53f007746309bb1f635fbf0
treeedb44459379c295b4d32b443fd25750d05464211
parentfcafaae747c0d032401ca7936b667f5dfcf0466b
signaturelock-open Commit is signed but in an unrecognized format.

riscv: basic libc varargs


1 files changed, 43 insertions(+), 3 deletions(-)

src/arch/riscv64/CodeGen.zig+43-3
...@@ -774,7 +774,7 @@ pub fn generate(...@@ -774,7 +774,7 @@ pub fn generate(
774 );774 );
775775
776 const fn_info = zcu.typeToFunc(fn_type).?;776 const fn_info = zcu.typeToFunc(fn_type).?;
777 var call_info = function.resolveCallingConventionValues(fn_info) catch |err| switch (err) {777 var call_info = function.resolveCallingConventionValues(fn_info, &.{}) catch |err| switch (err) {
778 error.CodegenFail => return Result{ .fail = function.err_msg.? },778 error.CodegenFail => return Result{ .fail = function.err_msg.? },
779 error.OutOfRegisters => return Result{779 error.OutOfRegisters => return Result{
780 .fail = try ErrorMsg.create(gpa, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}),780 .fail = try ErrorMsg.create(gpa, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}),
...@@ -3552,7 +3552,14 @@ fn genCall(...@@ -3552,7 +3552,14 @@ fn genCall(
3552 };3552 };
35533553
3554 const fn_info = zcu.typeToFunc(fn_ty).?;3554 const fn_info = zcu.typeToFunc(fn_ty).?;
3555 var call_info = try self.resolveCallingConventionValues(fn_info);3555
3556 const allocator = self.gpa;
3557
3558 const var_args = try allocator.alloc(Type, args.len - fn_info.param_types.len);
3559 defer allocator.free(var_args);
3560 for (var_args, arg_tys[fn_info.param_types.len..]) |*var_arg, arg_ty| var_arg.* = arg_ty;
3561
3562 var call_info = try self.resolveCallingConventionValues(fn_info, var_args);
3556 defer call_info.deinit(self);3563 defer call_info.deinit(self);
35573564
3558 // We need a properly aligned and sized call frame to be able to call this function.3565 // We need a properly aligned and sized call frame to be able to call this function.
...@@ -5318,16 +5325,19 @@ const CallMCValues = struct {...@@ -5318,16 +5325,19 @@ const CallMCValues = struct {
5318fn resolveCallingConventionValues(5325fn resolveCallingConventionValues(
5319 self: *Self,5326 self: *Self,
5320 fn_info: InternPool.Key.FuncType,5327 fn_info: InternPool.Key.FuncType,
5328 var_args: []const Type,
5321) !CallMCValues {5329) !CallMCValues {
5322 const zcu = self.bin_file.comp.module.?;5330 const zcu = self.bin_file.comp.module.?;
5323 const ip = &zcu.intern_pool;5331 const ip = &zcu.intern_pool;
53245332
5325 const param_types = try self.gpa.alloc(Type, fn_info.param_types.len);5333 const param_types = try self.gpa.alloc(Type, fn_info.param_types.len + var_args.len);
5326 defer self.gpa.free(param_types);5334 defer self.gpa.free(param_types);
53275335
5328 for (param_types[0..fn_info.param_types.len], fn_info.param_types.get(ip)) |*dest, src| {5336 for (param_types[0..fn_info.param_types.len], fn_info.param_types.get(ip)) |*dest, src| {
5329 dest.* = Type.fromInterned(src);5337 dest.* = Type.fromInterned(src);
5330 }5338 }
5339 for (param_types[fn_info.param_types.len..], var_args) |*param_ty, arg_ty|
5340 param_ty.* = self.promoteVarArg(arg_ty);
53315341
5332 const cc = fn_info.cc;5342 const cc = fn_info.cc;
5333 var result: CallMCValues = .{5343 var result: CallMCValues = .{
...@@ -5514,3 +5524,33 @@ pub fn errUnionErrorOffset(payload_ty: Type, zcu: *Module) u64 {...@@ -5514,3 +5524,33 @@ pub fn errUnionErrorOffset(payload_ty: Type, zcu: *Module) u64 {
5514 return 0;5524 return 0;
5515 }5525 }
5516}5526}
5527
5528fn promoteInt(self: *Self, ty: Type) Type {
5529 const mod = self.bin_file.comp.module.?;
5530 const int_info: InternPool.Key.IntType = switch (ty.toIntern()) {
5531 .bool_type => .{ .signedness = .unsigned, .bits = 1 },
5532 else => if (ty.isAbiInt(mod)) ty.intInfo(mod) else return ty,
5533 };
5534 for ([_]Type{
5535 Type.c_int, Type.c_uint,
5536 Type.c_long, Type.c_ulong,
5537 Type.c_longlong, Type.c_ulonglong,
5538 }) |promote_ty| {
5539 const promote_info = promote_ty.intInfo(mod);
5540 if (int_info.signedness == .signed and promote_info.signedness == .unsigned) continue;
5541 if (int_info.bits + @intFromBool(int_info.signedness == .unsigned and
5542 promote_info.signedness == .signed) <= promote_info.bits) return promote_ty;
5543 }
5544 return ty;
5545}
5546
5547fn promoteVarArg(self: *Self, ty: Type) Type {
5548 if (!ty.isRuntimeFloat()) return self.promoteInt(ty);
5549 switch (ty.floatBits(self.target.*)) {
5550 32, 64 => return Type.f64,
5551 else => |float_bits| {
5552 assert(float_bits == self.target.c_type_bit_size(.longdouble));
5553 return Type.c_longdouble;
5554 },
5555 }
5556}