1//===---- IndirectionUtils.cpp - Utilities for call indirection in Orc ----===//
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/ADT/STLExtras.h"
11#include "llvm/ADT/Triple.h"
12#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
13#include "llvm/IR/CallSite.h"
14#include "llvm/IR/IRBuilder.h"
15#include "llvm/Transforms/Utils/Cloning.h"
16#include <set>
17#include <sstream>
18
19namespace llvm {
20namespace orc {
21
22void JITCompileCallbackManager::anchor() {}
23void IndirectStubsManager::anchor() {}
24
25Constant* createIRTypedAddress(FunctionType &FT, TargetAddress Addr) {
26  Constant *AddrIntVal =
27    ConstantInt::get(Type::getInt64Ty(FT.getContext()), Addr);
28  Constant *AddrPtrVal =
29    ConstantExpr::getCast(Instruction::IntToPtr, AddrIntVal,
30                          PointerType::get(&FT, 0));
31  return AddrPtrVal;
32}
33
34GlobalVariable* createImplPointer(PointerType &PT, Module &M,
35                                  const Twine &Name, Constant *Initializer) {
36  auto IP = new GlobalVariable(M, &PT, false, GlobalValue::ExternalLinkage,
37                               Initializer, Name, nullptr,
38                               GlobalValue::NotThreadLocal, 0, true);
39  IP->setVisibility(GlobalValue::HiddenVisibility);
40  return IP;
41}
42
43void makeStub(Function &F, Value &ImplPointer) {
44  assert(F.isDeclaration() && "Can't turn a definition into a stub.");
45  assert(F.getParent() && "Function isn't in a module.");
46  Module &M = *F.getParent();
47  BasicBlock *EntryBlock = BasicBlock::Create(M.getContext(), "entry", &F);
48  IRBuilder<> Builder(EntryBlock);
49  LoadInst *ImplAddr = Builder.CreateLoad(&ImplPointer);
50  std::vector<Value*> CallArgs;
51  for (auto &A : F.args())
52    CallArgs.push_back(&A);
53  CallInst *Call = Builder.CreateCall(ImplAddr, CallArgs);
54  Call->setTailCall();
55  Call->setAttributes(F.getAttributes());
56  if (F.getReturnType()->isVoidTy())
57    Builder.CreateRetVoid();
58  else
59    Builder.CreateRet(Call);
60}
61
62// Utility class for renaming global values and functions during partitioning.
63class GlobalRenamer {
64public:
65
66  static bool needsRenaming(const Value &New) {
67    return !New.hasName() || New.getName().startswith("\01L");
68  }
69
70  const std::string& getRename(const Value &Orig) {
71    // See if we have a name for this global.
72    {
73      auto I = Names.find(&Orig);
74      if (I != Names.end())
75        return I->second;
76    }
77
78    // Nope. Create a new one.
79    // FIXME: Use a more robust uniquing scheme. (This may blow up if the user
80    //        writes a "__orc_anon[[:digit:]]* method).
81    unsigned ID = Names.size();
82    std::ostringstream NameStream;
83    NameStream << "__orc_anon" << ID++;
84    auto I = Names.insert(std::make_pair(&Orig, NameStream.str()));
85    return I.first->second;
86  }
87private:
88  DenseMap<const Value*, std::string> Names;
89};
90
91static void raiseVisibilityOnValue(GlobalValue &V, GlobalRenamer &R) {
92  if (V.hasLocalLinkage()) {
93    if (R.needsRenaming(V))
94      V.setName(R.getRename(V));
95    V.setLinkage(GlobalValue::ExternalLinkage);
96    V.setVisibility(GlobalValue::HiddenVisibility);
97  }
98  V.setUnnamedAddr(false);
99  assert(!R.needsRenaming(V) && "Invalid global name.");
100}
101
102void makeAllSymbolsExternallyAccessible(Module &M) {
103  GlobalRenamer Renamer;
104
105  for (auto &F : M)
106    raiseVisibilityOnValue(F, Renamer);
107
108  for (auto &GV : M.globals())
109    raiseVisibilityOnValue(GV, Renamer);
110
111  for (auto &A : M.aliases())
112    raiseVisibilityOnValue(A, Renamer);
113}
114
115Function* cloneFunctionDecl(Module &Dst, const Function &F,
116                            ValueToValueMapTy *VMap) {
117  assert(F.getParent() != &Dst && "Can't copy decl over existing function.");
118  Function *NewF =
119    Function::Create(cast<FunctionType>(F.getType()->getElementType()),
120                     F.getLinkage(), F.getName(), &Dst);
121  NewF->copyAttributesFrom(&F);
122
123  if (VMap) {
124    (*VMap)[&F] = NewF;
125    auto NewArgI = NewF->arg_begin();
126    for (auto ArgI = F.arg_begin(), ArgE = F.arg_end(); ArgI != ArgE;
127         ++ArgI, ++NewArgI)
128      (*VMap)[&*ArgI] = &*NewArgI;
129  }
130
131  return NewF;
132}
133
134void moveFunctionBody(Function &OrigF, ValueToValueMapTy &VMap,
135                      ValueMaterializer *Materializer,
136                      Function *NewF) {
137  assert(!OrigF.isDeclaration() && "Nothing to move");
138  if (!NewF)
139    NewF = cast<Function>(VMap[&OrigF]);
140  else
141    assert(VMap[&OrigF] == NewF && "Incorrect function mapping in VMap.");
142  assert(NewF && "Function mapping missing from VMap.");
143  assert(NewF->getParent() != OrigF.getParent() &&
144         "moveFunctionBody should only be used to move bodies between "
145         "modules.");
146
147  SmallVector<ReturnInst *, 8> Returns; // Ignore returns cloned.
148  CloneFunctionInto(NewF, &OrigF, VMap, /*ModuleLevelChanges=*/true, Returns,
149                    "", nullptr, nullptr, Materializer);
150  OrigF.deleteBody();
151}
152
153GlobalVariable* cloneGlobalVariableDecl(Module &Dst, const GlobalVariable &GV,
154                                        ValueToValueMapTy *VMap) {
155  assert(GV.getParent() != &Dst && "Can't copy decl over existing global var.");
156  GlobalVariable *NewGV = new GlobalVariable(
157      Dst, GV.getType()->getElementType(), GV.isConstant(),
158      GV.getLinkage(), nullptr, GV.getName(), nullptr,
159      GV.getThreadLocalMode(), GV.getType()->getAddressSpace());
160  NewGV->copyAttributesFrom(&GV);
161  if (VMap)
162    (*VMap)[&GV] = NewGV;
163  return NewGV;
164}
165
166void moveGlobalVariableInitializer(GlobalVariable &OrigGV,
167                                   ValueToValueMapTy &VMap,
168                                   ValueMaterializer *Materializer,
169                                   GlobalVariable *NewGV) {
170  assert(OrigGV.hasInitializer() && "Nothing to move");
171  if (!NewGV)
172    NewGV = cast<GlobalVariable>(VMap[&OrigGV]);
173  else
174    assert(VMap[&OrigGV] == NewGV &&
175           "Incorrect global variable mapping in VMap.");
176  assert(NewGV->getParent() != OrigGV.getParent() &&
177         "moveGlobalVariable should only be used to move initializers between "
178         "modules");
179
180  NewGV->setInitializer(MapValue(OrigGV.getInitializer(), VMap, RF_None,
181                                 nullptr, Materializer));
182}
183
184GlobalAlias* cloneGlobalAliasDecl(Module &Dst, const GlobalAlias &OrigA,
185                                  ValueToValueMapTy &VMap) {
186  assert(OrigA.getAliasee() && "Original alias doesn't have an aliasee?");
187  auto *NewA = GlobalAlias::create(OrigA.getValueType(),
188                                   OrigA.getType()->getPointerAddressSpace(),
189                                   OrigA.getLinkage(), OrigA.getName(), &Dst);
190  NewA->copyAttributesFrom(&OrigA);
191  VMap[&OrigA] = NewA;
192  return NewA;
193}
194
195} // End namespace orc.
196} // End namespace llvm.
197