diff options
Diffstat (limited to 'polly/lib/External/isl/interface/generator.cc')
-rw-r--r-- | polly/lib/External/isl/interface/generator.cc | 109 |
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(); |