about summary refs log tree commit diff
path: root/src/rustllvm/RustWrapper.cpp
diff options
context:
space:
mode:
authorJeremy Soller <jackpot51@gmail.com>2016-12-12 14:55:09 -0700
committerJeremy Soller <jackpot51@gmail.com>2016-12-12 14:55:09 -0700
commit7e7775ce7bfc916ce723bd1fdaf4ae54662c6627 (patch)
tree235a9c38e42bacdb671da33bc49ffc8a4aba17a4 /src/rustllvm/RustWrapper.cpp
parentc61baa0fc7a85bd2bcce34aac05ed739261cf037 (diff)
parent6483bdd860fd89fc68846d4cc94c7ae3307a84c1 (diff)
downloadrust-7e7775ce7bfc916ce723bd1fdaf4ae54662c6627.tar.gz
rust-7e7775ce7bfc916ce723bd1fdaf4ae54662c6627.zip
Merge branch 'master' into redox
Diffstat (limited to 'src/rustllvm/RustWrapper.cpp')
-rw-r--r--src/rustllvm/RustWrapper.cpp186
1 files changed, 167 insertions, 19 deletions
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index b035e134e37..ae2ab932a61 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -352,6 +352,91 @@ DIT* unwrapDIptr(LLVMRustMetadataRef ref) {
 #define DIArray DINodeArray
 #define unwrapDI unwrapDIptr
 
+// These values **must** match debuginfo::DIFlags! They also *happen*
+// to match LLVM, but that isn't required as we do giant sets of
+// matching below. The value shouldn't be directly passed to LLVM.
+enum class LLVMRustDIFlags : uint32_t {
+    FlagZero                = 0,
+    FlagPrivate             = 1,
+    FlagProtected           = 2,
+    FlagPublic              = 3,
+    FlagFwdDecl             = (1 << 2),
+    FlagAppleBlock          = (1 << 3),
+    FlagBlockByrefStruct    = (1 << 4),
+    FlagVirtual             = (1 << 5),
+    FlagArtificial          = (1 << 6),
+    FlagExplicit            = (1 << 7),
+    FlagPrototyped          = (1 << 8),
+    FlagObjcClassComplete   = (1 << 9),
+    FlagObjectPointer       = (1 << 10),
+    FlagVector              = (1 << 11),
+    FlagStaticMember        = (1 << 12),
+    FlagLValueReference     = (1 << 13),
+    FlagRValueReference     = (1 << 14),
+    // Do not add values that are not supported by the minimum LLVM
+    // version we support!
+};
+
+inline LLVMRustDIFlags operator& (LLVMRustDIFlags a, LLVMRustDIFlags b) {
+    return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(a) & static_cast<uint32_t>(b));
+}
+
+inline LLVMRustDIFlags operator| (LLVMRustDIFlags a, LLVMRustDIFlags b) {
+    return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(a) | static_cast<uint32_t>(b));
+}
+
+inline LLVMRustDIFlags& operator|= (LLVMRustDIFlags& a, LLVMRustDIFlags b) {
+    return a = a | b;
+}
+
+inline bool is_set(LLVMRustDIFlags f) {
+    return f != LLVMRustDIFlags::FlagZero;
+}
+
+inline LLVMRustDIFlags visibility(LLVMRustDIFlags f) {
+    return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(f) & 0x3);
+}
+
+#if LLVM_VERSION_GE(4, 0)
+static DINode::DIFlags from_rust(LLVMRustDIFlags flags) {
+    DINode::DIFlags result = DINode::DIFlags::FlagZero;
+#else
+static unsigned from_rust(LLVMRustDIFlags flags) {
+    unsigned result = 0;
+#endif
+
+    switch (visibility(flags)) {
+    case LLVMRustDIFlags::FlagPrivate:
+        result |= DINode::DIFlags::FlagPrivate;
+        break;
+    case LLVMRustDIFlags::FlagProtected:
+        result |= DINode::DIFlags::FlagProtected;
+        break;
+    case LLVMRustDIFlags::FlagPublic:
+        result |= DINode::DIFlags::FlagPublic;
+        break;
+    default:
+        // The rest are handled below
+        break;
+    }
+
+    if (is_set(flags & LLVMRustDIFlags::FlagFwdDecl))             { result |= DINode::DIFlags::FlagFwdDecl; }
+    if (is_set(flags & LLVMRustDIFlags::FlagAppleBlock))          { result |= DINode::DIFlags::FlagAppleBlock; }
+    if (is_set(flags & LLVMRustDIFlags::FlagBlockByrefStruct))    { result |= DINode::DIFlags::FlagBlockByrefStruct; }
+    if (is_set(flags & LLVMRustDIFlags::FlagVirtual))             { result |= DINode::DIFlags::FlagVirtual; }
+    if (is_set(flags & LLVMRustDIFlags::FlagArtificial))          { result |= DINode::DIFlags::FlagArtificial; }
+    if (is_set(flags & LLVMRustDIFlags::FlagExplicit))            { result |= DINode::DIFlags::FlagExplicit; }
+    if (is_set(flags & LLVMRustDIFlags::FlagPrototyped))          { result |= DINode::DIFlags::FlagPrototyped; }
+    if (is_set(flags & LLVMRustDIFlags::FlagObjcClassComplete))   { result |= DINode::DIFlags::FlagObjcClassComplete; }
+    if (is_set(flags & LLVMRustDIFlags::FlagObjectPointer))       { result |= DINode::DIFlags::FlagObjectPointer; }
+    if (is_set(flags & LLVMRustDIFlags::FlagVector))              { result |= DINode::DIFlags::FlagVector; }
+    if (is_set(flags & LLVMRustDIFlags::FlagStaticMember))        { result |= DINode::DIFlags::FlagStaticMember; }
+    if (is_set(flags & LLVMRustDIFlags::FlagLValueReference))     { result |= DINode::DIFlags::FlagLValueReference; }
+    if (is_set(flags & LLVMRustDIFlags::FlagRValueReference))     { result |= DINode::DIFlags::FlagRValueReference; }
+
+    return result;
+}
+
 extern "C" uint32_t LLVMRustDebugMetadataVersion() {
     return DEBUG_METADATA_VERSION;
 }
@@ -431,7 +516,7 @@ extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateFunction(
     bool isLocalToUnit,
     bool isDefinition,
     unsigned ScopeLine,
-    unsigned Flags,
+    LLVMRustDIFlags Flags,
     bool isOptimized,
     LLVMValueRef Fn,
     LLVMRustMetadataRef TParam,
@@ -443,7 +528,7 @@ extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateFunction(
         unwrapDI<DIScope>(Scope), Name, LinkageName,
         unwrapDI<DIFile>(File), LineNo,
         unwrapDI<DISubroutineType>(Ty), isLocalToUnit, isDefinition, ScopeLine,
-        Flags, isOptimized,
+        from_rust(Flags), isOptimized,
         TParams,
         unwrapDIptr<DISubprogram>(Decl));
     unwrap<Function>(Fn)->setSubprogram(Sub);
@@ -453,7 +538,7 @@ extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateFunction(
         unwrapDI<DIScope>(Scope), Name, LinkageName,
         unwrapDI<DIFile>(File), LineNo,
         unwrapDI<DISubroutineType>(Ty), isLocalToUnit, isDefinition, ScopeLine,
-        Flags, isOptimized,
+        from_rust(Flags), isOptimized,
         unwrap<Function>(Fn),
         unwrapDIptr<MDNode>(TParam),
         unwrapDIptr<MDNode>(Decl)));
@@ -489,7 +574,7 @@ extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateStructType(
     unsigned LineNumber,
     uint64_t SizeInBits,
     uint64_t AlignInBits,
-    unsigned Flags,
+    LLVMRustDIFlags Flags,
     LLVMRustMetadataRef DerivedFrom,
     LLVMRustMetadataRef Elements,
     unsigned RunTimeLang,
@@ -502,7 +587,7 @@ extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateStructType(
         LineNumber,
         SizeInBits,
         AlignInBits,
-        Flags,
+        from_rust(Flags),
         unwrapDI<DIType>(DerivedFrom),
         DINodeArray(unwrapDI<MDTuple>(Elements)),
         RunTimeLang,
@@ -520,12 +605,12 @@ extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateMemberType(
     uint64_t SizeInBits,
     uint64_t AlignInBits,
     uint64_t OffsetInBits,
-    unsigned Flags,
+    LLVMRustDIFlags Flags,
     LLVMRustMetadataRef Ty) {
     return wrap(Builder->createMemberType(
         unwrapDI<DIDescriptor>(Scope), Name,
         unwrapDI<DIFile>(File), LineNo,
-        SizeInBits, AlignInBits, OffsetInBits, Flags,
+        SizeInBits, AlignInBits, OffsetInBits, from_rust(Flags),
         unwrapDI<DIType>(Ty)));
 }
 
@@ -581,7 +666,7 @@ extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateVariable(
     unsigned LineNo,
     LLVMRustMetadataRef Ty,
     bool AlwaysPreserve,
-    unsigned Flags,
+    LLVMRustDIFlags Flags,
     unsigned ArgNo) {
 #if LLVM_VERSION_GE(3, 8)
     if (Tag == 0x100) { // DW_TAG_auto_variable
@@ -589,20 +674,20 @@ extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateVariable(
             unwrapDI<DIDescriptor>(Scope), Name,
             unwrapDI<DIFile>(File),
             LineNo,
-            unwrapDI<DIType>(Ty), AlwaysPreserve, Flags));
+            unwrapDI<DIType>(Ty), AlwaysPreserve, from_rust(Flags)));
     } else {
         return wrap(Builder->createParameterVariable(
             unwrapDI<DIDescriptor>(Scope), Name, ArgNo,
             unwrapDI<DIFile>(File),
             LineNo,
-            unwrapDI<DIType>(Ty), AlwaysPreserve, Flags));
+            unwrapDI<DIType>(Ty), AlwaysPreserve, from_rust(Flags)));
     }
 #else
     return wrap(Builder->createLocalVariable(Tag,
         unwrapDI<DIDescriptor>(Scope), Name,
         unwrapDI<DIFile>(File),
         LineNo,
-        unwrapDI<DIType>(Ty), AlwaysPreserve, Flags, ArgNo));
+        unwrapDI<DIType>(Ty), AlwaysPreserve, from_rust(Flags), ArgNo));
 #endif
 }
 
