Skip to content

Commit 09f5c29

Browse files
carlos4242dylanmckay
authored andcommitted
Add TargetLoweringInfo hook for explicitly setting the ABI calling convention endianess
Summary: The endianess used in the calling convention does not always match the endianess of the target on all architectures, namely AVR. When an argument is too large to be legalised by the architecture and is split for the ABI, a new hook TargetLoweringInfo::shouldSplitFunctionArgumentsAsLittleEndian is queried to find the endianess that function arguments must be laid out in. This approach was recommended by Eli Friedman. Originally reported in avr-rust/rust-legacy-fork#129. Patch by Carl Peto. Reviewers: bogner, t.p.northover, RKSimon, niravd Subscribers: JDevlieghere, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D62003
1 parent 64b3d65 commit 09f5c29

File tree

4 files changed

+64
-1
lines changed

4 files changed

+64
-1
lines changed

include/llvm/CodeGen/TargetLowering.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3538,6 +3538,15 @@ class TargetLowering : public TargetLoweringBase {
35383538
return false;
35393539
}
35403540

3541+
/// For some targets, an LLVM type must be broken down into multiple
3542+
/// smaller types. Usually the halves are ordered according to the endianness
3543+
/// but for some platform that would break. So this method will default to
3544+
/// matching the endianness but can be overridden.
3545+
virtual bool
3546+
shouldSplitFunctionArgumentsAsLittleEndian(const DataLayout &DL) const {
3547+
return DL.isLittleEndian();
3548+
}
3549+
35413550
/// Returns a 0 terminated array of registers that can be safely used as
35423551
/// scratch registers.
35433552
virtual const MCPhysReg *getScratchRegisters(CallingConv::ID CC) const {

lib/CodeGen/SelectionDAG/TargetLowering.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5846,7 +5846,7 @@ bool TargetLowering::expandMULO(SDNode *Node, SDValue &Result,
58465846
// being a legal type for the architecture and thus has to be split to
58475847
// two arguments.
58485848
SDValue Ret;
5849-
if (DAG.getDataLayout().isLittleEndian()) {
5849+
if (shouldSplitFunctionArgumentsAsLittleEndian(DAG.getDataLayout())) {
58505850
// Halves of WideVT are packed into registers in different order
58515851
// depending on platform endianness. This is usually handled by
58525852
// the C calling convention, but we can't defer to it in

lib/Target/AVR/AVRISelLowering.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,11 @@ class AVRTargetLowering : public TargetLowering {
128128
unsigned getRegisterByName(const char* RegName, EVT VT,
129129
SelectionDAG &DAG) const override;
130130

131+
bool shouldSplitFunctionArgumentsAsLittleEndian(const DataLayout &DL)
132+
const override {
133+
return false;
134+
}
135+
131136
private:
132137
SDValue getAVRCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue &AVRcc,
133138
SelectionDAG &DAG, SDLoc dl) const;
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
; RUN: llc -O1 < %s -march=avr | FileCheck %s
2+
3+
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
4+
target triple = "x86_64-apple-macosx10.9"
5+
6+
%Vs6UInt16 = type <{ i16 }>
7+
%Sb = type <{ i1 }>
8+
9+
define hidden void @setServoAngle(i16) {
10+
; CHECK-LABEL: entry
11+
entry:
12+
%adjustedAngle = alloca %Vs6UInt16, align 2
13+
%1 = bitcast %Vs6UInt16* %adjustedAngle to i8*
14+
%adjustedAngle._value = getelementptr inbounds %Vs6UInt16, %Vs6UInt16* %adjustedAngle, i32 0, i32 0
15+
store i16 %0, i16* %adjustedAngle._value, align 2
16+
17+
;print(unsignedInt: adjustedAngle &* UInt16(11))
18+
; breaks here
19+
%adjustedAngle._value2 = getelementptr inbounds %Vs6UInt16, %Vs6UInt16* %adjustedAngle, i32 0, i32 0
20+
%2 = load i16, i16* %adjustedAngle._value2, align 2
21+
22+
; CHECK: mov r22, r24
23+
; CHECK: mov r23, r25
24+
25+
; CHECK-DAG: ldi r20, 0
26+
; CHECK-DAG: ldi r21, 0
27+
; CHECK-DAG: ldi r18, 11
28+
; CHECK-DAG: ldi r19, 0
29+
30+
; CHECK: mov r24, r20
31+
; CHECK: mov r25, r21
32+
; CHECK: call __mulsi3
33+
%3 = call { i16, i1 } @llvm.umul.with.overflow.i16(i16 %2, i16 11)
34+
%4 = extractvalue { i16, i1 } %3, 0
35+
%5 = extractvalue { i16, i1 } %3, 1
36+
37+
; above code looks fine, how is it lowered?
38+
%6 = call i1 @printDefaultParam()
39+
call void @print(i16 %4, i1 %6)
40+
41+
; CHECK: ret
42+
ret void
43+
}
44+
45+
declare void @print(i16, i1)
46+
declare i1 @printDefaultParam()
47+
48+
; Function Attrs: nounwind readnone speculatable
49+
declare { i16, i1 } @llvm.umul.with.overflow.i16(i16, i16)

0 commit comments

Comments
 (0)