clover/llvm: Clean up compile_native().
authorFrancisco Jerez <currojerez@riseup.net>
Tue, 17 May 2016 14:02:49 +0000 (16:02 +0200)
committerFrancisco Jerez <currojerez@riseup.net>
Tue, 12 Jul 2016 03:22:50 +0000 (20:22 -0700)
This switches compile_native() to the C++ API (which the rest of this
file makes use of anyway so there is little benefit from using the C
API), what should get rid of an amount of boilerplate and fix a leak
of the TargetMachine object in the error path.

v2: Additional fixes for LLVM 3.6.
v3: Update for the latest LLVM SVN changes.

Reviewed-by: Serge Martin <edb+mesa@sigluy.net>
Tested-by: Jan Vesely <jan.vesely@rutgers.edu>
src/gallium/state_trackers/clover/llvm/compat.hpp
src/gallium/state_trackers/clover/llvm/invocation.cpp
src/gallium/state_trackers/clover/llvm/util.hpp

index 3206f77c6ccf6a71666ac8d10e8b057355c0e28f..82dd649837ce162701a694db127c25d1b0c1ce6c 100644 (file)
@@ -38,6 +38,7 @@
 
 #include <llvm/Linker/Linker.h>
 #include <llvm/Transforms/IPO.h>
+#include <llvm/Target/TargetMachine.h>
 
 #if HAVE_LLVM >= 0x0307
 #include <llvm/IR/LegacyPassManager.h>
@@ -45,6 +46,8 @@
 #else
 #include <llvm/PassManager.h>
 #include <llvm/Target/TargetLibraryInfo.h>
+#include <llvm/Target/TargetSubtargetInfo.h>
+#include <llvm/Support/FormattedStream.h>
 #endif
 
 #include <clang/Frontend/CodeGenOptions.h>
@@ -109,6 +112,33 @@ namespace clover {
                       map(std::mem_fn(&std::string::data), names))));
 #endif
          }
+
+#if HAVE_LLVM >= 0x0307
+         typedef ::llvm::raw_svector_ostream &raw_ostream_to_emit_file;
+#else
+         typedef ::llvm::formatted_raw_ostream raw_ostream_to_emit_file;
+#endif
+
+#if HAVE_LLVM >= 0x0307
+         typedef ::llvm::DataLayout data_layout;
+#else
+         typedef const ::llvm::DataLayout *data_layout;
+#endif
+
+         inline data_layout
+         get_data_layout(::llvm::TargetMachine &tm) {
+#if HAVE_LLVM >= 0x0307
+            return tm.createDataLayout();
+#else
+            return tm.getSubtargetImpl()->getDataLayout();
+#endif
+         }
+
+#if HAVE_LLVM >= 0x0309
+         const auto default_reloc_model = ::llvm::None;
+#else
+         const auto default_reloc_model = ::llvm::Reloc::Default;
+#endif
       }
    }
 }
index 9612216c4184251dad670cdd7c547d5913955e41..1e4bed81270def2fd888d9fa952df0d453c5df4c 100644 (file)
@@ -81,6 +81,7 @@ using ::llvm::Function;
 using ::llvm::LLVMContext;
 using ::llvm::Module;
 using ::llvm::raw_string_ostream;
