blob: dac63cf29e7ff2ca739788ec47e0afb489360d14 [file] [log] [blame]
buzbee67bf8852011-08-17 17:51:35 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ART_SRC_COMPILER_COMPILER_IR_H_
18#define ART_SRC_COMPILER_COMPILER_IR_H_
19
20#include "codegen/Optimizer.h"
buzbeec143c552011-08-20 17:38:58 -070021#include <vector>
buzbee67bf8852011-08-17 17:51:35 -070022
23typedef enum RegisterClass {
24 kCoreReg,
25 kFPReg,
26 kAnyReg,
27} RegisterClass;
28
29typedef enum RegLocationType {
30 kLocDalvikFrame = 0, // Normal Dalvik register
31 kLocPhysReg,
32 kLocSpill,
33} RegLocationType;
34
35typedef struct RegLocation {
36 RegLocationType location:2;
37 unsigned wide:1;
38 unsigned fp:1; // Hint for float/double
39 u1 lowReg:6; // First physical register
40 u1 highReg:6; // 2nd physical register (if wide)
41 s2 sRegLow; // SSA name for low Dalvik word
42 unsigned home:1; // Does this represent the home location?
43 RegLocationType fpLocation:2; // Used only for non-SSA loc records
44 u1 fpLowReg:6; // Used only for non-SSA loc records
45 u1 fpHighReg:6; // Used only for non-SSA loc records
46 int spOffset:17;
47} RegLocation;
48
49#define INVALID_SREG (-1)
buzbee3ddc0d12011-10-05 10:36:21 -070050#define INVALID_VREG (0xFFFFU)
buzbee67bf8852011-08-17 17:51:35 -070051#define INVALID_REG (0x3F)
52#define INVALID_OFFSET (-1)
53
54typedef enum BBType {
55 kEntryBlock,
56 kDalvikByteCode,
57 kExitBlock,
58 kExceptionHandling,
59 kCatchEntry,
60} BBType;
61
62typedef struct LIR {
63 int offset; // Offset of this instruction
64 int dalvikOffset; // Offset of Dalvik opcode
65 struct LIR* next;
66 struct LIR* prev;
67 struct LIR* target;
68} LIR;
69
70enum ExtendedMIROpcode {
71 kMirOpFirst = kNumPackedOpcodes,
72 kMirOpPhi = kMirOpFirst,
73 kMirOpNullNRangeUpCheck,
74 kMirOpNullNRangeDownCheck,
75 kMirOpLowerBound,
76 kMirOpPunt,
77 kMirOpCheckInlinePrediction, // Gen checks for predicted inlining
78 kMirOpLast,
79};
80
81struct SSARepresentation;
82
83typedef enum {
84 kMIRIgnoreNullCheck = 0,
85 kMIRNullCheckOnly,
86 kMIRIgnoreRangeCheck,
87 kMIRRangeCheckOnly,
88 kMIRInlined, // Invoke is inlined (ie dead)
89 kMIRInlinedPred, // Invoke is inlined via prediction
90 kMIRCallee, // Instruction is inlined from callee
buzbeec1f45042011-09-21 16:03:19 -070091 kMIRIgnoreSuspendCheck,
buzbee67bf8852011-08-17 17:51:35 -070092} MIROptimizationFlagPositons;
93
94#define MIR_IGNORE_NULL_CHECK (1 << kMIRIgnoreNullCheck)
95#define MIR_NULL_CHECK_ONLY (1 << kMIRNullCheckOnly)
96#define MIR_IGNORE_RANGE_CHECK (1 << kMIRIgnoreRangeCheck)
97#define MIR_RANGE_CHECK_ONLY (1 << kMIRRangeCheckOnly)
98#define MIR_INLINED (1 << kMIRInlined)
99#define MIR_INLINED_PRED (1 << kMIRInlinedPred)
100#define MIR_CALLEE (1 << kMIRCallee)
buzbeec1f45042011-09-21 16:03:19 -0700101#define MIR_IGNORE_SUSPEND_CHECK (1 << kMIRIgnoreSuspendCheck)
buzbee67bf8852011-08-17 17:51:35 -0700102
103typedef struct CallsiteInfo {
104 const char* classDescriptor;
105 Object* classLoader;
106 const Method* method;
107 LIR* misPredBranchOver;
108} CallsiteInfo;
109
110typedef struct MIR {
111 DecodedInstruction dalvikInsn;
112 unsigned int width;
113 unsigned int offset;
114 struct MIR* prev;
115 struct MIR* next;
116 struct SSARepresentation* ssaRep;
buzbee43a36422011-09-14 14:00:13 -0700117 int optimizationFlags;
buzbee67bf8852011-08-17 17:51:35 -0700118 int seqNum;
119 union {
120 // Used by the inlined insn from the callee to find the mother method
121 const Method* calleeMethod;
122 // Used by the inlined invoke to find the class and method pointers
123 CallsiteInfo* callsiteInfo;
buzbeec0ecd652011-09-25 18:11:54 -0700124 // Used to quickly locate all Phi opcodes
125 struct MIR* phiNext;
buzbee67bf8852011-08-17 17:51:35 -0700126 } meta;
127} MIR;
128
129struct BasicBlockDataFlow;
130
131/* For successorBlockList */
132typedef enum BlockListType {
133 kNotUsed = 0,
134 kCatch,
135 kPackedSwitch,
136 kSparseSwitch,
137} BlockListType;
138
139typedef struct BasicBlock {
140 int id;
141 bool visited;
142 bool hidden;
buzbee43a36422011-09-14 14:00:13 -0700143 bool catchEntry;
buzbee67bf8852011-08-17 17:51:35 -0700144 unsigned int startOffset;
145 const Method* containingMethod; // For blocks from the callee
146 BBType blockType;
147 bool needFallThroughBranch; // For blocks ended due to length limit
148 bool isFallThroughFromInvoke; // True means the block needs alignment
149 MIR* firstMIRInsn;
150 MIR* lastMIRInsn;
151 struct BasicBlock* fallThrough;
152 struct BasicBlock* taken;
153 struct BasicBlock* iDom; // Immediate dominator
154 struct BasicBlockDataFlow* dataFlowInfo;
155 ArenaBitVector* predecessors;
156 ArenaBitVector* dominators;
157 ArenaBitVector* iDominated; // Set nodes being immediately dominated
158 ArenaBitVector* domFrontier; // Dominance frontier
159 struct { // For one-to-many successors like
160 BlockListType blockListType; // switch and exception handling
161 GrowableList blocks;
162 } successorBlockList;
163} BasicBlock;
164
165/*
166 * The "blocks" field in "successorBlockList" points to an array of
167 * elements with the type "SuccessorBlockInfo".
168 * For catch blocks, key is type index for the exception.
169 * For swtich blocks, key is the case value.
170 */
171typedef struct SuccessorBlockInfo {
172 BasicBlock* block;
173 int key;
174} SuccessorBlockInfo;
175
176struct LoopAnalysis;
177struct RegisterPool;
178
179typedef enum AssemblerStatus {
180 kSuccess,
181 kRetryAll,
182 kRetryHalve
183} AssemblerStatus;
184
buzbee67bf8852011-08-17 17:51:35 -0700185typedef struct CompilationUnit {
186 int numInsts;
187 int numBlocks;
188 GrowableList blockList;
Brian Carlstrom928bf022011-10-11 02:48:14 -0700189 const Compiler* compiler;
190 const Method* method;
buzbee67bf8852011-08-17 17:51:35 -0700191 LIR* firstLIRInsn;
192 LIR* lastLIRInsn;
193 LIR* literalList; // Constants
194 LIR* classPointerList; // Relocatable
195 int numClassPointers;
196 LIR* chainCellOffsetLIR;
buzbeece302932011-10-04 14:32:18 -0700197 uint32_t disableOpt; // optControlVector flags
198 uint32_t enableDebug; // debugControlVector flags
buzbee67bf8852011-08-17 17:51:35 -0700199 int headerSize; // bytes before the first code ptr
200 int dataOffset; // starting offset of literal pool
201 int totalSize; // header + code size
202 AssemblerStatus assemblerStatus; // Success or fix and retry
203 int assemblerRetries;
buzbee4ef76522011-09-08 10:00:32 -0700204 std::vector<short> codeBuffer;
205 std::vector<uint32_t> mappingTable;
buzbee3ddc0d12011-10-05 10:36:21 -0700206 std::vector<uint16_t> coreVmapTable;
207 std::vector<uint16_t> fpVmapTable;
buzbee67bf8852011-08-17 17:51:35 -0700208 bool printMe;
buzbee67bf8852011-08-17 17:51:35 -0700209 bool hasClassLiterals; // Contains class ptrs used as literals
210 bool hasLoop; // Contains a loop
211 bool hasInvoke; // Contains an invoke instruction
212 bool heapMemOp; // Mark mem ops for self verification
213 bool usesLinkRegister; // For self-verification only
214 bool methodTraceSupport; // For TraceView profiling
215 struct RegisterPool* regPool;
216 int optRound; // round number to tell an LIR's age
217 OatInstructionSetType instructionSet;
218 /* Number of total regs used in the whole cUnit after SSA transformation */
219 int numSSARegs;
220 /* Map SSA reg i to the Dalvik[15..0]/Sub[31..16] pair. */
221 GrowableList* ssaToDalvikMap;
222
223 /* The following are new data structures to support SSA representations */
224 /* Map original Dalvik reg i to the SSA[15..0]/Sub[31..16] pair */
225 int* dalvikToSSAMap; // length == method->registersSize
buzbeef0cde542011-09-13 14:55:02 -0700226 int* SSALastDefs; // length == method->registersSize
buzbee67bf8852011-08-17 17:51:35 -0700227 ArenaBitVector* isConstantV; // length == numSSAReg
228 int* constantValues; // length == numSSAReg
buzbeec0ecd652011-09-25 18:11:54 -0700229 int* phiAliasMap; // length == numSSAReg
230 MIR* phiList;
buzbee67bf8852011-08-17 17:51:35 -0700231
232 /* Map SSA names to location */
233 RegLocation* regLocation;
234 int sequenceNumber;
235
236 /*
237 * Set to the Dalvik PC of the switch instruction if it has more than
238 * MAX_CHAINED_SWITCH_CASES cases.
239 */
240 const u2* switchOverflowPad;
241
242 int numReachableBlocks;
243 int numDalvikRegisters; // method->registersSize + inlined
244 BasicBlock* entryBlock;
245 BasicBlock* exitBlock;
246 BasicBlock* curBlock;
247 BasicBlock* nextCodegenBlock; // for extended trace codegen
248 GrowableList dfsOrder;
249 GrowableList domPostOrderTraversal;
buzbee5ade1d22011-09-09 14:44:52 -0700250 GrowableList throwLaunchpads;
buzbeec1f45042011-09-21 16:03:19 -0700251 GrowableList suspendLaunchpads;
buzbee67bf8852011-08-17 17:51:35 -0700252 ArenaBitVector* tryBlockAddr;
253 ArenaBitVector** defBlockMatrix; // numDalvikRegister x numBlocks
254 ArenaBitVector* tempBlockV;
255 ArenaBitVector* tempDalvikRegisterV;
256 ArenaBitVector* tempSSARegisterV; // numSSARegs
257 bool printSSANames;
258 void* blockLabelList;
259 bool quitLoopMode; // cold path/complex bytecode
260 int preservedRegsUsed; // How many callee save regs used
261 /*
buzbee5ade1d22011-09-09 14:44:52 -0700262 * Frame layout details.
263 * NOTE: for debug support it will be necessary to add a structure
264 * to map the Dalvik virtual registers to the promoted registers.
265 * NOTE: "num" fields are in 4-byte words, "Size" and "Offset" in bytes.
buzbee67bf8852011-08-17 17:51:35 -0700266 */
267 int numIns;
268 int numOuts;
269 int numRegs; // Unlike struct Method, does not include ins
buzbeebbaf8942011-10-02 13:08:29 -0700270 int numCoreSpills;
buzbee67bf8852011-08-17 17:51:35 -0700271 int numFPSpills;
272 int numPadding; // # of 4-byte padding cells
273 int regsOffset; // sp-relative offset to beginning of Dalvik regs
274 int insOffset; // sp-relative offset to beginning of Dalvik ins
275 int frameSize;
276 unsigned int coreSpillMask;
277 unsigned int fpSpillMask;
buzbeecefd1872011-09-09 09:59:52 -0700278 unsigned int attrs;
buzbee67bf8852011-08-17 17:51:35 -0700279 /*
280 * CLEANUP/RESTRUCTURE: The code generation utilities don't have a built-in
buzbee03fa2632011-09-20 17:10:57 -0700281 * mechanism to propagate the original Dalvik opcode address to the
buzbee67bf8852011-08-17 17:51:35 -0700282 * associated generated instructions. For the trace compiler, this wasn't
283 * necessary because the interpreter handled all throws and debugging
284 * requests. For now we'll handle this by placing the Dalvik offset
285 * in the CompilationUnit struct before codegen for each instruction.
286 * The low-level LIR creation utilites will pull it from here. Should
287 * be rewritten.
288 */
289 int currentDalvikOffset;
290 GrowableList switchTables;
buzbee67bf8852011-08-17 17:51:35 -0700291 GrowableList fillArrayData;
292 const u2* insns;
293 u4 insnsSize;
294} CompilationUnit;
295
296BasicBlock* oatNewBB(BBType blockType, int blockId);
297
298void oatAppendMIR(BasicBlock* bb, MIR* mir);
299
300void oatPrependMIR(BasicBlock* bb, MIR* mir);
301
302void oatInsertMIRAfter(BasicBlock* bb, MIR* currentMIR, MIR* newMIR);
303
304void oatAppendLIR(CompilationUnit* cUnit, LIR* lir);
305
306void oatInsertLIRBefore(LIR* currentLIR, LIR* newLIR);
307
308void oatInsertLIRAfter(LIR* currentLIR, LIR* newLIR);
309
310/* Debug Utilities */
311void oatDumpCompilationUnit(CompilationUnit* cUnit);
312
313#endif // ART_SRC_COMPILER_COMPILER_IR_H_