GCC Code Coverage Report


Directory: ./
File: src/codegen/llvm/llvm_gen.cpp
Date: 2023-04-27 00:55:30
Exec Total Coverage
Lines: 121 247 49.0%
Functions: 24 91 26.4%
Branches: 113 361 31.3%

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