Initial checkin of pointer safety checker
authorChris Lattner <sabre@nondot.org>
Wed, 7 Nov 2001 21:16:12 +0000 (21:16 +0000)
committerChris Lattner <sabre@nondot.org>
Wed, 7 Nov 2001 21:16:12 +0000 (21:16 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@1181 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Analysis/FindUnsafePointerTypes.h [new file with mode: 0644]
lib/Analysis/IPA/FindUnsafePointerTypes.cpp [new file with mode: 0644]

diff --git a/include/llvm/Analysis/FindUnsafePointerTypes.h b/include/llvm/Analysis/FindUnsafePointerTypes.h
new file mode 100644 (file)
index 0000000..3f66f33
--- /dev/null
@@ -0,0 +1,47 @@
+//===- llvm/Analysis/SafePointerAccess.h - Check pointer safety ---*- C++ -*-=//
+//
+// This file defines a pass that can be used to determine, interprocedurally, 
+// which pointer types are accessed unsafely in a program.  If there is an
+// "unsafe" access to a specific pointer type, transformations that depend on
+// type safety cannot be permitted.
+//
+// The result of running this analysis over a program is a set of unsafe pointer
+// types that cannot be transformed.  Safe pointer types are not tracked.
+//
+// Additionally, this analysis exports a hidden command line argument that (when
+// enabled) prints out the reasons a type was determined to be unsafe.  Just add
+// -unsafeptrinst to the command line of the tool you want to get it.
+// 
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ANALYSIS_SAFEPOINTERACCESS_H
+#define LLVM_ANALYSIS_SAFEPOINTERACCESS_H
+
+#include "llvm/Pass.h"
+#include <set>
+
+class PointerType;
+
+struct FindUnsafePointerTypes : public Pass {
+  // UnsafeTypes - Set of types that are not safe to transform.
+  set<PointerType*> UnsafeTypes;
+public:
+
+  // Accessor for underlying type set...
+  inline const set<PointerType*> &getUnsafeTypes() const {
+    return UnsafeTypes;
+  }
+
+  // doPerMethodWork - Inspect the operations that the specified method does on
+  // values of various types.  If they are deemed to be 'unsafe' note that the
+  // type is not safe to transform.
+  //
+  virtual bool doPerMethodWork(Method *M);
+
+  // printResults - Loop over the results of the analysis, printing out unsafe
+  // types.
+  //
+  void printResults(const Module *Mod, ostream &o);
+};
+
+#endif
diff --git a/lib/Analysis/IPA/FindUnsafePointerTypes.cpp b/lib/Analysis/IPA/FindUnsafePointerTypes.cpp
new file mode 100644 (file)
index 0000000..48e474f
--- /dev/null
@@ -0,0 +1,92 @@
+//===- SafePointerAccess.cpp - Check pointer usage safety -------------------=//
+//
+// This file defines a pass that can be used to determine, interprocedurally, 
+// which pointer types are accessed unsafely in a program.  If there is an
+// "unsafe" access to a specific pointer type, transformations that depend on
+// type safety cannot be permitted.
+//
+// The result of running this analysis over a program is a set of unsafe pointer
+// types that cannot be transformed.  Safe pointer types are not tracked.
+//
+// Additionally, this analysis exports a hidden command line argument that (when
+// enabled) prints out the reasons a type was determined to be unsafe.
+//
+// Currently, the only allowed operations on pointer types are:
+//   alloca, malloc, free, getelementptr, load, and store
+// 
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Analysis/FindUnsafePointerTypes.h"
+#include "llvm/Assembly/CachedWriter.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Type.h"
+
+// Provide a command line option to turn on printing of which instructions cause
+// a type to become invalid
+//
+static cl::Flag 
+PrintFailures("printunsafeptrinst", "Print Unsafe Pointer Access Instructions",
+              cl::Hidden, false);
+
+static inline bool isSafeInstruction(const Instruction *I) {
+  switch (I->getOpcode()) {
+  case Instruction::Alloca:
+  case Instruction::Malloc:
+  case Instruction::Free:
+  case Instruction::Load:
+  case Instruction::Store:
+  case Instruction::GetElementPtr:
+  case Instruction::Call:
+  case Instruction::Invoke:
+  case Instruction::PHINode:
+    return true;
+  }
+  return false;
+}
+
+
+// doPerMethodWork - Inspect the operations that the specified method does on
+// values of various types.  If they are deemed to be 'unsafe' note that the
+// type is not safe to transform.
+//
+bool FindUnsafePointerTypes::doPerMethodWork(Method *Meth) {
+  const Method *M = Meth;  // We don't need/want write access
+  for (Method::inst_const_iterator I = M->inst_begin(), E = M->inst_end();
+       I != E; ++I) {
+    const Instruction *Inst = *I;
+    const Type *ITy = Inst->getType();
+    if (ITy->isPointerType() && !UnsafeTypes.count((PointerType*)ITy))
+      if (!isSafeInstruction(Inst)) {
+        UnsafeTypes.insert((PointerType*)ITy);
+
+        if (PrintFailures) {
+          CachedWriter CW(M->getParent(), cerr);
+          CW << "FindUnsafePointerTypes: Type '" << ITy
+             << "' marked unsafe by:\n" << Inst;
+        }
+      }
+  }
+
+  return false;
+}
+
+
+// printResults - Loop over the results of the analysis, printing out unsafe
+// types.
+//
+void FindUnsafePointerTypes::printResults(const Module *M, ostream &o) {
+  if (UnsafeTypes.empty()) {
+    o << "SafePointerAccess Analysis: No unsafe types found!\n";
+    return;
+  }
+
+  CachedWriter CW(M, o);
+
+  CW << "SafePointerAccess Analysis: Found these unsafe types:\n";
+  unsigned Counter = 1;
+  for (set<PointerType*>::const_iterator I = getUnsafeTypes().begin(), 
+         E = getUnsafeTypes().end(); I != E; ++I, ++Counter) {
+    
+    CW << " #" << Counter << ". " << (Value*)*I << endl;
+  }
+}