A Hugo incarnation of the blog.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. #include "compiler.hpp"
  2. #include "binop.hpp"
  3. #include "error.hpp"
  4. #include "global_scope.hpp"
  5. #include "parse_driver.hpp"
  6. #include "type.hpp"
  7. #include "type_env.hpp"
  8. #include "llvm/IR/LegacyPassManager.h"
  9. #include "llvm/IR/Verifier.h"
  10. #include "llvm/Support/TargetSelect.h"
  11. #include "llvm/Support/TargetRegistry.h"
  12. #include "llvm/Support/raw_ostream.h"
  13. #include "llvm/Support/FileSystem.h"
  14. #include "llvm/Target/TargetOptions.h"
  15. #include "llvm/Target/TargetMachine.h"
  16. void compiler::add_default_types() {
  17. global_env->bind_type("Int", type_ptr(new type_base("Int")));
  18. }
  19. void compiler::add_binop_type(binop op, type_ptr type) {
  20. auto name = mng.new_mangled_name(op_action(op));
  21. global_env->bind(op_name(op), std::move(type), visibility::global);
  22. global_env->set_mangled_name(op_name(op), name);
  23. }
  24. void compiler::add_default_function_types() {
  25. type_ptr int_type = global_env->lookup_type("Int");
  26. assert(int_type != nullptr);
  27. type_ptr int_type_app = type_ptr(new type_app(int_type));
  28. type_ptr closed_int_op_type(
  29. new type_arr(int_type_app, type_ptr(new type_arr(int_type_app, int_type_app))));
  30. constexpr binop closed_ops[] = { PLUS, MINUS, TIMES, DIVIDE };
  31. for(auto& op : closed_ops) add_binop_type(op, closed_int_op_type);
  32. }
  33. void compiler::parse() {
  34. if(!driver())
  35. throw compiler_error("failed to open file");
  36. }
  37. void compiler::typecheck() {
  38. std::set<std::string> free_variables;
  39. global_defs.find_free(free_variables);
  40. global_defs.typecheck(type_m, global_env);
  41. }
  42. void compiler::translate() {
  43. for(auto& data : global_defs.defs_data) {
  44. data.second->into_globals(global_scp);
  45. }
  46. for(auto& defn : global_defs.defs_defn) {
  47. auto& function = defn.second->into_global(global_scp);
  48. defn.second->env->set_mangled_name(defn.first, function.name);
  49. }
  50. }
  51. void compiler::compile() {
  52. global_scp.compile();
  53. }
  54. void compiler::create_llvm_binop(binop op) {
  55. auto new_function =
  56. ctx.create_custom_function(global_env->get_mangled_name(op_name(op)), 2);
  57. std::vector<instruction_ptr> instructions;
  58. instructions.push_back(instruction_ptr(new instruction_push(1)));
  59. instructions.push_back(instruction_ptr(new instruction_eval()));
  60. instructions.push_back(instruction_ptr(new instruction_push(1)));
  61. instructions.push_back(instruction_ptr(new instruction_eval()));
  62. instructions.push_back(instruction_ptr(new instruction_binop(op)));
  63. instructions.push_back(instruction_ptr(new instruction_update(2)));
  64. instructions.push_back(instruction_ptr(new instruction_pop(2)));
  65. ctx.get_builder().SetInsertPoint(&new_function->getEntryBlock());
  66. for(auto& instruction : instructions) {
  67. instruction->gen_llvm(ctx, new_function);
  68. }
  69. ctx.get_builder().CreateRetVoid();
  70. }
  71. void compiler::generate_llvm() {
  72. for(auto op : all_binops) {
  73. create_llvm_binop(op);
  74. }
  75. global_scp.generate_llvm(ctx);
  76. }
  77. void compiler::output_llvm(const std::string& into) {
  78. std::string targetTriple = llvm::sys::getDefaultTargetTriple();
  79. llvm::InitializeNativeTarget();
  80. llvm::InitializeNativeTargetAsmParser();
  81. llvm::InitializeNativeTargetAsmPrinter();
  82. std::string error;
  83. const llvm::Target* target =
  84. llvm::TargetRegistry::lookupTarget(targetTriple, error);
  85. if (!target) {
  86. std::cerr << error << std::endl;
  87. } else {
  88. std::string cpu = "generic";
  89. std::string features = "";
  90. llvm::TargetOptions options;
  91. std::unique_ptr<llvm::TargetMachine> targetMachine(
  92. target->createTargetMachine(targetTriple, cpu, features,
  93. options, llvm::Optional<llvm::Reloc::Model>()));
  94. ctx.get_module().setDataLayout(targetMachine->createDataLayout());
  95. ctx.get_module().setTargetTriple(targetTriple);
  96. std::error_code ec;
  97. llvm::raw_fd_ostream file(into, ec, llvm::sys::fs::F_None);
  98. if (ec) {
  99. throw compiler_error("failed to open object file for writing");
  100. } else {
  101. llvm::CodeGenFileType type = llvm::CGFT_ObjectFile;
  102. llvm::legacy::PassManager pm;
  103. if (targetMachine->addPassesToEmitFile(pm, file, NULL, type)) {
  104. throw compiler_error("failed to add passes to pass manager");
  105. } else {
  106. pm.run(ctx.get_module());
  107. file.close();
  108. }
  109. }
  110. }
  111. }
  112. compiler::compiler(const std::string& filename)
  113. : file_m(), global_defs(), driver(file_m, global_defs, filename),
  114. global_env(new type_env), type_m(), mng(), global_scp(mng), ctx() {
  115. add_default_types();
  116. add_default_function_types();
  117. }
  118. void compiler::operator()(const std::string& into) {
  119. parse();
  120. typecheck();
  121. translate();
  122. compile();
  123. generate_llvm();
  124. output_llvm(into);
  125. }
  126. file_mgr& compiler::get_file_manager() {
  127. return file_m;
  128. }
  129. type_mgr& compiler::get_type_manager() {
  130. return type_m;
  131. }