1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 19:23:23 +01:00

AArch64: simplify calling conventions slightly.

We can eliminate the custom C++ code in favour of some TableGen to
check the same things. Functionality should be identical, except for a
buffer overrun that was present in the C++ code and meant webkit
failed if any small argument needed to be passed on the stack.

llvm-svn: 209636
This commit is contained in:
Tim Northover 2014-05-26 17:21:53 +00:00
parent 406287c5b7
commit fc1b1e8952
5 changed files with 44 additions and 128 deletions

View File

@ -1,94 +0,0 @@
//=== AArch64CallingConv.h - Custom Calling Convention Routines -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the custom routines for the AArch64 Calling Convention that
// aren't done by tablegen.
//
//===----------------------------------------------------------------------===//
#ifndef AArch64CALLINGCONV_H
#define AArch64CALLINGCONV_H
#include "AArch64InstrInfo.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/CodeGen/CallingConvLower.h"
#include "llvm/Target/TargetInstrInfo.h"
namespace llvm {
/// CC_AArch64_Custom_i1i8i16_Reg - customized handling of passing i1/i8/i16 via
/// register. Here, ValVT can be i1/i8/i16 or i32 depending on whether the
/// argument is already promoted and LocVT is i1/i8/i16. We only promote the
/// argument to i32 if we are sure this argument will be passed in register.
static bool CC_AArch64_Custom_i1i8i16_Reg(unsigned ValNo, MVT ValVT, MVT LocVT,
CCValAssign::LocInfo LocInfo,
ISD::ArgFlagsTy ArgFlags,
CCState &State,
bool IsWebKitJS = false) {
static const MCPhysReg RegList1[] = { AArch64::W0, AArch64::W1, AArch64::W2,
AArch64::W3, AArch64::W4, AArch64::W5,
AArch64::W6, AArch64::W7 };
static const MCPhysReg RegList2[] = { AArch64::X0, AArch64::X1, AArch64::X2,
AArch64::X3, AArch64::X4, AArch64::X5,
AArch64::X6, AArch64::X7 };
static const MCPhysReg WebKitRegList1[] = { AArch64::W0 };
static const MCPhysReg WebKitRegList2[] = { AArch64::X0 };
const MCPhysReg *List1 = IsWebKitJS ? WebKitRegList1 : RegList1;
const MCPhysReg *List2 = IsWebKitJS ? WebKitRegList2 : RegList2;
if (unsigned Reg = State.AllocateReg(List1, List2, 8)) {
// Customized extra section for handling i1/i8/i16:
// We need to promote the argument to i32 if it is not done already.
if (ValVT != MVT::i32) {
if (ArgFlags.isSExt())
LocInfo = CCValAssign::SExt;
else if (ArgFlags.isZExt())
LocInfo = CCValAssign::ZExt;
else
LocInfo = CCValAssign::AExt;
ValVT = MVT::i32;
}
// Set LocVT to i32 as well if passing via register.
LocVT = MVT::i32;
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
return true;
}
return false;
}
/// CC_AArch64_WebKit_JS_i1i8i16_Reg - customized handling of passing i1/i8/i16
/// via register. This behaves the same as CC_AArch64_Custom_i1i8i16_Reg, but only
/// uses the first register.
static bool CC_AArch64_WebKit_JS_i1i8i16_Reg(unsigned ValNo, MVT ValVT, MVT LocVT,
CCValAssign::LocInfo LocInfo,
ISD::ArgFlagsTy ArgFlags,
CCState &State) {
return CC_AArch64_Custom_i1i8i16_Reg(ValNo, ValVT, LocVT, LocInfo, ArgFlags,
State, true);
}
/// CC_AArch64_Custom_i1i8i16_Stack: customized handling of passing i1/i8/i16 on
/// stack. Here, ValVT can be i1/i8/i16 or i32 depending on whether the argument
/// is already promoted and LocVT is i1/i8/i16. If ValVT is already promoted,
/// it will be truncated back to i1/i8/i16.
static bool CC_AArch64_Custom_i1i8i16_Stack(unsigned ValNo, MVT ValVT, MVT LocVT,
CCValAssign::LocInfo LocInfo,
ISD::ArgFlagsTy ArgFlags,
CCState &State) {
unsigned Space = ((LocVT == MVT::i1 || LocVT == MVT::i8) ? 1 : 2);
unsigned Offset12 = State.AllocateStack(Space, Space);
ValVT = LocVT;
State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset12, LocVT, LocInfo));
return true;
}
} // End llvm namespace
#endif

View File