@@ -701,7 +786,7 @@ extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateUnionType(
     unsigned LineNumber,
     uint64_t SizeInBits,
     uint64_t AlignInBits,
-    unsigned Flags,
+    LLVMRustDIFlags Flags,
     LLVMRustMetadataRef Elements,
     unsigned RunTimeLang,
     const char* UniqueId)
@@ -713,7 +798,7 @@ extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateUnionType(
         LineNumber,
         SizeInBits,
         AlignInBits,
-        Flags,
+        from_rust(Flags),
         DINodeArray(unwrapDI<MDTuple>(Elements)),
         RunTimeLang,
         UniqueId
@@ -747,7 +832,11 @@ extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateNameSpace(
         unwrapDI<DIDescriptor>(Scope),
         Name,
         unwrapDI<DIFile>(File),
-        LineNo));
+        LineNo
+#if LLVM_VERSION_GE(4, 0)
+        , false // ExportSymbols (only relevant for C++ anonymous namespaces)
+#endif
+    ));
 }
 
 extern "C" void LLVMRustDICompositeTypeSetTypeArray(
@@ -803,19 +892,34 @@ extern "C" void LLVMRustWriteValueToString(LLVMValueRef Value, RustStringRef str
 extern "C" bool
 LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) {
     Module *Dst = unwrap(dst);
+
     std::unique_ptr<MemoryBuffer> buf = MemoryBuffer::getMemBufferCopy(StringRef(bc, len));
+
+#if LLVM_VERSION_GE(4, 0)
+    Expected<std::unique_ptr<Module>> SrcOrError =
+        llvm::getLazyBitcodeModule(buf->getMemBufferRef(), Dst->getContext());
+    if (!SrcOrError) {
+        LLVMRustSetLastError(toString(SrcOrError.takeError()).c_str());
+        return false;
+    }
+
+    auto Src = std::move(*SrcOrError);
+#else
     ErrorOr<std::unique_ptr<Module>> Src =
         llvm::getLazyBitcodeModule(std::move(buf), Dst->getContext());
     if (!Src) {
         LLVMRustSetLastError(Src.getError().message().c_str());
         return false;
     }
+#endif
 
     std::string Err;
 
     raw_string_ostream Stream(Err);
     DiagnosticPrinterRawOStream DP(Stream);
-#if LLVM_VERSION_GE(3, 8)
+#if LLVM_VERSION_GE(4, 0)
+    if (Linker::linkModules(*Dst, std::move(Src))) {
+#elif LLVM_VERSION_GE(3, 8)
     if (Linker::linkModules(*Dst, std::move(Src.get()))) {
 #else
     if (Linker::LinkModules(Dst, Src->get(), [&](const DiagnosticInfo &DI) { DI.print(DP); })) {
@@ -868,19 +972,21 @@ LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef str) {
 extern "C" void
 LLVMRustUnpackOptimizationDiagnostic(
     LLVMDiagnosticInfoRef di,
-    const char **pass_name_out,
+    RustStringRef pass_name_out,
     LLVMValueRef *function_out,
     LLVMDebugLocRef *debugloc_out,
-    LLVMTwineRef *message_out)
+    RustStringRef message_out)
 {
     // Undefined to call this not on an optimization diagnostic!
     llvm::DiagnosticInfoOptimizationBase *opt
         = static_cast<llvm::DiagnosticInfoOptimizationBase*>(unwrap(di));
 
-    *pass_name_out = opt->getPassName();
+    raw_rust_string_ostream pass_name_os(pass_name_out);
+    pass_name_os << opt->getPassName();
     *function_out = wrap(&opt->getFunction());
     *debugloc_out = wrap(&opt->getDebugLoc());
-    *message_out = wrap(&opt->getMsg());
+    raw_rust_string_ostream message_os(message_out);
+    message_os << opt->getMsg();
 }
 
 extern "C" void
@@ -1317,3 +1423,45 @@ extern "C" void LLVMRustSetLinkage(LLVMValueRef V, LLVMRustLinkage RustLinkage)
 extern "C" LLVMContextRef LLVMRustGetValueContext(LLVMValueRef V) {
     return wrap(&unwrap(V)->getContext());
 }
+
+enum class LLVMRustVisibility {
+    Default = 0,
+    Hidden = 1,
+    Protected = 2,
+};
+
+static LLVMRustVisibility to_rust(LLVMVisibility vis) {
+    switch (vis) {
+        case LLVMDefaultVisibility:
+            return LLVMRustVisibility::Default;
+        case LLVMHiddenVisibility:
+            return LLVMRustVisibility::Hidden;
+        case LLVMProtectedVisibility:
+            return LLVMRustVisibility::Protected;
+
+        default:
+            llvm_unreachable("Invalid LLVMRustVisibility value!");
+    }
+}
+
+static LLVMVisibility from_rust(LLVMRustVisibility vis) {
+    switch (vis) {
+        case LLVMRustVisibility::Default:
+            return LLVMDefaultVisibility;
+        case LLVMRustVisibility::Hidden:
+            return LLVMHiddenVisibility;
+        case LLVMRustVisibility::Protected:
+            return LLVMProtectedVisibility;
+
+        default:
+            llvm_unreachable("Invalid LLVMRustVisibility value!");
+    }
+}
+
+extern "C" LLVMRustVisibility LLVMRustGetVisibility(LLVMValueRef V) {
+    return to_rust(LLVMGetVisibility(V));
+}
+
+extern "C" void LLVMRustSetVisibility(LLVMValueRef V, LLVMRustVisibility RustVisibility) {
+    LLVMSetVisibility(V, from_rust(RustVisibility));
+}