Skip to content

Instantly share code, notes, and snippets.

@carlos4242
Created March 8, 2019 17:44
Show Gist options
  • Save carlos4242/f882c9f1213ef006feb6984acef291d7 to your computer and use it in GitHub Desktop.
Save carlos4242/f882c9f1213ef006feb6984acef291d7 to your computer and use it in GitHub Desktop.
diff --git a/lib/Target/AVR/AVRISelLowering.cpp b/lib/Target/AVR/AVRISelLowering.cpp
index fa8b5d4d3d7..1ff97910e4d 100644
--- a/lib/Target/AVR/AVRISelLowering.cpp
+++ b/lib/Target/AVR/AVRISelLowering.cpp
@@ -1307,32 +1307,36 @@ SDValue AVRTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
InVals);
}
-/// Reverse splitted return values to get the "big endian" format required
+/// Reverse splitted return values to "big endian" order
+/// so that when registers are assigned from standard CConv
+/// we end up with the format required
/// to agree with the calling convention ABI.
-static void ReverseArgumentsToBigEndian(MachineFunction &MF,
- SmallVector<CCValAssign, 16> &RVLocs) {
- if (RVLocs.size() > 1) {
- // Some hackery because SelectionDAGBuilder does not split
- // up arguments properly
- Type *retType = MF.getFunction().getReturnType();
- if (retType->isStructTy()) {
- if (retType->getNumContainedTypes() > 1 &&
- retType->getNumContainedTypes() > RVLocs.size()) {
- for (unsigned i = 0, pos = 0;
- i < retType->getNumContainedTypes(); ++i) {
- Type *field = retType->getContainedType(i);
- if(field->isIntegerTy() && field->getIntegerBitWidth() > 16) {
- int Size = field->getIntegerBitWidth() / 16;
- std::reverse(RVLocs.begin()+ pos, RVLocs.end() + pos + Size);
- pos += Size;
- } else {
- pos++;
- }
+static void ReverseReturnValuePartsToEnsureLittleEndian(
+ MachineFunction &MF,
+ SmallVector<CCValAssign, 16> &RVLocs) {
+
+ // Some hackery because SelectionDAGBuilder does not split
+ // up arguments properly
+ Type *retType = MF.getFunction().getReturnType();
+ if (retType->isStructTy()) {
+ // For structs we need more advanced rearrangement.
+ if (retType->getNumContainedTypes() > 1 &&
+ retType->getNumContainedTypes() > RVLocs.size()) {
+ for (unsigned i = 0, pos = 0;
+ i < retType->getNumContainedTypes(); ++i) {
+ Type *field = retType->getContainedType(i);
+ if(field->isIntegerTy() && field->getIntegerBitWidth() > 16) {
+ int Size = field->getIntegerBitWidth() / 16;
+ std::reverse(RVLocs.begin()+ pos, RVLocs.end() + pos + Size);
+ pos += Size;
+ } else {
+ pos++;
}
}
- } else {
- std::reverse(RVLocs.begin(), RVLocs.end());
}
+ } else {
+ // For scalar type returns, a simple reversal is fine.
+ std::reverse(RVLocs.begin(), RVLocs.end());
}
}
@@ -1353,6 +1357,11 @@ SDValue AVRTargetLowering::LowerCallResult(
auto CCFunction = CCAssignFnForReturn(CallConv);
CCInfo.AnalyzeCallResult(Ins, CCFunction);
+ if (CallConv != CallingConv::AVR_BUILTIN && RVLocs.size() > 1) {
+ ReverseReturnValuePartsToEnsureLittleEndian(
+ DAG.getMachineFunction(), RVLocs);
+ }
+
// Copy all of the result registers out of their specified physreg.
for (CCValAssign const &RVLoc : RVLocs) {
Chain = DAG.getCopyFromReg(Chain, dl, RVLoc.getLocReg(), RVLoc.getValVT(),
@@ -1411,14 +1420,16 @@ AVRTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
// If this is the first return lowered for this function, add the regs to
// the liveout set for the function.
MachineFunction &MF = DAG.getMachineFunction();
- unsigned e = RVLocs.size();
- // Reverse splitted return values to get the "big endian" format required
- // to agree with the calling convention ABI.
- ReverseArgumentsToBigEndian(MF, RVLocs);
+ if (RVLocs.size() > 1) {
+ // Reverse splitted return values to get the "big endian" format required
+ // to agree with the calling convention ABI.
+ ReverseReturnValuePartsToEnsureLittleEndian(MF, RVLocs);
+ }
SDValue Flag;
SmallVector<SDValue, 4> RetOps(1, Chain);
+ unsigned e = RVLocs.size();
// Copy the result values into the output registers.
for (unsigned i = 0; i != e; ++i) {
CCValAssign &VA = RVLocs[i];
diff --git a/test/CodeGen/AVR/call-avr-rust-issue-130-regression.ll b/test/CodeGen/AVR/call-avr-rust-issue-130-regression.ll
new file mode 100644
index 00000000000..2c2de5e6359
--- /dev/null
+++ b/test/CodeGen/AVR/call-avr-rust-issue-130-regression.ll
@@ -0,0 +1,61 @@
+; RUN: llc -O1 < %s -march=avr | FileCheck %s
+
+; CHECK-LABEL: setServoAngle1
+define hidden i32 @setServoAngle1(i32) local_unnamed_addr {
+entry:
+ %1 = mul i32 %0, 19
+; CHECK: ldi r18, 19
+; CHECK: ldi r19, 0
+; CHECK: ldi r20, 0
+; CHECK: ldi r21, 0
+; CHECK: call __mulsi3
+; CHECK: ret
+ ret i32 %1
+}
+
+; CHECK-LABEL: setServoAngle2
+define hidden i16 @setServoAngle2(i32) local_unnamed_addr {
+entry:
+ %1 = mul i32 %0, 19
+; CHECK: ldi r18, 19
+; CHECK: ldi r19, 0
+; CHECK: ldi r20, 0
+; CHECK: ldi r21, 0
+; CHECK: call __mulsi3
+ %2 = trunc i32 %1 to i16
+; CHECK: mov r24, r22
+; CHECK: mov r25, r23
+; CHECK: ret
+ ret i16 %2
+}
+
+; CHECK-LABEL: setServoAngle3
+define hidden i32 @setServoAngle3(i32) local_unnamed_addr {
+entry:
+ %1 = call i32 @myExternalFunction1(i32 %0, i32 119)
+; CHECK: ldi r18, 119
+; CHECK: ldi r19, 0
+; CHECK: ldi r20, 0
+; CHECK: ldi r21, 0
+; CHECK: call myExternalFunction1
+; CHECK: ret
+ ret i32 %1
+}
+
+; CHECK-LABEL: setServoAngle4
+define hidden i16 @setServoAngle4(i32) local_unnamed_addr {
+entry:
+ %1 = call i32 @myExternalFunction1(i32 %0, i32 119)
+; CHECK: ldi r18, 119
+; CHECK: ldi r19, 0
+; CHECK: ldi r20, 0
+; CHECK: ldi r21, 0
+; CHECK: call myExternalFunction1
+ %2 = trunc i32 %1 to i16
+; CHECK: mov r24, r22
+; CHECK: mov r25, r23
+; CHECK: ret
+ ret i16 %2
+}
+
+declare i32 @myExternalFunction1(i32, i32)
diff --git a/test/CodeGen/AVR/directmem.ll b/test/CodeGen/AVR/directmem.ll
index d0674cbc459..de78dde4558 100644
--- a/test/CodeGen/AVR/directmem.ll
+++ b/test/CodeGen/AVR/directmem.ll
@@ -84,6 +84,11 @@ define i16 @global16_load() {
define void @array16_store() {
; CHECK-LABEL: array16_store:
+; CHECK: ldi [[REG1:r[0-9]+]], 221
+; CHECK: ldi [[REG2:r[0-9]+]], 170
+; CHECK: sts int.array+5, [[REG2]]
+; CHECK: sts int.array+4, [[REG1]]
+
; CHECK: ldi [[REG1:r[0-9]+]], 204
; CHECK: ldi [[REG2:r[0-9]+]], 170
; CHECK: sts int.array+3, [[REG2]]
@@ -94,11 +99,6 @@ define void @array16_store() {
; CHECK: sts int.array+1, [[REG2]]
; CHECK: sts int.array, [[REG1]]
-
-; CHECK: ldi [[REG1:r[0-9]+]], 221
-; CHECK: ldi [[REG2:r[0-9]+]], 170
-; CHECK: sts int.array+5, [[REG2]]
-; CHECK: sts int.array+4, [[REG1]]
store i16 43707, i16* getelementptr inbounds ([3 x i16], [3 x i16]* @int.array, i32 0, i64 0)
store i16 43724, i16* getelementptr inbounds ([3 x i16], [3 x i16]* @int.array, i32 0, i64 1)
store i16 43741, i16* getelementptr inbounds ([3 x i16], [3 x i16]* @int.array, i32 0, i64 2)
@@ -152,6 +152,14 @@ define i32 @global32_load() {
define void @array32_store() {
; CHECK-LABEL: array32_store:
+; CHECK: ldi [[REG1:r[0-9]+]], 170
+; CHECK: ldi [[REG2:r[0-9]+]], 153
+; CHECK: sts long.array+11, [[REG2]]
+; CHECK: sts long.array+10, [[REG1]]
+; CHECK: ldi [[REG1:r[0-9]+]], 204
+; CHECK: ldi [[REG2:r[0-9]+]], 187
+; CHECK: sts long.array+9, [[REG2]]
+; CHECK: sts long.array+8, [[REG1]]
; CHECK: ldi [[REG1:r[0-9]+]], 102
; CHECK: ldi [[REG2:r[0-9]+]], 85
; CHECK: sts long.array+7, [[REG2]]
@@ -168,14 +176,6 @@ define void @array32_store() {
; CHECK: ldi [[REG2:r[0-9]+]], 13
; CHECK: sts long.array+1, [[REG2]]
; CHECK: sts long.array, [[REG1]]
-; CHECK: ldi [[REG1:r[0-9]+]], 170
-; CHECK: ldi [[REG2:r[0-9]+]], 153
-; CHECK: sts long.array+11, [[REG2]]
-; CHECK: sts long.array+10, [[REG1]]
-; CHECK: ldi [[REG1:r[0-9]+]], 204
-; CHECK: ldi [[REG2:r[0-9]+]], 187
-; CHECK: sts long.array+9, [[REG2]]
-; CHECK: sts long.array+8, [[REG1]]
store i32 2887454020, i32* getelementptr inbounds ([3 x i32], [3 x i32]* @long.array, i32 0, i64 0)
store i32 1432778632, i32* getelementptr inbounds ([3 x i32], [3 x i32]* @long.array, i32 0, i64 1)
store i32 2578103244, i32* getelementptr inbounds ([3 x i32], [3 x i32]* @long.array, i32 0, i64 2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment