blob: acc7c945f0f27e107655b44311dc933cb5f03af8 [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"
Ian Rogers1bddec32012-02-04 12:27:34 -080021#include "CompilerUtility.h"
buzbeec143c552011-08-20 17:38:58 -070022#include <vector>
buzbee31a4a6f2012-02-28 15:36:15 -080023#include "oat_compilation_unit.h"
buzbee67bf8852011-08-17 17:51:35 -070024
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080025namespace art {
26
buzbee31a4a6f2012-02-28 15:36:15 -080027#define SLOW_FIELD_PATH (cUnit->enableDebug & (1 << kDebugSlowFieldPath))
28#define SLOW_INVOKE_PATH (cUnit->enableDebug & (1 << kDebugSlowInvokePath))
29#define SLOW_STRING_PATH (cUnit->enableDebug & (1 << kDebugSlowStringPath))
30#define SLOW_TYPE_PATH (cUnit->enableDebug & (1 << kDebugSlowTypePath))
31#define EXERCISE_SLOWEST_FIELD_PATH (cUnit->enableDebug & \
32 (1 << kDebugSlowestFieldPath))
33#define EXERCISE_SLOWEST_STRING_PATH (cUnit->enableDebug & \
34 (1 << kDebugSlowestStringPath))
35#define EXERCISE_RESOLVE_METHOD (cUnit->enableDebug & \
36 (1 << kDebugExerciseResolveMethod))
37
Elliott Hughes719ace42012-03-09 18:06:03 -080038enum RegisterClass {
buzbee67bf8852011-08-17 17:51:35 -070039 kCoreReg,
40 kFPReg,
41 kAnyReg,
Elliott Hughes719ace42012-03-09 18:06:03 -080042};
buzbee67bf8852011-08-17 17:51:35 -070043
Elliott Hughes719ace42012-03-09 18:06:03 -080044enum RegLocationType {
buzbee67bf8852011-08-17 17:51:35 -070045 kLocDalvikFrame = 0, // Normal Dalvik register
46 kLocPhysReg,
buzbeee1965672012-03-11 18:39:19 -070047 kLocCompilerTemp,
Elliott Hughes719ace42012-03-09 18:06:03 -080048};
buzbee67bf8852011-08-17 17:51:35 -070049
Elliott Hughes719ace42012-03-09 18:06:03 -080050struct PromotionMap {
buzbee67bc2362011-10-11 18:08:40 -070051 RegLocationType coreLocation:3;
52 u1 coreReg;
53 RegLocationType fpLocation:3;
54 u1 fpReg;
55 bool firstInPair;
Elliott Hughes719ace42012-03-09 18:06:03 -080056};
buzbee67bc2362011-10-11 18:08:40 -070057
Elliott Hughes719ace42012-03-09 18:06:03 -080058struct RegLocation {
buzbee67bc2362011-10-11 18:08:40 -070059 RegLocationType location:3;
buzbee67bf8852011-08-17 17:51:35 -070060 unsigned wide:1;
buzbee67bc2362011-10-11 18:08:40 -070061 unsigned defined:1; // Do we know the type?
62 unsigned fp:1; // Floating point?
63 unsigned core:1; // Non-floating point?
64 unsigned highWord:1; // High word of pair?
65 unsigned home:1; // Does this represent the home location?
66 u1 lowReg; // First physical register
67 u1 highReg; // 2nd physical register (if wide)
buzbeee1965672012-03-11 18:39:19 -070068 int32_t sRegLow; // SSA name for low Dalvik word
69};
70
71struct CompilerTemp {
72 int sReg;
73 ArenaBitVector* bv;
Elliott Hughes719ace42012-03-09 18:06:03 -080074};
buzbee67bf8852011-08-17 17:51:35 -070075
buzbeee3acd072012-02-25 17:03:10 -080076 /*
77 * Data structure tracking the mapping between a Dalvik register (pair) and a
78 * native register (pair). The idea is to reuse the previously loaded value
79 * if possible, otherwise to keep the value in a native register as long as
80 * possible.
81 */
Elliott Hughes719ace42012-03-09 18:06:03 -080082struct RegisterInfo {
buzbeee3acd072012-02-25 17:03:10 -080083 int reg; // Reg number
84 bool inUse; // Has it been allocated?
85 bool isTemp; // Can allocate as temp?
86 bool pair; // Part of a register pair?
87 int partner; // If pair, other reg of pair
88 bool live; // Is there an associated SSA name?
89 bool dirty; // If live, is it dirty?
90 int sReg; // Name of live value
91 struct LIR *defStart; // Starting inst in last def sequence
92 struct LIR *defEnd; // Ending inst in last def sequence
Elliott Hughes719ace42012-03-09 18:06:03 -080093};
buzbeee3acd072012-02-25 17:03:10 -080094
Elliott Hughes719ace42012-03-09 18:06:03 -080095struct RegisterPool {
buzbeee3acd072012-02-25 17:03:10 -080096 int numCoreRegs;
97 RegisterInfo *coreRegs;
98 int nextCoreReg;
99 int numFPRegs;
100 RegisterInfo *FPRegs;
101 int nextFPReg;
Elliott Hughes719ace42012-03-09 18:06:03 -0800102};
buzbeee3acd072012-02-25 17:03:10 -0800103
buzbee67bf8852011-08-17 17:51:35 -0700104#define INVALID_SREG (-1)
buzbee3ddc0d12011-10-05 10:36:21 -0700105#define INVALID_VREG (0xFFFFU)
buzbee67bc2362011-10-11 18:08:40 -0700106#define INVALID_REG (0xFF)
buzbee67bf8852011-08-17 17:51:35 -0700107#define INVALID_OFFSET (-1)
108
buzbeee1965672012-03-11 18:39:19 -0700109/* SSA encodings for special registers */
buzbee9c044ce2012-03-18 13:24:07 -0700110#define SSA_METHOD_BASEREG (-2)
buzbeee1965672012-03-11 18:39:19 -0700111/* First compiler temp basereg, grows smaller */
buzbee9c044ce2012-03-18 13:24:07 -0700112#define SSA_CTEMP_BASEREG (SSA_METHOD_BASEREG - 1)
buzbeee1965672012-03-11 18:39:19 -0700113
buzbee99ba9642012-01-25 14:23:14 -0800114/*
115 * Some code patterns cause the generation of excessively large
116 * methods - in particular initialization sequences. There isn't much
117 * benefit in optimizing these methods, and the cost can be very high.
118 * We attempt to identify these cases, and avoid performing most dataflow
119 * analysis. Two thresholds are used - one for known initializers and one
buzbee5abfa3e2012-01-31 17:01:43 -0800120 * for everything else.
buzbee99ba9642012-01-25 14:23:14 -0800121 */
buzbee5abfa3e2012-01-31 17:01:43 -0800122#define MANY_BLOCKS_INITIALIZER 1000 /* Threshold for switching dataflow off */
123#define MANY_BLOCKS 4000 /* Non-initializer threshold */
buzbee99ba9642012-01-25 14:23:14 -0800124
Elliott Hughes719ace42012-03-09 18:06:03 -0800125enum BBType {
buzbee67bf8852011-08-17 17:51:35 -0700126 kEntryBlock,
127 kDalvikByteCode,
128 kExitBlock,
129 kExceptionHandling,
130 kCatchEntry,
Elliott Hughes719ace42012-03-09 18:06:03 -0800131};
buzbee67bf8852011-08-17 17:51:35 -0700132
buzbee31a4a6f2012-02-28 15:36:15 -0800133/* Utility macros to traverse the LIR list */
134#define NEXT_LIR(lir) (lir->next)
135#define PREV_LIR(lir) (lir->prev)
136
137#define NEXT_LIR_LVALUE(lir) (lir)->next
138#define PREV_LIR_LVALUE(lir) (lir)->prev
139
Elliott Hughes719ace42012-03-09 18:06:03 -0800140struct LIR {
buzbee67bf8852011-08-17 17:51:35 -0700141 int offset; // Offset of this instruction
142 int dalvikOffset; // Offset of Dalvik opcode
143 struct LIR* next;
144 struct LIR* prev;
145 struct LIR* target;
buzbee31a4a6f2012-02-28 15:36:15 -0800146 int opcode;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800147 int operands[5]; // [0..4] = [dest, src1, src2, extra, extra2]
buzbee31a4a6f2012-02-28 15:36:15 -0800148 struct {
149 bool isNop:1; // LIR is optimized away
150 bool pcRelFixup:1; // May need pc-relative fixup
151 unsigned int age:4; // default is 0, set lazily by the optimizer
buzbee71ac9942012-03-01 17:23:10 -0800152 unsigned int size:5; // in bytes
153 unsigned int unused:21;
buzbee31a4a6f2012-02-28 15:36:15 -0800154 } flags;
155 int aliasInfo; // For Dalvik register & litpool disambiguation
156 u8 useMask; // Resource mask for use
157 u8 defMask; // Resource mask for def
Elliott Hughes719ace42012-03-09 18:06:03 -0800158};
buzbee67bf8852011-08-17 17:51:35 -0700159
160enum ExtendedMIROpcode {
161 kMirOpFirst = kNumPackedOpcodes,
162 kMirOpPhi = kMirOpFirst,
163 kMirOpNullNRangeUpCheck,
164 kMirOpNullNRangeDownCheck,
165 kMirOpLowerBound,
buzbeee1965672012-03-11 18:39:19 -0700166 kMirOpCopy,
buzbee67bf8852011-08-17 17:51:35 -0700167 kMirOpLast,
168};
169
170struct SSARepresentation;
171
Elliott Hughes719ace42012-03-09 18:06:03 -0800172enum MIROptimizationFlagPositons {
buzbee67bf8852011-08-17 17:51:35 -0700173 kMIRIgnoreNullCheck = 0,
174 kMIRNullCheckOnly,
175 kMIRIgnoreRangeCheck,
176 kMIRRangeCheckOnly,
177 kMIRInlined, // Invoke is inlined (ie dead)
178 kMIRInlinedPred, // Invoke is inlined via prediction
179 kMIRCallee, // Instruction is inlined from callee
buzbeec1f45042011-09-21 16:03:19 -0700180 kMIRIgnoreSuspendCheck,
buzbeee1965672012-03-11 18:39:19 -0700181 kMIRDup,
buzbee239c4e72012-03-16 08:42:29 -0700182 kMIRMark, // Temporary node mark
Elliott Hughes719ace42012-03-09 18:06:03 -0800183};
buzbee67bf8852011-08-17 17:51:35 -0700184
185#define MIR_IGNORE_NULL_CHECK (1 << kMIRIgnoreNullCheck)
186#define MIR_NULL_CHECK_ONLY (1 << kMIRNullCheckOnly)
187#define MIR_IGNORE_RANGE_CHECK (1 << kMIRIgnoreRangeCheck)
188#define MIR_RANGE_CHECK_ONLY (1 << kMIRRangeCheckOnly)
189#define MIR_INLINED (1 << kMIRInlined)
190#define MIR_INLINED_PRED (1 << kMIRInlinedPred)
191#define MIR_CALLEE (1 << kMIRCallee)
buzbeec1f45042011-09-21 16:03:19 -0700192#define MIR_IGNORE_SUSPEND_CHECK (1 << kMIRIgnoreSuspendCheck)
buzbeee1965672012-03-11 18:39:19 -0700193#define MIR_DUP (1 << kMIRDup)
buzbee239c4e72012-03-16 08:42:29 -0700194#define MIR_MARK (1 << kMIRMark)
buzbee67bf8852011-08-17 17:51:35 -0700195
Elliott Hughes719ace42012-03-09 18:06:03 -0800196struct CallsiteInfo {
buzbee67bf8852011-08-17 17:51:35 -0700197 const char* classDescriptor;
198 Object* classLoader;
199 const Method* method;
200 LIR* misPredBranchOver;
Elliott Hughes719ace42012-03-09 18:06:03 -0800201};
buzbee67bf8852011-08-17 17:51:35 -0700202
Elliott Hughes719ace42012-03-09 18:06:03 -0800203struct MIR {
buzbee67bf8852011-08-17 17:51:35 -0700204 DecodedInstruction dalvikInsn;
205 unsigned int width;
206 unsigned int offset;
207 struct MIR* prev;
208 struct MIR* next;
209 struct SSARepresentation* ssaRep;
buzbee43a36422011-09-14 14:00:13 -0700210 int optimizationFlags;
buzbee67bf8852011-08-17 17:51:35 -0700211 int seqNum;
212 union {
213 // Used by the inlined insn from the callee to find the mother method
214 const Method* calleeMethod;
215 // Used by the inlined invoke to find the class and method pointers
216 CallsiteInfo* callsiteInfo;
buzbeec0ecd652011-09-25 18:11:54 -0700217 // Used to quickly locate all Phi opcodes
218 struct MIR* phiNext;
buzbee67bf8852011-08-17 17:51:35 -0700219 } meta;
Elliott Hughes719ace42012-03-09 18:06:03 -0800220};
buzbee67bf8852011-08-17 17:51:35 -0700221
222struct BasicBlockDataFlow;
223
224/* For successorBlockList */
Elliott Hughes719ace42012-03-09 18:06:03 -0800225enum BlockListType {
buzbee67bf8852011-08-17 17:51:35 -0700226 kNotUsed = 0,
227 kCatch,
228 kPackedSwitch,
229 kSparseSwitch,
Elliott Hughes719ace42012-03-09 18:06:03 -0800230};
buzbee67bf8852011-08-17 17:51:35 -0700231
Elliott Hughes719ace42012-03-09 18:06:03 -0800232struct BasicBlock {
buzbee67bf8852011-08-17 17:51:35 -0700233 int id;
buzbee5b537102012-01-17 17:33:47 -0800234 int dfsId;
buzbee67bf8852011-08-17 17:51:35 -0700235 bool visited;
236 bool hidden;
buzbee43a36422011-09-14 14:00:13 -0700237 bool catchEntry;
buzbeee1965672012-03-11 18:39:19 -0700238 bool fallThroughTarget; // Reached via fallthrough
buzbee239c4e72012-03-16 08:42:29 -0700239 uint16_t startOffset;
240 uint16_t nestingDepth;
buzbee67bf8852011-08-17 17:51:35 -0700241 const Method* containingMethod; // For blocks from the callee
242 BBType blockType;
243 bool needFallThroughBranch; // For blocks ended due to length limit
244 bool isFallThroughFromInvoke; // True means the block needs alignment
245 MIR* firstMIRInsn;
246 MIR* lastMIRInsn;
247 struct BasicBlock* fallThrough;
248 struct BasicBlock* taken;
249 struct BasicBlock* iDom; // Immediate dominator
250 struct BasicBlockDataFlow* dataFlowInfo;
buzbee5abfa3e2012-01-31 17:01:43 -0800251 GrowableList* predecessors;
buzbee67bf8852011-08-17 17:51:35 -0700252 ArenaBitVector* dominators;
253 ArenaBitVector* iDominated; // Set nodes being immediately dominated
254 ArenaBitVector* domFrontier; // Dominance frontier
255 struct { // For one-to-many successors like
256 BlockListType blockListType; // switch and exception handling
257 GrowableList blocks;
258 } successorBlockList;
Elliott Hughes719ace42012-03-09 18:06:03 -0800259};
buzbee67bf8852011-08-17 17:51:35 -0700260
261/*
262 * The "blocks" field in "successorBlockList" points to an array of
263 * elements with the type "SuccessorBlockInfo".
264 * For catch blocks, key is type index for the exception.
265 * For swtich blocks, key is the case value.
266 */
Elliott Hughes719ace42012-03-09 18:06:03 -0800267struct SuccessorBlockInfo {
buzbee67bf8852011-08-17 17:51:35 -0700268 BasicBlock* block;
269 int key;
Elliott Hughes719ace42012-03-09 18:06:03 -0800270};
buzbee67bf8852011-08-17 17:51:35 -0700271
272struct LoopAnalysis;
273struct RegisterPool;
buzbeeba938cb2012-02-03 14:47:55 -0800274struct ArenaMemBlock;
275struct Memstats;
buzbee67bf8852011-08-17 17:51:35 -0700276
Elliott Hughes719ace42012-03-09 18:06:03 -0800277enum AssemblerStatus {
buzbee67bf8852011-08-17 17:51:35 -0700278 kSuccess,
279 kRetryAll,
280 kRetryHalve
Elliott Hughes719ace42012-03-09 18:06:03 -0800281};
buzbee67bf8852011-08-17 17:51:35 -0700282
buzbee5b537102012-01-17 17:33:47 -0800283#define NOTVISITED (-1)
284
Elliott Hughes719ace42012-03-09 18:06:03 -0800285struct CompilationUnit {
buzbee67bf8852011-08-17 17:51:35 -0700286 int numInsts;
287 int numBlocks;
288 GrowableList blockList;
Ian Rogers996cc582012-02-14 22:23:29 -0800289 Compiler* compiler; // Compiler driving this compiler
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800290 ClassLinker* class_linker; // Linker to resolve fields and methods
291 const DexFile* dex_file; // DexFile containing the method being compiled
292 DexCache* dex_cache; // DexFile's corresponding cache
293 const ClassLoader* class_loader; // compiling method's class loader
Ian Rogersa3760aa2011-11-14 14:32:37 -0800294 uint32_t method_idx; // compiling method's index into method_ids of DexFile
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800295 const DexFile::CodeItem* code_item; // compiling method's DexFile code_item
Ian Rogersa3760aa2011-11-14 14:32:37 -0800296 uint32_t access_flags; // compiling method's access flags
297 const char* shorty; // compiling method's shorty
buzbee67bf8852011-08-17 17:51:35 -0700298 LIR* firstLIRInsn;
299 LIR* lastLIRInsn;
300 LIR* literalList; // Constants
Ian Rogers3fa13792012-03-18 15:53:45 -0700301 LIR* methodLiteralList; // Method literals requiring patching
302 LIR* codeLiteralList; // Code literals requiring patching
buzbee67bf8852011-08-17 17:51:35 -0700303 LIR* classPointerList; // Relocatable
304 int numClassPointers;
305 LIR* chainCellOffsetLIR;
buzbeece302932011-10-04 14:32:18 -0700306 uint32_t disableOpt; // optControlVector flags
307 uint32_t enableDebug; // debugControlVector flags
buzbee67bf8852011-08-17 17:51:35 -0700308 int headerSize; // bytes before the first code ptr
309 int dataOffset; // starting offset of literal pool
310 int totalSize; // header + code size
311 AssemblerStatus assemblerStatus; // Success or fix and retry
312 int assemblerRetries;
Ian Rogersab058bb2012-03-11 22:19:38 -0700313 std::vector<uint8_t> codeBuffer;
buzbee4ef76522011-09-08 10:00:32 -0700314 std::vector<uint32_t> mappingTable;
buzbee3ddc0d12011-10-05 10:36:21 -0700315 std::vector<uint16_t> coreVmapTable;
316 std::vector<uint16_t> fpVmapTable;
buzbee44b412b2012-02-04 08:50:53 -0800317 bool genDebugger; // Generate code for debugger
buzbee67bf8852011-08-17 17:51:35 -0700318 bool printMe;
buzbee67bf8852011-08-17 17:51:35 -0700319 bool hasClassLiterals; // Contains class ptrs used as literals
320 bool hasLoop; // Contains a loop
321 bool hasInvoke; // Contains an invoke instruction
322 bool heapMemOp; // Mark mem ops for self verification
buzbeea7c12682012-03-19 13:13:53 -0700323 bool qdMode; // Compile for code size/compile time
buzbee67bf8852011-08-17 17:51:35 -0700324 bool usesLinkRegister; // For self-verification only
325 bool methodTraceSupport; // For TraceView profiling
326 struct RegisterPool* regPool;
327 int optRound; // round number to tell an LIR's age
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800328 InstructionSet instructionSet;
buzbee67bf8852011-08-17 17:51:35 -0700329 /* Number of total regs used in the whole cUnit after SSA transformation */
330 int numSSARegs;
buzbeee1965672012-03-11 18:39:19 -0700331 /* Map SSA reg i to the base virtual register/subscript */
332 GrowableList* ssaBaseVRegs;
333 GrowableList* ssaSubscripts;
buzbee67bf8852011-08-17 17:51:35 -0700334
335 /* The following are new data structures to support SSA representations */
buzbeee1965672012-03-11 18:39:19 -0700336 /* Map original Dalvik virtual reg i to the current SSA name */
337 int* vRegToSSAMap; // length == method->registersSize
buzbeef0cde542011-09-13 14:55:02 -0700338 int* SSALastDefs; // length == method->registersSize
buzbee67bf8852011-08-17 17:51:35 -0700339 ArenaBitVector* isConstantV; // length == numSSAReg
340 int* constantValues; // length == numSSAReg
buzbeec0ecd652011-09-25 18:11:54 -0700341 int* phiAliasMap; // length == numSSAReg
342 MIR* phiList;
buzbee67bf8852011-08-17 17:51:35 -0700343
buzbee239c4e72012-03-16 08:42:29 -0700344 /* Use counts of ssa names */
345 GrowableList useCounts;
346
347 /* Optimization support */
348 GrowableList loopHeaders;
349
buzbee67bf8852011-08-17 17:51:35 -0700350 /* Map SSA names to location */
351 RegLocation* regLocation;
352 int sequenceNumber;
353
buzbee67bc2362011-10-11 18:08:40 -0700354 /* Keep track of Dalvik vReg to physical register mappings */
355 PromotionMap* promotionMap;
356
buzbeee1965672012-03-11 18:39:19 -0700357 /* SSA name for Method* */
358 int methodSReg;
359
buzbee67bf8852011-08-17 17:51:35 -0700360 /*
361 * Set to the Dalvik PC of the switch instruction if it has more than
362 * MAX_CHAINED_SWITCH_CASES cases.
363 */
364 const u2* switchOverflowPad;
365
366 int numReachableBlocks;
buzbeee1965672012-03-11 18:39:19 -0700367 int numDalvikRegisters; // method->registersSize
buzbee67bf8852011-08-17 17:51:35 -0700368 BasicBlock* entryBlock;
369 BasicBlock* exitBlock;
370 BasicBlock* curBlock;
371 BasicBlock* nextCodegenBlock; // for extended trace codegen
372 GrowableList dfsOrder;
buzbee5b537102012-01-17 17:33:47 -0800373 GrowableList dfsPostOrder;
buzbee67bf8852011-08-17 17:51:35 -0700374 GrowableList domPostOrderTraversal;
buzbee5ade1d22011-09-09 14:44:52 -0700375 GrowableList throwLaunchpads;
buzbeec1f45042011-09-21 16:03:19 -0700376 GrowableList suspendLaunchpads;
buzbeee1965672012-03-11 18:39:19 -0700377 GrowableList compilerTemps;
buzbee5b537102012-01-17 17:33:47 -0800378 int* iDomList;
buzbee67bf8852011-08-17 17:51:35 -0700379 ArenaBitVector* tryBlockAddr;
380 ArenaBitVector** defBlockMatrix; // numDalvikRegister x numBlocks
381 ArenaBitVector* tempBlockV;
382 ArenaBitVector* tempDalvikRegisterV;
383 ArenaBitVector* tempSSARegisterV; // numSSARegs
384 bool printSSANames;
385 void* blockLabelList;
386 bool quitLoopMode; // cold path/complex bytecode
387 int preservedRegsUsed; // How many callee save regs used
388 /*
buzbee5ade1d22011-09-09 14:44:52 -0700389 * Frame layout details.
390 * NOTE: for debug support it will be necessary to add a structure
391 * to map the Dalvik virtual registers to the promoted registers.
392 * NOTE: "num" fields are in 4-byte words, "Size" and "Offset" in bytes.
buzbee67bf8852011-08-17 17:51:35 -0700393 */
394 int numIns;
395 int numOuts;
Ian Rogersa3760aa2011-11-14 14:32:37 -0800396 int numRegs; // Unlike numDalvikRegisters, does not include ins
buzbeebbaf8942011-10-02 13:08:29 -0700397 int numCoreSpills;
buzbee67bf8852011-08-17 17:51:35 -0700398 int numFPSpills;
buzbeeefccc562012-03-11 11:19:28 -0700399 int numCompilerTemps;
buzbee67bf8852011-08-17 17:51:35 -0700400 int frameSize;
401 unsigned int coreSpillMask;
402 unsigned int fpSpillMask;
buzbeecefd1872011-09-09 09:59:52 -0700403 unsigned int attrs;
buzbee67bf8852011-08-17 17:51:35 -0700404 /*
405 * CLEANUP/RESTRUCTURE: The code generation utilities don't have a built-in
buzbee03fa2632011-09-20 17:10:57 -0700406 * mechanism to propagate the original Dalvik opcode address to the
buzbee67bf8852011-08-17 17:51:35 -0700407 * associated generated instructions. For the trace compiler, this wasn't
408 * necessary because the interpreter handled all throws and debugging
409 * requests. For now we'll handle this by placing the Dalvik offset
410 * in the CompilationUnit struct before codegen for each instruction.
411 * The low-level LIR creation utilites will pull it from here. Should
412 * be rewritten.
413 */
414 int currentDalvikOffset;
415 GrowableList switchTables;
buzbee67bf8852011-08-17 17:51:35 -0700416 GrowableList fillArrayData;
417 const u2* insns;
418 u4 insnsSize;
buzbee99ba9642012-01-25 14:23:14 -0800419 bool disableDataflow; // Skip dataflow analysis if possible
buzbee5b537102012-01-17 17:33:47 -0800420 std::map<unsigned int, BasicBlock*> blockMap; // findBlock lookup cache
buzbee85d8c1e2012-01-27 15:52:35 -0800421 std::map<unsigned int, LIR*> boundaryMap; // boundary lookup cache
buzbee5abfa3e2012-01-31 17:01:43 -0800422 int defCount; // Used to estimate number of SSA names
buzbeeba938cb2012-02-03 14:47:55 -0800423 std::string* compilerMethodMatch;
424 bool compilerFlipMatch;
425 struct ArenaMemBlock* arenaHead;
426 struct ArenaMemBlock* currentArena;
427 int numArenaBlocks;
428 struct Memstats* mstats;
buzbeea7c12682012-03-19 13:13:53 -0700429 int* opcodeCount; // Count Dalvik opcodes for tuning
buzbee3d661942012-03-14 17:37:27 -0700430#ifndef NDEBUG
431 /*
432 * Sanity checking for the register temp tracking. The same ssa
433 * name should never be associated with one temp register per
434 * instruction compilation.
435 */
436 int liveSReg;
437#endif
Elliott Hughes719ace42012-03-09 18:06:03 -0800438};
buzbee67bf8852011-08-17 17:51:35 -0700439
Elliott Hughes719ace42012-03-09 18:06:03 -0800440enum OpSize {
buzbeee3acd072012-02-25 17:03:10 -0800441 kWord,
442 kLong,
443 kSingle,
444 kDouble,
445 kUnsignedHalf,
446 kSignedHalf,
447 kUnsignedByte,
448 kSignedByte,
Elliott Hughes719ace42012-03-09 18:06:03 -0800449};
buzbeee3acd072012-02-25 17:03:10 -0800450
Elliott Hughes719ace42012-03-09 18:06:03 -0800451enum OpKind {
buzbee31a4a6f2012-02-28 15:36:15 -0800452 kOpMov,
453 kOpMvn,
454 kOpCmp,
455 kOpLsl,
456 kOpLsr,
457 kOpAsr,
458 kOpRor,
459 kOpNot,
460 kOpAnd,
461 kOpOr,
462 kOpXor,
463 kOpNeg,
464 kOpAdd,
465 kOpAdc,
466 kOpSub,
467 kOpSbc,
468 kOpRsub,
469 kOpMul,
470 kOpDiv,
471 kOpRem,
472 kOpBic,
473 kOpCmn,
474 kOpTst,
475 kOpBkpt,
476 kOpBlx,
477 kOpPush,
478 kOpPop,
479 kOp2Char,
480 kOp2Short,
481 kOp2Byte,
482 kOpCondBr,
483 kOpUncondBr,
buzbee5de34942012-03-01 14:51:57 -0800484 kOpBx,
buzbee31a4a6f2012-02-28 15:36:15 -0800485 kOpInvalid,
Elliott Hughes719ace42012-03-09 18:06:03 -0800486};
buzbee31a4a6f2012-02-28 15:36:15 -0800487
Ian Rogers680b1bd2012-03-07 20:18:49 -0800488std::ostream& operator<<(std::ostream& os, const OpKind& kind);
489
Elliott Hughes719ace42012-03-09 18:06:03 -0800490enum ConditionCode {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800491 kCondEq, // equal
492 kCondNe, // not equal
493 kCondCs, // carry set (unsigned less than)
494 kCondUlt = kCondCs,
495 kCondCc, // carry clear (unsigned greater than or same)
496 kCondUge = kCondCc,
497 kCondMi, // minus
498 kCondPl, // plus, positive or zero
499 kCondVs, // overflow
500 kCondVc, // no overflow
501 kCondHi, // unsigned greater than
502 kCondLs, // unsigned lower or same
503 kCondGe, // signed greater than or equal
504 kCondLt, // signed less than
505 kCondGt, // signed greater than
506 kCondLe, // signed less than or equal
507 kCondAl, // always
508 kCondNv, // never
Elliott Hughes719ace42012-03-09 18:06:03 -0800509};
buzbee31a4a6f2012-02-28 15:36:15 -0800510
Elliott Hughes719ace42012-03-09 18:06:03 -0800511enum ThrowKind {
buzbee31a4a6f2012-02-28 15:36:15 -0800512 kThrowNullPointer,
513 kThrowDivZero,
514 kThrowArrayBounds,
515 kThrowVerificationError,
516 kThrowNegArraySize,
517 kThrowNoSuchMethod,
518 kThrowStackOverflow,
Elliott Hughes719ace42012-03-09 18:06:03 -0800519};
buzbee31a4a6f2012-02-28 15:36:15 -0800520
Elliott Hughes719ace42012-03-09 18:06:03 -0800521struct SwitchTable {
buzbee5de34942012-03-01 14:51:57 -0800522 int offset;
523 const u2* table; // Original dex table
524 int vaddr; // Dalvik offset of switch opcode
buzbeec5159d52012-03-03 11:48:39 -0800525 LIR* anchor; // Reference instruction for relative offsets
buzbee5de34942012-03-01 14:51:57 -0800526 LIR** targets; // Array of case targets
Elliott Hughes719ace42012-03-09 18:06:03 -0800527};
buzbee5de34942012-03-01 14:51:57 -0800528
Elliott Hughes719ace42012-03-09 18:06:03 -0800529struct FillArrayData {
buzbee5de34942012-03-01 14:51:57 -0800530 int offset;
531 const u2* table; // Original dex table
532 int size;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800533 int vaddr; // Dalvik offset of FILL_ARRAY_DATA opcode
Elliott Hughes719ace42012-03-09 18:06:03 -0800534};
buzbee5de34942012-03-01 14:51:57 -0800535
buzbee16da88c2012-03-20 10:38:17 -0700536#define MAX_PATTERN_LEN 5
537
538enum SpecialCaseHandler {
539 kNoHandler,
540 kNullMethod,
541 kConstFunction,
542 kIGet,
543 kIGetBoolean,
544 kIGetObject,
545 kIGetByte,
546 kIGetChar,
547 kIGetShort,
548 kIGetWide,
549 kIPut,
550 kIPutBoolean,
551 kIPutObject,
552 kIPutByte,
553 kIPutChar,
554 kIPutShort,
555 kIPutWide,
556};
557
558struct CodePattern {
559 const Instruction::Code opcodes[MAX_PATTERN_LEN];
560 const SpecialCaseHandler handlerCode;
561};
562
563static const CodePattern specialPatterns[] = {
564 {{Instruction::RETURN_VOID}, kNullMethod},
565 {{Instruction::CONST, Instruction::RETURN}, kConstFunction},
566 {{Instruction::CONST_4, Instruction::RETURN}, kConstFunction},
567 {{Instruction::CONST_16, Instruction::RETURN}, kConstFunction},
568 {{Instruction::IGET, Instruction:: RETURN}, kIGet},
569 {{Instruction::IGET_BOOLEAN, Instruction:: RETURN}, kIGetBoolean},
570 {{Instruction::IGET_OBJECT, Instruction:: RETURN}, kIGetObject},
571 {{Instruction::IGET_BYTE, Instruction:: RETURN}, kIGetByte},
572 {{Instruction::IGET_CHAR, Instruction:: RETURN}, kIGetChar},
573 {{Instruction::IGET_SHORT, Instruction:: RETURN}, kIGetShort},
574 {{Instruction::IGET_WIDE, Instruction:: RETURN_WIDE}, kIGetWide},
575 {{Instruction::IPUT, Instruction:: RETURN}, kIPut},
576 {{Instruction::IPUT_BOOLEAN, Instruction:: RETURN}, kIPutBoolean},
577 {{Instruction::IPUT_OBJECT, Instruction:: RETURN}, kIPutObject},
578 {{Instruction::IPUT_BYTE, Instruction:: RETURN}, kIPutByte},
579 {{Instruction::IPUT_CHAR, Instruction:: RETURN}, kIPutChar},
580 {{Instruction::IPUT_SHORT, Instruction:: RETURN}, kIPutShort},
581 {{Instruction::IPUT_WIDE, Instruction:: RETURN_WIDE}, kIPutWide},
582};
buzbee5de34942012-03-01 14:51:57 -0800583
buzbee5abfa3e2012-01-31 17:01:43 -0800584BasicBlock* oatNewBB(CompilationUnit* cUnit, BBType blockType, int blockId);
buzbee67bf8852011-08-17 17:51:35 -0700585
586void oatAppendMIR(BasicBlock* bb, MIR* mir);
587
588void oatPrependMIR(BasicBlock* bb, MIR* mir);
589
590void oatInsertMIRAfter(BasicBlock* bb, MIR* currentMIR, MIR* newMIR);
591
592void oatAppendLIR(CompilationUnit* cUnit, LIR* lir);
593
594void oatInsertLIRBefore(LIR* currentLIR, LIR* newLIR);
595
596void oatInsertLIRAfter(LIR* currentLIR, LIR* newLIR);
597
598/* Debug Utilities */
599void oatDumpCompilationUnit(CompilationUnit* cUnit);
600
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800601} // namespace art
602
buzbee67bf8852011-08-17 17:51:35 -0700603#endif // ART_SRC_COMPILER_COMPILER_IR_H_