| Index: lib/Transforms/NaCl/ExpandTlsConstantExpr.cpp
|
| diff --git a/lib/Transforms/NaCl/ExpandTlsConstantExpr.cpp b/lib/Transforms/NaCl/ExpandTlsConstantExpr.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..16f776c726c11c6741950b5253509ce8b3f99a18
|
| --- /dev/null
|
| +++ b/lib/Transforms/NaCl/ExpandTlsConstantExpr.cpp
|
| @@ -0,0 +1,107 @@
|
| +//===- ExpandTlsConstantExpr.cpp - Convert ConstantExprs to Instructions---===//
|
| +//
|
| +// The LLVM Compiler Infrastructure
|
| +//
|
| +// This file is distributed under the University of Illinois Open Source
|
| +// License. See LICENSE.TXT for details.
|
| +//
|
| +//===----------------------------------------------------------------------===//
|
| +//
|
| +// This pass is a helper used by the ExpandTls pass.
|
| +//
|
| +// LLVM treats the address of a TLS variable as a ConstantExpr. This
|
| +// is arguably a bug because the address of a TLS variable is *not* a
|
| +// constant: it varies between threads.
|
| +//
|
| +// See http://llvm.org/bugs/show_bug.cgi?id=14353
|
| +//
|
| +// This is also a problem for the ExpandTls pass, which wants to use
|
| +// replaceUsesOfWith() to replace each TLS variable with an
|
| +// Instruction sequence that calls @llvm.nacl.read.tp(). This doesn't
|
| +// work if the TLS variable is used inside other ConstantExprs,
|
| +// because ConstantExprs are interned and are not associated with any
|
| +// function, whereas each Instruction must be part of a function.
|
| +//
|
| +// To fix that problem, this pass converts ConstantExprs that
|
| +// reference TLS variables into Instructions.
|
| +//
|
| +// For example, this use of a 'ptrtoint' ConstantExpr:
|
| +//
|
| +// ret i32 ptrtoint (i32* @tls_var to i32)
|
| +//
|
| +// is converted into this 'ptrtoint' Instruction:
|
| +//
|
| +// %expanded = ptrtoint i32* @tls_var to i32
|
| +// ret i32 %expanded
|
| +//
|
| +//===----------------------------------------------------------------------===//
|
| +
|
| +#include <vector>
|
| +
|
| +#include "llvm/Pass.h"
|
| +#include "llvm/IR/Constants.h"
|
| +#include "llvm/IR/Instructions.h"
|
| +#include "llvm/IR/Module.h"
|
| +#include "llvm/Transforms/NaCl.h"
|
| +
|
| +using namespace llvm;
|
| +
|
| +namespace {
|
| + class ExpandTlsConstantExpr : public ModulePass {
|
| + public:
|
| + static char ID; // Pass identification, replacement for typeid
|
| + ExpandTlsConstantExpr() : ModulePass(ID) {
|
| + initializeExpandTlsConstantExprPass(*PassRegistry::getPassRegistry());
|
| + }
|
| +
|
| + virtual bool runOnModule(Module &M);
|
| + };
|
| +}
|
| +
|
| +char ExpandTlsConstantExpr::ID = 0;
|
| +INITIALIZE_PASS(ExpandTlsConstantExpr, "nacl-expand-tls-constant-expr",
|
| + "Eliminate ConstantExpr references to TLS variables",
|
| + false, false)
|
| +
|
| +// This removes ConstantExpr references to the given Constant.
|
| +static void expandConstExpr(Constant *Expr) {
|
| + // First, ensure that ConstantExpr references to Expr are converted
|
| + // to Instructions so that we can modify them.
|
| + for (Use &U : Expr->uses())
|
| + if (ConstantExpr *CE = dyn_cast<ConstantExpr>(U.getUser()))
|
| + expandConstExpr(CE);
|
| + Expr->removeDeadConstantUsers();
|
| +
|
| + if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Expr)) {
|
| + while (Expr->hasNUsesOrMore(1)) {
|
| + Use *U = &*Expr->use_begin();
|
| + Instruction *NewInst = CE->getAsInstruction();
|
| + NewInst->insertBefore(PhiSafeInsertPt(U));
|
| + NewInst->setName("expanded");
|
| + PhiSafeReplaceUses(U, NewInst);
|
| + }
|
| + }
|
| +}
|
| +
|
| +bool ExpandTlsConstantExpr::runOnModule(Module &M) {
|
| + for (Module::alias_iterator Iter = M.alias_begin();
|
| + Iter != M.alias_end(); ) {
|
| + GlobalAlias *GA = Iter++;
|
| + if (GA->isThreadDependent()) {
|
| + GA->replaceAllUsesWith(GA->getAliasee());
|
| + GA->eraseFromParent();
|
| + }
|
| + }
|
| + for (Module::global_iterator Global = M.global_begin();
|
| + Global != M.global_end();
|
| + ++Global) {
|
| + if (Global->isThreadLocal()) {
|
| + expandConstExpr(Global);
|
| + }
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +ModulePass *llvm::createExpandTlsConstantExprPass() {
|
| + return new ExpandTlsConstantExpr();
|
| +}
|
|
|