Subzero: Add basic ELFObjectWriter (text section, symtab, strtab, headers).

Able to write out the ELF file header w/ a text section,
a symbol table, and string table. Write text buffer
directly to file after translating each CFG.
This means that the header is written out early w/ fake
data and then we seek back and write the real header
at the very end.

Does not yet handle relocations, data, rodata, constant
pools, bss, or -ffunction-sections, more than 64K sections
or more than 2^24 symbols.

Numbers w/ current NOASSERT=1 build on 176.gcc:

w/out -elf-writer:
    0.233771 (21.1%): [ 1287] emit
    28MB .s file

w/ -elf-writer:
    0.051056 ( 5.6%): [ 1287] emit
    2.4MB .o file

BUG=none
R=stichnot@chromium.org

Review URL: https://codereview.chromium.org/678533005
diff --git a/src/IceELFObjectWriter.h b/src/IceELFObjectWriter.h
new file mode 100644
index 0000000..1dc9daa
--- /dev/null
+++ b/src/IceELFObjectWriter.h
@@ -0,0 +1,125 @@
+//===- subzero/src/IceELFObjectWriter.h - ELF object writer -----*- C++ -*-===//
+//
+//                        The Subzero Code Generator
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Abstraction for a writer that is responsible for writing an ELF file.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SUBZERO_SRC_ICEELFOBJECTWRITER_H
+#define SUBZERO_SRC_ICEELFOBJECTWRITER_H
+
+#include "IceDefs.h"
+#include "IceELFSection.h"
+#include "IceELFStreamer.h"
+
+using namespace llvm::ELF;
+
+namespace Ice {
+
+// Higher level ELF object writer.  Manages section information and writes
+// the final ELF object.  The object writer will write to file the code
+// and data as it is being defined (rather than keep a copy).
+// After all definitions are written out, it will finalize the bookkeeping
+// sections and write them out.  Expected usage:
+//
+// (1) writeInitialELFHeader
+// (2) writeDataInitializer*
+// (3) writeFunctionCode*
+// (4) writeNonUserSections
+class ELFObjectWriter {
+  ELFObjectWriter(const ELFObjectWriter &) = delete;
+  ELFObjectWriter &operator=(const ELFObjectWriter &) = delete;
+
+public:
+  ELFObjectWriter(GlobalContext &Ctx, ELFStreamer &Out);
+
+  // Write the initial ELF header. This is just to reserve space in the ELF
+  // file. Reserving space allows the other functions to write text
+  // and data directly to the file and get the right file offsets.
+  void writeInitialELFHeader();
+
+  // Copy data of a function's text section to file and note the offset of the
+  // symbol's definition in the symbol table.
+  // TODO(jvoung): This also needs the relocations to adjust the
+  // section-relative offsets and hook them up to the symbol table references.
+  void writeFunctionCode(const IceString &FuncName, bool IsInternal,
+                         const llvm::StringRef Data);
+
+  // Copy initializer data for a global to file and note the offset and
+  // size of the global's definition in the symbol table.
+  // TODO(jvoung): This needs to know which section. This also needs the
+  // relocations to hook them up to the symbol table references. Also
+  // TODO is handling BSS (which just needs to note the size).
+  void writeDataInitializer(const IceString &VarName,
+                            const llvm::StringRef Data);
+
+  // Do final layout and write out the rest of the object file, then
+  // patch up the initial ELF header with the final info.
+  void writeNonUserSections();
+
+private:
+  GlobalContext &Ctx;
+  ELFStreamer &Str;
+  bool SectionNumbersAssigned;
+
+  // All created sections, separated into different pools.
+  typedef std::vector<ELFSection *> SectionList;
+  typedef std::vector<ELFTextSection *> TextSectionList;
+  typedef std::vector<ELFDataSection *> DataSectionList;
+  typedef std::vector<ELFRelocationSectionBase *> RelSectionList;
+  TextSectionList TextSections;
+  RelSectionList RelTextSections;
+  DataSectionList DataSections;
+  RelSectionList RelDataSections;
+  DataSectionList RoDataSections;
+  RelSectionList RelRoDataSections;
+
+  // Handles to special sections that need incremental bookkeeping.
+  ELFSection *NullSection;
+  ELFStringTableSection *ShStrTab;
+  ELFSymbolTableSection *SymTab;
+  ELFStringTableSection *StrTab;
+
+  template <typename T>
+  T *createSection(const IceString &Name, Elf64_Word ShType,
+                   Elf64_Xword ShFlags, Elf64_Xword ShAddralign,
+                   Elf64_Xword ShEntsize);
+
+  // Align the file position before writing out a section's data,
+  // and return the position of the file.
+  Elf64_Off alignFileOffset(Elf64_Xword Align);
+
+  // Assign an ordering / section numbers to each section.
+  // Fill in other information that is only known near the end
+  // (such as the size, if it wasn't already incrementally updated).
+  // This then collects all sections in the decided order, into one vector,
+  // for conveniently writing out all of the section headers.
+  void assignSectionNumbersInfo(SectionList &AllSections);
+
+  // This function assigns .foo and .rel.foo consecutive section numbers.
+  // It also sets the relocation section's sh_info field to the related
+  // section's number.
+  template <typename UserSectionList>
+  void assignRelSectionNumInPairs(SizeT &CurSectionNumber,
+                                  UserSectionList &UserSections,
+                                  RelSectionList &RelSections,
+                                  SectionList &AllSections);
+
+  // Link the relocation sections to the symbol table.
+  void assignRelLinkNum(SizeT SymTabNumber, RelSectionList &RelSections);
+
+  // Write the ELF file header with the given information about sections.
+  template <bool IsELF64>
+  void writeELFHeaderInternal(uint64_t SectionHeaderOffset,
+                              SizeT SectHeaderStrIndex, SizeT NumSections);
+};
+
+} // end of namespace Ice
+
+#endif // SUBZERO_SRC_ICEELFOBJECTWRITER_H