summaryrefslogtreecommitdiff
path: root/lib/Target/SparcV9/InternalGlobalMapper.cpp
blob: ef870b224f46320589d97db9634d895a1557464b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
//===-- InternalGlobalMapper.cpp - Mapping Info for Internal Globals ------===//
// 
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
// 
//===----------------------------------------------------------------------===//
//
// InternalGlobalMapper is a pass that helps the runtime trace optimizer map
// the names of internal GlobalValues (which may have mangled,
// unreconstructible names in the executable) to pointers. If the name mangler
// is changed at some point in the future to allow its results to be
// reconstructible (for instance, by making the type mangling symbolic instead
// of using a UniqueID) this pass should probably be phased out.
//
//===----------------------------------------------------------------------===//

#include "llvm/Constants.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Type.h"
#include "llvm/DerivedTypes.h"
using namespace llvm;

namespace llvm {

typedef std::vector<Constant *> GVVectorTy;

class InternalGlobalMapper : public ModulePass {
public:
  bool runOnModule(Module &M);
};

ModulePass *llvm::createInternalGlobalMapperPass() {
  return new InternalGlobalMapper();
}

static void maybeAddInternalValueToVector (GVVectorTy &Vector, GlobalValue &GV){
  // If it's a GlobalValue with internal linkage and a name (i.e. it's going to
  // be mangled), then put the GV, casted to sbyte*, in the vector. Otherwise
  // add a null.
  if (GV.hasInternalLinkage () && GV.hasName ())
    Vector.push_back(ConstantExpr::getCast(&GV,
                                           PointerType::get(Type::SByteTy)));
  else
    Vector.push_back (ConstantPointerNull::get (PointerType::get
                                                (Type::SByteTy)));
}

bool InternalGlobalMapper::runOnModule(Module &M) {
  GVVectorTy gvvector;

  // Populate the vector with internal global values and their names.
  for (Module::giterator i = M.gbegin (), e = M.gend (); i != e; ++i)
    maybeAddInternalValueToVector (gvvector, *i);
  // Add an extra global for _llvm_internalGlobals itself (null,
  // because it's not internal)
  gvvector.push_back (ConstantPointerNull::get
    (PointerType::get (Type::SByteTy)));
  for (Module::iterator i = M.begin (), e = M.end (); i != e; ++i)
    maybeAddInternalValueToVector (gvvector, *i);

  // Convert the vector to a constant struct of type {Size, [Size x sbyte*]}.
  ArrayType *ATy = ArrayType::get (PointerType::get (Type::SByteTy),
                                  gvvector.size ());
  std::vector<const Type *> FieldTypes;
  FieldTypes.push_back (Type::UIntTy);
  FieldTypes.push_back (ATy);
  StructType *STy = StructType::get (FieldTypes);
  std::vector<Constant *> FieldValues;
  FieldValues.push_back (ConstantUInt::get (Type::UIntTy, gvvector.size ()));
  FieldValues.push_back (ConstantArray::get (ATy, gvvector));
  
  // Add the constant struct to M as an external global symbol named
  // "_llvm_internalGlobals".
  new GlobalVariable (STy, true, GlobalValue::ExternalLinkage,
                      ConstantStruct::get (STy, FieldValues),
                      "_llvm_internalGlobals", &M);

  return true; // Module was modified.
}

} // end namespace llvm