Line | Branch | Exec | Source |
---|---|---|---|
1 | #if WITH_LLVM_CODEGEN | ||
2 | |||
3 | // include | ||
4 | # include "codegen/llvm/llvm_gen.h" | ||
5 | |||
6 | // Kiwi | ||
7 | # include "ast/magic.h" | ||
8 | # include "builtin/operators.h" | ||
9 | # include "utilities/guard.h" | ||
10 | # include "utilities/strings.h" | ||
11 | |||
12 | // STL | ||
13 | # include <iostream> | ||
14 | |||
15 | // LLVM | ||
16 | # include "llvm/ADT/STLExtras.h" | ||
17 | # include "llvm/Analysis/BasicAliasAnalysis.h" | ||
18 | # include "llvm/Analysis/Passes.h" | ||
19 | # include "llvm/IR/DIBuilder.h" | ||
20 | # include "llvm/IR/IRBuilder.h" | ||
21 | # include "llvm/IR/Intrinsics.h" | ||
22 | # include "llvm/IR/LLVMContext.h" | ||
23 | # include "llvm/IR/LegacyPassManager.h" | ||
24 | # include "llvm/IR/Module.h" | ||
25 | # include "llvm/IR/Verifier.h" | ||
26 | # include "llvm/Support/Host.h" | ||
27 | # include "llvm/Support/TargetSelect.h" | ||
28 | # include "llvm/Transforms/Scalar.h" | ||
29 | |||
30 | namespace lython { | ||
31 | |||
32 | using StmtRet = LLVMGen::StmtRet; | ||
33 | using ExprRet = LLVMGen::ExprRet; | ||
34 | using ModRet = LLVMGen::ModRet; | ||
35 | using PatRet = LLVMGen::PatRet; | ||
36 | |||
37 | using namespace llvm; | ||
38 | |||
39 | std::string tostr(StringRef const& ref) { return std::string(String(ref).c_str()); } | ||
40 | |||
41 | template <typename T> | ||
42 | std::string llvmstr(T* const obj) { | ||
43 | ✗ | std::string str; | |
44 | ✗ | llvm::raw_string_ostream ss(str); | |
45 | ✗ | obj->print(ss); | |
46 | ✗ | return str; | |
47 | ✗ | } | |
48 | |||
49 | void LLVMGen::dump() const { llmodule->print(llvm::outs(), nullptr); } | ||
50 | |||
51 | LLVMGen::LLVMGen() { | ||
52 |
1/1✓ Branch 1 taken 30 times.
|
30 | InitializeNativeTarget(); |
53 |
1/1✓ Branch 1 taken 30 times.
|
30 | InitializeNativeTargetAsmPrinter(); |
54 |
1/1✓ Branch 1 taken 30 times.
|
30 | InitializeNativeTargetAsmParser(); |
55 | |||
56 |
1/1✓ Branch 1 taken 30 times.
|
30 | context = std::make_unique<LLVMContext>(); |
57 |
1/1✓ Branch 2 taken 30 times.
|
30 | llmodule = std::make_unique<llvm::Module>("KiwiJIT", *context); |
58 |
1/1✓ Branch 2 taken 30 times.
|
30 | builder = std::make_unique<IRBuilder<>>(*context); |
59 | |||
60 | # if WITH_LLVM_DEBUG_SYMBOL | ||
61 | dbuilder = std::make_unique<DIBuilder>(*llmodule); | ||
62 | String sourcefile = "<string>"; | ||
63 | debug_compile_unit = dbuilder->createCompileUnit( | ||
64 | dwarf::DW_LANG_C, dbuilder->createFile(tostr(sourcefile), "."), "Kiwi Compiler", 0, "", 0); | ||
65 | # endif | ||
66 | |||
67 | // TODO put this somewhere | ||
68 | // dbuilder->finalize(); | ||
69 | 30 | } | |
70 | |||
71 | LLVMGen::~LLVMGen() { | ||
72 | // llvm::llvm_shutdown(); | ||
73 | 30 | } | |
74 | |||
75 | # if WITH_LLVM_DEBUG_SYMBOL | ||
76 | void LLVMGen::emit_location(ExprNode* node) { | ||
77 | DIScope* scope; | ||
78 | |||
79 | if (scopes.empty()) | ||
80 | scope = debug_compile_unit; | ||
81 | else | ||
82 | scope = scopes.back(); | ||
83 | |||
84 | builder.SetCurrentDebugLocation( | ||
85 | DILocation::get(scope->getContext(), node->lineno, node->col_offset, scope)); | ||
86 | } | ||
87 | # endif | ||
88 | |||
89 | ExprRet LLVMGen::call(Call_t* n, int depth) { | ||
90 | // Struct construction | ||
91 | // std::vector<llvm::Constant*> values; | ||
92 | // values.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(*context), 42)); | ||
93 | // values.push_back(llvm::ConstantFP::get(llvm::Type::getFloatTy(*context), 3.14)); | ||
94 | // llvm::Constant* myStructInstance = llvm::ConstantStruct::get(struct_type, values); | ||
95 | |||
96 |
1/1✓ Branch 1 taken 1 times.
|
1 | Value* callee = exec(n->func, depth); |
97 |
1/1✓ Branch 1 taken 1 times.
|
1 | Function* function = dyn_cast_or_null<Function>(callee); |
98 | 1 | llvm::FunctionType const* ftype = nullptr; | |
99 | |||
100 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (function == nullptr) { |
101 | kwerror("Function is not callable"); | ||
102 | ✗ | return nullptr; | |
103 | } | ||
104 |
1/1✓ Branch 1 taken 1 times.
|
1 | ftype = function->getFunctionType(); |
105 | |||
106 | 1 | Array<Value*> args; | |
107 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
|
3 | for (size_t i = 0, end = n->args.size(); i != end; ++i) { |
108 |
1/1✓ Branch 2 taken 2 times.
|
2 | ExprRet argvalue = exec(n->args[i], depth); |
109 |
1/1✓ Branch 1 taken 2 times.
|
2 | args.push_back(argvalue); |
110 | |||
111 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (argvalue == nullptr) { |
112 | kwerror("Could not generate function call"); | ||
113 | ✗ | return nullptr; | |
114 | } | ||
115 | } | ||
116 | |||
117 | kwassert(function->arg_size() == args.size(), "Argument should match"); | ||
118 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
|
3 | for (size_t i = 0; i < args.size(); i++) { |
119 | 2 | auto* arg_type = ftype->getParamType(i); | |
120 | 2 | auto* val_type = args[i]->getType(); | |
121 | |||
122 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (arg_type != val_type) { |
123 | kwerror("Type mistmatch expected {} got {}", llvmstr(arg_type), llvmstr(val_type)); | ||
124 | } | ||
125 | } | ||
126 | |||
127 |
3/3✓ Branch 2 taken 1 times.
✓ Branch 6 taken 1 times.
✓ Branch 9 taken 1 times.
|
1 | return builder->CreateCall(function, args, "calltmp"); |
128 | // return builder->CreateCall(callee, args, "calltmp"); | ||
129 | 1 | } | |
130 | |||
131 | using BuiltinBinaryOperators = Dict<String, std::function<Value*(IRBuilder<>*, Value*, Value*)>>; | ||
132 | |||
133 | # define LLMV_OPERATORS(OP) \ | ||
134 | OP(FAdd) \ | ||
135 | OP(FSub) \ | ||
136 | OP(FMul) \ | ||
137 | OP(FCmp) | ||
138 | |||
139 | Value* fadd(IRBuilder<>* builder, Value* left, Value* right) { | ||
140 | ✗ | return builder->CreateFAdd(left, right, "addtmp"); | |
141 | } | ||
142 | Value* fsub(IRBuilder<>* builder, Value* left, Value* right) { | ||
143 | ✗ | return builder->CreateFSub(left, right, "addtmp"); | |
144 | } | ||
145 | Value* fmul(IRBuilder<>* builder, Value* left, Value* right) { | ||
146 | ✗ | return builder->CreateFMul(left, right, "addtmp"); | |
147 | } | ||
148 | |||
149 | // BuiltinBinaryOperators const& builtin_binary_operators() { | ||
150 | // static BuiltinBinaryOperators ops = { | ||
151 | // {String("f+"), fadd}, | ||
152 | // {String("f-"), fsub}, | ||
153 | // {String("f*"), fmul}, | ||
154 | // }; | ||
155 | // return ops; | ||
156 | // } | ||
157 | |||
158 | // Dict<String, std::function<Value*(Value*, Value*)>> operators | ||
159 | |||
160 | ExprRet LLVMGen::binary_operator( | ||
161 | IRBuilder<>* builder, ExprNode* lefths, ExprNode* righths, int opidx, int depth) { | ||
162 | 6 | Value* left = exec(lefths, depth); | |
163 | 6 | Value* right = exec(righths, depth); | |
164 | |||
165 |
2/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
|
6 | if (left == nullptr || right == nullptr) { |
166 | kwerror("Could not generate binary operator"); | ||
167 | ✗ | return nullptr; | |
168 | } | ||
169 | |||
170 |
2/2✓ Branch 1 taken 6 times.
✓ Branch 4 taken 6 times.
|
6 | return builder->CreateFAdd(left, right, "addtmp"); |
171 | } | ||
172 | |||
173 | ExprRet LLVMGen::binop(BinOp_t* n, int depth) { | ||
174 | // Generic case is function call to a kiwi method/function | ||
175 | // | ||
176 | 6 | return binary_operator(builder.get(), n->left, n->right, 0, depth); | |
177 | } | ||
178 | ExprRet LLVMGen::boolop(BoolOp_t* n, int depth) { return ExprRet(); } | ||
179 | ExprRet LLVMGen::unaryop(UnaryOp_t* n, int depth) { return ExprRet(); } | ||
180 | ExprRet LLVMGen::compare(Compare_t* n, int depth) { return ExprRet(); } | ||
181 | |||
182 | ExprRet LLVMGen::namedexpr(NamedExpr_t* n, int depth) { | ||
183 | ✗ | ExprRet target = exec(n->target, depth); | |
184 | ✗ | ExprRet value = exec(n->value, depth); | |
185 | ✗ | return value; | |
186 | } | ||
187 | ExprRet LLVMGen::lambda(Lambda_t* n, int depth) { return ExprRet(); } | ||
188 | ExprRet LLVMGen::ifexp(IfExp_t* n, int depth) { | ||
189 | ✗ | Value* cond = exec(n->test, depth); | |
190 | |||
191 | ✗ | if (cond == nullptr) { | |
192 | ✗ | return nullptr; | |
193 | } | ||
194 | |||
195 | Value* condcmp = | ||
196 | ✗ | builder->CreateFCmpONE(cond, ConstantFP::get(*context, APFloat(0.0)), "ifstmt_cond"); | |
197 | |||
198 | ✗ | Function* fundef = builder->GetInsertBlock()->getParent(); | |
199 | |||
200 | ✗ | BasicBlock* then = BasicBlock::Create(*context, "then", fundef); | |
201 | ✗ | BasicBlock* elxpr = BasicBlock::Create(*context, "else"); | |
202 | ✗ | BasicBlock* merged = BasicBlock::Create(*context, "ifcont"); | |
203 | |||
204 | ✗ | builder->CreateCondBr(condcmp, then, elxpr); | |
205 | |||
206 | // then | ||
207 | ✗ | builder->SetInsertPoint(then); | |
208 | ✗ | Value* then_value = exec(n->body, depth); | |
209 | ✗ | builder->CreateBr(merged); | |
210 | // ---- | ||
211 | |||
212 | ✗ | then = builder->GetInsertBlock(); | |
213 | ✗ | fundef->getBasicBlockList().push_back(elxpr); | |
214 | |||
215 | // orelse | ||
216 | ✗ | builder->SetInsertPoint(elxpr); | |
217 | ✗ | Value* else_value = exec(n->orelse, depth); | |
218 | ✗ | builder->CreateBr(merged); | |
219 | // ----- | ||
220 | |||
221 | ✗ | elxpr = builder->GetInsertBlock(); | |
222 | |||
223 | ✗ | fundef->getBasicBlockList().push_back(merged); | |
224 | ✗ | builder->SetInsertPoint(merged); | |
225 | |||
226 | // Conditional value | ||
227 | ✗ | PHINode* cond_value = builder->CreatePHI(Type::getDoubleTy(*context), 2, "iftmp"); | |
228 | ✗ | cond_value->addIncoming(then_value, then); | |
229 | ✗ | cond_value->addIncoming(else_value, elxpr); | |
230 | ✗ | return cond_value; | |
231 | } | ||
232 | ExprRet LLVMGen::dictexpr(DictExpr_t* n, int depth) { return ExprRet(); } | ||
233 | ExprRet LLVMGen::setexpr(SetExpr_t* n, int depth) { return ExprRet(); } | ||
234 | ExprRet LLVMGen::listcomp(ListComp_t* n, int depth) { return ExprRet(); } | ||
235 | ExprRet LLVMGen::generateexpr(GeneratorExp_t* n, int depth) { return ExprRet(); } | ||
236 | ExprRet LLVMGen::setcomp(SetComp_t* n, int depth) { return ExprRet(); } | ||
237 | ExprRet LLVMGen::dictcomp(DictComp_t* n, int depth) { return ExprRet(); } | ||
238 | ExprRet LLVMGen::await(Await_t* n, int depth) { return ExprRet(); } | ||
239 | ExprRet LLVMGen::yield(Yield_t* n, int depth) { return ExprRet(); } | ||
240 | ExprRet LLVMGen::yieldfrom(YieldFrom_t* n, int depth) { return ExprRet(); } | ||
241 | ExprRet LLVMGen::joinedstr(JoinedStr_t* n, int depth) { return ExprRet(); } | ||
242 | ExprRet LLVMGen::formattedvalue(FormattedValue_t* n, int depth) { return ExprRet(); } | ||
243 | ExprRet LLVMGen::constant(Constant_t* n, int depth) { | ||
244 | |||
245 | 13 | ConstantValue const& val = n->value; | |
246 | using Ty = double; | ||
247 | |||
248 | // clang-format off | ||
249 |
4/12✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 6 times.
✓ Branch 11 taken 3 times.
✓ Branch 12 taken 2 times.
|
13 | switch (n->value.get_kind()) { |
250 | #if 1 | ||
251 | ✗ | case ConstantValue::Ti8: return ConstantFP::get(*context, APFloat((Ty)val.get<int8> ())); | |
252 | ✗ | case ConstantValue::Ti16: return ConstantFP::get(*context, APFloat((Ty)val.get<int16> ())); | |
253 |
2/2✓ Branch 2 taken 2 times.
✓ Branch 6 taken 2 times.
|
2 | case ConstantValue::Ti32: return ConstantFP::get(*context, APFloat((Ty)val.get<int32> ())); |
254 | ✗ | case ConstantValue::Ti64: return ConstantFP::get(*context, APFloat((Ty)val.get<int64> ())); | |
255 | ✗ | case ConstantValue::Tu8: return ConstantFP::get(*context, APFloat((Ty)val.get<uint8> ())); | |
256 | ✗ | case ConstantValue::Tu16: return ConstantFP::get(*context, APFloat((Ty)val.get<uint16> ())); | |
257 | ✗ | case ConstantValue::Tu32: return ConstantFP::get(*context, APFloat((Ty)val.get<uint32> ())); | |
258 | ✗ | case ConstantValue::Tu64: return ConstantFP::get(*context, APFloat((Ty)val.get<uint64> ())); | |
259 | ✗ | case ConstantValue::Tf32: return ConstantFP::get(*context, APFloat((Ty)val.get<float32>())); | |
260 |
2/2✓ Branch 2 taken 6 times.
✓ Branch 6 taken 6 times.
|
6 | case ConstantValue::Tf64: return ConstantFP::get(*context, APFloat((Ty)val.get<float64>())); |
261 |
2/2✓ Branch 2 taken 3 times.
✓ Branch 6 taken 3 times.
|
3 | case ConstantValue::TBool:return ConstantFP::get(*context, APFloat((Ty)val.get<int8> ())); |
262 | #else | ||
263 | case ConstantValue::Ti8: return ConstantInt::get(*context, APInt(8, (int8) val.get<int8> (), true)); | ||
264 | case ConstantValue::Ti16: return ConstantInt::get(*context, APInt(16, (int16) val.get<int16> (), true)); | ||
265 | case ConstantValue::Ti32: return ConstantInt::get(*context, APInt(32, (int32) val.get<int32> (), true)); | ||
266 | case ConstantValue::Ti64: return ConstantInt::get(*context, APInt(64, (int64) val.get<int64> (), true)); | ||
267 | case ConstantValue::Tu8: return ConstantInt::get(*context, APInt(8, (uint8) val.get<uint8> ())); | ||
268 | case ConstantValue::Tu16: return ConstantInt::get(*context, APInt(16, (uint16) val.get<uint16> ())); | ||
269 | case ConstantValue::Tu32: return ConstantInt::get(*context, APInt(32, (uint32) val.get<uint32> ())); | ||
270 | case ConstantValue::Tu64: return ConstantInt::get(*context, APInt(64, (uint64) val.get<uint64> ())); | ||
271 | case ConstantValue::Tf32: return ConstantFP ::get(*context, APFloat( (float32)val.get<float32>())); | ||
272 | case ConstantValue::Tf64: return ConstantFP ::get(*context, APFloat( (float64)val.get<float64>())); | ||
273 | case ConstantValue::TBool:return ConstantInt::get(*context, APInt(8, (int8) val.get<int8> ())); | ||
274 | #endif | ||
275 | } | ||
276 | // clang-format on | ||
277 | |||
278 | // TODO: object are a bit more complex | ||
279 | // llvm::ConstantStruct::get(); | ||
280 | // llvm::ConstantArray | ||
281 | |||
282 | 2 | return nullptr; | |
283 | } | ||
284 | ExprRet LLVMGen::attribute(Attribute_t* n, int depth) { return ExprRet(); } | ||
285 | ExprRet LLVMGen::subscript(Subscript_t* n, int depth) { return ExprRet(); } | ||
286 | ExprRet LLVMGen::starred(Starred_t* n, int depth) { return ExprRet(); } | ||
287 | |||
288 | ExprRet LLVMGen::name(Name_t* n, int depth) { | ||
289 | |||
290 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 17 times.
|
20 | if (n->ctx == ExprContext::Store) |
291 | { | ||
292 | 3 | Function* fundef = builder->GetInsertBlock()->getParent(); | |
293 |
4/4✓ Branch 2 taken 3 times.
✓ Branch 5 taken 3 times.
✓ Branch 8 taken 3 times.
✓ Branch 11 taken 3 times.
|
3 | IRBuilder<> allocabuilder(&fundef->getEntryBlock(), fundef->getEntryBlock().begin()); |
294 |
3/3✓ Branch 1 taken 3 times.
✓ Branch 4 taken 3 times.
✓ Branch 7 taken 3 times.
|
6 | AllocaInst* variable = allocabuilder.CreateAlloca( // |
295 | 3 | Type::getDoubleTy(*context), // | |
296 | nullptr, // | ||
297 |
1/1✓ Branch 1 taken 3 times.
|
6 | tostr(n->id) // |
298 | ); | ||
299 |
1/1✓ Branch 2 taken 3 times.
|
3 | index_to_index[n->id] = named_values.size(); |
300 |
1/1✓ Branch 1 taken 3 times.
|
3 | named_values.push_back(variable); |
301 | 3 | return variable; | |
302 | 3 | } | |
303 | |||
304 |
1/1✓ Branch 1 taken 17 times.
|
17 | auto index = index_to_index[n->id]; |
305 | kwinfo("Size: {} varid: {} index: {}", named_values.size(), n->varid, index); | ||
306 | 17 | Value* value = named_values[index]; | |
307 | |||
308 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
|
17 | if (value == nullptr) { |
309 | ✗ | return nullptr; | |
310 | } | ||
311 | |||
312 | # if WITH_LLVM_DEBUG_SYMBOL | ||
313 | KSDbgInfo.emitLocation(this); | ||
314 | # endif | ||
315 | |||
316 |
4/4✓ Branch 2 taken 17 times.
✓ Branch 5 taken 17 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 16 times.
|
17 | if (!value->getType()->getPointerElementType()->isSized()) { |
317 | 1 | return value; | |
318 | } | ||
319 | |||
320 | // Load the value. | ||
321 | // return builder->CreateLoad(value, tostr(n->id)); | ||
322 |
4/4✓ Branch 2 taken 16 times.
✓ Branch 5 taken 16 times.
✓ Branch 9 taken 16 times.
✓ Branch 12 taken 16 times.
|
16 | return builder->CreateLoad(value->getType()->getPointerElementType(), value, tostr(n->id)); |
323 | } | ||
324 | |||
325 | ExprRet LLVMGen::listexpr(ListExpr_t* n, int depth) { return ExprRet(); } | ||
326 | ExprRet LLVMGen::tupleexpr(TupleExpr_t* n, int depth) { return ExprRet(); } | ||
327 | ExprRet LLVMGen::slice(Slice_t* n, int depth) { return ExprRet(); } | ||
328 | ExprRet LLVMGen::dicttype(DictType_t* n, int depth) { return ExprRet(); } | ||
329 | ExprRet LLVMGen::arraytype(ArrayType_t* n, int depth) { return ExprRet(); } | ||
330 | ExprRet LLVMGen::arrow(Arrow_t* n, int depth) { return ExprRet(); } | ||
331 | ExprRet LLVMGen::builtintype(BuiltinType_t* n, int depth) { return ExprRet(); } | ||
332 | ExprRet LLVMGen::tupletype(TupleType_t* n, int depth) { return ExprRet(); } | ||
333 | ExprRet LLVMGen::settype(SetType_t* n, int depth) { return ExprRet(); } | ||
334 | ExprRet LLVMGen::classtype(ClassType_t* n, int depth) { return ExprRet(); } | ||
335 | ExprRet LLVMGen::comment(Comment_t* n, int depth) { return ExprRet(); } | ||
336 | |||
337 | StmtRet LLVMGen::functiondef(FunctionDef_t* n, int depth) { | ||
338 |
2/2✓ Branch 3 taken 31 times.
✓ Branch 7 taken 31 times.
|
31 | Array<Type*> arg_types(n->args.size(), Type::getDoubleTy(*context)); |
339 |
2/2✓ Branch 2 taken 31 times.
✓ Branch 5 taken 31 times.
|
62 | llvm::FunctionType* arrow = llvm::FunctionType::get( // |
340 | 31 | Type::getDoubleTy(*context), // | |
341 | arg_types, // | ||
342 | false // | ||
343 | ); | ||
344 | |||
345 |
2/2✓ Branch 2 taken 31 times.
✓ Branch 5 taken 31 times.
|
62 | Function* fundef = Function::Create( // |
346 | arrow, // | ||
347 | Function::ExternalLinkage, // | ||
348 |
1/1✓ Branch 1 taken 31 times.
|
62 | tostr(n->name), // |
349 | llmodule.get() // | ||
350 | ); | ||
351 | |||
352 |
1/1✓ Branch 2 taken 31 times.
|
31 | index_to_index[n->name] = named_values.size(); |
353 |
1/1✓ Branch 1 taken 31 times.
|
31 | named_values.push_back(fundef); |
354 | |||
355 |
2/2✓ Branch 1 taken 31 times.
✓ Branch 5 taken 31 times.
|
31 | BasicBlock* block = BasicBlock::Create(*context, "entry", fundef); |
356 |
1/1✓ Branch 2 taken 31 times.
|
31 | builder->SetInsertPoint(block); |
357 | |||
358 | # if WITH_LLVM_DEBUG_SYMBOL | ||
359 | DIFile* unit = | ||
360 | dbuilder->createFile(debug_compile_unit->getFilename(), debug_compile_unit->getDirectory()); | ||
361 | DIScope* debug_ctx = unit; | ||
362 | DISubprogram* debug_info = dbuilder->createFunction( // | ||
363 | debug_ctx, // | ||
364 | tostr(n->name), // | ||
365 | llvm::StringRef(), // | ||
366 | unit, // | ||
367 | n->lineno, // | ||
368 | CreateFunctionType(fundef->arg_size(), unit), // | ||
369 | false, // internal linkage | ||
370 | true, // definition | ||
371 | 0, // | ||
372 | DINode::FlagPrototyped, // | ||
373 | false // | ||
374 | ); | ||
375 | fundef->setSubprogram(debug_info); | ||
376 | # endif | ||
377 | |||
378 | 31 | unsigned i = 0; | |
379 | 31 | ArrayScope<llvm::Value*> scope(named_values); | |
380 | |||
381 |
3/3✓ Branch 1 taken 31 times.
✓ Branch 5 taken 28 times.
✓ Branch 6 taken 31 times.
|
59 | for (auto& arg: fundef->args()) { |
382 |
1/1✓ Branch 2 taken 28 times.
|
28 | Identifier argname_ref = n->args.args[i].arg; |
383 |
1/1✓ Branch 1 taken 28 times.
|
28 | std::string argname = tostr(argname_ref); |
384 |
2/2✓ Branch 1 taken 28 times.
✓ Branch 4 taken 28 times.
|
28 | arg.setName(argname); |
385 | |||
386 |
4/4✓ Branch 2 taken 28 times.
✓ Branch 5 taken 28 times.
✓ Branch 8 taken 28 times.
✓ Branch 11 taken 28 times.
|
28 | IRBuilder<> allocabuilder(&fundef->getEntryBlock(), fundef->getEntryBlock().begin()); |
387 |
3/3✓ Branch 1 taken 28 times.
✓ Branch 4 taken 28 times.
✓ Branch 7 taken 28 times.
|
56 | AllocaInst* arg_mem = allocabuilder.CreateAlloca( // |
388 | 28 | Type::getDoubleTy(*context), // | |
389 | nullptr, // | ||
390 |
1/1✓ Branch 1 taken 28 times.
|
28 | arg.getName() // |
391 | ); | ||
392 |
1/1✓ Branch 2 taken 28 times.
|
28 | index_to_index[argname_ref] = named_values.size(); |
393 |
1/1✓ Branch 1 taken 28 times.
|
28 | named_values.push_back(arg_mem); |
394 | |||
395 | // CreateEntryBlockAlloca(fundef, arg.getName()); | ||
396 | |||
397 | # if WITH_LLVM_DEBUG_SYMBOL | ||
398 | DILocalVariable* vard = dbuilder->createParameterVariable( | ||
399 | SP, arg.getName(), ++ArgIdx, Unit, LineNo, KSDbgInfo.getDoubleTy(), true); | ||
400 | |||
401 | dbuilder->insertDeclare(Alloca, | ||
402 | D, | ||
403 | dbuilder->createExpression(), | ||
404 | DILocation::get(SP->getContext(), LineNo, 0, SP), | ||
405 | Builder.GetInsertBlock()); | ||
406 | # endif | ||
407 | |||
408 | // Store the initial value into the alloca. | ||
409 |
1/1✓ Branch 2 taken 28 times.
|
28 | builder->CreateStore(&arg, arg_mem); |
410 | //*/ | ||
411 | |||
412 | 28 | i += 1; | |
413 | 28 | } | |
414 | |||
415 |
2/2✓ Branch 5 taken 34 times.
✓ Branch 6 taken 31 times.
|
65 | for (auto* stmt: n->body) { |
416 |
1/1✓ Branch 1 taken 34 times.
|
34 | exec(stmt, depth); |
417 | } | ||
418 | |||
419 |
1/1✓ Branch 1 taken 31 times.
|
31 | verifyFunction(*fundef); |
420 | |||
421 | 62 | return StmtRet(); | |
422 | 31 | } | |
423 | |||
424 | llvm::Type* LLVMGen::builtin_type(StringRef name) { | ||
425 | static Dict<StringRef, llvm::Type*> builtin_types = { | ||
426 | ✗ | {StringRef("i8"), IntegerType::get(*context, 8)}, | |
427 | ✗ | {StringRef("i16"), IntegerType::get(*context, 16)}, | |
428 | ✗ | {StringRef("i32"), IntegerType::get(*context, 32)}, | |
429 | ✗ | {StringRef("i64"), IntegerType::get(*context, 64)}, | |
430 | |||
431 | ✗ | {StringRef("u8"), IntegerType::get(*context, 8)}, | |
432 | ✗ | {StringRef("u16"), IntegerType::get(*context, 16)}, | |
433 | ✗ | {StringRef("u32"), IntegerType::get(*context, 32)}, | |
434 | ✗ | {StringRef("u64"), IntegerType::get(*context, 64)}, | |
435 | |||
436 | ✗ | {StringRef("f32"), Type::getFloatTy(*context)}, | |
437 | ✗ | {StringRef("f64"), Type::getDoubleTy(*context)}, | |
438 | ✗ | }; | |
439 | ✗ | return builtin_types[name]; | |
440 | ✗ | } | |
441 | |||
442 | llvm::Type* LLVMGen::retrieve_type(ExprNode* type, int depth) { | ||
443 | kwinfo("{}", str(type)); | ||
444 | |||
445 | ✗ | switch (type->kind) { | |
446 | ✗ | case NodeKind::BuiltinType: return builtin_type(cast<BuiltinType>(type)->name); | |
447 | ✗ | case NodeKind::Name: return builtin_type(cast<Name>(type)->id); | |
448 | } | ||
449 | ✗ | return nullptr; | |
450 | } | ||
451 | |||
452 | StmtRet LLVMGen::classdef(ClassDef_t* n, int depth) { | ||
453 | // Create the type definition | ||
454 | ✗ | Array<llvm::Type*> fields; | |
455 | ✗ | llvm::Type* int_type = llvm::Type::getInt32Ty(*context); | |
456 | |||
457 | ✗ | for (ClassDef::Attr const& attr: n->attributes) { | |
458 | ✗ | llvm::Type* field_type = retrieve_type(attr.type, depth); | |
459 | ✗ | if (field_type == nullptr) { | |
460 | kwerror("Could not find type for {}", str(attr.type)); | ||
461 | } | ||
462 | ✗ | fields.push_back(field_type); | |
463 | } | ||
464 | |||
465 | ✗ | StructType* clstype = llvm::StructType::create(*context, fields, tostr(n->name)); | |
466 | ✗ | llmodule->getOrInsertGlobal(tostr(n->name), clstype); | |
467 | |||
468 | // index_to_index[n->name] = named_values.size(); | ||
469 | // named_values.push_back(clstype); | ||
470 | |||
471 | // TODO: | ||
472 | // Runtime Reflection | ||
473 | // Create Type Instance used for runtime reflextion | ||
474 | |||
475 | ✗ | return StmtRet(); | |
476 | ✗ | } | |
477 | StmtRet LLVMGen::invalidstmt(InvalidStatement_t* n, int depth) { return StmtRet(); } | ||
478 | StmtRet LLVMGen::returnstmt(Return_t* n, int depth) { | ||
479 | |||
480 |
1/2✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
|
26 | if (n->value.has_value()) { |
481 | 26 | Value* retvalue = exec(n->value.value(), depth); | |
482 | 26 | builder->CreateRet(retvalue); | |
483 | 26 | return; | |
484 | } | ||
485 | |||
486 | ✗ | return StmtRet(); | |
487 | } | ||
488 | StmtRet LLVMGen::deletestmt(Delete_t* n, int depth) { | ||
489 | // Function call | ||
490 | ✗ | return StmtRet(); | |
491 | } | ||
492 | |||
493 | StmtRet LLVMGen::assign(Assign_t* n, int depth) { | ||
494 | |||
495 | // Unpacking ? | ||
496 | // create the variable | ||
497 | 2 | Value* variable = exec(n->targets[0], depth); | |
498 | |||
499 | // Get the value | ||
500 | 2 | Value* val = exec(n->value, depth); | |
501 | |||
502 | // Store the result | ||
503 | 2 | builder->CreateStore(val, variable); | |
504 | 2 | return StmtRet(); | |
505 | } | ||
506 | |||
507 | StmtRet LLVMGen::augassign(AugAssign_t* n, int depth) { | ||
508 | ✗ | Value* variable = exec(n->target, depth); | |
509 | ✗ | Value* val = exec(n->value, depth); | |
510 | |||
511 | // Call the binary oerator here | ||
512 | |||
513 | ✗ | builder->CreateStore(val, variable); | |
514 | ✗ | return StmtRet(); | |
515 | } | ||
516 | StmtRet LLVMGen::annassign(AnnAssign_t* n, int depth) { | ||
517 | 1 | Value* variable = exec(n->target, depth); | |
518 | |||
519 | 1 | Value* val = nullptr; | |
520 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | if (n->value.has_value()) { |
521 | 1 | val = exec(n->value.value(), depth); | |
522 | } | ||
523 | |||
524 | 1 | builder->CreateStore(val, variable); | |
525 | 1 | return StmtRet(); | |
526 | } | ||
527 | |||
528 | StmtRet LLVMGen::forstmt(For_t* n, int depth) { | ||
529 | ✗ | Function* fundef = builder->GetInsertBlock()->getParent(); | |
530 | |||
531 | ✗ | BasicBlock* preheader = builder->GetInsertBlock(); | |
532 | ✗ | BasicBlock* body = BasicBlock::Create(*context, "loop", fundef); | |
533 | ✗ | BasicBlock* orelse = BasicBlock::Create(*context, "orelse", fundef); | |
534 | ✗ | BasicBlock* after = BasicBlock::Create(*context, "after", fundef); | |
535 | |||
536 | ✗ | start_block = body; | |
537 | ✗ | end_block = after; | |
538 | |||
539 | ✗ | builder->CreateBr(body); | |
540 | ✗ | builder->SetInsertPoint(body); | |
541 | |||
542 | // Initialization | ||
543 | // exec(n->target, depth); | ||
544 | // PHINode *var = builder->CreatePHI(Type::getDoubleTy(*context), 2, VarName); | ||
545 | // var->addIncoming(StartVal, preheader); | ||
546 | |||
547 | ✗ | for (auto* stmt: n->body) { | |
548 | ✗ | exec(stmt, depth); | |
549 | } | ||
550 | |||
551 | // Step val | ||
552 | // | ||
553 | // | ||
554 | |||
555 | // Comparison | ||
556 | // EndCond = builder->CreateFCmpONE(EndCond, ConstantFP::get(*context, APFloat(0.0)), | ||
557 | // "loopcond"); | ||
558 | ✗ | BasicBlock* loop_end = builder->GetInsertBlock(); | |
559 | |||
560 | // builder->CreateCondBr(EndCond, loop_end, after); | ||
561 | |||
562 | // var->addIncoming(NextVar, loop_end); | ||
563 | |||
564 | ✗ | builder->SetInsertPoint(orelse); | |
565 | ✗ | for (auto* stmt: n->orelse) { | |
566 | ✗ | exec(stmt, depth); | |
567 | } | ||
568 | |||
569 | // builder->CreateCondBr(EndCond, body, after); | ||
570 | ✗ | builder->SetInsertPoint(after); | |
571 | |||
572 | ✗ | start_block = nullptr; | |
573 | ✗ | end_block = nullptr; | |
574 | ✗ | return StmtRet(); | |
575 | } | ||
576 | StmtRet LLVMGen::whilestmt(While_t* n, int depth) { | ||
577 | // | ||
578 | |||
579 | // | ||
580 | ✗ | return StmtRet(); | |
581 | } | ||
582 | |||
583 | StmtRet LLVMGen::ifstmt(If_t* n, int depth) { | ||
584 | 1 | Value* cond = exec(n->test, depth); | |
585 | |||
586 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (cond == nullptr) { |
587 | ✗ | return StmtRet(); | |
588 | } | ||
589 | |||
590 | Value* condcmp = | ||
591 |
4/4✓ Branch 2 taken 1 times.
✓ Branch 5 taken 1 times.
✓ Branch 9 taken 1 times.
✓ Branch 12 taken 1 times.
|
1 | builder->CreateFCmpONE(cond, ConstantFP::get(*context, APFloat(0.0)), "ifstmt_cond"); |
592 | |||
593 | 1 | Function* fundef = builder->GetInsertBlock()->getParent(); | |
594 | |||
595 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 5 taken 1 times.
|
1 | BasicBlock* then = BasicBlock::Create(*context, "then", fundef); |
596 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 5 taken 1 times.
|
1 | BasicBlock* elxpr = BasicBlock::Create(*context, "else"); |
597 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 5 taken 1 times.
|
1 | BasicBlock* merged = BasicBlock::Create(*context, "ifcont"); |
598 | |||
599 | 1 | builder->CreateCondBr(condcmp, then, elxpr); | |
600 | |||
601 | // then | ||
602 | 1 | builder->SetInsertPoint(then); | |
603 |
2/2✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
|
2 | for (auto* stmt: n->body) { |
604 |
1/1✓ Branch 1 taken 1 times.
|
1 | exec(stmt, depth); |
605 | } | ||
606 | 1 | builder->CreateBr(merged); | |
607 | // ---- | ||
608 | |||
609 | 1 | then = builder->GetInsertBlock(); | |
610 | 1 | fundef->getBasicBlockList().push_back(elxpr); | |
611 | |||
612 | // orelse | ||
613 | 1 | builder->SetInsertPoint(elxpr); | |
614 |
2/2✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
|
2 | for (auto* stmt: n->orelse) { |
615 |
1/1✓ Branch 1 taken 1 times.
|
1 | exec(stmt, depth); |
616 | } | ||
617 | 1 | builder->CreateBr(merged); | |
618 | // ----- | ||
619 | |||
620 | 1 | elxpr = builder->GetInsertBlock(); | |
621 | |||
622 | 1 | fundef->getBasicBlockList().push_back(merged); | |
623 | 1 | builder->SetInsertPoint(merged); | |
624 | |||
625 | 1 | return StmtRet(); | |
626 | } | ||
627 | StmtRet LLVMGen::with(With_t* n, int depth) { return StmtRet(); } | ||
628 | StmtRet LLVMGen::raise(Raise_t* n, int depth) { | ||
629 | ✗ | Function* fundef = builder->GetInsertBlock()->getParent(); | |
630 | |||
631 | ✗ | Function* raisefun = nullptr; | |
632 | // Function* raisefun = Intrinsic::getDeclaration(fundef->getParent(), Intrinsic::eh_throw); | ||
633 | ✗ | Value* exception = nullptr; | |
634 | ✗ | CallInst* raise = builder->CreateCall(raisefun, {exception}); | |
635 | ✗ | raise->setDoesNotReturn(); | |
636 | ✗ | builder->GetInsertBlock()->getInstList().push_back(raise); | |
637 | |||
638 | ✗ | return StmtRet(); | |
639 | } | ||
640 | StmtRet LLVMGen::trystmt(Try_t* n, int depth) { | ||
641 | |||
642 | // Body | ||
643 | |||
644 | ✗ | BasicBlock* body = BasicBlock::Create(*context, "body"); | |
645 | ✗ | BasicBlock* handlers = BasicBlock::Create(*context, "catch"); | |
646 | ✗ | BasicBlock* orelse = BasicBlock::Create(*context, "orelse"); | |
647 | ✗ | BasicBlock* finalbody = BasicBlock::Create(*context, "finalbody"); | |
648 | |||
649 | // Landing Pad for exception handling | ||
650 | ✗ | Type* Int8PtrTy = PointerType::getUnqual(Type::getInt8Ty(*context)); | |
651 | // Constant* NullPtr = ConstantPointerNull::get(Int8PtrTy); | ||
652 | |||
653 | ✗ | LandingPadInst* LPInst = LandingPadInst::Create(Int8PtrTy, 1, "landingpad", handlers); | |
654 | // LPInst->addClause(NullPtr); | ||
655 | |||
656 | // InvokeInst* InvokeInst = InvokeInst::Create(Func, NormalBB, CatchBB, Args, "invoke", | ||
657 | // EntryBB); | ||
658 | |||
659 | ✗ | return StmtRet(); | |
660 | } | ||
661 | StmtRet LLVMGen::assertstmt(Assert_t* n, int depth) { return StmtRet(); } | ||
662 | StmtRet LLVMGen::global(Global_t* n, int depth) { return StmtRet(); } | ||
663 | StmtRet LLVMGen::nonlocal(Nonlocal_t* n, int depth) { return StmtRet(); } | ||
664 | |||
665 | StmtRet LLVMGen::exprstmt(Expr_t* n, int depth) { | ||
666 | 3 | exec(n->value, depth); | |
667 | 3 | return StmtRet(); | |
668 | } | ||
669 | |||
670 | StmtRet LLVMGen::pass(Pass_t* n, int depth) { return StmtRet(); } | ||
671 | StmtRet LLVMGen::breakstmt(Break_t* n, int depth) { | ||
672 | ✗ | BasicBlock* current_block = builder->GetInsertBlock(); | |
673 | ✗ | BranchInst* breakbr = llvm::BranchInst::Create(end_block, current_block); | |
674 | ✗ | current_block->getInstList().push_back(breakbr); | |
675 | ✗ | return StmtRet(); | |
676 | } | ||
677 | |||
678 | StmtRet LLVMGen::continuestmt(Continue_t* n, int depth) { | ||
679 | ✗ | BasicBlock* current_block = builder->GetInsertBlock(); | |
680 | ✗ | BranchInst* continuebr = llvm::BranchInst::Create(start_block, current_block); | |
681 | ✗ | current_block->getInstList().push_back(continuebr); | |
682 | ✗ | return StmtRet(); | |
683 | } | ||
684 | |||
685 | StmtRet LLVMGen::match(Match_t* n, int depth) { return StmtRet(); } | ||
686 | StmtRet LLVMGen::inlinestmt(Inline_t* n, int depth) { | ||
687 | ✗ | for (auto* stmt: n->body) { | |
688 | ✗ | exec(stmt, depth); | |
689 | } | ||
690 | ✗ | return StmtRet(); | |
691 | } | ||
692 | StmtRet LLVMGen::import(Import_t* n, int depth) { return StmtRet(); } | ||
693 | StmtRet LLVMGen::importfrom(ImportFrom_t* n, int depth) { return StmtRet(); } | ||
694 | |||
695 | PatRet LLVMGen::matchvalue(MatchValue_t* n, int depth) { return PatRet(); } | ||
696 | PatRet LLVMGen::matchsingleton(MatchSingleton_t* n, int depth) { return PatRet(); } | ||
697 | PatRet LLVMGen::matchsequence(MatchSequence_t* n, int depth) { return PatRet(); } | ||
698 | PatRet LLVMGen::matchmapping(MatchMapping_t* n, int depth) { return PatRet(); } | ||
699 | PatRet LLVMGen::matchclass(MatchClass_t* n, int depth) { return PatRet(); } | ||
700 | PatRet LLVMGen::matchstar(MatchStar_t* n, int depth) { return PatRet(); } | ||
701 | PatRet LLVMGen::matchas(MatchAs_t* n, int depth) { return PatRet(); } | ||
702 | PatRet LLVMGen::matchor(MatchOr_t* n, int depth) { return PatRet(); } | ||
703 | |||
704 | ModRet LLVMGen::module(Module_t* stmt, int depth) { | ||
705 |
2/2✓ Branch 5 taken 31 times.
✓ Branch 6 taken 30 times.
|
61 | for (auto* stmt: stmt->body) { |
706 |
1/1✓ Branch 1 taken 31 times.
|
31 | exec(stmt, depth); |
707 | } | ||
708 | 30 | return ModRet(); | |
709 | }; | ||
710 | ModRet LLVMGen::interactive(Interactive_t* n, int depth) { return ModRet(); } | ||
711 | ModRet LLVMGen::functiontype(FunctionType_t* n, int depth) { return ModRet(); } | ||
712 | ModRet LLVMGen::expression(Expression_t* n, int depth) {} | ||
713 | |||
714 | } // namespace lython | ||
715 | |||
716 | #endif | ||
717 |