aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2008-05-07 18:21:13 +0000
committerChris Lattner <sabre@nondot.org>2008-05-07 18:21:13 +0000
commit14852f27e792470232287371c5ffd4cee1d5b943 (patch)
tree1cbcc88ab4a3b6fc57f0f53e452bccb239e477e8
parent094aa6ce47f0f0604469e0a24bde131ce6326938 (diff)
Add a new interface for describing the behavior of library calls. This
Currently is sufficient to describe mod/ref behavior but will hopefully eventually be extended for other purposes. This isn't used by anything yet. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50820 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/Analysis/LibCallSemantics.h166
-rw-r--r--lib/Analysis/LibCallSemantics.cpp65
2 files changed, 231 insertions, 0 deletions
diff --git a/include/llvm/Analysis/LibCallSemantics.h b/include/llvm/Analysis/LibCallSemantics.h
new file mode 100644
index 0000000000..74e8401a1f
--- /dev/null
+++ b/include/llvm/Analysis/LibCallSemantics.h
@@ -0,0 +1,166 @@
+//===- LibCallSemantics.h - Describe library semantics --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines interfaces that can be used to describe language specific
+// runtime library interfaces (e.g. libc, libm, etc) to LLVM optimizers.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ANALYSIS_LIBCALLSEMANTICS_H
+#define LLVM_ANALYSIS_LIBCALLSEMANTICS_H
+
+#include "llvm/Analysis/AliasAnalysis.h"
+
+namespace llvm {
+
+ /// LibCallLocationInfo - This struct describes a set of memory locations that
+ /// are accessed by libcalls. Identification of a location is doing with a
+ /// simple callback function.
+ ///
+ /// For example, the LibCallInfo may be set up to model the behavior of
+ /// standard libm functions. The location that they may be interested in is
+ /// an abstract location that represents errno for the current target. In
+ /// this case, a location for errno is anything such that the predicate
+ /// returns true. On Mac OS/X, this predicate would return true if the
+ /// pointer is the result of a call to "__error()".
+ ///
+ /// Locations can also be defined in a constant-sensitive way. For example,
+ /// it is possible to define a location that returns true iff it is passed
+ /// into the call as a specific argument. This is useful for modeling things
+ /// like "printf", which can store to memory, but only through pointers passed
+ /// with a '%n' constraint.
+ ///
+ struct LibCallLocationInfo {
+ // TODO: Flags: isContextSensitive etc.
+
+ /// isLocation - Return a LocResult if the specified pointer refers to this
+ /// location for the specified call site. This returns "Yes" if we can tell
+ /// that the pointer *does definitely* refer to the location, "No" if we can
+ /// tell that the location *definitely does not* refer to the location, and
+ /// returns "Unknown" if we cannot tell for certain.
+ enum LocResult {
+ Yes, No, Unknown
+ };
+ LocResult (*isLocation)(CallSite CS, const Value *Ptr, unsigned Size);
+ };
+
+ /// LibCallFunctionInfo - Each record in the array of FunctionInfo structs
+ /// records the behavior of one libcall that is known by the optimizer. This
+ /// captures things like the side effects of the call. Side effects are
+ /// modeled both universally (in the readnone/readonly) sense, but also
+ /// potentially against a set of abstract locations defined by the optimizer.
+ /// This allows an optimizer to define that some libcall (e.g. sqrt) is
+ /// side-effect free except that it might modify errno (thus, the call is
+ /// *not* universally readonly). Or it might say that the side effects
+ /// are unknown other than to say that errno is not modified.
+ ///
+ struct LibCallFunctionInfo {
+ /// Name - This is the name of the libcall this describes.
+ const char *Name;
+
+ /// TODO: Constant folding function: Constant* vector -> Constant*.
+
+ /// UniversalBehavior - This captures the absolute mod/ref behavior without
+ /// any specific context knowledge. For example, if the function is known
+ /// to be readonly, this would be set to 'ref'. If known to be readnone,
+ /// this is set to NoModRef.
+ AliasAnalysis::ModRefResult UniversalBehavior;
+
+ /// LocationMRInfo - This pair captures info about whether a specific
+ /// location is modified or referenced by a libcall.
+ struct LocationMRInfo {
+ /// LocationID - ID # of the accessed location or ~0U for array end.
+ unsigned LocationID;
+ /// MRInfo - Mod/Ref info for this location.
+ AliasAnalysis::ModRefResult MRInfo;
+ };
+
+ /// DetailsType - Indicate the sense of the LocationDetails array. This
+ /// controls how the LocationDetails array is interpreted.
+ enum {
+ /// DoesOnly - If DetailsType is set to DoesOnly, then we know that the
+ /// *only* mod/ref behavior of this function is captured by the
+ /// LocationDetails array. If we are trying to say that 'sqrt' can only
+ /// modify errno, we'd have the {errnoloc,mod} in the LocationDetails
+ /// array and have DetailsType set to DoesOnly.
+ DoesOnly,
+
+ /// DoesNot - If DetailsType is set to DoesNot, then the sense of the
+ /// LocationDetails array is completely inverted. This means that we *do
+ /// not* know everything about the side effects of this libcall, but we do
+ /// know things that the libcall cannot do. This is useful for complex
+ /// functions like 'ctime' which have crazy mod/ref behavior, but are
+ /// known to never read or write errno. In this case, we'd have
+ /// {errnoloc,modref} in the LocationDetails array and DetailsType would
+ /// be set to DoesNot, indicating that ctime does not read or write the
+ /// errno location.
+ DoesNot
+ } DetailsType;
+
+ /// LocationDetails - This is a pointer to an array of LocationMRInfo
+ /// structs which indicates the behavior of the libcall w.r.t. specific
+ /// locations. For example, if this libcall is known to only modify
+ /// 'errno', it would have a LocationDetails array with the errno ID and
+ /// 'mod' in it. See the DetailsType field for how this is interpreted.
+ ///
+ /// In the "DoesOnly" case, this information is 'may' information for: there
+ /// is no guarantee that the specified side effect actually does happen,
+ /// just that it could. In the "DoesNot" case, this is 'must not' info.
+ ///
+ /// If this pointer is null, no details are known.
+ ///
+ const LocationMRInfo *LocationDetails;
+ };
+
+
+ /// LibCallInfo - Abstract interface to query about library call information.
+ /// Instances of this class return known information about some set of
+ /// libcalls.
+ ///
+ class LibCallInfo {
+ // Implementation details of this object, private.
+ mutable void *Impl;
+ mutable const LibCallLocationInfo *Locations;
+ mutable unsigned NumLocations;
+ public:
+ LibCallInfo() : Impl(0), Locations(0), NumLocations(0) {}
+ virtual ~LibCallInfo();
+
+ //===------------------------------------------------------------------===//
+ // Accessor Methods: Efficient access to contained data.
+ //===------------------------------------------------------------------===//
+
+ /// getLocationInfo - Return information about the specified LocationID.
+ const LibCallLocationInfo &getLocationInfo(unsigned LocID) const;
+
+
+ /// getFunctionInfo - Return the LibCallFunctionInfo object corresponding to
+ /// the specified function if we have it. If not, return null.
+ const LibCallFunctionInfo *getFunctionInfo(Function *F) const;
+
+
+ //===------------------------------------------------------------------===//
+ // Implementation Methods: Subclasses should implement these.
+ //===------------------------------------------------------------------===//
+
+ /// getLocationInfo - Return descriptors for the locations referenced by
+ /// this set of libcalls.
+ virtual unsigned getLocationInfo(const LibCallLocationInfo *&Array) const {
+ return 0;
+ }
+
+ /// getFunctionInfoArray - Return an array of descriptors that describe the
+ /// set of libcalls represented by this LibCallInfo object. This array is
+ /// terminated by an entry with a NULL name.
+ virtual const LibCallFunctionInfo *getFunctionInfoArray() const = 0;
+ };
+
+} // end namespace llvm
+
+#endif
diff --git a/lib/Analysis/LibCallSemantics.cpp b/lib/Analysis/LibCallSemantics.cpp
new file mode 100644
index 0000000000..29850471f7
--- /dev/null
+++ b/lib/Analysis/LibCallSemantics.cpp
@@ -0,0 +1,65 @@
+//===- LibCallSemantics.cpp - Describe library semantics ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements interfaces that can be used to describe language
+// specific runtime library interfaces (e.g. libc, libm, etc) to LLVM
+// optimizers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Analysis/LibCallSemantics.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Function.h"
+using namespace llvm;
+
+/// getMap - This impl pointer in ~LibCallInfo is actually a StringMap. This
+/// helper does the cast.
+static StringMap<const LibCallFunctionInfo*> *getMap(void *Ptr) {
+ return static_cast<StringMap<const LibCallFunctionInfo*> *>(Ptr);
+}
+
+LibCallInfo::~LibCallInfo() {
+ delete getMap(Impl);
+}
+
+const LibCallLocationInfo &LibCallInfo::getLocationInfo(unsigned LocID) const {
+ // Get location info on the first call.
+ if (NumLocations == 0)
+ NumLocations = getLocationInfo(Locations);
+
+ assert(LocID < NumLocations && "Invalid location ID!");
+ return Locations[LocID];
+}
+
+
+/// getFunctionInfo - Return the LibCallFunctionInfo object corresponding to
+/// the specified function if we have it. If not, return null.
+const LibCallFunctionInfo *LibCallInfo::getFunctionInfo(Function *F) const {
+ StringMap<const LibCallFunctionInfo*> *Map = getMap(Impl);
+
+ /// If this is the first time we are querying for this info, lazily construct
+ /// the StringMap to index it.
+ if (Map == 0) {
+ Impl = Map = new StringMap<const LibCallFunctionInfo*>();
+
+ const LibCallFunctionInfo *Array = getFunctionInfoArray();
+ if (Array == 0) return 0;
+
+ // We now have the array of entries. Populate the StringMap.
+ for (unsigned i = 0; Array[i].Name; ++i)
+ (*Map)[Array[i].Name] = Array+i;
+ }
+
+ // Look up this function in the string map.
+ const char *ValueName = F->getNameStart();
+ StringMap<const LibCallFunctionInfo*>::iterator I =
+ Map->find(ValueName, ValueName+F->getNameLen());
+ return I != Map->end() ? I->second : 0;
+}
+