@ -18,6 +18,9 @@ class CCIfAlign<string Align, CCAction A> :
class CCIfBigEndian<CCAction A> :
CCIf<"State.getTarget().getDataLayout()->isBigEndian()", A>;
class CCIfUnallocated<string Reg, CCAction A> :
CCIf<"!State.isAllocated(AArch64::" # Reg # ")", A>;
//===----------------------------------------------------------------------===//
// ARM AAPCS64 Calling Convention
//===----------------------------------------------------------------------===//
@ -42,7 +45,7 @@ def CC_AArch64_AAPCS : CallingConv<[
// Handle i1, i8, i16, i32, i64, f32, f64 and v2f64 by passing in registers,
// up to eight each of GPR and FPR.
CCIfType<[i1, i8, i16], CCCustom<"CC_AArch64_Custom_i1i8i16_Reg">>,
CCIfType<[i1, i8, i16], CCIfUnallocated<"X7", CCPromoteToType<i32>>>,
CCIfType<[i32], CCAssignToRegWithShadow<[W0, W1, W2, W3, W4, W5, W6, W7],
[X0, X1, X2, X3, X4, X5, X6, X7]>>,
// i128 is split to two i64s, we can't fit half to register X7.
@ -117,7 +120,7 @@ def CC_AArch64_DarwinPCS : CallingConv<[
// Handle i1, i8, i16, i32, i64, f32, f64 and v2f64 by passing in registers,
// up to eight each of GPR and FPR.
CCIfType<[i1, i8, i16], CCCustom<"CC_AArch64_Custom_i1i8i16_Reg">>,
CCIfType<[i1, i8, i16], CCIfUnallocated<"X7", CCPromoteToType<i32>>>,
CCIfType<[i32], CCAssignToRegWithShadow<[W0, W1, W2, W3, W4, W5, W6, W7],
[X0, X1, X2, X3, X4, X5, X6, X7]>>,
// i128 is split to two i64s, we can't fit half to register X7.
@ -140,7 +143,8 @@ def CC_AArch64_DarwinPCS : CallingConv<[
CCAssignToReg<[Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7]>>,
// If more than will fit in registers, pass them on the stack instead.
CCIfType<[i1, i8, i16], CCCustom<"CC_AArch64_Custom_i1i8i16_Stack">>,
CCIfType<[i1, i8], CCAssignToStack<1, 1>>,
CCIfType<[i16], CCAssignToStack<2, 2>>,
CCIfType<[i32, f32], CCAssignToStack<4, 4>>,
CCIfType<[i64, f64, v1f64, v2f32, v1i64, v2i32, v4i16, v8i8],
CCAssignToStack<8, 8>>,
@ -168,7 +172,7 @@ def CC_AArch64_DarwinPCS_VarArg : CallingConv<[
// 32bit quantity as undef.
def CC_AArch64_WebKit_JS : CallingConv<[
// Handle i1, i8, i16, i32, and i64 passing in register X0 (W0).
CCIfType<[i1, i8, i16], CCCustom<"CC_AArch64_WebKit_JS_i1i8i16_Reg">>,
CCIfType<[i1, i8, i16], CCIfUnallocated<"X0", CCPromoteToType<i32>>>,
CCIfType<[i32], CCAssignToRegWithShadow<[W0], [X0]>>,
CCIfType<[i64], CCAssignToRegWithShadow<[X0], [W0]>>,

View File

@ -16,7 +16,6 @@
#include "AArch64.h"
#include "AArch64TargetMachine.h"
#include "AArch64Subtarget.h"
#include "AArch64CallingConv.h"
#include "MCTargetDesc/AArch64AddressingModes.h"
#include "llvm/CodeGen/CallingConvLower.h"
#include "llvm/CodeGen/FastISel.h"

View File

@ -14,7 +14,6 @@
#include "AArch64ISelLowering.h"
#include "AArch64PerfectShuffle.h"
#include "AArch64Subtarget.h"
#include "AArch64CallingConv.h"
#include "AArch64MachineFunctionInfo.h"
#include "AArch64TargetMachine.h"
#include "AArch64TargetObjectFile.h"
@ -1681,15 +1680,14 @@ SDValue AArch64TargetLowering::LowerFormalArguments(
EVT ActualVT = getValueType(CurOrigArg->getType(), /*AllowUnknown*/ true);
MVT ActualMVT = ActualVT.isSimple() ? ActualVT.getSimpleVT() : MVT::Other;
// If ActualMVT is i1/i8/i16, we should set LocVT to i8/i8/i16.
MVT LocVT = ValVT;
if (ActualMVT == MVT::i1 || ActualMVT == MVT::i8)
LocVT = MVT::i8;
ValVT = MVT::i8;
else if (ActualMVT == MVT::i16)
LocVT = MVT::i16;
ValVT = MVT::i16;
CCAssignFn *AssignFn = CCAssignFnForCall(CallConv, /*IsVarArg=*/false);
bool Res =
AssignFn(i, ValVT, LocVT, CCValAssign::Full, Ins[i].Flags, CCInfo);
AssignFn(i, ValVT, ValVT, CCValAssign::Full, Ins[i].Flags, CCInfo);
assert(!Res && "Call operand has unhandled type");
(void)Res;
}
@ -1748,15 +1746,12 @@ SDValue AArch64TargetLowering::LowerFormalArguments(
case CCValAssign::BCvt:
ArgValue = DAG.getNode(ISD::BITCAST, DL, VA.getValVT(), ArgValue);
break;
case CCValAssign::AExt:
case CCValAssign::SExt:
ArgValue = DAG.getNode(ISD::AssertSext, DL, RegVT, ArgValue,
DAG.getValueType(VA.getValVT()));
ArgValue = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), ArgValue);
break;
case CCValAssign::ZExt:
ArgValue = DAG.getNode(ISD::AssertZext, DL, RegVT, ArgValue,
DAG.getValueType(VA.getValVT()));
ArgValue = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), ArgValue);
// SelectionDAGBuilder will insert appropriate AssertZExt & AssertSExt
// nodes after our lowering.
assert(RegVT == Ins[i].VT && "incorrect register location selected");
break;
}
@ -1777,21 +1772,26 @@ SDValue AArch64TargetLowering::LowerFormalArguments(
SDValue FIN = DAG.getFrameIndex(FI, getPointerTy());
SDValue ArgValue;
// If the loc type and val type are not the same, create an anyext load.
if (VA.getLocVT().getSizeInBits() != VA.getValVT().getSizeInBits()) {
// We should only get here if this is a pure integer.
assert(!VA.getValVT().isVector() && VA.getValVT().isInteger() &&
"Only integer extension supported!");
ArgValue = DAG.getExtLoad(ISD::EXTLOAD, DL, VA.getValVT(), Chain, FIN,
MachinePointerInfo::getFixedStack(FI),
VA.getLocVT(),
false, false, false, 0);
} else {
ArgValue = DAG.getLoad(VA.getValVT(), DL, Chain, FIN,
MachinePointerInfo::getFixedStack(FI), false,
false, false, 0);
ISD::LoadExtType ExtType = ISD::NON_EXTLOAD;
switch (VA.getLocInfo()) {
default:
break;
case CCValAssign::SExt:
ExtType = ISD::SEXTLOAD;
break;
case CCValAssign::ZExt:
ExtType = ISD::ZEXTLOAD;
break;
case CCValAssign::AExt:
ExtType = ISD::EXTLOAD;
break;
}
ArgValue = DAG.getExtLoad(ExtType, DL, VA.getValVT(), Chain, FIN,
MachinePointerInfo::getFixedStack(FI),
VA.getLocVT(),
false, false, false, 0);
InVals.push_back(ArgValue);
}
}
@ -2184,14 +2184,13 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
MVT ActualMVT = ActualVT.isSimple() ? ActualVT.getSimpleVT() : ValVT;
ISD::ArgFlagsTy ArgFlags = Outs[i].Flags;
// If ActualMVT is i1/i8/i16, we should set LocVT to i8/i8/i16.
MVT LocVT = ValVT;
if (ActualMVT == MVT::i1 || ActualMVT == MVT::i8)
LocVT = MVT::i8;
ValVT = MVT::i8;
else if (ActualMVT == MVT::i16)
LocVT = MVT::i16;
ValVT = MVT::i16;
CCAssignFn *AssignFn = CCAssignFnForCall(CallConv, /*IsVarArg=*/false);
bool Res = AssignFn(i, ValVT, LocVT, CCValAssign::Full, ArgFlags, CCInfo);
bool Res = AssignFn(i, ValVT, ValVT, CCValAssign::Full, ArgFlags, CCInfo);
assert(!Res && "Call operand has unhandled type");
(void)Res;
}

View File

@ -161,3 +161,11 @@ define void @clobberScratch(i32* %p) {
declare void @llvm.experimental.stackmap(i64, i32, ...)
declare void @llvm.experimental.patchpoint.void(i64, i32, i8*, i32, ...)
declare i64 @llvm.experimental.patchpoint.i64(i64, i32, i8*, i32, ...)
; CHECK-LABEL: test_i16:
; CHECK: ldrh [[BREG:w[0-9]+]], [sp]
; CHECK: add w0, w0, [[BREG]]
define webkit_jscc i16 @test_i16(i16 zeroext %a, i16 zeroext %b) {
%sum = add i16 %a, %b
ret i16 %sum
}