about summary refs log tree commit diff
path: root/src/rustllvm
diff options
context:
space:
mode:
authorAriel Ben-Yehuda <ariel.byd@gmail.com>2016-08-02 00:16:16 +0300
committerAriel Ben-Yehuda <arielb1@mail.tau.ac.il>2016-08-03 15:08:47 +0300
commit696691e3c4f2b3aa02fbd1cc76dc2f7e8a401db8 (patch)
treeb74e88f26e0a6d2f5d3ff114efe34fbd6b805223 /src/rustllvm
parent81df89fc2d6ba1b55ab20b0615b8523a6e90963f (diff)
downloadrust-696691e3c4f2b3aa02fbd1cc76dc2f7e8a401db8.tar.gz
rust-696691e3c4f2b3aa02fbd1cc76dc2f7e8a401db8.zip
audit LLVM C++ types in ArchiveWrapper and PassWrapper
Diffstat (limited to 'src/rustllvm')
-rw-r--r--src/rustllvm/ArchiveWrapper.cpp98
-rw-r--r--src/rustllvm/PassWrapper.cpp138
-rw-r--r--src/rustllvm/README14
-rw-r--r--src/rustllvm/rustllvm.h5
4 files changed, 196 insertions, 59 deletions
diff --git a/src/rustllvm/ArchiveWrapper.cpp b/src/rustllvm/ArchiveWrapper.cpp
index 3d48024c879..059cc40d511 100644
--- a/src/rustllvm/ArchiveWrapper.cpp
+++ b/src/rustllvm/ArchiveWrapper.cpp
@@ -16,24 +16,62 @@
 using namespace llvm;
 using namespace llvm::object;
 
