Subzero: Remove IceString.

The purpose is to get control over excess string creation and deletion, especially when the strings are long enough to involve malloc/free.

Strings that interface with the outside world, or used for dump/debug, are now explicitly std::string.

Variable names and node names are represented as string IDs and pooled locally in the CFG.  (In a non-DUMP build, this pool should always be empty.)

Other strings that are used across functions are represented as string IDs and pooled globally in the GlobalContext.

The --dump-strings flag allows these strings to be dumped for sanity checking, even in a MINIMAL build.  In a MINIMAL build, the set of strings includes external symbol names, intrinsic names, helper function names, and label names of pooled constants to facilitate deterministic ELF string table output.  For now, it also includes jump table entry names until that gets sorted out.

Constants are fixed so that the name and pooled fields are properly immutable after the constant is fully initialized.

BUG= https://bugs.chromium.org/p/nativeclient/issues/detail?id=4360
R=jpp@chromium.org

Review URL: https://codereview.chromium.org/1838753002 .
diff --git a/src/IceCfgNode.cpp b/src/IceCfgNode.cpp
index 212f742..ca3897e 100644
--- a/src/IceCfgNode.cpp
+++ b/src/IceCfgNode.cpp
@@ -26,15 +26,13 @@
 
 namespace Ice {
 
-CfgNode::CfgNode(Cfg *Func, SizeT LabelNumber)
-    : Func(Func), Number(LabelNumber), LabelNumber(LabelNumber) {}
-
-// Returns the name the node was created with. If no name was given, it
-// synthesizes a (hopefully) unique name.
-IceString CfgNode::getName() const {
-  if (NameIndex >= 0)
-    return Func->getIdentifierName(NameIndex);
-  return "__" + std::to_string(LabelNumber);
+CfgNode::CfgNode(Cfg *Func, SizeT Number) : Func(Func), Number(Number) {
+  if (BuildDefs::dump()) {
+    Name =
+        NodeString::createWithString(Func, "__" + std::to_string(getIndex()));
+  } else {
+    Name = NodeString::createWithoutString(Func);
+  }
 }
 
 // Adds an instruction to either the Phi list or the regular instruction list.
@@ -1428,23 +1426,22 @@
 }
 
 void CfgNode::profileExecutionCount(VariableDeclaration *Var) {
-  constexpr char RMW_I64[] = "llvm.nacl.atomic.rmw.i64";
-
-  GlobalContext *Context = Func->getContext();
+  GlobalContext *Ctx = Func->getContext();
+  GlobalString RMW_I64 = Ctx->getGlobalString("llvm.nacl.atomic.rmw.i64");
 
   bool BadIntrinsic = false;
   const Intrinsics::FullIntrinsicInfo *Info =
-      Context->getIntrinsicsInfo().find(RMW_I64, BadIntrinsic);
+      Ctx->getIntrinsicsInfo().find(RMW_I64, BadIntrinsic);
   assert(!BadIntrinsic);
   assert(Info != nullptr);
 
-  Operand *RMWI64Name = Context->getConstantExternSym(RMW_I64);
+  Operand *RMWI64Name = Ctx->getConstantExternSym(RMW_I64);
   constexpr RelocOffsetT Offset = 0;
-  Constant *Counter = Context->getConstantSym(Offset, Var->getName());
-  Constant *AtomicRMWOp = Context->getConstantInt32(Intrinsics::AtomicAdd);
-  Constant *One = Context->getConstantInt64(1);
+  Constant *Counter = Ctx->getConstantSym(Offset, Var->getName());
+  Constant *AtomicRMWOp = Ctx->getConstantInt32(Intrinsics::AtomicAdd);
+  Constant *One = Ctx->getConstantInt64(1);
   Constant *OrderAcquireRelease =
-      Context->getConstantInt32(Intrinsics::MemoryOrderAcquireRelease);
+      Ctx->getConstantInt32(Intrinsics::MemoryOrderAcquireRelease);
 
   auto *Instr = InstIntrinsicCall::create(
       Func, 5, Func->makeVariable(IceType_i64), RMWI64Name, Info->Info);