blob: a440555358c31d89f8aafbec9712559047d9fc92 [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;
buzbeefc9e6fa2012-03-23 15:14:29 -0700378 GrowableList intrinsicLaunchpads;
buzbeee1965672012-03-11 18:39:19 -0700379 GrowableList compilerTemps;
buzbee5b537102012-01-17 17:33:47 -0800380 int* iDomList;
buzbee67bf8852011-08-17 17:51:35 -0700381 ArenaBitVector* tryBlockAddr;
382 ArenaBitVector** defBlockMatrix; // numDalvikRegister x numBlocks
383 ArenaBitVector* tempBlockV;
384 ArenaBitVector* tempDalvikRegisterV;
385 ArenaBitVector* tempSSARegisterV; // numSSARegs
386 bool printSSANames;
387 void* blockLabelList;
388 bool quitLoopMode; // cold path/complex bytecode
389 int preservedRegsUsed; // How many callee save regs used
390 /*
buzbee5ade1d22011-09-09 14:44:52 -0700391 * Frame layout details.
392 * NOTE: for debug support it will be necessary to add a structure
393 * to map the Dalvik virtual registers to the promoted registers.
394 * NOTE: "num" fields are in 4-byte words, "Size" and "Offset" in bytes.
buzbee67bf8852011-08-17 17:51:35 -0700395 */
396 int numIns;
397 int numOuts;
Ian Rogersa3760aa2011-11-14 14:32:37 -0800398 int numRegs; // Unlike numDalvikRegisters, does not include ins
buzbeebbaf8942011-10-02 13:08:29 -0700399 int numCoreSpills;
buzbee67bf8852011-08-17 17:51:35 -0700400 int numFPSpills;
buzbeeefccc562012-03-11 11:19:28 -0700401 int numCompilerTemps;
buzbee67bf8852011-08-17 17:51:35 -0700402 int frameSize;
403 unsigned int coreSpillMask;
404 unsigned int fpSpillMask;
buzbeecefd1872011-09-09 09:59:52 -0700405 unsigned int attrs;
buzbee67bf8852011-08-17 17:51:35 -0700406 /*
407 * CLEANUP/RESTRUCTURE: The code generation utilities don't have a built-in
buzbee03fa2632011-09-20 17:10:57 -0700408 * mechanism to propagate the original Dalvik opcode address to the
buzbee67bf8852011-08-17 17:51:35 -0700409 * associated generated instructions. For the trace compiler, this wasn't
410 * necessary because the interpreter handled all throws and debugging
411 * requests. For now we'll handle this by placing the Dalvik offset
412 * in the CompilationUnit struct before codegen for each instruction.
413 * The low-level LIR creation utilites will pull it from here. Should
414 * be rewritten.
415 */
416 int currentDalvikOffset;
417 GrowableList switchTables;
buzbee67bf8852011-08-17 17:51:35 -0700418 GrowableList fillArrayData;
419 const u2* insns;
420 u4 insnsSize;
buzbee99ba9642012-01-25 14:23:14 -0800421 bool disableDataflow; // Skip dataflow analysis if possible
buzbee5b537102012-01-17 17:33:47 -0800422 std::map<unsigned int, BasicBlock*> blockMap; // findBlock lookup cache
buzbee85d8c1e2012-01-27 15:52:35 -0800423 std::map<unsigned int, LIR*> boundaryMap; // boundary lookup cache
buzbee5abfa3e2012-01-31 17:01:43 -0800424 int defCount; // Used to estimate number of SSA names
buzbeeba938cb2012-02-03 14:47:55 -0800425 std::string* compilerMethodMatch;
426 bool compilerFlipMatch;
427 struct ArenaMemBlock* arenaHead;
428 struct ArenaMemBlock* currentArena;
429 int numArenaBlocks;
430 struct Memstats* mstats;
buzbeea7c12682012-03-19 13:13:53 -0700431 int* opcodeCount; // Count Dalvik opcodes for tuning
buzbee3d661942012-03-14 17:37:27 -0700432#ifndef NDEBUG
433 /*
434 * Sanity checking for the register temp tracking. The same ssa
435 * name should never be associated with one temp register per
436 * instruction compilation.
437 */
438 int liveSReg;
439#endif
Elliott Hughes719ace42012-03-09 18:06:03 -0800440};
buzbee67bf8852011-08-17 17:51:35 -0700441
Elliott Hughes719ace42012-03-09 18:06:03 -0800442enum OpSize {
buzbeee3acd072012-02-25 17:03:10 -0800443 kWord,
444 kLong,
445 kSingle,
446 kDouble,
447 kUnsignedHalf,
448 kSignedHalf,
449 kUnsignedByte,
450 kSignedByte,
Elliott Hughes719ace42012-03-09 18:06:03 -0800451};
buzbeee3acd072012-02-25 17:03:10 -0800452
Elliott Hughes719ace42012-03-09 18:06:03 -0800453enum OpKind {
buzbee31a4a6f2012-02-28 15:36:15 -0800454 kOpMov,
455 kOpMvn,
456 kOpCmp,
457 kOpLsl,
458 kOpLsr,
459 kOpAsr,
460 kOpRor,
461 kOpNot,
462 kOpAnd,
463 kOpOr,
464 kOpXor,
465 kOpNeg,
466 kOpAdd,
467 kOpAdc,
468 kOpSub,
469 kOpSbc,
470 kOpRsub,
471 kOpMul,
472 kOpDiv,
473 kOpRem,
474 kOpBic,
475 kOpCmn,
476 kOpTst,
477 kOpBkpt,
478 kOpBlx,
479 kOpPush,
480 kOpPop,
481 kOp2Char,
482 kOp2Short,
483 kOp2Byte,
484 kOpCondBr,
485 kOpUncondBr,
buzbee5de34942012-03-01 14:51:57 -0800486 kOpBx,
buzbee31a4a6f2012-02-28 15:36:15 -0800487 kOpInvalid,
Elliott Hughes719ace42012-03-09 18:06:03 -0800488};
buzbee31a4a6f2012-02-28 15:36:15 -0800489
Ian Rogers680b1bd2012-03-07 20:18:49 -0800490std::ostream& operator<<(std::ostream& os, const OpKind& kind);
491
Elliott Hughes719ace42012-03-09 18:06:03 -0800492enum ConditionCode {
Ian Rogersb5d09b22012-03-06 22:14:17 -0800493 kCondEq, // equal
494 kCondNe, // not equal
495 kCondCs, // carry set (unsigned less than)
496 kCondUlt = kCondCs,
497 kCondCc, // carry clear (unsigned greater than or same)
498 kCondUge = kCondCc,
499 kCondMi, // minus
500 kCondPl, // plus, positive or zero
501 kCondVs, // overflow
502 kCondVc, // no overflow
503 kCondHi, // unsigned greater than
504 kCondLs, // unsigned lower or same
505 kCondGe, // signed greater than or equal
506 kCondLt, // signed less than
507 kCondGt, // signed greater than
508 kCondLe, // signed less than or equal
509 kCondAl, // always
510 kCondNv, // never
Elliott Hughes719ace42012-03-09 18:06:03 -0800511};
buzbee31a4a6f2012-02-28 15:36:15 -0800512
Elliott Hughes719ace42012-03-09 18:06:03 -0800513enum ThrowKind {
buzbee31a4a6f2012-02-28 15:36:15 -0800514 kThrowNullPointer,
515 kThrowDivZero,
516 kThrowArrayBounds,
517 kThrowVerificationError,
518 kThrowNegArraySize,
519 kThrowNoSuchMethod,
520 kThrowStackOverflow,
Elliott Hughes719ace42012-03-09 18:06:03 -0800521};
buzbee31a4a6f2012-02-28 15:36:15 -0800522
Elliott Hughes719ace42012-03-09 18:06:03 -0800523struct SwitchTable {
buzbee5de34942012-03-01 14:51:57 -0800524 int offset;
525 const u2* table; // Original dex table
526 int vaddr; // Dalvik offset of switch opcode
buzbeec5159d52012-03-03 11:48:39 -0800527 LIR* anchor; // Reference instruction for relative offsets
buzbee5de34942012-03-01 14:51:57 -0800528 LIR** targets; // Array of case targets
Elliott Hughes719ace42012-03-09 18:06:03 -0800529};
buzbee5de34942012-03-01 14:51:57 -0800530
Elliott Hughes719ace42012-03-09 18:06:03 -0800531struct FillArrayData {
buzbee5de34942012-03-01 14:51:57 -0800532 int offset;
533 const u2* table; // Original dex table
534 int size;
Elliott Hughesadb8c672012-03-06 16:49:32 -0800535 int vaddr; // Dalvik offset of FILL_ARRAY_DATA opcode
Elliott Hughes719ace42012-03-09 18:06:03 -0800536};
buzbee5de34942012-03-01 14:51:57 -0800537
buzbee16da88c2012-03-20 10:38:17 -0700538#define MAX_PATTERN_LEN 5
539
540enum SpecialCaseHandler {
541 kNoHandler,
542 kNullMethod,
543 kConstFunction,
544 kIGet,
545 kIGetBoolean,
546 kIGetObject,
547 kIGetByte,
548 kIGetChar,
549 kIGetShort,
550 kIGetWide,
551 kIPut,
552 kIPutBoolean,
553 kIPutObject,
554 kIPutByte,
555 kIPutChar,
556 kIPutShort,
557 kIPutWide,
buzbeee62076c2012-03-21 14:26:16 -0700558 kIdentity,
buzbee16da88c2012-03-20 10:38:17 -0700559};
560
561struct CodePattern {
562 const Instruction::Code opcodes[MAX_PATTERN_LEN];
563 const SpecialCaseHandler handlerCode;
564};
565
566static const CodePattern specialPatterns[] = {
567 {{Instruction::RETURN_VOID}, kNullMethod},
568 {{Instruction::CONST, Instruction::RETURN}, kConstFunction},
569 {{Instruction::CONST_4, Instruction::RETURN}, kConstFunction},
Ian Rogersf24132c2012-03-21 01:34:31 -0700570 {{Instruction::CONST_4, Instruction::RETURN_OBJECT}, kConstFunction},
buzbee16da88c2012-03-20 10:38:17 -0700571 {{Instruction::CONST_16, Instruction::RETURN}, kConstFunction},
572 {{Instruction::IGET, Instruction:: RETURN}, kIGet},
Ian Rogersf24132c2012-03-21 01:34:31 -0700573 {{Instruction::IGET_BOOLEAN, Instruction::RETURN}, kIGetBoolean},
574 {{Instruction::IGET_OBJECT, Instruction::RETURN_OBJECT}, kIGetObject},
575 {{Instruction::IGET_BYTE, Instruction::RETURN}, kIGetByte},
576 {{Instruction::IGET_CHAR, Instruction::RETURN}, kIGetChar},
577 {{Instruction::IGET_SHORT, Instruction::RETURN}, kIGetShort},
578 {{Instruction::IGET_WIDE, Instruction::RETURN_WIDE}, kIGetWide},
579 {{Instruction::IPUT, Instruction::RETURN_VOID}, kIPut},
580 {{Instruction::IPUT_BOOLEAN, Instruction::RETURN_VOID}, kIPutBoolean},
581 {{Instruction::IPUT_OBJECT, Instruction::RETURN_VOID}, kIPutObject},
582 {{Instruction::IPUT_BYTE, Instruction::RETURN_VOID}, kIPutByte},
583 {{Instruction::IPUT_CHAR, Instruction::RETURN_VOID}, kIPutChar},
584 {{Instruction::IPUT_SHORT, Instruction::RETURN_VOID}, kIPutShort},
585 {{Instruction::IPUT_WIDE, Instruction::RETURN_VOID}, kIPutWide},
buzbeee62076c2012-03-21 14:26:16 -0700586 {{Instruction::RETURN}, kIdentity},
587 {{Instruction::RETURN_OBJECT}, kIdentity},
588 {{Instruction::RETURN_WIDE}, kIdentity},
buzbee16da88c2012-03-20 10:38:17 -0700589};
buzbee5de34942012-03-01 14:51:57 -0800590
buzbee5abfa3e2012-01-31 17:01:43 -0800591BasicBlock* oatNewBB(CompilationUnit* cUnit, BBType blockType, int blockId);
buzbee67bf8852011-08-17 17:51:35 -0700592
593void oatAppendMIR(BasicBlock* bb, MIR* mir);
594
595void oatPrependMIR(BasicBlock* bb, MIR* mir);
596
597void oatInsertMIRAfter(BasicBlock* bb, MIR* currentMIR, MIR* newMIR);
598
599void oatAppendLIR(CompilationUnit* cUnit, LIR* lir);
600
601void oatInsertLIRBefore(LIR* currentLIR, LIR* newLIR);
602
603void oatInsertLIRAfter(LIR* currentLIR, LIR* newLIR);
604
buzbeefc9e6fa2012-03-23 15:14:29 -0700605MIR* oatFindMoveResult(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,
606 bool wide);
buzbee67bf8852011-08-17 17:51:35 -0700607/* Debug Utilities */
608void oatDumpCompilationUnit(CompilationUnit* cUnit);
609
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800610} // namespace art
611
buzbee67bf8852011-08-17 17:51:35 -0700612#endif // ART_SRC_COMPILER_COMPILER_IR_H_