]> granicus.if.org Git - llvm/commitdiff
CodeGen: add support for emitting ObjC image info
authorSaleem Abdulrasool <compnerd@compnerd.org>
Mon, 5 Jun 2017 21:26:39 +0000 (21:26 +0000)
committerSaleem Abdulrasool <compnerd@compnerd.org>
Mon, 5 Jun 2017 21:26:39 +0000 (21:26 +0000)
This ensures that we can emit the ObjC Image Info structure on COFF and
ELF as well.  The frontend already would attempt to emit this
information but would get dropped when generating assembly or an object
file.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@304736 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
lib/CodeGen/TargetLoweringObjectFileImpl.cpp
test/Object/objc-imageinfo-coff.ll [new file with mode: 0644]
test/Object/objc-imageinfo-elf.ll [new file with mode: 0644]
test/Object/objc-imageinfo-macho.ll [new file with mode: 0644]

index adf2b3ea1c9b3f79883330bf30f1725cda33da8d..106a084a95c00a0f59e7400726a9165bf2fec6eb 100644 (file)
@@ -41,6 +41,11 @@ public:
   TargetLoweringObjectFileELF() = default;
   ~TargetLoweringObjectFileELF() override = default;
 
+  /// Emit Obj-C garbage collection and linker options.
+  void emitModuleFlags(MCStreamer &Streamer,
+                       ArrayRef<Module::ModuleFlagEntry> ModuleFlags,
+                       const TargetMachine &TM) const override;
+
   void emitPersonalityValue(MCStreamer &Streamer, const DataLayout &TM,
                             const MCSymbol *Sym) const override;
 
@@ -149,8 +154,7 @@ public:
   MCSection *getSectionForJumpTable(const Function &F,
                                     const TargetMachine &TM) const override;
 
-  /// Emit Obj-C garbage collection and linker options. Only linker option
-  /// emission is implemented for COFF.
+  /// Emit Obj-C garbage collection and linker options.
   void emitModuleFlags(MCStreamer &Streamer,
                        ArrayRef<Module::ModuleFlagEntry> ModuleFlags,
                        const TargetMachine &TM) const override;
index 3ba4a3a2926226fd05732c611d27ac77fb42eab5..24baa59db5dc857baaab6af97661c2b9a781f9d0 100644 (file)
 using namespace llvm;
 using namespace dwarf;
 
+static void GetObjCImageInfo(ArrayRef<Module::ModuleFlagEntry> ModuleFlags,
+                             unsigned &Version, unsigned &Flags,
+                             StringRef &Section) {
+  for (const auto &MFE: ModuleFlags) {
+    // Ignore flags with 'Require' behaviour.
+    if (MFE.Behavior == Module::Require)
+      continue;
+
+    StringRef Key = MFE.Key->getString();
+    if (Key == "Objective-C Image Info Version") {
+      Version = mdconst::extract<ConstantInt>(MFE.Val)->getZExtValue();
+    } else if (Key == "Objective-C Garbage Collection" ||
+               Key == "Objective-C GC Only" ||
+               Key == "Objective-C Is Simulated" ||
+               Key == "Objective-C Class Properties" ||
+               Key == "Objective-C Image Swift Version") {
+      Flags |= mdconst::extract<ConstantInt>(MFE.Val)->getZExtValue();
+    } else if (Key == "Objective-C Image Info Section") {
+      Section = cast<MDString>(MFE.Val)->getString();
+    }
+  }
+}
+
 //===----------------------------------------------------------------------===//
 //                                  ELF
 //===----------------------------------------------------------------------===//
 