+using ::llvm::TargetMachine;
 
 namespace {
    // XXX - Temporary hack to avoid breaking the build for the moment, will
@@ -542,80 +543,55 @@ namespace {
       return m;
    }
 
-   void
-   emit_code(LLVMTargetMachineRef tm, LLVMModuleRef mod,
-             LLVMCodeGenFileType file_type,
-             LLVMMemoryBufferRef *out_buffer,
+   std::vector<char>
+   emit_code(::llvm::Module &mod, const target &target,
+             TargetMachine::CodeGenFileType ft,
              std::string &r_log) {
-      char *err_message = NULL;
+      std::string err;
+      auto t = ::llvm::TargetRegistry::lookupTarget(target.triple, err);
+      if (!t)
+         fail(r_log, compile_error(), err);
+
+      std::unique_ptr<TargetMachine> tm {
+         t->createTargetMachine(target.triple, target.cpu, "", {},
+                                compat::default_reloc_model,
+                                ::llvm::CodeModel::Default,
+                                ::llvm::CodeGenOpt::Default) };
+      if (!tm)
+         fail(r_log, compile_error(),
+              "Could not create TargetMachine: " + target.triple);
 
-      try {
-         if (LLVMTargetMachineEmitToMemoryBuffer(tm, mod, file_type,
-                                                 &err_message, out_buffer))
-            fail(r_log, compile_error(), err_message);
+      ::llvm::SmallVector<char, 1024> data;
 
-      } catch (...) {
-         LLVMDisposeMessage(err_message);
-         throw;
-      }
-   }
+      {
+         compat::pass_manager pm;
+         ::llvm::raw_svector_ostream os { data };
+         compat::raw_ostream_to_emit_file fos { os };
 
-   std::vector<char>
-   compile_native(const llvm::Module *mod, const target &t,
-                  std::string &r_log) {
+         mod.setDataLayout(compat::get_data_layout(*tm));
+         tm->Options.MCOptions.AsmVerbose =
+            (ft == TargetMachine::CGFT_AssemblyFile);
 
-      std::string log;
-      LLVMTargetRef target;
-      char *error_message;
-      LLVMMemoryBufferRef out_buffer;
-      unsigned buffer_size;
-      const char *buffer_data;
-      LLVMModuleRef mod_ref = wrap(mod);
-
-      try {
-         if (LLVMGetTargetFromTriple(t.triple.c_str(), &target, &error_message))
-            fail(r_log, compile_error(), error_message);
-
-      } catch (...) {
-         LLVMDisposeMessage(error_message);
-         throw;
+         if (tm->addPassesToEmitFile(pm, fos, ft))
+            fail(r_log, compile_error(), "TargetMachine can't emit this file");
+
+         pm.run(mod);
       }
 
-      LLVMTargetMachineRef tm = LLVMCreateTargetMachine(
-            target, t.triple.c_str(), t.cpu.c_str(), "",
-            LLVMCodeGenLevelDefault, LLVMRelocDefault, LLVMCodeModelDefault);
-      if (!tm)
-         fail(r_log, compile_error(),
-              "Could not create TargetMachine: " + t.triple);
+      return { data.begin(), data.end() };
+   }
 
+   std::vector<char>
+   compile_native(llvm::Module *mod, const target &target,
+                  std::string &r_log) {
       if (has_flag(debug::native)) {
-         LLVMSetTargetMachineAsmVerbosity(tm, true);
-#if HAVE_LLVM >= 0x0308
-         LLVMModuleRef debug_mod = wrap(llvm::CloneModule(mod).release());
-#else
-         LLVMModuleRef debug_mod = wrap(llvm::CloneModule(mod));
-#endif
-         emit_code(tm, debug_mod, LLVMAssemblyFile, &out_buffer, r_log);
-         buffer_size = LLVMGetBufferSize(out_buffer);
-         buffer_data = LLVMGetBufferStart(out_buffer);
-         debug::log(".asm", std::string(buffer_data, buffer_size));
-
-         LLVMSetTargetMachineAsmVerbosity(tm, false);
-         LLVMDisposeMemoryBuffer(out_buffer);
-         LLVMDisposeModule(debug_mod);
+         std::unique_ptr<llvm::Module> cmod { CloneModule(mod) };
+         debug::log(".asm", as_string(
+                       emit_code(*cmod, target,
+                                 TargetMachine::CGFT_AssemblyFile, r_log)));
       }
 
-      emit_code(tm, mod_ref, LLVMObjectFile, &out_buffer, r_log);
-
-      buffer_size = LLVMGetBufferSize(out_buffer);
-      buffer_data = LLVMGetBufferStart(out_buffer);
-
-      std::vector<char> code(buffer_data, buffer_data + buffer_size);
-
-      LLVMDisposeMemoryBuffer(out_buffer);
-      LLVMDisposeTargetMachine(tm);
-
-      return code;
+      return emit_code(*mod, target, TargetMachine::CGFT_ObjectFile, r_log);
    }
 
    namespace elf {
index f9a057d878c3066a4adc9fab033679c567cf1bcc..8db6f20e5a7d19fe5263af758fa2daa91751bf89 100644 (file)
@@ -51,6 +51,11 @@ namespace clover {
          return ss;
       }
 
+      inline std::string
+      as_string(const std::vector<char> &v) {
+         return { v.begin(), v.end() };
+      }
+
       struct target {
          target(const std::string &s) :
             cpu(s.begin(), s.begin() + s.find_first_of("-")),