Add lower argument and return of device function
[oota-llvm.git] / lib / Target / PTX / PTXISelLowering.cpp
1 //===-- PTXISelLowering.cpp - PTX DAG Lowering Implementation -------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the PTXTargetLowering class.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "PTX.h"
15 #include "PTXISelLowering.h"
16 #include "PTXRegisterInfo.h"
17 #include "llvm/Support/ErrorHandling.h"
18 #include "llvm/CodeGen/MachineFunction.h"
19 #include "llvm/CodeGen/MachineRegisterInfo.h"
20 #include "llvm/CodeGen/SelectionDAG.h"
21 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
22
23 using namespace llvm;
24
25 PTXTargetLowering::PTXTargetLowering(TargetMachine &TM)
26   : TargetLowering(TM, new TargetLoweringObjectFileELF()) {
27   // Set up the register classes.
28   addRegisterClass(MVT::i1,  PTX::PredsRegisterClass);
29   addRegisterClass(MVT::i32, PTX::RRegs32RegisterClass);
30
31   // Compute derived properties from the register classes
32   computeRegisterProperties();
33 }
34
35 const char *PTXTargetLowering::getTargetNodeName(unsigned Opcode) const {
36   switch (Opcode) {
37     default:           llvm_unreachable("Unknown opcode");
38     case PTXISD::EXIT: return "PTXISD::EXIT";
39     case PTXISD::RET:  return "PTXISD::RET";
40   }
41 }
42
43 //===----------------------------------------------------------------------===//
44 //                      Calling Convention Implementation
45 //===----------------------------------------------------------------------===//
46
47 static struct argmap_entry {
48   MVT::SimpleValueType VT;
49   TargetRegisterClass *RC;
50   TargetRegisterClass::iterator loc;
51
52   argmap_entry(MVT::SimpleValueType _VT, TargetRegisterClass *_RC)
53     : VT(_VT), RC(_RC), loc(_RC->begin()) {}
54
55   void reset(void) { loc = RC->begin(); }
56   bool operator==(MVT::SimpleValueType _VT) { return VT == _VT; }
57 } argmap[] = {
58   argmap_entry(MVT::i1,  PTX::PredsRegisterClass),
59   argmap_entry(MVT::i32, PTX::RRegs32RegisterClass)
60 };
61
62 static SDValue lower_kernel_argument(int i,
63                                      SDValue Chain,
64                                      DebugLoc dl,
65                                      MVT::SimpleValueType VT,
66                                      argmap_entry *entry,
67                                      SelectionDAG &DAG,
68                                      unsigned *argreg) {
69   // TODO
70   llvm_unreachable("Not implemented yet");
71 }
72
73 static SDValue lower_device_argument(int i,
74                                      SDValue Chain,
75                                      DebugLoc dl,
76                                      MVT::SimpleValueType VT,
77                                      argmap_entry *entry,
78                                      SelectionDAG &DAG,
79                                      unsigned *argreg) {
80   MachineRegisterInfo &RegInfo = DAG.getMachineFunction().getRegInfo();
81
82   unsigned preg = *++(entry->loc); // allocate start from register 1
83   unsigned vreg = RegInfo.createVirtualRegister(entry->RC);
84   RegInfo.addLiveIn(preg, vreg);
85
86   *argreg = preg;
87   return DAG.getCopyFromReg(Chain, dl, vreg, VT);
88 }
89
90 typedef SDValue (*lower_argument_func)(int i,
91                                        SDValue Chain,
92                                        DebugLoc dl,
93                                        MVT::SimpleValueType VT,
94                                        argmap_entry *entry,
95                                        SelectionDAG &DAG,
96                                        unsigned *argreg);
97
98 SDValue PTXTargetLowering::
99   LowerFormalArguments(SDValue Chain,
100                        CallingConv::ID CallConv,
101                        bool isVarArg,
102                        const SmallVectorImpl<ISD::InputArg> &Ins,
103                        DebugLoc dl,
104                        SelectionDAG &DAG,
105                        SmallVectorImpl<SDValue> &InVals) const {
106   if (isVarArg) llvm_unreachable("PTX does not support varargs");
107
108   lower_argument_func lower_argument;
109
110   switch (CallConv) {
111     default:
112       llvm_unreachable("Unsupported calling convention");
113       break;
114     case CallingConv::PTX_Kernel:
115       lower_argument = lower_kernel_argument;
116       break;
117     case CallingConv::PTX_Device:
118       lower_argument = lower_device_argument;
119       break;
120   }
121
122   // Reset argmap before allocation
123   for (struct argmap_entry *i = argmap, *e = argmap + array_lengthof(argmap);
124        i != e; ++ i)
125     i->reset();
126
127   for (int i = 0, e = Ins.size(); i != e; ++ i) {
128     MVT::SimpleValueType VT = Ins[i].VT.getSimpleVT().SimpleTy;
129
130     struct argmap_entry *entry = std::find(argmap,
131                                            argmap + array_lengthof(argmap), VT);
132     if (entry == argmap + array_lengthof(argmap))
133       llvm_unreachable("Type of argument is not supported");
134
135     unsigned reg;
136     SDValue arg = lower_argument(i, Chain, dl, VT, entry, DAG, &reg);
137     InVals.push_back(arg);
138   }
139
140   return Chain;
141 }
142
143 SDValue PTXTargetLowering::
144   LowerReturn(SDValue Chain,
145               CallingConv::ID CallConv,
146               bool isVarArg,
147               const SmallVectorImpl<ISD::OutputArg> &Outs,
148               const SmallVectorImpl<SDValue> &OutVals,
149               DebugLoc dl,
150               SelectionDAG &DAG) const {
151   if (isVarArg) llvm_unreachable("PTX does not support varargs");
152
153   switch (CallConv) {
154     default:
155       llvm_unreachable("Unsupported calling convention.");
156     case CallingConv::PTX_Kernel:
157       assert(Outs.size() == 0 && "Kernel must return void.");
158       return DAG.getNode(PTXISD::EXIT, dl, MVT::Other, Chain);
159     case CallingConv::PTX_Device:
160       assert(Outs.size() <= 1 && "Can at most return one value.");
161       break;
162   }
163
164   // PTX_Device
165
166   // return void
167   if (Outs.size() == 0)
168     return DAG.getNode(PTXISD::RET, dl, MVT::Other, Chain);
169
170   assert(Outs[0].VT == MVT::i32 && "Can return only basic types");
171
172   SDValue Flag;
173   unsigned reg = PTX::R0;
174
175   // If this is the first return lowered for this function, add the regs to the
176   // liveout set for the function
177   if (DAG.getMachineFunction().getRegInfo().liveout_empty())
178     DAG.getMachineFunction().getRegInfo().addLiveOut(reg);
179
180   // Copy the result values into the output registers
181   Chain = DAG.getCopyToReg(Chain, dl, reg, OutVals[0], Flag);
182
183   // Guarantee that all emitted copies are stuck together,
184   // avoiding something bad
185   Flag = Chain.getValue(1);
186
187   return DAG.getNode(PTXISD::RET, dl, MVT::Other, Chain, Flag);
188 }