blob: 02b5dfa8106b045e39e57536f91b41599d947dae [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"
21
22typedef enum RegisterClass {
23 kCoreReg,
24 kFPReg,
25 kAnyReg,
26} RegisterClass;
27
28typedef enum RegLocationType {
29 kLocDalvikFrame = 0, // Normal Dalvik register
30 kLocPhysReg,
31 kLocSpill,
32} RegLocationType;
33
34typedef struct RegLocation {
35 RegLocationType location:2;
36 unsigned wide:1;
37 unsigned fp:1; // Hint for float/double
38 u1 lowReg:6; // First physical register
39 u1 highReg:6; // 2nd physical register (if wide)
40 s2 sRegLow; // SSA name for low Dalvik word
41 unsigned home:1; // Does this represent the home location?
42 RegLocationType fpLocation:2; // Used only for non-SSA loc records
43 u1 fpLowReg:6; // Used only for non-SSA loc records
44 u1 fpHighReg:6; // Used only for non-SSA loc records
45 int spOffset:17;
46} RegLocation;
47
48#define INVALID_SREG (-1)
49#define INVALID_REG (0x3F)
50#define INVALID_OFFSET (-1)
51
52typedef enum BBType {
53 kEntryBlock,
54 kDalvikByteCode,
55 kExitBlock,
56 kExceptionHandling,
57 kCatchEntry,
58} BBType;
59
60typedef struct LIR {
61 int offset; // Offset of this instruction
62 int dalvikOffset; // Offset of Dalvik opcode
63 struct LIR* next;
64 struct LIR* prev;
65 struct LIR* target;
66} LIR;
67
68enum ExtendedMIROpcode {
69 kMirOpFirst = kNumPackedOpcodes,
70 kMirOpPhi = kMirOpFirst,
71 kMirOpNullNRangeUpCheck,
72 kMirOpNullNRangeDownCheck,
73 kMirOpLowerBound,
74 kMirOpPunt,
75 kMirOpCheckInlinePrediction, // Gen checks for predicted inlining
76 kMirOpLast,
77};
78
79struct SSARepresentation;
80
81typedef enum {
82 kMIRIgnoreNullCheck = 0,
83 kMIRNullCheckOnly,
84 kMIRIgnoreRangeCheck,
85 kMIRRangeCheckOnly,
86 kMIRInlined, // Invoke is inlined (ie dead)
87 kMIRInlinedPred, // Invoke is inlined via prediction
88 kMIRCallee, // Instruction is inlined from callee
89} MIROptimizationFlagPositons;
90
91#define MIR_IGNORE_NULL_CHECK (1 << kMIRIgnoreNullCheck)
92#define MIR_NULL_CHECK_ONLY (1 << kMIRNullCheckOnly)
93#define MIR_IGNORE_RANGE_CHECK (1 << kMIRIgnoreRangeCheck)
94#define MIR_RANGE_CHECK_ONLY (1 << kMIRRangeCheckOnly)
95#define MIR_INLINED (1 << kMIRInlined)
96#define MIR_INLINED_PRED (1 << kMIRInlinedPred)
97#define MIR_CALLEE (1 << kMIRCallee)
98
99typedef struct CallsiteInfo {
100 const char* classDescriptor;
101 Object* classLoader;
102 const Method* method;
103 LIR* misPredBranchOver;
104} CallsiteInfo;
105
106typedef struct MIR {
107 DecodedInstruction dalvikInsn;
108 unsigned int width;
109 unsigned int offset;
110 struct MIR* prev;
111 struct MIR* next;
112 struct SSARepresentation* ssaRep;
113 int OptimizationFlags;
114 int seqNum;
115 union {
116 // Used by the inlined insn from the callee to find the mother method
117 const Method* calleeMethod;
118 // Used by the inlined invoke to find the class and method pointers
119 CallsiteInfo* callsiteInfo;
120 } meta;
121} MIR;
122
123struct BasicBlockDataFlow;
124
125/* For successorBlockList */
126typedef enum BlockListType {
127 kNotUsed = 0,
128 kCatch,
129 kPackedSwitch,
130 kSparseSwitch,
131} BlockListType;
132
133typedef struct BasicBlock {
134 int id;
135 bool visited;
136 bool hidden;
137 unsigned int startOffset;
138 const Method* containingMethod; // For blocks from the callee
139 BBType blockType;
140 bool needFallThroughBranch; // For blocks ended due to length limit
141 bool isFallThroughFromInvoke; // True means the block needs alignment
142 MIR* firstMIRInsn;
143 MIR* lastMIRInsn;
144 struct BasicBlock* fallThrough;
145 struct BasicBlock* taken;
146 struct BasicBlock* iDom; // Immediate dominator
147 struct BasicBlockDataFlow* dataFlowInfo;
148 ArenaBitVector* predecessors;
149 ArenaBitVector* dominators;
150 ArenaBitVector* iDominated; // Set nodes being immediately dominated
151 ArenaBitVector* domFrontier; // Dominance frontier
152 struct { // For one-to-many successors like
153 BlockListType blockListType; // switch and exception handling
154 GrowableList blocks;
155 } successorBlockList;
156} BasicBlock;
157
158/*
159 * The "blocks" field in "successorBlockList" points to an array of
160 * elements with the type "SuccessorBlockInfo".
161 * For catch blocks, key is type index for the exception.
162 * For swtich blocks, key is the case value.
163 */
164typedef struct SuccessorBlockInfo {
165 BasicBlock* block;
166 int key;
167} SuccessorBlockInfo;
168
169struct LoopAnalysis;
170struct RegisterPool;
171
172typedef enum AssemblerStatus {
173 kSuccess,
174 kRetryAll,
175 kRetryHalve
176} AssemblerStatus;
177
178typedef struct MappingTable {
179 int targetOffset;
180 int dalvikOffset;
181} MappingTable;
182
183typedef struct CompilationUnit {
184 int numInsts;
185 int numBlocks;
186 GrowableList blockList;
187 const Method *method;
188 LIR* firstLIRInsn;
189 LIR* lastLIRInsn;
190 LIR* literalList; // Constants
191 LIR* classPointerList; // Relocatable
192 int numClassPointers;
193 LIR* chainCellOffsetLIR;
194 int disableOpt;
195 int headerSize; // bytes before the first code ptr
196 int dataOffset; // starting offset of literal pool
197 int totalSize; // header + code size
198 AssemblerStatus assemblerStatus; // Success or fix and retry
199 int assemblerRetries;
200 unsigned char* codeBuffer;
201 void* baseAddr;
202 bool printMe;
203 bool printMeVerbose;
204 bool hasClassLiterals; // Contains class ptrs used as literals
205 bool hasLoop; // Contains a loop
206 bool hasInvoke; // Contains an invoke instruction
207 bool heapMemOp; // Mark mem ops for self verification
208 bool usesLinkRegister; // For self-verification only
209 bool methodTraceSupport; // For TraceView profiling
210 struct RegisterPool* regPool;
211 int optRound; // round number to tell an LIR's age
212 OatInstructionSetType instructionSet;
213 /* Number of total regs used in the whole cUnit after SSA transformation */
214 int numSSARegs;
215 /* Map SSA reg i to the Dalvik[15..0]/Sub[31..16] pair. */
216 GrowableList* ssaToDalvikMap;
217
218 /* The following are new data structures to support SSA representations */
219 /* Map original Dalvik reg i to the SSA[15..0]/Sub[31..16] pair */
220 int* dalvikToSSAMap; // length == method->registersSize
221 ArenaBitVector* isConstantV; // length == numSSAReg
222 int* constantValues; // length == numSSAReg
223
224 /* Map SSA names to location */
225 RegLocation* regLocation;
226 int sequenceNumber;
227
228 /*
229 * Set to the Dalvik PC of the switch instruction if it has more than
230 * MAX_CHAINED_SWITCH_CASES cases.
231 */
232 const u2* switchOverflowPad;
233
234 int numReachableBlocks;
235 int numDalvikRegisters; // method->registersSize + inlined
236 BasicBlock* entryBlock;
237 BasicBlock* exitBlock;
238 BasicBlock* curBlock;
239 BasicBlock* nextCodegenBlock; // for extended trace codegen
240 GrowableList dfsOrder;
241 GrowableList domPostOrderTraversal;
242 ArenaBitVector* tryBlockAddr;
243 ArenaBitVector** defBlockMatrix; // numDalvikRegister x numBlocks
244 ArenaBitVector* tempBlockV;
245 ArenaBitVector* tempDalvikRegisterV;
246 ArenaBitVector* tempSSARegisterV; // numSSARegs
247 bool printSSANames;
248 void* blockLabelList;
249 bool quitLoopMode; // cold path/complex bytecode
250 int preservedRegsUsed; // How many callee save regs used
251 /*
252 * Frame layout details. TODO: Reorganize, remove reduncancy
253 * and move elsewhere. Some of this is already in struct Method,
254 * at least frameSize should eventually move there. Delay regorg
255 * until we get a feel for how this will be used by the low-level
256 * codegen utilities. "num" fields are in 4-byte words, "Size" and
257 * "Offset" in bytes.
258 */
259 int numIns;
260 int numOuts;
261 int numRegs; // Unlike struct Method, does not include ins
262 int numSpills; // NOTE: includes numFPSpills
263 int numFPSpills;
264 int numPadding; // # of 4-byte padding cells
265 int regsOffset; // sp-relative offset to beginning of Dalvik regs
266 int insOffset; // sp-relative offset to beginning of Dalvik ins
267 int frameSize;
268 unsigned int coreSpillMask;
269 unsigned int fpSpillMask;
270 /*
271 * CLEANUP/RESTRUCTURE: The code generation utilities don't have a built-in
272 * mechanism to propogate the original Dalvik opcode address to the
273 * associated generated instructions. For the trace compiler, this wasn't
274 * necessary because the interpreter handled all throws and debugging
275 * requests. For now we'll handle this by placing the Dalvik offset
276 * in the CompilationUnit struct before codegen for each instruction.
277 * The low-level LIR creation utilites will pull it from here. Should
278 * be rewritten.
279 */
280 int currentDalvikOffset;
281 GrowableList switchTables;
282 int mappingTableSize;
283 MappingTable* mappingTable;
284 GrowableList fillArrayData;
285 const u2* insns;
286 u4 insnsSize;
287} CompilationUnit;
288
289BasicBlock* oatNewBB(BBType blockType, int blockId);
290
291void oatAppendMIR(BasicBlock* bb, MIR* mir);
292
293void oatPrependMIR(BasicBlock* bb, MIR* mir);
294
295void oatInsertMIRAfter(BasicBlock* bb, MIR* currentMIR, MIR* newMIR);
296
297void oatAppendLIR(CompilationUnit* cUnit, LIR* lir);
298
299void oatInsertLIRBefore(LIR* currentLIR, LIR* newLIR);
300
301void oatInsertLIRAfter(LIR* currentLIR, LIR* newLIR);
302
303/* Debug Utilities */
304void oatDumpCompilationUnit(CompilationUnit* cUnit);
305
306#endif // ART_SRC_COMPILER_COMPILER_IR_H_