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 
35 namespace art {
36 
37 struct BasicBlock;
38 struct CallInfo;
39 struct CompilationUnit;
40 struct MIR;
41 struct RegLocation;
42 struct RegisterInfo;
43 class MIRGraph;
44 
45 // Target-specific initialization.
46 Backend* PortableCodeGenerator(CompilationUnit* const cu, MIRGraph* const mir_graph,
47                                ArenaAllocator* const arena,
48                                llvm::LlvmCompilationUnit* const llvm_compilation_unit);
49 
50 class MirConverter : public Backend {
51   public:
52     // TODO: flesh out and integrate into new world order.
MirConverter(CompilationUnit * cu,MIRGraph * mir_graph,ArenaAllocator * arena,llvm::LlvmCompilationUnit * llvm_compilation_unit)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 
Materialize()77     void Materialize() {
78       MethodMIR2Bitcode();
79     }
80 
GetCompiledMethod()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