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