+void TargetLoweringObjectFileELF::emitModuleFlags(
+    MCStreamer &Streamer, ArrayRef<Module::ModuleFlagEntry> ModuleFlags,
+    const TargetMachine &TM) const {
+  unsigned Version = 0;
+  unsigned Flags = 0;
+  StringRef Section;
+
+  GetObjCImageInfo(ModuleFlags, Version, Flags, Section);
+  if (Section.empty())
+    return;
+
+  auto &C = getContext();
+  auto *S = C.getELFSection(Section, ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
+  Streamer.SwitchSection(S);
+  Streamer.EmitLabel(C.getOrCreateSymbol(StringRef("OBJC_IMAGE_INFO")));
+  Streamer.EmitIntValue(Version, 4);
+  Streamer.EmitIntValue(Flags, 4);
+  Streamer.AddBlankLine();
+}
+
 MCSymbol *TargetLoweringObjectFileELF::getCFIPersonalitySymbol(
     const GlobalValue *GV, const TargetMachine &TM,
     MachineModuleInfo *MMI) const {
@@ -579,32 +622,12 @@ void TargetLoweringObjectFileMachO::Initialize(MCContext &Ctx,
 void TargetLoweringObjectFileMachO::emitModuleFlags(
     MCStreamer &Streamer, ArrayRef<Module::ModuleFlagEntry> ModuleFlags,
     const TargetMachine &TM) const {
-  unsigned VersionVal = 0;
-  unsigned ImageInfoFlags = 0;
   MDNode *LinkerOptions = nullptr;
-  StringRef SectionVal;
 
   for (const auto &MFE : ModuleFlags) {
-    // Ignore flags with 'Require' behavior.
-    if (MFE.Behavior == Module::Require)
-      continue;
-
     StringRef Key = MFE.Key->getString();
-    Metadata *Val = MFE.Val;
-
-    if (Key == "Objective-C Image Info Version") {
-      VersionVal = mdconst::extract<ConstantInt>(Val)->getZExtValue();
-    } else if (Key == "Objective-C Garbage Collection" ||
-               Key == "Objective-C GC Only" ||
-               Key == "Objective-C Is Simulated" ||
-               Key == "Objective-C Class Properties" ||
-               Key == "Objective-C Image Swift Version") {
-      ImageInfoFlags |= mdconst::extract<ConstantInt>(Val)->getZExtValue();
-    } else if (Key == "Objective-C Image Info Section") {
-      SectionVal = cast<MDString>(Val)->getString();
-    } else if (Key == "Linker Options") {
-      LinkerOptions = cast<MDNode>(Val);
-    }
+    if (Key == "Linker Options")
+      LinkerOptions = cast<MDNode>(MFE.Val);
   }
 
   // Emit the linker options if present.
@@ -617,8 +640,14 @@ void TargetLoweringObjectFileMachO::emitModuleFlags(
     }
   }
 
+  unsigned VersionVal = 0;
+  unsigned ImageInfoFlags = 0;
+  StringRef SectionVal;
+  GetObjCImageInfo(ModuleFlags, VersionVal, ImageInfoFlags, SectionVal);
+
   // The section is mandatory. If we don't have it, then we don't have GC info.
-  if (SectionVal.empty()) return;
+  if (SectionVal.empty())
+    return;
 
   StringRef Segment, Section;
   unsigned TAA = 0, StubSize = 0;
@@ -1156,6 +1185,24 @@ void TargetLoweringObjectFileCOFF::emitModuleFlags(
       }
     }
   }
+
+  unsigned Version = 0;
+  unsigned Flags = 0;
+  StringRef Section;
+
+  GetObjCImageInfo(ModuleFlags, Version, Flags, Section);
+  if (Section.empty())
+    return;
+
+  auto &C = getContext();
+  auto *S = C.getCOFFSection(
+      Section, COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ,
+      SectionKind::getReadOnly());
+  Streamer.SwitchSection(S);
+  Streamer.EmitLabel(C.getOrCreateSymbol(StringRef("OBJC_IMAGE_INFO")));
+  Streamer.EmitIntValue(Version, 4);
+  Streamer.EmitIntValue(Flags, 4);
+  Streamer.AddBlankLine();
 }
 
 void TargetLoweringObjectFileCOFF::Initialize(MCContext &Ctx,
diff --git a/test/Object/objc-imageinfo-coff.ll b/test/Object/objc-imageinfo-coff.ll
new file mode 100644 (file)
index 0000000..cab0103
--- /dev/null
@@ -0,0 +1,14 @@
+; RUN: llc -mtriple x86_64-unknown-windows-msvc -filetype asm -o - %s | FileCheck %s
+
+!llvm.module.flags = !{!0, !1, !2, !3}
+
+!0 = !{i32 1, !"Objective-C Version", i32 2}
+!1 = !{i32 1, !"Objective-C Image Info Version", i32 0}
+!2 = !{i32 1, !"Objective-C Image Info Section", !".objc_imageinfo$B"}
+!3 = !{i32 1, !"Objective-C Garbage Collection", i32 2}
+
+; CHECK: .section .objc_imageinfo$B,"dr"
+; CHECK: OBJC_IMAGE_INFO:
+; CHECK:   .long 0
+; CHECK:   .long 2
+
diff --git a/test/Object/objc-imageinfo-elf.ll b/test/Object/objc-imageinfo-elf.ll
new file mode 100644 (file)
index 0000000..7979e01
--- /dev/null
@@ -0,0 +1,14 @@
+; RUN: llc -mtriple x86_64-unknown-linux-gnu -filetype asm -o - %s | FileCheck %s
+
+!llvm.module.flags = !{!0, !1, !2, !3}
+
+!0 = !{i32 1, !"Objective-C Version", i32 2}
+!1 = !{i32 1, !"Objective-C Image Info Version", i32 0}
+!2 = !{i32 1, !"Objective-C Image Info Section", !"objc_imageinfo"}
+!3 = !{i32 1, !"Objective-C Garbage Collection", i32 2}
+
+; CHECK: .section objc_imageinfo
+; CHECK: OBJC_IMAGE_INFO:
+; CHECK:   .long 0
+; CHECK:   .long 2
+
diff --git a/test/Object/objc-imageinfo-macho.ll b/test/Object/objc-imageinfo-macho.ll
new file mode 100644 (file)
index 0000000..90bc9d9
--- /dev/null
@@ -0,0 +1,14 @@
+; RUN: llc -mtriple x86_64-apple-ios -filetype asm -o - %s | FileCheck %s
+
+!llvm.module.flags = !{!0, !1, !2, !3}
+
+!0 = !{i32 1, !"Objective-C Version", i32 2}
+!1 = !{i32 1, !"Objective-C Image Info Version", i32 0}
+!2 = !{i32 1, !"Objective-C Image Info Section", !"__DATA,__objc_imageinfo,regular,no_dead_strip"}
+!3 = !{i32 1, !"Objective-C Garbage Collection", i32 2}
+
+; CHECK: .section __DATA,__objc_imageinfo,regular,no_dead_strip
+; CHECK: L_OBJC_IMAGE_INFO:
+; CHECK:   .long 0
+; CHECK:   .long 2
+