OLD | NEW |
(Empty) | |
| 1 //===- ExpandTlsConstantExpr.cpp - Convert ConstantExprs to Instructions---===// |
| 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 // This pass is a helper used by the ExpandTls pass. |
| 11 // |
| 12 // LLVM treats the address of a TLS variable as a ConstantExpr. This |
| 13 // is arguably a bug because the address of a TLS variable is *not* a |
| 14 // constant: it varies between threads. |
| 15 // |
| 16 // See http://llvm.org/bugs/show_bug.cgi?id=14353 |
| 17 // |
| 18 // This is also a problem for the ExpandTls pass, which wants to use |
| 19 // replaceUsesOfWith() to replace each TLS variable with an |
| 20 // Instruction sequence that calls @llvm.nacl.read.tp(). This doesn't |
| 21 // work if the TLS variable is used inside other ConstantExprs, |
| 22 // because ConstantExprs are interned and are not associated with any |
| 23 // function, whereas each Instruction must be part of a function. |
| 24 // |
| 25 // To fix that problem, this pass converts ConstantExprs that |
| 26 // reference TLS variables into Instructions. |
| 27 // |
| 28 // For example, this use of a 'ptrtoint' ConstantExpr: |
| 29 // |
| 30 // ret i32 ptrtoint (i32* @tls_var to i32) |
| 31 // |
| 32 // is converted into this 'ptrtoint' Instruction: |
| 33 // |
| 34 // %expanded = ptrtoint i32* @tls_var to i32 |
| 35 // ret i32 %expanded |
| 36 // |
| 37 //===----------------------------------------------------------------------===// |
| 38 |
| 39 #include <vector> |
| 40 |
| 41 #include "llvm/Pass.h" |
| 42 #include "llvm/IR/Constants.h" |
| 43 #include "llvm/IR/Instructions.h" |
| 44 #include "llvm/IR/Module.h" |
| 45 #include "llvm/Transforms/NaCl.h" |
| 46 |
| 47 using namespace llvm; |
| 48 |
| 49 namespace { |
| 50 class ExpandTlsConstantExpr : public ModulePass { |
| 51 public: |
| 52 static char ID; // Pass identification, replacement for typeid |
| 53 ExpandTlsConstantExpr() : ModulePass(ID) { |
| 54 initializeExpandTlsConstantExprPass(*PassRegistry::getPassRegistry()); |
| 55 } |
| 56 |
| 57 virtual bool runOnModule(Module &M); |
| 58 }; |
| 59 } |
| 60 |
| 61 char ExpandTlsConstantExpr::ID = 0; |
| 62 INITIALIZE_PASS(ExpandTlsConstantExpr, "nacl-expand-tls-constant-expr", |
| 63 "Eliminate ConstantExpr references to TLS variables", |
| 64 false, false) |
| 65 |
| 66 // This removes ConstantExpr references to the given Constant. |
| 67 static void expandConstExpr(Constant *Expr) { |
| 68 // First, ensure that ConstantExpr references to Expr are converted |
| 69 // to Instructions so that we can modify them. |
| 70 for (Use &U : Expr->uses()) |
| 71 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(U.getUser())) |
| 72 expandConstExpr(CE); |
| 73 Expr->removeDeadConstantUsers(); |
| 74 |
| 75 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Expr)) { |
| 76 while (Expr->hasNUsesOrMore(1)) { |
| 77 Use *U = &*Expr->use_begin(); |
| 78 Instruction *NewInst = CE->getAsInstruction(); |
| 79 NewInst->insertBefore(PhiSafeInsertPt(U)); |
| 80 NewInst->setName("expanded"); |
| 81 PhiSafeReplaceUses(U, NewInst); |
| 82 } |
| 83 } |
| 84 } |
| 85 |
| 86 bool ExpandTlsConstantExpr::runOnModule(Module &M) { |
| 87 for (Module::alias_iterator Iter = M.alias_begin(); |
| 88 Iter != M.alias_end(); ) { |
| 89 GlobalAlias *GA = Iter++; |
| 90 if (GA->isThreadDependent()) { |
| 91 GA->replaceAllUsesWith(GA->getAliasee()); |
| 92 GA->eraseFromParent(); |
| 93 } |
| 94 } |
| 95 for (Module::global_iterator Global = M.global_begin(); |
| 96 Global != M.global_end(); |
| 97 ++Global) { |
| 98 if (Global->isThreadLocal()) { |
| 99 expandConstExpr(Global); |
| 100 } |
| 101 } |
| 102 return true; |
| 103 } |
| 104 |
| 105 ModulePass *llvm::createExpandTlsConstantExprPass() { |
| 106 return new ExpandTlsConstantExpr(); |
| 107 } |
OLD | NEW |