aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/NaCl/PNaClABIVerifyModule.cpp
blob: 5062f710f62c88951f9eeb2b469e4f57ab958472 (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
85
86
87
88
89
90
91
//===- PNaClABIVerifyModule.cpp - Verify PNaCl ABI rules --------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Verify module-level PNaCl ABI requirements (specifically those that do not
// require looking at the function bodies)
//
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/Twine.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Analysis/NaCl.h"
using namespace llvm;

namespace {

// This pass should not touch function bodies, to stay streaming-friendly
struct PNaClABIVerifyModule : public ModulePass {
  static char ID;
  PNaClABIVerifyModule() : ModulePass(ID) {}
  bool runOnModule(Module &M);
  // For now, this print method exists to allow us to run the pass with
  // opt -analyze to avoid dumping the result to stdout, to make testing
  // simpler. In the future we will probably want to make it do something
  // useful.
  virtual void print(llvm::raw_ostream &O, const Module *M) const {};
};

static const char* LinkageName(GlobalValue::LinkageTypes LT) {
  // This logic is taken from PrintLinkage in lib/VMCore/AsmWriter.cpp
  switch (LT) {
    case GlobalValue::ExternalLinkage: return "external";
    case GlobalValue::PrivateLinkage:       return "private ";
    case GlobalValue::LinkerPrivateLinkage: return "linker_private ";
    case GlobalValue::LinkerPrivateWeakLinkage: return "linker_private_weak ";
    case GlobalValue::InternalLinkage:      return "internal ";
    case GlobalValue::LinkOnceAnyLinkage:   return "linkonce ";
    case GlobalValue::LinkOnceODRLinkage:   return "linkonce_odr ";
    case GlobalValue::LinkOnceODRAutoHideLinkage:
      return "linkonce_odr_auto_hide ";
    case GlobalValue::WeakAnyLinkage:       return "weak ";
    case GlobalValue::WeakODRLinkage:       return "weak_odr ";
    case GlobalValue::CommonLinkage:        return "common ";
    case GlobalValue::AppendingLinkage:     return "appending ";
    case GlobalValue::DLLImportLinkage:     return "dllimport ";
    case GlobalValue::DLLExportLinkage:     return "dllexport ";
    case GlobalValue::ExternalWeakLinkage:  return "extern_weak ";
    case GlobalValue::AvailableExternallyLinkage:
      return "available_externally ";
    default:
      return "unknown";
  }
}

} // end anonymous namespace

bool PNaClABIVerifyModule::runOnModule(Module &M) {
  // Check GV linkage types
  for (Module::const_global_iterator MI = M.global_begin(), ME = M.global_end();
       MI != ME; ++MI) {
    switch(MI->getLinkage()) {
      case GlobalValue::ExternalLinkage:
      case GlobalValue::AvailableExternallyLinkage:
      case GlobalValue::InternalLinkage:
      case GlobalValue::PrivateLinkage:
        break;
      default:
        errs() << (Twine("Variable ") + MI->getName() +
            " has disallowed linkage type: " +
                LinkageName(MI->getLinkage()) + "\n");
    }
  }
  return false;
}

char PNaClABIVerifyModule::ID = 0;

static RegisterPass<PNaClABIVerifyModule> X("verify-pnaclabi-module",
    "Verify module for PNaCl", false, false);

ModulePass *llvm::createPNaClABIVerifyModulePass() {
  return new PNaClABIVerifyModule();
}