blob: 429772afbb7551da3368818677f3661316408d09 [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,
buzbeee62076c2012-03-21 14:26:16 -070048 kLocInvalid
Elliott Hughes719ace42012-03-09 18:06:03 -080049};
buzbee67bf8852011-08-17 17:51:35 -070050
Elliott Hughes719ace42012-03-09 18:06:03 -080051struct PromotionMap {
buzbee67bc2362011-10-11 18:08:40 -070052 RegLocationType coreLocation:3;
53 u1 coreReg;
54 RegLocationType fpLocation:3;
55 u1 fpReg;
56 bool firstInPair;
Elliott Hughes719ace42012-03-09 18:06:03 -080057};
buzbee67bc2362011-10-11 18:08:40 -070058
Elliott Hughes719ace42012-03-09 18:06:03 -080059struct RegLocation {
buzbee67bc2362011-10-11 18:08:40 -070060 RegLocationType location:3;
buzbee67bf8852011-08-17 17:51:35 -070061 unsigned wide:1;
buzbee67bc2362011-10-11 18:08:40 -070062 unsigned defined:1; // Do we know the type?
63 unsigned fp:1; // Floating point?
64 unsigned core:1; // Non-floating point?
65 unsigned highWord:1; // High word of pair?
66 unsigned home:1; // Does this represent the home location?
67 u1 lowReg; // First physical register
68 u1 highReg; // 2nd physical register (if wide)
buzbeee1965672012-03-11 18:39:19 -070069 int32_t sRegLow; // SSA name for low Dalvik word
70};
71
72struct CompilerTemp {
73 int sReg;
74 ArenaBitVector* bv;
Elliott Hughes719ace42012-03-09 18:06:03 -080075};
buzbee67bf8852011-08-17 17:51:35 -070076
buzbeee3acd072012-02-25 17:03:10 -080077 /*
78 * Data structure tracking the mapping between a Dalvik register (pair) and a
79 * native register (pair). The idea is to reuse the previously loaded value
80 * if possible, otherwise to keep the value in a native register as long as
81 * possible.
82 */
Elliott Hughes719ace42012-03-09 18:06:03 -080083struct RegisterInfo {
buzbeee3acd072012-02-25 17:03:10 -080084 int reg; // Reg number
85 bool inUse; // Has it been allocated?
86 bool isTemp; // Can allocate as temp?
87 bool pair; // Part of a register pair?
88 int partner; // If pair, other reg of pair
89 bool live; // Is there an associated SSA name?
90 bool dirty; // If live, is it dirty?
91 int sReg; // Name of live value
92 struct LIR *defStart; // Starting inst in last def sequence
93 struct LIR *defEnd; // Ending inst in last def sequence
Elliott Hughes719ace42012-03-09 18:06:03 -080094};
buzbeee3acd072012-02-25 17:03:10 -080095
Elliott Hughes719ace42012-03-09 18:06:03 -080096struct RegisterPool {
buzbeee3acd072012-02-25 17:03:10 -080097 int numCoreRegs;
98 RegisterInfo *coreRegs;
99 int nextCoreReg;
100 int numFPRegs;
101 RegisterInfo *FPRegs;
102 int nextFPReg;
Elliott Hughes719ace42012-03-09 18:06:03 -0800103};
buzbeee3acd072012-02-25 17:03:10 -0800104
buzbee67bf8852011-08-17 17:51:35 -0700105#define INVALID_SREG (-1)
buzbee3ddc0d12011-10-05 10:36:21 -0700106#define INVALID_VREG (0xFFFFU)
buzbee67bc2362011-10-11 18:08:40 -0700107#define INVALID_REG (0xFF)
buzbee67bf8852011-08-17 17:51:35 -0700108#define INVALID_OFFSET (-1)
109
buzbeee1965672012-03-11 18:39:19 -0700110/* SSA encodings for special registers */
buzbee9c044ce2012-03-18 13:24:07 -0700111#define SSA_METHOD_BASEREG (-2)
buzbeee1965672012-03-11 18:39:19 -0700112/* First compiler temp basereg, grows smaller */
buzbee9c044ce2012-03-18 13:24:07 -0700113#define SSA_CTEMP_BASEREG (SSA_METHOD_BASEREG - 1)
buzbeee1965672012-03-11 18:39:19 -0700114
buzbee99ba9642012-01-25 14:23:14 -0800115/*
116 * Some code patterns cause the generation of excessively large
117 * methods - in particular initialization sequences. There isn't much
118 * benefit in optimizing these methods, and the cost can be very high.
119 * We attempt to identify these cases, and avoid performing most dataflow
120 * analysis. Two thresholds are used - one for known initializers and one
buzbee5abfa3e2012-01-31 17:01:43 -0800121 * for everything else.
buzbee99ba9642012-01-25 14:23:14 -0800122 */
buzbee5abfa3e2012-01-31 17:01:43 -0800123#define MANY_BLOCKS_INITIALIZER 1000 /* Threshold for switching dataflow off */
124#define MANY_BLOCKS 4000 /* Non-initializer threshold */
buzbee99ba9642012-01-25 14:23:14 -0800125
Elliott Hughes719ace42012-03-09 18:06:03 -0800126enum BBType {
buzbee67bf8852011-08-17 17:51:35 -0700127 kEntryBlock,
128 kDalvikByteCode,
129 kExitBlock,
130 kExceptionHandling,
131 kCatchEntry,
Elliott Hughes719ace42012-03-09 18:06:03 -0800132};
buzbee67bf8852011-08-17 17:51:35 -0700133
buzbee31a4a6f2012-02-28 15:36:15 -0800134/* Utility macros to traverse the LIR list */
135#define NEXT_LIR(lir) (lir->next)
136#define PREV_LIR(lir) (lir->prev)
137
138#define NEXT_LIR_LVALUE(lir) (lir)->next
139#define PREV_LIR_LVALUE(lir) (lir)->prev
140
Elliott Hughes719ace42012-03-09 18:06:03 -0800141struct LIR {
buzbee67bf8852011-08-17 17:51:35 -0700142 int offset; // Offset of this instruction
143 int dalvikOffset; // Offset of Dalvik opcode
144 struct LIR* next;
145 struct LIR* prev;
146 struct LIR* target;
buzbee31a4a6f2012-02-28 15:36:15 -0800147 int opcode;
Ian Rogersb5d09b22012-03-06 22:14:17 -0800148 int operands[5]; // [0..4] = [dest, src1, src2, extra, extra2]
buzbee31a4a6f2012-02-28 15:36:15 -0800149 struct {
150 bool isNop:1; // LIR is optimized away
151 bool pcRelFixup:1; // May need pc-relative fixup
152 unsigned int age:4; // default is 0, set lazily by the optimizer
buzbee71ac9942012-03-01 17:23:10 -0800153 unsigned int size:5; // in bytes
154 unsigned int unused:21;
buzbee31a4a6f2012-02-28 15:36:15 -0800155 } flags;
156 int aliasInfo; // For Dalvik register & litpool disambiguation
157 u8 useMask; // Resource mask for use
158 u8 defMask; // Resource mask for def
Elliott Hughes719ace42012-03-09 18:06:03 -0800159};
buzbee67bf8852011-08-17 17:51:35 -0700160
161enum ExtendedMIROpcode {
162 kMirOpFirst = kNumPackedOpcodes,
163 kMirOpPhi = kMirOpFirst,
164 kMirOpNullNRangeUpCheck,
165 kMirOpNullNRangeDownCheck,
166 kMirOpLowerBound,
buzbeee1965672012-03-11 18:39:19 -0700167 kMirOpCopy,
buzbee67bf8852011-08-17 17:51:35 -0700168 kMirOpLast,
169};
170
171struct SSARepresentation;
172
Elliott Hughes719ace42012-03-09 18:06:03 -0800173enum MIROptimizationFlagPositons {
buzbee67bf8852011-08-17 17:51:35 -0700174 kMIRIgnoreNullCheck = 0,
175 kMIRNullCheckOnly,
176 kMIRIgnoreRangeCheck,
177 kMIRRangeCheckOnly,
178 kMIRInlined, // Invoke is inlined (ie dead)
179 kMIRInlinedPred, // Invoke is inlined via prediction
180 kMIRCallee, // Instruction is inlined from callee
buzbeec1f45042011-09-21 16:03:19 -0700181 kMIRIgnoreSuspendCheck,
buzbeee1965672012-03-11 18:39:19 -0700182 kMIRDup,
buzbee239c4e72012-03-16 08:42:29 -0700183 kMIRMark, // Temporary node mark
Elliott Hughes719ace42012-03-09 18:06:03 -0800184};
buzbee67bf8852011-08-17 17:51:35 -0700185
186#define MIR_IGNORE_NULL_CHECK (1 << kMIRIgnoreNullCheck)
187#define MIR_NULL_CHECK_ONLY (1 << kMIRNullCheckOnly)
188#define MIR_IGNORE_RANGE_CHECK (1 << kMIRIgnoreRangeCheck)
189#define MIR_RANGE_CHECK_ONLY (1 << kMIRRangeCheckOnly)
190#define MIR_INLINED (1 << kMIRInlined)
191#define MIR_INLINED_PRED (1 << kMIRInlinedPred)
192#define MIR_CALLEE (1 << kMIRCallee)
buzbeec1f45042011-09-21 16:03:19 -0700193#define MIR_IGNORE_SUSPEND_CHECK (1 << kMIRIgnoreSuspendCheck)
buzbeee1965672012-03-11 18:39:19 -0700194#define MIR_DUP (1 << kMIRDup)
buzbee239c4e72012-03-16 08:42:29 -0700195#define MIR_MARK (1 << kMIRMark)
buzbee67bf8852011-08-17 17:51:35 -0700196
Elliott Hughes719ace42012-03-09 18:06:03 -0800197struct CallsiteInfo {
buzbee67bf8852011-08-17 17:51:35 -0700198 const char* classDescriptor;
199 Object* classLoader;
200 const Method* method;
201 LIR* misPredBranchOver;
Elliott Hughes719ace42012-03-09 18:06:03 -0800202};
buzbee67bf8852011-08-17 17:51:35 -0700203
Elliott Hughes719ace42012-03-09 18:06:03 -0800204struct MIR {
buzbee67bf8852011-08-17 17:51:35 -0700205 DecodedInstruction dalvikInsn;
206 unsigned int width;
207 unsigned int offset;
208 struct MIR* prev;
209 struct MIR* next;
210 struct SSARepresentation* ssaRep;
buzbee43a36422011-09-14 14:00:13 -0700211 int optimizationFlags;
buzbee67bf8852011-08-17 17:51:35 -0700212 int seqNum;
213 union {
214 // Used by the inlined insn from the callee to find the mother method
215 const Method* calleeMethod;
216 // Used by the inlined invoke to find the class and method pointers
217 CallsiteInfo* callsiteInfo;
buzbeec0ecd652011-09-25 18:11:54 -0700218 // Used to quickly locate all Phi opcodes
219 struct MIR* phiNext;
buzbee67bf8852011-08-17 17:51:35 -0700220 } meta;
Elliott Hughes719ace42012-03-09 18:06:03 -0800221};
buzbee67bf8852011-08-17 17:51:35 -0700222
223struct BasicBlockDataFlow;
224
225/* For successorBlockList */
Elliott Hughes719ace42012-03-09 18:06:03 -0800226enum BlockListType {
buzbee67bf8852011-08-17 17:51:35 -0700227 kNotUsed = 0,
228 kCatch,
229 kPackedSwitch,
230 kSparseSwitch,
Elliott Hughes719ace42012-03-09 18:06:03 -0800231};
buzbee67bf8852011-08-17 17:51:35 -0700232
Elliott Hughes719ace42012-03-09 18:06:03 -0800233struct BasicBlock {
buzbee67bf8852011-08-17 17:51:35 -0700234 int id;
buzbee5b537102012-01-17 17:33:47 -0800235 int dfsId;
buzbee67bf8852011-08-17 17:51:35 -0700236 bool visited;
237 bool hidden;
buzbee43a36422011-09-14 14:00:13 -0700238 bool catchEntry;
buzbeee1965672012-03-11 18:39:19 -0700239 bool fallThroughTarget; // Reached via fallthrough
buzbee239c4e72012-03-16 08:42:29 -0700240 uint16_t startOffset;
241 uint16_t nestingDepth;
buzbee67bf8852011-08-17 17:51:35 -0700242 const Method* containingMethod; // For blocks from the callee
243 BBType blockType;
244 bool needFallThroughBranch; // For blocks ended due to length limit
245 bool isFallThroughFromInvoke; // True means the block needs alignment
246 MIR* firstMIRInsn;
247 MIR* lastMIRInsn;
248 struct BasicBlock* fallThrough;
249 struct BasicBlock* taken;
250 struct BasicBlock* iDom; // Immediate dominator
251 struct BasicBlockDataFlow* dataFlowInfo;
buzbee5abfa3e2012-01-31 17:01:43 -0800252 GrowableList* predecessors;
buzbee67bf8852011-08-17 17:51:35 -0700253 ArenaBitVector* dominators;
254 ArenaBitVector* iDominated; // Set nodes being immediately dominated
255 ArenaBitVector* domFrontier; // Dominance frontier
256 struct { // For one-to-many successors like
257 BlockListType blockListType; // switch and exception handling
258 GrowableList blocks;
259 } successorBlockList;
Elliott Hughes719ace42012-03-09 18:06:03 -0800260};
buzbee67bf8852011-08-17 17:51:35 -0700261
262/*
263 * The "blocks" field in "successorBlockList" points to an array of
264 * elements with the type "SuccessorBlockInfo".
265 * For catch blocks, key is type index for the exception.
266 * For swtich blocks, key is the case value.
267 */
Elliott Hughes719ace42012-03-09 18:06:03 -0800268struct SuccessorBlockInfo {
buzbee67bf8852011-08-17 17:51:35 -0700269 BasicBlock* block;
270 int key;
Elliott Hughes719ace42012-03-09 18:06:03 -0800271};
buzbee67bf8852011-08-17 17:51:35 -0700272
273struct LoopAnalysis;
274struct RegisterPool;
buzbeeba938cb2012-02-03 14:47:55 -0800275struct ArenaMemBlock;
276struct Memstats;
buzbee67bf8852011-08-17 17:51:35 -0700277
Elliott Hughes719ace42012-03-09 18:06:03 -0800278enum AssemblerStatus {
buzbee67bf8852011-08-17 17:51:35 -0700279 kSuccess,
280 kRetryAll,
281 kRetryHalve
Elliott Hughes719ace42012-03-09 18:06:03 -0800282};
buzbee67bf8852011-08-17 17:51:35 -0700283
buzbee5b537102012-01-17 17:33:47 -0800284#define NOTVISITED (-1)
285
Elliott Hughes719ace42012-03-09 18:06:03 -0800286struct CompilationUnit {
buzbee67bf8852011-08-17 17:51:35 -0700287 int numInsts;
288 int numBlocks;
289 GrowableList blockList;
Ian Rogers996cc582012-02-14 22:23:29 -0800290 Compiler* compiler; // Compiler driving this compiler
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800291 ClassLinker* class_linker; // Linker to resolve fields and methods
292 const DexFile* dex_file; // DexFile containing the method being compiled
293 DexCache* dex_cache; // DexFile's corresponding cache
294 const ClassLoader* class_loader; // compiling method's class loader
Ian Rogersa3760aa2011-11-14 14:32:37 -0800295 uint32_t method_idx; // compiling method's index into method_ids of DexFile
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800296 const DexFile::CodeItem* code_item; // compiling method's DexFile code_item
Ian Rogersa3760aa2011-11-14 14:32:37 -0800297 uint32_t access_flags; // compiling method's access flags
298 const char* shorty; // compiling method's shorty
buzbee67bf8852011-08-17 17:51:35 -0700299 LIR* firstLIRInsn;
300 LIR* lastLIRInsn;
301 LIR* literalList; // Constants
Ian Rogers3fa13792012-03-18 15:53:45 -0700302 LIR* methodLiteralList; // Method literals requiring patching
303 LIR* codeLiteralList; // Code literals requiring patching
buzbee67bf8852011-08-17 17:51:35 -0700304 LIR* classPointerList; // Relocatable
305 int numClassPointers;
306 LIR* chainCellOffsetLIR;
buzbeece302932011-10-04 14:32:18 -0700307 uint32_t disableOpt; // optControlVector flags
308 uint32_t enableDebug; // debugControlVector flags
buzbee67bf8852011-08-17 17:51:35 -0700309 int headerSize; // bytes before the first code ptr
310 int dataOffset; // starting offset of literal pool
311 int totalSize; // header + code size
312 AssemblerStatus assemblerStatus; // Success or fix and retry
313 int assemblerRetries;
Ian Rogersab058bb2012-03-11 22:19:38 -0700314 std::vector<uint8_t> codeBuffer;
buzbee4ef76522011-09-08 10:00:32 -0700315 std::vector<uint32_t> mappingTable;
buzbee3ddc0d12011-10-05 10:36:21 -0700316 std::vector<uint16_t> coreVmapTable;
317 std::vector<uint16_t> fpVmapTable;
buzbee44b412b2012-02-04 08:50:53 -0800318 bool genDebugger; // Generate code for debugger
buzbee67bf8852011-08-17 17:51:35 -0700319 bool printMe;
buzbee67bf8852011-08-17 17:51:35 -0700320 bool hasClassLiterals; // Contains class ptrs used as literals
321 bool hasLoop; // Contains a loop
322 bool hasInvoke; // Contains an invoke instruction
323 bool heapMemOp; // Mark mem ops for self verification
buzbeea7c12682012-03-19 13:13:53 -0700324 bool qdMode; // Compile for code size/compile time
buzbee67bf8852011-08-17 17:51:35 -0700325 bool usesLinkRegister; // For self-verification only
326 bool methodTraceSupport; // For TraceView profiling
327 struct RegisterPool* regPool;
328 int optRound; // round number to tell an LIR's age
Elliott Hughesb3bd5f02012-03-08 21:05:27 -0800329 InstructionSet instructionSet;
buzbee67bf8852011-08-17 17:51:35 -0700330 /* Number of total regs used in the whole cUnit after SSA transformation */
331 int numSSARegs;
buzbeee1965672012-03-11 18:39:19 -0700332 /* Map SSA reg i to the base virtual register/subscript */
333 GrowableList* ssaBaseVRegs;
334 GrowableList* ssaSubscripts;
buzbee67bf8852011-08-17 17:51:35 -0700335
336 /* The following are new data structures to support SSA representations */
buzbeee1965672012-03-11 18:39:19 -0700337 /* Map original Dalvik virtual reg i to the current SSA name */
338 int* vRegToSSAMap; // length == method->registersSize
buzbeef0cde542011-09-13 14:55:02 -0700339 int* SSALastDefs; // length == method->registersSize
buzbee67bf8852011-08-17 17:51:35 -0700340 ArenaBitVector* isConstantV; // length == numSSAReg
341 int* constantValues; // length == numSSAReg
buzbeec0ecd652011-09-25 18:11:54 -0700342 int* phiAliasMap; // length == numSSAReg
343 MIR* phiList;
buzbee67bf8852011-08-17 17:51:35 -0700344
buzbee239c4e72012-03-16 08:42:29 -0700345 /* Use counts of ssa names */
346 GrowableList useCounts;
347
348 /* Optimization support */
349 GrowableList loopHeaders;
350
buzbee67bf8852011-08-17 17:51:35 -0700351 /* Map SSA names to location */
352 RegLocation* regLocation;
353 int sequenceNumber;
354
buzbee67bc2362011-10-11 18:08:40 -0700355 /* Keep track of Dalvik vReg to physical register mappings */
356 PromotionMap* promotionMap;
357
buzbeee1965672012-03-11 18:39:19 -0700358 /* SSA name for Method* */
359 int methodSReg;
360
buzbee67bf8852011-08-17 17:51:35 -0700361 /*
362 * Set to the Dalvik PC of the switch instruction if it has more than
363 * MAX_CHAINED_SWITCH_CASES cases.
364 */
365 const u2* switchOverflowPad;
366
367 int numReachableBlocks;
buzbeee1965672012-03-11 18:39:19 -0700368 int numDalvikRegisters; // method->registersSize
buzbee67bf8852011-08-17 17:51:35 -0700369 BasicBlock* entryBlock;
370 BasicBlock* exitBlock;
371 BasicBlock* curBlock;
372 BasicBlock* nextCodegenBlock; // for extended trace codegen
373 GrowableList dfsOrder;
buzbee5b537102012-01-17 17:33:47 -0800374 GrowableList dfsPostOrder;
buzbee67bf8852011-08-17 17:51:35 -0700375 GrowableList domPostOrderTraversal;
buzbee5ade1d22011-09-09 14:44:52 -0700376 GrowableList throwLaunchpads;
buzbeec1f45042011-09-21 16:03:19 -0700377 GrowableList suspendLaunchpads;
buzbeee1965672012-03-11 18:39:19 -0700378 GrowableList compilerTemps;
buzbee5b537102012-01-17 17:33:47 -0800379 int* iDomList;
buzbee67bf8852011-08-17 17:51:35 -0700380 ArenaBitVector* tryBlockAddr;
381 ArenaBitVector** defBlockMatrix; // numDalvikRegister x numBlocks
382 ArenaBitVector* tempBlockV;
383 ArenaBitVector* tempDalvikRegisterV;
384 ArenaBitVector* tempSSARegisterV; // numSSARegs
385 bool printSSANames;
386 void* blockLabelList;
387 bool quitLoopMode; // cold path/complex bytecode
388 int preservedRegsUsed; // How many callee save regs used
389 /*
buzbee5ade1d22011-09-09 14:44:52 -0700390 * Frame layout details.
391 * NOTE: for debug support it will be necessary to add a structure
392 * to map the Dalvik virtual registers to the promoted registers.
393 * NOTE: "num" fields are in 4-byte words, "Size" and "Offset" in bytes.
buzbee67bf8852011-08-17 17:51:35 -0700394 */
395 int numIns;
396 int numOuts;
Ian Rogersa3760aa2011-11-14 14:32:37 -0800397 int numRegs; // Unlike numDalvikRegisters, does not include ins
buzbeebbaf8942011-10-02 13:08:29 -0700398 int numCoreSpills;
buzbee67bf8852011-08-17 17:51:35 -0700399 int numFPSpills;
buzbeeefccc562012-03-11 11:19:28 -0700400 int numCompilerTemps;
buzbee67bf8852011-08-17 17:51:35 -0700401 int frameSize;
402 unsigned int coreSpillMask;
403 unsigned int fpSpillMask;
buzbeecefd1872011-09-09 09:59:52 -0700404 unsigned int attrs;
buzbee67bf8852011-08-17 17:51:35 -0700405 /*
406 * CLEANUP/RESTRUCTURE: The code generation utilities don't have a built-in
buzbee03fa2632011-09-20 17:10:57 -0700407 * mechanism to propagate the original Dalvik opcode address to the
buzbee67bf8852011-08-17 17:51:35 -0700408 * associated generated instructions. For the trace compiler, this wasn't
409 * necessary because the interpreter handled all throws and debugging
410 * requests. For now we'll handle this by placing the Dalvik offset
411 * in the CompilationUnit struct before codegen for each instruction.
412 * The low-level LIR creation utilites will pull it from here. Should
413 * be rewritten.
414 */
415 int currentDalvikOffset;
416 GrowableList switchTables;
buzbee67bf8852011-08-17 17:51:35 -0700417 GrowableList fillArrayData;
418 const u2* insns;
419 u4 insnsSize;
buzbee99ba9642012-01-25 14:23:14 -0800420 bool disableDataflow; // Skip dataflow analysis if possible
buzbee5b537102012-01-17 17:33:47 -0800421 std::map<unsigned int, BasicBlock*> blockMap; // findBlock lookup cache
buzbee85d8c1e2012-01-27 15:52:35 -0800422 std::map<unsigned int, LIR*> boundaryMap; // boundary lookup cache
buzbee5abfa3e2012-01-31 17:01:43 -0800423 int defCount; // Used to estimate number of SSA names
buzbeeba938cb2012-02-03 14:47:55 -0800424 std::string* compilerMethodMatch;
425 bool compilerFlipMatch;
426 struct ArenaMemBlock* arenaHead;
427 struct ArenaMemBlock* currentArena;
428 int numArenaBlocks;
429 struct Memstats* mstats;
buzbeea7c12682012-03-19 13:13:53 -0700430 int* opcodeCount; // Count Dalvik opcodes for tuning
buzbee3d661942012-03-14 17:37:27 -0700431#ifndef NDEBUG
432 /*
433 * Sanity checking for the register temp tracking. The same ssa
434 * name should never be associated with one temp register per
435 * instruction compilation.
436 */
437 int liveSReg;
438#endif
Elliott Hughes719ace42012-03-09 18:06:03 -0800439};
buzbee67bf8852011-08-17 17:51:35 -0700440
Elliott Hughes719ace42012-03-09 18:06:03 -0800441enum OpSize {
buzbeee3acd072012-02-25 17:03:10 -0800442 kWord,
443 kLong,
444 kSingle,
445 kDouble,
446 kUnsignedHalf,
447 kSignedHalf,
448 kUnsignedByte,
449 kSignedByte,
Elliott Hughes719ace42012-03-09 18:06:03 -0800450};
buzbeee3acd072012-02-25 17:03:10 -0800451
Elliott Hughes719ace42012-03-09 18:06:03 -0800452enum OpKind {
buzbee31a4a6f2012-02-28 15:36:15 -0800453 kOpMov,
454 kOpMvn,
455 kOpCmp,
456 kOpLsl,
457 kOpLsr,
458 kOpAsr,
459 kOpRor,
460 kOpNot,
461 kOpAnd,
462 kOpOr,
463 kOpXor,
464 kOpNeg,
465 kOpAdd,
466 kOpAdc,
467 kOpSub,
468 kOpSbc,
469 kOpRsub,
470 kOpMul,
471 kOpDiv,
472 kOpRem,
473 kOpBic,
474 kOpCmn,
475 kOpTst,
476 kOpBkpt,
477 kOpBlx,
478 kOpPush,
479 kOpPop,
480 kOp2Char,
481 kOp2Short,
482 kOp2Byte,
483 kOpCondBr,
484 kOpUncondBr,
buzbee5de34942012-03-01 14:51:57 -0800485 kOpBx,
buzbee31a4a6f2012-02-28 15:36:15 -0800486 kOpInvalid,
Elliott Hughes719ace42012-03-09 18:06:03 -0800487};
buzbee31a4a6f2012-02-28 15:36:15 -0800488
Ian Rogers680b1bd2012-03-07 20:18:49 -0800489std::ostream& operator<<(std::ostream& os, const OpKind& kind);
490
Elliott Hughes719ace42012-03-09 18:06:03 -0800491enum ConditionCode {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800492 kCondEq, // equal
493 kCondNe, // not equal
494 kCondCs, // carry set (unsigned less than)
495 kCondUlt = kCondCs,
496 kCondCc, // carry clear (unsigned greater than or same)
497 kCondUge = kCondCc,
498 kCondMi, // minus
499 kCondPl, // plus, positive or zero
500 kCondVs, // overflow
501 kCondVc, // no overflow
502 kCondHi, // unsigned greater than
503 kCondLs, // unsigned lower or same
504 kCondGe, // signed greater than or equal
505 kCondLt, // signed less than
506 kCondGt, // signed greater than
507 kCondLe, // signed less than or equal
508 kCondAl, // always
509 kCondNv, // never
Elliott Hughes719ace42012-03-09 18:06:03 -0800510};
buzbee31a4a6f2012-02-28 15:36:15 -0800511
Elliott Hughes719ace42012-03-09 18:06:03 -0800512enum ThrowKind {
buzbee31a4a6f2012-02-28 15:36:15 -0800513 kThrowNullPointer,
514 kThrowDivZero,
515 kThrowArrayBounds,
516 kThrowVerificationError,
517 kThrowNegArraySize,
518 kThrowNoSuchMethod,
519 kThrowStackOverflow,
Elliott Hughes719ace42012-03-09 18:06:03 -0800520};
buzbee31a4a6f2012-02-28 15:36:15 -0800521
Elliott Hughes719ace42012-03-09 18:06:03 -0800522struct SwitchTable {
buzbee5de34942012-03-01 14:51:57 -0800523 int offset;
524 const u2* table; // Original dex table
525 int vaddr; // Dalvik offset of switch opcode
buzbeec5159d52012-03-03 11:48:39 -0800526 LIR* anchor; // Reference instruction for relative offsets
buzbee5de34942012-03-01 14:51:57 -0800527 LIR** targets; // Array of case targets
Elliott Hughes719ace42012-03-09 18:06:03 -0800528};
buzbee5de34942012-03-01 14:51:57 -0800529
Elliott Hughes719ace42012-03-09 18:06:03 -0800530struct FillArrayData {
buzbee5de34942012-03-01 14:51:57 -0800531 int offset;
532 const u2* table; // Original dex table
533 int size;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800534 int vaddr; // Dalvik offset of FILL_ARRAY_DATA opcode
Elliott Hughes719ace42012-03-09 18:06:03 -0800535};
buzbee5de34942012-03-01 14:51:57 -0800536
buzbee16da88c2012-03-20 10:38:17 -0700537#define MAX_PATTERN_LEN 5
538
539enum SpecialCaseHandler {
540 kNoHandler,
541 kNullMethod,
542 kConstFunction,
543 kIGet,
544 kIGetBoolean,
545 kIGetObject,
546 kIGetByte,
547 kIGetChar,
548 kIGetShort,
549 kIGetWide,
550 kIPut,
551 kIPutBoolean,
552 kIPutObject,
553 kIPutByte,
554 kIPutChar,
555 kIPutShort,
556 kIPutWide,
buzbeee62076c2012-03-21 14:26:16 -0700557 kIdentity,
buzbee16da88c2012-03-20 10:38:17 -0700558};
559
560struct CodePattern {
561 const Instruction::Code opcodes[MAX_PATTERN_LEN];
562 const SpecialCaseHandler handlerCode;
563};
564
565static const CodePattern specialPatterns[] = {
566 {{Instruction::RETURN_VOID}, kNullMethod},
567 {{Instruction::CONST, Instruction::RETURN}, kConstFunction},
568 {{Instruction::CONST_4, Instruction::RETURN}, kConstFunction},
Ian Rogersf24132c2012-03-21 01:34:31 -0700569 {{Instruction::CONST_4, Instruction::RETURN_OBJECT}, kConstFunction},
buzbee16da88c2012-03-20 10:38:17 -0700570 {{Instruction::CONST_16, Instruction::RETURN}, kConstFunction},
571 {{Instruction::IGET, Instruction:: RETURN}, kIGet},
Ian Rogersf24132c2012-03-21 01:34:31 -0700572 {{Instruction::IGET_BOOLEAN, Instruction::RETURN}, kIGetBoolean},
573 {{Instruction::IGET_OBJECT, Instruction::RETURN_OBJECT}, kIGetObject},
574 {{Instruction::IGET_BYTE, Instruction::RETURN}, kIGetByte},
575 {{Instruction::IGET_CHAR, Instruction::RETURN}, kIGetChar},
576 {{Instruction::IGET_SHORT, Instruction::RETURN}, kIGetShort},
577 {{Instruction::IGET_WIDE, Instruction::RETURN_WIDE}, kIGetWide},
578 {{Instruction::IPUT, Instruction::RETURN_VOID}, kIPut},
579 {{Instruction::IPUT_BOOLEAN, Instruction::RETURN_VOID}, kIPutBoolean},
580 {{Instruction::IPUT_OBJECT, Instruction::RETURN_VOID}, kIPutObject},
581 {{Instruction::IPUT_BYTE, Instruction::RETURN_VOID}, kIPutByte},
582 {{Instruction::IPUT_CHAR, Instruction::RETURN_VOID}, kIPutChar},
583 {{Instruction::IPUT_SHORT, Instruction::RETURN_VOID}, kIPutShort},
584 {{Instruction::IPUT_WIDE, Instruction::RETURN_VOID}, kIPutWide},
buzbeee62076c2012-03-21 14:26:16 -0700585 {{Instruction::RETURN}, kIdentity},
586 {{Instruction::RETURN_OBJECT}, kIdentity},
587 {{Instruction::RETURN_WIDE}, kIdentity},
buzbee16da88c2012-03-20 10:38:17 -0700588};
buzbee5de34942012-03-01 14:51:57 -0800589
buzbee5abfa3e2012-01-31 17:01:43 -0800590BasicBlock* oatNewBB(CompilationUnit* cUnit, BBType blockType, int blockId);
buzbee67bf8852011-08-17 17:51:35 -0700591
592void oatAppendMIR(BasicBlock* bb, MIR* mir);
593
594void oatPrependMIR(BasicBlock* bb, MIR* mir);
595
596void oatInsertMIRAfter(BasicBlock* bb, MIR* currentMIR, MIR* newMIR);
597
598void oatAppendLIR(CompilationUnit* cUnit, LIR* lir);
599
600void oatInsertLIRBefore(LIR* currentLIR, LIR* newLIR);
601
602void oatInsertLIRAfter(LIR* currentLIR, LIR* newLIR);
603
604/* Debug Utilities */
605void oatDumpCompilationUnit(CompilationUnit* cUnit);
606
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800607} // namespace art
608
buzbee67bf8852011-08-17 17:51:35 -0700609#endif // ART_SRC_COMPILER_COMPILER_IR_H_