[lld] r290115 - Detemplate PhdrEntry. NFC.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 19 18:11:07 PST 2016


Nice! We probably should de-template more classes by simply using int64
instead of intX_t (which is either 32-bit or 64-bit depending on the
target) to reduce complexity.

On Mon, Dec 19, 2016 at 11:01 AM, Rafael Espindola via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

> Author: rafael
> Date: Mon Dec 19 11:01:01 2016
> New Revision: 290115
>
> URL: http://llvm.org/viewvc/llvm-project?rev=290115&view=rev
> Log:
> Detemplate PhdrEntry. NFC.
>
> Modified:
>     lld/trunk/ELF/LinkerScript.cpp
>     lld/trunk/ELF/LinkerScript.h
>     lld/trunk/ELF/OutputSections.h
>     lld/trunk/ELF/Symbols.cpp
>     lld/trunk/ELF/Writer.cpp
>     lld/trunk/ELF/Writer.h
>
> Modified: lld/trunk/ELF/LinkerScript.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScri
> pt.cpp?rev=290115&r1=290114&r2=290115&view=diff
> ============================================================
> ==================
> --- lld/trunk/ELF/LinkerScript.cpp (original)
> +++ lld/trunk/ELF/LinkerScript.cpp Mon Dec 19 11:01:01 2016
> @@ -714,7 +714,7 @@ template <class ELFT> void LinkerScript<
>  }
>
>  template <class ELFT>
> -void LinkerScript<ELFT>::assignAddresses(std::vector<PhdrEntry<ELFT>>
> &Phdrs) {
> +void LinkerScript<ELFT>::assignAddresses(std::vector<PhdrEntry> &Phdrs) {
>    // Assign addresses as instructed by linker script SECTIONS
> sub-commands.
>    Dot = 0;
>
> @@ -749,9 +749,8 @@ void LinkerScript<ELFT>::assignAddresses
>
>    uintX_t HeaderSize = getHeaderSize();
>    auto FirstPTLoad =
> -      std::find_if(Phdrs.begin(), Phdrs.end(), [](const PhdrEntry<ELFT>
> &E) {
> -        return E.H.p_type == PT_LOAD;
> -      });
> +      std::find_if(Phdrs.begin(), Phdrs.end(),
> +                   [](const PhdrEntry &E) { return E.p_type == PT_LOAD;
> });
>    if (FirstPTLoad == Phdrs.end())
>      return;
>
> @@ -771,15 +770,14 @@ void LinkerScript<ELFT>::assignAddresses
>  }
>
>  // Creates program headers as instructed by PHDRS linker script command.
> -template <class ELFT>
> -std::vector<PhdrEntry<ELFT>> LinkerScript<ELFT>::createPhdrs() {
> -  std::vector<PhdrEntry<ELFT>> Ret;
> +template <class ELFT> std::vector<PhdrEntry>
> LinkerScript<ELFT>::createPhdrs() {
> +  std::vector<PhdrEntry> Ret;
>
>    // Process PHDRS and FILEHDR keywords because they are not
>    // real output sections and cannot be added in the following loop.
>    for (const PhdrsCommand &Cmd : Opt.PhdrsCommands) {
>      Ret.emplace_back(Cmd.Type, Cmd.Flags == UINT_MAX ? PF_R : Cmd.Flags);
> -    PhdrEntry<ELFT> &Phdr = Ret.back();
> +    PhdrEntry &Phdr = Ret.back();
>
>      if (Cmd.HasFilehdr)
>        Phdr.add(Out<ELFT>::ElfHeader);
> @@ -787,7 +785,7 @@ std::vector<PhdrEntry<ELFT>> LinkerScrip
>        Phdr.add(Out<ELFT>::ProgramHeaders);
>
>      if (Cmd.LMAExpr) {
> -      Phdr.H.p_paddr = Cmd.LMAExpr(0);
> +      Phdr.p_paddr = Cmd.LMAExpr(0);
>        Phdr.HasLMA = true;
>      }
>    }
> @@ -801,7 +799,7 @@ std::vector<PhdrEntry<ELFT>> LinkerScrip
>      for (size_t Id : getPhdrIndices(Sec->getName())) {
>        Ret[Id].add(Sec);
>        if (Opt.PhdrsCommands[Id].Flags == UINT_MAX)
> -        Ret[Id].H.p_flags |= Sec->getPhdrFlags();
> +        Ret[Id].p_flags |= Sec->getPhdrFlags();
>      }
>    }
>    return Ret;
>
> Modified: lld/trunk/ELF/LinkerScript.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScri
> pt.h?rev=290115&r1=290114&r2=290115&view=diff
> ============================================================
> ==================
> --- lld/trunk/ELF/LinkerScript.h (original)
> +++ lld/trunk/ELF/LinkerScript.h Mon Dec 19 11:01:01 2016
> @@ -233,7 +233,7 @@ public:
>    void adjustSectionsBeforeSorting();
>    void adjustSectionsAfterSorting();
>
> -  std::vector<PhdrEntry<ELFT>> createPhdrs();
> +  std::vector<PhdrEntry> createPhdrs();
>    bool ignoreInterpSection();
>
>    uint32_t getFiller(StringRef Name);
> @@ -242,7 +242,7 @@ public:
>    bool shouldKeep(InputSectionBase<ELFT> *S);
>    void assignOffsets(OutputSectionCommand *Cmd);
>    void placeOrphanSections();
> -  void assignAddresses(std::vector<PhdrEntry<ELFT>> &Phdrs);
> +  void assignAddresses(std::vector<PhdrEntry> &Phdrs);
>    bool hasPhdrsCommands();
>    uint64_t getHeaderSize() override;
>    uint64_t getSymbolValue(StringRef S) override;
>
> Modified: lld/trunk/ELF/OutputSections.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSect
> ions.h?rev=290115&r1=290114&r2=290115&view=diff
> ============================================================
> ==================
> --- lld/trunk/ELF/OutputSections.h (original)
> +++ lld/trunk/ELF/OutputSections.h Mon Dec 19 11:01:01 2016
> @@ -20,6 +20,7 @@
>  namespace lld {
>  namespace elf {
>
> +struct PhdrEntry;
>  class SymbolBody;
>  struct EhSectionPiece;
>  template <class ELFT> class EhInputSection;
> @@ -207,7 +208,7 @@ template <class ELFT> struct Out {
>    static OutputSection<ELFT> *Bss;
>    static OutputSectionBase *Opd;
>    static uint8_t *OpdBuf;
> -  static Elf_Phdr *TlsPhdr;
> +  static PhdrEntry *TlsPhdr;
>    static OutputSectionBase *DebugInfo;
>    static OutputSectionBase *ElfHeader;
>    static OutputSectionBase *ProgramHeaders;
> @@ -254,7 +255,7 @@ template <class ELFT> EhOutputSection<EL
>  template <class ELFT> OutputSection<ELFT> *Out<ELFT>::Bss;
>  template <class ELFT> OutputSectionBase *Out<ELFT>::Opd;
>  template <class ELFT> uint8_t *Out<ELFT>::OpdBuf;
> -template <class ELFT> typename ELFT::Phdr *Out<ELFT>::TlsPhdr;
> +template <class ELFT> PhdrEntry *Out<ELFT>::TlsPhdr;
>  template <class ELFT> OutputSectionBase *Out<ELFT>::DebugInfo;
>  template <class ELFT> OutputSectionBase *Out<ELFT>::ElfHeader;
>  template <class ELFT> OutputSectionBase *Out<ELFT>::ProgramHeaders;
>
> Modified: lld/trunk/ELF/Symbols.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cp
> p?rev=290115&r1=290114&r2=290115&view=diff
> ============================================================
> ==================
> --- lld/trunk/ELF/Symbols.cpp (original)
> +++ lld/trunk/ELF/Symbols.cpp Mon Dec 19 11:01:01 2016
> @@ -15,6 +15,7 @@
>  #include "Strings.h"
>  #include "SyntheticSections.h"
>  #include "Target.h"
> +#include "Writer.h"
>
>  #include "llvm/ADT/STLExtras.h"
>  #include "llvm/Support/Path.h"
>
> Modified: lld/trunk/ELF/Writer.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp
> ?rev=290115&r1=290114&r2=290115&view=diff
> ============================================================
> ==================
> --- lld/trunk/ELF/Writer.cpp (original)
> +++ lld/trunk/ELF/Writer.cpp Mon Dec 19 11:01:01 2016
> @@ -48,8 +48,6 @@ public:
>    void run();
>
>  private:
> -  typedef PhdrEntry<ELFT> Phdr;
> -
>    void createSyntheticSections();
>    void copyLocalSymbols();
>    void addReservedSymbols();
> @@ -60,9 +58,9 @@ private:
>    void finalizeSections();
>    void addPredefinedSections();
>
> -  std::vector<Phdr> createPhdrs();
> +  std::vector<PhdrEntry> createPhdrs();
>    void removeEmptyPTLoad();
> -  void addPtArmExid(std::vector<Phdr> &Phdrs);
> +  void addPtArmExid(std::vector<PhdrEntry> &Phdrs);
>    void assignAddresses();
>    void assignFileOffsets();
>    void assignFileOffsetsBinary();
> @@ -87,7 +85,7 @@ private:
>    uintX_t getEntryAddr();
>    OutputSectionBase *findSection(StringRef Name);
>
> -  std::vector<Phdr> Phdrs;
> +  std::vector<PhdrEntry> Phdrs;
>
>    uintX_t FileSize;
>    uintX_t SectionHeaderOff;
> @@ -135,8 +133,8 @@ template <class ELFT> static bool needsI
>  template <class ELFT> void elf::writeResult() { Writer<ELFT>().run(); }
>
>  template <class ELFT> void Writer<ELFT>::removeEmptyPTLoad() {
> -  auto I = std::remove_if(Phdrs.begin(), Phdrs.end(), [&](const Phdr &P) {
> -    if (P.H.p_type != PT_LOAD)
> +  auto I = std::remove_if(Phdrs.begin(), Phdrs.end(), [&](const PhdrEntry
> &P) {
> +    if (P.p_type != PT_LOAD)
>        return false;
>      if (!P.First)
>        return true;
> @@ -603,18 +601,17 @@ static bool compareSections(const Output
>  }
>
>  // Program header entry
> -template <class ELFT>
> -PhdrEntry<ELFT>::PhdrEntry(unsigned Type, unsigned Flags) {
> -  H.p_type = Type;
> -  H.p_flags = Flags;
> +PhdrEntry::PhdrEntry(unsigned Type, unsigned Flags) {
> +  p_type = Type;
> +  p_flags = Flags;
>  }
>
> -template <class ELFT> void PhdrEntry<ELFT>::add(OutputSectionBase *Sec) {
> +void PhdrEntry::add(OutputSectionBase *Sec) {
>    Last = Sec;
>    if (!First)
>      First = Sec;
> -  H.p_align = std::max<typename ELFT::uint>(H.p_align, Sec->Addralign);
> -  if (H.p_type == PT_LOAD)
> +  p_align = std::max(p_align, Sec->Addralign);
> +  if (p_type == PT_LOAD)
>      Sec->FirstInPtLoad = First;
>  }
>
> @@ -1136,34 +1133,34 @@ static typename ELFT::uint computeFlags(
>
>  // Decide which program headers to create and which sections to include
> in each
>  // one.
> -template <class ELFT> std::vector<PhdrEntry<ELFT>>
> Writer<ELFT>::createPhdrs() {
> -  std::vector<Phdr> Ret;
> -  auto AddHdr = [&](unsigned Type, unsigned Flags) -> Phdr * {
> +template <class ELFT> std::vector<PhdrEntry> Writer<ELFT>::createPhdrs() {
> +  std::vector<PhdrEntry> Ret;
> +  auto AddHdr = [&](unsigned Type, unsigned Flags) -> PhdrEntry * {
>      Ret.emplace_back(Type, Flags);
>      return &Ret.back();
>    };
>
>    // The first phdr entry is PT_PHDR which describes the program header
> itself.
> -  Phdr &Hdr = *AddHdr(PT_PHDR, PF_R);
> +  PhdrEntry &Hdr = *AddHdr(PT_PHDR, PF_R);
>    Hdr.add(Out<ELFT>::ProgramHeaders);
>
>    // PT_INTERP must be the second entry if exists.
>    if (OutputSectionBase *Sec = findSection(".interp")) {
> -    Phdr &Hdr = *AddHdr(PT_INTERP, Sec->getPhdrFlags());
> +    PhdrEntry &Hdr = *AddHdr(PT_INTERP, Sec->getPhdrFlags());
>      Hdr.add(Sec);
>    }
>
>    // Add the first PT_LOAD segment for regular output sections.
>    uintX_t Flags = computeFlags<ELFT>(PF_R);
> -  Phdr *Load = AddHdr(PT_LOAD, Flags);
> +  PhdrEntry *Load = AddHdr(PT_LOAD, Flags);
>    if (!ScriptConfig->HasSections) {
>      Load->add(Out<ELFT>::ElfHeader);
>      Load->add(Out<ELFT>::ProgramHeaders);
>    }
>
> -  Phdr TlsHdr(PT_TLS, PF_R);
> -  Phdr RelRo(PT_GNU_RELRO, PF_R);
> -  Phdr Note(PT_NOTE, PF_R);
> +  PhdrEntry TlsHdr(PT_TLS, PF_R);
> +  PhdrEntry RelRo(PT_GNU_RELRO, PF_R);
> +  PhdrEntry Note(PT_NOTE, PF_R);
>    for (OutputSectionBase *Sec : OutputSections) {
>      if (!(Sec->Flags & SHF_ALLOC))
>        break;
> @@ -1202,7 +1199,8 @@ template <class ELFT> std::vector<PhdrEn
>
>    // Add an entry for .dynamic.
>    if (In<ELFT>::DynSymTab) {
> -    Phdr &H = *AddHdr(PT_DYNAMIC, In<ELFT>::Dynamic->OutSec->get
> PhdrFlags());
> +    PhdrEntry &H =
> +        *AddHdr(PT_DYNAMIC, In<ELFT>::Dynamic->OutSec->getPhdrFlags());
>      H.add(In<ELFT>::Dynamic->OutSec);
>    }
>
> @@ -1213,7 +1211,7 @@ template <class ELFT> std::vector<PhdrEn
>
>    // PT_GNU_EH_FRAME is a special section pointing on .eh_frame_hdr.
>    if (!Out<ELFT>::EhFrame->empty() && In<ELFT>::EhFrameHdr) {
> -    Phdr &Hdr =
> +    PhdrEntry &Hdr =
>          *AddHdr(PT_GNU_EH_FRAME, In<ELFT>::EhFrameHdr->OutSec->
> getPhdrFlags());
>      Hdr.add(In<ELFT>::EhFrameHdr->OutSec);
>    }
> @@ -1222,16 +1220,16 @@ template <class ELFT> std::vector<PhdrEn
>    // memory image of the program that must be filled with random data
> before any
>    // code in the object is executed.
>    if (OutputSectionBase *Sec = findSection(".openbsd.randomdata")) {
> -    Phdr &Hdr = *AddHdr(PT_OPENBSD_RANDOMIZE, Sec->getPhdrFlags());
> +    PhdrEntry &Hdr = *AddHdr(PT_OPENBSD_RANDOMIZE, Sec->getPhdrFlags());
>      Hdr.add(Sec);
>    }
>
>    // PT_GNU_STACK is a special section to tell the loader to make the
>    // pages for the stack non-executable.
>    if (!Config->ZExecstack) {
> -    Phdr &Hdr = *AddHdr(PT_GNU_STACK, PF_R | PF_W);
> +    PhdrEntry &Hdr = *AddHdr(PT_GNU_STACK, PF_R | PF_W);
>      if (Config->ZStackSize != uint64_t(-1))
> -      Hdr.H.p_memsz = Config->ZStackSize;
> +      Hdr.p_memsz = Config->ZStackSize;
>    }
>
>    // PT_OPENBSD_WXNEEDED is a OpenBSD-specific header to mark the
> executable
> @@ -1247,7 +1245,7 @@ template <class ELFT> std::vector<PhdrEn
>  }
>
>  template <class ELFT>
> -void Writer<ELFT>::addPtArmExid(std::vector<PhdrEntry<ELFT>> &Phdrs) {
> +void Writer<ELFT>::addPtArmExid(std::vector<PhdrEntry> &Phdrs) {
>    if (Config->EMachine != EM_ARM)
>      return;
>    auto I = std::find_if(
> @@ -1257,7 +1255,7 @@ void Writer<ELFT>::addPtArmExid(std::vec
>      return;
>
>    // PT_ARM_EXIDX is the ARM EHABI equivalent of PT_GNU_EH_FRAME
> -  Phdr ARMExidx(PT_ARM_EXIDX, PF_R);
> +  PhdrEntry ARMExidx(PT_ARM_EXIDX, PF_R);
>    ARMExidx.add(*I);
>    Phdrs.push_back(ARMExidx);
>  }
> @@ -1265,12 +1263,12 @@ void Writer<ELFT>::addPtArmExid(std::vec
>  // The first section of each PT_LOAD and the first section after
> PT_GNU_RELRO
>  // have to be page aligned so that the dynamic linker can set the
> permissions.
>  template <class ELFT> void Writer<ELFT>::fixSectionAlignments() {
> -  for (const Phdr &P : Phdrs)
> -    if (P.H.p_type == PT_LOAD)
> +  for (const PhdrEntry &P : Phdrs)
> +    if (P.p_type == PT_LOAD)
>        P.First->PageAlign = true;
>
> -  for (const Phdr &P : Phdrs) {
> -    if (P.H.p_type != PT_GNU_RELRO)
> +  for (const PhdrEntry &P : Phdrs) {
> +    if (P.p_type != PT_GNU_RELRO)
>        continue;
>      // Find the first section after PT_GNU_RELRO. If it is in a PT_LOAD we
>      // have to align it to a page.
> @@ -1381,31 +1379,30 @@ template <class ELFT> void Writer<ELFT>:
>  // Finalize the program headers. We call this function after we assign
>  // file offsets and VAs to all sections.
>  template <class ELFT> void Writer<ELFT>::setPhdrs() {
> -  for (Phdr &P : Phdrs) {
> -    Elf_Phdr &H = P.H;
> +  for (PhdrEntry &P : Phdrs) {
>      OutputSectionBase *First = P.First;
>      OutputSectionBase *Last = P.Last;
>      if (First) {
> -      H.p_filesz = Last->Offset - First->Offset;
> +      P.p_filesz = Last->Offset - First->Offset;
>        if (Last->Type != SHT_NOBITS)
> -        H.p_filesz += Last->Size;
> -      H.p_memsz = Last->Addr + Last->Size - First->Addr;
> -      H.p_offset = First->Offset;
> -      H.p_vaddr = First->Addr;
> +        P.p_filesz += Last->Size;
> +      P.p_memsz = Last->Addr + Last->Size - First->Addr;
> +      P.p_offset = First->Offset;
> +      P.p_vaddr = First->Addr;
>        if (!P.HasLMA)
> -        H.p_paddr = First->getLMA();
> +        P.p_paddr = First->getLMA();
>      }
> -    if (H.p_type == PT_LOAD)
> -      H.p_align = Config->MaxPageSize;
> -    else if (H.p_type == PT_GNU_RELRO)
> -      H.p_align = 1;
> +    if (P.p_type == PT_LOAD)
> +      P.p_align = Config->MaxPageSize;
> +    else if (P.p_type == PT_GNU_RELRO)
> +      P.p_align = 1;
>
>      // The TLS pointer goes after PT_TLS. At least glibc will align it,
>      // so round up the size to make sure the offsets are correct.
> -    if (H.p_type == PT_TLS) {
> -      Out<ELFT>::TlsPhdr = &H;
> -      if (H.p_memsz)
> -        H.p_memsz = alignTo(H.p_memsz, H.p_align);
> +    if (P.p_type == PT_TLS) {
> +      Out<ELFT>::TlsPhdr = &P;
> +      if (P.p_memsz)
> +        P.p_memsz = alignTo(P.p_memsz, P.p_align);
>      }
>    }
>  }
> @@ -1473,14 +1470,13 @@ template <class ELFT> void Writer<ELFT>:
>    // _etext is the first location after the last read-only loadable
> segment.
>    // _edata is the first location after the last read-write loadable
> segment.
>    // _end is the first location after the uninitialized data region.
> -  for (Phdr &P : Phdrs) {
> -    Elf_Phdr &H = P.H;
> -    if (H.p_type != PT_LOAD)
> +  for (PhdrEntry &P : Phdrs) {
> +    if (P.p_type != PT_LOAD)
>        continue;
> -    Set(ElfSym<ELFT>::End, ElfSym<ELFT>::End2, H.p_vaddr + H.p_memsz);
> +    Set(ElfSym<ELFT>::End, ElfSym<ELFT>::End2, P.p_vaddr + P.p_memsz);
>
> -    uintX_t Val = H.p_vaddr + H.p_filesz;
> -    if (H.p_flags & PF_W)
> +    uintX_t Val = P.p_vaddr + P.p_filesz;
> +    if (P.p_flags & PF_W)
>        Set(ElfSym<ELFT>::Edata, ElfSym<ELFT>::Edata2, Val);
>      else
>        Set(ElfSym<ELFT>::Etext, ElfSym<ELFT>::Etext2, Val);
> @@ -1542,8 +1538,17 @@ template <class ELFT> void Writer<ELFT>:
>
>    // Write the program header table.
>    auto *HBuf = reinterpret_cast<Elf_Phdr *>(Buf + EHdr->e_phoff);
> -  for (Phdr &P : Phdrs)
> -    *HBuf++ = P.H;
> +  for (PhdrEntry &P : Phdrs) {
> +    HBuf->p_type = P.p_type;
> +    HBuf->p_flags = P.p_flags;
> +    HBuf->p_offset = P.p_offset;
> +    HBuf->p_vaddr = P.p_vaddr;
> +    HBuf->p_paddr = P.p_paddr;
> +    HBuf->p_filesz = P.p_filesz;
> +    HBuf->p_memsz = P.p_memsz;
> +    HBuf->p_align = P.p_align;
> +    ++HBuf;
> +  }
>
>    // Write the section header table. Note that the first table entry is
> null.
>    auto *SHdrs = reinterpret_cast<Elf_Shdr *>(Buf + EHdr->e_shoff);
> @@ -1671,11 +1676,6 @@ template void elf::writeResult<ELF32BE>(
>  template void elf::writeResult<ELF64LE>();
>  template void elf::writeResult<ELF64BE>();
>
> -template struct elf::PhdrEntry<ELF32LE>;
> -template struct elf::PhdrEntry<ELF32BE>;
> -template struct elf::PhdrEntry<ELF64LE>;
> -template struct elf::PhdrEntry<ELF64BE>;
> -
>  template bool elf::isRelroSection<ELF32LE>(const OutputSectionBase *);
>  template bool elf::isRelroSection<ELF32BE>(const OutputSectionBase *);
>  template bool elf::isRelroSection<ELF64LE>(const OutputSectionBase *);
>
> Modified: lld/trunk/ELF/Writer.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.h?
> rev=290115&r1=290114&r2=290115&view=diff
> ============================================================
> ==================
> --- lld/trunk/ELF/Writer.h (original)
> +++ lld/trunk/ELF/Writer.h Mon Dec 19 11:01:01 2016
> @@ -28,11 +28,19 @@ template <class ELFT> bool isRelroSectio
>  // This describes a program header entry.
>  // Each contains type, access flags and range of output sections that
> will be
>  // placed in it.
> -template <class ELFT> struct PhdrEntry {
> +struct PhdrEntry {
>    PhdrEntry(unsigned Type, unsigned Flags);
>    void add(OutputSectionBase *Sec);
>
> -  typename ELFT::Phdr H = {};
> +  uint64_t p_paddr = 0;
> +  uint64_t p_vaddr = 0;
> +  uint64_t p_align = 0;
> +  uint64_t p_memsz = 0;
> +  uint64_t p_filesz = 0;
> +  uint64_t p_offset = 0;
> +  uint32_t p_type = 0;
> +  uint32_t p_flags = 0;
> +
>    OutputSectionBase *First = nullptr;
>    OutputSectionBase *Last = nullptr;
>    bool HasLMA = false;
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20161219/dbb4059b/attachment.html>


More information about the llvm-commits mailing list