Created
March 8, 2019 17:44
-
-
Save carlos4242/f882c9f1213ef006feb6984acef291d7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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