• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef LIBLLVMBACKEND_LOWERING_LLVM_IR_CONSTRUCTOR_H
17 #define LIBLLVMBACKEND_LOWERING_LLVM_IR_CONSTRUCTOR_H
18 
19 #include "optimizer/ir/graph.h"
20 #include "optimizer/ir/graph_visitor.h"
21 #include "optimizer/ir/inst.h"
22 
23 #include "debug_data_builder.h"
24 #include "llvm_ark_interface.h"
25 
26 #include <llvm/IR/Function.h>
27 #include <llvm/IR/IRBuilder.h>
28 
29 namespace panda::compiler {
30 
31 class LLVMIrConstructor : public GraphVisitor {
32     using RuntimeCallId = std::variant<RuntimeInterface::EntrypointId, RuntimeInterface::IntrinsicId>;
33 
34     bool TryEmitIntrinsic(Inst *inst, RuntimeInterface::IntrinsicId arkId);
35 
36 private:
37     // Specific intrinsic Emitters
38     bool EmitUnreachable();
39     bool EmitSlowPathEntry(Inst *inst);
40     bool EmitExclusiveLoadWithAcquire(Inst *inst);
41     bool EmitExclusiveStoreWithRelease(Inst *inst);
42     bool EmitInterpreterReturn();
43     bool EmitTailCall(Inst *inst);
44     bool EmitMemoryFence(memory_order::Order order);
45     template <uint32_t VECTOR_SIZE>
46     bool EmitCompressUtf16ToUtf8CharsUsingSimd(Inst *inst);
47 
48 public:
49     llvm::Value *GetMappedValue(Inst *inst, DataType::Type type);
50     llvm::Value *GetInputValue(Inst *inst, size_t index, bool skipCoerce = false);
51     llvm::Value *GetInputValueFromConstant(ConstantInst *constant, DataType::Type pandaType);
52 
GetGraph()53     Graph *GetGraph() const
54     {
55         return graph_;
56     }
57 
GetFunc()58     llvm::Function *GetFunc()
59     {
60         return func_;
61     }
62 
GetBlocksToVisit()63     const ArenaVector<BasicBlock *> &GetBlocksToVisit() const override
64     {
65         return graph_->GetBlocksRPO();
66     }
67 
68 private:
69     // Initializers. BuildIr calls them
70     void BuildBasicBlocks();
71     void BuildInstructions();
72     void FillPhiInputs();
73 
74     // Creator functions for internal usage
75 
76     void CreateInterpreterReturnRestoreRegs(RegMask &regMask, size_t offset, bool fp);
77     llvm::Value *CreateBinaryOp(Inst *inst, llvm::Instruction::BinaryOps opcode);
78     llvm::Value *CreateBinaryImmOp(Inst *inst, llvm::Instruction::BinaryOps opcode, uint64_t c);
79     llvm::Value *CreateShiftOp(Inst *inst, llvm::Instruction::BinaryOps opcode);
80     llvm::Value *CreateSignDivMod(Inst *inst, llvm::Instruction::BinaryOps opcode);
81     llvm::Value *CreateAArch64SignDivMod(Inst *inst, llvm::Instruction::BinaryOps opcode, llvm::Value *x,
82                                          llvm::Value *y);
83     llvm::Value *CreateFloatComparison(CmpInst *cmpInst, llvm::Value *x, llvm::Value *y);
84     llvm::Value *CreateIntegerComparison(CmpInst *inst, llvm::Value *x, llvm::Value *y);
85     llvm::Value *CreateCastToInt(Inst *inst);
86     llvm::Value *CreateLoadWithOrdering(Inst *inst, llvm::Value *value, llvm::AtomicOrdering ordering,
87                                         const llvm::Twine &name = "");
88     llvm::Value *CreateStoreWithOrdering(llvm::Value *value, llvm::Value *ptr, llvm::AtomicOrdering ordering);
89     void CreatePreWRB(Inst *inst, llvm::Value *mem);
90     void CreatePostWRB(Inst *inst, llvm::Value *mem, llvm::Value *offset, llvm::Value *value);
91     llvm::Value *CreateMemoryFence(memory_order::Order order);
92     llvm::Value *CreateCondition(ConditionCode cc, llvm::Value *x, llvm::Value *y);
93     void CreateIf(Inst *inst, llvm::Value *cond, bool likely, bool unlikely);
94     llvm::CallInst *CreateTailCallFastPath(Inst *inst);
95     llvm::CallInst *CreateTailCallInterpreter(Inst *inst);
96 
97     // Getters
98     llvm::FunctionType *GetEntryFunctionType();
99 
100     llvm::StringRef GetRuntimeFunctionName(RuntimeCallId id);
101 
102     llvm::Value *GetThreadRegValue();
103     llvm::Value *GetRealFrameRegValue();
104 
GetArgument(size_t index)105     llvm::Argument *GetArgument(size_t index)
106     {
107         ASSERT(func_ != nullptr);
108         auto offset = 0;
109         return func_->arg_begin() + offset + index;
110     }
111 
112     llvm::Type *GetType(DataType::Type pandaType);
113     llvm::Type *GetExactType(DataType::Type targetType);
114 
115     llvm::Instruction::CastOps GetCastOp(DataType::Type from, DataType::Type to);
116 
117     llvm::Value *CoerceValue(llvm::Value *value, DataType::Type sourceType, DataType::Type targetType);
118     llvm::Value *CoerceValue(llvm::Value *value, llvm::Type *targetType);
119 
120     void ValueMapAdd(Inst *inst, llvm::Value *value, bool setName = true);
121     void FillValueMapForUsers(Inst *inst, llvm::Value *value, DataType::Type type,
122                               ArenaUnorderedMap<DataType::Type, llvm::Value *> *typeMap);
123 
AddBlock(BasicBlock * pb,llvm::BasicBlock * lb)124     void AddBlock(BasicBlock *pb, llvm::BasicBlock *lb)
125     {
126         ASSERT(blockTailMap_.count(pb) == 0);
127         blockTailMap_.insert({pb, lb});
128         blockHeadMap_.insert({pb, lb});
129     }
130 
SetCurrentBasicBlock(llvm::BasicBlock * block)131     void SetCurrentBasicBlock(llvm::BasicBlock *block)
132     {
133         builder_.SetInsertPoint(block);
134     }
135 
GetCurrentBasicBlock()136     llvm::BasicBlock *GetCurrentBasicBlock()
137     {
138         return builder_.GetInsertBlock();
139     }
140 
ReplaceTailBlock(BasicBlock * pandaBlock,llvm::BasicBlock * llvmBlock)141     void ReplaceTailBlock(BasicBlock *pandaBlock, llvm::BasicBlock *llvmBlock)
142     {
143         auto it = blockTailMap_.find(pandaBlock);
144         ASSERT(it != blockTailMap_.end());
145         it->second = llvmBlock;
146     }
147 
GetHeadBlock(BasicBlock * block)148     llvm::BasicBlock *GetHeadBlock(BasicBlock *block)
149     {
150         ASSERT(blockHeadMap_.count(block) == 1);
151         auto result = blockHeadMap_.at(block);
152         ASSERT(result != nullptr);
153         return result;
154     }
155 
GetTailBlock(BasicBlock * block)156     llvm::BasicBlock *GetTailBlock(BasicBlock *block)
157     {
158         ASSERT(blockTailMap_.count(block) == 1);
159         auto result = blockTailMap_.at(block);
160         ASSERT(result != nullptr);
161         return result;
162     }
163 
164 protected:
165     // Instruction Visitors
166 
167     static void VisitConstant(GraphVisitor *v, Inst *inst);
168     static void VisitNullPtr(GraphVisitor *v, Inst *inst);
169     static void VisitLiveIn(GraphVisitor *v, Inst *inst);
170     static void VisitParameter(GraphVisitor *v, Inst *inst);
171     static void VisitReturnVoid(GraphVisitor *v, Inst *inst);
172     static void VisitReturn(GraphVisitor *v, Inst *inst);
173     static void VisitLiveOut(GraphVisitor *v, Inst *inst);
174     static void VisitLoad(GraphVisitor *v, Inst *inst);
175     static void VisitStore(GraphVisitor *v, Inst *inst);
176     static void VisitLoadI(GraphVisitor *v, Inst *inst);
177     static void VisitStoreI(GraphVisitor *v, Inst *inst);
178     static void VisitBitcast(GraphVisitor *v, Inst *inst);
179     static void VisitCast(GraphVisitor *v, Inst *inst);
180     static void VisitAnd(GraphVisitor *v, Inst *inst);
181     static void VisitAndI(GraphVisitor *v, Inst *inst);
182     static void VisitOr(GraphVisitor *v, Inst *inst);
183     static void VisitOrI(GraphVisitor *v, Inst *inst);
184     static void VisitXor(GraphVisitor *v, Inst *inst);
185     static void VisitXorI(GraphVisitor *v, Inst *inst);
186     static void VisitShl(GraphVisitor *v, Inst *inst);
187     static void VisitShlI(GraphVisitor *v, Inst *inst);
188     static void VisitShr(GraphVisitor *v, Inst *inst);
189     static void VisitShrI(GraphVisitor *v, Inst *inst);
190     static void VisitAShr(GraphVisitor *v, Inst *inst);
191     static void VisitAShrI(GraphVisitor *v, Inst *inst);
192     static void VisitAdd(GraphVisitor *v, Inst *inst);
193     static void VisitAddI(GraphVisitor *v, Inst *inst);
194     static void VisitSub(GraphVisitor *v, Inst *inst);
195     static void VisitSubI(GraphVisitor *v, Inst *inst);
196     static void VisitMul(GraphVisitor *v, Inst *inst);
197     static void VisitMulI(GraphVisitor *v, Inst *inst);
198     static void VisitDiv(GraphVisitor *v, Inst *inst);
199     static void VisitMod(GraphVisitor *v, Inst *inst);
200     static void VisitCompare(GraphVisitor *v, Inst *inst);
201     static void VisitCmp(GraphVisitor *v, Inst *inst);
202     static void VisitNeg(GraphVisitor *v, Inst *inst);
203     static void VisitNot(GraphVisitor *v, Inst *inst);
204     static void VisitIfImm(GraphVisitor *v, Inst *inst);
205     static void VisitIf(GraphVisitor *v, Inst *inst);
206     static void VisitCallIndirect(GraphVisitor *v, Inst *inst);
207     static void VisitCall(GraphVisitor *v, Inst *inst);
208     static void VisitPhi(GraphVisitor *v, Inst *inst);
209     static void VisitIntrinsic(GraphVisitor *v, Inst *inst);
210 
211     void VisitDefault(Inst *inst) override;
212 
213 public:
214     explicit LLVMIrConstructor(Graph *graph, llvm::Module *module, llvm::LLVMContext *context,
215                                llvmbackend::LLVMArkInterface *arkInterface,
216                                const std::unique_ptr<llvmbackend::DebugDataBuilder> &debugData);
217 
218     bool BuildIr();
219 
220     static Expected<bool, std::string> CanCompile(Graph *graph);
221     static bool CanCompile(Inst *inst);
222 
223 #include "optimizer/ir/visitor.inc"
224 
225 private:
226     Graph *graph_ {nullptr};
227     llvm::Function *func_;
228     llvm::IRBuilder<> builder_;
229     ArenaDoubleUnorderedMap<Inst *, DataType::Type, llvm::Value *> inputMap_;
230     ArenaUnorderedMap<BasicBlock *, llvm::BasicBlock *> blockTailMap_;
231     ArenaUnorderedMap<BasicBlock *, llvm::BasicBlock *> blockHeadMap_;
232     llvmbackend::LLVMArkInterface *arkInterface_;
233     const std::unique_ptr<llvmbackend::DebugDataBuilder> &debugData_;
234     ArenaVector<uint8_t> cc_;
235     ArenaVector<llvm::Value *> ccValues_;
236 };
237 
238 }  // namespace panda::compiler
239 
240 #endif  // LIBLLVMBACKEND_LOWERING_LLVM_IR_CONSTRUCTOR_H
241