Factor some code out and support for Jump Table relocations
authorBruno Cardoso Lopes <bruno.cardoso@gmail.com>
Fri, 3 Jul 2009 04:36:26 +0000 (04:36 +0000)
committerBruno Cardoso Lopes <bruno.cardoso@gmail.com>
Fri, 3 Jul 2009 04:36:26 +0000 (04:36 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@74760 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/ELFCodeEmitter.cpp
lib/CodeGen/ELFCodeEmitter.h
lib/CodeGen/ELFWriter.cpp
lib/CodeGen/ELFWriter.h

index 57b75a37f2317738efa5a1468fd2325cff720bb0..691f19408d47877e2e9023e4ed82a6f9d5ef7856 100644 (file)
@@ -97,6 +97,9 @@ bool ELFCodeEmitter::finishFunction(MachineFunction &MF) {
   // Emit constant pool to appropriate section(s)
   emitConstantPool(MF.getConstantPool());
 
+  // Emit jump tables to appropriate section
+  emitJumpTables(MF.getJumpTableInfo());
+
   // Relocations
   // -----------
   // If we have emitted any relocations to function-specific objects such as
@@ -116,13 +119,22 @@ bool ELFCodeEmitter::finishFunction(MachineFunction &MF) {
       Addr = getConstantPoolEntryAddress(MR.getConstantPoolIndex());
       MR.setConstantVal(CPSections[MR.getConstantPoolIndex()]);
       MR.setResultPointer((void*)Addr);
+    } else if (MR.isJumpTableIndex()) {
+      Addr = getJumpTableEntryAddress(MR.getJumpTableIndex());
+      MR.setResultPointer((void*)Addr);
+      MR.setConstantVal(JumpTableSectionIdx);
     } else {
       assert(0 && "Unhandled relocation type");
     }
     ES->addRelocation(MR);
   }
-  Relocations.clear();
 
+  // Clear per-function data structures.
+  Relocations.clear();
+  CPLocations.clear();
+  CPSections.clear();
+  JTLocations.clear();
+  MBBLocations.clear();
   return false;
 }
 
@@ -158,4 +170,56 @@ void ELFCodeEmitter::emitConstantPool(MachineConstantPool *MCP) {
   }
 }
 
+/// emitJumpTables - Emit all the jump tables for a given jump table info
+/// record to the appropriate section.
+void ELFCodeEmitter::emitJumpTables(MachineJumpTableInfo *MJTI) {
+  const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
+  if (JT.empty()) return;
+
+  // FIXME: handle PIC codegen
+  assert(TM.getRelocationModel() != Reloc::PIC_ &&
+         "PIC codegen not yet handled for elf jump tables!");
+
+  const TargetAsmInfo *TAI = TM.getTargetAsmInfo();
+
+  // Get the ELF Section to emit the jump table
+  unsigned Align = TM.getTargetData()->getPointerABIAlignment();
+  std::string JTName(TAI->getJumpTableDataSection());
+  ELFSection &JTSection = EW.getJumpTableSection(JTName, Align);
+  JumpTableSectionIdx = JTSection.SectionIdx;
+
+  // Entries in the JT Section are relocated against the text section
+  ELFSection &TextSection = EW.getTextSection();
+
+  // For each JT, record its offset from the start of the section
+  for (unsigned i = 0, e = JT.size(); i != e; ++i) {
+    const std::vector<MachineBasicBlock*> &MBBs = JT[i].MBBs;
+
+    DOUT << "JTSection.size(): " << JTSection.size() << "\n";
+    DOUT << "JTLocations.size: " << JTLocations.size() << "\n";
+
+    // Record JT 'i' offset in the JT section
+    JTLocations.push_back(JTSection.size());
+
+    // Each MBB entry in the Jump table section has a relocation entry
+    // against the current text section.
+    for (unsigned mi = 0, me = MBBs.size(); mi != me; ++mi) {
+      MachineRelocation MR =
+        MachineRelocation::getBB(JTSection.size(),
+                                 MachineRelocation::VANILLA,
+                                 MBBs[mi]);
+
+      // Offset of JT 'i' in JT section
+      MR.setResultPointer((void*)getMachineBasicBlockAddress(MBBs[mi]));
+      MR.setConstantVal(TextSection.SectionIdx);
+
+      // Add the relocation to the Jump Table section
+      JTSection.addRelocation(MR);
+
+      // Output placeholder for MBB in the JT section
+      JTSection.emitWord(0);
+    }
+  }
+}
+
 } // end namespace llvm
