1/*
2 * Copyright (C) 2009 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#include "Dalvik.h"
18#include "CompilerInternals.h"
19
20/* Allocate a new basic block */
21BasicBlock *dvmCompilerNewBB(BBType blockType, int blockId)
22{
23    BasicBlock *bb = (BasicBlock *)dvmCompilerNew(sizeof(BasicBlock), true);
24    bb->blockType = blockType;
25    bb->id = blockId;
26    bb->predecessors = dvmCompilerAllocBitVector(blockId > 32 ? blockId : 32,
27                                                 true /* expandable */);
28    return bb;
29}
30
31/* Insert an MIR instruction to the end of a basic block */
32void dvmCompilerAppendMIR(BasicBlock *bb, MIR *mir)
33{
34    if (bb->firstMIRInsn == NULL) {
35        assert(bb->lastMIRInsn == NULL);
36        bb->lastMIRInsn = bb->firstMIRInsn = mir;
37        mir->prev = mir->next = NULL;
38    } else {
39        bb->lastMIRInsn->next = mir;
40        mir->prev = bb->lastMIRInsn;
41        mir->next = NULL;
42        bb->lastMIRInsn = mir;
43    }
44}
45
46/* Insert an MIR instruction to the head of a basic block */
47void dvmCompilerPrependMIR(BasicBlock *bb, MIR *mir)
48{
49    if (bb->firstMIRInsn == NULL) {
50        assert(bb->lastMIRInsn == NULL);
51        bb->lastMIRInsn = bb->firstMIRInsn = mir;
52        mir->prev = mir->next = NULL;
53    } else {
54        bb->firstMIRInsn->prev = mir;
55        mir->next = bb->firstMIRInsn;
56        mir->prev = NULL;
57        bb->firstMIRInsn = mir;
58    }
59}
60
61/* Insert an MIR instruction after the specified MIR */
62void dvmCompilerInsertMIRAfter(BasicBlock *bb, MIR *currentMIR, MIR *newMIR)
63{
64    newMIR->prev = currentMIR;
65    newMIR->next = currentMIR->next;
66    currentMIR->next = newMIR;
67
68    if (newMIR->next) {
69        /* Is not the last MIR in the block */
70        newMIR->next->prev = newMIR;
71    } else {
72        /* Is the last MIR in the block */
73        bb->lastMIRInsn = newMIR;
74    }
75}
76
77/*
78 * Append an LIR instruction to the LIR list maintained by a compilation
79 * unit
80 */
81void dvmCompilerAppendLIR(CompilationUnit *cUnit, LIR *lir)
82{
83    if (cUnit->firstLIRInsn == NULL) {
84        assert(cUnit->lastLIRInsn == NULL);
85        cUnit->lastLIRInsn = cUnit->firstLIRInsn = lir;
86        lir->prev = lir->next = NULL;
87    } else {
88        cUnit->lastLIRInsn->next = lir;
89        lir->prev = cUnit->lastLIRInsn;
90        lir->next = NULL;
91        cUnit->lastLIRInsn = lir;
92    }
93}
94
95/*
96 * Insert an LIR instruction before the current instruction, which cannot be the
97 * first instruction.
98 *
99 * prevLIR <-> newLIR <-> currentLIR
100 */
101void dvmCompilerInsertLIRBefore(LIR *currentLIR, LIR *newLIR)
102{
103    assert(currentLIR->prev != NULL);
104    LIR *prevLIR = currentLIR->prev;
105
106    prevLIR->next = newLIR;
107    newLIR->prev = prevLIR;
108    newLIR->next = currentLIR;
109    currentLIR->prev = newLIR;
110}
111
112/*
113 * Insert an LIR instruction after the current instruction, which cannot be the
114 * first instruction.
115 *
116 * currentLIR -> newLIR -> oldNext
117 */
118void dvmCompilerInsertLIRAfter(LIR *currentLIR, LIR *newLIR)
119{
120    newLIR->prev = currentLIR;
121    newLIR->next = currentLIR->next;
122    currentLIR->next = newLIR;
123    newLIR->next->prev = newLIR;
124}
125