blob: 0965c1421867db39102ef4a11fe0642cd30c2b1e [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)
50#define INVALID_REG (0x3F)
51#define INVALID_OFFSET (-1)
52
53typedef enum BBType {
54 kEntryBlock,
55 kDalvikByteCode,
56 kExitBlock,
57 kExceptionHandling,
58 kCatchEntry,
59} BBType;
60
61typedef struct LIR {
62 int offset; // Offset of this instruction
63 int dalvikOffset; // Offset of Dalvik opcode
64 struct LIR* next;
65 struct LIR* prev;
66 struct LIR* target;
67} LIR;
68
69enum ExtendedMIROpcode {
70 kMirOpFirst = kNumPackedOpcodes,
71 kMirOpPhi = kMirOpFirst,
72 kMirOpNullNRangeUpCheck,
73 kMirOpNullNRangeDownCheck,
74 kMirOpLowerBound,
75 kMirOpPunt,
76 kMirOpCheckInlinePrediction, // Gen checks for predicted inlining
77 kMirOpLast,
78};
79
80struct SSARepresentation;
81
82typedef enum {
83 kMIRIgnoreNullCheck = 0,
84 kMIRNullCheckOnly,
85 kMIRIgnoreRangeCheck,
86 kMIRRangeCheckOnly,
87 kMIRInlined, // Invoke is inlined (ie dead)
88 kMIRInlinedPred, // Invoke is inlined via prediction
89 kMIRCallee, // Instruction is inlined from callee
buzbeec1f45042011-09-21 16:03:19 -070090 kMIRIgnoreSuspendCheck,
buzbee67bf8852011-08-17 17:51:35 -070091} MIROptimizationFlagPositons;
92
93#define MIR_IGNORE_NULL_CHECK (1 << kMIRIgnoreNullCheck)
94#define MIR_NULL_CHECK_ONLY (1 << kMIRNullCheckOnly)
95#define MIR_IGNORE_RANGE_CHECK (1 << kMIRIgnoreRangeCheck)
96#define MIR_RANGE_CHECK_ONLY (1 << kMIRRangeCheckOnly)
97#define MIR_INLINED (1 << kMIRInlined)
98#define MIR_INLINED_PRED (1 << kMIRInlinedPred)
99#define MIR_CALLEE (1 << kMIRCallee)
buzbeec1f45042011-09-21 16:03:19 -0700100#define MIR_IGNORE_SUSPEND_CHECK (1 << kMIRIgnoreSuspendCheck)
buzbee67bf8852011-08-17 17:51:35 -0700101
102typedef struct CallsiteInfo {
103 const char* classDescriptor;
104 Object* classLoader;
105 const Method* method;
106 LIR* misPredBranchOver;
107} CallsiteInfo;
108
109typedef struct MIR {
110 DecodedInstruction dalvikInsn;
111 unsigned int width;
112 unsigned int offset;
113 struct MIR* prev;
114 struct MIR* next;
115 struct SSARepresentation* ssaRep;
buzbee43a36422011-09-14 14:00:13 -0700116 int optimizationFlags;
buzbee67bf8852011-08-17 17:51:35 -0700117 int seqNum;
118 union {
119 // Used by the inlined insn from the callee to find the mother method
120 const Method* calleeMethod;
121 // Used by the inlined invoke to find the class and method pointers
122 CallsiteInfo* callsiteInfo;
123 } meta;
124} MIR;
125
126struct BasicBlockDataFlow;
127
128/* For successorBlockList */
129typedef enum BlockListType {
130 kNotUsed = 0,
131 kCatch,
132 kPackedSwitch,
133 kSparseSwitch,
134} BlockListType;
135
136typedef struct BasicBlock {
137 int id;
138 bool visited;
139 bool hidden;
buzbee43a36422011-09-14 14:00:13 -0700140 bool catchEntry;
buzbee67bf8852011-08-17 17:51:35 -0700141 unsigned int startOffset;
142 const Method* containingMethod; // For blocks from the callee
143 BBType blockType;
144 bool needFallThroughBranch; // For blocks ended due to length limit
145 bool isFallThroughFromInvoke; // True means the block needs alignment
146 MIR* firstMIRInsn;
147 MIR* lastMIRInsn;
148 struct BasicBlock* fallThrough;
149 struct BasicBlock* taken;
150 struct BasicBlock* iDom; // Immediate dominator
151 struct BasicBlockDataFlow* dataFlowInfo;
152 ArenaBitVector* predecessors;
153 ArenaBitVector* dominators;
154 ArenaBitVector* iDominated; // Set nodes being immediately dominated
155 ArenaBitVector* domFrontier; // Dominance frontier
156 struct { // For one-to-many successors like
157 BlockListType blockListType; // switch and exception handling
158 GrowableList blocks;
159 } successorBlockList;
160} BasicBlock;
161
162/*
163 * The "blocks" field in "successorBlockList" points to an array of
164 * elements with the type "SuccessorBlockInfo".
165 * For catch blocks, key is type index for the exception.
166 * For swtich blocks, key is the case value.
167 */
168typedef struct SuccessorBlockInfo {
169 BasicBlock* block;
170 int key;
171} SuccessorBlockInfo;
172
173struct LoopAnalysis;
174struct RegisterPool;
175
176typedef enum AssemblerStatus {
177 kSuccess,
178 kRetryAll,
179 kRetryHalve
180} AssemblerStatus;
181
buzbee67bf8852011-08-17 17:51:35 -0700182typedef struct CompilationUnit {
183 int numInsts;
184 int numBlocks;
185 GrowableList blockList;
186 const Method *method;
187 LIR* firstLIRInsn;
188 LIR* lastLIRInsn;
189 LIR* literalList; // Constants
190 LIR* classPointerList; // Relocatable
191 int numClassPointers;
192 LIR* chainCellOffsetLIR;
193 int disableOpt;
194 int headerSize; // bytes before the first code ptr
195 int dataOffset; // starting offset of literal pool
196 int totalSize; // header + code size
197 AssemblerStatus assemblerStatus; // Success or fix and retry
198 int assemblerRetries;
buzbee4ef76522011-09-08 10:00:32 -0700199 std::vector<short> codeBuffer;
200 std::vector<uint32_t> mappingTable;
buzbee67bf8852011-08-17 17:51:35 -0700201 bool printMe;
202 bool printMeVerbose;
buzbeeec5adf32011-09-11 15:25:43 -0700203 bool dumpCFG;
buzbee67bf8852011-08-17 17:51:35 -0700204 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
buzbeef0cde542011-09-13 14:55:02 -0700221 int* SSALastDefs; // length == method->registersSize
buzbee67bf8852011-08-17 17:51:35 -0700222 ArenaBitVector* isConstantV; // length == numSSAReg
223 int* constantValues; // length == numSSAReg
224
225 /* Map SSA names to location */
226 RegLocation* regLocation;
227 int sequenceNumber;
228
229 /*
230 * Set to the Dalvik PC of the switch instruction if it has more than
231 * MAX_CHAINED_SWITCH_CASES cases.
232 */
233 const u2* switchOverflowPad;
234
235 int numReachableBlocks;
236 int numDalvikRegisters; // method->registersSize + inlined
237 BasicBlock* entryBlock;
238 BasicBlock* exitBlock;
239 BasicBlock* curBlock;
240 BasicBlock* nextCodegenBlock; // for extended trace codegen
241 GrowableList dfsOrder;
242 GrowableList domPostOrderTraversal;
buzbee5ade1d22011-09-09 14:44:52 -0700243 GrowableList throwLaunchpads;
buzbeec1f45042011-09-21 16:03:19 -0700244 GrowableList suspendLaunchpads;
buzbee67bf8852011-08-17 17:51:35 -0700245 ArenaBitVector* tryBlockAddr;
246 ArenaBitVector** defBlockMatrix; // numDalvikRegister x numBlocks
247 ArenaBitVector* tempBlockV;
248 ArenaBitVector* tempDalvikRegisterV;
249 ArenaBitVector* tempSSARegisterV; // numSSARegs
250 bool printSSANames;
251 void* blockLabelList;
252 bool quitLoopMode; // cold path/complex bytecode
253 int preservedRegsUsed; // How many callee save regs used
254 /*
buzbee5ade1d22011-09-09 14:44:52 -0700255 * Frame layout details.
256 * NOTE: for debug support it will be necessary to add a structure
257 * to map the Dalvik virtual registers to the promoted registers.
258 * NOTE: "num" fields are in 4-byte words, "Size" and "Offset" in bytes.
buzbee67bf8852011-08-17 17:51:35 -0700259 */
260 int numIns;
261 int numOuts;
262 int numRegs; // Unlike struct Method, does not include ins
263 int numSpills; // NOTE: includes numFPSpills
264 int numFPSpills;
265 int numPadding; // # of 4-byte padding cells
266 int regsOffset; // sp-relative offset to beginning of Dalvik regs
267 int insOffset; // sp-relative offset to beginning of Dalvik ins
268 int frameSize;
269 unsigned int coreSpillMask;
270 unsigned int fpSpillMask;
buzbeecefd1872011-09-09 09:59:52 -0700271 unsigned int attrs;
buzbee67bf8852011-08-17 17:51:35 -0700272 /*
273 * CLEANUP/RESTRUCTURE: The code generation utilities don't have a built-in
buzbee03fa2632011-09-20 17:10:57 -0700274 * mechanism to propagate the original Dalvik opcode address to the
buzbee67bf8852011-08-17 17:51:35 -0700275 * associated generated instructions. For the trace compiler, this wasn't
276 * necessary because the interpreter handled all throws and debugging
277 * requests. For now we'll handle this by placing the Dalvik offset
278 * in the CompilationUnit struct before codegen for each instruction.
279 * The low-level LIR creation utilites will pull it from here. Should
280 * be rewritten.
281 */
282 int currentDalvikOffset;
283 GrowableList switchTables;
buzbee67bf8852011-08-17 17:51:35 -0700284 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_