10b57cec5SDimitry Andric //===- ModuleSymbolTable.cpp - symbol table for in-memory IR --------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This class represents a symbol table built from in-memory IR. It provides
100b57cec5SDimitry Andric // access to GlobalValues and should only be used if such access is required
110b57cec5SDimitry Andric // (e.g. in the LTO implementation).
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "llvm/Object/ModuleSymbolTable.h"
160b57cec5SDimitry Andric #include "RecordStreamer.h"
170b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
180b57cec5SDimitry Andric #include "llvm/ADT/StringMap.h"
190b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
200b57cec5SDimitry Andric #include "llvm/IR/Function.h"
210b57cec5SDimitry Andric #include "llvm/IR/GlobalAlias.h"
220b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h"
230b57cec5SDimitry Andric #include "llvm/IR/GlobalVariable.h"
245ffd83dbSDimitry Andric #include "llvm/IR/InlineAsm.h"
250b57cec5SDimitry Andric #include "llvm/IR/Module.h"
260b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
270b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
280b57cec5SDimitry Andric #include "llvm/MC/MCInstrInfo.h"
290b57cec5SDimitry Andric #include "llvm/MC/MCObjectFileInfo.h"
300b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmParser.h"
310b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCTargetAsmParser.h"
320b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
330b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
340b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h"
350b57cec5SDimitry Andric #include "llvm/MC/MCTargetOptions.h"
36349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
370b57cec5SDimitry Andric #include "llvm/Object/SymbolicFile.h"
380b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
390b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
400b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
410b57cec5SDimitry Andric #include "llvm/Support/SMLoc.h"
420b57cec5SDimitry Andric #include "llvm/Support/SourceMgr.h"
430b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
44*fe013be4SDimitry Andric #include "llvm/TargetParser/Triple.h"
450b57cec5SDimitry Andric #include <algorithm>
460b57cec5SDimitry Andric #include <cassert>
470b57cec5SDimitry Andric #include <cstdint>
480b57cec5SDimitry Andric #include <memory>
490b57cec5SDimitry Andric #include <string>
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric using namespace llvm;
520b57cec5SDimitry Andric using namespace object;
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric void ModuleSymbolTable::addModule(Module *M) {
550b57cec5SDimitry Andric   if (FirstMod)
560b57cec5SDimitry Andric     assert(FirstMod->getTargetTriple() == M->getTargetTriple());
570b57cec5SDimitry Andric   else
580b57cec5SDimitry Andric     FirstMod = M;
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric   for (GlobalValue &GV : M->global_values())
610b57cec5SDimitry Andric     SymTab.push_back(&GV);
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric   CollectAsmSymbols(*M, [this](StringRef Name, BasicSymbolRef::Flags Flags) {
645ffd83dbSDimitry Andric     SymTab.push_back(new (AsmSymbols.Allocate())
655ffd83dbSDimitry Andric                          AsmSymbol(std::string(Name), Flags));
660b57cec5SDimitry Andric   });
670b57cec5SDimitry Andric }
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric static void
700b57cec5SDimitry Andric initializeRecordStreamer(const Module &M,
710b57cec5SDimitry Andric                          function_ref<void(RecordStreamer &)> Init) {
720b57cec5SDimitry Andric   StringRef InlineAsm = M.getModuleInlineAsm();
730b57cec5SDimitry Andric   if (InlineAsm.empty())
740b57cec5SDimitry Andric     return;
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric   std::string Err;
770b57cec5SDimitry Andric   const Triple TT(M.getTargetTriple());
780b57cec5SDimitry Andric   const Target *T = TargetRegistry::lookupTarget(TT.str(), Err);
790b57cec5SDimitry Andric   assert(T && T->hasMCAsmParser());
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric   std::unique_ptr<MCRegisterInfo> MRI(T->createMCRegInfo(TT.str()));
820b57cec5SDimitry Andric   if (!MRI)
830b57cec5SDimitry Andric     return;
840b57cec5SDimitry Andric 
85480093f4SDimitry Andric   MCTargetOptions MCOptions;
86480093f4SDimitry Andric   std::unique_ptr<MCAsmInfo> MAI(T->createMCAsmInfo(*MRI, TT.str(), MCOptions));
870b57cec5SDimitry Andric   if (!MAI)
880b57cec5SDimitry Andric     return;
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric   std::unique_ptr<MCSubtargetInfo> STI(
910b57cec5SDimitry Andric       T->createMCSubtargetInfo(TT.str(), "", ""));
920b57cec5SDimitry Andric   if (!STI)
930b57cec5SDimitry Andric     return;
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric   std::unique_ptr<MCInstrInfo> MCII(T->createMCInstrInfo());
960b57cec5SDimitry Andric   if (!MCII)
970b57cec5SDimitry Andric     return;
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric   std::unique_ptr<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer(InlineAsm));
1000b57cec5SDimitry Andric   SourceMgr SrcMgr;
1010b57cec5SDimitry Andric   SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc());
102fe6060f1SDimitry Andric 
103fe6060f1SDimitry Andric   MCContext MCCtx(TT, MAI.get(), MRI.get(), STI.get(), &SrcMgr);
104fe6060f1SDimitry Andric   std::unique_ptr<MCObjectFileInfo> MOFI(
105fe6060f1SDimitry Andric       T->createMCObjectFileInfo(MCCtx, /*PIC=*/false));
106fe6060f1SDimitry Andric   MOFI->setSDKVersion(M.getSDKVersion());
107fe6060f1SDimitry Andric   MCCtx.setObjectFileInfo(MOFI.get());
108fe6060f1SDimitry Andric   RecordStreamer Streamer(MCCtx, M);
109fe6060f1SDimitry Andric   T->createNullTargetStreamer(Streamer);
110fe6060f1SDimitry Andric 
1110b57cec5SDimitry Andric   std::unique_ptr<MCAsmParser> Parser(
1120b57cec5SDimitry Andric       createMCAsmParser(SrcMgr, MCCtx, Streamer, *MAI));
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric   std::unique_ptr<MCTargetAsmParser> TAP(
1150b57cec5SDimitry Andric       T->createMCAsmParser(*STI, *Parser, *MCII, MCOptions));
1160b57cec5SDimitry Andric   if (!TAP)
1170b57cec5SDimitry Andric     return;
1180b57cec5SDimitry Andric 
1195ffd83dbSDimitry Andric   // Module-level inline asm is assumed to use At&t syntax (see
1205ffd83dbSDimitry Andric   // AsmPrinter::doInitialization()).
1215ffd83dbSDimitry Andric   Parser->setAssemblerDialect(InlineAsm::AD_ATT);
1225ffd83dbSDimitry Andric 
1230b57cec5SDimitry Andric   Parser->setTargetParser(*TAP);
1240b57cec5SDimitry Andric   if (Parser->Run(false))
1250b57cec5SDimitry Andric     return;
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric   Init(Streamer);
1280b57cec5SDimitry Andric }
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric void ModuleSymbolTable::CollectAsmSymbols(
1310b57cec5SDimitry Andric     const Module &M,
1320b57cec5SDimitry Andric     function_ref<void(StringRef, BasicSymbolRef::Flags)> AsmSymbol) {
1330b57cec5SDimitry Andric   initializeRecordStreamer(M, [&](RecordStreamer &Streamer) {
1340b57cec5SDimitry Andric     Streamer.flushSymverDirectives();
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric     for (auto &KV : Streamer) {
1370b57cec5SDimitry Andric       StringRef Key = KV.first();
1380b57cec5SDimitry Andric       RecordStreamer::State Value = KV.second;
1390b57cec5SDimitry Andric       // FIXME: For now we just assume that all asm symbols are executable.
1400b57cec5SDimitry Andric       uint32_t Res = BasicSymbolRef::SF_Executable;
1410b57cec5SDimitry Andric       switch (Value) {
1420b57cec5SDimitry Andric       case RecordStreamer::NeverSeen:
1430b57cec5SDimitry Andric         llvm_unreachable("NeverSeen should have been replaced earlier");
1440b57cec5SDimitry Andric       case RecordStreamer::DefinedGlobal:
1450b57cec5SDimitry Andric         Res |= BasicSymbolRef::SF_Global;
1460b57cec5SDimitry Andric         break;
1470b57cec5SDimitry Andric       case RecordStreamer::Defined:
1480b57cec5SDimitry Andric         break;
1490b57cec5SDimitry Andric       case RecordStreamer::Global:
1500b57cec5SDimitry Andric       case RecordStreamer::Used:
1510b57cec5SDimitry Andric         Res |= BasicSymbolRef::SF_Undefined;
1520b57cec5SDimitry Andric         Res |= BasicSymbolRef::SF_Global;
1530b57cec5SDimitry Andric         break;
1540b57cec5SDimitry Andric       case RecordStreamer::DefinedWeak:
1550b57cec5SDimitry Andric         Res |= BasicSymbolRef::SF_Weak;
1560b57cec5SDimitry Andric         Res |= BasicSymbolRef::SF_Global;
1570b57cec5SDimitry Andric         break;
1580b57cec5SDimitry Andric       case RecordStreamer::UndefinedWeak:
1590b57cec5SDimitry Andric         Res |= BasicSymbolRef::SF_Weak;
1600b57cec5SDimitry Andric         Res |= BasicSymbolRef::SF_Undefined;
1610b57cec5SDimitry Andric       }
1620b57cec5SDimitry Andric       AsmSymbol(Key, BasicSymbolRef::Flags(Res));
1630b57cec5SDimitry Andric     }
1640b57cec5SDimitry Andric   });
1650b57cec5SDimitry Andric }
1660b57cec5SDimitry Andric 
1670b57cec5SDimitry Andric void ModuleSymbolTable::CollectAsmSymvers(
1680b57cec5SDimitry Andric     const Module &M, function_ref<void(StringRef, StringRef)> AsmSymver) {
1690b57cec5SDimitry Andric   initializeRecordStreamer(M, [&](RecordStreamer &Streamer) {
1700b57cec5SDimitry Andric     for (auto &KV : Streamer.symverAliases())
1710b57cec5SDimitry Andric       for (auto &Alias : KV.second)
1720b57cec5SDimitry Andric         AsmSymver(KV.first->getName(), Alias);
1730b57cec5SDimitry Andric   });
1740b57cec5SDimitry Andric }
1750b57cec5SDimitry Andric 
1760b57cec5SDimitry Andric void ModuleSymbolTable::printSymbolName(raw_ostream &OS, Symbol S) const {
177*fe013be4SDimitry Andric   if (isa<AsmSymbol *>(S)) {
178*fe013be4SDimitry Andric     OS << cast<AsmSymbol *>(S)->first;
1790b57cec5SDimitry Andric     return;
1800b57cec5SDimitry Andric   }
1810b57cec5SDimitry Andric 
182*fe013be4SDimitry Andric   auto *GV = cast<GlobalValue *>(S);
1830b57cec5SDimitry Andric   if (GV->hasDLLImportStorageClass())
1840b57cec5SDimitry Andric     OS << "__imp_";
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric   Mang.getNameWithPrefix(OS, GV, false);
1870b57cec5SDimitry Andric }
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric uint32_t ModuleSymbolTable::getSymbolFlags(Symbol S) const {
190*fe013be4SDimitry Andric   if (isa<AsmSymbol *>(S))
191*fe013be4SDimitry Andric     return cast<AsmSymbol *>(S)->second;
1920b57cec5SDimitry Andric 
193*fe013be4SDimitry Andric   auto *GV = cast<GlobalValue *>(S);
1940b57cec5SDimitry Andric 
1950b57cec5SDimitry Andric   uint32_t Res = BasicSymbolRef::SF_None;
1960b57cec5SDimitry Andric   if (GV->isDeclarationForLinker())
1970b57cec5SDimitry Andric     Res |= BasicSymbolRef::SF_Undefined;
1980b57cec5SDimitry Andric   else if (GV->hasHiddenVisibility() && !GV->hasLocalLinkage())
1990b57cec5SDimitry Andric     Res |= BasicSymbolRef::SF_Hidden;
2000b57cec5SDimitry Andric   if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV)) {
2010b57cec5SDimitry Andric     if (GVar->isConstant())
2020b57cec5SDimitry Andric       Res |= BasicSymbolRef::SF_Const;
2030b57cec5SDimitry Andric   }
204349cc55cSDimitry Andric   if (const GlobalObject *GO = GV->getAliaseeObject())
205349cc55cSDimitry Andric     if (isa<Function>(GO) || isa<GlobalIFunc>(GO))
2060b57cec5SDimitry Andric       Res |= BasicSymbolRef::SF_Executable;
2070b57cec5SDimitry Andric   if (isa<GlobalAlias>(GV))
2080b57cec5SDimitry Andric     Res |= BasicSymbolRef::SF_Indirect;
2090b57cec5SDimitry Andric   if (GV->hasPrivateLinkage())
2100b57cec5SDimitry Andric     Res |= BasicSymbolRef::SF_FormatSpecific;
2110b57cec5SDimitry Andric   if (!GV->hasLocalLinkage())
2120b57cec5SDimitry Andric     Res |= BasicSymbolRef::SF_Global;
2130b57cec5SDimitry Andric   if (GV->hasCommonLinkage())
2140b57cec5SDimitry Andric     Res |= BasicSymbolRef::SF_Common;
2150b57cec5SDimitry Andric   if (GV->hasLinkOnceLinkage() || GV->hasWeakLinkage() ||
2160b57cec5SDimitry Andric       GV->hasExternalWeakLinkage())
2170b57cec5SDimitry Andric     Res |= BasicSymbolRef::SF_Weak;
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric   if (GV->getName().startswith("llvm."))
2200b57cec5SDimitry Andric     Res |= BasicSymbolRef::SF_FormatSpecific;
2210b57cec5SDimitry Andric   else if (auto *Var = dyn_cast<GlobalVariable>(GV)) {
2220b57cec5SDimitry Andric     if (Var->getSection() == "llvm.metadata")
2230b57cec5SDimitry Andric       Res |= BasicSymbolRef::SF_FormatSpecific;
2240b57cec5SDimitry Andric   }
2250b57cec5SDimitry Andric 
2260b57cec5SDimitry Andric   return Res;
2270b57cec5SDimitry Andric }
228