10 #include <llvm/AsmParser/Parser.h> 11 #include <llvm/IR/DebugInfo.h> 12 #include <llvm/IR/IRBuilder.h> 13 #include <llvm/IR/Module.h> 14 #include <llvm/Support/SourceMgr.h> 16 #if LLVM_VERSION_LESS_EQUAL(3, 6) 17 #include <llvm/IR/DIBuilder.h> 24 struct IfNodeType : NodeType {
25 IfNodeType(LangModule& mod) : NodeType(mod,
"if",
"If") {
27 setExecOutputs({
"True",
"False"});
29 setDataInputs({{
"condition", mod.typeFromName(
"i1")}});
32 Result codegen(NodeCompiler& compiler, llvm::BasicBlock& codegenInto,
size_t execInputID,
33 const llvm::DebugLoc& nodeLocation,
const std::vector<llvm::Value*>& io,
34 const std::vector<llvm::BasicBlock*>& outputBlocks)
override {
35 assert(io.size() == 1 && outputBlocks.size() == 2);
37 llvm::IRBuilder<> builder(&codegenInto);
38 builder.SetCurrentDebugLocation(nodeLocation);
40 builder.CreateCondBr(io[0], outputBlocks[0], outputBlocks[1]);
45 std::unique_ptr<NodeType> clone()
const override {
return std::make_unique<IfNodeType>(*this); }
48 struct EntryNodeType : NodeType {
49 EntryNodeType(LangModule& mod, std::vector<NamedDataType> dataInputs,
50 std::vector<std::string> execInputs)
51 : NodeType(mod,
"entry",
"Entry") {
52 setExecOutputs(std::move(execInputs));
54 setDataOutputs(std::move(dataInputs));
57 Result codegen(NodeCompiler& compiler, llvm::BasicBlock& codegenInto,
size_t execInputID,
58 const llvm::DebugLoc& nodeLocation,
const std::vector<llvm::Value*>& io,
59 const std::vector<llvm::BasicBlock*>& outputBlocks)
override {
60 assert(io.size() == dataOutputs().size() && outputBlocks.size() == execOutputs().size());
62 llvm::IRBuilder<> builder(&codegenInto);
63 builder.SetCurrentDebugLocation(nodeLocation);
66 auto arg_iter = codegenInto.getParent()->arg_begin();
68 for (
const auto& iovalue : io) {
69 builder.CreateStore(&*arg_iter, iovalue);
74 auto inExecID = &*codegenInto.getParent()->arg_begin();
75 auto switchInst = builder.CreateSwitch(inExecID, outputBlocks[0], execOutputs().size());
77 for (
auto id = 0ull;
id < execOutputs().size(); ++id) {
78 switchInst->addCase(builder.getInt32(
id), outputBlocks[id]);
83 std::unique_ptr<NodeType> clone()
const override {
84 return std::make_unique<EntryNodeType>(*this);
87 nlohmann::json toJSON()
const override {
88 nlohmann::json ret = nlohmann::json::object();
90 auto& data = ret[
"data"];
91 data = nlohmann::json::array();
92 for (
auto& pair : dataOutputs()) {
93 data.push_back({{pair.name, pair.type.qualifiedName()}});
96 auto& exec = ret[
"exec"];
97 exec = nlohmann::json::array();
98 for (
auto& name : execOutputs()) { exec.push_back(name); }
104 struct ConstIntNodeType : NodeType {
105 ConstIntNodeType(LangModule& mod,
int num)
106 : NodeType(mod,
"const-int",
"Integer"), number(num) {
109 setDataOutputs({{
"", mod.typeFromName(
"i32")}});
112 Result codegen(NodeCompiler& compiler, llvm::BasicBlock& codegenInto,
size_t execInputID,
113 const llvm::DebugLoc& nodeLocation,
const std::vector<llvm::Value*>& io,
114 const std::vector<llvm::BasicBlock*>& outputBlocks)
override {
115 assert(io.size() == 1 && outputBlocks.size() == 1);
117 llvm::IRBuilder<> builder(&codegenInto);
118 builder.SetCurrentDebugLocation(nodeLocation);
120 builder.CreateStore(builder.getInt32(number), io[0],
false);
121 builder.CreateBr(outputBlocks[0]);
126 std::unique_ptr<NodeType> clone()
const override {
127 return std::make_unique<ConstIntNodeType>(*this);
130 nlohmann::json toJSON()
const override {
return number; }
134 struct ConstFloatNodeType : NodeType {
135 ConstFloatNodeType(LangModule& mod,
double num)
136 : NodeType(mod,
"const-float",
"Float"), number(num) {
139 setDataOutputs({{
"", mod.typeFromName(
"float")}});
142 Result codegen(NodeCompiler& compiler, llvm::BasicBlock& codegenInto,
size_t execInputID,
143 const llvm::DebugLoc& nodeLocation,
const std::vector<llvm::Value*>& io,
144 const std::vector<llvm::BasicBlock*>& outputBlocks)
override {
145 assert(io.size() == 1 && outputBlocks.size() == 1);
147 llvm::IRBuilder<> builder(&codegenInto);
148 builder.SetCurrentDebugLocation(nodeLocation);
150 builder.CreateStore(llvm::ConstantFP::get(builder.getFloatTy(), number), io[0]);
151 builder.CreateBr(outputBlocks[0]);
156 std::unique_ptr<NodeType> clone()
const override {
157 return std::make_unique<ConstFloatNodeType>(*this);
160 nlohmann::json toJSON()
const override {
return number; }
164 struct ConstBoolNodeType : NodeType {
165 ConstBoolNodeType(LangModule& mod,
bool num)
166 : NodeType{mod,
"const-bool",
"Boolean literal"}, value{num} {
169 setDataOutputs({{
"", mod.typeFromName(
"i1")}});
172 Result codegen(NodeCompiler& compiler, llvm::BasicBlock& codegenInto,
size_t execInputID,
173 const llvm::DebugLoc& nodeLocation,
const std::vector<llvm::Value*>& io,
174 const std::vector<llvm::BasicBlock*>& outputBlocks)
override {
175 assert(io.size() == 1 && outputBlocks.size() == 1);
177 llvm::IRBuilder<> builder(&codegenInto);
178 builder.SetCurrentDebugLocation(nodeLocation);
180 builder.CreateStore(builder.getInt1(value), io[0],
false);
181 builder.CreateBr(outputBlocks[0]);
186 std::unique_ptr<NodeType> clone()
const override {
187 return std::make_unique<ConstBoolNodeType>(*this);
190 nlohmann::json toJSON()
const override {
return value; }
194 struct ExitNodeType : NodeType {
195 ExitNodeType(LangModule& mod, std::vector<NamedDataType> dataOutputs,
196 std::vector<std::string> execOutputs)
197 : NodeType{mod,
"exit",
"Return from a function"} {
199 setExecInputs(std::move(execOutputs));
201 setDataInputs(std::move(dataOutputs));
204 Result codegen(NodeCompiler& compiler, llvm::BasicBlock& codegenInto,
size_t execInputID,
205 const llvm::DebugLoc& nodeLocation,
const std::vector<llvm::Value*>& io,
206 const std::vector<llvm::BasicBlock*>& outputBlocks)
override {
207 assert(execInputID < execInputs().size() && io.size() == dataInputs().size());
210 llvm::IRBuilder<> builder(&codegenInto);
211 builder.SetCurrentDebugLocation(nodeLocation);
213 llvm::Function* f = codegenInto.getParent();
215 f->arg_size() - io.size();
216 auto arg_iter = f->arg_begin();
217 std::advance(arg_iter, ret_start);
218 for (
auto& value : io) {
219 builder.CreateStore(value, &*arg_iter,
false);
223 builder.CreateRet(builder.getInt32(execInputID));
228 std::unique_ptr<NodeType> clone()
const override {
229 return std::make_unique<ExitNodeType>(*this);
232 nlohmann::json toJSON()
const override {
233 nlohmann::json ret = nlohmann::json::object();
235 auto& data = ret[
"data"];
236 data = nlohmann::json::array();
237 for (
auto& pair : dataInputs()) {
238 data.push_back({{pair.name, pair.type.qualifiedName()}});
241 auto& exec = ret[
"exec"];
242 exec = nlohmann::json::array();
243 for (
auto& name : execInputs()) { exec.push_back(name); }
249 struct StringLiteralNodeType : NodeType {
250 StringLiteralNodeType(LangModule& mod, std::string str)
251 : NodeType(mod,
"strliteral",
"String"), literalString(
std::move(str)) {
254 setDataOutputs({{
"", mod.typeFromName(
"i8*")}});
257 Result codegen(NodeCompiler& compiler, llvm::BasicBlock& codegenInto,
size_t execInputID,
258 const llvm::DebugLoc& nodeLocation,
const std::vector<llvm::Value*>& io,
259 const std::vector<llvm::BasicBlock*>& outputBlocks)
override {
260 assert(io.size() == 1 && outputBlocks.size() == 1);
262 llvm::IRBuilder<> builder(&codegenInto);
263 builder.SetCurrentDebugLocation(nodeLocation);
265 auto global = builder.CreateGlobalString(literalString);
267 auto const0ID = llvm::ConstantInt::get(context().llvmContext(), llvm::APInt(32, 0,
false));
268 auto gep = builder.CreateGEP(global,
270 #
if LLVM_VERSION_LESS_EQUAL(3, 6)
271 std::vector<llvm::Value*> {
272 { const0ID, const0ID }
275 { const0ID, const0ID }
278 builder.CreateStore(gep, io[0],
false);
280 builder.CreateBr(outputBlocks[0]);
285 std::unique_ptr<NodeType> clone()
const override {
286 return std::make_unique<StringLiteralNodeType>(*this);
289 nlohmann::json toJSON()
const override {
return literalString; }
290 std::string literalString;
293 struct IntToFloatNodeType : NodeType {
294 IntToFloatNodeType(LangModule& mod) : NodeType(mod,
"inttofloat",
"Float -> Integer") {
297 setDataInputs({{
"", mod.typeFromName(
"i32")}});
298 setDataOutputs({{
"", mod.typeFromName(
"float")}});
303 Result codegen(NodeCompiler& , llvm::BasicBlock& codegenInto,
304 size_t ,
const llvm::DebugLoc& nodeLocation,
305 const std::vector<llvm::Value*>& io,
306 const std::vector<llvm::BasicBlock*>& outputBlocks)
override {
307 assert(io.size() == 2 && outputBlocks.size() == 1);
309 llvm::IRBuilder<> builder(&codegenInto);
310 builder.SetCurrentDebugLocation(nodeLocation);
313 builder.CreateCast(llvm::Instruction::CastOps::SIToFP, io[0], builder.getFloatTy());
314 builder.CreateStore(casted, io[1]);
316 builder.CreateBr(outputBlocks[0]);
321 std::unique_ptr<NodeType> clone()
const override {
322 return std::make_unique<IntToFloatNodeType>(*this);
326 struct FloatToIntNodeType : NodeType {
327 FloatToIntNodeType(LangModule& mod) : NodeType(mod,
"floattoint",
"Float -> Integer") {
330 setDataInputs({{
"", mod.typeFromName(
"float")}});
331 setDataOutputs({{
"", mod.typeFromName(
"i32")}});
336 Result codegen(NodeCompiler& compiler, llvm::BasicBlock& codegenInto,
size_t execInputID,
337 const llvm::DebugLoc& nodeLocation,
const std::vector<llvm::Value*>& io,
338 const std::vector<llvm::BasicBlock*>& outputBlocks)
override {
339 assert(io.size() == 2 && outputBlocks.size() == 1);
341 llvm::IRBuilder<> builder(&codegenInto);
342 builder.SetCurrentDebugLocation(nodeLocation);
345 builder.CreateCast(llvm::Instruction::CastOps::FPToSI, io[0], builder.getInt32Ty());
346 builder.CreateStore(casted, io[1]);
348 builder.CreateBr(outputBlocks[0]);
353 std::unique_ptr<NodeType> clone()
const override {
354 return std::make_unique<FloatToIntNodeType>(*this);
359 enum class BinOp { Add, Subtract, Multiply, Divide };
361 struct BinaryOperationNodeType : NodeType {
362 BinaryOperationNodeType(LangModule& mod, DataType ty, BinOp binaryOperation)
363 : NodeType(mod), mBinOp(binaryOperation), mType{ty} {
366 std::string opStr = [](BinOp b) {
368 case BinOp::Add:
return "+";
369 case BinOp::Subtract:
return "-";
370 case BinOp::Multiply:
return "*";
371 case BinOp::Divide:
return "/";
377 setName(ty.unqualifiedName() + opStr + ty.unqualifiedName());
379 std::string opVerb = [](BinOp b) {
381 case BinOp::Add:
return "Add";
382 case BinOp::Subtract:
return "Subtract";
383 case BinOp::Multiply:
return "Multiply";
384 case BinOp::Divide:
return "Divide";
390 setDescription(opVerb +
" two " + ty.unqualifiedName() +
"s");
392 setDataInputs({{
"a", ty}, {
"b", ty}});
393 setDataOutputs({{
"", ty}});
396 Result codegen(NodeCompiler& , llvm::BasicBlock& codegenInto,
397 size_t ,
const llvm::DebugLoc& nodeLocation,
398 const std::vector<llvm::Value*>& io,
399 const std::vector<llvm::BasicBlock*>& outputBlocks)
override {
400 assert(io.size() == 3 && outputBlocks.size() == 1);
402 llvm::IRBuilder<> builder(&codegenInto);
403 builder.SetCurrentDebugLocation(nodeLocation);
405 llvm::Value* result =
nullptr;
406 if (mType.unqualifiedName() ==
"i32") {
407 result = [&](BinOp b) {
409 case BinOp::Add:
return builder.CreateAdd(io[0], io[1]);
410 case BinOp::Subtract:
return builder.CreateSub(io[0], io[1]);
411 case BinOp::Multiply:
return builder.CreateMul(io[0], io[1]);
412 case BinOp::Divide:
return builder.CreateSDiv(io[0], io[1]);
413 default:
return (llvm::Value*)
nullptr;
415 return (llvm::Value*)
nullptr;
419 result = [&](BinOp b) {
421 case BinOp::Add:
return builder.CreateFAdd(io[0], io[1]);
422 case BinOp::Subtract:
return builder.CreateFSub(io[0], io[1]);
423 case BinOp::Multiply:
return builder.CreateFMul(io[0], io[1]);
424 case BinOp::Divide:
return builder.CreateFDiv(io[0], io[1]);
425 default:
return (llvm::Value*)
nullptr;
427 return (llvm::Value*)
nullptr;
431 builder.CreateStore(result, io[2]);
433 builder.CreateBr(outputBlocks[0]);
438 std::unique_ptr<NodeType> clone()
const override {
439 return std::make_unique<BinaryOperationNodeType>(*this);
446 enum class CmpOp { Lt, Gt, Let, Get, Eq, Neq };
448 struct CompareNodeType : NodeType {
449 CompareNodeType(LangModule& mod, DataType ty, CmpOp op)
450 : NodeType(mod), mCompOp(op), mType{ty} {
453 std::string opStr = [](CmpOp b) {
455 case CmpOp::Lt:
return "<";
456 case CmpOp::Gt:
return ">";
457 case CmpOp::Let:
return "<=";
458 case CmpOp::Get:
return ">=";
459 case CmpOp::Eq:
return "==";
460 case CmpOp::Neq:
return "!=";
466 setName(ty.unqualifiedName() + opStr + ty.unqualifiedName());
467 setDescription(ty.unqualifiedName() + opStr + ty.unqualifiedName());
469 setDataInputs({{
"a", ty}, {
"b", ty}});
470 setDataOutputs({{
"", mod.typeFromName(
"i1")}});
473 Result codegen(NodeCompiler& , llvm::BasicBlock& codegenInto,
474 size_t ,
const llvm::DebugLoc& nodeLocation,
475 const std::vector<llvm::Value*>& io,
476 const std::vector<llvm::BasicBlock*>& outputBlocks)
override {
477 assert(io.size() == 3 && outputBlocks.size() == 1);
479 llvm::IRBuilder<> builder(&codegenInto);
480 builder.SetCurrentDebugLocation(nodeLocation);
482 llvm::Value* result =
nullptr;
483 if (mType.unqualifiedName() ==
"i32") {
484 result = [&](CmpOp b) -> llvm::Value* {
486 case CmpOp::Lt:
return builder.CreateICmpSLT(io[0], io[1]);
487 case CmpOp::Gt:
return builder.CreateICmpSGT(io[0], io[1]);
488 case CmpOp::Let:
return builder.CreateICmpSLE(io[0], io[1]);
489 case CmpOp::Get:
return builder.CreateICmpSGE(io[0], io[1]);
490 case CmpOp::Eq:
return builder.CreateICmpEQ(io[0], io[1]);
491 case CmpOp::Neq:
return builder.CreateICmpNE(io[0], io[1]);
492 default:
return nullptr;
498 result = [&](CmpOp b) -> llvm::Value* {
500 case CmpOp::Lt:
return builder.CreateFCmpULT(io[0], io[1]);
501 case CmpOp::Gt:
return builder.CreateFCmpUGT(io[0], io[1]);
502 case CmpOp::Let:
return builder.CreateFCmpULE(io[0], io[1]);
503 case CmpOp::Get:
return builder.CreateFCmpUGE(io[0], io[1]);
504 case CmpOp::Eq:
return builder.CreateFCmpUEQ(io[0], io[1]);
505 case CmpOp::Neq:
return builder.CreateFCmpUNE(io[0], io[1]);
506 default:
return nullptr;
512 builder.CreateStore(result, io[2]);
514 builder.CreateBr(outputBlocks[0]);
519 std::unique_ptr<NodeType> clone()
const override {
520 return std::make_unique<CompareNodeType>(*this);
530 using namespace std::string_literals;
535 [
this](
const nlohmann::json&,
Result&) {
return std::make_unique<IfNodeType>(*this); }},
537 [
this](
const nlohmann::json&,
Result&) {
538 return std::make_unique<BinaryOperationNodeType>(
542 [
this](
const nlohmann::json&,
Result&) {
543 return std::make_unique<BinaryOperationNodeType>(
547 [
this](
const nlohmann::json&,
Result&) {
548 return std::make_unique<BinaryOperationNodeType>(
552 [
this](
const nlohmann::json&,
Result&) {
553 return std::make_unique<BinaryOperationNodeType>(
557 [
this](
const nlohmann::json&,
Result&) {
558 return std::make_unique<BinaryOperationNodeType>(
562 [
this](
const nlohmann::json&,
Result&) {
563 return std::make_unique<BinaryOperationNodeType>(
567 [
this](
const nlohmann::json&,
Result&) {
568 return std::make_unique<BinaryOperationNodeType>(
572 [
this](
const nlohmann::json&,
Result&) {
573 return std::make_unique<BinaryOperationNodeType>(
577 [
this](
const nlohmann::json&,
Result&) {
582 [
this](
const nlohmann::json&,
Result&) {
587 [
this](
const nlohmann::json&,
Result&) {
592 [
this](
const nlohmann::json&,
Result&) {
597 [
this](
const nlohmann::json&,
Result&) {
602 [
this](
const nlohmann::json&,
Result&) {
607 [
this](
const nlohmann::json&,
Result&) {
612 [
this](
const nlohmann::json&,
Result&) {
617 [
this](
const nlohmann::json&,
Result&) {
622 [
this](
const nlohmann::json&,
Result&) {
627 [
this](
const nlohmann::json&,
Result&) {
632 [
this](
const nlohmann::json&,
Result&) {
636 {
"inttofloat"s, [
this](
const nlohmann::json&,
637 Result&) {
return std::make_unique<IntToFloatNodeType>(*this); }},
638 {
"floattoint"s, [
this](
const nlohmann::json&,
639 Result&) {
return std::make_unique<FloatToIntNodeType>(*this); }},
641 [
this](
const nlohmann::json& injson,
Result& res) {
644 std::vector<NamedDataType> dataInputs;
646 if (injson.find(
"data") != injson.end()) {
647 auto& data = injson[
"data"];
649 if (data.is_array()) {
650 for (
const auto& input : data) {
651 std::string docString;
652 std::string qualifiedType;
653 for (
auto iter = input.begin(); iter != input.end(); ++iter) {
654 docString = iter.key();
655 qualifiedType = iter.value();
658 std::string module = qualifiedType.substr(0, qualifiedType.find(
':'));
659 std::string type = qualifiedType.substr(qualifiedType.find(
':') + 1);
665 if (!res) {
continue; }
667 dataInputs.emplace_back(docString, cty);
671 res.addEntry(
"WUKN",
"Data for lang:entry must be an array",
672 {{
"Given Data", data}});
676 res.addEntry(
"WUKN",
"Data for lang:entry must have a data element",
677 {{
"Data JSON", injson}});
680 std::vector<std::string> execInputs;
682 if (injson.find(
"exec") != injson.end()) {
683 auto& exec = injson[
"exec"];
684 if (exec.is_array()) {
685 for (
const auto& output : exec) { execInputs.push_back(output); }
688 res.addEntry(
"WUKN",
"Data for lang:entry must have a exec element",
689 {{
"Data JSON", injson}});
693 return std::make_unique<EntryNodeType>(*
this, std::move(dataInputs),
694 std::move(execInputs));
696 return std::unique_ptr<EntryNodeType>();
699 [
this](
const nlohmann::json& injson,
Result& res) {
701 std::vector<NamedDataType> dataOutputs;
703 if (injson.find(
"data") != injson.end()) {
704 auto& data = injson[
"data"];
706 if (data.is_array()) {
707 for (
const auto& output : data) {
708 std::string docString;
709 std::string qualifiedType;
710 for (
auto iter = output.begin(); iter != output.end(); ++iter) {
711 docString = iter.key();
712 qualifiedType = iter.value();
715 std::string module = qualifiedType.substr(0, qualifiedType.find(
':'));
716 std::string type = qualifiedType.substr(qualifiedType.find(
':') + 1);
722 dataOutputs.emplace_back(docString, cty);
726 res.addEntry(
"WUKN",
"Data element for lang:exit must be an array",
727 {{
"Data JSON", injson}});
731 res.addEntry(
"WUKN",
"Data for lang:exit must have a data element",
732 {{
"Data JSON", injson}});
734 std::vector<std::string> execOutputs;
736 if (injson.find(
"exec") != injson.end()) {
737 auto& exec = injson[
"exec"];
738 if (exec.is_array()) {
739 for (
const auto& output : exec) { execOutputs.push_back(output); }
741 res.addEntry(
"WUKN",
"Exec element for lang:exit must be an array",
742 {{
"Data JSON", injson}});
746 res.addEntry(
"WUKN",
"Data for lang:exit must have a exec element",
747 {{
"Data JSON", injson}});
750 return std::make_unique<ExitNodeType>(*
this, std::move(dataOutputs),
751 std::move(execOutputs));
755 [
this](
const nlohmann::json& data,
Result& res) {
759 if (data.is_number_integer()) {
762 res.addEntry(
"WUKN",
"Data for lang:const-int must be an integer",
763 {{
"Given Data", data}});
766 return std::make_unique<ConstIntNodeType>(*
this, num);
769 [
this](
const nlohmann::json& data,
Result& res) {
773 if (data.is_number()) {
776 res.addEntry(
"WUKN",
"Data for lang:const-float must be a number",
777 {{
"Given Data", data}});
780 return std::make_unique<ConstFloatNodeType>(*
this, num);
783 [
this](
const nlohmann::json& data,
Result& res) {
787 if (data.is_boolean()) {
790 res.addEntry(
"WUKN",
"Data for lang:const-bool must be a boolean",
791 {{
"Given Data", data}});
794 return std::make_unique<ConstBoolNodeType>(*
this, val);
796 {
"strliteral"s, [
this](
const nlohmann::json& data,
Result& res) {
798 if (data.is_string()) {
801 res.addEntry(
"WUKN",
"Data for lang:strliteral must be a string",
802 {{
"Given Data", data}});
805 return std::make_unique<StringLiteralNodeType>(*
this, str);
807 #if LLVM_VERSION_LESS_EQUAL(3, 6) 811 auto builder = std::make_unique<llvm::DIBuilder>(*mod);
813 new llvm::DIType(builder->createBasicType(
"lang:i32", 32, 32, llvm::dwarf::DW_ATE_signed));
815 new llvm::DIType(builder->createBasicType(
"lang:i1", 8, 7, llvm::dwarf::DW_ATE_boolean));
816 mDebugTypes[
"float"] =
817 new llvm::DIType(builder->createBasicType(
"lang:float", 64, 64, llvm::dwarf::DW_ATE_float));
819 auto charType = builder->createBasicType(
"lang:i8", 8, 8, llvm::dwarf::DW_ATE_unsigned_char);
821 mDebugTypes[
"i8*"] =
new llvm::DIType(builder->createPointerType(charType, 64, 64,
"lang:i8*"));
826 llvm::DIBasicType::get(
context().llvmContext(), llvm::dwarf::DW_TAG_base_type,
"lang:i32",
827 32, 32, llvm::dwarf::DW_ATE_signed);
829 llvm::DIBasicType::get(
context().llvmContext(), llvm::dwarf::DW_TAG_base_type,
"lang:i1", 8,
830 8, llvm::dwarf::DW_ATE_boolean);
831 mDebugTypes[
"float"] =
832 llvm::DIBasicType::get(
context().llvmContext(), llvm::dwarf::DW_TAG_base_type,
"lang:float",
833 64, 64, llvm::dwarf::DW_ATE_float);
834 auto charType = llvm::DIBasicType::get(
context().llvmContext(), llvm::dwarf::DW_TAG_base_type,
835 "lang:i8", 8, 8, llvm::dwarf::DW_ATE_unsigned_char);
838 llvm::DIDerivedType::get(
context().llvmContext(), llvm::dwarf::DW_TAG_pointer_type,
nullptr,
839 nullptr, 0,
nullptr, charType, 64, 64, 0,
840 #
if LLVM_VERSION_AT_LEAST(5, 0)
843 llvm::DINode::DIFlags());
848 std::unique_ptr<NodeType>* toFill) {
851 auto iter = nodes.find(name.to_string());
852 if (iter != nodes.end()) {
853 *toFill = iter->second(jsonData, res);
857 res.
addEntry(
"E37",
"Failed to find node in module",
858 {{
"Module",
"lang"}, {
"Requested Node Type", name.to_string()}});
864 #if LLVM_VERSION_LESS_EQUAL(3, 6) 866 for (
const auto& ptr : mDebugTypes) {
delete ptr.second; }
872 using namespace std::string_literals;
876 auto err = llvm::SMDiagnostic();
877 #if LLVM_VERSION_LESS_EQUAL(3, 8) 879 auto IR =
"@G = external global "s + name.to_string();
881 auto tmpModule =
llvm::
882 #if LLVM_VERSION_LESS_EQUAL(3, 5) 883 ParseAssemblyString(IR.c_str(),
new llvm::Module(
"tmp",
context().llvmContext()), err,
886 parseAssemblyString(IR, err,
context().llvmContext());
889 if (!tmpModule) {
return nullptr; }
891 ty = tmpModule->getNamedValue(
"G")->getType()->getContainedType(0);
894 llvm::Module tMod(
"tmp",
context().llvmContext());
895 ty = llvm::parseType(name.to_string(), err, tMod,
nullptr);
900 auto iter = mDebugTypes.find(name.to_string());
901 if (iter == mDebugTypes.end()) {
return {}; }
903 #if LLVM_VERSION_LESS_EQUAL(3, 5) 907 return DataType{
this, name.to_string(), ty, iter->second};
Result nodeTypeFromName(boost::string_view name, const nlohmann::json &jsonData, std::unique_ptr< NodeType > *toFill) override
Create a node type that is in the module from the name and json.
void addEntry(const char *ec, const char *overview, nlohmann::json data)
Add a entry to the result, either a warning or an error.
Defines the Result class and related functions.
The class that handles the loading, creation, storing, and compilation of modules It also stores a LL...
An abstract class that represents a module of code in Chigraph Can be compiled to a llvm::Module...
Result addForwardDeclarations(llvm::Module &module) const override
Adds forward declartions for the functions in this module.
DataType typeFromName(boost::string_view name) override
Get a DataType from the name.
Defines the NodeType class.
llvm::LLVMContext & llvmContext()
Get the LLVMContext
Defines the LangModule class.
Result generateModule(llvm::Module &) override
Generate a llvm::Module from the module.
Defines the DataType class.
Result typeFromModule(const boost::filesystem::path &module, boost::string_view name, DataType *toFill) noexcept
Gets a DataType from a module.
The namespace where chigraph lives.
Context & context() const
Get the Context that this module belongs to.
LangModule(Context &ctx)
Default constructor, usually called from Context::loadModule("lang")
Defines the Context class and related functions.
A type of data Loose wrapper around llvm::Type*, except it knows which ChiModule it's in and it embed...
The result object, used for identifiying errors with good diagnostics.