Nicolas Winkler 6 vuotta sitten
vanhempi
commit
7f4680c88d
5 muutettua tiedostoa jossa 56 lisäystä ja 10 poistoa
  1. 16 9
      src/Driver.cpp
  2. 5 0
      src/Driver.h
  3. 4 1
      src/Linking.cpp
  4. 30 0
      src/sem/CodeGeneration.cpp
  5. 1 0
      src/sem/CodeGeneration.h

+ 16 - 9
src/Driver.cpp

@@ -56,6 +56,11 @@ Options Options::parseOptions(int argc, char** argv)
                 options.optLevel = 2;
             }
         }
+        else if (arg.rfind("-l", 0) == 0) {
+            if (arg.size() > 2) {
+                options.libs.push_back(arg.substr(2));
+            }
+        }
         else {
             if (options.outfile == "")
                 options.outfile = arg + ".o";
@@ -149,10 +154,10 @@ int Driver::run(void) try
     }
     
     // TODO create better tempfile
-    std::string tmpPath = "/tmp/temp.o";
+    tempObject = "/tmp/temp.o";
 
     try {
-        qlow::gen::generateObjectFile(tmpPath, std::move(mod), options.optLevel);
+        qlow::gen::generateObjectFile(tempObject, std::move(mod), options.optLevel);
     }
     catch (const char* msg) {
         printError(printer, msg);
@@ -163,7 +168,7 @@ int Driver::run(void) try
         reportError("unknown error during object file creation");
         return 1;
     }
-    
+
 #ifdef DEBUGGING
     printer << "object exported!" << std::endl;
 #endif
@@ -279,12 +284,14 @@ bool Driver::linkingStage(void)
     bool errorOccurred = false;
     auto linkerPath = qlow::getLinkerExecutable();
 
-    int linkerRun = qlow::invokeProgram(linkerPath,
-        {
-            "/tmp/temp.o", "-e", "main", "--output="s + options.outfile,
-            "-lc", "-dynamic-linker", "/lib64/ld-linux-x86-64.so.2"
-        }
-    );
+    std::vector<std::string> ldArgs = {
+        tempObject.string(), "-e", "_qlow_start", "-o", options.outfile,
+        "-lc", "-dynamic-linker", "/lib64/ld-linux-x86-64.so.2"
+    };
+
+    std::copy(options.libs.begin(), options.libs.end(), std::back_inserter(ldArgs));
+
+    int linkerRun = qlow::invokeProgram(linkerPath, ldArgs);
 
     if (linkerRun != 0) {
         reportError("linker error");

+ 5 - 0
src/Driver.h

@@ -6,6 +6,8 @@
 #include <memory>
 #include <string>
 #include <utility>
+#include <filesystem>
+
 #include "Parser.h"
 #include "Scope.h"
 
@@ -30,6 +32,7 @@ struct qlow::Options
     bool emitLlvm;
     std::string outfile = "a.out";
     std::vector<std::string> infiles;
+    std::vector<std::string> libs;
     
     int optLevel = 0;
     
@@ -43,6 +46,8 @@ class qlow::Driver
     std::unique_ptr<ast::Ast> ast = nullptr;
     std::unique_ptr<sem::Context> context = nullptr;
     std::unique_ptr<sem::GlobalScope> semClasses = nullptr;
+
+    std::filesystem::path tempObject = "";
 public:
     Driver(void) = delete;
     Driver(int argc, char** argv);

+ 4 - 1
src/Linking.cpp

@@ -29,8 +29,11 @@ int qlow::invokeProgram(const std::string& path, const std::vector<std::string>&
             strncpy(c_args[i + 1], args[i].c_str(), args[i].size() + 1);
         }
         c_args[args.size() + 1] = nullptr;
+#ifdef DEBUGGING
         for (size_t i = 0; i < args.size() + 1; i++)
-            Printer::getInstance() << c_args[i] << std::endl;
+            Printer::getInstance() << c_args[i] << " ";
+        Printer::getInstance() << std::endl;
+#endif
         execvp(path.c_str(), c_args);
     }
     else if (pid > 0) { // we are the parent

+ 30 - 0
src/sem/CodeGeneration.cpp

@@ -138,6 +138,7 @@ std::unique_ptr<llvm::Module> generateModule(sem::GlobalScope& semantic)
         printf("verified function: %s\n", method->name.c_str());
 #endif
     }
+    generateStartFunction(module.get(), semantic.getMethod("main")->llvmNode);
     return module;
 }
 
@@ -203,6 +204,35 @@ llvm::Function* generateFunction(llvm::Module* module, sem::Method* method)
 }
 
 
+
+llvm::Function* generateStartFunction(llvm::Module* module, llvm::Function* start)
+{
+    using llvm::Function;
+    using llvm::FunctionType;
+    using llvm::Type;
+    using llvm::IRBuilder;
+    using llvm::BasicBlock;
+    using llvm::Value;
+
+    FunctionType* startFuncType = FunctionType::get(
+        Type::getVoidTy(context), { Type::getInt32Ty(context), Type::getInt8PtrTy(context)->getPointerTo() }, false);
+    FunctionType* exitFuncType = FunctionType::get(
+        Type::getVoidTy(context), { Type::getInt32Ty(context) }, false);
+    Function* startFunction = Function::Create(startFuncType, Function::ExternalLinkage, "_qlow_start", module);
+    Function* exitFunction = Function::Create(exitFuncType, Function::ExternalLinkage, "exit", module);
+
+
+    IRBuilder<> builder(context);
+    BasicBlock* bb = BasicBlock::Create(context, "entry", startFunction);
+    builder.SetInsertPoint(bb);
+    builder.CreateCall(start, {});
+    builder.CreateCall(exitFunction, { llvm::ConstantInt::get(context, llvm::APInt(32, "0", 10)) });
+    builder.CreateRetVoid();
+
+    return startFunction;
+}
+
+
 void generateObjectFile(const std::string& filename, std::unique_ptr<llvm::Module> module, int optLevel)
 {
     using llvm::legacy::PassManager;

+ 1 - 0
src/sem/CodeGeneration.h

@@ -16,6 +16,7 @@ namespace gen
 {
     std::unique_ptr<llvm::Module> generateModule(sem::GlobalScope& objects);
     llvm::Function* generateFunction (llvm::Module* module, sem::Method* method);
+    llvm::Function* generateStartFunction(llvm::Module* module, llvm::Function* start);
     void generateObjectFile(const std::string& name, std::unique_ptr<llvm::Module> module, int optLevel);
 
     class FunctionGenerator;