summaryrefslogtreecommitdiffstats
path: root/polly/lib/External/isl/interface/generator.cc
diff options
context:
space:
mode:
Diffstat (limited to 'polly/lib/External/isl/interface/generator.cc')
-rw-r--r--polly/lib/External/isl/interface/generator.cc109
1 files changed, 97 insertions, 12 deletions
diff --git a/polly/lib/External/isl/interface/generator.cc b/polly/lib/External/isl/interface/generator.cc
index 01704f881b1..c3572852d19 100644
--- a/polly/lib/External/isl/interface/generator.cc
+++ b/polly/lib/External/isl/interface/generator.cc
@@ -32,14 +32,23 @@
*/
#include <stdio.h>
+#include <string.h>
#include <iostream>
#include <clang/AST/Attr.h>
+#include <clang/Basic/SourceManager.h>
#include "isl_config.h"
#include "extract_interface.h"
#include "generator.h"
+/* Compare the prefix of "s" to "prefix" up to the length of "prefix".
+ */
+static int prefixcmp(const char *s, const char *prefix)
+{
+ return strncmp(s, prefix, strlen(prefix));
+}
+
/* Should "method" be considered to be a static method?
* That is, is the first argument something other than
* an instance of the class?
@@ -76,8 +85,9 @@ FunctionDecl *generator::find_by_name(const string &name, bool required)
* functions, then they are grouped based on their name after removing the
* argument type suffix.
*/
-generator::generator(set<RecordDecl *> &exported_types,
- set<FunctionDecl *> exported_functions, set<FunctionDecl *> functions)
+generator::generator(SourceManager &SM, set<RecordDecl *> &exported_types,
+ set<FunctionDecl *> exported_functions, set<FunctionDecl *> functions) :
+ SM(SM)
{
map<string, isl_class>::iterator ci;
@@ -107,8 +117,7 @@ generator::generator(set<RecordDecl *> &exported_types,
c->constructors.insert(*in);
} else {
FunctionDecl *method = *in;
- string fullname = method->getName();
- fullname = drop_type_suffix(fullname, method);
+ string fullname = c->name_without_type_suffix(method);
c->methods[fullname].insert(method);
}
}
@@ -243,6 +252,82 @@ bool generator::first_arg_is_isl_ctx(FunctionDecl *fd)
return is_isl_ctx(param->getOriginalType());
}
+namespace {
+
+struct ClangAPI {
+ /* Return the first location in the range returned by
+ * clang::SourceManager::getImmediateExpansionRange.
+ * Older versions of clang return a pair of SourceLocation objects.
+ * More recent versions return a CharSourceRange.
+ */
+ static SourceLocation range_begin(
+ const std::pair<SourceLocation,SourceLocation> &p) {
+ return p.first;
+ }
+ static SourceLocation range_begin(const CharSourceRange &range) {
+ return range.getBegin();
+ }
+};
+
+}
+
+/* Does the callback argument "param" take its argument at position "pos"?
+ *
+ * The memory management annotations of arguments to function pointers
+ * are not recorded by clang, so the information cannot be extracted
+ * from the type of "param".
+ * Instead, go to the location in the source where the callback argument
+ * is declared, look for the right argument of the callback itself and
+ * then check if it has an "__isl_take" memory management annotation.
+ *
+ * If the return value of the function has a memory management annotation,
+ * then the spelling of "param" will point to the spelling
+ * of this memory management annotation. Since the macro is defined
+ * on the command line (in main), this location does not have a file entry.
+ * In this case, move up one level in the macro expansion to the location
+ * where the memory management annotation is used.
+ */
+bool generator::callback_takes_argument(ParmVarDecl *param,
+ int pos)
+{
+ SourceLocation loc;
+ const char *s, *end, *next;
+ bool takes, keeps;
+
+ loc = param->getSourceRange().getBegin();
+ if (!SM.getFileEntryForID(SM.getFileID(SM.getSpellingLoc(loc))))
+ loc = ClangAPI::range_begin(SM.getImmediateExpansionRange(loc));
+ s = SM.getCharacterData(loc);
+ if (!s)
+ die("No character data");
+ s = strchr(s, '(');
+ if (!s)
+ die("Cannot find function pointer");
+ s = strchr(s + 1, '(');
+ if (!s)
+ die("Cannot find function pointer arguments");
+ end = strchr(s + 1, ')');
+ if (!end)
+ die("Cannot find end of function pointer arguments");
+ while (pos-- > 0) {
+ s = strchr(s + 1, ',');
+ if (!s || s > end)
+ die("Cannot find function pointer argument");
+ }
+ next = strchr(s + 1, ',');
+ if (next && next < end)
+ end = next;
+ s = strchr(s + 1, '_');
+ if (!s || s > end)
+ die("Cannot find function pointer argument annotation");
+ takes = prefixcmp(s, "__isl_take") == 0;
+ keeps = prefixcmp(s, "__isl_keep") == 0;
+ if (!takes && !keeps)
+ die("Cannot find function pointer argument annotation");
+
+ return takes;
+}
+
/* Is "type" that of a pointer to an isl_* structure?
*/
bool generator::is_isl_type(QualType type)
@@ -327,24 +412,24 @@ string generator::extract_type(QualType type)
die("Cannot extract type from non-pointer type");
}
-/* If "method" is overloaded, then drop the suffix of "name"
- * corresponding to the type of the final argument and
- * return the modified name (or the original name if
- * no modifications were made).
+/* If "method" is overloaded, then return its name with the suffix
+ * corresponding to the type of the final argument removed.
+ * Otherwise, simply return the name of the function.
*/
-string generator::drop_type_suffix(string name, FunctionDecl *method)
+string isl_class::name_without_type_suffix(FunctionDecl *method)
{
int num_params;
ParmVarDecl *param;
- string type;
+ string name, type;
size_t name_len, type_len;
- if (!is_overload(method))
+ name = method->getName();
+ if (!generator::is_overload(method))
return name;
num_params = method->getNumParams();
param = method->getParamDecl(num_params - 1);
- type = extract_type(param->getOriginalType());
+ type = generator::extract_type(param->getOriginalType());
type = type.substr(4);
name_len = name.length();
type_len = type.length();
OpenPOWER on IntegriCloud