Move some flag-like props from GlobalContext and TargetLowering to ClFlags.

Simplifies the GlobalContext constructor so that a future
change may just set up the flags and the GlobalContext
before calling into what is currently "main".
Namely this change:
https://codereview.chromium.org/997773002/

This also moves all uses of LLVM's CommandLine.h to
a single file, so that in the future we may be able
to simplify the flags parsing (especially for the
minimal build).

BUG= https://code.google.com/p/nativeclient/issues/detail?id=4091
BUG= https://code.google.com/p/nativeclient/issues/detail?id=4084
R=stichnot@chromium.org

Review URL: https://codereview.chromium.org/1024203002
diff --git a/src/IceCfg.cpp b/src/IceCfg.cpp
index 2a1fdb6..e6a9cab 100644
--- a/src/IceCfg.cpp
+++ b/src/IceCfg.cpp
@@ -32,15 +32,16 @@
 }
 
 Cfg::Cfg(GlobalContext *Ctx, uint32_t SequenceNumber)
-    : Ctx(Ctx), SequenceNumber(SequenceNumber), VMask(Ctx->getVerbose()),
-      FunctionName(""), ReturnType(IceType_void), IsInternalLinkage(false),
-      HasError(false), FocusedTiming(false), ErrorMessage(""), Entry(nullptr),
+    : Ctx(Ctx), SequenceNumber(SequenceNumber),
+      VMask(Ctx->getFlags().getVerbose()), FunctionName(""),
+      ReturnType(IceType_void), IsInternalLinkage(false), HasError(false),
+      FocusedTiming(false), ErrorMessage(""), Entry(nullptr),
       NextInstNumber(Inst::NumberInitial), Allocator(new ArenaAllocator<>()),
-      Live(nullptr),
-      Target(TargetLowering::createLowering(Ctx->getTargetArch(), this)),
+      Live(nullptr), Target(TargetLowering::createLowering(
+                         Ctx->getFlags().getTargetArch(), this)),
       VMetadata(new VariablesMetadata(this)),
-      TargetAssembler(
-          TargetLowering::createAssembler(Ctx->getTargetArch(), this)),
+      TargetAssembler(TargetLowering::createAssembler(
+          Ctx->getFlags().getTargetArch(), this)),
       CurrentNode(nullptr) {
   assert(!Ctx->isIRGenerationDisabled() &&
          "Attempt to build cfg when IR generation disabled");
diff --git a/src/IceClFlags.h b/src/IceClFlags.h
index 6fcbbbb..1133f8c 100644
--- a/src/IceClFlags.h
+++ b/src/IceClFlags.h
@@ -14,7 +14,7 @@
 #ifndef SUBZERO_SRC_ICECLFLAGS_H
 #define SUBZERO_SRC_ICECLFLAGS_H
 
-#include "IceTypes.def"
+#include "IceTypes.h"
 
 namespace Ice {
 
@@ -30,15 +30,18 @@
         DecorateAsm(false), DisableInternal(false), DisableIRGeneration(false),
         DisableTranslation(false), DumpStats(false), FunctionSections(false),
         GenerateUnitTestMessages(false), PhiEdgeSplit(false),
+        RandomNopInsertion(false), RandomRegAlloc(false),
         SubzeroTimingEnabled(false), TimeEachFunction(false),
         UseSandboxing(false),
-        // FileType field
-        OutFileType(FT_Iasm),
+        // Enum and integer fields
+        Opt(Opt_m1), OutFileType(FT_Iasm), RandomMaxNopsPerInstruction(0),
+        RandomNopProbabilityAsPercentage(0), TArch(TargetArch_NUM),
+        VMask(IceV_None),
         // IceString fields.
-        DefaultFunctionPrefix(""), DefaultGlobalPrefix(""), TimingFocusOn(""),
-        TranslateOnly(""), VerboseFocusOn(""),
-        // size_t fields.
-        NumTranslationThreads(0) {}
+        DefaultFunctionPrefix(""), DefaultGlobalPrefix(""), TestPrefix(""),
+        TimingFocusOn(""), TranslateOnly(""), VerboseFocusOn(""),
+        // size_t and 64-bit fields.
+        NumTranslationThreads(0), RandomSeed(0) {}
 
   // bool accessors.
 
@@ -87,6 +90,12 @@
   bool getPhiEdgeSplit() const { return PhiEdgeSplit; }
   void setPhiEdgeSplit(bool NewValue) { PhiEdgeSplit = NewValue; }
 
+  bool shouldDoNopInsertion() const { return RandomNopInsertion; }
+  void setShouldDoNopInsertion(bool NewValue) { RandomNopInsertion = NewValue; }
+
+  bool shouldRandomizeRegAlloc() const { return RandomRegAlloc; }
+  void setShouldRandomizeRegAlloc(bool NewValue) { RandomRegAlloc = NewValue; }
+
   bool getSubzeroTimingEnabled() const { return SubzeroTimingEnabled; }
   void setSubzeroTimingEnabled(bool NewValue) {
     SubzeroTimingEnabled = NewValue;
@@ -98,10 +107,36 @@
   bool getUseSandboxing() const { return UseSandboxing; }
   void setUseSandboxing(bool NewValue) { UseSandboxing = NewValue; }
 
-  // FileType accessor.
+  // Enum and integer accessors.
+  OptLevel getOptLevel() const { return Opt; }
+  void setOptLevel(OptLevel NewValue) { Opt = NewValue; }
+
   FileType getOutFileType() const { return OutFileType; }
   void setOutFileType(FileType NewValue) { OutFileType = NewValue; }
 
+  int getMaxNopsPerInstruction() const { return RandomMaxNopsPerInstruction; }
+  void setMaxNopsPerInstruction(int NewValue) {
+    RandomMaxNopsPerInstruction = NewValue;
+  }
+
+  int getNopProbabilityAsPercentage() const {
+    return RandomNopProbabilityAsPercentage;
+  }
+  void setNopProbabilityAsPercentage(int NewValue) {
+    RandomNopProbabilityAsPercentage = NewValue;
+  }
+
+  TargetArch getTargetArch() const { return TArch; }
+  void setTargetArch(TargetArch NewValue) { TArch = NewValue; }
+
+  TargetInstructionSet getTargetInstructionSet() const { return TInstrSet; }
+  void setTargetInstructionSet(TargetInstructionSet NewValue) {
+    TInstrSet = NewValue;
+  }
+
+  VerboseMask getVerbose() const { return ALLOW_DUMP ? VMask : IceV_None; }
+  void setVerbose(VerboseMask NewValue) { VMask = NewValue; }
+
   // IceString accessors.
 
   const IceString &getDefaultFunctionPrefix() const {
@@ -118,6 +153,9 @@
     DefaultGlobalPrefix = NewValue;
   }
 
+  const IceString &getTestPrefix() const { return TestPrefix; }
+  void setTestPrefix(const IceString &NewValue) { TestPrefix = NewValue; }
+
   const IceString &getTimingFocusOn() const { return TimingFocusOn; }
   void setTimingFocusOn(const IceString &NewValue) { TimingFocusOn = NewValue; }
 
@@ -129,7 +167,7 @@
     VerboseFocusOn = NewValue;
   }
 
-  // size_t accessors.
+  // size_t and 64-bit accessors.
 
   size_t getNumTranslationThreads() const { return NumTranslationThreads; }
   bool isSequential() const { return NumTranslationThreads == 0; }
@@ -137,6 +175,9 @@
     NumTranslationThreads = NewValue;
   }
 
+  uint64_t getRandomSeed() const { return RandomSeed; }
+  void setRandomSeed(size_t NewValue) { RandomSeed = NewValue; }
+
 private:
   bool AllowErrorRecovery;
   bool AllowUninitializedGlobals;
@@ -149,19 +190,29 @@
   bool FunctionSections;
   bool GenerateUnitTestMessages;
   bool PhiEdgeSplit;
+  bool RandomNopInsertion;
+  bool RandomRegAlloc;
   bool SubzeroTimingEnabled;
   bool TimeEachFunction;
   bool UseSandboxing;
 
+  OptLevel Opt;
   FileType OutFileType;
+  int RandomMaxNopsPerInstruction;
+  int RandomNopProbabilityAsPercentage;
+  TargetArch TArch;
+  TargetInstructionSet TInstrSet;
+  VerboseMask VMask;
 
   IceString DefaultFunctionPrefix;
   IceString DefaultGlobalPrefix;
+  IceString TestPrefix;
   IceString TimingFocusOn;
   IceString TranslateOnly;
   IceString VerboseFocusOn;
 
   size_t NumTranslationThreads; // 0 means completely sequential
+  uint64_t RandomSeed;
 };
 
 } // end of namespace Ice
