Index: lib/Analysis/NaCl/PNaClABITypeChecker.cpp |
diff --git a/lib/Analysis/NaCl/PNaClABITypeChecker.cpp b/lib/Analysis/NaCl/PNaClABITypeChecker.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..9ce28ed7961c01156741a65b9200c30ed9283485 |
--- /dev/null |
+++ b/lib/Analysis/NaCl/PNaClABITypeChecker.cpp |
@@ -0,0 +1,109 @@ |
+//===- PNaClABITypeChecker.cpp - 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 "llvm/Analysis/NaCl/PNaClABITypeChecker.h" |
+#include "llvm/IR/Constant.h" |
+#include "llvm/IR/Constants.h" |
+#include "llvm/IR/DerivedTypes.h" |
+#include "llvm/IR/Metadata.h" |
+ |
+using namespace llvm; |
+ |
+bool PNaClABITypeChecker::isValidParamType(const Type *Ty) { |
+ if (!(isValidScalarType(Ty) || isValidVectorType(Ty))) |
+ return false; |
+ if (const IntegerType *IntTy = dyn_cast<IntegerType>(Ty)) { |
+ // PNaCl requires function arguments and return values to be 32 |
+ // bits or larger. This avoids exposing architecture |
+ // ABI-dependent differences about whether arguments or return |
+ // values are zero-extended when calling a function with the wrong |
+ // prototype. |
+ if (IntTy->getBitWidth() < 32) |
+ return false; |
+ } |
+ return true; |
+} |
+ |
+bool PNaClABITypeChecker::isValidFunctionType(const FunctionType *FTy) { |
+ if (FTy->isVarArg()) |
+ return false; |
+ if (!isValidParamType(FTy->getReturnType())) |
+ return false; |
+ for (unsigned I = 0, E = FTy->getNumParams(); I < E; ++I) { |
+ if (!isValidParamType(FTy->getParamType(I))) |
+ return false; |
+ } |
+ return true; |
+} |
+ |
+namespace { |
+static inline bool NaClIsValidIntType(const Type *Ty) { |
+ unsigned Width = cast<const IntegerType>(Ty)->getBitWidth(); |
+ return Width == 1 || Width == 8 || Width == 16 || |
+ Width == 32 || Width == 64; |
+} |
+} |
+ |
+bool PNaClABITypeChecker::isValidScalarType(const Type *Ty) { |
+ switch (Ty->getTypeID()) { |
+ case Type::IntegerTyID: { |
+ return NaClIsValidIntType(Ty); |
+ } |
+ case Type::VoidTyID: |
+ case Type::FloatTyID: |
+ case Type::DoubleTyID: |
+ return true; |
+ default: |
+ return false; |
+ } |
+} |
+ |
+// TODO(jfb) Handle 64-bit int and double, and 2xi1. |
+bool PNaClABITypeChecker::isValidVectorType(const Type *Ty) { |
+ if (!Ty->isVectorTy()) |
+ return false; |
+ unsigned Elems = Ty->getVectorNumElements(); |
+ const Type *VTy = Ty->getVectorElementType(); |
+ |
+ switch (VTy->getTypeID()) { |
+ case Type::IntegerTyID: { |
+ unsigned Width = cast<const IntegerType>(VTy)->getBitWidth(); |
+ switch (Width) { |
+ case 1: return Elems == 4 || Elems == 8 || Elems == 16; |
+ case 8: return Elems == 16; |
+ case 16: return Elems == 8; |
+ case 32: return Elems == 4; |
+ default: return false; |
+ } |
+ } |
+ case Type::FloatTyID: |
+ return Elems == 4; |
+ default: |
+ return false; |
+ } |
+} |
+ |
+namespace { |
+static inline bool NaClIsValidIntArithmeticType(const Type *Ty) { |
+ return Ty->isIntegerTy() && !Ty->isIntegerTy(1) |
+ && NaClIsValidIntType(Ty); |
+} |
+ |
+} |
+ |
+bool PNaClABITypeChecker::isValidIntArithmeticType(const Type *Ty) { |
+ if (isValidVectorType(Ty)) |
+ return NaClIsValidIntArithmeticType(Ty->getVectorElementType()); |
+ return NaClIsValidIntArithmeticType(Ty); |
+} |