index e3d3618474841e2152d6ae2572f115244891f6cf..982aebf8fcc022ce1ec172c50591be8026539fd0 100644 (file)
@@ -40,6 +40,10 @@ namespace llvm {
     /// containing the constant pool entry for that index.
     std::vector<unsigned> CPSections;
 
+    /// JTLocations - This is a map of jump table indices to offsets from the
+    /// start of the section for that jump table index.
+    std::vector<uintptr_t> JTLocations;
+
     /// MBBLocations - This vector is a mapping from MBB ID's to their address.
     /// It is filled in by the StartMachineBasicBlock callback and queried by
     /// the getMachineBasicBlockAddress callback.
@@ -48,8 +52,12 @@ namespace llvm {
     /// FnStartPtr - Pointer to the start location of the current function
     /// in the buffer
     uint8_t *FnStartPtr;
+
+    /// JumpTableSectionIdx - Holds the index of the Jump Table Section 
+    unsigned JumpTableSectionIdx;
   public:
-    explicit ELFCodeEmitter(ELFWriter &ew) : EW(ew), TM(EW.TM) {}
+    explicit ELFCodeEmitter(ELFWriter &ew) : EW(ew), TM(EW.TM),
+                                             JumpTableSectionIdx(0) {}
 
     void startFunction(MachineFunction &F);
     bool finishFunction(MachineFunction &F);
@@ -64,25 +72,20 @@ namespace llvm {
       MBBLocations[MBB->getNumber()] = getCurrentPCOffset();
     }
 
-    virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) {
-      assert(MBBLocations.size() > (unsigned)MBB->getNumber() && 
-             MBBLocations[MBB->getNumber()] && "MBB not emitted!");
-      return MBBLocations[MBB->getNumber()];
-    }
-
     virtual uintptr_t getConstantPoolEntryAddress(unsigned Index) const {
       assert(CPLocations.size() > Index && "CP not emitted!");
       return CPLocations[Index];
     }
 
     virtual uintptr_t getJumpTableEntryAddress(unsigned Index) const {
-      assert(0 && "JT not implementated yet!");
-      return 0;
+      assert(JTLocations.size() > Index && "JT not emitted!");
+      return JTLocations[Index];
     }
 
     virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const {
-      assert(0 && "JT not implementated yet!");
-      return 0;
+      assert(MBBLocations.size() > (unsigned)MBB->getNumber() && 
+             MBBLocations[MBB->getNumber()] && "MBB not emitted!");
+      return MBBLocations[MBB->getNumber()];
     }
 
     virtual uintptr_t getLabelAddress(uint64_t Label) const {
@@ -100,7 +103,11 @@ namespace llvm {
     /// the constant should live in and emit the constant.
     void emitConstantPool(MachineConstantPool *MCP);
 
-    virtual void setModuleInfo(llvm::MachineModuleInfo* MMI) { }
+    /// emitJumpTables - Emit all the jump tables for a given jump table info
+    /// record to the appropriate section.
+    void emitJumpTables(MachineJumpTableInfo *MJTI);
+
+    virtual void setModuleInfo(llvm::MachineModuleInfo* MMI) {}
 
     /// JIT SPECIFIC FUNCTIONS - DO NOT IMPLEMENT THESE HERE!
     void startGVStub(const GlobalValue* F, unsigned StubSize,
index d74e826f92e6f6a9fd114e6eb329481029923ab3..9e915245525a3800bf1ac217babd19efc7182bd3 100644 (file)
@@ -166,43 +166,51 @@ unsigned ELFWriter::getGlobalELFLinkage(const GlobalValue *GV) {
   return ELFSym::STB_GLOBAL;
 }
 
+// getElfSectionFlags - Get the ELF Section Header based on the
+// flags defined in ELFTargetAsmInfo.
+unsigned ELFWriter::getElfSectionFlags(unsigned Flags) {
+  unsigned ElfSectionFlags = ELFSection::SHF_ALLOC;
+
+  if (Flags & SectionFlags::Code)
+    ElfSectionFlags |= ELFSection::SHF_EXECINSTR;
+  if (Flags & SectionFlags::Writeable)
+    ElfSectionFlags |= ELFSection::SHF_WRITE;
+  if (Flags & SectionFlags::Mergeable)
+    ElfSectionFlags |= ELFSection::SHF_MERGE;
+  if (Flags & SectionFlags::TLS)
+    ElfSectionFlags |= ELFSection::SHF_TLS;
+  if (Flags & SectionFlags::Strings)
+    ElfSectionFlags |= ELFSection::SHF_STRINGS;
+
+  return ElfSectionFlags;
+}
+
 // For global symbols without a section, return the Null section as a
 // placeholder
 ELFSection &ELFWriter::getGlobalSymELFSection(const GlobalVariable *GV,
                                               ELFSym &Sym) {
-  const Section *S = TAI->SectionForGlobal(GV);
-  unsigned Flags = S->getFlags();
-  unsigned SectionType = ELFSection::SHT_PROGBITS;
-  unsigned SHdrFlags = ELFSection::SHF_ALLOC;
-  DOUT << "Section " << S->getName() << " for global " << GV->getName() << "\n";
-
-  // If this is an external global, the symbol does not have a section.
+  // If this is a declaration, the symbol does not have a section.
   if (!GV->hasInitializer()) {
     Sym.SectionIdx = ELFSection::SHN_UNDEF;
     return getNullSection();
   }
 
+  // Get the name and flags of the section for the global
+  const Section *S = TAI->SectionForGlobal(GV);
+  unsigned SectionType = ELFSection::SHT_PROGBITS;
+  unsigned SectionFlags = getElfSectionFlags(S->getFlags());
+  DOUT << "Section " << S->getName() << " for global " << GV->getName() << "\n";
+
   const TargetData *TD = TM.getTargetData();
   unsigned Align = TD->getPreferredAlignment(GV);
   Constant *CV = GV->getInitializer();
 
-  if (Flags & SectionFlags::Code)
-    SHdrFlags |= ELFSection::SHF_EXECINSTR;
-  if (Flags & SectionFlags::Writeable)
-    SHdrFlags |= ELFSection::SHF_WRITE;
-  if (Flags & SectionFlags::Mergeable)
-    SHdrFlags |= ELFSection::SHF_MERGE;
-  if (Flags & SectionFlags::TLS)
-    SHdrFlags |= ELFSection::SHF_TLS;
-  if (Flags & SectionFlags::Strings)
-    SHdrFlags |= ELFSection::SHF_STRINGS;
-
   // If this global has a zero initializer, go to .bss or common section.
   // Variables are part of the common block if they are zero initialized
   // and allowed to be merged with other symbols.
   if (CV->isNullValue() || isa<UndefValue>(CV)) {
     SectionType = ELFSection::SHT_NOBITS;
-    ELFSection &ElfS = getSection(S->getName(), SectionType, SHdrFlags);
+    ELFSection &ElfS = getSection(S->getName(), SectionType, SectionFlags);
     if (GV->hasLinkOnceLinkage() || GV->hasWeakLinkage() ||
         GV->hasCommonLinkage()) {
       Sym.SectionIdx = ELFSection::SHN_COMMON;
@@ -218,7 +226,7 @@ ELFSection &ELFWriter::getGlobalSymELFSection(const GlobalVariable *GV,
   }
 
   Sym.IsConstant = true;
-  ELFSection &ElfS = getSection(S->getName(), SectionType, SHdrFlags);
+  ELFSection &ElfS = getSection(S->getName(), SectionType, SectionFlags);
   Sym.SectionIdx = ElfS.SectionIdx;
   ElfS.Align = std::max(ElfS.Align, Align);
   return ElfS;
index 950af90035bf676f6cb06b3501ddcd15d4c3a9e2..bab118c6e356820c40763f37cd6abb2145e7e4b5 100644 (file)
@@ -118,19 +118,33 @@ namespace llvm {
     /// is seen, the symbol will move from this list to the SymbolList.
     SetVector<GlobalValue*> PendingGlobals;
 
+    // Remove tab from section name prefix. This is necessary becase TAI 
+    // sometimes return a section name prefixed with a "\t" char. This is
+    // a little bit dirty. FIXME: find a better approach, maybe add more
+    // methods to TAI to get the clean name?
+    void fixNameForSection(std::string &Name) {
+      size_t Pos = Name.find("\t");
+      if (Pos != std::string::npos)
+        Name.erase(Pos, 1);
+
+      Pos = Name.find(".section ");
+      if (Pos != std::string::npos)
+        Name.erase(Pos, 9);
+
+      Pos = Name.find("\n");
+      if (Pos != std::string::npos)
+        Name.erase(Pos, 1);
+    }
+
     /// getSection - Return the section with the specified name, creating a new
     /// section if one does not already exist.
     ELFSection &getSection(const std::string &Name, unsigned Type,
                            unsigned Flags = 0, unsigned Align = 0) {
-      ELFSection *&SN = SectionLookup[Name];
-      if (SN) return *SN;
-
-      // Remove tab from section name prefix. This is necessary becase TAI 
-      // sometimes return a section name prefixed with a "\t" char.
       std::string SectionName(Name);
-      size_t Pos = SectionName.find("\t");
-      if (Pos != std::string::npos)
-        SectionName.erase(Pos, 1);
+      fixNameForSection(SectionName);
+
+      ELFSection *&SN = SectionLookup[SectionName];
+      if (SN) return *SN;
 
       SectionList.push_back(ELFSection(SectionName, isLittleEndian, is64Bit));
       SN = &SectionList.back();
@@ -149,6 +163,12 @@ namespace llvm {
                         ELFSection::SHF_EXECINSTR | ELFSection::SHF_ALLOC);
     }
 
+    /// Get jump table section on the section name returned by TAI
+    ELFSection &getJumpTableSection(std::string SName, unsigned Align) {
+      return getSection(SName, ELFSection::SHT_PROGBITS,
+                        ELFSection::SHF_ALLOC, Align);
+    }
+
     /// Get a constant pool section based on the section name returned by TAI
     ELFSection &getConstantPoolSection(std::string SName, unsigned Align) {
       return getSection(SName, ELFSection::SHT_PROGBITS,
@@ -197,9 +217,10 @@ namespace llvm {
       return getSection("", ELFSection::SHT_NULL, 0);
     }
 
-    // Helpers for obtaining ELF specific Linkage and Visibility info.
+    // Helpers for obtaining ELF specific info.
     unsigned getGlobalELFLinkage(const GlobalValue *GV);
     unsigned getGlobalELFVisibility(const GlobalValue *GV);
+    unsigned getElfSectionFlags(unsigned Flags);
 
     // As we complete the ELF file, we need to update fields in the ELF header
     // (e.g. the location of the section table).  These members keep track of