unlogic
Loading...
Searching...
No Matches
IRGenerator.cpp
Go to the documentation of this file.
1#include "IRGenerator.h"
2#include <format>
3#include <llvm/IR/Verifier.h>
4
6{
7 return llvm::ConstantFP::get(this->ctx.llvm_ctx, llvm::APFloat(node.value));
8}
9
11{
12 return this->builder.CreateGlobalStringPtr(node.value);
13}
14
16{
17 llvm::Value *lhs = std::visit(*this, *node.lhs);
18 llvm::Value *rhs = std::visit(*this, *node.rhs);
19
20 return this->builder.CreateFDiv(lhs, rhs, "divtmp");
21}
22
24{
25 for (auto &statement: node.statements)
26 {
27 std::visit(*this, *statement);
28 }
29
30 return nullptr;
31}
32
34{
35 return *this->ctx.scope.Lookup(node.identifier);
36}
37
39{
40 llvm::Function *function = ctx.module->getFunction(node.function_name);
41
42 if (function->arg_size() < node.arguments.size())
43 {
44 throw std::runtime_error("Aaaaaahhhhhhh");
45 }
46
47 std::vector<llvm::Value *> argument_values;
48 argument_values.reserve(node.arguments.size());
49 for (auto &argument: node.arguments)
50 {
51 llvm::Value *arg_value = std::visit(*this, *argument);
52 argument_values.push_back(arg_value);
53 }
54
55 return this->builder.CreateCall(function, argument_values, "calltmp");
56}
57
59{
60 llvm::Value *lhs = std::visit(*this, *node.lhs);
61 llvm::Value *rhs = std::visit(*this, *node.rhs);
62
63 return this->builder.CreateFAdd(lhs, rhs, "addtmp");
64}
65
67{
68 llvm::Value *lhs = std::visit(*this, *node.lhs);
69 llvm::Value *rhs = std::visit(*this, *node.rhs);
70
71 return this->builder.CreateFSub(lhs, rhs, "subtmp");
72}
73
75{
76 llvm::Value *lhs = std::visit(*this, *node.lhs);
77 llvm::Value *rhs = std::visit(*this, *node.rhs);
78
79 return this->builder.CreateFMul(lhs, rhs, "multmp");
80}
81
83{
84 llvm::Value *lhs = std::visit(*this, *node.lhs);
85 llvm::Value *rhs = std::visit(*this, *node.rhs);
86
87 llvm::Function *std_pow = this->ctx.module->getFunction("pow");
88
89 return this->builder.CreateCall(std_pow, {lhs, rhs}, "powtmp");
90}
91
93{
94 // Save entry
95 llvm::BasicBlock *parent = this->builder.GetInsertBlock();
96
97 // Generate function information
98 std::vector<llvm::Type *> argument_types(node.args.size(), llvm::Type::getDoubleTy(ctx.llvm_ctx));
99 llvm::FunctionType *function_type = llvm::FunctionType::get(llvm::Type::getDoubleTy(ctx.llvm_ctx), argument_types, false);
100 llvm::Function *function = llvm::Function::Create(function_type, llvm::Function::ExternalLinkage, node.name, *ctx.module);
101
102 this->ctx.scope.Insert(node.name, function);
103
104 unsigned idx = 0;
105 for (auto &arg: function->args())
106 {
107 arg.setName(node.args[idx++]);
108 }
109
110 // Generate function body
111 llvm::BasicBlock *block = llvm::BasicBlock::Create(ctx.llvm_ctx, node.name, function);
112 this->builder.SetInsertPoint(block);
113
114 ctx.scope.PushLayer();
115 for (auto &arg: function->args())
116 {
117 ctx.scope.Insert(std::string(arg.getName()), &arg);
118 }
119
120 llvm::Value *return_value = std::visit(*this, *node.body);
121
122 this->builder.CreateRet(return_value);
123
124 ctx.scope.PopLayer();
125
126 if (llvm::verifyFunction(*function, &llvm::errs()))
127 {
128 throw std::runtime_error("function has errors");
129 }
130
131 // Return to parent block
132 this->builder.SetInsertPoint(parent);
133
134 return function;
135}
136
138{
139 llvm::Value *scene = *this->ctx.scope.Lookup("__scene");
140 llvm::Value *name = this->builder.CreateGlobalStringPtr(node.function_name);
141
142 auto function = this->ctx.module->getFunction(node.function_name);
143 if (!function)
144 {
145 throw std::runtime_error(std::format("Function \"{}\" could not be found!", node.function_name));
146 }
147
148 auto scene_add_plot = this->ctx.module->getFunction("unlogic_scene_add_plot");
149
150 std::array<llvm::Value *, 3> args = {scene, name, function};
151
152 return this->builder.CreateCall(scene_add_plot, args);
153}
154
156{
157 std::array<llvm::Type *, 1> args = {
158 llvm::PointerType::getUnqual(this->ctx.llvm_ctx),
159 };
160 llvm::FunctionType *entry_type = llvm::FunctionType::get(llvm::Type::getVoidTy(this->ctx.llvm_ctx), args, false);
161 llvm::Function *entry = llvm::Function::Create(entry_type, llvm::Function::ExternalLinkage, "__entry", *this->ctx.module);
162
163 llvm::BasicBlock *block = llvm::BasicBlock::Create(ctx.llvm_ctx, "__entry", entry);
164
165 this->ctx.scope.PushLayer();
166
167 this->ctx.scope.Insert("__scene", entry->getArg(0));
168
169 this->builder.SetInsertPoint(block);
170
171 std::visit(*this, *node.body);
172
173 this->builder.CreateRetVoid();
174 this->ctx.scope.PopLayer();
175
176 if (llvm::verifyFunction(*entry, &llvm::errs()))
177 {
178 throw std::runtime_error("function has errors");
179 }
180
181 return nullptr;
182}
183
184llvm::Value *unlogic::IRGenerator::operator()(std::monostate &node)
185{
186 throw std::runtime_error("Invalid Node!");
187}
bf::DefineNonTerminal< G, std::unique_ptr< Node > > statement
Definition Parser.cpp:156
LibrarySymbol scene_add_plot(runtime, "unlogic_scene_add_plot",(void *) unlogic_scene_add_plot, [](llvm::LLVMContext &ctx, llvm::Module &mod) { std::array< llvm::Type *, 1 > plot_function_args={ llvm::Type::getDoubleTy(ctx), };llvm::FunctionType *plot_function_type=llvm::FunctionType::get(llvm::Type::getDoubleTy(ctx), plot_function_args, false);std::array< llvm::Type *, 3 > args={ llvm::PointerType::getUnqual(ctx), llvm::PointerType::getUnqual(llvm::Type::getInt8Ty(ctx)), llvm::PointerType::getUnqual(plot_function_type), };llvm::Type *ret=llvm::Type::getVoidTy(ctx);llvm::FunctionType *fn=llvm::FunctionType::get(ret, args, false);llvm::Function::Create(fn, llvm::GlobalValue::ExternalLinkage, "unlogic_scene_add_plot", mod);})
LibrarySymbol std_pow(stdlib, "pow",(void *) unlogic_std_pow, [](llvm::LLVMContext &ctx, llvm::Module &mod) { std::array args={ llvm::Type::getDoubleTy(ctx), llvm::Type::getDoubleTy(ctx), };llvm::Type *ret=llvm::Type::getDoubleTy(ctx);llvm::FunctionType *fn=llvm::FunctionType::get(ret, args, false);llvm::Function::Create(fn, llvm::GlobalValue::ExternalLinkage, "pow", mod);})
UniqueNode rhs
Definition Node.h:72
UniqueNode lhs
Definition Node.h:72
std::vector< UniqueNode > arguments
Definition Node.h:64
std::string function_name
Definition Node.h:63
std::vector< std::string > args
Definition Node.h:111
IRGenerationContext & ctx
Definition IRGenerator.h:13
llvm::Value * operator()(std::monostate &node)
std::string function_name
Definition Node.h:121
std::vector< UniqueNode > statements
Definition Node.h:129
std::string identifier
Definition Node.h:55