aboutsummaryrefslogtreecommitdiff
path: root/lib/Transforms/NaCl/NoExitRuntime.cpp
blob: ca622d3c06693d18ae835c22165d7b7a223d7f4a (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
92
93
94
95
96
97
//===- NoExitRuntime.cpp - Expand i64 and wider integer types -------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===------------------------------------------------------------------===//
//
//===------------------------------------------------------------------===//

#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
#include "llvm/Support/CFG.h"
#include "llvm/Target/TargetLibraryInfo.h"
#include "llvm/Transforms/NaCl.h"
#include "llvm/Transforms/Utils/Local.h"
#include <map>

#include "llvm/Support/raw_ostream.h"

#ifdef NDEBUG
#undef assert
#define assert(x) { if (!(x)) report_fatal_error(#x); }
#endif

using namespace llvm;

namespace {
  class NoExitRuntime : public ModulePass {
    Module *TheModule;

  public:
    static char ID;
    NoExitRuntime() : ModulePass(ID) {
      initializeNoExitRuntimePass(*PassRegistry::getPassRegistry());
    }

    virtual bool runOnModule(Module &M);
  };
}

char NoExitRuntime::ID = 0;
INITIALIZE_PASS(NoExitRuntime, "emscripten-no-exit-runtime",
                "Generate code which assumes the runtime is never exited (so atexit etc. is unneeded; see emscripten NO_EXIT_RUNTIME setting)",
                false, false)


// Implementation of NoExitRuntime

bool NoExitRuntime::runOnModule(Module &M) {
  TheModule = &M;

  Function *AtExit = TheModule->getFunction("__cxa_atexit");
  if (!AtExit || !AtExit->isDeclaration() || AtExit->getNumUses() == 0) return false;

  // The system atexit is used - let's remove calls to it

  Type *i32 = Type::getInt32Ty(TheModule->getContext());
  Value *Zero  = Constant::getNullValue(i32);

  std::vector<Instruction*> ToErase;

  for (Instruction::use_iterator UI = AtExit->use_begin(), UE = AtExit->use_end(); UI != UE; ++UI) {
    if (CallInst *CI = dyn_cast<CallInst>(*UI)) {
      if (CI->getCalledValue() == AtExit) {
        // calls to atexit can just be removed
        CI->replaceAllUsesWith(Zero);
        ToErase.push_back(CI);
        continue;
      }
    }
    // Possibly other uses of atexit are done - ptrtoint, etc. - but we leave those alone
  }

  for (unsigned i = 0; i < ToErase.size(); i++) {
    ToErase[i]->eraseFromParent();
  }

  return true;
}

ModulePass *llvm::createNoExitRuntimePass() {
  return new NoExitRuntime();
}