[lld-macho] Support -add_ast_path

Swift builds seem to use it. All it requires is emitting the
corresponding paths as STABS.

Fixes llvm.org/PR49385.

Reviewed By: clayborg

Differential Revision: https://reviews.llvm.org/D100076

GitOrigin-RevId: c23b92acd0654bd63942fd70d39c7955354ba3f6
diff --git a/MachO/Config.h b/MachO/Config.h
index 693c348..b07c711 100644
--- a/MachO/Config.h
+++ b/MachO/Config.h
@@ -110,6 +110,7 @@
   std::vector<llvm::StringRef> librarySearchPaths;
   std::vector<llvm::StringRef> frameworkSearchPaths;
   std::vector<llvm::StringRef> runtimePaths;
+  std::vector<std::string> astPaths;
   std::vector<Symbol *> explicitUndefineds;
   // There are typically very few custom segmentProtections, so use a vector
   // instead of a map.
diff --git a/MachO/Driver.cpp b/MachO/Driver.cpp
index 7f34157..8175afe 100644
--- a/MachO/Driver.cpp
+++ b/MachO/Driver.cpp
@@ -913,6 +913,7 @@
 
   config->mapFile = args.getLastArgValue(OPT_map);
   config->outputFile = args.getLastArgValue(OPT_o, "a.out");
+  config->astPaths = args.getAllArgValues(OPT_add_ast_path);
   config->headerPad = args::getHex(args, OPT_headerpad, /*Default=*/32);
   config->headerPadMaxInstallNames =
       args.hasArg(OPT_headerpad_max_install_names);
diff --git a/MachO/Options.td b/MachO/Options.td
index e4bdc4b..23a9034 100644
--- a/MachO/Options.td
+++ b/MachO/Options.td
@@ -511,7 +511,7 @@
     HelpText<"Save intermediate LTO compilation results">,
     Group<grp_introspect>;
 
-def grp_symtab : OptionGroup<"symtab">, HelpText<"SYMBOL TABLE OPTIMIZATIONS">;
+def grp_symtab : OptionGroup<"symtab">, HelpText<"SYMBOL TABLE">;
 
 def S : Flag<["-"], "S">,
     HelpText<"Strip debug information (STABS or DWARF) from the output">,
@@ -536,6 +536,10 @@
     HelpText<"Remove the prefix <path> from OSO symbols in the debug map">,
     Flags<[HelpHidden]>,
     Group<grp_symtab>;
+def add_ast_path : Separate<["-"], "add_ast_path">,
+    MetaVarName<"<path>">,
+    HelpText<"AST paths will be emitted as STABS">,
+    Group<grp_symtab>;
 
 def grp_bitcode : OptionGroup<"bitcode">, HelpText<"BITCODE BUILD FLOW">;
 
@@ -1092,10 +1096,6 @@
 
 def grp_undocumented : OptionGroup<"undocumented">, HelpText<"UNDOCUMENTED">;
 
-def add_ast_path : Flag<["-"], "add_ast_path">,
-    HelpText<"This option is undocumented in ld64">,
-    Flags<[HelpHidden]>,
-    Group<grp_undocumented>;
 def add_linker_option : Flag<["-"], "add_linker_option">,
     HelpText<"This option is undocumented in ld64">,
     Flags<[HelpHidden]>,
diff --git a/MachO/SyntheticSections.cpp b/MachO/SyntheticSections.cpp
index 5bba34d..60fd36d 100644
--- a/MachO/SyntheticSections.cpp
+++ b/MachO/SyntheticSections.cpp
@@ -680,6 +680,12 @@
 }
 
 void SymtabSection::emitStabs() {
+  for (const std::string &s : config->astPaths) {
+    StabsEntry astStab(N_AST);
+    astStab.strx = stringTableSection.addString(s);
+    stabs.emplace_back(std::move(astStab));
+  }
+
   std::vector<Defined *> symbolsNeedingStabs;
   for (const SymtabEntry &entry :
        concat<SymtabEntry>(localSymbols, externalSymbols)) {
@@ -705,8 +711,7 @@
   InputFile *lastFile = nullptr;
   for (Defined *defined : symbolsNeedingStabs) {
     InputSection *isec = defined->isec;
-    ObjFile *file = dyn_cast<ObjFile>(isec->file);
-    assert(file);
+    ObjFile *file = cast<ObjFile>(isec->file);
 
     if (lastFile == nullptr || lastFile != file) {
       if (lastFile != nullptr)
diff --git a/test/MachO/add-ast-path.s b/test/MachO/add-ast-path.s
new file mode 100644
index 0000000..c8d6359
--- /dev/null
+++ b/test/MachO/add-ast-path.s
@@ -0,0 +1,11 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.o
+# RUN: %lld -lSystem %t.o -o %t -add_ast_path asdf -add_ast_path fdsa
+# RUN: dsymutil -s %t | FileCheck %s
+# CHECK:      [     0] {{[0-9a-f]+}} 32 (N_AST        ) 00     0000   0000000000000000 'asdf'
+# CHECK-NEXT: [     1] {{[0-9a-f]+}} 32 (N_AST        ) 00     0000   0000000000000000 'fdsa'
+
+.globl _main
+
+_main:
+  ret