aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/Analysis/NaCl.h35
-rw-r--r--include/llvm/InitializePasses.h13
-rw-r--r--include/llvm/Transforms/NaCl.h2
-rw-r--r--lib/Analysis/NaCl/CMakeLists.txt4
-rw-r--r--lib/Analysis/NaCl/LLVMBuild.txt2
-rw-r--r--lib/Analysis/NaCl/Makefile2
-rw-r--r--lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp75
-rw-r--r--lib/Analysis/NaCl/PNaClABIVerifyModule.cpp95
-rw-r--r--lib/Target/X86/X86ISelDAGToDAG.cpp3
-rw-r--r--lib/Transforms/NaCl/CMakeLists.txt1
-rw-r--r--lib/Transforms/NaCl/ExpandConstantExpr.cpp112
-rw-r--r--test/NaCl/PNaClABI/instructions.ll2
-rw-r--r--test/NaCl/PNaClABI/linkagetypes.ll2
-rw-r--r--test/NaCl/PNaClABI/types-function.ll2
-rw-r--r--test/NaCl/PNaClABI/types.ll2
-rw-r--r--test/NaCl/X86/nacl64-addrmodes.ll64
-rw-r--r--test/Transforms/NaCl/expand-constantexpr.ll109
-rw-r--r--tools/CMakeLists.txt1
-rw-r--r--tools/LLVMBuild.txt2
-rw-r--r--tools/Makefile2
-rw-r--r--tools/llc/CMakeLists.txt2
-rw-r--r--tools/llc/LLVMBuild.txt2
-rw-r--r--tools/llc/Makefile2
-rw-r--r--tools/llc/llc.cpp41
-rw-r--r--tools/opt/opt.cpp1
-rw-r--r--tools/pnacl-abicheck/CMakeLists.txt5
-rw-r--r--tools/pnacl-abicheck/LLVMBuild.txt22
-rw-r--r--tools/pnacl-abicheck/Makefile16
-rw-r--r--tools/pnacl-abicheck/pnacl-abicheck.cpp62
29 files changed, 597 insertions, 86 deletions
diff --git a/include/llvm/Analysis/NaCl.h b/include/llvm/Analysis/NaCl.h
index 8e599594b2..a8f2c9651e 100644
--- a/include/llvm/Analysis/NaCl.h
+++ b/include/llvm/Analysis/NaCl.h
@@ -10,13 +10,44 @@
#ifndef LLVM_ANALYSIS_NACL_H
#define LLVM_ANALYSIS_NACL_H
+#include "llvm/Support/raw_ostream.h"
+#include <string>
+
namespace llvm {
class FunctionPass;
class ModulePass;
-FunctionPass *createPNaClABIVerifyFunctionsPass();
-ModulePass *createPNaClABIVerifyModulePass();
+class PNaClABIErrorReporter {
+ public:
+ PNaClABIErrorReporter() : ErrorCount(0), Errors(ErrorString) {}
+ // Return the number of verification errors from the last run.
+ int getErrorCount() { return ErrorCount; }
+ // Print the error messages to O
+ void printErrors(llvm::raw_ostream &O) {
+ Errors.flush();
+ O << ErrorString;
+ }
+ // Increments the error count and returns an ostream to which the error
+ // message can be streamed.
+ raw_ostream &addError() {
+ ErrorCount++;
+ return Errors;
+ }
+ // Reset the error count and error messages.
+ void reset() {
+ ErrorCount = 0;
+ Errors.flush();
+ ErrorString.clear();
+ }
+ private:
+ int ErrorCount;
+ std::string ErrorString;
+ raw_string_ostream Errors;
+};
+
+FunctionPass *createPNaClABIVerifyFunctionsPass(PNaClABIErrorReporter * Reporter);
+ModulePass *createPNaClABIVerifyModulePass(PNaClABIErrorReporter * Reporter);
}
diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h
index 0816a85848..da72dcd1a8 100644
--- a/include/llvm/InitializePasses.h
+++ b/include/llvm/InitializePasses.h
@@ -276,10 +276,15 @@ void initializeFinalizeMachineBundlesPass(PassRegistry&);
void initializeLoopVectorizePass(PassRegistry&);
void initializeBBVectorizePass(PassRegistry&);
void initializeMachineFunctionPrinterPassPass(PassRegistry&);
-void initializeExpandCtorsPass(PassRegistry&); // @LOCALMOD
-void initializeExpandTlsPass(PassRegistry&); // @LOCALMOD
-void initializeExpandTlsConstantExprPass(PassRegistry&); // @LOCALMOD
-void initializeNaClCcRewritePass(PassRegistry&); // @LOCALMOD
+// @LOCALMOD-BEGIN
+void initializeExpandConstantExprPass(PassRegistry&);
+void initializeExpandCtorsPass(PassRegistry&);
+void initializeExpandTlsPass(PassRegistry&);
+void initializeExpandTlsConstantExprPass(PassRegistry&);
+void initializeNaClCcRewritePass(PassRegistry&);
+void initializePNaClABIVerifyModulePass(PassRegistry&);
+void initializePNaClABIVerifyFunctionsPass(PassRegistry&);
+// @LOCALMOD-END
}
#endif
diff --git a/include/llvm/Transforms/NaCl.h b/include/llvm/Transforms/NaCl.h
index 79c9b9fe79..686b45ff74 100644
--- a/include/llvm/Transforms/NaCl.h
+++ b/include/llvm/Transforms/NaCl.h
@@ -12,8 +12,10 @@
namespace llvm {
+class FunctionPass;
class ModulePass;
+FunctionPass *createExpandConstantExprPass();
ModulePass *createExpandCtorsPass();
ModulePass *createExpandTlsPass();
ModulePass *createExpandTlsConstantExprPass();
diff --git a/lib/Analysis/NaCl/CMakeLists.txt b/lib/Analysis/NaCl/CMakeLists.txt
index 7fa3a134ac..a01a333802 100644
--- a/lib/Analysis/NaCl/CMakeLists.txt
+++ b/lib/Analysis/NaCl/CMakeLists.txt
@@ -1,7 +1,7 @@
-add_llvm_library(LLVMAnalysisNaCl
+add_llvm_library(LLVMNaClAnalysis
PNaCLABITypeChecker.cpp
PNaClABIVerifyFunctions.cpp
PNaClABIVerifyModule.cpp
)
-add_dependencies(LLVMAnalysisNaCl intrinsics_gen)
+add_dependencies(LLVMNaClAnalysis intrinsics_gen)
diff --git a/lib/Analysis/NaCl/LLVMBuild.txt b/lib/Analysis/NaCl/LLVMBuild.txt
index 997803bb5d..b5e7c8a5ea 100644
--- a/lib/Analysis/NaCl/LLVMBuild.txt
+++ b/lib/Analysis/NaCl/LLVMBuild.txt
@@ -20,4 +20,4 @@ type = Library
name = NaClAnalysis
parent = Analysis
library_name = NaClAnalysis
-required_libraries = Core
+required_libraries = Analysis Core Support
diff --git a/lib/Analysis/NaCl/Makefile b/lib/Analysis/NaCl/Makefile
index 6a2f0ed8d9..7d03b1e92e 100644
--- a/lib/Analysis/NaCl/Makefile
+++ b/lib/Analysis/NaCl/Makefile
@@ -8,7 +8,7 @@
##===----------------------------------------------------------------------===##
LEVEL = ../../..
-LIBRARYNAME = LLVMAnalysisNaCl
+LIBRARYNAME = LLVMNaClAnalysis
BUILD_ARCHIVE = 1
include $(LEVEL)/Makefile.common \ No newline at end of file
diff --git a/lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp b/lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp
index fa94733ef0..8404a4cafc 100644
--- a/lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp
+++ b/lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp
@@ -14,11 +14,11 @@
#include "llvm/Pass.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/Analysis/NaCl.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Metadata.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Analysis/NaCl.h"
#include "PNaClABITypeChecker.h"
using namespace llvm;
@@ -30,22 +30,34 @@ namespace {
class PNaClABIVerifyFunctions : public FunctionPass {
public:
static char ID;
- PNaClABIVerifyFunctions() : FunctionPass(ID), Errors(ErrorsString) {}
+ PNaClABIVerifyFunctions() :
+ FunctionPass(ID),
+ Reporter(new PNaClABIErrorReporter),
+ ReporterIsOwned(true) {
+ initializePNaClABIVerifyFunctionsPass(*PassRegistry::getPassRegistry());
+ }
+ explicit PNaClABIVerifyFunctions(PNaClABIErrorReporter *Reporter_) :
+ FunctionPass(ID),
+ Reporter(Reporter_),
+ ReporterIsOwned(false) {
+ initializePNaClABIVerifyFunctionsPass(*PassRegistry::getPassRegistry());
+ }
+ ~PNaClABIVerifyFunctions() {
+ if (ReporterIsOwned)
+ delete Reporter;
+ }
bool runOnFunction(Function &F);
virtual void print(raw_ostream &O, const Module *M) const;
private:
PNaClABITypeChecker TC;
- std::string ErrorsString;
- raw_string_ostream Errors;
+ PNaClABIErrorReporter *Reporter;
+ bool ReporterIsOwned;
};
} // and anonymous namespace
bool PNaClABIVerifyFunctions::runOnFunction(Function &F) {
- // For now just start with new errors on each function; this may change
- // once we want to do something with them other than just calling print()
- ErrorsString.clear();
- // TODO: only report one error per instruction
+ // TODO: only report one error per instruction?
for (Function::const_iterator FI = F.begin(), FE = F.end();
FI != FE; ++FI) {
for (BasicBlock::const_iterator BBI = FI->begin(), BBE = FI->end();
@@ -59,9 +71,9 @@ bool PNaClABIVerifyFunctions::runOnFunction(Function &F) {
case Instruction::ExtractElement:
case Instruction::InsertElement:
case Instruction::ShuffleVector:
- Errors << "Function " + F.getName() +
- " has disallowed instruction: " +
- BBI->getOpcodeName() + "\n";
+ Reporter->addError() << "Function " << F.getName() <<
+ " has disallowed instruction: " <<
+ BBI->getOpcodeName() << "\n";
break;
// Terminator instructions
@@ -126,9 +138,9 @@ bool PNaClABIVerifyFunctions::runOnFunction(Function &F) {
}
// Check the types. First check the type of the instruction.
if (!TC.isValidType(BBI->getType())) {
- Errors << "Function " + F.getName() +
- " has instruction with disallowed type: " +
- PNaClABITypeChecker::getTypeName(BBI->getType()) + "\n";
+ Reporter->addError() << "Function " << F.getName() <<
+ " has instruction with disallowed type: " <<
+ PNaClABITypeChecker::getTypeName(BBI->getType()) << "\n";
}
// Check the instruction operands. Operands which are Instructions will
@@ -141,10 +153,11 @@ bool PNaClABIVerifyFunctions::runOnFunction(Function &F) {
OI != OE; OI++) {
if (isa<Constant>(OI) && !isa<GlobalValue>(OI)) {
Type *T = TC.checkTypesInConstant(cast<Constant>(*OI));
- if (T)
- Errors << "Function " + F.getName() +
- " has instruction operand with disallowed type: " +
- PNaClABITypeChecker::getTypeName(T) + "\n";
+ if (T) {
+ Reporter->addError() << "Function " << F.getName() <<
+ " has instruction operand with disallowed type: " <<
+ PNaClABITypeChecker::getTypeName(T) << "\n";
+ }
}
}
@@ -153,28 +166,32 @@ bool PNaClABIVerifyFunctions::runOnFunction(Function &F) {
BBI->getAllMetadataOtherThanDebugLoc(MDForInst);
for (unsigned i = 0, e = MDForInst.size(); i != e; i++) {
Type *T = TC.checkTypesInMDNode(MDForInst[i].second);
- if (T)
- Errors << "Function " + F.getName() +
- " has instruction metadata containing disallowed type: " +
- PNaClABITypeChecker::getTypeName(T) + "\n";
+ if (T) {
+ Reporter->addError() << "Function " << F.getName() <<
+ " has instruction metadata containing disallowed type: " <<
+ PNaClABITypeChecker::getTypeName(T) << "\n";
+ }
}
}
}
- Errors.flush();
return false;
}
+// This method exists so that the passes can easily be run with opt -analyze.
+// In this case the default constructor is used and we want to reset the error
+// messages after each print.
void PNaClABIVerifyFunctions::print(llvm::raw_ostream &O, const Module *M)
const {
- O << ErrorsString;
+ Reporter->printErrors(O);
+ Reporter->reset();
}
char PNaClABIVerifyFunctions::ID = 0;
+INITIALIZE_PASS(PNaClABIVerifyFunctions, "verify-pnaclabi-functions",
+ "Verify functions for PNaCl", false, true)
-static RegisterPass<PNaClABIVerifyFunctions> X("verify-pnaclabi-functions",
- "Verify functions for PNaCl", false, false);
-
-FunctionPass *llvm::createPNaClABIVerifyFunctionsPass() {
- return new PNaClABIVerifyFunctions();
+FunctionPass *llvm::createPNaClABIVerifyFunctionsPass(
+ PNaClABIErrorReporter *Reporter) {
+ return new PNaClABIVerifyFunctions(Reporter);
}
diff --git a/lib/Analysis/NaCl/PNaClABIVerifyModule.cpp b/lib/Analysis/NaCl/PNaClABIVerifyModule.cpp
index 59addab087..660fa9f8fe 100644
--- a/lib/Analysis/NaCl/PNaClABIVerifyModule.cpp
+++ b/lib/Analysis/NaCl/PNaClABIVerifyModule.cpp
@@ -14,8 +14,8 @@
//===----------------------------------------------------------------------===//
#include "llvm/Pass.h"
-#include "llvm/Analysis/NaCl.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/Analysis/NaCl.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/raw_ostream.h"
@@ -28,13 +28,28 @@ namespace {
class PNaClABIVerifyModule : public ModulePass {
public:
static char ID;
- PNaClABIVerifyModule();
+ PNaClABIVerifyModule() :
+ ModulePass(ID),
+ Reporter(new PNaClABIErrorReporter),
+ ReporterIsOwned(true) {
+ initializePNaClABIVerifyModulePass(*PassRegistry::getPassRegistry());
+ }
+ explicit PNaClABIVerifyModule(PNaClABIErrorReporter *Reporter_) :
+ ModulePass(ID),
+ Reporter(Reporter_),
+ ReporterIsOwned(false) {
+ initializePNaClABIVerifyModulePass(*PassRegistry::getPassRegistry());
+ }
+ ~PNaClABIVerifyModule() {
+ if (ReporterIsOwned)
+ delete Reporter;
+ }
bool runOnModule(Module &M);
virtual void print(raw_ostream &O, const Module *M) const;
private:
PNaClABITypeChecker TC;
- std::string ErrorsString;
- raw_string_ostream Errors;
+ PNaClABIErrorReporter *Reporter;
+ bool ReporterIsOwned;
};
static const char *linkageName(GlobalValue::LinkageTypes LT) {
@@ -65,26 +80,24 @@ static const char *linkageName(GlobalValue::LinkageTypes LT) {
} // end anonymous namespace
-PNaClABIVerifyModule::PNaClABIVerifyModule() : ModulePass(ID),
- Errors(ErrorsString) {}
-
bool PNaClABIVerifyModule::runOnModule(Module &M) {
for (Module::const_global_iterator MI = M.global_begin(), ME = M.global_end();
MI != ME; ++MI) {
// Check types of global variables and their initializers
if (!TC.isValidType(MI->getType())) {
// GVs are pointers, so print the pointed-to type for clarity
- Errors << "Variable " + MI->getName() +
- " has disallowed type: " +
+ Reporter->addError() << "Variable " << MI->getName() <<
+ " has disallowed type: " <<
PNaClABITypeChecker::getTypeName(MI->getType()->getContainedType(0))
+ "\n";
} else if (MI->hasInitializer()) {
// If the type of the global is bad, no point in checking its initializer
Type *T = TC.checkTypesInConstant(MI->getInitializer());
- if (T)
- Errors << "Initializer for " + MI->getName() +
- " has disallowed type: " +
- PNaClABITypeChecker::getTypeName(T) + "\n";
+ if (T) {
+ Reporter->addError() << "Initializer for " << MI->getName() <<
+ " has disallowed type: " <<
+ PNaClABITypeChecker::getTypeName(T) << "\n";
+ }
}
// Check GV linkage types
@@ -95,28 +108,33 @@ bool PNaClABIVerifyModule::runOnModule(Module &M) {
case GlobalValue::PrivateLinkage:
break;
default:
- Errors << "Variable " + MI->getName() +
- " has disallowed linkage type: " +
- linkageName(MI->getLinkage()) + "\n";
+ Reporter->addError() << "Variable " << MI->getName() <<
+ " has disallowed linkage type: " <<
+ linkageName(MI->getLinkage()) << "\n";
}
}
// No aliases allowed for now.
for (Module::alias_iterator MI = M.alias_begin(),
- E = M.alias_end(); MI != E; ++MI)
- Errors << "Variable " + MI->getName() + " is an alias (disallowed)\n";
+ E = M.alias_end(); MI != E; ++MI) {
+ Reporter->addError() << "Variable " << MI->getName() <<
+ " is an alias (disallowed)\n";
+ }
for (Module::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI) {
// Check types of functions and their arguments
FunctionType *FT = MI->getFunctionType();
- if (!TC.isValidType(FT->getReturnType()))
- Errors << "Function " + MI->getName() + " has disallowed return type: " +
- PNaClABITypeChecker::getTypeName(FT->getReturnType()) + "\n";
+ if (!TC.isValidType(FT->getReturnType())) {
+ Reporter->addError() << "Function " << MI->getName() <<
+ " has disallowed return type: " <<
+ PNaClABITypeChecker::getTypeName(FT->getReturnType()) << "\n";
+ }
for (unsigned I = 0, E = FT->getNumParams(); I < E; ++I) {
Type *PT = FT->getParamType(I);
- if (!TC.isValidType(PT))
- Errors << "Function " << MI->getName() << " argument " << I + 1 <<
- " has disallowed type: " <<
- PNaClABITypeChecker::getTypeName(PT) + "\n";
+ if (!TC.isValidType(PT)) {
+ Reporter->addError() << "Function " << MI->getName() << " argument " <<
+ I + 1 << " has disallowed type: " <<
+ PNaClABITypeChecker::getTypeName(PT) << "\n";
+ }
}
}
@@ -124,25 +142,30 @@ bool PNaClABIVerifyModule::runOnModule(Module &M) {
for (Module::const_named_metadata_iterator I = M.named_metadata_begin(),
E = M.named_metadata_end(); I != E; ++I) {
for (unsigned i = 0, e = I->getNumOperands(); i != e; i++) {
- if (Type *T = TC.checkTypesInMDNode(I->getOperand(i)))
- Errors << "Named metadata node " + I->getName() +
- " refers to disallowed type: " +
- PNaClABITypeChecker::getTypeName(T) + "\n";
+ if (Type *T = TC.checkTypesInMDNode(I->getOperand(i))) {
+ Reporter->addError() << "Named metadata node " << I->getName() <<
+ " refers to disallowed type: " <<
+ PNaClABITypeChecker::getTypeName(T) << "\n";
+ }
}
}
- Errors.flush();
return false;
}
+// This method exists so that the passes can easily be run with opt -analyze.
+// In this case the default constructor is used and we want to reset the error
+// messages after each print (this is more of an issue for the FunctionPass
+// than the ModulePass)
void PNaClABIVerifyModule::print(llvm::raw_ostream &O, const Module *M) const {
- O << ErrorsString;
+ Reporter->printErrors(O);
+ Reporter->reset();
}
char PNaClABIVerifyModule::ID = 0;
+INITIALIZE_PASS(PNaClABIVerifyModule, "verify-pnaclabi-module",
+ "Verify module for PNaCl", false, true)
-static RegisterPass<PNaClABIVerifyModule> X("verify-pnaclabi-module",
- "Verify module for PNaCl", false, false);
-
-ModulePass *llvm::createPNaClABIVerifyModulePass() {
- return new PNaClABIVerifyModule();
+ModulePass *llvm::createPNaClABIVerifyModulePass(
+ PNaClABIErrorReporter *Reporter) {
+ return new PNaClABIVerifyModule(Reporter);
}
diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp
index 049ca7a705..8df2e7ca2e 100644
--- a/lib/Target/X86/X86ISelDAGToDAG.cpp
+++ b/lib/Target/X86/X86ISelDAGToDAG.cpp
@@ -614,7 +614,8 @@ bool X86DAGToDAGISel::FoldOffsetIntoAddress(uint64_t Offset,
// and often results in a negative value in the index register
// (see also LegalizeAddressModeForNaCl)
else if (Subtarget->isTargetNaCl64() &&
- AM.BaseType == X86ISelAddressMode::RegBase &&
+ (AM.BaseType == X86ISelAddressMode::RegBase ||
+ AM.BaseType == X86ISelAddressMode::FrameIndexBase) &&
(Val > 65535 || Val < -65536) && selectingMemOp)
return true;
// LOCALMOD-END
diff --git a/lib/Transforms/NaCl/CMakeLists.txt b/lib/Transforms/NaCl/CMakeLists.txt
index 5e24cc7e28..acf7656f64 100644
--- a/lib/Transforms/NaCl/CMakeLists.txt
+++ b/lib/Transforms/NaCl/CMakeLists.txt
@@ -1,4 +1,5 @@
add_llvm_library(LLVMTransformsNaCl
+ ExpandConstantExpr.cpp
ExpandCtors.cpp
ExpandTls.cpp
ExpandTlsConstantExpr.cpp
diff --git a/lib/Transforms/NaCl/ExpandConstantExpr.cpp b/lib/Transforms/NaCl/ExpandConstantExpr.cpp
new file mode 100644
index 0000000000..5ff47cb00c
--- /dev/null
+++ b/lib/Transforms/NaCl/ExpandConstantExpr.cpp
@@ -0,0 +1,112 @@
+//===- ExpandConstantExpr.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 expands out ConstantExprs into Instructions.
+//
+// Note that this only converts ConstantExprs that are referenced by
+// Instructions. It does not convert ConstantExprs that are used as
+// initializers for global variables.
+//
+// This simplifies the language so that the PNaCl translator does not
+// need to handle ConstantExprs as part of a stable wire format for
+// PNaCl.
+//
+//===----------------------------------------------------------------------===//
+
+#include <map>
+
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/Pass.h"
+#include "llvm/Transforms/NaCl.h"
+
+using namespace llvm;
+
+static bool expandInstruction(Instruction *Inst);
+
+namespace {
+ // This is a FunctionPass because our handling of PHI nodes means
+ // that our modifications may cross BasicBlocks.
+ struct ExpandConstantExpr : public FunctionPass {
+ static char ID; // Pass identification, replacement for typeid
+ ExpandConstantExpr() : FunctionPass(ID) {
+ initializeExpandConstantExprPass(*PassRegistry::getPassRegistry());
+ }
+
+ virtual bool runOnFunction(Function &Func);
+ };
+}
+
+char ExpandConstantExpr::ID = 0;
+INITIALIZE_PASS(ExpandConstantExpr, "expand-constant-expr",
+ "Expand out ConstantExprs into Instructions",
+ false, false)
+
+static Value *expandConstantExpr(Instruction *InsertPt, ConstantExpr *Expr) {
+ Instruction *NewInst = Expr->getAsInstruction();
+ NewInst->insertBefore(InsertPt);
+ NewInst->setName("expanded");
+ expandInstruction(NewInst);
+ return NewInst;
+}
+
+static bool expandInstruction(Instruction *Inst) {
+ // A landingpad can only accept ConstantExprs, so it should remain
+ // unmodified.
+ if (isa<LandingPadInst>(Inst))
+ return false;
+
+ bool Modified = false;
+ if (PHINode *PN = dyn_cast<PHINode>(Inst)) {
+ // PHI nodes require special treatment. A incoming block may be
+ // listed twice, but its incoming values must match so they must
+ // be converted only once.
+ std::map<BasicBlock*,Value*> Converted;
+ for (unsigned OpNum = 0; OpNum < Inst->getNumOperands(); OpNum++) {
+ if (ConstantExpr *Expr =
+ dyn_cast<ConstantExpr>(Inst->getOperand(OpNum))) {
+ Modified = true;
+ BasicBlock *Incoming = PN->getIncomingBlock(OpNum);
+ if (Converted.count(Incoming) == 0) {
+ Converted[Incoming] = expandConstantExpr(Incoming->getTerminator(),
+ Expr);
+ }
+ Inst->setOperand(OpNum, Converted[Incoming]);
+ }
+ }
+ return Modified;
+ }
+
+ for (unsigned OpNum = 0; OpNum < Inst->getNumOperands(); OpNum++) {
+ if (ConstantExpr *Expr =
+ dyn_cast<ConstantExpr>(Inst->getOperand(OpNum))) {
+ Modified = true;
+ Inst->setOperand(OpNum, expandConstantExpr(Inst, Expr));
+ }
+ }
+ return Modified;
+}
+
+bool ExpandConstantExpr::runOnFunction(Function &Func) {
+ bool Modified = false;
+ for (llvm::Function::iterator BB = Func.begin(), E = Func.end();
+ BB != E;
+ ++BB) {
+ for (BasicBlock::InstListType::iterator Inst = BB->begin(), E = BB->end();
+ Inst != E;
+ ++Inst) {
+ Modified |= expandInstruction(Inst);
+ }
+ }
+ return Modified;
+}
+
+FunctionPass *llvm::createExpandConstantExprPass() {
+ return new ExpandConstantExpr();
+}
diff --git a/test/NaCl/PNaClABI/instructions.ll b/test/NaCl/PNaClABI/instructions.ll
index 7461f7a361..3bd95c8e0f 100644
--- a/test/NaCl/PNaClABI/instructions.ll
+++ b/test/NaCl/PNaClABI/instructions.ll
@@ -1,4 +1,4 @@
-; RUN: opt -verify-pnaclabi-functions -analyze < %s | FileCheck %s
+; RUN: pnacl-abicheck < %s | FileCheck %s
; Test instruction opcodes allowed by PNaCl ABI
; No testing yet of operands, types, attributes, etc
diff --git a/test/NaCl/PNaClABI/linkagetypes.ll b/test/NaCl/PNaClABI/linkagetypes.ll
index ab6d81f351..7aa0ea8122 100644
--- a/test/NaCl/PNaClABI/linkagetypes.ll
+++ b/test/NaCl/PNaClABI/linkagetypes.ll
@@ -1,4 +1,4 @@
-; RUN: opt -verify-pnaclabi-module -analyze < %s | FileCheck %s
+; RUN: pnacl-abicheck < %s | FileCheck %s
; Test linkage types allowed by PNaCl ABI
target datalayout = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-p:32:32:32-v128:32:32"
diff --git a/test/NaCl/PNaClABI/types-function.ll b/test/NaCl/PNaClABI/types-function.ll
index d020c76499..e781163b83 100644
--- a/test/NaCl/PNaClABI/types-function.ll
+++ b/test/NaCl/PNaClABI/types-function.ll
@@ -1,4 +1,4 @@
-; RUN: opt -verify-pnaclabi-functions -analyze < %s | FileCheck %s
+; RUN: pnacl-abicheck < %s | FileCheck %s
; Test type-checking in function bodies. This test is not intended to verify
; all the rules about the various types, but instead to make sure that types
; stashed in various places in function bodies are caught.
diff --git a/test/NaCl/PNaClABI/types.ll b/test/NaCl/PNaClABI/types.ll
index 05248bae06..8fdfb4e794 100644
--- a/test/NaCl/PNaClABI/types.ll
+++ b/test/NaCl/PNaClABI/types.ll
@@ -1,4 +1,4 @@
-; RUN: opt -verify-pnaclabi-module -analyze < %s | FileCheck %s
+; RUN: pnacl-abicheck < %s | FileCheck %s
; Test types allowed by PNaCl ABI
; Basic global types
diff --git a/test/NaCl/X86/nacl64-addrmodes.ll b/test/NaCl/X86/nacl64-addrmodes.ll
index c4dc359bdb..fa528a5740 100644
--- a/test/NaCl/X86/nacl64-addrmodes.ll
+++ b/test/NaCl/X86/nacl64-addrmodes.ll
@@ -1,4 +1,7 @@
-; RUN: llc -mtriple=x86_64-unknown-nacl -filetype=asm %s -o - \
+; RUN: llc -mtriple=x86_64-unknown-nacl -filetype=asm %s -O0 -o - \
+; RUN: | FileCheck %s
+
+; RUN: llc -mtriple=x86_64-unknown-nacl -filetype=asm %s -O2 -o - \
; RUN: | FileCheck %s
; Check that we don't try to fold a negative displacement into a memory
@@ -67,3 +70,62 @@ entry:
%cmp = icmp eq i64 %conv, %add18
ret i1 %cmp
}
+
+
+@main.array = private unnamed_addr constant [1 x i64] [i64 1438933078946427748], align 8
+
+define i1 @largeconst_frameindex() nounwind {
+; CHECK: largeconst_frameindex
+entry:
+ %retval = alloca i32, align 4
+ %r_Ng = alloca i64, align 8
+ %i = alloca i32, align 4
+ %adat = alloca i64*, align 4
+ %array = alloca [1 x i64], align 8
+ store i32 0, i32* %retval
+ store i32 -270770481, i32* %i, align 4
+ %0 = bitcast [1 x i64]* %array to i8*
+ call void @llvm.memcpy.p0i8.p0i8.i32(i8* %0, i8* bitcast ([1 x i64]* @main.array to i8*), i32 8, i32 8, i1 false)
+ store i32 -270770481, i32* %i, align 4
+ %1 = load i32* %i, align 4
+ %mul = mul i32 %1, 947877507
+ %add = add i32 %mul, 1574375955
+ %2 = bitcast [1 x i64]* %array to i64*
+ %arrayidx = getelementptr inbounds i64* %2, i32 %add
+; Ensure the large constant didn't get folded into the load
+; CHECK: nacl:(%r15
+ %3 = load i64* %arrayidx, align 8
+ %add1 = add i64 %3, -5707596139582126917
+ %4 = load i32* %i, align 4
+ %mul2 = mul i32 %4, 947877507
+ %add3 = add i32 %mul2, 1574375955
+ %5 = bitcast [1 x i64]* %array to i64*
+ %arrayidx4 = getelementptr inbounds i64* %5, i32 %add3
+ store i64 %add1, i64* %arrayidx4, align 8
+ %6 = load i32* %i, align 4
+ %mul5 = mul nsw i32 %6, 947877507
+ %add6 = add nsw i32 %mul5, 1574375955
+ %arrayidx7 = getelementptr inbounds [1 x i64]* %array, i32 0, i32 %add6
+; CHECK: nacl:(%r15
+ %7 = load i64* %arrayidx7, align 8
+ %add8 = add i64 %7, -5707596139582126917
+ %8 = load i32* %i, align 4
+ %mul9 = mul nsw i32 %8, 947877507
+ %add10 = add nsw i32 %mul9, 1574375955
+ %arrayidx11 = getelementptr inbounds [1 x i64]* %array, i32 0, i32 %add10
+ store i64 %add8, i64* %arrayidx11, align 8
+ %9 = load i32* %i, align 4
+ %mul12 = mul nsw i32 %9, 947877507
+ %add13 = add nsw i32 %mul12, 1574375955
+ %10 = bitcast [1 x i64]* %array to i64*
+ %arrayidx14 = getelementptr inbounds i64* %10, i32 %add13
+ store i64* %arrayidx14, i64** %adat, align 4
+ %11 = load i64** %adat, align 4
+ %12 = load i64* %11, align 8
+ %mul15 = mul i64 %12, -1731288434922394955
+ %add16 = add i64 %mul15, -7745351015538694962
+ store i64 %add16, i64* %r_Ng, align 8
+ ret i1 0
+}
+
+declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32, i1) nounwind \ No newline at end of file
diff --git a/test/Transforms/NaCl/expand-constantexpr.ll b/test/Transforms/NaCl/expand-constantexpr.ll
new file mode 100644
index 0000000000..e8786d4cac
--- /dev/null
+++ b/test/Transforms/NaCl/expand-constantexpr.ll
@@ -0,0 +1,109 @@
+; RUN: opt < %s -expand-constant-expr -S | FileCheck %s
+
+@global_var1 = global i32 123
+@global_var2 = global i32 123
+
+
+define i8* @constantexpr_bitcast() {
+ ret i8* bitcast (i32* @global_var1 to i8*)
+}
+; CHECK: @constantexpr_bitcast
+; CHECK: %expanded = bitcast i32* @global_var1 to i8*
+; CHECK: ret i8* %expanded
+
+
+define i32 @constantexpr_nested() {
+ ret i32 add (i32 ptrtoint (i32* @global_var1 to i32),
+ i32 ptrtoint (i32* @global_var2 to i32))
+}
+; CHECK: @constantexpr_nested
+; CHECK: %expanded1 = ptrtoint i32* @global_var1 to i32
+; CHECK: %expanded2 = ptrtoint i32* @global_var2 to i32
+; CHECK: %expanded = add i32 %expanded1, %expanded2
+; CHECK: ret i32 %expanded
+
+
+define i32 @constantexpr_nested2() {
+ ret i32 mul (i32 add (i32 ptrtoint (i32* @global_var1 to i32),
+ i32 ptrtoint (i32* @global_var2 to i32)), i32 2)
+}
+; CHECK: @constantexpr_nested2
+; CHECK: %expanded2 = ptrtoint i32* @global_var1 to i32
+; CHECK: %expanded3 = ptrtoint i32* @global_var2 to i32
+; CHECK: %expanded1 = add i32 %expanded2, %expanded3
+; CHECK: %expanded = mul i32 %expanded1, 2
+; CHECK: ret i32 %expanded
+
+
+define i32 @constantexpr_phi() {
+entry:
+ br label %label
+label:
+ %result = phi i32 [ ptrtoint (i32* @global_var1 to i32), %entry ]
+ ret i32 %result
+}
+; CHECK: @constantexpr_phi
+; CHECK: entry:
+; CHECK: %expanded = ptrtoint i32* @global_var1 to i32
+; CHECK: br label %label
+; CHECK: label:
+; CHECK: %result = phi i32 [ %expanded, %entry ]
+
+
+; This tests that ExpandConstantExpr correctly handles a PHI node that
+; contains the same