[lld] r304381 - Move name lookup to script parsing time.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Wed May 31 18:16:50 PDT 2017


Author: rafael
Date: Wed May 31 20:16:50 2017
New Revision: 304381

URL: http://llvm.org/viewvc/llvm-project?rev=304381&view=rev
Log:
Move name lookup to script parsing time.

We were looking up sections by name during expression evaluation. By
keeping track of forward declarations we can do the lookup during
script parsing.

Doing the lookup earlier will be more efficient when assignAddresses
is run twice and removes two uses of OutputSections.

Modified:
    lld/trunk/ELF/LinkerScript.cpp
    lld/trunk/ELF/LinkerScript.h
    lld/trunk/ELF/ScriptParser.cpp

Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=304381&r1=304380&r2=304381&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Wed May 31 20:16:50 2017
@@ -84,29 +84,28 @@ template <class ELFT> static SymbolBody
   return Sym->body();
 }
 
-OutputSection *LinkerScript::getOutputSection(const Twine &Loc,
-                                              StringRef Name) {
-  for (OutputSection *Sec : *OutputSections)
-    if (Sec->Name == Name)
-      return Sec;
-
-  static OutputSection Dummy("", 0, 0);
-  if (ErrorOnMissingSection)
-    error(Loc + ": undefined section " + Name);
-  return &Dummy;
+OutputSectionCommand *
+LinkerScript::createOutputSectionCommand(StringRef Name, StringRef Location) {
+  OutputSectionCommand *&CmdRef = NameToOutputSectionCommand[Name];
+  OutputSectionCommand *Cmd;
+  if (CmdRef && CmdRef->Location.empty()) {
+    // There was a forward reference.
+    Cmd = CmdRef;
+  } else {
+    Cmd = make<OutputSectionCommand>(Name);
+    if (!CmdRef)
+      CmdRef = Cmd;
+  }
+  Cmd->Location = Location;
+  return Cmd;
 }
 
-// This function is essentially the same as getOutputSection(Name)->Size,
-// but it won't print out an error message if a given section is not found.
-//
-// Linker script does not create an output section if its content is empty.
-// We want to allow SIZEOF(.foo) where .foo is a section which happened to
-// be empty. That is why this function is different from getOutputSection().
-uint64_t LinkerScript::getOutputSectionSize(StringRef Name) {
-  for (OutputSection *Sec : *OutputSections)
-    if (Sec->Name == Name)
-      return Sec->Size;
-  return 0;
+OutputSectionCommand *
+LinkerScript::getOrCreateOutputSectionCommand(StringRef Name) {
+  OutputSectionCommand *&CmdRef = NameToOutputSectionCommand[Name];
+  if (!CmdRef)
+    CmdRef = make<OutputSectionCommand>(Name);
+  return CmdRef;
 }
 
 void LinkerScript::setDot(Expr E, const Twine &Loc, bool InSec) {
@@ -456,7 +455,7 @@ void LinkerScript::fabricateDefaultComma
   // For each OutputSection that needs a VA fabricate an OutputSectionCommand
   // with an InputSectionDescription describing the InputSections
   for (OutputSection *Sec : *OutputSections) {
-    auto *OSCmd = make<OutputSectionCommand>(Sec->Name);
+    auto *OSCmd = createOutputSectionCommand(Sec->Name, "<internal>");
     OSCmd->Sec = Sec;
     SecToCommand[Sec] = OSCmd;
 
@@ -843,7 +842,7 @@ void LinkerScript::placeOrphanSections()
     // representations agree on which input sections to use.
     OutputSectionCommand *Cmd = getCmd(Sec);
     if (!Cmd) {
-      Cmd = make<OutputSectionCommand>(Name);
+      Cmd = createOutputSectionCommand(Name, "<internal>");
       Opt.Commands.insert(CmdIter, Cmd);
       ++CmdIndex;
 

Modified: lld/trunk/ELF/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.h?rev=304381&r1=304380&r2=304381&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.h (original)
+++ lld/trunk/ELF/LinkerScript.h Wed May 31 20:16:50 2017
@@ -221,6 +221,8 @@ struct ScriptConfiguration {
 
 class LinkerScript final {
   llvm::DenseMap<OutputSection *, OutputSectionCommand *> SecToCommand;
+  llvm::DenseMap<StringRef, OutputSectionCommand *> NameToOutputSectionCommand;
+
   void assignSymbol(SymbolAssignment *Cmd, bool InSec);
   void setDot(Expr E, const Twine &Loc, bool InSec);
 
@@ -241,7 +243,6 @@ class LinkerScript final {
   void process(BaseCommand &Base);
 
   OutputSection *Aether;
-  bool ErrorOnMissingSection = false;
 
   uint64_t Dot;
   uint64_t ThreadBssOffset = 0;
@@ -251,11 +252,14 @@ class LinkerScript final {
   MemoryRegion *CurMemRegion = nullptr;
 
 public:
+  bool ErrorOnMissingSection = false;
+  OutputSectionCommand *createOutputSectionCommand(StringRef Name,
+                                                   StringRef Location);
+  OutputSectionCommand *getOrCreateOutputSectionCommand(StringRef Name);
+
   OutputSectionCommand *getCmd(OutputSection *Sec) const;
   bool hasPhdrsCommands() { return !Opt.PhdrsCommands.empty(); }
   uint64_t getDot() { return Dot; }
-  OutputSection *getOutputSection(const Twine &Loc, StringRef S);
-  uint64_t getOutputSectionSize(StringRef S);
   void discard(ArrayRef<InputSectionBase *> V);
 
   ExprValue getSymbolValue(const Twine &Loc, StringRef S);

Modified: lld/trunk/ELF/ScriptParser.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/ScriptParser.cpp?rev=304381&r1=304380&r2=304381&view=diff
==============================================================================
--- lld/trunk/ELF/ScriptParser.cpp (original)
+++ lld/trunk/ELF/ScriptParser.cpp Wed May 31 20:16:50 2017
@@ -55,6 +55,7 @@ public:
 
 private:
   void addFile(StringRef Path);
+  OutputSection *checkSection(OutputSectionCommand *Cmd, StringRef Loccation);
 
   void readAsNeeded();
   void readEntry();
@@ -564,8 +565,8 @@ uint32_t ScriptParser::readFill() {
 
 OutputSectionCommand *
 ScriptParser::readOutputSectionDescription(StringRef OutSec) {
-  OutputSectionCommand *Cmd = make<OutputSectionCommand>(OutSec);
-  Cmd->Location = getCurrentLocation();
+  OutputSectionCommand *Cmd =
+      Script->createOutputSectionCommand(OutSec, getCurrentLocation());
 
   // Read an address expression.
   // https://sourceware.org/binutils/docs/ld/Output-Section-Address.html
@@ -819,6 +820,16 @@ StringRef ScriptParser::readParenLiteral
   return Tok;
 }
 
+OutputSection *ScriptParser::checkSection(OutputSectionCommand *Cmd,
+                                          StringRef Location) {
+  if (Cmd->Location.empty() && Script->ErrorOnMissingSection)
+    error(Location + ": undefined section " + Cmd->Name);
+  if (Cmd->Sec)
+    return Cmd->Sec;
+  static OutputSection Dummy("", 0, 0);
+  return &Dummy;
+}
+
 Expr ScriptParser::readPrimary() {
   if (peek() == "(")
     return readParenExpr();
@@ -847,9 +858,8 @@ Expr ScriptParser::readPrimary() {
   }
   if (Tok == "ADDR") {
     StringRef Name = readParenLiteral();
-    return [=]() -> ExprValue {
-      return {Script->getOutputSection(Location, Name), 0};
-    };
+    OutputSectionCommand *Cmd = Script->getOrCreateOutputSectionCommand(Name);
+    return [=]() -> ExprValue { return {checkSection(Cmd, Location), 0}; };
   }
   if (Tok == "ALIGN") {
     expect("(");
@@ -867,7 +877,8 @@ Expr ScriptParser::readPrimary() {
   }
   if (Tok == "ALIGNOF") {
     StringRef Name = readParenLiteral();
-    return [=] { return Script->getOutputSection(Location, Name)->Alignment; };
+    OutputSectionCommand *Cmd = Script->getOrCreateOutputSectionCommand(Name);
+    return [=] { return checkSection(Cmd, Location)->Alignment; };
   }
   if (Tok == "ASSERT")
     return readAssertExpr();
@@ -912,7 +923,8 @@ Expr ScriptParser::readPrimary() {
   }
   if (Tok == "LOADADDR") {
     StringRef Name = readParenLiteral();
-    return [=] { return Script->getOutputSection(Location, Name)->getLMA(); };
+    OutputSectionCommand *Cmd = Script->getOrCreateOutputSectionCommand(Name);
+    return [=] { return checkSection(Cmd, Location)->getLMA(); };
   }
   if (Tok == "ORIGIN") {
     StringRef Name = readParenLiteral();
@@ -930,7 +942,11 @@ Expr ScriptParser::readPrimary() {
   }
   if (Tok == "SIZEOF") {
     StringRef Name = readParenLiteral();
-    return [=] { return Script->getOutputSectionSize(Name); };
+    OutputSectionCommand *Cmd = Script->getOrCreateOutputSectionCommand(Name);
+    // Linker script does not create an output section if its content is empty.
+    // We want to allow SIZEOF(.foo) where .foo is a section which happened to
+    // be empty.
+    return [=] { return Cmd->Sec ? Cmd->Sec->Size : 0; };
   }
   if (Tok == "SIZEOF_HEADERS")
     return [=] { return elf::getHeaderSize(); };




More information about the llvm-commits mailing list