1 //===-------------------- Layer.cpp - Layer interfaces --------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "llvm/ExecutionEngine/Orc/Layer.h"
11 #include "llvm/Object/ObjectFile.h"
12 
13 namespace llvm {
14 namespace orc {
15 
16 IRLayer::IRLayer(ExecutionSession &ES) : ES(ES) {}
17 IRLayer::~IRLayer() {}
18 
19 Error IRLayer::add(VSO &V, VModuleKey K, std::unique_ptr<Module> M) {
20   return V.define(llvm::make_unique<BasicIRLayerMaterializationUnit>(
21       *this, std::move(K), std::move(M)));
22 }
23 
24 IRMaterializationUnit::IRMaterializationUnit(ExecutionSession &ES,
25                                              std::unique_ptr<Module> M)
26   : MaterializationUnit(SymbolFlagsMap()), M(std::move(M)) {
27 
28   MangleAndInterner Mangle(ES, this->M->getDataLayout());
29   for (auto &G : this->M->global_values()) {
30     if (G.hasName() && !G.isDeclaration() && !G.hasLocalLinkage() &&
31         !G.hasAvailableExternallyLinkage() && !G.hasAppendingLinkage()) {
32       auto MangledName = Mangle(G.getName());
33       SymbolFlags[MangledName] = JITSymbolFlags::fromGlobalValue(G);
34       SymbolToDefinition[MangledName] = &G;
35     }
36   }
37 }
38 
39 IRMaterializationUnit::IRMaterializationUnit(
40     std::unique_ptr<Module> M, SymbolFlagsMap SymbolFlags,
41     SymbolNameToDefinitionMap SymbolToDefinition)
42     : MaterializationUnit(std::move(SymbolFlags)), M(std::move(M)),
43       SymbolToDefinition(std::move(SymbolToDefinition)) {}
44 
45 void IRMaterializationUnit::discard(const VSO &V, SymbolStringPtr Name) {
46   auto I = SymbolToDefinition.find(Name);
47   assert(I != SymbolToDefinition.end() &&
48          "Symbol not provided by this MU, or previously discarded");
49   assert(!I->second->isDeclaration() &&
50          "Discard should only apply to definitions");
51   I->second->setLinkage(GlobalValue::AvailableExternallyLinkage);
52   SymbolToDefinition.erase(I);
53 }
54 
55 BasicIRLayerMaterializationUnit::BasicIRLayerMaterializationUnit(
56     IRLayer &L, VModuleKey K, std::unique_ptr<Module> M)
57   : IRMaterializationUnit(L.getExecutionSession(), std::move(M)),
58       L(L), K(std::move(K)) {}
59 
60 void BasicIRLayerMaterializationUnit::materialize(
61     MaterializationResponsibility R) {
62   L.emit(std::move(R), std::move(K), std::move(M));
63 }
64 
65 ObjectLayer::ObjectLayer(ExecutionSession &ES) : ES(ES) {}
66 
67 ObjectLayer::~ObjectLayer() {}
68 
69 Error ObjectLayer::add(VSO &V, VModuleKey K, std::unique_ptr<MemoryBuffer> O) {
70   auto ObjMU = BasicObjectLayerMaterializationUnit::Create(*this, std::move(K),
71                                                            std::move(O));
72   if (!ObjMU)
73     return ObjMU.takeError();
74   return V.define(std::move(*ObjMU));
75 }
76 
77 Expected<std::unique_ptr<BasicObjectLayerMaterializationUnit>>
78 BasicObjectLayerMaterializationUnit::Create(ObjectLayer &L, VModuleKey K,
79                                             std::unique_ptr<MemoryBuffer> O) {
80   auto SymbolFlags =
81       getObjectSymbolFlags(L.getExecutionSession(), O->getMemBufferRef());
82 
83   if (!SymbolFlags)
84     return SymbolFlags.takeError();
85 
86   return std::unique_ptr<BasicObjectLayerMaterializationUnit>(
87       new BasicObjectLayerMaterializationUnit(L, K, std::move(O),
88                                               std::move(*SymbolFlags)));
89 }
90 
91 BasicObjectLayerMaterializationUnit::BasicObjectLayerMaterializationUnit(
92     ObjectLayer &L, VModuleKey K, std::unique_ptr<MemoryBuffer> O,
93     SymbolFlagsMap SymbolFlags)
94     : MaterializationUnit(std::move(SymbolFlags)), L(L), K(std::move(K)),
95       O(std::move(O)) {}
96 
97 void BasicObjectLayerMaterializationUnit::materialize(
98     MaterializationResponsibility R) {
99   L.emit(std::move(R), std::move(K), std::move(O));
100 }
101 
102 void BasicObjectLayerMaterializationUnit::discard(const VSO &V,
103                                                   SymbolStringPtr Name) {
104   // FIXME: Support object file level discard. This could be done by building a
105   //        filter to pass to the object layer along with the object itself.
106 }
107 
108 Expected<SymbolFlagsMap> getObjectSymbolFlags(ExecutionSession &ES,
109                                               MemoryBufferRef ObjBuffer) {
110   auto Obj = object::ObjectFile::createObjectFile(ObjBuffer);
111 
112   if (!Obj)
113     return Obj.takeError();
114 
115   SymbolFlagsMap SymbolFlags;
116   for (auto &Sym : (*Obj)->symbols()) {
117     if (!(Sym.getFlags() & object::BasicSymbolRef::SF_Undefined) &&
118         (Sym.getFlags() & object::BasicSymbolRef::SF_Exported)) {
119       auto Name = Sym.getName();
120       if (!Name)
121         return Name.takeError();
122       auto InternedName = ES.getSymbolStringPool().intern(*Name);
123       auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
124       if (!SymFlags)
125         return SymFlags.takeError();
126       SymbolFlags[InternedName] = std::move(*SymFlags);
127     }
128   }
129 
130   return SymbolFlags;
131 }
132 
133 } // End namespace orc.
134 } // End namespace llvm.
135