diff options
author | Derek Schuff <dschuff@chromium.org> | 2013-02-19 15:13:36 -0800 |
---|---|---|
committer | Derek Schuff <dschuff@chromium.org> | 2013-02-19 15:13:36 -0800 |
commit | 06dd2371667be256a846a68e51d376349f041752 (patch) | |
tree | fe02d69310734aab59839d5f27e802117664c35a | |
parent | 50c20006ea707be7e439c3093d4a064ccfe78b7a (diff) |
Move ABI type checker to its own file
R=jvoung@chromium.org,eliben@chromium.org
BUG=
Review URL: https://codereview.chromium.org/12302030
-rw-r--r-- | lib/Analysis/NaCl/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/Analysis/NaCl/CheckTypes.h | 130 | ||||
-rw-r--r-- | lib/Analysis/NaCl/PNaClABITypeChecker.cpp | 106 | ||||
-rw-r--r-- | lib/Analysis/NaCl/PNaClABITypeChecker.h | 52 | ||||
-rw-r--r-- | lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp | 8 | ||||
-rw-r--r-- | lib/Analysis/NaCl/PNaClABIVerifyModule.cpp | 13 |
6 files changed, 170 insertions, 140 deletions
diff --git a/lib/Analysis/NaCl/CMakeLists.txt b/lib/Analysis/NaCl/CMakeLists.txt index 8a5eceb3e4..7fa3a134ac 100644 --- a/lib/Analysis/NaCl/CMakeLists.txt +++ b/lib/Analysis/NaCl/CMakeLists.txt @@ -1,4 +1,5 @@ add_llvm_library(LLVMAnalysisNaCl + PNaCLABITypeChecker.cpp PNaClABIVerifyFunctions.cpp PNaClABIVerifyModule.cpp ) diff --git a/lib/Analysis/NaCl/CheckTypes.h b/lib/Analysis/NaCl/CheckTypes.h deleted file mode 100644 index 64a634cd25..0000000000 --- a/lib/Analysis/NaCl/CheckTypes.h +++ /dev/null @@ -1,130 +0,0 @@ -//===- CheckTypes.h - Verify PNaCl ABI rules --------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Common type-checking code for module and function-level passes -// -// -//===----------------------------------------------------------------------===// - -#ifndef LIB_ANALYSIS_NACL_CHECKTYPES_H -#define LIB_ANALYSIS_NACL_CHECKTYPES_H - -#include "llvm/ADT/DenseSet.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/Support/raw_ostream.h" - -class TypeChecker { - public: - bool isValidType(const llvm::Type *Ty) { - if (VisitedTypes.count(Ty)) - return VisitedTypes[Ty]; - - unsigned Width; - bool Valid = false; - switch (Ty->getTypeID()) { - // Allowed primitive types - case llvm::Type::VoidTyID: - case llvm::Type::FloatTyID: - case llvm::Type::DoubleTyID: - case llvm::Type::LabelTyID: - case llvm::Type::MetadataTyID: - Valid = true; - break; - // Disallowed primitive types - case llvm::Type::HalfTyID: - case llvm::Type::X86_FP80TyID: - case llvm::Type::FP128TyID: - case llvm::Type::PPC_FP128TyID: - case llvm::Type::X86_MMXTyID: - Valid = false; - break; - // Derived types - case llvm::Type::VectorTyID: - Valid = false; - break; - case llvm::Type::IntegerTyID: - Width = llvm::cast<const llvm::IntegerType>(Ty)->getBitWidth(); - Valid = (Width == 1 || Width == 8 || Width == 16 || - Width == 32 || Width == 64); - break; - case llvm::Type::FunctionTyID: - case llvm::Type::StructTyID: - case llvm::Type::ArrayTyID: - case llvm::Type::PointerTyID: - // These types are valid if their contained or pointed-to types are - // valid. Since struct/pointer subtype relationships may be circular, - // mark the current type as valid to avoid infinite recursion - Valid = true; - VisitedTypes[Ty] = true; - for (llvm::Type::subtype_iterator I = Ty->subtype_begin(), - E = Ty->subtype_end(); I != E; ++I) - Valid &= isValidType(*I); - break; - // Handle NumTypeIDs, and no default case, - // so we get a warning if new types are added - case llvm::Type::NumTypeIDs: - Valid = false; - break; - } - - VisitedTypes[Ty] = Valid; - return Valid; - } - - // If the value contains an invalid type, return a pointer to the type. - // Return null if there are no invalid types. - llvm::Type *checkTypesInValue(const llvm::Value *V) { - // TODO: Checking types in values probably belongs in its - // own value checker which also handles the various types of - // constexpr (in particular, blockaddr constexprs cause this code - // to assert rather than go off and try to verify the BBs of a function) - // But this code is in a good consistent checkpoint-able state. - assert(llvm::isa<llvm::Constant>(V)); - if (VisitedConstants.count(V)) - return VisitedConstants[V]; - - if (!isValidType(V->getType())) { - VisitedConstants[V] = V->getType(); - return V->getType(); - } - - // Operand values must also be valid. Values may be circular, so - // mark the current value as valid to avoid infinite recursion. - VisitedConstants[V] = NULL; - const llvm::User *U = llvm::cast<llvm::User>(V); - for (llvm::Constant::const_op_iterator I = U->op_begin(), - E = U->op_end(); I != E; ++I) { - llvm::Type *Invalid = checkTypesInValue(*I); - if (Invalid) { - VisitedConstants[V] = Invalid; - return Invalid; - } - } - VisitedConstants[V] = NULL; - return NULL; - } - - // There's no built-in way to get the name of a type, so use a - // string ostream to print it. - static std::string getTypeName(const llvm::Type *T) { - std::string TypeName; - llvm::raw_string_ostream N(TypeName); - T->print(N); - return N.str(); - } - - private: - // To avoid walking constexprs and types multiple times, keep a cache of - // what we have seen. This is also used to prevent infinite recursion e.g. - // in case of structures like linked lists with pointers to themselves. - llvm::DenseMap<const llvm::Value*, llvm::Type*> VisitedConstants; - llvm::DenseMap<const llvm::Type*, bool> VisitedTypes; -}; - -#endif // LIB_ANALYSIS_NACL_CHECKTYPES_H diff --git a/lib/Analysis/NaCl/PNaClABITypeChecker.cpp b/lib/Analysis/NaCl/PNaClABITypeChecker.cpp new file mode 100644 index 0000000000..3a18129588 --- /dev/null +++ b/lib/Analysis/NaCl/PNaClABITypeChecker.cpp @@ -0,0 +1,106 @@ +//===- PNaClABICheckTypes.h - Verify PNaCl ABI rules --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Common type-checking code for module and function-level passes +// +// +//===----------------------------------------------------------------------===// + +#include "PNaClABITypeChecker.h" +#include "llvm/IR/Constant.h" +#include "llvm/IR/DerivedTypes.h" + +using namespace llvm; + +bool PNaClABITypeChecker::isValidType(const Type *Ty) { + if (VisitedTypes.count(Ty)) + return VisitedTypes[Ty]; + + unsigned Width; + bool Valid = false; + switch (Ty->getTypeID()) { + // Allowed primitive types + case Type::VoidTyID: + case Type::FloatTyID: + case Type::DoubleTyID: + case Type::LabelTyID: + case Type::MetadataTyID: + Valid = true; + break; + // Disallowed primitive types + case Type::HalfTyID: + case Type::X86_FP80TyID: + case Type::FP128TyID: + case Type::PPC_FP128TyID: + case Type::X86_MMXTyID: + Valid = false; + break; + // Derived types + case Type::VectorTyID: + Valid = false; + break; + case Type::IntegerTyID: + Width = cast<const IntegerType>(Ty)->getBitWidth(); + Valid = (Width == 1 || Width == 8 || Width == 16 || + Width == 32 || Width == 64); + break; + case Type::FunctionTyID: + case Type::StructTyID: + case Type::ArrayTyID: + case Type::PointerTyID: + // These types are valid if their contained or pointed-to types are + // valid. Since struct/pointer subtype relationships may be circular, + // mark the current type as valid to avoid infinite recursion + Valid = true; + VisitedTypes[Ty] = true; + for (Type::subtype_iterator I = Ty->subtype_begin(), + E = Ty->subtype_end(); I != E; ++I) + Valid &= isValidType(*I); + break; + // Handle NumTypeIDs, and no default case, + // so we get a warning if new types are added + case Type::NumTypeIDs: + Valid = false; + break; + } + + VisitedTypes[Ty] = Valid; + return Valid; +} + +Type *PNaClABITypeChecker::checkTypesInValue(const Value *V) { + // TODO: Checking types in values probably belongs in its + // own value checker which also handles the various types of + // constexpr (in particular, blockaddr constexprs cause this code + // to assert rather than go off and try to verify the BBs of a function) + // But this code is in a good consistent checkpoint-able state. + assert(isa<Constant>(V)); + if (VisitedConstants.count(V)) + return VisitedConstants[V]; + + if (!isValidType(V->getType())) { + VisitedConstants[V] = V->getType(); + return V->getType(); + } + + // Operand values must also be valid. Values may be circular, so + // mark the current value as valid to avoid infinite recursion. + VisitedConstants[V] = NULL; + const User *U = cast<User>(V); + for (Constant::const_op_iterator I = U->op_begin(), + E = U->op_end(); I != E; ++I) { + Type *Invalid = checkTypesInValue(*I); + if (Invalid) { + VisitedConstants[V] = Invalid; + return Invalid; + } + } + VisitedConstants[V] = NULL; + return NULL; +} diff --git a/lib/Analysis/NaCl/PNaClABITypeChecker.h b/lib/Analysis/NaCl/PNaClABITypeChecker.h new file mode 100644 index 0000000000..1249bf04cd --- /dev/null +++ b/lib/Analysis/NaCl/PNaClABITypeChecker.h @@ -0,0 +1,52 @@ +//===- CheckTypes.h - Verify PNaCl ABI rules --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Common type-checking code for module and function-level passes +// +// +//===----------------------------------------------------------------------===// + +#ifndef LIB_ANALYSIS_NACL_CHECKTYPES_H +#define LIB_ANALYSIS_NACL_CHECKTYPES_H + +#include "llvm/ADT/DenseSet.h" +#include "llvm/IR/Type.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { +class Value; + +class PNaClABITypeChecker { + public: + // Returns true if Ty is a valid type for PNaCl. + bool isValidType(const Type *Ty); + + // If the value contains an invalid type, return a pointer to the type. + // Return null if there are no invalid types. + Type *checkTypesInValue(const Value *V); + + // There's no built-in way to get the name of a type, so use a + // string ostream to print it. + static std::string getTypeName(const Type *T) { + std::string TypeName; + raw_string_ostream N(TypeName); + T->print(N); + return N.str(); + } + + private: + // To avoid walking constexprs and types multiple times, keep a cache of + // what we have seen. This is also used to prevent infinite recursion e.g. + // in case of structures like linked lists with pointers to themselves. + DenseMap<const Value*, Type*> VisitedConstants; + DenseMap<const Type*, bool> VisitedTypes; +}; +} // namespace llvm + +#endif // LIB_ANALYSIS_NACL_CHECKTYPES_H diff --git a/lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp b/lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp index df57cfbbce..97278d95cc 100644 --- a/lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp +++ b/lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp @@ -19,7 +19,7 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/Analysis/NaCl.h" -#include "CheckTypes.h" +#include "PNaClABITypeChecker.h" using namespace llvm; namespace { @@ -31,9 +31,9 @@ class PNaClABIVerifyFunctions : public FunctionPass { static char ID; PNaClABIVerifyFunctions() : FunctionPass(ID), Errors(ErrorsString) {} bool runOnFunction(Function &F); - virtual void print(llvm::raw_ostream &O, const Module *M) const; + virtual void print(raw_ostream &O, const Module *M) const; private: - TypeChecker TC; + PNaClABITypeChecker TC; std::string ErrorsString; raw_string_ostream Errors; }; @@ -126,7 +126,7 @@ bool PNaClABIVerifyFunctions::runOnFunction(Function &F) { if (!TC.isValidType(BBI->getType())) { Errors << "Function " + F.getName() + " has instruction with disallowed type: " + - TypeChecker::getTypeName(BBI->getType()) + "\n"; + PNaClABITypeChecker::getTypeName(BBI->getType()) + "\n"; } } } diff --git a/lib/Analysis/NaCl/PNaClABIVerifyModule.cpp b/lib/Analysis/NaCl/PNaClABIVerifyModule.cpp index afe42434e7..54666378b3 100644 --- a/lib/Analysis/NaCl/PNaClABIVerifyModule.cpp +++ b/lib/Analysis/NaCl/PNaClABIVerifyModule.cpp @@ -20,7 +20,7 @@ #include "llvm/IR/Module.h" #include "llvm/Support/raw_ostream.h" -#include "CheckTypes.h" +#include "PNaClABITypeChecker.h" using namespace llvm; namespace { @@ -30,11 +30,11 @@ class PNaClABIVerifyModule : public ModulePass { static char ID; PNaClABIVerifyModule(); bool runOnModule(Module &M); - virtual void print(llvm::raw_ostream &O, const Module *M) const; + virtual void print(raw_ostream &O, const Module *M) const; private: - TypeChecker TC; + PNaClABITypeChecker TC; std::string ErrorsString; - llvm::raw_string_ostream Errors; + raw_string_ostream Errors; }; static const char *linkageName(GlobalValue::LinkageTypes LT) { @@ -76,14 +76,15 @@ bool PNaClABIVerifyModule::runOnModule(Module &M) { // GVs are pointers, so print the pointed-to type for clarity Errors << "Variable " + MI->getName() + " has disallowed type: " + - TypeChecker::getTypeName(MI->getType()->getContainedType(0)) + "\n"; + 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.checkTypesInValue(MI->getInitializer()); if (T) Errors << "Initializer for " + MI->getName() + " has disallowed type: " + - TypeChecker::getTypeName(T) + "\n"; + PNaClABITypeChecker::getTypeName(T) + "\n"; } // Check GV linkage types |