Skip to content

Commit

Permalink
Pass FP values to printf
Browse files Browse the repository at this point in the history
On variadic function, it seems FP values are passed on GP registers.

RISC-V instruction: `fmv.x.d`
  • Loading branch information
tyfkda committed Dec 21, 2023
1 parent a9d83c2 commit a6c1139
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 3 deletions.
10 changes: 10 additions & 0 deletions src/cc/arch/riscv64/ir_riscv64.c
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,16 @@ static void ei_precall(IR *ir) {
static void ei_pusharg(IR *ir) {
assert(!(ir->opr1->flag & VRF_CONST));
if (ir->opr1->flag & VRF_FLONUM) {
#if VAARG_FP_AS_GP
if (ir->pusharg.fp_as_gp) {
switch (ir->opr1->vsize) {
case SZ_FLOAT: FMV_X_W(kReg64s[ir->pusharg.index], kFReg32s[ir->opr1->phys]); break;
case SZ_DOUBLE: FMV_X_D(kReg64s[ir->pusharg.index], kFReg64s[ir->opr1->phys]); break;
default: assert(false); break;
}
return;
}
#endif
// Assume parameter registers are arranged from index 0.
if (ir->pusharg.index != ir->opr1->phys) {
switch (ir->opr1->vsize) {
Expand Down
3 changes: 3 additions & 0 deletions src/cc/arch/riscv64/riscv64.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,9 @@
#define FCVT_D_S(o1, o2) EMIT_ASM("fcvt.d.s", o1, o2) // double <- float
#define FCVT_S_D(o1, o2) EMIT_ASM("fcvt.s.d", o1, o2) // float <- double

#define FMV_X_W(o1, o2) EMIT_ASM("fmv.x.w", o1, o2) // int <- float(hex)
#define FMV_X_D(o1, o2) EMIT_ASM("fmv.x.d", o1, o2) // int <- double(hex)

#define FEQ_D(o1, o2, o3) EMIT_ASM("feq.d", o1, o2, o3)
#define FEQ_S(o1, o2, o3) EMIT_ASM("feq.s", o1, o2, o3)
#define FLT_D(o1, o2, o3) EMIT_ASM("flt.d", o1, o2, o3)
Expand Down
18 changes: 17 additions & 1 deletion src/cc/backend/codegen_expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,9 @@ static VReg *gen_funcall(Expr *expr) {
int size;
bool stack_arg;
bool is_flo;
#if VAARG_FP_AS_GP
bool fp_as_gp;
#endif
} ArgInfo;

ArgInfo *arg_infos = NULL;
Expand All @@ -468,6 +471,13 @@ static VReg *gen_funcall(Expr *expr) {
assert(arg->type->kind != TY_ARRAY);
p->size = type_size(arg->type);
p->is_flo = is_flonum(arg->type);
#if VAARG_FP_AS_GP
p->fp_as_gp = false;
if (functype->func.vaargs && functype->func.params != NULL && i >= functype->func.params->len) {
p->is_flo = false;
p->fp_as_gp = true;
}
#endif
p->stack_arg = is_stack_param(arg->type);
#if VAARG_ON_STACK
if (functype->func.vaargs && functype->func.params != NULL && i >= functype->func.params->len)
Expand Down Expand Up @@ -517,7 +527,13 @@ static VReg *gen_funcall(Expr *expr) {
++iregarg;
int index = reg_arg_count - iregarg + arg_start;
assert(index < MAX_REG_ARGS);
new_ir_pusharg(vreg, index);
IR *ir = new_ir_pusharg(vreg, index);
#if !VAARG_FP_AS_GP
UNUSED(ir);
#else
if (p->fp_as_gp)
ir->pusharg.fp_as_gp = true;
#endif
}
} else {
enum VRegSize offset_type = 2; //{.size = 4, .align = 4}; // TODO:
Expand Down
6 changes: 5 additions & 1 deletion src/cc/backend/ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -252,11 +252,15 @@ void new_ir_tjmp(VReg *val, BB **bbs, size_t len) {
ir->tjmp.len = len;
}

void new_ir_pusharg(VReg *vreg, int index) {
IR *new_ir_pusharg(VReg *vreg, int index) {
assert(index >= 0);
IR *ir = new_ir(IR_PUSHARG);
ir->opr1 = vreg;
ir->pusharg.index = index;
#if VAARG_FP_AS_GP
ir->pusharg.fp_as_gp = false;
#endif
return ir;
}

IR *new_ir_precall(int arg_count, int stack_args_size) {
Expand Down
5 changes: 4 additions & 1 deletion src/cc/backend/ir.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,9 @@ typedef struct IR {
} precall;
struct {
int index;
#if VAARG_FP_AS_GP
bool fp_as_gp;
#endif
} pusharg;
struct {
const Name *label;
Expand Down Expand Up @@ -183,7 +186,7 @@ void new_ir_jmp(BB *bb); // Non-conditional jump
void new_ir_cjmp(VReg *opr1, VReg *opr2, enum ConditionKind cond, BB *bb); // Conditional jump
void new_ir_tjmp(VReg *val, BB **bbs, size_t len);
IR *new_ir_precall(int arg_count, int stack_args_size);
void new_ir_pusharg(VReg *vreg, int index);
IR *new_ir_pusharg(VReg *vreg, int index);
VReg *new_ir_call(const Name *label, bool global, VReg *freg, int total_arg_count,
int reg_arg_count, enum VRegSize result_size, int result_flag, IR *precall,
VReg **args, int vaarg_start);
Expand Down
5 changes: 5 additions & 0 deletions src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@
#define VAARG_ON_STACK 1
#endif

#if !defined(VAARG_FP_AS_GP) && XCC_TARGET_ARCH == XCC_ARCH_RISCV64
// Pass floating-point arguments in general-purpose registers for variadic arguments.
#define VAARG_FP_AS_GP 1
#endif

#if !defined(MANGLE_PREFIX) && XCC_TARGET_PLATFORM == XCC_PLATFORM_APPLE
#define MANGLE_PREFIX "_"
#endif
Expand Down

0 comments on commit a6c1139

Please sign in to comment.