1/*
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_COMPILER_DEX_PORTABLE_MIR_TO_GBC_H_
18#define ART_COMPILER_DEX_PORTABLE_MIR_TO_GBC_H_
19
20#include <llvm/ADT/ArrayRef.h>
21#include <llvm/IR/BasicBlock.h>
22#include <llvm/IR/IRBuilder.h>
23#include <llvm/IR/LLVMContext.h>
24#include <llvm/IR/Module.h>
25
26#include "invoke_type.h"
27#include "compiled_method.h"
28#include "dex/compiler_enums.h"
29#include "dex/compiler_ir.h"
30#include "dex/backend.h"
31#include "llvm/intrinsic_helper.h"
32#include "llvm/llvm_compilation_unit.h"
33#include "safe_map.h"
34
35namespace art {
36
37struct BasicBlock;
38struct CallInfo;
39struct CompilationUnit;
40struct MIR;
41struct RegLocation;
42struct RegisterInfo;
43class MIRGraph;
44
45// Target-specific initialization.
46Backend* PortableCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
47                               ArenaAllocator* const arena,
48                               llvm::LlvmCompilationUnit* const llvm_compilation_unit);
49
50class MirConverter : public Backend {
51  public:
52    // TODO: flesh out and integrate into new world order.
53    MirConverter(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena,
54                 llvm::LlvmCompilationUnit* llvm_compilation_unit)
55      : Backend(arena),
56        cu_(cu),
57        mir_graph_(mir_graph),
58        llvm_compilation_unit_(llvm_compilation_unit),
59        llvm_info_(llvm_compilation_unit->GetQuickContext()),
60        symbol_(llvm_compilation_unit->GetDexCompilationUnit()->GetSymbol()),
61        context_(NULL),
62        module_(NULL),
63        func_(NULL),
64        intrinsic_helper_(NULL),
65        irb_(NULL),
66        placeholder_bb_(NULL),
67        entry_bb_(NULL),
68        entry_target_bb_(NULL),
69        llvm_values_(arena, mir_graph->GetNumSSARegs()),
70        temp_name_(0),
71        current_dalvik_offset_(0) {
72      if (kIsDebugBuild) {
73        cu->enable_debug |= (1 << kDebugVerifyBitcode);
74      }
75    }
76
77    void Materialize() {
78      MethodMIR2Bitcode();
79    }
80
81    CompiledMethod* GetCompiledMethod() {
82      return NULL;
83    }
84
85  private:
86    ::llvm::BasicBlock* GetLLVMBlock(int id);
87    ::llvm::Value* GetLLVMValue(int s_reg);
88    void SetVregOnValue(::llvm::Value* val, int s_reg);
89    void DefineValueOnly(::llvm::Value* val, int s_reg);
90    void DefineValue(::llvm::Value* val, int s_reg);
91    ::llvm::Type* LlvmTypeFromLocRec(RegLocation loc);
92    void InitIR();
93    ::llvm::BasicBlock* FindCaseTarget(uint32_t vaddr);
94    void ConvertPackedSwitch(BasicBlock* bb, int32_t table_offset,
95                             RegLocation rl_src);
96    void ConvertSparseSwitch(BasicBlock* bb, int32_t table_offset,
97                             RegLocation rl_src);
98    void ConvertSget(int32_t field_index,
99                     art::llvm::IntrinsicHelper::IntrinsicId id, RegLocation rl_dest);
100    void ConvertSput(int32_t field_index,
101                     art::llvm::IntrinsicHelper::IntrinsicId id, RegLocation rl_src);
102    void ConvertFillArrayData(int32_t offset, RegLocation rl_array);
103    ::llvm::Value* EmitConst(::llvm::ArrayRef< ::llvm::Value*> src,
104                             RegLocation loc);
105    void EmitPopShadowFrame();
106    ::llvm::Value* EmitCopy(::llvm::ArrayRef< ::llvm::Value*> src,
107                            RegLocation loc);
108    void ConvertMoveException(RegLocation rl_dest);
109    void ConvertThrow(RegLocation rl_src);
110    void ConvertMonitorEnterExit(int opt_flags,
111                                 art::llvm::IntrinsicHelper::IntrinsicId id, RegLocation rl_src);
112    void ConvertArrayLength(int opt_flags, RegLocation rl_dest,
113                            RegLocation rl_src);
114    void EmitSuspendCheck();
115    ::llvm::Value* ConvertCompare(ConditionCode cc,
116                                  ::llvm::Value* src1, ::llvm::Value* src2);
117    void ConvertCompareAndBranch(BasicBlock* bb, MIR* mir, ConditionCode cc,
118                                 RegLocation rl_src1, RegLocation rl_src2);
119    void ConvertCompareZeroAndBranch(BasicBlock* bb, MIR* mir, ConditionCode cc,
120                                     RegLocation rl_src1);
121    ::llvm::Value* GenDivModOp(bool is_div, bool is_long, ::llvm::Value* src1,
122                               ::llvm::Value* src2);
123    ::llvm::Value* GenArithOp(OpKind op, bool is_long, ::llvm::Value* src1,
124                              ::llvm::Value* src2);
125    void ConvertFPArithOp(OpKind op, RegLocation rl_dest, RegLocation rl_src1,
126                          RegLocation rl_src2);
127    void ConvertShift(art::llvm::IntrinsicHelper::IntrinsicId id,
128                      RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
129    void ConvertShiftLit(art::llvm::IntrinsicHelper::IntrinsicId id,
130                         RegLocation rl_dest, RegLocation rl_src, int shift_amount);
131    void ConvertArithOp(OpKind op, RegLocation rl_dest, RegLocation rl_src1,
132                        RegLocation rl_src2);
133    void ConvertArithOpLit(OpKind op, RegLocation rl_dest, RegLocation rl_src1,
134                           int32_t imm);
135    void ConvertInvoke(BasicBlock* bb, MIR* mir, InvokeType invoke_type,
136                       bool is_range, bool is_filled_new_array);
137    void ConvertConstObject(uint32_t idx,
138                            art::llvm::IntrinsicHelper::IntrinsicId id, RegLocation rl_dest);
139    void ConvertCheckCast(uint32_t type_idx, RegLocation rl_src);
140    void ConvertNewInstance(uint32_t type_idx, RegLocation rl_dest);
141    void ConvertNewArray(uint32_t type_idx, RegLocation rl_dest,
142                         RegLocation rl_src);
143    void ConvertAget(int opt_flags, art::llvm::IntrinsicHelper::IntrinsicId id,
144                     RegLocation rl_dest, RegLocation rl_array, RegLocation rl_index);
145    void ConvertAput(int opt_flags, art::llvm::IntrinsicHelper::IntrinsicId id,
146                     RegLocation rl_src, RegLocation rl_array, RegLocation rl_index);
147    void ConvertIget(int opt_flags, art::llvm::IntrinsicHelper::IntrinsicId id,
148                     RegLocation rl_dest, RegLocation rl_obj, int field_index);
149    void ConvertIput(int opt_flags, art::llvm::IntrinsicHelper::IntrinsicId id,
150                     RegLocation rl_src, RegLocation rl_obj, int field_index);
151    void ConvertInstanceOf(uint32_t type_idx, RegLocation rl_dest,
152                           RegLocation rl_src);
153    void ConvertIntToLong(RegLocation rl_dest, RegLocation rl_src);
154    void ConvertLongToInt(RegLocation rl_dest, RegLocation rl_src);
155    void ConvertFloatToDouble(RegLocation rl_dest, RegLocation rl_src);
156    void ConvertDoubleToFloat(RegLocation rl_dest, RegLocation rl_src);
157    void ConvertWideComparison(art::llvm::IntrinsicHelper::IntrinsicId id,
158                               RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
159    void ConvertIntNarrowing(RegLocation rl_dest, RegLocation rl_src,
160                             art::llvm::IntrinsicHelper::IntrinsicId id);
161    void ConvertNeg(RegLocation rl_dest, RegLocation rl_src);
162    void ConvertIntToFP(::llvm::Type* ty, RegLocation rl_dest, RegLocation rl_src);
163    void ConvertFPToInt(art::llvm::IntrinsicHelper::IntrinsicId id,
164                        RegLocation rl_dest, RegLocation rl_src);
165    void ConvertNegFP(RegLocation rl_dest, RegLocation rl_src);
166    void ConvertNot(RegLocation rl_dest, RegLocation rl_src);
167    void EmitConstructorBarrier();
168    bool ConvertMIRNode(MIR* mir, BasicBlock* bb, ::llvm::BasicBlock* llvm_bb);
169    void SetDexOffset(int32_t offset);
170    void SetMethodInfo();
171    void HandlePhiNodes(BasicBlock* bb, ::llvm::BasicBlock* llvm_bb);
172    void ConvertExtendedMIR(BasicBlock* bb, MIR* mir, ::llvm::BasicBlock* llvm_bb);
173    bool BlockBitcodeConversion(BasicBlock* bb);
174    ::llvm::FunctionType* GetFunctionType();
175    bool CreateFunction();
176    bool CreateLLVMBasicBlock(BasicBlock* bb);
177    void MethodMIR2Bitcode();
178
179    CompilationUnit* cu_;
180    MIRGraph* mir_graph_;
181    llvm::LlvmCompilationUnit* const llvm_compilation_unit_;
182    LLVMInfo* llvm_info_;
183    std::string symbol_;
184    ::llvm::LLVMContext* context_;
185    ::llvm::Module* module_;
186    ::llvm::Function* func_;
187    art::llvm::IntrinsicHelper* intrinsic_helper_;
188    art::llvm::IRBuilder* irb_;
189    ::llvm::BasicBlock* placeholder_bb_;
190    ::llvm::BasicBlock* entry_bb_;
191    ::llvm::BasicBlock* entry_target_bb_;
192    std::string bitcode_filename_;
193    GrowableArray< ::llvm::Value*> llvm_values_;
194    int32_t temp_name_;
195    SafeMap<int32_t, ::llvm::BasicBlock*> id_to_block_map_;  // block id -> llvm bb.
196    int current_dalvik_offset_;
197};  // Class MirConverter
198
199}  // namespace art
200
201#endif  // ART_COMPILER_DEX_PORTABLE_MIR_TO_GBC_H_
202