diff --git a/src/IceELFObjectWriter.cpp b/src/IceELFObjectWriter.cpp
index 073163a..9761dde 100644
--- a/src/IceELFObjectWriter.cpp
+++ b/src/IceELFObjectWriter.cpp
@@ -64,7 +64,8 @@
 } // end of anonymous namespace
 
 ELFObjectWriter::ELFObjectWriter(GlobalContext &Ctx, ELFStreamer &Out)
-    : Ctx(Ctx), Str(Out), SectionNumbersAssigned(false) {
+    : Ctx(Ctx), Str(Out), SectionNumbersAssigned(false),
+      ELF64(isELF64(Ctx.getFlags().getTargetArch())) {
   // Create the special bookkeeping sections now.
   const IceString NullSectionName("");
   NullSection = new (Ctx.allocate<ELFSection>())
@@ -76,10 +77,9 @@
   ShStrTab->add(ShStrTabName);
 
   const IceString SymTabName(".symtab");
-  bool IsELF64 = isELF64(Ctx.getTargetArch());
-  const Elf64_Xword SymTabAlign = IsELF64 ? 8 : 4;
+  const Elf64_Xword SymTabAlign = ELF64 ? 8 : 4;
   const Elf64_Xword SymTabEntSize =
-      IsELF64 ? sizeof(Elf64_Sym) : sizeof(Elf32_Sym);
+      ELF64 ? sizeof(Elf64_Sym) : sizeof(Elf32_Sym);
   static_assert(sizeof(Elf64_Sym) == 24 && sizeof(Elf32_Sym) == 16,
                 "Elf_Sym sizes cannot be derived from sizeof");
   SymTab = createSection<ELFSymbolTableSection>(SymTabName, SHT_SYMTAB, 0,
@@ -103,18 +103,16 @@
 }
 
 ELFRelocationSection *
-ELFObjectWriter::createRelocationSection(bool IsELF64,
-                                         const ELFSection *RelatedSection) {
+ELFObjectWriter::createRelocationSection(const ELFSection *RelatedSection) {
   // Choice of RELA vs REL is actually separate from elf64 vs elf32,
   // but in practice we've only had .rela for elf64 (x86-64).
   // In the future, the two properties may need to be decoupled
   // and the ShEntSize can vary more.
-  const Elf64_Word ShType = IsELF64 ? SHT_RELA : SHT_REL;
-  IceString RelPrefix = IsELF64 ? ".rela" : ".rel";
+  const Elf64_Word ShType = ELF64 ? SHT_RELA : SHT_REL;
+  IceString RelPrefix = ELF64 ? ".rela" : ".rel";
   IceString RelSectionName = RelPrefix + RelatedSection->getName();
-  const Elf64_Xword ShAlign = IsELF64 ? 8 : 4;
-  const Elf64_Xword ShEntSize =
-      IsELF64 ? sizeof(Elf64_Rela) : sizeof(Elf32_Rel);
+  const Elf64_Xword ShAlign = ELF64 ? 8 : 4;
+  const Elf64_Xword ShEntSize = ELF64 ? sizeof(Elf64_Rela) : sizeof(Elf32_Rel);
   static_assert(sizeof(Elf64_Rela) == 24 && sizeof(Elf32_Rel) == 8,
                 "Elf_Rel/Rela sizes cannot be derived from sizeof");
   const Elf64_Xword ShFlags = 0;
@@ -220,7 +218,6 @@
     IceString SectionName = ".text";
     if (FunctionSections)
       SectionName += "." + FuncName;
-    bool IsELF64 = isELF64(Ctx.getTargetArch());
     const Elf64_Xword ShFlags = SHF_ALLOC | SHF_EXECINSTR;
     const Elf64_Xword ShAlign = 1 << Asm->getBundleAlignLog2Bytes();
     Section = createSection<ELFTextSection>(SectionName, SHT_PROGBITS, ShFlags,
@@ -228,7 +225,7 @@
     Elf64_Off OffsetInFile = alignFileOffset(Section->getSectionAlign());
     Section->setFileOffset(OffsetInFile);
     TextSections.push_back(Section);
-    RelSection = createRelocationSection(IsELF64, Section);
+    RelSection = createRelocationSection(Section);
     RelTextSections.push_back(RelSection);
   } else {
     Section = TextSections[0];
@@ -295,17 +292,15 @@
     SectionList.reserve(Vars.size());
   partitionGlobalsBySection(Vars, VarsBySection,
                             Ctx.getFlags().getTranslateOnly());
-  bool IsELF64 = isELF64(Ctx.getTargetArch());
   size_t I = 0;
   for (auto &SectionList : VarsBySection) {
-    writeDataOfType(static_cast<SectionType>(I++), SectionList, RelocationKind,
-                    IsELF64);
+    writeDataOfType(static_cast<SectionType>(I++), SectionList, RelocationKind);
   }
 }
 
 void ELFObjectWriter::writeDataOfType(SectionType ST,
                                       const VariableDeclarationList &Vars,
-                                      FixupKind RelocationKind, bool IsELF64) {
+                                      FixupKind RelocationKind) {
   if (Vars.empty())
     return;
   ELFDataSection *Section;
@@ -329,7 +324,7 @@
                                             ShAddralign, ShEntsize);
     Section->setFileOffset(alignFileOffset(ShAddralign));
     RODataSections.push_back(Section);
-    RelSection = createRelocationSection(IsELF64, Section);
+    RelSection = createRelocationSection(Section);
     RelRODataSections.push_back(RelSection);
     break;
   }
@@ -341,7 +336,7 @@
                                             ShAddralign, ShEntsize);
     Section->setFileOffset(alignFileOffset(ShAddralign));
     DataSections.push_back(Section);
-    RelSection = createRelocationSection(IsELF64, Section);
+    RelSection = createRelocationSection(Section);
     RelDataSections.push_back(RelSection);
     break;
   }
@@ -422,7 +417,7 @@
   const Elf64_Off DummySHOffset = 0;
   const SizeT DummySHStrIndex = 0;
   const SizeT DummyNumSections = 0;
-  if (isELF64(Ctx.getTargetArch())) {
+  if (ELF64) {
     writeELFHeaderInternal<true>(DummySHOffset, DummySHStrIndex,
                                  DummyNumSections);
   } else {
@@ -453,17 +448,18 @@
   assert(NumSections < SHN_LORESERVE);
   assert(SectHeaderStrIndex < SHN_LORESERVE);
 
+  const TargetArch Arch = Ctx.getFlags().getTargetArch();
   // Write the rest of the file header, which does depend on byte order
   // and ELF class.
-  Str.writeLE16(ET_REL);                             // e_type
-  Str.writeLE16(getELFMachine(Ctx.getTargetArch())); // e_machine
-  Str.writeELFWord<IsELF64>(1);                      // e_version
+  Str.writeLE16(ET_REL);                                        // e_type
+  Str.writeLE16(getELFMachine(Ctx.getFlags().getTargetArch())); // e_machine
+  Str.writeELFWord<IsELF64>(1);                                 // e_version
   // Since this is for a relocatable object, there is no entry point,
   // and no program headers.
   Str.writeAddrOrOffset<IsELF64>(0);                                // e_entry
   Str.writeAddrOrOffset<IsELF64>(0);                                // e_phoff
   Str.writeAddrOrOffset<IsELF64>(SectionHeaderOffset);              // e_shoff
-  Str.writeELFWord<IsELF64>(getELFFlags(Ctx.getTargetArch()));      // e_flags
+  Str.writeELFWord<IsELF64>(getELFFlags(Arch));                     // e_flags
   Str.writeLE16(IsELF64 ? sizeof(Elf64_Ehdr) : sizeof(Elf32_Ehdr)); // e_ehsize
   static_assert(sizeof(Elf64_Ehdr) == 64 && sizeof(Elf32_Ehdr) == 52,
                 "Elf_Ehdr sizes cannot be derived from sizeof");
@@ -532,10 +528,10 @@
 
 template void ELFObjectWriter::writeConstantPool<ConstantDouble>(Type Ty);
 
-void ELFObjectWriter::writeAllRelocationSections(bool IsELF64) {
-  writeRelocationSections(IsELF64, RelTextSections);
-  writeRelocationSections(IsELF64, RelDataSections);
-  writeRelocationSections(IsELF64, RelRODataSections);
+void ELFObjectWriter::writeAllRelocationSections() {
+  writeRelocationSections(RelTextSections);
+  writeRelocationSections(RelDataSections);
+  writeRelocationSections(RelRODataSections);
 }
 
 void ELFObjectWriter::setUndefinedSyms(const ConstantList &UndefSyms) {
@@ -555,13 +551,12 @@
   }
 }
 
-void ELFObjectWriter::writeRelocationSections(bool IsELF64,
-                                              RelSectionList &RelSections) {
+void ELFObjectWriter::writeRelocationSections(RelSectionList &RelSections) {
   for (ELFRelocationSection *RelSec : RelSections) {
     Elf64_Off Offset = alignFileOffset(RelSec->getSectionAlign());
     RelSec->setFileOffset(Offset);
     RelSec->setSize(RelSec->getSectionDataSize());
-    if (IsELF64) {
+    if (ELF64) {
       RelSec->writeData<true>(Ctx, Str, SymTab);
     } else {
       RelSec->writeData<false>(Ctx, Str, SymTab);
@@ -570,8 +565,6 @@
 }
 
 void ELFObjectWriter::writeNonUserSections() {
-  bool IsELF64 = isELF64(Ctx.getTargetArch());
-
   // Write out the shstrtab now that all sections are known.
   ShStrTab->doLayout();
   ShStrTab->setSize(ShStrTab->getSectionDataSize());
@@ -591,19 +584,19 @@
   Elf64_Off SymTabOffset = alignFileOffset(SymTab->getSectionAlign());
   SymTab->setFileOffset(SymTabOffset);
   SymTab->setSize(SymTab->getSectionDataSize());
-  SymTab->writeData(Str, IsELF64);
+  SymTab->writeData(Str, ELF64);
 
   Elf64_Off StrTabOffset = alignFileOffset(StrTab->getSectionAlign());
   StrTab->setFileOffset(StrTabOffset);
   Str.writeBytes(StrTab->getSectionData());
 
-  writeAllRelocationSections(IsELF64);
+  writeAllRelocationSections();
 
   // Write out the section headers.
-  const size_t ShdrAlign = IsELF64 ? 8 : 4;
+  const size_t ShdrAlign = ELF64 ? 8 : 4;
   Elf64_Off ShOffset = alignFileOffset(ShdrAlign);
   for (const auto S : AllSections) {
-    if (IsELF64)
+    if (ELF64)
       S->writeHeader<true>(Str);
     else
       S->writeHeader<false>(Str);
@@ -611,7 +604,7 @@
 
   // Finally write the updated ELF header w/ the correct number of sections.
   Str.seek(0);
-  if (IsELF64) {
+  if (ELF64) {
     writeELFHeaderInternal<true>(ShOffset, ShStrTab->getNumber(),
                                  AllSections.size());
   } else {
diff --git a/src/IceELFObjectWriter.h b/src/IceELFObjectWriter.h
index d27ee9c..1103845 100644
--- a/src/IceELFObjectWriter.h
+++ b/src/IceELFObjectWriter.h
@@ -93,6 +93,7 @@
   GlobalContext &Ctx;
   ELFStreamer &Str;
   bool SectionNumbersAssigned;
+  bool ELF64;
 
   // All created sections, separated into different pools.
   typedef std::vector<ELFSection *> SectionList;
@@ -121,7 +122,7 @@
   // Create a relocation section, given the related section
   // (e.g., .text, .data., .rodata).
   ELFRelocationSection *
-  createRelocationSection(bool IsELF64, const ELFSection *RelatedSection);
+  createRelocationSection(const ELFSection *RelatedSection);
 
   // Align the file position before writing out a section's data,
   // and return the position of the file.
@@ -150,13 +151,13 @@
   // SectionType, given the global variables Vars belonging to that SectionType.
   void writeDataOfType(SectionType SectionType,
                        const VariableDeclarationList &Vars,
-                       FixupKind RelocationKind, bool IsELF64);
+                       FixupKind RelocationKind);
 
   // Write the final relocation sections given the final symbol table.
   // May also be able to seek around the file and resolve function calls
   // that are for functions within the same section.
-  void writeAllRelocationSections(bool IsELF64);
-  void writeRelocationSections(bool IsELF64, RelSectionList &RelSections);
+  void writeAllRelocationSections();
+  void writeRelocationSections(RelSectionList &RelSections);
 
   // Write the ELF file header with the given information about sections.
   template <bool IsELF64>
diff --git a/src/IceGlobalContext.cpp b/src/IceGlobalContext.cpp
index af4d358..c710edf 100644
--- a/src/IceGlobalContext.cpp
+++ b/src/IceGlobalContext.cpp
@@ -162,12 +162,9 @@
 }
 
 GlobalContext::GlobalContext(Ostream *OsDump, Ostream *OsEmit,
-                             ELFStreamer *ELFStr, VerboseMask Mask,
-                             TargetArch Arch, OptLevel Opt,
-                             IceString TestPrefix, const ClFlags &Flags)
+                             ELFStreamer *ELFStr, const ClFlags &Flags)
     : ConstPool(new ConstantPool()), ErrorStatus(), StrDump(OsDump),
-      StrEmit(OsEmit), VMask(Mask), Arch(Arch), Opt(Opt),
-      TestPrefix(TestPrefix), Flags(Flags), RNG(""), ObjectWriter(),
+      StrEmit(OsEmit), Flags(Flags), RNG(Flags.getRandomSeed()), ObjectWriter(),
       OptQ(/*Sequential=*/Flags.isSequential(),
            /*MaxSize=*/Flags.getNumTranslationThreads()),
       // EmitQ is allowed unlimited size.
@@ -267,7 +264,7 @@
                   std::unique_ptr<VariableDeclarationList> VariableDeclarations,
                   TargetDataLowering *DataLowering) {
   TimerMarker T(TimerStack::TT_emitGlobalInitializers, Ctx);
-  const bool DumpGlobalVariables = ALLOW_DUMP && Ctx->getVerbose() &&
+  const bool DumpGlobalVariables = ALLOW_DUMP && Ctx->getFlags().getVerbose() &&
                                    Ctx->getFlags().getVerboseFocusOn().empty();
   if (DumpGlobalVariables) {
     OstreamLocker L(Ctx);
@@ -459,10 +456,11 @@
   //   _Z3barxyz ==> ZN6Prefix3barExyz
   // An unmangled, extern "C" style name, gets a simple prefix:
   //   bar ==> Prefixbar
-  if (!ALLOW_DUMP || getTestPrefix().empty())
+  if (!ALLOW_DUMP || getFlags().getTestPrefix().empty())
     return Name;
 
-  unsigned PrefixLength = getTestPrefix().length();
+  const IceString &TestPrefix = getFlags().getTestPrefix();
+  unsigned PrefixLength = TestPrefix.length();
   ManglerVector NameBase(1 + Name.length());
   const size_t BufLen = 30 + Name.length() + PrefixLength;
   ManglerVector NewName(BufLen);
@@ -473,7 +471,7 @@
     // Transform _ZN3foo3barExyz ==> _ZN6Prefix3foo3barExyz
     //   (splice in "6Prefix")          ^^^^^^^
     snprintf(NewName.data(), BufLen, "_ZN%u%s%s", PrefixLength,
-             getTestPrefix().c_str(), NameBase.data());
+             TestPrefix.c_str(), NameBase.data());
     // We ignore the snprintf return value (here and below).  If we
     // somehow miscalculated the output buffer length, the output will
     // be truncated, but it will be truncated consistently for all
@@ -512,7 +510,7 @@
     OrigName[ActualBaseLength] = '\0';
     strcpy(OrigSuffix.data(), NameBase.data() + ActualBaseLength);
     snprintf(NewName.data(), BufLen, "_ZN%u%s%u%sE%s", PrefixLength,
-             getTestPrefix().c_str(), BaseLength, OrigName.data(),
+             TestPrefix.c_str(), BaseLength, OrigName.data(),
              OrigSuffix.data());
     incrementSubstitutions(NewName);
     return NewName.data();
@@ -520,7 +518,7 @@
 
   // Transform bar ==> Prefixbar
   //                   ^^^^^^
-  return getTestPrefix() + Name;
+  return TestPrefix + Name;
 }
 
 GlobalContext::~GlobalContext() {
diff --git a/src/IceGlobalContext.h b/src/IceGlobalContext.h
index ec821c0..a709981 100644
--- a/src/IceGlobalContext.h
+++ b/src/IceGlobalContext.h
@@ -146,12 +146,9 @@
 
 public:
   GlobalContext(Ostream *OsDump, Ostream *OsEmit, ELFStreamer *ELFStreamer,
-                VerboseMask Mask, TargetArch Arch, OptLevel Opt,
-                IceString TestPrefix, const ClFlags &Flags);
+                const ClFlags &Flags);
   ~GlobalContext();
 
-  VerboseMask getVerbose() const { return VMask; }
-
   // The dump and emit streams need to be used by only one thread at a
   // time.  This is done by exclusively reserving the streams via
   // lockStr() and unlockStr().  The OstreamLocker class can be used
@@ -168,8 +165,6 @@
   Ostream &getStrDump() { return *StrDump; }
   Ostream &getStrEmit() { return *StrEmit; }
 
-  TargetArch getTargetArch() const { return Arch; }
-  OptLevel getOptLevel() const { return Opt; }
   LockedPtr<ErrorCode> getErrorStatus() {
     return LockedPtr<ErrorCode>(&ErrorStatus, &ErrorStatusLock);
   }
@@ -178,7 +173,6 @@
   // names of translated functions.  This makes it easier to create an
   // execution test against a reference translator like llc, with both
   // translators using the same bitcode as input.
-  IceString getTestPrefix() const { return TestPrefix; }
   IceString mangleName(const IceString &Name) const;
 
   // Manage Constants.
@@ -419,11 +413,7 @@
 
   ICE_CACHELINE_BOUNDARY;
 
-  const VerboseMask VMask;
   Intrinsics IntrinsicsInfo;
-  const TargetArch Arch;
-  const OptLevel Opt;
-  const IceString TestPrefix;
   const ClFlags &Flags;
   RandomNumberGenerator RNG; // TODO(stichnot): Move into Cfg.
   std::unique_ptr<ELFObjectWriter> ObjectWriter;
diff --git a/src/IceRNG.cpp b/src/IceRNG.cpp
index 03171ad..43c7f07 100644
--- a/src/IceRNG.cpp
+++ b/src/IceRNG.cpp
@@ -13,24 +13,12 @@
 
 #include <time.h>
 
-#include "llvm/Support/CommandLine.h"
-
 #include "IceRNG.h"
 
 namespace Ice {
 
 namespace {
-namespace cl = llvm::cl;
-
-// TODO(stichnot): See if we can easily use LLVM's -rng-seed option
-// and implementation.  I expect the implementation is different and
-// therefore the tests would need to be changed.
-cl::opt<unsigned long long>
-    RandomSeed("sz-seed", cl::desc("Seed the random number generator"),
-               cl::init(time(0)));
-
 const unsigned MAX = 2147483647;
-
 } // end of anonymous namespace
 
 // TODO(wala,stichnot): Switch to RNG implementation from LLVM or C++11.
@@ -39,8 +27,8 @@
 // subsequent run, for reproducing a bug.  Print the seed in a comment
 // in the asm output.  Embed the seed in the binary via metadata that an
 // attacker can't introspect.
-RandomNumberGenerator::RandomNumberGenerator(llvm::StringRef)
-    : State(RandomSeed) {}
+RandomNumberGenerator::RandomNumberGenerator(uint64_t Seed, llvm::StringRef)
+    : State(Seed) {}
 
 uint64_t RandomNumberGenerator::next(uint64_t Max) {
   // Lewis, Goodman, and Miller (1969)
diff --git a/src/IceRNG.h b/src/IceRNG.h
index 174e3e0..bf01e41 100644
--- a/src/IceRNG.h
+++ b/src/IceRNG.h
@@ -27,7 +27,7 @@
   RandomNumberGenerator &operator=(const RandomNumberGenerator &) = delete;
 
 public:
-  explicit RandomNumberGenerator(llvm::StringRef Salt);
+  explicit RandomNumberGenerator(uint64_t Seed, llvm::StringRef Salt = "");
   uint64_t next(uint64_t Max);
 
 private:
diff --git a/src/IceTargetLowering.cpp b/src/IceTargetLowering.cpp
index 3ea9e6d..39d27fe 100644
--- a/src/IceTargetLowering.cpp
+++ b/src/IceTargetLowering.cpp
@@ -15,8 +15,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/Support/CommandLine.h"
-
 #include "assembler_ia32.h"
 #include "IceCfg.h" // setError()
 #include "IceCfgNode.h"
@@ -27,27 +25,6 @@
 
 namespace Ice {
 
-namespace {
-
-// TODO(stichnot): Move this machinery into main.cpp.
-namespace cl = llvm::cl;
-cl::opt<bool> DoNopInsertion("nop-insertion", cl::desc("Randomly insert NOPs"),
-                             cl::init(false));
-
-cl::opt<int> MaxNopsPerInstruction(
-    "max-nops-per-instruction",
-    cl::desc("Max number of nops to insert per instruction"), cl::init(1));
-
-cl::opt<int> NopProbabilityAsPercentage(
-    "nop-insertion-percentage",
-    cl::desc("Nop insertion probability as percentage"), cl::init(10));
-
-cl::opt<bool>
-    CLRandomizeRegisterAllocation("randomize-regalloc",
-                                  cl::desc("Randomize register allocation"),
-                                  cl::init(false));
-} // end of anonymous namespace
-
 void LoweringContext::init(CfgNode *N) {
   Node = N;
   End = getNode()->getInsts().end();
@@ -102,10 +79,9 @@
 }
 
 TargetLowering::TargetLowering(Cfg *Func)
-    : Func(Func), Ctx(Func->getContext()),
-      RandomizeRegisterAllocation(CLRandomizeRegisterAllocation),
-      HasComputedFrame(false), CallsReturnsTwice(false), StackAdjustment(0),
-      Context(), SnapshotStackAdjustment(0) {}
+    : Func(Func), Ctx(Func->getContext()), HasComputedFrame(false),
+      CallsReturnsTwice(false), StackAdjustment(0), Context(),
+      SnapshotStackAdjustment(0) {}
 
 std::unique_ptr<Assembler> TargetLowering::createAssembler(TargetArch Target,
                                                            Cfg *Func) {
@@ -126,16 +102,15 @@
   Context.advanceNext();
 }
 
-bool TargetLowering::shouldDoNopInsertion() const { return DoNopInsertion; }
-
 void TargetLowering::doNopInsertion() {
   Inst *I = Context.getCur();
   bool ShouldSkip = llvm::isa<InstFakeUse>(I) || llvm::isa<InstFakeDef>(I) ||
                     llvm::isa<InstFakeKill>(I) || I->isRedundantAssign() ||
                     I->isDeleted();
   if (!ShouldSkip) {
-    for (int I = 0; I < MaxNopsPerInstruction; ++I) {
-      randomlyInsertNop(NopProbabilityAsPercentage / 100.0);
+    int Probability = Ctx->getFlags().getNopProbabilityAsPercentage();
+    for (int I = 0; I < Ctx->getFlags().getMaxNopsPerInstruction(); ++I) {
+      randomlyInsertNop(Probability / 100.0);
     }
   }
 }
@@ -251,14 +226,14 @@
     RegExclude |= RegSet_FramePointer;
   LinearScan.init(Kind);
   llvm::SmallBitVector RegMask = getRegisterSet(RegInclude, RegExclude);
-  LinearScan.scan(RegMask, RandomizeRegisterAllocation);
+  LinearScan.scan(RegMask, Ctx->getFlags().shouldRandomizeRegAlloc());
 }
 
 std::unique_ptr<TargetDataLowering>
 TargetDataLowering::createLowering(GlobalContext *Ctx) {
   // These statements can be #ifdef'd to specialize the code generator
   // to a subset of the available targets.  TODO: use CRTP.
-  TargetArch Target = Ctx->getTargetArch();
+  TargetArch Target = Ctx->getFlags().getTargetArch();
   if (Target == Target_X8632)
     return std::unique_ptr<TargetDataLowering>(TargetDataX8632::create(Ctx));
 #if 0
diff --git a/src/IceTargetLowering.h b/src/IceTargetLowering.h
index 8b4bd27..112572c 100644
--- a/src/IceTargetLowering.h
+++ b/src/IceTargetLowering.h
@@ -99,7 +99,7 @@
   static std::unique_ptr<Assembler> createAssembler(TargetArch Target,
                                                     Cfg *Func);
   void translate() {
-    switch (Ctx->getOptLevel()) {
+    switch (Ctx->getFlags().getOptLevel()) {
     case Opt_m1:
       translateOm1();
       break;
@@ -164,7 +164,6 @@
   virtual SizeT getFrameOrStackReg() const = 0;
   virtual size_t typeWidthInBytesOnStack(Type Ty) const = 0;
   bool hasComputedFrame() const { return HasComputedFrame; }
-  bool shouldDoNopInsertion() const;
   // Returns true if this function calls a function that has the
   // "returns twice" attribute.
   bool callsReturnsTwice() const { return CallsReturnsTwice; }
@@ -244,7 +243,6 @@
 
   Cfg *Func;
   GlobalContext *Ctx;
-  const bool RandomizeRegisterAllocation;
   bool HasComputedFrame;
   bool CallsReturnsTwice;
   // StackAdjustment keeps track of the current stack offset from its
diff --git a/src/IceTargetLoweringX8632.cpp b/src/IceTargetLoweringX8632.cpp
index 0a41cc8..84333b4 100644
--- a/src/IceTargetLoweringX8632.cpp
+++ b/src/IceTargetLoweringX8632.cpp
@@ -13,7 +13,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/MathExtras.h"
 
 #include "IceCfg.h"
@@ -153,16 +152,6 @@
   return applyAlignment(Value, X86_STACK_ALIGNMENT_BYTES);
 }
 
-// Instruction set options
-namespace cl = ::llvm::cl;
-cl::opt<TargetX8632::X86InstructionSet> CLInstructionSet(
-    "mattr", cl::desc("X86 target attributes"), cl::init(TargetX8632::SSE2),
-    cl::values(clEnumValN(TargetX8632::SSE2, "sse2",
-                          "Enable SSE2 instructions (default)"),
-               clEnumValN(TargetX8632::SSE4_1, "sse4.1",
-                          "Enable SSE 4.1 instructions"),
-               clEnumValEnd));
-
 // In some cases, there are x-macros tables for both high-level and
 // low-level instructions/operands that use the same enum key value.
 // The tables are kept separate to maintain a proper separation
@@ -272,9 +261,16 @@
 } // end of anonymous namespace
 
 TargetX8632::TargetX8632(Cfg *Func)
-    : TargetLowering(Func), InstructionSet(CLInstructionSet),
+    : TargetLowering(Func),
+      InstructionSet(static_cast<X86InstructionSet>(
+          Func->getContext()->getFlags().getTargetInstructionSet() -
+          TargetInstructionSet::X86InstructionSet_Begin)),
       IsEbpBasedFrame(false), NeedsStackAlignment(false), FrameSizeLocals(0),
       SpillAreaSizeBytes(0), NextLabelNumber(0) {
+  static_assert((X86InstructionSet::End - X86InstructionSet::Begin) ==
+                    (TargetInstructionSet::X86InstructionSet_End -
+                     TargetInstructionSet::X86InstructionSet_Begin),
+                "X86InstructionSet range different from TargetInstructionSet");
   // TODO: Don't initialize IntegerRegisters and friends every time.
   // Instead, initialize in some sort of static initializer for the
   // class.
@@ -400,7 +396,7 @@
   Func->dump("After branch optimization");
 
   // Nop insertion
-  if (shouldDoNopInsertion()) {
+  if (Ctx->getFlags().shouldDoNopInsertion()) {
     Func->doNopInsertion();
   }
 }
@@ -437,7 +433,7 @@
   Func->dump("After stack frame mapping");
 
   // Nop insertion
-  if (shouldDoNopInsertion()) {
+  if (Ctx->getFlags().shouldDoNopInsertion()) {
     Func->doNopInsertion();
   }
 }
@@ -3230,7 +3226,7 @@
 bool TargetX8632::tryOptimizedCmpxchgCmpBr(Variable *Dest, Operand *PtrToMem,
                                            Operand *Expected,
                                            Operand *Desired) {
-  if (Ctx->getOptLevel() == Opt_m1)
+  if (Ctx->getFlags().getOptLevel() == Opt_m1)
     return false;
   // Peek ahead a few instructions and see how Dest is used.
   // It's very common to have:
@@ -4543,7 +4539,7 @@
 }
 
 void TargetX8632::postLower() {
-  if (Ctx->getOptLevel() == Opt_m1)
+  if (Ctx->getFlags().getOptLevel() == Opt_m1)
     return;
   // Find two-address non-SSA instructions where Dest==Src0, and set
   // the DestNonKillable flag to keep liveness analysis consistent.
diff --git a/src/IceTargetLoweringX8632.h b/src/IceTargetLoweringX8632.h
index aa16010..74e0d50 100644
--- a/src/IceTargetLoweringX8632.h
+++ b/src/IceTargetLoweringX8632.h
@@ -71,9 +71,11 @@
   x86::Address stackVarToAsmOperand(const Variable *Var) const;
 
   enum X86InstructionSet {
+    Begin,
     // SSE2 is the PNaCl baseline instruction set.
-    SSE2,
-    SSE4_1
+    SSE2 = Begin,
+    SSE4_1,
+    End
   };
 
   X86InstructionSet getInstructionSet() const { return InstructionSet; }
diff --git a/src/IceTypes.h b/src/IceTypes.h
index 2cf5e40..297fad3 100644
--- a/src/IceTypes.h
+++ b/src/IceTypes.h
@@ -40,6 +40,16 @@
   return Stream << targetArchString(Arch);
 }
 
+// The list of all target instruction sets. Individual targets will
+// map this to include only what is valid for the target.
+enum TargetInstructionSet {
+  X86InstructionSet_Begin,
+  // SSE2 is the PNaCl baseline instruction set.
+  X86InstructionSet_SSE2 = X86InstructionSet_Begin,
+  X86InstructionSet_SSE4_1,
+  X86InstructionSet_End,
+};
+
 enum OptLevel { Opt_m1, Opt_0, Opt_1, Opt_2 };
 
 size_t typeWidthInBytes(Type Ty);
diff --git a/src/main.cpp b/src/main.cpp
index bd96142..9858fa2 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -69,6 +69,16 @@
         clEnumValN(Ice::Target_ARM32, "arm", "arm32"),
         clEnumValN(Ice::Target_ARM32, "arm32", "arm32 (same as arm)"),
         clEnumValN(Ice::Target_ARM64, "arm64", "arm64"), clEnumValEnd));
+
+cl::opt<Ice::TargetInstructionSet> InstructionSet(
+    "mattr", cl::desc("Target architecture attributes"),
+    cl::init(Ice::X86InstructionSet_SSE2),
+    cl::values(clEnumValN(Ice::X86InstructionSet_SSE2, "sse2",
+                          "Enable SSE2 instructions (default)"),
+               clEnumValN(Ice::X86InstructionSet_SSE4_1, "sse4.1",
+                          "Enable SSE 4.1 instructions"),
+               clEnumValEnd));
+
 static cl::opt<bool> UseSandboxing("sandbox", cl::desc("Use sandboxing"));
 static cl::opt<bool>
     FunctionSections("ffunction-sections",
@@ -211,6 +221,30 @@
     // something related to std::thread::hardware_concurrency().
     cl::init(2));
 
+static cl::opt<bool> DoNopInsertion("nop-insertion",
+                                    cl::desc("Randomly insert NOPs"),
+                                    cl::init(false));
+
+static cl::opt<int> MaxNopsPerInstruction(
+    "max-nops-per-instruction",
+    cl::desc("Max number of nops to insert per instruction"), cl::init(1));
+
+static cl::opt<int> NopProbabilityAsPercentage(
+    "nop-insertion-percentage",
+    cl::desc("Nop insertion probability as percentage"), cl::init(10));
+
+static cl::opt<bool>
+    RandomizeRegisterAllocation("randomize-regalloc",
+                                cl::desc("Randomize register allocation"),
+                                cl::init(false));
+
+// TODO(stichnot): See if we can easily use LLVM's -rng-seed option
+// and implementation.  I expect the implementation is different and
+// therefore the tests would need to be changed.
+cl::opt<unsigned long long>
+    RandomSeed("sz-seed", cl::desc("Seed the random number generator"),
+               cl::init(time(0)));
+
 static int GetReturnValue(int Val) {
   if (AlwaysExitSuccess)
     return 0;
@@ -304,14 +338,24 @@
   Flags.setDumpStats(DumpStats);
   Flags.setFunctionSections(FunctionSections);
   Flags.setNumTranslationThreads(NumThreads);
+  Flags.setOptLevel(OptLevel);
   Flags.setPhiEdgeSplit(EnablePhiEdgeSplit);
+  Flags.setRandomSeed(RandomSeed);
+  Flags.setShouldDoNopInsertion(DoNopInsertion);
+  Flags.setShouldRandomizeRegAlloc(RandomizeRegisterAllocation);
   Flags.setSubzeroTimingEnabled(SubzeroTimingEnabled);
+  Flags.setTargetArch(TargetArch);
+  Flags.setTargetInstructionSet(InstructionSet);
+  Flags.setTestPrefix(TestPrefix);
   Flags.setTimeEachFunction(TimeEachFunction);
   Flags.setTimingFocusOn(TimingFocusOn);
   Flags.setTranslateOnly(TranslateOnly);
   Flags.setUseSandboxing(UseSandboxing);
   Flags.setVerboseFocusOn(VerboseFocusOn);
   Flags.setOutFileType(OutFileType);
+  Flags.setMaxNopsPerInstruction(MaxNopsPerInstruction);
+  Flags.setNopProbabilityAsPercentage(NopProbabilityAsPercentage);
+  Flags.setVerbose(VMask);
 
   // Force -build-on-read=0 for .ll files.
   const std::string LLSuffix = ".ll";
@@ -357,8 +401,7 @@
   } break;
   }
 
-  Ice::GlobalContext Ctx(Ls.get(), Os.get(), ELFStr.get(), VMask, TargetArch,
-                         OptLevel, TestPrefix, Flags);
+  Ice::GlobalContext Ctx(Ls.get(), Os.get(), ELFStr.get(), Flags);
 
   Ice::TimerMarker T(Ice::TimerStack::TT_szmain, &Ctx);
 
diff --git a/unittest/BitcodeMunge.cpp b/unittest/BitcodeMunge.cpp
index 2b7b918..fd7100c 100644
--- a/unittest/BitcodeMunge.cpp
+++ b/unittest/BitcodeMunge.cpp
@@ -28,10 +28,11 @@
   Ice::ClFlags Flags;
   Flags.setAllowErrorRecovery(true);
   Flags.setGenerateUnitTestMessages(true);
+  Flags.setOptLevel(Ice::Opt_m1);
   Flags.setOutFileType(Ice::FT_Iasm);
-  Ice::GlobalContext Ctx(DumpStream, DumpStream, nullptr,
-                         Ice::IceV_Instructions, Ice::Target_X8632, Ice::Opt_m1,
-                         "", Flags);
+  Flags.setTargetArch(Ice::Target_X8632);
+  Flags.setVerbose(Ice::IceV_Instructions);
+  Ice::GlobalContext Ctx(DumpStream, DumpStream, nullptr, Flags);
   Ice::PNaClTranslator Translator(&Ctx);
   Translator.translateBuffer(TestName, MungedInput.get());