1234285Sdim//===-- llvm/CallingConvLower.cpp - Calling Convention lowering -----------===// 2234285Sdim// 3234285Sdim// The LLVM Compiler Infrastructure 4234285Sdim// 5234285Sdim// This file is distributed under the University of Illinois Open Source 6234285Sdim// License. See LICENSE.TXT for details. 7234285Sdim// 8234285Sdim//===----------------------------------------------------------------------===// 9234285Sdim// 10234285Sdim// This file implements the Hexagon_CCState class, used for lowering and 11234285Sdim// implementing calling conventions. Adapted from the machine independent 12234285Sdim// version of the class (CCState) but this handles calls to varargs functions 13234285Sdim// 14234285Sdim//===----------------------------------------------------------------------===// 15234285Sdim 16234285Sdim#include "HexagonCallingConvLower.h" 17234285Sdim#include "Hexagon.h" 18249423Sdim#include "llvm/IR/DataLayout.h" 19234285Sdim#include "llvm/Support/Debug.h" 20234285Sdim#include "llvm/Support/ErrorHandling.h" 21234285Sdim#include "llvm/Support/raw_ostream.h" 22249423Sdim#include "llvm/Target/TargetMachine.h" 23249423Sdim#include "llvm/Target/TargetRegisterInfo.h" 24234285Sdimusing namespace llvm; 25234285Sdim 26234285SdimHexagon_CCState::Hexagon_CCState(CallingConv::ID CC, bool isVarArg, 27234285Sdim const TargetMachine &tm, 28263508Sdim SmallVectorImpl<CCValAssign> &locs, 29234285Sdim LLVMContext &c) 30263508Sdim : CallingConv(CC), IsVarArg(isVarArg), TM(tm), Locs(locs), Context(c) { 31234285Sdim // No stack is used. 32234285Sdim StackOffset = 0; 33234285Sdim 34263508Sdim UsedRegs.resize((TM.getRegisterInfo()->getNumRegs()+31)/32); 35234285Sdim} 36234285Sdim 37234285Sdim// HandleByVal - Allocate a stack slot large enough to pass an argument by 38234285Sdim// value. The size and alignment information of the argument is encoded in its 39234285Sdim// parameter attribute. 40234285Sdimvoid Hexagon_CCState::HandleByVal(unsigned ValNo, EVT ValVT, 41234285Sdim EVT LocVT, CCValAssign::LocInfo LocInfo, 42234285Sdim int MinSize, int MinAlign, 43234285Sdim ISD::ArgFlagsTy ArgFlags) { 44234285Sdim unsigned Align = ArgFlags.getByValAlign(); 45234285Sdim unsigned Size = ArgFlags.getByValSize(); 46234285Sdim if (MinSize > (int)Size) 47234285Sdim Size = MinSize; 48234285Sdim if (MinAlign > (int)Align) 49234285Sdim Align = MinAlign; 50234285Sdim unsigned Offset = AllocateStack(Size, Align); 51234285Sdim 52234285Sdim addLoc(CCValAssign::getMem(ValNo, ValVT.getSimpleVT(), Offset, 53234285Sdim LocVT.getSimpleVT(), LocInfo)); 54234285Sdim} 55234285Sdim 56234285Sdim/// MarkAllocated - Mark a register and all of its aliases as allocated. 57234285Sdimvoid Hexagon_CCState::MarkAllocated(unsigned Reg) { 58263508Sdim const TargetRegisterInfo &TRI = *TM.getRegisterInfo(); 59239462Sdim for (MCRegAliasIterator AI(Reg, &TRI, true); AI.isValid(); ++AI) 60239462Sdim UsedRegs[*AI/32] |= 1 << (*AI&31); 61234285Sdim} 62234285Sdim 63234285Sdim/// AnalyzeFormalArguments - Analyze an ISD::FORMAL_ARGUMENTS node, 64234285Sdim/// incorporating info about the formals into this state. 65234285Sdimvoid 66234285SdimHexagon_CCState::AnalyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> 67234285Sdim &Ins, 68234285Sdim Hexagon_CCAssignFn Fn, 69234285Sdim unsigned SretValueInRegs) { 70234285Sdim unsigned NumArgs = Ins.size(); 71234285Sdim unsigned i = 0; 72234285Sdim 73234285Sdim // If the function returns a small struct in registers, skip 74234285Sdim // over the first (dummy) argument. 75234285Sdim if (SretValueInRegs != 0) { 76234285Sdim ++i; 77234285Sdim } 78234285Sdim 79234285Sdim 80234285Sdim for (; i != NumArgs; ++i) { 81234285Sdim EVT ArgVT = Ins[i].VT; 82234285Sdim ISD::ArgFlagsTy ArgFlags = Ins[i].Flags; 83234285Sdim if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this, 0, 0, false)) { 84234285Sdim dbgs() << "Formal argument #" << i << " has unhandled type " 85234285Sdim << ArgVT.getEVTString() << "\n"; 86234285Sdim abort(); 87234285Sdim } 88234285Sdim } 89234285Sdim} 90234285Sdim 91234285Sdim/// AnalyzeReturn - Analyze the returned values of an ISD::RET node, 92234285Sdim/// incorporating info about the result values into this state. 93234285Sdimvoid 94234285SdimHexagon_CCState::AnalyzeReturn(const SmallVectorImpl<ISD::OutputArg> &Outs, 95234285Sdim Hexagon_CCAssignFn Fn, 96234285Sdim unsigned SretValueInRegs) { 97234285Sdim 98234285Sdim // For Hexagon, Return small structures in registers. 99234285Sdim if (SretValueInRegs != 0) { 100234285Sdim if (SretValueInRegs <= 32) { 101234285Sdim unsigned Reg = Hexagon::R0; 102234285Sdim addLoc(CCValAssign::getReg(0, MVT::i32, Reg, MVT::i32, 103234285Sdim CCValAssign::Full)); 104234285Sdim return; 105234285Sdim } 106234285Sdim if (SretValueInRegs <= 64) { 107234285Sdim unsigned Reg = Hexagon::D0; 108234285Sdim addLoc(CCValAssign::getReg(0, MVT::i64, Reg, MVT::i64, 109234285Sdim CCValAssign::Full)); 110234285Sdim return; 111234285Sdim } 112234285Sdim } 113234285Sdim 114234285Sdim 115234285Sdim // Determine which register each value should be copied into. 116234285Sdim for (unsigned i = 0, e = Outs.size(); i != e; ++i) { 117234285Sdim EVT VT = Outs[i].VT; 118234285Sdim ISD::ArgFlagsTy ArgFlags = Outs[i].Flags; 119234285Sdim if (Fn(i, VT, VT, CCValAssign::Full, ArgFlags, *this, -1, -1, false)){ 120234285Sdim dbgs() << "Return operand #" << i << " has unhandled type " 121234285Sdim << VT.getEVTString() << "\n"; 122234285Sdim abort(); 123234285Sdim } 124234285Sdim } 125234285Sdim} 126234285Sdim 127234285Sdim 128234285Sdim/// AnalyzeCallOperands - Analyze an ISD::CALL node, incorporating info 129234285Sdim/// about the passed values into this state. 130234285Sdimvoid 131234285SdimHexagon_CCState::AnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> 132234285Sdim &Outs, 133234285Sdim Hexagon_CCAssignFn Fn, 134234285Sdim int NonVarArgsParams, 135234285Sdim unsigned SretValueSize) { 136234285Sdim unsigned NumOps = Outs.size(); 137234285Sdim 138234285Sdim unsigned i = 0; 139234285Sdim // If the called function returns a small struct in registers, skip 140234285Sdim // the first actual parameter. We do not want to pass a pointer to 141234285Sdim // the stack location. 142234285Sdim if (SretValueSize != 0) { 143234285Sdim ++i; 144234285Sdim } 145234285Sdim 146234285Sdim for (; i != NumOps; ++i) { 147234285Sdim EVT ArgVT = Outs[i].VT; 148234285Sdim ISD::ArgFlagsTy ArgFlags = Outs[i].Flags; 149234285Sdim if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this, 150234285Sdim NonVarArgsParams, i+1, false)) { 151234285Sdim dbgs() << "Call operand #" << i << " has unhandled type " 152234285Sdim << ArgVT.getEVTString() << "\n"; 153234285Sdim abort(); 154234285Sdim } 155234285Sdim } 156234285Sdim} 157234285Sdim 158234285Sdim/// AnalyzeCallOperands - Same as above except it takes vectors of types 159234285Sdim/// and argument flags. 160234285Sdimvoid 161234285SdimHexagon_CCState::AnalyzeCallOperands(SmallVectorImpl<EVT> &ArgVTs, 162234285Sdim SmallVectorImpl<ISD::ArgFlagsTy> &Flags, 163234285Sdim Hexagon_CCAssignFn Fn) { 164234285Sdim unsigned NumOps = ArgVTs.size(); 165234285Sdim for (unsigned i = 0; i != NumOps; ++i) { 166234285Sdim EVT ArgVT = ArgVTs[i]; 167234285Sdim ISD::ArgFlagsTy ArgFlags = Flags[i]; 168234285Sdim if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this, -1, -1, 169234285Sdim false)) { 170234285Sdim dbgs() << "Call operand #" << i << " has unhandled type " 171234285Sdim << ArgVT.getEVTString() << "\n"; 172234285Sdim abort(); 173234285Sdim } 174234285Sdim } 175234285Sdim} 176234285Sdim 177234285Sdim/// AnalyzeCallResult - Analyze the return values of an ISD::CALL node, 178234285Sdim/// incorporating info about the passed values into this state. 179234285Sdimvoid 180234285SdimHexagon_CCState::AnalyzeCallResult(const SmallVectorImpl<ISD::InputArg> &Ins, 181234285Sdim Hexagon_CCAssignFn Fn, 182234285Sdim unsigned SretValueInRegs) { 183234285Sdim 184234285Sdim for (unsigned i = 0, e = Ins.size(); i != e; ++i) { 185234285Sdim EVT VT = Ins[i].VT; 186234285Sdim ISD::ArgFlagsTy Flags = ISD::ArgFlagsTy(); 187234285Sdim if (Fn(i, VT, VT, CCValAssign::Full, Flags, *this, -1, -1, false)) { 188234285Sdim dbgs() << "Call result #" << i << " has unhandled type " 189234285Sdim << VT.getEVTString() << "\n"; 190234285Sdim abort(); 191234285Sdim } 192234285Sdim } 193234285Sdim} 194234285Sdim 195234285Sdim/// AnalyzeCallResult - Same as above except it's specialized for calls which 196234285Sdim/// produce a single value. 197234285Sdimvoid Hexagon_CCState::AnalyzeCallResult(EVT VT, Hexagon_CCAssignFn Fn) { 198234285Sdim if (Fn(0, VT, VT, CCValAssign::Full, ISD::ArgFlagsTy(), *this, -1, -1, 199234285Sdim false)) { 200234285Sdim dbgs() << "Call result has unhandled type " 201234285Sdim << VT.getEVTString() << "\n"; 202234285Sdim abort(); 203234285Sdim } 204234285Sdim} 205