forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			161 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			161 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===-- ARMCallingConv.h - ARM Custom Calling Convention Routines ---------===//
 | |
| //
 | |
| //                     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 ARM Calling Convention that
 | |
| // aren't done by tablegen.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #ifndef ARMCALLINGCONV_H
 | |
| #define ARMCALLINGCONV_H
 | |
| 
 | |
| #include "llvm/CallingConv.h"
 | |
| #include "llvm/CodeGen/CallingConvLower.h"
 | |
| #include "llvm/Target/TargetInstrInfo.h"
 | |
| #include "ARMBaseInstrInfo.h"
 | |
| #include "ARMRegisterInfo.h"
 | |
| #include "ARMSubtarget.h"
 | |
| #include "ARM.h"
 | |
| 
 | |
| namespace llvm {
 | |
| 
 | |
| // APCS f64 is in register pairs, possibly split to stack
 | |
| static bool f64AssignAPCS(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
 | |
|                           CCValAssign::LocInfo &LocInfo,
 | |
|                           CCState &State, bool CanFail) {
 | |
|   static const unsigned RegList[] = { ARM::R0, ARM::R1, ARM::R2, ARM::R3 };
 | |
| 
 | |
|   // Try to get the first register.
 | |
|   if (unsigned Reg = State.AllocateReg(RegList, 4))
 | |
|     State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
 | |
|   else {
 | |
|     // For the 2nd half of a v2f64, do not fail.
 | |
|     if (CanFail)
 | |
|       return false;
 | |
| 
 | |
|     // Put the whole thing on the stack.
 | |
|     State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT,
 | |
|                                            State.AllocateStack(8, 4),
 | |
|                                            LocVT, LocInfo));
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   // Try to get the second register.
 | |
|   if (unsigned Reg = State.AllocateReg(RegList, 4))
 | |
|     State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
 | |
|   else
 | |
|     State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT,
 | |
|                                            State.AllocateStack(4, 4),
 | |
|                                            LocVT, LocInfo));
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| static bool CC_ARM_APCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
 | |
|                                    CCValAssign::LocInfo &LocInfo,
 | |
|                                    ISD::ArgFlagsTy &ArgFlags,
 | |
|                                    CCState &State) {
 | |
|   if (!f64AssignAPCS(ValNo, ValVT, LocVT, LocInfo, State, true))
 | |
|     return false;
 | |
|   if (LocVT == MVT::v2f64 &&
 | |
|       !f64AssignAPCS(ValNo, ValVT, LocVT, LocInfo, State, false))
 | |
|     return false;
 | |
|   return true;  // we handled it
 | |
| }
 | |
| 
 | |
| // AAPCS f64 is in aligned register pairs
 | |
| static bool f64AssignAAPCS(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
 | |
|                            CCValAssign::LocInfo &LocInfo,
 | |
|                            CCState &State, bool CanFail) {
 | |
|   static const unsigned HiRegList[] = { ARM::R0, ARM::R2 };
 | |
|   static const unsigned LoRegList[] = { ARM::R1, ARM::R3 };
 | |
|   static const unsigned ShadowRegList[] = { ARM::R0, ARM::R1 };
 | |
| 
 | |
|   unsigned Reg = State.AllocateReg(HiRegList, ShadowRegList, 2);
 | |
|   if (Reg == 0) {
 | |
|     // For the 2nd half of a v2f64, do not just fail.
 | |
|     if (CanFail)
 | |
|       return false;
 | |
| 
 | |
|     // Put the whole thing on the stack.
 | |
|     State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT,
 | |
|                                            State.AllocateStack(8, 8),
 | |
|                                            LocVT, LocInfo));
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   unsigned i;
 | |
|   for (i = 0; i < 2; ++i)
 | |
|     if (HiRegList[i] == Reg)
 | |
|       break;
 | |
| 
 | |
|   unsigned T = State.AllocateReg(LoRegList[i]);
 | |
|   (void)T;
 | |
|   assert(T == LoRegList[i] && "Could not allocate register");
 | |
| 
 | |
|   State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
 | |
|   State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i],
 | |
|                                          LocVT, LocInfo));
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| static bool CC_ARM_AAPCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
 | |
|                                     CCValAssign::LocInfo &LocInfo,
 | |
|                                     ISD::ArgFlagsTy &ArgFlags,
 | |
|                                     CCState &State) {
 | |
|   if (!f64AssignAAPCS(ValNo, ValVT, LocVT, LocInfo, State, true))
 | |
|     return false;
 | |
|   if (LocVT == MVT::v2f64 &&
 | |
|       !f64AssignAAPCS(ValNo, ValVT, LocVT, LocInfo, State, false))
 | |
|     return false;
 | |
|   return true;  // we handled it
 | |
| }
 | |
| 
 | |
| static bool f64RetAssign(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
 | |
|                          CCValAssign::LocInfo &LocInfo, CCState &State) {
 | |
|   static const unsigned HiRegList[] = { ARM::R0, ARM::R2 };
 | |
|   static const unsigned LoRegList[] = { ARM::R1, ARM::R3 };
 | |
| 
 | |
|   unsigned Reg = State.AllocateReg(HiRegList, LoRegList, 2);
 | |
|   if (Reg == 0)
 | |
|     return false; // we didn't handle it
 | |
| 
 | |
|   unsigned i;
 | |
|   for (i = 0; i < 2; ++i)
 | |
|     if (HiRegList[i] == Reg)
 | |
|       break;
 | |
| 
 | |
|   State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
 | |
|   State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, LoRegList[i],
 | |
|                                          LocVT, LocInfo));
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| static bool RetCC_ARM_APCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
 | |
|                                       CCValAssign::LocInfo &LocInfo,
 | |
|                                       ISD::ArgFlagsTy &ArgFlags,
 | |
|                                       CCState &State) {
 | |
|   if (!f64RetAssign(ValNo, ValVT, LocVT, LocInfo, State))
 | |
|     return false;
 | |
|   if (LocVT == MVT::v2f64 && !f64RetAssign(ValNo, ValVT, LocVT, LocInfo, State))
 | |
|     return false;
 | |
|   return true;  // we handled it
 | |
| }
 | |
| 
 | |
| static bool RetCC_ARM_AAPCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
 | |
|                                        CCValAssign::LocInfo &LocInfo,
 | |
|                                        ISD::ArgFlagsTy &ArgFlags,
 | |
|                                        CCState &State) {
 | |
|   return RetCC_ARM_APCS_Custom_f64(ValNo, ValVT, LocVT, LocInfo, ArgFlags,
 | |
|                                    State);
 | |
| }
 | |
| 
 | |
| } // End llvm namespace
 | |
| 
 | |
| #endif
 |