Support ABSOLUE keyword in symbol assignments

This patch allows making section defined symbols absolute:
.foo : {
  begin_foo = ABSOLUTE(.);
  *(.foo)
}

Differential revision: https://reviews.llvm.org/D24135

llvm-svn: 280788
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 5f04382..8e0016a 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -56,6 +56,12 @@
   Cmd->Sym = Sym->body();
 }
 
+template <class ELFT> static void addSymbol(SymbolAssignment *Cmd) {
+  if (Cmd->IsAbsolute)
+    addRegular<ELFT>(Cmd);
+  else
+    addSynthetic<ELFT>(Cmd);
+}
 // If a symbol was in PROVIDE(), we need to define it only when
 // it is an undefined symbol.
 template <class ELFT> static bool shouldDefine(SymbolAssignment *Cmd) {
@@ -184,7 +190,7 @@
   for (const std::unique_ptr<BaseCommand> &Base : OutCmd.Commands) {
     if (auto *OutCmd = dyn_cast<SymbolAssignment>(Base.get())) {
       if (shouldDefine<ELFT>(OutCmd))
-        addSynthetic<ELFT>(OutCmd);
+        addSymbol<ELFT>(OutCmd);
       OutCmd->GoesAfter = Ret.empty() ? nullptr : Ret.back();
       continue;
     }
@@ -267,6 +273,26 @@
   }
 }
 
+// Sets value of a section-defined symbol. Two kinds of
+// symbols are processed: synthetic symbols, whose value
+// is an offset from beginning of section and regular
+// symbols whose value is absolute.
+template <class ELFT>
+static void assignSectionSymbol(SymbolAssignment *Cmd,
+                                OutputSectionBase<ELFT> *Sec,
+                                typename ELFT::uint Off) {
+  if (!Cmd->Sym)
+    return;
+
+  if (auto *Body = dyn_cast<DefinedSynthetic<ELFT>>(Cmd->Sym)) {
+    Body->Section = Sec;
+    Body->Value = Cmd->Expression(Sec->getVA() + Off) - Sec->getVA();
+    return;
+  }
+  auto *Body = cast<DefinedRegular<ELFT>>(Cmd->Sym);
+  Body->Value = Cmd->Expression(Sec->getVA() + Off);
+}
+
 // Linker script may define start and end symbols for special section types,
 // like .got, .eh_frame_hdr, .eh_frame and others. Those sections are not a list
 // of regular input input sections, therefore our way of defining symbols for
@@ -280,12 +306,7 @@
 
   for (std::unique_ptr<BaseCommand> &Base : Cmd->Commands) {
     if (auto *AssignCmd = dyn_cast<SymbolAssignment>(Base.get())) {
-      if (auto *Sym = cast_or_null<DefinedSynthetic<ELFT>>(AssignCmd->Sym)) {
-        Sym->Section = Sec;
-        Sym->Value =
-            AssignCmd->Expression(Sec->getVA() + (Start ? 0 : Sec->getSize())) -
-            Sec->getVA();
-      }
+      assignSectionSymbol<ELFT>(AssignCmd, Sec, Start ? 0 : Sec->getSize());
     } else {
       if (!Start && isa<SymbolAssignment>(PrevCmd))
         error("section '" + Sec->getName() +
@@ -322,19 +343,13 @@
       if (D != AssignCmd->GoesAfter)
         break;
 
-      uintX_t Value = AssignCmd->Expression(Sec->getVA() + Off) - Sec->getVA();
       if (AssignCmd->Name == ".") {
         // Update to location counter means update to section size.
-        Off = Value;
+        Off = AssignCmd->Expression(Sec->getVA() + Off) - Sec->getVA();
         Sec->setSize(Off);
         continue;
       }
-
-      if (DefinedSynthetic<ELFT> *Sym =
-              cast_or_null<DefinedSynthetic<ELFT>>(AssignCmd->Sym)) {
-        Sym->Section = OutSec;
-        Sym->Value = Value;
-      }
+      assignSectionSymbol<ELFT>(AssignCmd, Sec, Off);
     }
   };
 
@@ -631,7 +646,7 @@
   unsigned readPhdrType();
   SortKind readSortKind();
   SymbolAssignment *readProvideHidden(bool Provide, bool Hidden);
-  SymbolAssignment *readProvideOrAssignment(StringRef Tok);
+  SymbolAssignment *readProvideOrAssignment(StringRef Tok, bool MakeAbsolute);
   void readSort();
   Expr readAssert();
 
@@ -710,7 +725,7 @@
       readSections();
     } else if (Tok == "VERSION") {
       readVersion();
-    } else if (SymbolAssignment *Cmd = readProvideOrAssignment(Tok)) {
+    } else if (SymbolAssignment *Cmd = readProvideOrAssignment(Tok, true)) {
       if (Opt.HasContents)
         Opt.Commands.emplace_back(Cmd);
       else
@@ -872,7 +887,7 @@
   expect("{");
   while (!Error && !skip("}")) {
     StringRef Tok = next();
-    BaseCommand *Cmd = readProvideOrAssignment(Tok);
+    BaseCommand *Cmd = readProvideOrAssignment(Tok, true);
     if (!Cmd) {
       if (Tok == "ASSERT")
         Cmd = new AssertCommand(readAssert());
@@ -1020,7 +1035,7 @@
 
   while (!Error && !skip("}")) {
     StringRef Tok = next();
-    if (SymbolAssignment *Assignment = readProvideOrAssignment(Tok))
+    if (SymbolAssignment *Assignment = readProvideOrAssignment(Tok, false))
       Cmd->Commands.emplace_back(Assignment);
     else if (Tok == "FILL")
       Cmd->Filler = readFill();
@@ -1063,7 +1078,8 @@
   return Cmd;
 }
 
-SymbolAssignment *ScriptParser::readProvideOrAssignment(StringRef Tok) {
+SymbolAssignment *ScriptParser::readProvideOrAssignment(StringRef Tok,
+                                                        bool MakeAbsolute) {
   SymbolAssignment *Cmd = nullptr;
   if (peek() == "=" || peek() == "+=") {
     Cmd = readAssignment(Tok);
@@ -1075,6 +1091,8 @@
   } else if (Tok == "PROVIDE_HIDDEN") {
     Cmd = readProvideHidden(true, true);
   }
+  if (Cmd && MakeAbsolute)
+    Cmd->IsAbsolute = true;
   return Cmd;
 }
 
@@ -1153,11 +1171,18 @@
 
 SymbolAssignment *ScriptParser::readAssignment(StringRef Name) {
   StringRef Op = next();
+  bool IsAbsolute = false;
+  Expr E;
   assert(Op == "=" || Op == "+=");
-  Expr E = readExpr();
+  if (skip("ABSOLUTE")) {
+    E = readParenExpr();
+    IsAbsolute = true;
+  } else {
+    E = readExpr();
+  }
   if (Op == "+=")
     E = [=](uint64_t Dot) { return getSymbolValue(Name, Dot) + E(Dot); };
-  return new SymbolAssignment(Name, E);
+  return new SymbolAssignment(Name, E, IsAbsolute);
 }
 
 // This is an operator-precedence parser to parse a linker