Browse Source

adding linker

Nicolas Winkler 6 năm trước cách đây
mục cha
commit
274c19330d
6 tập tin đã thay đổi với 114 bổ sung4 xóa
  1. 1 0
      src/CMakeLists.txt
  2. 32 1
      src/Driver.cpp
  3. 1 0
      src/Driver.h
  4. 61 0
      src/Linking.cpp
  5. 15 0
      src/Linking.h
  6. 4 3
      src/sem/CodeGeneration.cpp

+ 1 - 0
src/CMakeLists.txt

@@ -41,6 +41,7 @@ include_directories( ${LLVM_INCLUDE_DIRS} )
 link_directories( ${LLVM_LIBRARY_DIRS} )
 add_definitions( ${LLVM_DEFINITIONS} )
 
+target_compile_definitions(${PROJECT_NAME} PRIVATE LLVM_VERSION=${LLVM_VERSION_MAJOR})
 
 if ( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG )
     target_compile_options(${PROJECT_NAME} PRIVATE 

+ 32 - 1
src/Driver.cpp

@@ -4,6 +4,7 @@
 #include "Semantic.h"
 #include "Builtin.h"
 #include "CodeGeneration.h"
+#include "Linking.h"
 
 #include "Printer.h"
 #include "ErrorReporting.h"
@@ -147,8 +148,11 @@ int Driver::run(void) try
         return 1;
     }
     
+    // TODO create better tempfile
+    std::string tmpPath = "/tmp/temp.o";
+
     try {
-        qlow::gen::generateObjectFile(options.outfile, std::move(mod), options.optLevel);
+        qlow::gen::generateObjectFile(tmpPath, std::move(mod), options.optLevel);
     }
     catch (const char* msg) {
         printError(printer, msg);
@@ -163,6 +167,14 @@ int Driver::run(void) try
 #ifdef DEBUGGING
     printer << "object exported!" << std::endl;
 #endif
+
+    try {
+        linkingStage();
+    }
+    catch (...) {
+        reportError("unknown error during linking");
+        return 1;
+    }
     
     return 0;
 }
@@ -261,6 +273,25 @@ bool Driver::semanticStage(void)
 }
 
 
+bool Driver::linkingStage(void)
+{
+    using namespace std::literals;
+    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"
+        }
+    );
+
+    if (linkerRun != 0) {
+        reportError("linker error");
+        errorOccurred = true;
+    }
+    return errorOccurred;
+}
 
 
 

+ 1 - 0
src/Driver.h

@@ -51,6 +51,7 @@ public:
 
     bool parseStage(void);
     bool semanticStage(void);
+    bool linkingStage(void);
 };
 
 

+ 61 - 0
src/Linking.cpp

@@ -0,0 +1,61 @@
+#include "Linking.h"
+#include "Printer.h"
+
+#include <cstring>
+#ifdef __unix__
+#include <unistd.h>
+#include <sys/wait.h>
+#endif
+
+std::string qlow::getLinkerExecutable(void)
+{
+    return "ld";
+}
+
+
+int qlow::invokeProgram(const std::string& path, const std::vector<std::string>& args)
+{
+#ifdef _WIN32
+    throw "unimplemented on windows";
+#elif defined(__unix__)
+    pid_t pid = fork();
+    
+    if (pid == 0) { // we are the child
+        char** c_args = new char*[args.size() + 2];
+        c_args[0] = new char[path.size() + 1];
+        strncpy(c_args[0], path.c_str(), path.size() + 1);
+        for (size_t i = 0; i < args.size(); i++) {
+            c_args[i + 1] = new char[args[i].size() + 1];
+            strncpy(c_args[i + 1], args[i].c_str(), args[i].size() + 1);
+        }
+        c_args[args.size() + 1] = nullptr;
+        for (size_t i = 0; i < args.size() + 1; i++)
+            Printer::getInstance() << c_args[i] << std::endl;
+        execvp(path.c_str(), c_args);
+    }
+    else if (pid > 0) { // we are the parent
+        int exitStatus;
+        pid_t p;
+        while ((waitpid(pid, &exitStatus, 0)) > 0) {
+            if (WIFEXITED(exitStatus)) {
+                return WEXITSTATUS(exitStatus);
+            }
+            else {
+                throw "child interrupted";
+            }
+        }
+    }
+    else {
+        throw "fork failed";
+    }
+#else
+#error unsupported platform
+#endif
+    throw "error invoking program";
+}
+
+
+
+
+
+

+ 15 - 0
src/Linking.h

@@ -0,0 +1,15 @@
+#ifndef QLOW_LINKING_H_
+#define QLOW_LINKING_H_
+
+#include <filesystem>
+
+namespace qlow
+{
+    std::string getLinkerExecutable(void);
+    int invokeProgram(const std::string& path, const std::vector<std::string>& args);
+}
+
+
+#endif // QLOW_LINKING_H_
+
+

+ 4 - 3
src/sem/CodeGeneration.cpp

@@ -270,14 +270,15 @@ void generateObjectFile(const std::string& filename, std::unique_ptr<llvm::Modul
 
     std::error_code errorCode;
 
-    auto tempfile = std::filesystem::temp_directory_path() / "qlow.o";
-
-    raw_fd_ostream dest(tempfile.c_str(), errorCode, llvm::sys::fs::F_None);
+    raw_fd_ostream dest(filename, errorCode, llvm::sys::fs::F_None);
 #ifdef DEBUGGING
     printer << "adding passes" << std::endl;
 #endif
     targetMachine->addPassesToEmitFile(pm, dest,
 //        llvm::LLVMTargetMachine::CGFT_ObjectFile,
+#if defined(LLVM_VERSION_MAJOR) && LLVM_VERSION_MAJOR >= 7
+            nullptr,
+#endif
 //        nullptr,
         llvm::TargetMachine::CGFT_ObjectFile);