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:
parent
406287c5b7
commit
fc1b1e8952
@ -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
|
@ -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]>>,
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user