| 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 |