Backend : What am I missing here

Hi,

While working on adding newlib to my backend I hit the following assert :

Assertion failed: BestRC && “Couldn’t find the register class”, file TargetRegisterInfo.cpp, line 112

The following llvm causes this :

define void @specialBreak(i8* %out) nounwind {
entry:
%out.addr = alloca i8*, align 4
store i8* %out, i8** %out.addr, align 4
%0 = load i8** %out.addr, align 4
%call = call signext i8 @cnv(i8* %0)
%1 = load i8** %out.addr, align 4
%arrayidx = getelementptr inbounds i8* %1, i32 0
store i8 %call, i8* %arrayidx, align 1
ret void
}

declare signext i8 @cnv(i8*)

Now originally (at the time I hadn’t added 8/16 bit register support) I had made the calling convention return values promote i8 & i16 to i32 :

def RetCC_test : CallingConv<[
// Promote i8 returns to i32.
CCIfType<[i8], CCPromoteToType>,
// Promote i16 returns to i32.
CCIfType<[i16], CCPromoteToType>,

// i32 are returned in register R0
CCIfType<[i32], CCAssignToReg<[R0L]>>
]>;

I’ve now changed this to :

def RetCC_test : CallingConv<[
// i8 are returned in register R0
CCIfType<[i8], CCAssignToReg<[R0B]>>,
// i16 are returned in register R0
CCIfType<[i16], CCAssignToReg<[R0W]>>,
// i32 are returned in register R0
CCIfType<[i32], CCAssignToReg<[R0L]>>
]>;

Which has stopped the assert and produced valid code.

I`m happy to leave the return value definitions as they are now, but was wondering if it perhaps points to something I’ve missed elsewhere as to why the original promoted convention would fail.

Lee

Hi Lee,

Hi,

While working on adding newlib to my backend I hit the following assert :

Assertion failed: BestRC && "Couldn't find the register class", file TargetRegisterInfo.cpp, line 112

The following llvm causes this :

define void @specialBreak(i8* %out) nounwind {
entry:
  %out.addr = alloca i8*, align 4
  store i8* %out, i8** %out.addr, align 4
  %0 = load i8** %out.addr, align 4
  %call = call signext i8 @cnv(i8* %0)
  %1 = load i8** %out.addr, align 4
  %arrayidx = getelementptr inbounds i8* %1, i32 0
  store i8 %call, i8* %arrayidx, align 1
  ret void
}

declare signext i8 @cnv(i8*)

Now originally (at the time I hadn't added 8/16 bit register support) I had made the calling convention return values promote i8 & i16 to i32 :

def RetCC_test : CallingConv<[
  // Promote i8 returns to i32.
  CCIfType<[i8], CCPromoteToType<i32>>,
  // Promote i16 returns to i32.
  CCIfType<[i16], CCPromoteToType<i32>>,

  // i32 are returned in register R0
  CCIfType<[i32], CCAssignToReg<[R0L]>>
]>;

>>> if you do not override getTypeForExtArgOrReturn, i8, i16 will be promoted to i32 automatically.

I've now changed this to :

def RetCC_test : CallingConv<[
  // i8 are returned in register R0
  CCIfType<[i8], CCAssignToReg<[R0B]>>,
  // i16 are returned in register R0
  CCIfType<[i16], CCAssignToReg<[R0W]>>,
  // i32 are returned in register R0
  CCIfType<[i32], CCAssignToReg<[R0L]>>
]>;

Which has stopped the assert and produced valid code.

I`m happy to leave the return value definitions as they are now, but was wondering if it perhaps points to something I've missed elsewhere as to why the original promoted convention would fail.

  >>> I suggest you use gdb to see what's the physical reg num, and you can check the generated XXXGenRegisterInfo.inc, maybe it will help you to find out what you are missing.