CodeGeneration.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. #include "CodeGeneration.h"
  2. #include "Linking.h"
  3. #include <llvm/IR/LLVMContext.h>
  4. #include <llvm/IR/LegacyPassManager.h>
  5. #include <llvm/Transforms/IPO/PassManagerBuilder.h>
  6. #include <llvm/IR/Type.h>
  7. #include <llvm/IR/DerivedTypes.h>
  8. #include <llvm/IR/Constants.h>
  9. #include <llvm/IR/BasicBlock.h>
  10. #include <llvm/IR/Verifier.h>
  11. #include <llvm/IR/IRBuilder.h>
  12. #include <llvm/IR/Attributes.h>
  13. #include <llvm/Target/TargetMachine.h>
  14. #include <llvm/Support/TargetRegistry.h>
  15. #include <llvm/Support/TargetSelect.h>
  16. #include <llvm/Support/FileSystem.h>
  17. #include <llvm/Support/raw_os_ostream.h>
  18. using namespace qlow;
  19. static llvm::LLVMContext context;
  20. namespace qlow
  21. {
  22. namespace gen
  23. {
  24. std::unique_ptr<llvm::Module> generateModule(sem::GlobalScope& semantic)
  25. {
  26. using llvm::Module;
  27. using llvm::Function;
  28. using llvm::Argument;
  29. using llvm::Type;
  30. using llvm::FunctionType;
  31. using llvm::BasicBlock;
  32. using llvm::Value;
  33. using llvm::IRBuilder;
  34. Printer& printer = Printer::getInstance();
  35. #ifdef DEBUGGING
  36. printf("creating llvm module\n");
  37. #endif
  38. std::unique_ptr<Module> module = llvm::make_unique<Module>("qlow_module", context);
  39. // create llvm structs
  40. // TODO implement detection of circles
  41. semantic.getContext().createLlvmTypes(context);
  42. llvm::AttrBuilder ab;
  43. ab.addAttribute(llvm::Attribute::AttrKind::NoInline);
  44. ab.addAttribute(llvm::Attribute::AttrKind::NoUnwind);
  45. //ab.addAttribute(llvm::Attribute::AttrKind::OptimizeNone);
  46. //ab.addAttribute(llvm::Attribute::AttrKind::UWTable);
  47. ab.addAttribute("no-frame-pointer-elim", "true");
  48. ab.addAttribute("no-frame-pointer-elim-non-leaf");
  49. llvm::AttributeSet as = llvm::AttributeSet::get(context, ab);
  50. std::vector<llvm::Function*> functions;
  51. auto verifyStream = llvm::raw_os_ostream(printer);
  52. // create all llvm functions
  53. for (const auto& [name, cl] : semantic.getClasses()) {
  54. for (const auto& [name, method] : cl->methods) {
  55. Function* func = generateFunction(module.get(), method.get());
  56. for (auto a : as) {
  57. func->addFnAttr(a);
  58. }
  59. functions.push_back(func);
  60. }
  61. }
  62. for (const auto& [name, method] : semantic.getMethods()) {
  63. Function* func = generateFunction(module.get(), method.get());
  64. for (auto a : as) {
  65. func->addFnAttr(a);
  66. }
  67. functions.push_back(func);
  68. }
  69. for (const auto& [name, cl] : semantic.getClasses()){
  70. for (const auto& [name, method] : cl->methods) {
  71. if (!method->body)
  72. continue;
  73. FunctionGenerator fg(*method, module.get(), as);
  74. Function* f = fg.generate();
  75. // printer << "verifying function: " << method->name << std::endl;
  76. bool corrupt = llvm::verifyFunction(*f, &verifyStream);
  77. if (corrupt) {
  78. #ifdef DEBUGGING
  79. //module->print(verifyStream, nullptr);
  80. #endif
  81. throw (std::string("corrupt llvm function: ") + method->name).c_str();
  82. }
  83. #ifdef DEBUGGING
  84. printf("verified function: %s\n", method->name.c_str());
  85. #endif
  86. }
  87. }
  88. for (const auto& [name, method] : semantic.getMethods()) {
  89. if (!method->body)
  90. continue;
  91. FunctionGenerator fg(*method, module.get(), as);
  92. Function* f = fg.generate();
  93. //printer.debug() << "verifying function: " << method->name << std::endl;
  94. bool corrupt = llvm::verifyFunction(*f, &verifyStream);
  95. if (corrupt) {
  96. f->print(verifyStream, nullptr);
  97. throw (std::string("corrupt llvm function: ") + method->name).c_str();
  98. }
  99. #ifdef DEBUGGING
  100. printf("verified function: %s\n", method->name.c_str());
  101. #endif
  102. }
  103. generateStartFunction(module.get(), semantic.getMethod("main")->llvmNode);
  104. return module;
  105. }
  106. llvm::Function* generateFunction(llvm::Module* module, sem::Method* method)
  107. {
  108. sem::Context& semCtxt = method->context;
  109. using llvm::Function;
  110. using llvm::Argument;
  111. using llvm::Type;
  112. using llvm::FunctionType;
  113. Type* returnType;
  114. if (method->returnType)
  115. returnType = method->returnType->getLlvmType(context);
  116. else
  117. returnType = llvm::Type::getVoidTy(context);
  118. std::vector<Type*> argumentTypes;
  119. if (method->thisExpression != nullptr) {
  120. Type* enclosingType = method->thisExpression->type->getLlvmType(context);
  121. argumentTypes.push_back(enclosingType);
  122. }
  123. for (auto& arg : method->arguments) {
  124. Type* argumentType = arg->type->getLlvmType(context);
  125. argumentTypes.push_back(argumentType);
  126. }
  127. FunctionType* funcType = FunctionType::get(
  128. returnType, argumentTypes, false);
  129. #ifdef DEBUGGING
  130. printf("looking up llvm type of %s\n", method->name.c_str());
  131. #endif
  132. if (returnType == nullptr)
  133. throw "invalid return type";
  134. std::string symbolName;
  135. if (method->isExtern) {
  136. symbolName = qlow::getExternalSymbol(method->name);
  137. }
  138. else {
  139. symbolName = method->name;
  140. }
  141. Function* func = Function::Create(funcType, Function::ExternalLinkage, symbolName, module);
  142. method->llvmNode = func;
  143. // linking alloca instances for funcs
  144. auto argIterator = func->arg_begin();
  145. if (method->thisExpression != nullptr) {
  146. method->thisExpression->allocaInst = &*argIterator;
  147. #ifdef DEBUGGING
  148. Printer::getInstance() << "allocaInst of this";
  149. #endif
  150. argIterator++;
  151. }
  152. size_t argIndex = 0;
  153. for (; argIterator != func->arg_end(); argIterator++) {
  154. if (argIndex > method->arguments.size())
  155. throw "internal error";
  156. method->arguments[argIndex]->allocaInst = &*argIterator;
  157. #ifdef DEBUGGING
  158. printf("allocaInst of arg '%s': %p\n", method->arguments[argIndex]->name.c_str(), (void*)method->arguments[argIndex]->allocaInst);
  159. #endif
  160. argIndex++;
  161. }
  162. //printf("UEEEEEEEE %s\n", method->name.c_str());
  163. return func;
  164. }
  165. llvm::Function* generateStartFunction(llvm::Module* module, llvm::Function* start)
  166. {
  167. using llvm::Function;
  168. using llvm::FunctionType;
  169. using llvm::Type;
  170. using llvm::IRBuilder;
  171. using llvm::BasicBlock;
  172. using llvm::Value;
  173. FunctionType* startFuncType = FunctionType::get(
  174. Type::getVoidTy(context), { Type::getInt32Ty(context), Type::getInt8PtrTy(context)->getPointerTo() }, false);
  175. FunctionType* exitFuncType = FunctionType::get(
  176. Type::getVoidTy(context), { Type::getInt32Ty(context) }, false);
  177. Function* startFunction = Function::Create(startFuncType, Function::ExternalLinkage, "_qlow_start", module);
  178. Function* exitFunction = Function::Create(exitFuncType, Function::ExternalLinkage, qlow::getExternalSymbol("exit"), module);
  179. IRBuilder<> builder(context);
  180. BasicBlock* bb = BasicBlock::Create(context, "entry", startFunction);
  181. builder.SetInsertPoint(bb);
  182. builder.CreateCall(start, {});
  183. builder.CreateCall(exitFunction, { llvm::ConstantInt::get(context, llvm::APInt(32, "0", 10)) });
  184. builder.CreateRetVoid();
  185. return startFunction;
  186. }
  187. void generateObjectFile(const std::string& filename, std::unique_ptr<llvm::Module> module, int optLevel)
  188. {
  189. using llvm::legacy::PassManager;
  190. using llvm::PassManagerBuilder;
  191. using llvm::raw_fd_ostream;
  192. using llvm::Target;
  193. using llvm::TargetMachine;
  194. using llvm::TargetRegistry;
  195. using llvm::TargetOptions;
  196. Printer& printer = Printer::getInstance();
  197. #ifdef DEBUGGING
  198. printer << "verifying mod" << std::endl;
  199. #endif
  200. auto ostr = llvm::raw_os_ostream(printer);
  201. #ifdef DEBUGGING
  202. module->print(ostr, nullptr);
  203. #endif
  204. bool broken = llvm::verifyModule(*module);
  205. if (broken)
  206. throw "invalid llvm module";
  207. llvm::InitializeNativeTarget ();
  208. llvm::InitializeNativeTargetAsmPrinter();
  209. //llvm::InitializeAllTargetInfos();
  210. //llvm::InitializeAllTargets();
  211. //llvm::InitializeAllTargetMCs();
  212. //llvm::InitializeAllAsmParsers();
  213. //llvm::InitializeAllAsmPrinters();
  214. PassManager pm;
  215. int sizeLevel = 0;
  216. PassManagerBuilder builder;
  217. builder.OptLevel = optLevel;
  218. builder.SizeLevel = sizeLevel;
  219. if (optLevel >= 2) {
  220. builder.DisableUnitAtATime = false;
  221. builder.DisableUnrollLoops = false;
  222. builder.LoopVectorize = true;
  223. builder.SLPVectorize = true;
  224. }
  225. builder.populateModulePassManager(pm);
  226. const char cpu[] = "generic";
  227. const char features[] = "";
  228. std::string error;
  229. std::string targetTriple = llvm::sys::getDefaultTargetTriple();
  230. const Target* target = TargetRegistry::lookupTarget(targetTriple, error);
  231. if (!target) {
  232. #ifdef DEBUGGING
  233. printer << "could not create target: " << error << std::endl;
  234. #endif
  235. throw "internal error";
  236. }
  237. TargetOptions targetOptions;
  238. auto relocModel = llvm::Optional<llvm::Reloc::Model>(llvm::Reloc::Model::PIC_);
  239. TargetMachine* targetMachine = target->createTargetMachine(targetTriple, cpu,
  240. features, targetOptions, relocModel);
  241. std::error_code errorCode;
  242. raw_fd_ostream dest(filename, errorCode, llvm::sys::fs::F_None);
  243. #ifdef DEBUGGING
  244. printer << "adding passes" << std::endl;
  245. #endif
  246. targetMachine->addPassesToEmitFile(pm, dest,
  247. // llvm::LLVMTargetMachine::CGFT_ObjectFile,
  248. #if defined(LLVM_VERSION_MAJOR) && LLVM_VERSION_MAJOR >= 7
  249. nullptr,
  250. #endif
  251. // nullptr,
  252. llvm::TargetMachine::CGFT_ObjectFile);
  253. pm.run(*module);
  254. dest.flush();
  255. dest.close();
  256. return;
  257. }
  258. } // namespace gen
  259. } // namespace qlow
  260. llvm::Function* qlow::gen::FunctionGenerator::generate(void)
  261. {
  262. using llvm::Function;
  263. using llvm::Argument;
  264. using llvm::Type;
  265. using llvm::FunctionType;
  266. using llvm::BasicBlock;
  267. using llvm::Value;
  268. using llvm::IRBuilder;
  269. sem::Context& semCtxt = this->method.context;
  270. #ifdef DEBUGGING
  271. printf("generate function %s\n", method.name.c_str());
  272. #endif
  273. Function* func = module->getFunction(method.name);
  274. if (func == nullptr) {
  275. throw "internal error: function not found";
  276. }
  277. BasicBlock* bb = BasicBlock::Create(context, "entry", func);
  278. pushBlock(bb);
  279. IRBuilder<> builder(context);
  280. builder.SetInsertPoint(bb);
  281. for (auto& [name, var] : method.body->scope.getLocals()) {
  282. if (var.get() == nullptr)
  283. throw "wtf null variable";
  284. if (var->type == nullptr)
  285. throw "wtf null type";
  286. llvm::AllocaInst* v = builder.CreateAlloca(var->type->getLlvmType(context));
  287. var->allocaInst = v;
  288. }
  289. for (auto& statement : method.body->statements) {
  290. #ifdef DEBUGGING
  291. printf("statement visit %s\n", statement->toString().c_str());
  292. #endif
  293. statement->accept(statementVisitor, *this);
  294. }
  295. #ifdef DEBUGGING
  296. printf("End of Function\n");
  297. #endif
  298. //Value* val = llvm::ConstantFP::get(context, llvm::APFloat(5.0));
  299. builder.SetInsertPoint(getCurrentBlock());
  300. //if (method.returnType->equals(sem::NativeType(sem::NativeType::Type::VOID))) {
  301. if (method.returnType == nullptr || method.returnType->isVoid()) {
  302. builder.CreateRetVoid();
  303. }
  304. return func;
  305. }