ARMISelDAGToDAG.cpp revision 4b02367d542c7eaa429d1ff73119ae44ddb252a8
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  SDOperand Chain = Op.getOperand(0);
53  switch(Op.getNumOperands()) {
54  default:
55    assert(0 && "Do not know how to return this many arguments!");
56    abort();
57  case 1: {
58    SDOperand LR = DAG.getRegister(ARM::R14, MVT::i32);
59    return DAG.getNode(ISD::BRIND, MVT::Other, Chain, LR);
60  }
61  case 3:
62    Copy = DAG.getCopyToReg(Chain, ARM::R0, Op.getOperand(1), SDOperand());
63    if (DAG.getMachineFunction().liveout_empty())
64      DAG.getMachineFunction().addLiveOut(ARM::R0);
65    break;
66  }
67
68  SDOperand LR = DAG.getRegister(ARM::R14, MVT::i32);
69
70  //bug: the copy and branch should be linked with a flag so that the
71  //scheduller can't move an instruction that destroys R0 in between them
72  //return DAG.getNode(ISD::BRIND, MVT::Other, Copy, LR, Copy.getValue(1));
73
74  return DAG.getNode(ISD::BRIND, MVT::Other, Copy, LR);
75}
76
77static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG) {
78  MachineFunction &MF = DAG.getMachineFunction();
79  SSARegMap *RegMap = MF.getSSARegMap();
80  std::vector<SDOperand> ArgValues;
81  SDOperand Root = Op.getOperand(0);
82
83  unsigned reg_idx = 0;
84  unsigned num_regs = 4;
85
86  static const unsigned REGS[] = {
87    ARM::R0, ARM::R1, ARM::R2, ARM::R3
88  };
89
90  for (unsigned ArgNo = 0, e = Op.Val->getNumValues()-1; ArgNo != e; ++ArgNo) {
91    SDOperand ArgVal;
92
93    MVT::ValueType ObjectVT = Op.getValue(ArgNo).getValueType();
94    assert (ObjectVT == MVT::i32);
95
96    assert(reg_idx < num_regs);
97    unsigned VReg = RegMap->createVirtualRegister(&ARM::IntRegsRegClass);
98    MF.addLiveIn(REGS[reg_idx], VReg);
99    ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i32);
100    ++reg_idx;
101
102    ArgValues.push_back(ArgVal);
103  }
104
105  bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
106  assert(!isVarArg);
107
108  ArgValues.push_back(Root);
109
110  // Return the new list of results.
111  std::vector<MVT::ValueType> RetVT(Op.Val->value_begin(),
112                                    Op.Val->value_end());
113  return DAG.getNode(ISD::MERGE_VALUES, RetVT, ArgValues);
114}
115
116SDOperand ARMTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
117  switch (Op.getOpcode()) {
118  default:
119    assert(0 && "Should not custom lower this!");
120    abort();
121  case ISD::FORMAL_ARGUMENTS:
122    return LowerFORMAL_ARGUMENTS(Op, DAG);
123  case ISD::CALL:
124    return LowerCALL(Op, DAG);
125  case ISD::RET:
126    return LowerRET(Op, DAG);
127  }
128}
129
130//===----------------------------------------------------------------------===//
131// Instruction Selector Implementation
132//===----------------------------------------------------------------------===//
133
134//===--------------------------------------------------------------------===//
135/// ARMDAGToDAGISel - ARM specific code to select ARM machine
136/// instructions for SelectionDAG operations.
137///
138namespace {
139class ARMDAGToDAGISel : public SelectionDAGISel {
140  ARMTargetLowering Lowering;
141
142public:
143  ARMDAGToDAGISel(TargetMachine &TM)
144    : SelectionDAGISel(Lowering), Lowering(TM) {
145  }
146
147  void Select(SDOperand &Result, SDOperand Op);
148  virtual void InstructionSelectBasicBlock(SelectionDAG &DAG);
149
150  // Include the pieces autogenerated from the target description.
151#include "ARMGenDAGISel.inc"
152};
153
154void ARMDAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) {
155  DEBUG(BB->dump());
156
157  DAG.setRoot(SelectRoot(DAG.getRoot()));
158  assert(InFlightSet.empty() && "ISel InFlightSet has not been emptied!");
159  CodeGenMap.clear();
160  HandleMap.clear();
161  ReplaceMap.clear();
162  DAG.RemoveDeadNodes();
163
164  ScheduleAndEmitDAG(DAG);
165}
166
167void ARMDAGToDAGISel::Select(SDOperand &Result, SDOperand Op) {
168  SelectCode(Result, Op);
169}
170
171}  // end anonymous namespace
172
173/// createARMISelDag - This pass converts a legalized DAG into a
174/// ARM-specific DAG, ready for instruction scheduling.
175///
176FunctionPass *llvm::createARMISelDag(TargetMachine &TM) {
177  return new ARMDAGToDAGISel(TM);
178}
179