Index: llvm/trunk/lib/Target/AArch64/AArch64CallingConvention.h =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64CallingConvention.h +++ llvm/trunk/lib/Target/AArch64/AArch64CallingConvention.h @@ -1,4 +1,4 @@ -//=== AArch64CallingConv.h - Custom Calling Convention Routines -*- C++ -*-===// +//=== AArch64CallingConvention.h - AArch64 CC entry points ------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,133 +6,40 @@ // //===----------------------------------------------------------------------===// // -// This file contains the custom routines for the AArch64 Calling Convention -// that aren't done by tablegen. +// This file declares the entry points for AArch64 calling convention analysis. // //===----------------------------------------------------------------------===// #ifndef LLVM_LIB_TARGET_AARCH64_AARCH64CALLINGCONVENTION_H #define LLVM_LIB_TARGET_AARCH64_AARCH64CALLINGCONVENTION_H -#include "AArch64.h" -#include "AArch64InstrInfo.h" -#include "AArch64Subtarget.h" #include "llvm/CodeGen/CallingConvLower.h" -#include "llvm/CodeGen/TargetInstrInfo.h" -#include "llvm/IR/CallingConv.h" -namespace { -using namespace llvm; - -static const MCPhysReg XRegList[] = {AArch64::X0, AArch64::X1, AArch64::X2, - AArch64::X3, AArch64::X4, AArch64::X5, - AArch64::X6, AArch64::X7}; -static const MCPhysReg HRegList[] = {AArch64::H0, AArch64::H1, AArch64::H2, - AArch64::H3, AArch64::H4, AArch64::H5, - AArch64::H6, AArch64::H7}; -static const MCPhysReg SRegList[] = {AArch64::S0, AArch64::S1, AArch64::S2, - AArch64::S3, AArch64::S4, AArch64::S5, - AArch64::S6, AArch64::S7}; -static const MCPhysReg DRegList[] = {AArch64::D0, AArch64::D1, AArch64::D2, - AArch64::D3, AArch64::D4, AArch64::D5, - AArch64::D6, AArch64::D7}; -static const MCPhysReg QRegList[] = {AArch64::Q0, AArch64::Q1, AArch64::Q2, - AArch64::Q3, AArch64::Q4, AArch64::Q5, - AArch64::Q6, AArch64::Q7}; - -static bool finishStackBlock(SmallVectorImpl &PendingMembers, - MVT LocVT, ISD::ArgFlagsTy &ArgFlags, - CCState &State, unsigned SlotAlign) { - unsigned Size = LocVT.getSizeInBits() / 8; - unsigned StackAlign = - State.getMachineFunction().getDataLayout().getStackAlignment(); - unsigned Align = std::min(ArgFlags.getOrigAlign(), StackAlign); - - for (auto &It : PendingMembers) { - It.convertToMem(State.AllocateStack(Size, std::max(Align, SlotAlign))); - State.addLoc(It); - SlotAlign = 1; - } - - // All pending members have now been allocated - PendingMembers.clear(); - return true; -} - -/// The Darwin variadic PCS places anonymous arguments in 8-byte stack slots. An -/// [N x Ty] type must still be contiguous in memory though. -static bool CC_AArch64_Custom_Stack_Block( - unsigned &ValNo, MVT &ValVT, MVT &LocVT, CCValAssign::LocInfo &LocInfo, - ISD::ArgFlagsTy &ArgFlags, CCState &State) { - SmallVectorImpl &PendingMembers = State.getPendingLocs(); - - // Add the argument to the list to be allocated once we know the size of the - // block. - PendingMembers.push_back( - CCValAssign::getPending(ValNo, ValVT, LocVT, LocInfo)); - - if (!ArgFlags.isInConsecutiveRegsLast()) - return true; - - return finishStackBlock(PendingMembers, LocVT, ArgFlags, State, 8); -} - -/// Given an [N x Ty] block, it should be passed in a consecutive sequence of -/// registers. If no such sequence is available, mark the rest of the registers -/// of that type as used and place the argument on the stack. -static bool CC_AArch64_Custom_Block(unsigned &ValNo, MVT &ValVT, MVT &LocVT, - CCValAssign::LocInfo &LocInfo, - ISD::ArgFlagsTy &ArgFlags, CCState &State) { - // Try to allocate a contiguous block of registers, each of the correct - // size to hold one member. - ArrayRef RegList; - if (LocVT.SimpleTy == MVT::i64) - RegList = XRegList; - else if (LocVT.SimpleTy == MVT::f16) - RegList = HRegList; - else if (LocVT.SimpleTy == MVT::f32 || LocVT.is32BitVector()) - RegList = SRegList; - else if (LocVT.SimpleTy == MVT::f64 || LocVT.is64BitVector()) - RegList = DRegList; - else if (LocVT.SimpleTy == MVT::f128 || LocVT.is128BitVector()) - RegList = QRegList; - else { - // Not an array we want to split up after all. - return false; - } - - SmallVectorImpl &PendingMembers = State.getPendingLocs(); - - // Add the argument to the list to be allocated once we know the size of the - // block. - PendingMembers.push_back( - CCValAssign::getPending(ValNo, ValVT, LocVT, LocInfo)); - - if (!ArgFlags.isInConsecutiveRegsLast()) - return true; - - unsigned RegResult = State.AllocateRegBlock(RegList, PendingMembers.size()); - if (RegResult) { - for (auto &It : PendingMembers) { - It.convertToReg(RegResult); - State.addLoc(It); - ++RegResult; - } - PendingMembers.clear(); - return true; - } - - // Mark all regs in the class as unavailable - for (auto Reg : RegList) - State.AllocateReg(Reg); - - const AArch64Subtarget &Subtarget = static_cast( - State.getMachineFunction().getSubtarget()); - unsigned SlotAlign = Subtarget.isTargetDarwin() ? 1 : 8; - - return finishStackBlock(PendingMembers, LocVT, ArgFlags, State, SlotAlign); -} - -} +namespace llvm { +bool CC_AArch64_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT, + CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, + CCState &State); +bool CC_AArch64_DarwinPCS_VarArg(unsigned ValNo, MVT ValVT, MVT LocVT, + CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, CCState &State); +bool CC_AArch64_DarwinPCS(unsigned ValNo, MVT ValVT, MVT LocVT, + CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, CCState &State); +bool CC_AArch64_Win64_VarArg(unsigned ValNo, MVT ValVT, MVT LocVT, + CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, CCState &State); +bool CC_AArch64_WebKit_JS(unsigned ValNo, MVT ValVT, MVT LocVT, + CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, CCState &State); +bool CC_AArch64_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, + CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, + CCState &State); +bool RetCC_AArch64_AAPCS(unsigned ValNo, MVT ValVT, MVT LocVT, + CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, + CCState &State); +bool RetCC_AArch64_WebKit_JS(unsigned ValNo, MVT ValVT, MVT LocVT, + CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, CCState &State); +} // namespace llvm #endif Index: llvm/trunk/lib/Target/AArch64/AArch64CallingConvention.cpp =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64CallingConvention.cpp +++ llvm/trunk/lib/Target/AArch64/AArch64CallingConvention.cpp @@ -0,0 +1,134 @@ +//=== AArch64CallingConvention.cpp - AArch64 CC impl ------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains the table-generated and custom routines for the AArch64 +// Calling Convention. +// +//===----------------------------------------------------------------------===// + +#include "AArch64CallingConvention.h" +#include "AArch64.h" +#include "AArch64InstrInfo.h" +#include "AArch64Subtarget.h" +#include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/CodeGen/TargetInstrInfo.h" +#include "llvm/IR/CallingConv.h" +using namespace llvm; + +static const MCPhysReg XRegList[] = {AArch64::X0, AArch64::X1, AArch64::X2, + AArch64::X3, AArch64::X4, AArch64::X5, + AArch64::X6, AArch64::X7}; +static const MCPhysReg HRegList[] = {AArch64::H0, AArch64::H1, AArch64::H2, + AArch64::H3, AArch64::H4, AArch64::H5, + AArch64::H6, AArch64::H7}; +static const MCPhysReg SRegList[] = {AArch64::S0, AArch64::S1, AArch64::S2, + AArch64::S3, AArch64::S4, AArch64::S5, + AArch64::S6, AArch64::S7}; +static const MCPhysReg DRegList[] = {AArch64::D0, AArch64::D1, AArch64::D2, + AArch64::D3, AArch64::D4, AArch64::D5, + AArch64::D6, AArch64::D7}; +static const MCPhysReg QRegList[] = {AArch64::Q0, AArch64::Q1, AArch64::Q2, + AArch64::Q3, AArch64::Q4, AArch64::Q5, + AArch64::Q6, AArch64::Q7}; + +static bool finishStackBlock(SmallVectorImpl &PendingMembers, + MVT LocVT, ISD::ArgFlagsTy &ArgFlags, + CCState &State, unsigned SlotAlign) { + unsigned Size = LocVT.getSizeInBits() / 8; + unsigned StackAlign = + State.getMachineFunction().getDataLayout().getStackAlignment(); + unsigned Align = std::min(ArgFlags.getOrigAlign(), StackAlign); + + for (auto &It : PendingMembers) { + It.convertToMem(State.AllocateStack(Size, std::max(Align, SlotAlign))); + State.addLoc(It); + SlotAlign = 1; + } + + // All pending members have now been allocated + PendingMembers.clear(); + return true; +} + +/// The Darwin variadic PCS places anonymous arguments in 8-byte stack slots. An +/// [N x Ty] type must still be contiguous in memory though. +static bool CC_AArch64_Custom_Stack_Block( + unsigned &ValNo, MVT &ValVT, MVT &LocVT, CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, CCState &State) { + SmallVectorImpl &PendingMembers = State.getPendingLocs(); + + // Add the argument to the list to be allocated once we know the size of the + // block. + PendingMembers.push_back( + CCValAssign::getPending(ValNo, ValVT, LocVT, LocInfo)); + + if (!ArgFlags.isInConsecutiveRegsLast()) + return true; + + return finishStackBlock(PendingMembers, LocVT, ArgFlags, State, 8); +} + +/// Given an [N x Ty] block, it should be passed in a consecutive sequence of +/// registers. If no such sequence is available, mark the rest of the registers +/// of that type as used and place the argument on the stack. +static bool CC_AArch64_Custom_Block(unsigned &ValNo, MVT &ValVT, MVT &LocVT, + CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, CCState &State) { + // Try to allocate a contiguous block of registers, each of the correct + // size to hold one member. + ArrayRef RegList; + if (LocVT.SimpleTy == MVT::i64) + RegList = XRegList; + else if (LocVT.SimpleTy == MVT::f16) + RegList = HRegList; + else if (LocVT.SimpleTy == MVT::f32 || LocVT.is32BitVector()) + RegList = SRegList; + else if (LocVT.SimpleTy == MVT::f64 || LocVT.is64BitVector()) + RegList = DRegList; + else if (LocVT.SimpleTy == MVT::f128 || LocVT.is128BitVector()) + RegList = QRegList; + else { + // Not an array we want to split up after all. + return false; + } + + SmallVectorImpl &PendingMembers = State.getPendingLocs(); + + // Add the argument to the list to be allocated once we know the size of the + // block. + PendingMembers.push_back( + CCValAssign::getPending(ValNo, ValVT, LocVT, LocInfo)); + + if (!ArgFlags.isInConsecutiveRegsLast()) + return true; + + unsigned RegResult = State.AllocateRegBlock(RegList, PendingMembers.size()); + if (RegResult) { + for (auto &It : PendingMembers) { + It.convertToReg(RegResult); + State.addLoc(It); + ++RegResult; + } + PendingMembers.clear(); + return true; + } + + // Mark all regs in the class as unavailable + for (auto Reg : RegList) + State.AllocateReg(Reg); + + const AArch64Subtarget &Subtarget = static_cast( + State.getMachineFunction().getSubtarget()); + unsigned SlotAlign = Subtarget.isTargetDarwin() ? 1 : 8; + + return finishStackBlock(PendingMembers, LocVT, ArgFlags, State, SlotAlign); +} + +// TableGen provides definitions of the calling convention analysis entry +// points. +#include "AArch64GenCallingConv.inc" Index: llvm/trunk/lib/Target/AArch64/AArch64CallingConvention.td =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64CallingConvention.td +++ llvm/trunk/lib/Target/AArch64/AArch64CallingConvention.td @@ -21,6 +21,7 @@ // ARM AAPCS64 Calling Convention //===----------------------------------------------------------------------===// +let Entry = 1 in def CC_AArch64_AAPCS : CallingConv<[ CCIfType<[iPTR], CCBitConvertToType>, CCIfType<[v2f32], CCBitConvertToType>, @@ -88,6 +89,7 @@ CCAssignToStack<16, 16>> ]>; +let Entry = 1 in def RetCC_AArch64_AAPCS : CallingConv<[ CCIfType<[iPTR], CCBitConvertToType>, CCIfType<[v2f32], CCBitConvertToType>, @@ -121,6 +123,7 @@ ]>; // Vararg functions on windows pass floats in integer registers +let Entry = 1 in def CC_AArch64_Win64_VarArg : CallingConv<[ CCIfType<[f16, f32], CCPromoteToType>, CCIfType<[f64], CCBitConvertToType>, @@ -132,6 +135,7 @@ // from the standard one at this level: // + i128s (i.e. split i64s) don't need even registers. // + Stack slots are sized as needed rather than being at least 64-bit. +let Entry = 1 in def CC_AArch64_DarwinPCS : CallingConv<[ CCIfType<[iPTR], CCBitConvertToType>, CCIfType<[v2f32], CCBitConvertToType>, @@ -188,6 +192,7 @@ CCAssignToStack<16, 16>> ]>; +let Entry = 1 in def CC_AArch64_DarwinPCS_VarArg : CallingConv<[ CCIfType<[iPTR], CCBitConvertToType>, CCIfType<[v2f32], CCBitConvertToType>, @@ -212,6 +217,7 @@ // in register and the remaining arguments on stack. We allow 32bit stack slots, // so that WebKit can write partial values in the stack and define the other // 32bit quantity as undef. +let Entry = 1 in def CC_AArch64_WebKit_JS : CallingConv<[ // Handle i1, i8, i16, i32, and i64 passing in register X0 (W0). CCIfType<[i1, i8, i16], CCPromoteToType>, @@ -223,6 +229,7 @@ CCIfType<[i64, f64], CCAssignToStack<8, 8>> ]>; +let Entry = 1 in def RetCC_AArch64_WebKit_JS : CallingConv<[ CCIfType<[i32], CCAssignToRegWithShadow<[W0, W1, W2, W3, W4, W5, W6, W7], [X0, X1, X2, X3, X4, X5, X6, X7]>>, @@ -256,6 +263,7 @@ // The AArch64 register mapping is under the heading "The ARMv8/AArch64 ABI // register mapping". +let Entry = 1 in def CC_AArch64_GHC : CallingConv<[ CCIfType<[iPTR], CCBitConvertToType>, Index: llvm/trunk/lib/Target/AArch64/AArch64FastISel.cpp =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64FastISel.cpp +++ llvm/trunk/lib/Target/AArch64/AArch64FastISel.cpp @@ -304,8 +304,6 @@ } // end anonymous namespace -#include "AArch64GenCallingConv.inc" - /// Check if the sign-/zero-extend will be a noop. static bool isIntExtFree(const Instruction *I) { assert((isa(I) || isa(I)) && @@ -5171,10 +5169,6 @@ return selectAtomicCmpXchg(cast(I)); } - // Silence warnings. - (void)&CC_AArch64_DarwinPCS_VarArg; - (void)&CC_AArch64_Win64_VarArg; - // fall-back to target-independent instruction selection. return selectOperator(I, I->getOpcode()); } Index: llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp +++ llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -2972,8 +2972,6 @@ // Calling Convention Implementation //===----------------------------------------------------------------------===// -#include "AArch64GenCallingConv.inc" - /// Selects the correct CCAssignFn for a given CallingConvention value. CCAssignFn *AArch64TargetLowering::CCAssignFnForCall(CallingConv::ID CC, bool IsVarArg) const { Index: llvm/trunk/lib/Target/AArch64/CMakeLists.txt =================================================================== --- llvm/trunk/lib/Target/AArch64/CMakeLists.txt +++ llvm/trunk/lib/Target/AArch64/CMakeLists.txt @@ -24,6 +24,7 @@ AArch64AdvSIMDScalarPass.cpp AArch64AsmPrinter.cpp AArch64BranchTargets.cpp + AArch64CallingConvention.cpp AArch64CallLowering.cpp AArch64CleanupLocalDynamicTLSPass.cpp AArch64CollectLOH.cpp