Skip to content

CodeGen optimisation: return structs of two pointers in a0 and a1 #177

@xdoardo

Description

@xdoardo

Quoting RISC-V's ABI:

Values are returned from functions in integer registers a0 and a1 [...] Other return values
that fit into two pointer-words are returned in a0 and a1.

Our current behaviour is, however, different. The following C snippet

struct X {
  int  *one;
  int  *two;
};

struct X __attribute__((cheri_ccall)) emptyX(void) {
  struct X Res = { 0, 0 };
  return Res;
}

void myFn(void) {
  struct X x = emptyX();
  return;
}

compiled with clang -target riscv32cheriot-unknown-cheriotrtos -mcpu=cheriot -mabi=cheriot -O0 test.c -S -emit-llvm returns:

; Function Attrs: noinline nounwind optnone
define dso_local chericcallcc void @emptyX(ptr addrspace(200) dead_on_unwind noalias writable sret(%struct.X) align 8 %0) addrspace(200) #0 {
  %2 = alloca ptr addrspace(200), align 8, addrspace(200)
  store ptr addrspace(200) %0, ptr addrspace(200) %2, align 8
  call void @llvm.memset.p200.i32(ptr addrspace(200) align 8 %0, i8 0, i32 16, i1 false)
  ret void
}

; Function Attrs: noinline nounwind optnone
define dso_local void @myFn() addrspace(200) #0 {
  %1 = alloca %struct.X, align 8, addrspace(200)
  notail call chericcallcc void @emptyX(ptr addrspace(200) dead_on_unwind writable sret(%struct.X) align 8 %1)
  ret void
}

where a pointer to the memory location of the result is indirectly passed to the callee as a synthesised argument; this is due to (ABIArgInfo Kind=Indirect Align=8 ByVal=0 Realign=0) being attributed to the return value in this function.

Ideally, we'd want the codegen step to make use of the second register described by the ABI and return the struct value in a0 and a1.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions