diff options
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 |