LLVM uses the exact reverse order of return registers as MSPGCC. This patch fixes this.
Note that I did not find a clean way to do this using tablegen so the method I used might look like a hack :-)
Differential D1046
Reverse the order of allocation of return value registers to be compatible with MSPGCC jobnoorman on Jun 26 2013, 9:20 AM. Authored by
Details
LLVM uses the exact reverse order of return registers as MSPGCC. This patch fixes this. Note that I did not find a clean way to do this using tablegen so the method I used might look like a hack :-)
Diff Detail Event TimelineComment Actions The register allocation order is defined by RetCC_MSP430 entry inside MSP430CallingConv.td Comment Actions Yes, I have been playing around with the calling convention definitions but I think there is no way to match MSPGCC's return value convention. Let me try to explain what I think the problem is. First and for all, before the ISel phase even begins, all values larger than i16 are lowered (is that the correct terminology?) to a number of i16 values. This means using something like CCIfType<[i64], CCAssignToReg<[R12W, R13W, R14W, R15W]>> doesn't do anything since i64 types simply do not exist any more at this point. So returning a value larger than i16 will result in returning multiple i16 values and I have found no way to convince tablegen to put those in the correct registers. Here is MSPGCC's return value calling convention (I'll use little endian ordering of the registers):
Currently, LLVM uses the following rule: CCIfType<[i16], CCAssignToReg<[R15W, R14W, R13W, R12W]>> which produces this register assignment:
Although this is the exact reverse of what MSPGCC does, we cannot simply reverse the tablegen rule to become CCIfType<[i16], CCAssignToReg<[R12W, R13W, R14W, R15W]>> since this will produce the following register assignment:
Therefore, my patch will simply reverse the order of allocated registers after the tablegen rule has been applied which always does the correct thing. Comment Actions This is hackish solution, because it seems to the fix outcome of the problem, but not the problem by itself. It looks like we need to change the splitting of i32 / i64 here. Because otherwise the difference might be seen in other places.... (what's about e.g. i32 stores?) Comment Actions I completely agree this is a hackish solution and we need something better. However, I do not think there is a problem with the splitting of i32/i64 since it mostly does what it should do. For example, loads/stores of these values work correctly since codegen knows we are little endian. Also, for the calling convention, I think codegen is doing the "logical" thing. Return values are assigned to R15-R12 and codegen assigns the return value in little endian byte order to these registers (R15=LSB, r12=MSB). The thing is that the calling convention used by MSPGCC is kind of weird: registers should also be picked in the order R15-R12 but then the actual return value should be assigned to these registers in big endian byte order (R15=MSB, R12=LSB). Also note that exactly the same happens for i32/i64 arguments. This is actually a bigger problem since my hack won't work for arguments :-) After looking a bit longer at the code, I don't really see a clean way to solve this problem. Do you think it it might be a good option to implement the calling convention "by hand"? That is, without using tablegen. |