summaryrefslogtreecommitdiffstats
path: root/compiler/dex/portable/mir_to_gbc.h
blob: bc4f5c41002905ee4b429ecb53b801ff1636f7ba (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
/*
 * 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.
 */

#ifndef ART_COMPILER_DEX_PORTABLE_MIR_TO_GBC_H_
#define ART_COMPILER_DEX_PORTABLE_MIR_TO_GBC_H_

#include <llvm/ADT/ArrayRef.h>
#include <llvm/IR/BasicBlock.h>
#include <llvm/IR/IRBuilder.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>

#include "invoke_type.h"
#include "compiled_method.h"
#include "dex/compiler_enums.h"
#include "dex/compiler_ir.h"
#include "dex/backend.h"
#include "llvm/intrinsic_helper.h"
#include "llvm/llvm_compilation_unit.h"
#include "safe_map.h"
#include "utils/arena_containers.h"

namespace llvm {
  class Module;
  class LLVMContext;
}

namespace art {

namespace llvm {
  class IntrinsicHelper;
  class IRBuilder;
}

class LLVMInfo {
  public:
    LLVMInfo();
    ~LLVMInfo();

    ::llvm::LLVMContext* GetLLVMContext() {
      return llvm_context_.get();
    }

    ::llvm::Module* GetLLVMModule() {
      return llvm_module_;
    }

    art::llvm::IntrinsicHelper* GetIntrinsicHelper() {
      return intrinsic_helper_.get();
    }

    art::llvm::IRBuilder* GetIRBuilder() {
      return ir_builder_.get();
    }

  private:
    std::unique_ptr< ::llvm::LLVMContext> llvm_context_;
    ::llvm::Module* llvm_module_;  // Managed by context_.
    std::unique_ptr<art::llvm::IntrinsicHelper> intrinsic_helper_;
    std::unique_ptr<art::llvm::IRBuilder> ir_builder_;
};

class BasicBlock;
struct CallInfo;
struct CompilationUnit;
struct MIR;
struct RegLocation;
struct RegisterInfo;
class MIRGraph;

// Target-specific initialization.
Backend* PortableCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
                               ArenaAllocator* const arena,
                               llvm::LlvmCompilationUnit* const llvm_compilation_unit);

class MirConverter : public Backend {
  public:
    // TODO: flesh out and integrate into new world order.
    MirConverter(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena,
                 llvm::LlvmCompilationUnit* llvm_compilation_unit)
      : Backend(arena),
        cu_(cu),
        mir_graph_(mir_graph),
        llvm_compilation_unit_(llvm_compilation_unit),
        llvm_info_(llvm_compilation_unit->GetQuickContext()),
        symbol_(llvm_compilation_unit->GetDexCompilationUnit()->GetSymbol()),
        context_(NULL),
        module_(NULL),
        func_(NULL),
        intrinsic_helper_(NULL),
        irb_(NULL),
        placeholder_bb_(NULL),
        entry_bb_(NULL),
        entry_target_bb_(NULL),
        llvm_values_(arena->Adapter()),
        temp_name_(0),
        current_dalvik_offset_(0) {
      llvm_values_.reserve(mir_graph->GetNumSSARegs());
      if (kIsDebugBuild) {
        cu->enable_debug |= (1 << kDebugVerifyBitcode);
      }
    }

    void Materialize() {
      MethodMIR2Bitcode();
    }

    CompiledMethod* GetCompiledMethod() {
      return NULL;
    }

  private:
    ::llvm::BasicBlock* GetLLVMBlock(int id);
    ::llvm::Value* GetLLVMValue(int s_reg);
    void SetVregOnValue(::llvm::Value* val, int s_reg);
    void DefineValueOnly(::llvm::Value* val, int s_reg);
    void DefineValue(::llvm::Value* val, int s_reg);
    ::llvm::Type* LlvmTypeFromLocRec(RegLocation loc);
    void InitIR();
    ::llvm::BasicBlock* FindCaseTarget(uint32_t vaddr);
    void ConvertPackedSwitch(BasicBlock* bb, MIR* mir, int32_t table_offset,
                             RegLocation rl_src);
    void ConvertSparseSwitch(BasicBlock* bb, MIR* mir, int32_t table_offset,
                             RegLocation rl_src);
    void ConvertSget(int32_t field_index,
                     art::llvm::IntrinsicHelper::IntrinsicId id, RegLocation rl_dest);
    void ConvertSput(int32_t field_index,
                     art::llvm::IntrinsicHelper::IntrinsicId id, RegLocation rl_src);
    void ConvertFillArrayData(int32_t offset, RegLocation rl_array);
    ::llvm::Value* EmitConst(::llvm::ArrayRef< ::llvm::Value*> src,
                             RegLocation loc);
    void EmitPopShadowFrame();
    ::llvm::Value* EmitCopy(::llvm::ArrayRef< ::llvm::Value*> src,
                            RegLocation loc);
    void ConvertMoveException(RegLocation rl_dest);
    void ConvertThrow(RegLocation rl_src);
    void ConvertMonitorEnterExit(int opt_flags,
                                 art::llvm::IntrinsicHelper::IntrinsicId id, RegLocation rl_src);
    void ConvertArrayLength(int opt_flags, RegLocation rl_dest,
                            RegLocation rl_src);
    void EmitSuspendCheck();
    ::llvm::Value* ConvertCompare(ConditionCode cc,
                                  ::llvm::Value* src1, ::llvm::Value* src2);
    void ConvertCompareAndBranch(BasicBlock* bb, MIR* mir, ConditionCode cc,
                                 RegLocation rl_src1, RegLocation rl_src2);
    void ConvertCompareZeroAndBranch(BasicBlock* bb, MIR* mir, ConditionCode cc,
                                     RegLocation rl_src1);
    ::llvm::Value* GenDivModOp(bool is_div, bool is_long, ::llvm::Value* src1,
                               ::llvm::Value* src2);
    ::llvm::Value* GenArithOp(OpKind op, bool is_long, ::llvm::Value* src1,
                              ::llvm::Value* src2);
    void ConvertFPArithOp(OpKind op, RegLocation rl_dest, RegLocation rl_src1,
                          RegLocation rl_src2);
    void ConvertShift(art::llvm::IntrinsicHelper::IntrinsicId id,
                      RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
    void ConvertShiftLit(art::llvm::IntrinsicHelper::IntrinsicId id,
                         RegLocation rl_dest, RegLocation rl_src, int shift_amount);
    void ConvertArithOp(OpKind op, RegLocation rl_dest, RegLocation rl_src1,
                        RegLocation rl_src2);
    void ConvertArithOpLit(OpKind op, RegLocation rl_dest, RegLocation rl_src1,
                           int32_t imm);
    void ConvertInvoke(BasicBlock* bb, MIR* mir, InvokeType invoke_type,
                       bool is_range, bool is_filled_new_array);
    void ConvertConstObject(uint32_t idx,
                            art::llvm::IntrinsicHelper::IntrinsicId id, RegLocation rl_dest);
    void ConvertCheckCast(uint32_t type_idx, RegLocation rl_src);
    void ConvertNewInstance(uint32_t type_idx, RegLocation rl_dest);
    void ConvertNewArray(uint32_t type_idx, RegLocation rl_dest,
                         RegLocation rl_src);
    void ConvertAget(int opt_flags, art::llvm::IntrinsicHelper::IntrinsicId id,
                     RegLocation rl_dest, RegLocation rl_array, RegLocation rl_index);
    void ConvertAput(int opt_flags, art::llvm::IntrinsicHelper::IntrinsicId id,
                     RegLocation rl_src, RegLocation rl_array, RegLocation rl_index);
    void ConvertIget(int opt_flags, art::llvm::IntrinsicHelper::IntrinsicId id,
                     RegLocation rl_dest, RegLocation rl_obj, int field_index);
    void ConvertIput(int opt_flags, art::llvm::IntrinsicHelper::IntrinsicId id,
                     RegLocation rl_src, RegLocation rl_obj, int field_index);
    void ConvertInstanceOf(uint32_t type_idx, RegLocation rl_dest,
                           RegLocation rl_src);
    void ConvertIntToLong(RegLocation rl_dest, RegLocation rl_src);
    void ConvertLongToInt(RegLocation rl_dest, RegLocation rl_src);
    void ConvertFloatToDouble(RegLocation rl_dest, RegLocation rl_src);
    void ConvertDoubleToFloat(RegLocation rl_dest, RegLocation rl_src);
    void ConvertWideComparison(art::llvm::IntrinsicHelper::IntrinsicId id,
                               RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
    void ConvertIntNarrowing(RegLocation rl_dest, RegLocation rl_src,
                             art::llvm::IntrinsicHelper::IntrinsicId id);
    void ConvertNeg(RegLocation rl_dest, RegLocation rl_src);
    void ConvertIntToFP(::llvm::Type* ty, RegLocation rl_dest, RegLocation rl_src);
    void ConvertFPToInt(art::llvm::IntrinsicHelper::IntrinsicId id,
                        RegLocation rl_dest, RegLocation rl_src);
    void ConvertNegFP(RegLocation rl_dest, RegLocation rl_src);
    void ConvertNot(RegLocation rl_dest, RegLocation rl_src);
    void EmitConstructorBarrier();
    bool ConvertMIRNode(MIR* mir, BasicBlock* bb, ::llvm::BasicBlock* llvm_bb);
    void SetDexOffset(int32_t offset);
    void SetMethodInfo();
    void HandlePhiNodes(BasicBlock* bb, ::llvm::BasicBlock* llvm_bb);
    void ConvertExtendedMIR(BasicBlock* bb, MIR* mir, ::llvm::BasicBlock* llvm_bb);
    bool BlockBitcodeConversion(BasicBlock* bb);
    ::llvm::FunctionType* GetFunctionType();
    bool CreateFunction();
    bool CreateLLVMBasicBlock(BasicBlock* bb);
    void MethodMIR2Bitcode();

    CompilationUnit* cu_;
    MIRGraph* mir_graph_;
    llvm::LlvmCompilationUnit* const llvm_compilation_unit_;
    LLVMInfo* llvm_info_;
    std::string symbol_;
    ::llvm::LLVMContext* context_;
    ::llvm::Module* module_;
    ::llvm::Function* func_;
    art::llvm::IntrinsicHelper* intrinsic_helper_;
    art::llvm::IRBuilder* irb_;
    ::llvm::BasicBlock* placeholder_bb_;
    ::llvm::BasicBlock* entry_bb_;
    ::llvm::BasicBlock* entry_target_bb_;
    std::string bitcode_filename_;
    ArenaVector< ::llvm::Value*> llvm_values_;
    int32_t temp_name_;
    SafeMap<int32_t, ::llvm::BasicBlock*> id_to_block_map_;  // block id -> llvm bb.
    int current_dalvik_offset_;
};  // Class MirConverter

}  // namespace art

#endif  // ART_COMPILER_DEX_PORTABLE_MIR_TO_GBC_H_