Oat compiler integration snapshot.

Cleanly compiles, but not integrated.  Old-world dependencies captured
in hacked-up temporary files "Dalvik.h" and "HackStubs.cc".

Dalvik.h is a placeholder that captures all of the constants, struct
definitions and inline functions the compiler needs.  It largely consists
of declaration fragments of libdex, Object.h, DvmDex.h and Thread.h.

HackStubs.cc contains empty shells for some required libdex routines.

Change-Id: Ia479dda41da4e3162ff6df383252fdc7dbf38d71
diff --git a/src/compiler/codegen/arm/CodegenCommon.cc b/src/compiler/codegen/arm/CodegenCommon.cc
new file mode 100644
index 0000000..1aba82c
--- /dev/null
+++ b/src/compiler/codegen/arm/CodegenCommon.cc
@@ -0,0 +1,418 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This file contains codegen and support common to all supported
+ * ARM variants.  It is included by:
+ *
+ *        Codegen-$(TARGET_ARCH_VARIANT).c
+ *
+ * which combines this common code with specific support found in the
+ * applicable directory below this one.
+ */
+
+/* Track exercised opcodes */
+static int opcodeCoverage[kNumPackedOpcodes];
+
+static void setMemRefType(ArmLIR* lir, bool isLoad, int memType)
+{
+    u8 *maskPtr;
+    u8 mask = ENCODE_MEM;;
+    assert(EncodingMap[lir->opcode].flags & (IS_LOAD | IS_STORE));
+    if (isLoad) {
+        maskPtr = &lir->useMask;
+    } else {
+        maskPtr = &lir->defMask;
+    }
+    /* Clear out the memref flags */
+    *maskPtr &= ~mask;
+    /* ..and then add back the one we need */
+    switch(memType) {
+        case kLiteral:
+            assert(isLoad);
+            *maskPtr |= ENCODE_LITERAL;
+            break;
+        case kDalvikReg:
+            *maskPtr |= ENCODE_DALVIK_REG;
+            break;
+        case kHeapRef:
+            *maskPtr |= ENCODE_HEAP_REF;
+            break;
+        case kMustNotAlias:
+            /* Currently only loads can be marked as kMustNotAlias */
+            assert(!(EncodingMap[lir->opcode].flags & IS_STORE));
+            *maskPtr |= ENCODE_MUST_NOT_ALIAS;
+            break;
+        default:
+            LOG(FATAL) << "Oat: invalid memref kind - " << memType;
+    }
+}
+
+/*
+ * Mark load/store instructions that access Dalvik registers through r5FP +
+ * offset.
+ */
+static void annotateDalvikRegAccess(ArmLIR* lir, int regId, bool isLoad)
+{
+    setMemRefType(lir, isLoad, kDalvikReg);
+
+    /*
+     * Store the Dalvik register id in aliasInfo. Mark he MSB if it is a 64-bit
+     * access.
+     */
+    lir->aliasInfo = regId;
+    if (DOUBLEREG(lir->operands[0])) {
+        lir->aliasInfo |= 0x80000000;
+    }
+}
+
+/*
+ * Decode the register id.
+ */
+static inline u8 getRegMaskCommon(int reg)
+{
+    u8 seed;
+    int shift;
+    int regId = reg & 0x1f;
+
+    /*
+     * Each double register is equal to a pair of single-precision FP registers
+     */
+    seed = DOUBLEREG(reg) ? 3 : 1;
+    /* FP register starts at bit position 16 */
+    shift = FPREG(reg) ? kFPReg0 : 0;
+    /* Expand the double register id into single offset */
+    shift += regId;
+    return (seed << shift);
+}
+
+/*
+ * Mark the corresponding bit(s).
+ */
+static inline void setupRegMask(u8* mask, int reg)
+{
+    *mask |= getRegMaskCommon(reg);
+}
+
+/*
+ * Set up the proper fields in the resource mask
+ */
+static void setupResourceMasks(ArmLIR* lir)
+{
+    int opcode = lir->opcode;
+    int flags;
+
+    if (opcode <= 0) {
+        lir->useMask = lir->defMask = 0;
+        return;
+    }
+
+    flags = EncodingMap[lir->opcode].flags;
+
+    /* Set up the mask for resources that are updated */
+    if (flags & (IS_LOAD | IS_STORE)) {
+        /* Default to heap - will catch specialized classes later */
+        setMemRefType(lir, flags & IS_LOAD, kHeapRef);
+    }
+
+    /*
+     * Conservatively assume the branch here will call out a function that in
+     * turn will trash everything.
+     */
+    if (flags & IS_BRANCH) {
+        lir->defMask = lir->useMask = ENCODE_ALL;
+        return;
+    }
+
+    if (flags & REG_DEF0) {
+        setupRegMask(&lir->defMask, lir->operands[0]);
+    }
+
+    if (flags & REG_DEF1) {
+        setupRegMask(&lir->defMask, lir->operands[1]);
+    }
+
+    if (flags & REG_DEF_SP) {
+        lir->defMask |= ENCODE_REG_SP;
+    }
+
+    if (flags & REG_DEF_LR) {
+        lir->defMask |= ENCODE_REG_LR;
+    }
+
+    if (flags & REG_DEF_LIST0) {
+        lir->defMask |= ENCODE_REG_LIST(lir->operands[0]);
+    }
+
+    if (flags & REG_DEF_LIST1) {
+        lir->defMask |= ENCODE_REG_LIST(lir->operands[1]);
+    }
+
+    if (flags & REG_DEF_FPCS_LIST0) {
+        lir->defMask |= ENCODE_REG_FPCS_LIST(lir->operands[0]);
+    }
+
+    if (flags & SETS_CCODES) {
+        lir->defMask |= ENCODE_CCODE;
+    }
+
+    /* Conservatively treat the IT block */
+    if (flags & IS_IT) {
+        lir->defMask = ENCODE_ALL;
+    }
+
+    if (flags & (REG_USE0 | REG_USE1 | REG_USE2 | REG_USE3)) {
+        int i;
+
+        for (i = 0; i < 4; i++) {
+            if (flags & (1 << (kRegUse0 + i))) {
+                setupRegMask(&lir->useMask, lir->operands[i]);
+            }
+        }
+    }
+
+    if (flags & REG_USE_PC) {
+        lir->useMask |= ENCODE_REG_PC;
+    }
+
+    if (flags & REG_USE_SP) {
+        lir->useMask |= ENCODE_REG_SP;
+    }
+
+    if (flags & REG_USE_LIST0) {
+        lir->useMask |= ENCODE_REG_LIST(lir->operands[0]);
+    }
+
+    if (flags & REG_USE_LIST1) {
+        lir->useMask |= ENCODE_REG_LIST(lir->operands[1]);
+    }
+
+    if (flags & REG_USE_FPCS_LIST0) {
+        lir->useMask |= ENCODE_REG_FPCS_LIST(lir->operands[0]);
+    }
+
+    if (flags & REG_USE_FPCS_LIST2) {
+        lir->useMask |= ENCODE_REG_FPCS_LIST(lir->operands[2] >> 16);
+    }
+
+    if (flags & USES_CCODES) {
+        lir->useMask |= ENCODE_CCODE;
+    }
+
+    /* Fixup for kThumbPush/lr and kThumbPop/pc */
+    if (opcode == kThumbPush || opcode == kThumbPop) {
+        u8 r8Mask = getRegMaskCommon(r8);
+        if ((opcode == kThumbPush) && (lir->useMask & r8Mask)) {
+            lir->useMask &= ~r8Mask;
+            lir->useMask |= ENCODE_REG_LR;
+        } else if ((opcode == kThumbPop) && (lir->defMask & r8Mask)) {
+            lir->defMask &= ~r8Mask;
+            lir->defMask |= ENCODE_REG_PC;
+        }
+    }
+}
+
+/*
+ * Set up the accurate resource mask for branch instructions
+ */
+static void relaxBranchMasks(ArmLIR* lir)
+{
+    int flags = EncodingMap[lir->opcode].flags;
+
+    /* Make sure only branch instructions are passed here */
+    assert(flags & IS_BRANCH);
+
+    lir->useMask = lir->defMask = ENCODE_REG_PC;
+
+    if (flags & REG_DEF_LR) {
+        lir->defMask |= ENCODE_REG_LR;
+    }
+
+    if (flags & (REG_USE0 | REG_USE1 | REG_USE2 | REG_USE3)) {
+        int i;
+
+        for (i = 0; i < 4; i++) {
+            if (flags & (1 << (kRegUse0 + i))) {
+                setupRegMask(&lir->useMask, lir->operands[i]);
+            }
+        }
+    }
+
+    if (flags & USES_CCODES) {
+        lir->useMask |= ENCODE_CCODE;
+    }
+}
+
+/*
+ * The following are building blocks to construct low-level IRs with 0 - 4
+ * operands.
+ */
+static ArmLIR* newLIR0(CompilationUnit* cUnit, ArmOpcode opcode)
+{
+    ArmLIR* insn = (ArmLIR* ) oatNew(sizeof(ArmLIR), true);
+    assert(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & NO_OPERAND));
+    insn->opcode = opcode;
+    setupResourceMasks(insn);
+    insn->generic.dalvikOffset = cUnit->currentDalvikOffset;
+    oatAppendLIR(cUnit, (LIR*) insn);
+    return insn;
+}
+
+static ArmLIR* newLIR1(CompilationUnit* cUnit, ArmOpcode opcode,
+                           int dest)
+{
+    ArmLIR* insn = (ArmLIR* ) oatNew(sizeof(ArmLIR), true);
+    assert(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_UNARY_OP));
+    insn->opcode = opcode;
+    insn->operands[0] = dest;
+    setupResourceMasks(insn);
+    insn->generic.dalvikOffset = cUnit->currentDalvikOffset;
+    oatAppendLIR(cUnit, (LIR*) insn);
+    return insn;
+}
+
+static ArmLIR* newLIR2(CompilationUnit* cUnit, ArmOpcode opcode,
+                           int dest, int src1)
+{
+    ArmLIR* insn = (ArmLIR* ) oatNew(sizeof(ArmLIR), true);
+    assert(isPseudoOpcode(opcode) ||
+           (EncodingMap[opcode].flags & IS_BINARY_OP));
+    insn->opcode = opcode;
+    insn->operands[0] = dest;
+    insn->operands[1] = src1;
+    setupResourceMasks(insn);
+    insn->generic.dalvikOffset = cUnit->currentDalvikOffset;
+    oatAppendLIR(cUnit, (LIR*) insn);
+    return insn;
+}
+
+static ArmLIR* newLIR3(CompilationUnit* cUnit, ArmOpcode opcode,
+                           int dest, int src1, int src2)
+{
+    ArmLIR* insn = (ArmLIR* ) oatNew(sizeof(ArmLIR), true);
+    assert(isPseudoOpcode(opcode) ||
+           (EncodingMap[opcode].flags & IS_TERTIARY_OP));
+    insn->opcode = opcode;
+    insn->operands[0] = dest;
+    insn->operands[1] = src1;
+    insn->operands[2] = src2;
+    setupResourceMasks(insn);
+    insn->generic.dalvikOffset = cUnit->currentDalvikOffset;
+    oatAppendLIR(cUnit, (LIR*) insn);
+    return insn;
+}
+
+#if defined(_ARMV7_A) || defined(_ARMV7_A_NEON)
+static ArmLIR* newLIR4(CompilationUnit* cUnit, ArmOpcode opcode,
+                           int dest, int src1, int src2, int info)
+{
+    ArmLIR* insn = (ArmLIR* ) oatNew(sizeof(ArmLIR), true);
+    assert(isPseudoOpcode(opcode) ||
+           (EncodingMap[opcode].flags & IS_QUAD_OP));
+    insn->opcode = opcode;
+    insn->operands[0] = dest;
+    insn->operands[1] = src1;
+    insn->operands[2] = src2;
+    insn->operands[3] = info;
+    setupResourceMasks(insn);
+    insn->generic.dalvikOffset = cUnit->currentDalvikOffset;
+    oatAppendLIR(cUnit, (LIR*) insn);
+    return insn;
+}
+#endif
+
+/*
+ * Search the existing constants in the literal pool for an exact or close match
+ * within specified delta (greater or equal to 0).
+ */
+static ArmLIR* scanLiteralPool(LIR* dataTarget, int value, unsigned int delta)
+{
+    while (dataTarget) {
+        if (((unsigned) (value - ((ArmLIR* ) dataTarget)->operands[0])) <=
+            delta)
+            return (ArmLIR* ) dataTarget;
+        dataTarget = dataTarget->next;
+    }
+    return NULL;
+}
+
+/*
+ * The following are building blocks to insert constants into the pool or
+ * instruction streams.
+ */
+
+/* Add a 32-bit constant either in the constant pool or mixed with code */
+static ArmLIR* addWordData(CompilationUnit* cUnit, LIR* *constantListP,
+                           int value)
+{
+    /* Add the constant to the literal pool */
+    if (constantListP) {
+        ArmLIR* newValue = (ArmLIR* ) oatNew(sizeof(ArmLIR), true);
+        newValue->operands[0] = value;
+        newValue->generic.next = *constantListP;
+        *constantListP = (LIR*) newValue;
+        return newValue;
+    } else {
+        /* Add the constant in the middle of code stream */
+        newLIR1(cUnit, kArm16BitData, (value & 0xffff));
+        newLIR1(cUnit, kArm16BitData, (value >> 16));
+    }
+    return NULL;
+}
+
+/*
+ * Generate an kArmPseudoBarrier marker to indicate the boundary of special
+ * blocks.
+ */
+static void genBarrier(CompilationUnit* cUnit)
+{
+    ArmLIR* barrier = newLIR0(cUnit, kArmPseudoBarrier);
+    /* Mark all resources as being clobbered */
+    barrier->defMask = -1;
+}
+
+/* Create the PC reconstruction slot if not already done */
+static ArmLIR* genCheckCommon(CompilationUnit* cUnit, int dOffset,
+                              ArmLIR* branch,
+                              ArmLIR* pcrLabel)
+{
+    //FIXME - won't be rolling back, need to throw now.
+    UNIMPLEMENTED(WARNING);
+#if 0
+
+    /* Forget all def info (because we might rollback here.  Bug #2367397 */
+    oatResetDefTracking(cUnit);
+
+    /* Set up the place holder to reconstruct this Dalvik PC */
+    if (pcrLabel == NULL) {
+        int dPC = (int) (cUnit->insns + dOffset);
+        pcrLabel = (ArmLIR* ) oatNew(sizeof(ArmLIR), true);
+        pcrLabel->opcode = kArmPseudoPCReconstructionCell;
+        pcrLabel->operands[0] = dPC;
+        pcrLabel->operands[1] = dOffset;
+        /* Insert the place holder to the growable list */
+        oatInsertGrowableList(&cUnit->pcReconstructionList,
+                              (intptr_t) pcrLabel);
+    }
+#endif
+    /* Branch to the PC reconstruction code */
+    branch->generic.target = (LIR*) pcrLabel;
+
+    /* Clear the conservative flags for branches that punt to the interpreter */
+    relaxBranchMasks(branch);
+
+    return pcrLabel;
+}