-struct LLVMRustArchiveMember {
+struct RustArchiveMember {
   const char *filename;
   const char *name;
   Archive::Child child;
 
-  LLVMRustArchiveMember(): filename(NULL), name(NULL),
+  RustArchiveMember(): filename(NULL), name(NULL),
 #if LLVM_VERSION_MINOR >= 8
     child(NULL, NULL, NULL)
 #else
     child(NULL, NULL)
 #endif
   {}
-  ~LLVMRustArchiveMember() {}
+  ~RustArchiveMember() {}
 };
 
-typedef OwningBinary<Archive> RustArchive;
 
-extern "C" void*
+struct RustArchiveIterator {
+    Archive::child_iterator cur;
+    Archive::child_iterator end;
+#if LLVM_VERSION_MINOR >= 9
+    Error err;
+#endif
+};
+
+enum class LLVMRustArchiveKind {
+    Other,
+    GNU,
+    MIPS64,
+    BSD,
+    COFF,
+};
+
+static Archive::Kind
+from_rust(LLVMRustArchiveKind kind)
+{
+    switch (kind) {
+    case LLVMRustArchiveKind::GNU:
+        return Archive::K_GNU;
+    case LLVMRustArchiveKind::MIPS64:
+        return Archive::K_MIPS64;
+    case LLVMRustArchiveKind::BSD:
+        return Archive::K_BSD;
+    case LLVMRustArchiveKind::COFF:
+        return Archive::K_COFF;
+    default:
+        abort();
+  }
+}
+
+typedef OwningBinary<Archive> *LLVMRustArchiveRef;
+typedef RustArchiveMember *LLVMRustArchiveMemberRef;
+typedef Archive::Child *LLVMRustArchiveChildRef;
+typedef Archive::Child const *LLVMRustArchiveChildConstRef;
+typedef RustArchiveIterator *LLVMRustArchiveIteratorRef;
+
+extern "C" LLVMRustArchiveRef
 LLVMRustOpenArchive(char *path) {
     ErrorOr<std::unique_ptr<MemoryBuffer>> buf_or = MemoryBuffer::getFile(path,
                                                                           -1,
@@ -66,20 +104,12 @@ LLVMRustOpenArchive(char *path) {
 }
 
 extern "C" void
-LLVMRustDestroyArchive(RustArchive *ar) {
+LLVMRustDestroyArchive(LLVMRustArchiveRef ar) {
     delete ar;
 }
 
-struct RustArchiveIterator {
-    Archive::child_iterator cur;
-    Archive::child_iterator end;
-#if LLVM_VERSION_MINOR >= 9
-    Error err;
-#endif
-};
-
-extern "C" RustArchiveIterator*
-LLVMRustArchiveIteratorNew(RustArchive *ra) {
+extern "C" LLVMRustArchiveIteratorRef
+LLVMRustArchiveIteratorNew(LLVMRustArchiveRef ra) {
     Archive *ar = ra->getBinary();
     RustArchiveIterator *rai = new RustArchiveIterator();
 #if LLVM_VERSION_MINOR <= 8
@@ -95,8 +125,8 @@ LLVMRustArchiveIteratorNew(RustArchive *ra) {
     return rai;
 }
 
-extern "C" const Archive::Child*
-LLVMRustArchiveIteratorNext(RustArchiveIterator *rai) {
+extern "C" LLVMRustArchiveChildConstRef
+LLVMRustArchiveIteratorNext(LLVMRustArchiveIteratorRef rai) {
 #if LLVM_VERSION_MINOR >= 9
     if (rai->err) {
         LLVMRustSetLastError(toString(std::move(rai->err)).c_str());
@@ -122,17 +152,17 @@ LLVMRustArchiveIteratorNext(RustArchiveIterator *rai) {
 }
 
 extern "C" void
-LLVMRustArchiveChildFree(Archive::Child *child) {
+LLVMRustArchiveChildFree(LLVMRustArchiveChildRef child) {
     delete child;
 }
 
 extern "C" void
-LLVMRustArchiveIteratorFree(RustArchiveIterator *rai) {
+LLVMRustArchiveIteratorFree(LLVMRustArchiveIteratorRef rai) {
     delete rai;
 }
 
 extern "C" const char*
-LLVMRustArchiveChildName(const Archive::Child *child, size_t *size) {
+LLVMRustArchiveChildName(LLVMRustArchiveChildConstRef child, size_t *size) {
     ErrorOr<StringRef> name_or_err = child->getName();
     if (name_or_err.getError())
         return NULL;
@@ -142,7 +172,7 @@ LLVMRustArchiveChildName(const Archive::Child *child, size_t *size) {
 }
 
 extern "C" const char*
-LLVMRustArchiveChildData(Archive::Child *child, size_t *size) {
+LLVMRustArchiveChildData(LLVMRustArchiveChildRef child, size_t *size) {
     StringRef buf;
     ErrorOr<StringRef> buf_or_err = child->getBuffer();
     if (buf_or_err.getError()) {
@@ -154,9 +184,10 @@ LLVMRustArchiveChildData(Archive::Child *child, size_t *size) {
     return buf.data();
 }
 
-extern "C" LLVMRustArchiveMember*
-LLVMRustArchiveMemberNew(char *Filename, char *Name, Archive::Child *child) {
-    LLVMRustArchiveMember *Member = new LLVMRustArchiveMember;
+extern "C" LLVMRustArchiveMemberRef
+LLVMRustArchiveMemberNew(char *Filename, char *Name,
+			 LLVMRustArchiveChildRef child) {
+    RustArchiveMember *Member = new RustArchiveMember;
     Member->filename = Filename;
     Member->name = Name;
     if (child)
@@ -165,22 +196,23 @@ LLVMRustArchiveMemberNew(char *Filename, char *Name, Archive::Child *child) {
 }
 
 extern "C" void
-LLVMRustArchiveMemberFree(LLVMRustArchiveMember *Member) {
+LLVMRustArchiveMemberFree(LLVMRustArchiveMemberRef Member) {
     delete Member;
 }
 
-extern "C" int
+extern "C" LLVMRustResult
 LLVMRustWriteArchive(char *Dst,
                      size_t NumMembers,
-                     const LLVMRustArchiveMember **NewMembers,
+                     const LLVMRustArchiveMemberRef *NewMembers,
                      bool WriteSymbtab,
-                     Archive::Kind Kind) {
+                     LLVMRustArchiveKind rust_kind) {
 
 #if LLVM_VERSION_MINOR <= 8
   std::vector<NewArchiveIterator> Members;
 #else
   std::vector<NewArchiveMember> Members;
 #endif
+  auto Kind = from_rust(rust_kind);
 
   for (size_t i = 0; i < NumMembers; i++) {
     auto Member = NewMembers[i];
@@ -190,7 +222,7 @@ LLVMRustWriteArchive(char *Dst,
       Expected<NewArchiveMember> MOrErr = NewArchiveMember::getFile(Member->filename, true);
       if (!MOrErr) {
         LLVMRustSetLastError(toString(MOrErr.takeError()).c_str());
-        return -1;
+        return LLVMRustResult::Failure;
       }
       Members.push_back(std::move(*MOrErr));
 #elif LLVM_VERSION_MINOR == 8
@@ -205,7 +237,7 @@ LLVMRustWriteArchive(char *Dst,
       Expected<NewArchiveMember> MOrErr = NewArchiveMember::getOldMember(Member->child, true);
       if (!MOrErr) {
         LLVMRustSetLastError(toString(MOrErr.takeError()).c_str());
-        return -1;
+        return LLVMRustResult::Failure;
       }
       Members.push_back(std::move(*MOrErr));
 #endif
@@ -217,7 +249,7 @@ LLVMRustWriteArchive(char *Dst,
   auto pair = writeArchive(Dst, Members, WriteSymbtab, Kind, true);
 #endif
   if (!pair.second)
-    return 0;
+    return LLVMRustResult::Success;
   LLVMRustSetLastError(pair.second.message().c_str());
-  return -1;
+  return LLVMRustResult::Failure;
 }
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
index a1276060271..9e72724d8ab 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/src/rustllvm/PassWrapper.cpp
@@ -54,41 +54,48 @@ LLVMInitializePasses() {
   initializeTarget(Registry);
 }
 
-
-enum class SupportedPassKind {
+enum class LLVMRustPassKind {
+  Other,
   Function,
   Module,
-  Unsupported
 };
 
-extern "C" Pass*
+static LLVMRustPassKind
+to_rust(PassKind kind)
+{
+  switch (kind) {
+  case PT_Function:
+      return LLVMRustPassKind::Function;
+  case PT_Module:
+      return LLVMRustPassKind::Module;
+  default:
+      return LLVMRustPassKind::Other;
+  }
+}
+
+extern "C" LLVMPassRef
 LLVMRustFindAndCreatePass(const char *PassName) {
     StringRef SR(PassName);
     PassRegistry *PR = PassRegistry::getPassRegistry();
 
     const PassInfo *PI = PR->getPassInfo(SR);
     if (PI) {
-        return PI->createPass();
+      return wrap(PI->createPass());
     }
     return NULL;
 }
 
-extern "C" SupportedPassKind
-LLVMRustPassKind(Pass *pass) {
-    assert(pass);
-    PassKind passKind = pass->getPassKind();
-    if (passKind == PT_Module) {
-        return SupportedPassKind::Module;
-    } else if (passKind == PT_Function) {
-        return SupportedPassKind::Function;
-    } else {
-        return SupportedPassKind::Unsupported;
-    }
+extern "C" LLVMRustPassKind
+LLVMRustPassKind(LLVMPassRef rust_pass) {
+    assert(rust_pass);
+    Pass *pass = unwrap(rust_pass);
+    return to_rust(pass->getPassKind());
 }
 
 extern "C" void
-LLVMRustAddPass(LLVMPassManagerRef PM, Pass *pass) {
-    assert(pass);
+LLVMRustAddPass(LLVMPassManagerRef PM, LLVMPassRef rust_pass) {
+    assert(rust_pass);
+    Pass *pass = unwrap(rust_pass);
     PassManagerBase *pm = unwrap(PM);
     pm->add(pass);
 }
@@ -162,13 +169,69 @@ LLVMRustHasFeature(LLVMTargetMachineRef TM,
     return (Bits & FeatureEntry->Value) == FeatureEntry->Value;
 }
 
+enum class LLVMRustCodeModel {
+    Other,
+    Default,
+    JITDefault,
+    Small,
+    Kernel,
+    Medium,
+    Large,
+};
+
+static CodeModel::Model
+from_rust(LLVMRustCodeModel model)
+{
+    switch (model) {
+    case LLVMRustCodeModel::Default:
+        return CodeModel::Default;
+    case LLVMRustCodeModel::JITDefault:
+        return CodeModel::JITDefault;
+    case LLVMRustCodeModel::Small:
+        return CodeModel::Small;
+    case LLVMRustCodeModel::Kernel:
+        return CodeModel::Kernel;
+    case LLVMRustCodeModel::Medium:
+        return CodeModel::Medium;
+    case LLVMRustCodeModel::Large:
+        return CodeModel::Large;
+    default:
+        abort();
+  }
+}
+
+enum class LLVMRustCodeGenOptLevel {
+    Other,
+    None,
+    Less,
+    Default,
+    Aggressive,
+};
+
+static CodeGenOpt::Level
+from_rust(LLVMRustCodeGenOptLevel level)
+{
+    switch (level) {
+    case LLVMRustCodeGenOptLevel::None:
+        return CodeGenOpt::None;
+    case LLVMRustCodeGenOptLevel::Less:
+        return CodeGenOpt::Less;
+    case LLVMRustCodeGenOptLevel::Default:
+        return CodeGenOpt::Default;
+    case LLVMRustCodeGenOptLevel::Aggressive:
+        return CodeGenOpt::Aggressive;
+    default:
+        abort();
+  }
+}
+
 extern "C" LLVMTargetMachineRef
 LLVMRustCreateTargetMachine(const char *triple,
                             const char *cpu,
                             const char *feature,
-                            CodeModel::Model CM,
+                            LLVMRustCodeModel rust_CM,
                             LLVMRelocMode Reloc,
-                            CodeGenOpt::Level OptLevel,
+                            LLVMRustCodeGenOptLevel rust_OptLevel,
                             bool UseSoftFloat,
                             bool PositionIndependentExecutable,
                             bool FunctionSections,
@@ -179,6 +242,9 @@ LLVMRustCreateTargetMachine(const char *triple,
 #else
     Optional<Reloc::Model> RM;
 #endif
+    auto CM = from_rust(rust_CM);
+    auto OptLevel = from_rust(rust_OptLevel);
+
     switch (Reloc){
         case LLVMRelocStatic:
             RM = Reloc::Static;
@@ -251,14 +317,14 @@ LLVMRustAddAnalysisPasses(LLVMTargetMachineRef TM,
 
 extern "C" void
 LLVMRustConfigurePassManagerBuilder(LLVMPassManagerBuilderRef PMB,
-                                    CodeGenOpt::Level OptLevel,
+				    LLVMRustCodeGenOptLevel OptLevel,
                                     bool MergeFunctions,
                                     bool SLPVectorize,
                                     bool LoopVectorize) {
     // Ignore mergefunc for now as enabling it causes crashes.
     //unwrap(PMB)->MergeFunctions = MergeFunctions;
     unwrap(PMB)->SLPVectorize = SLPVectorize;
-    unwrap(PMB)->OptLevel = OptLevel;
+    unwrap(PMB)->OptLevel = from_rust(OptLevel);
     unwrap(PMB)->LoopVectorize = LoopVectorize;
 }
 
@@ -314,13 +380,33 @@ LLVMRustSetLLVMOptions(int Argc, char **Argv) {
     cl::ParseCommandLineOptions(Argc, Argv);
 }
 
-extern "C" bool
+enum class LLVMRustFileType {
+    Other,
+    AssemblyFile,
+    ObjectFile,
+};
+
+static TargetMachine::CodeGenFileType
+from_rust(LLVMRustFileType type)
+{
+    switch (type) {
+    case LLVMRustFileType::AssemblyFile:
+        return TargetMachine::CGFT_AssemblyFile;
+    case LLVMRustFileType::ObjectFile:
+        return TargetMachine::CGFT_ObjectFile;
+    default:
+        abort();
+  }
+}
+
+extern "C" LLVMRustResult
 LLVMRustWriteOutputFile(LLVMTargetMachineRef Target,
                         LLVMPassManagerRef PMR,
                         LLVMModuleRef M,
                         const char *path,
-                        TargetMachine::CodeGenFileType FileType) {
+                        LLVMRustFileType rust_FileType) {
   llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR);
+  auto FileType = from_rust(rust_FileType);
 
   std::string ErrorInfo;
   std::error_code EC;
@@ -329,7 +415,7 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target,
     ErrorInfo = EC.message();
   if (ErrorInfo != "") {
     LLVMRustSetLastError(ErrorInfo.c_str());
-    return false;
+    return LLVMRustResult::Failure;
   }
 
   unwrap(Target)->addPassesToEmitFile(*PM, OS, FileType, false);
@@ -339,7 +425,7 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target,
   // stream (OS), so the only real safe place to delete this is here? Don't we
   // wish this was written in Rust?
   delete PM;
-  return true;
+  return LLVMRustResult::Success;
 }
 
 extern "C" void
diff --git a/src/rustllvm/README b/src/rustllvm/README
index c0db3f68a76..e1c6dd07d2b 100644
--- a/src/rustllvm/README
+++ b/src/rustllvm/README
@@ -1,2 +1,16 @@
 This directory currently contains some LLVM support code. This will generally
 be sent upstream to LLVM in time; for now it lives here.
+
+NOTE: the LLVM C++ ABI is subject to between-version breakage and must *never*
+be exposed to Rust. To allow for easy auditing of that, all Rust-exposed types
+must be typedef-ed as "LLVMXyz", or "LLVMRustXyz" if they were defined here.
+
+Functions that return a failure status and leave the error in
+the LLVM last error should return an LLVMRustResult rather than an
+int or anything to avoid confusion.
+
+When translating enums, add a single `Other` variant as the first
+one to allow for new variants to be added. It should abort when used
+as an input.
+
+All other types must not be typedef-ed as such.
diff --git a/src/rustllvm/rustllvm.h b/src/rustllvm/rustllvm.h
index 2a47e8b0895..5aae11fb456 100644
--- a/src/rustllvm/rustllvm.h
+++ b/src/rustllvm/rustllvm.h
@@ -58,6 +58,11 @@
 
 void LLVMRustSetLastError(const char*);
 
+enum class LLVMRustResult {
+    Success,
+    Failure
+};
+
 typedef struct OpaqueRustString *RustStringRef;
 typedef struct LLVMOpaqueTwine *LLVMTwineRef;
 typedef struct LLVMOpaqueDebugLoc *LLVMDebugLocRef;