diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -5159,15 +5159,18 @@ Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Section", llvm::MDString::get(VMContext, Section)); + auto Int8Ty = llvm::Type::getInt8Ty(VMContext); if (CGM.getLangOpts().getGC() == LangOptions::NonGC) { // Non-GC overrides those files which specify GC. - Mod.addModuleFlag(llvm::Module::Override, - "Objective-C Garbage Collection", (uint32_t)0); + Mod.addModuleFlag(llvm::Module::Error, + "Objective-C Garbage Collection", + llvm::ConstantInt::get(Int8Ty,0)); } else { // Add the ObjC garbage collection value. Mod.addModuleFlag(llvm::Module::Error, "Objective-C Garbage Collection", - eImageInfo_GarbageCollected); + llvm::ConstantInt::get(Int8Ty, + (uint8_t)eImageInfo_GarbageCollected)); if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) { // Add the ObjC GC Only value. @@ -5178,7 +5181,7 @@ llvm::Metadata *Ops[2] = { llvm::MDString::get(VMContext, "Objective-C Garbage Collection"), llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( - llvm::Type::getInt32Ty(VMContext), eImageInfo_GarbageCollected))}; + Int8Ty, eImageInfo_GarbageCollected))}; Mod.addModuleFlag(llvm::Module::Require, "Objective-C GC Only", llvm::MDNode::get(VMContext, Ops)); } diff --git a/clang/test/CodeGenObjC/image-info.m b/clang/test/CodeGenObjC/image-info.m --- a/clang/test/CodeGenObjC/image-info.m +++ b/clang/test/CodeGenObjC/image-info.m @@ -8,10 +8,10 @@ // CHECK-FRAGILE: !{{[0-9]+}} = !{i32 1, !"Objective-C Version", i32 1} // CHECK-FRAGILE-NEXT: !{{[0-9]+}} = !{i32 1, !"Objective-C Image Info Version", i32 0} // CHECK-FRAGILE-NEXT: !{{[0-9]+}} = !{i32 1, !"Objective-C Image Info Section", !"__OBJC,__image_info,regular"} -// CHECK-FRAGILE-NEXT: !{{[0-9]+}} = !{i32 4, !"Objective-C Garbage Collection", i32 0} +// CHECK-FRAGILE-NEXT: !{{[0-9]+}} = !{i32 1, !"Objective-C Garbage Collection", i8 0} // CHECK-NONFRAGILE: !llvm.module.flags = !{{{.*}}} // CHECK-NONFRAGILE: !{{[0-9]+}} = !{i32 1, !"Objective-C Version", i32 2} // CHECK-NONFRAGILE-NEXT: !{{[0-9]+}} = !{i32 1, !"Objective-C Image Info Version", i32 0} // CHECK-NONFRAGILE-NEXT: !{{[0-9]+}} = !{i32 1, !"Objective-C Image Info Section", !"__DATA,__objc_imageinfo,regular,no_dead_strip"} -// CHECK-NONFRAGILE-NEXT: !{{[0-9]+}} = !{i32 4, !"Objective-C Garbage Collection", i32 0} +// CHECK-NONFRAGILE-NEXT: !{{[0-9]+}} = !{i32 1, !"Objective-C Garbage Collection", i8 0} diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp --- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -84,6 +84,15 @@ } else if (Key == "Objective-C Image Info Section") { Section = cast(MFE.Val)->getString(); } + // Backend generates L_OBJC_IMAGE_INFO from Swift ABI version + major + minor + + // "Objective-C Garbage Collection". + else if (Key == "Swift ABI Version") { + Flags |= (mdconst::extract(MFE.Val)->getZExtValue()) << 8; + } else if (Key == "Swift Major Version") { + Flags |= (mdconst::extract(MFE.Val)->getZExtValue()) << 24; + } else if (Key == "Swift Minor Version") { + Flags |= (mdconst::extract(MFE.Val)->getZExtValue()) << 16; + } } } diff --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp --- a/llvm/lib/IR/AutoUpgrade.cpp +++ b/llvm/lib/IR/AutoUpgrade.cpp @@ -4022,6 +4022,12 @@ return false; bool HasObjCFlag = false, HasClassProperties = false, Changed = false; + bool HasSwiftVersionFlag = false; + uint8_t SwiftMajorVersion, SwiftMinorVersion; + uint32_t SwiftABIVersion; + auto Int8Ty = Type::getInt8Ty(M.getContext()); + auto Int32Ty = Type::getInt32Ty(M.getContext()); + for (unsigned I = 0, E = ModFlags->getNumOperands(); I != E; ++I) { MDNode *Op = ModFlags->getOperand(I); if (Op->getNumOperands() != 3) @@ -4067,6 +4073,31 @@ } } } + + // IRUpgrader turns a i32 type "Objective-C Garbage Collection" into i8 value. + // If the higher bits are set, it adds new module flag for swift info. + if (ID->getString() == "Objective-C Garbage Collection") { + auto Md = dyn_cast(Op->getOperand(2)); + if (Md) { + assert(Md->getValue() && "Expected non-empty metadata"); + auto Type = Md->getValue()->getType(); + if (Type == Int8Ty) + continue; + unsigned Val = Md->getValue()->getUniqueInteger().getZExtValue(); + if ((Val & 0xff) != Val) { + HasSwiftVersionFlag = true; + SwiftABIVersion = (Val & 0xff00) >> 8; + SwiftMajorVersion = (Val & 0xff000000) >> 24; + SwiftMinorVersion = (Val & 0xff0000) >> 16; + } + Metadata *Ops[3] = { + ConstantAsMetadata::get(ConstantInt::get(Int32Ty,Module::Error)), + Op->getOperand(1), + ConstantAsMetadata::get(ConstantInt::get(Int8Ty,Val & 0xff))}; + ModFlags->setOperand(I, MDNode::get(M.getContext(), Ops)); + Changed = true; + } + } } // "Objective-C Class Properties" is recently added for Objective-C. We @@ -4080,6 +4111,16 @@ Changed = true; } + if (HasSwiftVersionFlag) { + M.addModuleFlag(Module::Error, "Swift ABI Version", + SwiftABIVersion); + M.addModuleFlag(Module::Error, "Swift Major Version", + ConstantInt::get(Int8Ty, SwiftMajorVersion)); + M.addModuleFlag(Module::Error, "Swift Minor Version", + ConstantInt::get(Int8Ty, SwiftMinorVersion)); + Changed = true; + } + return Changed; } diff --git a/llvm/test/Bitcode/upgrade-garbage-collection-for-objc.ll b/llvm/test/Bitcode/upgrade-garbage-collection-for-objc.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Bitcode/upgrade-garbage-collection-for-objc.ll @@ -0,0 +1,21 @@ +; RUN: llvm-as %s -o - | llvm-dis - | FileCheck %s + +; The IRUpgrader turns a i32 type "Objective-C Garbage Collection" +; into i8 value. + +target triple = "x86_64-apple-macosx10.15.0" + +!llvm.module.flags = !{!0, !1, !2, !3, !4, !5, !6, !7} +!llvm.ident = !{!8} + +!0 = !{i32 2, !"SDK Version", [2 x i32] [i32 10, i32 15]} +!1 = !{i32 1, !"Objective-C Version", i32 2} +!2 = !{i32 1, !"Objective-C Image Info Version", i32 0} +!3 = !{i32 1, !"Objective-C Image Info Section", !"__DATA,__objc_imageinfo,regular,no_dead_strip"} +!4 = !{i32 1, !"Objective-C Garbage Collection", i32 0} +!5 = !{i32 1, !"Objective-C Class Properties", i32 64} +!6 = !{i32 1, !"wchar_size", i32 4} +!7 = !{i32 7, !"PIC Level", i32 2} +!8 = !{!"Apple clang version 11.0.0 (clang-1100.0.33.12)"} + +; CHECK: !{{[0-9]+}} = !{i32 1, !"Objective-C Garbage Collection", i8 0} diff --git a/llvm/test/Bitcode/upgrade-garbage-collection-for-swift.ll b/llvm/test/Bitcode/upgrade-garbage-collection-for-swift.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Bitcode/upgrade-garbage-collection-for-swift.ll @@ -0,0 +1,41 @@ +; RUN: llvm-as %s -o - | llvm-dis - | FileCheck %s + +; The IRUpgrader turns a i32 type "Objective-C Garbage Collection" +; into i8 value. If the higher bits are set, it adds the module flag for swift info. + +target triple = "x86_64-apple-macosx10.15.0" + +@__swift_reflection_version = linkonce_odr hidden constant i16 3 +@llvm.used = appending global [1 x i8*] [i8* bitcast (i16* @__swift_reflection_version to i8*)], section "llvm.metadata", align 8 + +define i32 @main(i32 %0, i8** %1) #0 { + %3 = bitcast i8** %1 to i8* + ret i32 0 +} + +attributes #0 = { "frame-pointer"="all" "target-cpu"="penryn" "target-features"="+cx16,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" } + +!llvm.module.flags = !{!0, !1, !2, !3, !4, !5, !6, !7, !8} +!swift.module.flags = !{!9} +!llvm.linker.options = !{!10, !11, !12} +!llvm.asan.globals = !{!13} + +!0 = !{i32 2, !"SDK Version", [2 x i32] [i32 10, i32 15]} +!1 = !{i32 1, !"Objective-C Version", i32 2} +!2 = !{i32 1, !"Objective-C Image Info Version", i32 0} +!3 = !{i32 1, !"Objective-C Image Info Section", !"__DATA,__objc_imageinfo,regular,no_dead_strip"} +!4 = !{i32 4, !"Objective-C Garbage Collection", i32 83953408} +!5 = !{i32 1, !"Objective-C Class Properties", i32 64} +!6 = !{i32 1, !"wchar_size", i32 4} +!7 = !{i32 7, !"PIC Level", i32 2} +!8 = !{i32 1, !"Swift Version", i32 7} +!9 = !{!"standard-library", i1 false} +!10 = !{!"-lswiftSwiftOnoneSupport"} +!11 = !{!"-lswiftCore"} +!12 = !{!"-lobjc"} +!13 = !{[1 x i8*]* @llvm.used, null, null, i1 false, i1 true} + +; CHECK: !{{[0-9]+}} = !{i32 1, !"Objective-C Garbage Collection", i8 0} +; CHECK: !{{[0-9]+}} = !{i32 1, !"Swift ABI Version", i32 7} +; CHECK: !{{[0-9]+}} = !{i32 1, !"Swift Major Version", i8 5} +; CHECK: !{{[0-9]+}} = !{i32 1, !"Swift Minor Version", i8 1} diff --git a/llvm/test/Linker/Inputs/empty-objc.ll b/llvm/test/Linker/Inputs/empty-objc.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Linker/Inputs/empty-objc.ll @@ -0,0 +1,14 @@ +target triple = "x86_64-apple-macosx10.15.0" + +!llvm.module.flags = !{!0, !1, !2, !3, !4, !5, !6, !7} +!llvm.ident = !{!8} + +!0 = !{i32 2, !"SDK Version", [2 x i32] [i32 10, i32 15]} +!1 = !{i32 1, !"Objective-C Version", i32 2} +!2 = !{i32 1, !"Objective-C Image Info Version", i32 0} +!3 = !{i32 1, !"Objective-C Image Info Section", !"__DATA,__objc_imageinfo,regular,no_dead_strip"} +!4 = !{i32 1, !"Objective-C Garbage Collection", i32 0} +!5 = !{i32 1, !"Objective-C Class Properties", i32 64} +!6 = !{i32 1, !"wchar_size", i32 4} +!7 = !{i32 7, !"PIC Level", i32 2} +!8 = !{!"Apple clang version 11.0.0 (clang-1100.0.33.12)"} diff --git a/llvm/test/Linker/empty-swift.ll b/llvm/test/Linker/empty-swift.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Linker/empty-swift.ll @@ -0,0 +1,42 @@ +; RUN: llvm-link %s %p/Inputs/empty-objc.ll -S | FileCheck %s + +; It tests whether Swift bitcode can be successfully linked with Objecitive-C bitcode. +; During the process, the IRUpgrader turns a i32 type "Objective-C Garbage Collection" +; into i8 value. If the higher bits are set, it adds the module flag for swift info. + +target triple = "x86_64-apple-macosx10.15.0" + +@__swift_reflection_version = linkonce_odr hidden constant i16 3 +@llvm.used = appending global [1 x i8*] [i8* bitcast (i16* @__swift_reflection_version to i8*)], section "llvm.metadata", align 8 + +define i32 @main(i32 %0, i8** %1) #0 { + %3 = bitcast i8** %1 to i8* + ret i32 0 +} + +attributes #0 = { "frame-pointer"="all" "target-cpu"="penryn" "target-features"="+cx16,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" } + +!llvm.module.flags = !{!0, !1, !2, !3, !4, !5, !6, !7, !8} +!swift.module.flags = !{!9} +!llvm.linker.options = !{!10, !11, !12} +!llvm.asan.globals = !{!13} + +!0 = !{i32 2, !"SDK Version", [2 x i32] [i32 10, i32 15]} +!1 = !{i32 1, !"Objective-C Version", i32 2} +!2 = !{i32 1, !"Objective-C Image Info Version", i32 0} +!3 = !{i32 1, !"Objective-C Image Info Section", !"__DATA,__objc_imageinfo,regular,no_dead_strip"} +!4 = !{i32 4, !"Objective-C Garbage Collection", i32 83953408} +!5 = !{i32 1, !"Objective-C Class Properties", i32 64} +!6 = !{i32 1, !"wchar_size", i32 4} +!7 = !{i32 7, !"PIC Level", i32 2} +!8 = !{i32 1, !"Swift Version", i32 7} +!9 = !{!"standard-library", i1 false} +!10 = !{!"-lswiftSwiftOnoneSupport"} +!11 = !{!"-lswiftCore"} +!12 = !{!"-lobjc"} +!13 = !{[1 x i8*]* @llvm.used, null, null, i1 false, i1 true} + +; CHECK: !{{[0-9]+}} = !{i32 1, !"Objective-C Garbage Collection", i8 0} +; CHECK: !{{[0-9]+}} = !{i32 1, !"Swift ABI Version", i32 7} +; CHECK: !{{[0-9]+}} = !{i32 1, !"Swift Major Version", i8 5} +; CHECK: !{{[0-9]+}} = !{i32 1, !"Swift Minor Version", i8 1} diff --git a/llvm/test/Object/objc-swift-mixed-imageinfo-macho.ll b/llvm/test/Object/objc-swift-mixed-imageinfo-macho.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Object/objc-swift-mixed-imageinfo-macho.ll @@ -0,0 +1,46 @@ +; RUN: llc -mtriple x86_64-apple-ios -filetype asm -o - %s | FileCheck %s +; REQUIRES: x86-registered-target + +; It checks whether the backend generates IMAGE_INFO from Swift ABI version + major + minor + "Objective-C Garbage Collection". + +target triple = "x86_64-apple-macosx10.15.0" + +@llvm.used = appending global [1 x i8*] [i8* bitcast (i16* @__swift_reflection_version to i8*)], section "llvm.metadata", align 8 +@__swift_reflection_version = linkonce_odr hidden constant i16 3 + +define i32 @main(i32 %0, i8** %1) #0 { + %3 = bitcast i8** %1 to i8* + ret i32 0 +} + +attributes #0 = { "frame-pointer"="all" "target-cpu"="penryn" "target-features"="+cx16,+fxsr,+mmx,+sahf,+sse,+sse2,+sse3,+sse4.1,+ssse3,+x87" } + +!swift.module.flags = !{!0} +!llvm.linker.options = !{!1, !2, !3} +!llvm.asan.globals = !{!4} +!llvm.module.flags = !{!5, !6, !7, !8, !9, !10, !11, !12, !13, !14, !15, !16} +!llvm.ident = !{!17} + +!0 = !{!"standard-library", i1 false} +!1 = !{!"-lswiftSwiftOnoneSupport"} +!2 = !{!"-lswiftCore"} +!3 = !{!"-lobjc"} +!4 = !{[1 x i8*]* @llvm.used, null, null, i1 false, i1 true} +!5 = !{i32 2, !"SDK Version", [2 x i32] [i32 10, i32 15]} +!6 = !{i32 1, !"Objective-C Version", i32 2} +!7 = !{i32 1, !"Objective-C Image Info Version", i32 0} +!8 = !{i32 1, !"Objective-C Image Info Section", !"__DATA,__objc_imageinfo,regular,no_dead_strip"} +!9 = !{i32 1, !"Objective-C Garbage Collection", i8 0} +!10 = !{i32 1, !"Objective-C Class Properties", i32 64} +!11 = !{i32 1, !"wchar_size", i32 4} +!12 = !{i32 7, !"PIC Level", i32 2} +!13 = !{i32 1, !"Swift Version", i32 7} +!14 = !{i32 1, !"Swift ABI Version", i32 7} +!15 = !{i32 1, !"Swift Major Version", i8 5} +!16 = !{i32 1, !"Swift Minor Version", i8 1} +!17 = !{!"Apple clang version 11.0.0 (clang-1100.0.33.12)"} + +; CHECK: .section __DATA,__objc_imageinfo,regular,no_dead_strip +; CHECK: L_OBJC_IMAGE_INFO: +; CHECK: .long 0 +; CHECK: .long 83953472