ARMISelDAGToDAG.cpp revision 85ede37ca90b5d1846f37631ed2e8b8f96000db8
1//===-- ARMISelDAGToDAG.cpp - A dag to dag inst selector for ARM ----------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file was developed by Chris Lattner and is distributed under 6// the University of Illinois Open Source License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file defines an instruction selector for the ARM target. 11// 12//===----------------------------------------------------------------------===// 13 14#include "ARM.h" 15#include "ARMTargetMachine.h" 16#include "llvm/DerivedTypes.h" 17#include "llvm/Function.h" 18#include "llvm/Intrinsics.h" 19#include "llvm/CodeGen/MachineFrameInfo.h" 20#include "llvm/CodeGen/MachineFunction.h" 21#include "llvm/CodeGen/MachineInstrBuilder.h" 22#include "llvm/CodeGen/SelectionDAG.h" 23#include "llvm/CodeGen/SelectionDAGISel.h" 24#include "llvm/CodeGen/SSARegMap.h" 25#include "llvm/Target/TargetLowering.h" 26#include "llvm/Support/Debug.h" 27#include <iostream> 28#include <set> 29using namespace llvm; 30 31namespace { 32 class ARMTargetLowering : public TargetLowering { 33 public: 34 ARMTargetLowering(TargetMachine &TM); 35 virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG); 36 }; 37 38} 39 40ARMTargetLowering::ARMTargetLowering(TargetMachine &TM) 41 : TargetLowering(TM) { 42 setOperationAction(ISD::RET, MVT::Other, Custom); 43} 44 45static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) { 46 assert(0 && "Not implemented"); 47 abort(); 48} 49 50static SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG) { 51 SDOperand Copy; 52 switch(Op.getNumOperands()) { 53 default: 54 assert(0 && "Do not know how to return this many arguments!"); 55 abort(); 56 case 1: 57 return SDOperand(); // ret void is legal 58 case 3: 59 Copy = DAG.getCopyToReg(Op.getOperand(0), ARM::R0, Op.getOperand(1), SDOperand()); 60 break; 61 } 62 SDOperand LR = DAG.getRegister(ARM::R14, MVT::i32); 63 64 return DAG.getNode(ISD::BRIND, MVT::Other, Copy, LR); 65} 66 67static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG) { 68 MachineFunction &MF = DAG.getMachineFunction(); 69 SSARegMap *RegMap = MF.getSSARegMap(); 70 std::vector<SDOperand> ArgValues; 71 SDOperand Root = Op.getOperand(0); 72 73 unsigned reg_idx = 0; 74 unsigned num_regs = 4; 75 76 static const unsigned REGS[] = { 77 ARM::R0, ARM::R1, ARM::R2, ARM::R3 78 }; 79 80 for (unsigned ArgNo = 0, e = Op.Val->getNumValues()-1; ArgNo != e; ++ArgNo) { 81 SDOperand ArgVal; 82 83 MVT::ValueType ObjectVT = Op.getValue(ArgNo).getValueType(); 84 assert (ObjectVT == MVT::i32); 85 86 assert(reg_idx < num_regs); 87 unsigned VReg = RegMap->createVirtualRegister(&ARM::IntRegsRegClass); 88 MF.addLiveIn(REGS[reg_idx], VReg); 89 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i32); 90 ++reg_idx; 91 92 ArgValues.push_back(ArgVal); 93 } 94 95 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0; 96 assert(!isVarArg); 97 98 ArgValues.push_back(Root); 99 100 // Return the new list of results. 101 std::vector<MVT::ValueType> RetVT(Op.Val->value_begin(), 102 Op.Val->value_end()); 103 return DAG.getNode(ISD::MERGE_VALUES, RetVT, ArgValues); 104} 105 106SDOperand ARMTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { 107 switch (Op.getOpcode()) { 108 default: 109 assert(0 && "Should not custom lower this!"); 110 abort(); 111 case ISD::FORMAL_ARGUMENTS: 112 return LowerFORMAL_ARGUMENTS(Op, DAG); 113 case ISD::CALL: 114 return LowerCALL(Op, DAG); 115 case ISD::RET: 116 return LowerRET(Op, DAG); 117 } 118} 119 120//===----------------------------------------------------------------------===// 121// Instruction Selector Implementation 122//===----------------------------------------------------------------------===// 123 124//===--------------------------------------------------------------------===// 125/// ARMDAGToDAGISel - ARM specific code to select ARM machine 126/// instructions for SelectionDAG operations. 127/// 128namespace { 129class ARMDAGToDAGISel : public SelectionDAGISel { 130 ARMTargetLowering Lowering; 131 132public: 133 ARMDAGToDAGISel(TargetMachine &TM) 134 : SelectionDAGISel(Lowering), Lowering(TM) { 135 } 136 137 void Select(SDOperand &Result, SDOperand Op); 138 virtual void InstructionSelectBasicBlock(SelectionDAG &DAG); 139 140 // Include the pieces autogenerated from the target description. 141#include "ARMGenDAGISel.inc" 142}; 143 144void ARMDAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) { 145 DEBUG(BB->dump()); 146 147 DAG.setRoot(SelectRoot(DAG.getRoot())); 148 assert(InFlightSet.empty() && "ISel InFlightSet has not been emptied!"); 149 CodeGenMap.clear(); 150 HandleMap.clear(); 151 ReplaceMap.clear(); 152 DAG.RemoveDeadNodes(); 153 154 ScheduleAndEmitDAG(DAG); 155} 156 157void ARMDAGToDAGISel::Select(SDOperand &Result, SDOperand Op) { 158 SelectCode(Result, Op); 159} 160 161} // end anonymous namespace 162 163/// createARMISelDag - This pass converts a legalized DAG into a 164/// ARM-specific DAG, ready for instruction scheduling. 165/// 166FunctionPass *llvm::createARMISelDag(TargetMachine &TM) { 167 return new ARMDAGToDAGISel(TM); 168} 169