From b4b54153ad760c69a00a08531abef4ed434a5092 Mon Sep 17 00:00:00 2001 From: Tony Linthicum Date: Mon, 12 Dec 2011 21:14:40 +0000 Subject: Hexagon backend support git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@146412 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Hexagon/HexagonCallingConvLower.cpp | 207 +++++++++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 lib/Target/Hexagon/HexagonCallingConvLower.cpp (limited to 'lib/Target/Hexagon/HexagonCallingConvLower.cpp') diff --git a/lib/Target/Hexagon/HexagonCallingConvLower.cpp b/lib/Target/Hexagon/HexagonCallingConvLower.cpp new file mode 100644 index 0000000000..2e51dbf51c --- /dev/null +++ b/lib/Target/Hexagon/HexagonCallingConvLower.cpp @@ -0,0 +1,207 @@ +//===-- llvm/CallingConvLower.cpp - Calling Convention lowering -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Hexagon_CCState class, used for lowering and +// implementing calling conventions. Adapted from the machine independent +// version of the class (CCState) but this handles calls to varargs functions +// +//===----------------------------------------------------------------------===// + +#include "HexagonCallingConvLower.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "Hexagon.h" +using namespace llvm; + +Hexagon_CCState::Hexagon_CCState(CallingConv::ID CC, bool isVarArg, + const TargetMachine &tm, + SmallVector &locs, + LLVMContext &c) + : CallingConv(CC), IsVarArg(isVarArg), TM(tm), + TRI(*TM.getRegisterInfo()), Locs(locs), Context(c) { + // No stack is used. + StackOffset = 0; + + UsedRegs.resize((TRI.getNumRegs()+31)/32); +} + +// HandleByVal - Allocate a stack slot large enough to pass an argument by +// value. The size and alignment information of the argument is encoded in its +// parameter attribute. +void Hexagon_CCState::HandleByVal(unsigned ValNo, EVT ValVT, + EVT LocVT, CCValAssign::LocInfo LocInfo, + int MinSize, int MinAlign, + ISD::ArgFlagsTy ArgFlags) { + unsigned Align = ArgFlags.getByValAlign(); + unsigned Size = ArgFlags.getByValSize(); + if (MinSize > (int)Size) + Size = MinSize; + if (MinAlign > (int)Align) + Align = MinAlign; + unsigned Offset = AllocateStack(Size, Align); + + addLoc(CCValAssign::getMem(ValNo, ValVT.getSimpleVT(), Offset, + LocVT.getSimpleVT(), LocInfo)); +} + +/// MarkAllocated - Mark a register and all of its aliases as allocated. +void Hexagon_CCState::MarkAllocated(unsigned Reg) { + UsedRegs[Reg/32] |= 1 << (Reg&31); + + if (const unsigned *RegAliases = TRI.getAliasSet(Reg)) + for (; (Reg = *RegAliases); ++RegAliases) + UsedRegs[Reg/32] |= 1 << (Reg&31); +} + +/// AnalyzeFormalArguments - Analyze an ISD::FORMAL_ARGUMENTS node, +/// incorporating info about the formals into this state. +void +Hexagon_CCState::AnalyzeFormalArguments(const SmallVectorImpl + &Ins, + Hexagon_CCAssignFn Fn, + unsigned SretValueInRegs) { + unsigned NumArgs = Ins.size(); + unsigned i = 0; + + // If the function returns a small struct in registers, skip + // over the first (dummy) argument. + if (SretValueInRegs != 0) { + ++i; + } + + + for (; i != NumArgs; ++i) { + EVT ArgVT = Ins[i].VT; + ISD::ArgFlagsTy ArgFlags = Ins[i].Flags; + if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this, 0, 0, false)) { + dbgs() << "Formal argument #" << i << " has unhandled type " + << ArgVT.getEVTString() << "\n"; + abort(); + } + } +} + +/// AnalyzeReturn - Analyze the returned values of an ISD::RET node, +/// incorporating info about the result values into this state. +void +Hexagon_CCState::AnalyzeReturn(const SmallVectorImpl &Outs, + Hexagon_CCAssignFn Fn, + unsigned SretValueInRegs) { + + // For Hexagon, Return small structures in registers. + if (SretValueInRegs != 0) { + if (SretValueInRegs <= 32) { + unsigned Reg = Hexagon::R0; + addLoc(CCValAssign::getReg(0, MVT::i32, Reg, MVT::i32, + CCValAssign::Full)); + return; + } + if (SretValueInRegs <= 64) { + unsigned Reg = Hexagon::D0; + addLoc(CCValAssign::getReg(0, MVT::i64, Reg, MVT::i64, + CCValAssign::Full)); + return; + } + } + + + // Determine which register each value should be copied into. + for (unsigned i = 0, e = Outs.size(); i != e; ++i) { + EVT VT = Outs[i].VT; + ISD::ArgFlagsTy ArgFlags = Outs[i].Flags; + if (Fn(i, VT, VT, CCValAssign::Full, ArgFlags, *this, -1, -1, false)){ + dbgs() << "Return operand #" << i << " has unhandled type " + << VT.getEVTString() << "\n"; + abort(); + } + } +} + + +/// AnalyzeCallOperands - Analyze an ISD::CALL node, incorporating info +/// about the passed values into this state. +void +Hexagon_CCState::AnalyzeCallOperands(const SmallVectorImpl + &Outs, + Hexagon_CCAssignFn Fn, + int NonVarArgsParams, + unsigned SretValueSize) { + unsigned NumOps = Outs.size(); + + unsigned i = 0; + // If the called function returns a small struct in registers, skip + // the first actual parameter. We do not want to pass a pointer to + // the stack location. + if (SretValueSize != 0) { + ++i; + } + + for (; i != NumOps; ++i) { + EVT ArgVT = Outs[i].VT; + ISD::ArgFlagsTy ArgFlags = Outs[i].Flags; + if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this, + NonVarArgsParams, i+1, false)) { + dbgs() << "Call operand #" << i << " has unhandled type " + << ArgVT.getEVTString() << "\n"; + abort(); + } + } +} + +/// AnalyzeCallOperands - Same as above except it takes vectors of types +/// and argument flags. +void +Hexagon_CCState::AnalyzeCallOperands(SmallVectorImpl &ArgVTs, + SmallVectorImpl &Flags, + Hexagon_CCAssignFn Fn) { + unsigned NumOps = ArgVTs.size(); + for (unsigned i = 0; i != NumOps; ++i) { + EVT ArgVT = ArgVTs[i]; + ISD::ArgFlagsTy ArgFlags = Flags[i]; + if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this, -1, -1, + false)) { + dbgs() << "Call operand #" << i << " has unhandled type " + << ArgVT.getEVTString() << "\n"; + abort(); + } + } +} + +/// AnalyzeCallResult - Analyze the return values of an ISD::CALL node, +/// incorporating info about the passed values into this state. +void +Hexagon_CCState::AnalyzeCallResult(const SmallVectorImpl &Ins, + Hexagon_CCAssignFn Fn, + unsigned SretValueInRegs) { + + for (unsigned i = 0, e = Ins.size(); i != e; ++i) { + EVT VT = Ins[i].VT; + ISD::ArgFlagsTy Flags = ISD::ArgFlagsTy(); + if (Fn(i, VT, VT, CCValAssign::Full, Flags, *this, -1, -1, false)) { + dbgs() << "Call result #" << i << " has unhandled type " + << VT.getEVTString() << "\n"; + abort(); + } + } +} + +/// AnalyzeCallResult - Same as above except it's specialized for calls which +/// produce a single value. +void Hexagon_CCState::AnalyzeCallResult(EVT VT, Hexagon_CCAssignFn Fn) { + if (Fn(0, VT, VT, CCValAssign::Full, ISD::ArgFlagsTy(), *this, -1, -1, + false)) { + dbgs() << "Call result has unhandled type " + << VT.getEVTString() << "\n"; + abort(); + } +} -- cgit v1.2.3