summaryrefslogtreecommitdiff
path: root/polly/lib/External/isl/interface/generator.h
blob: 90eae8266a7300ca9368a75df10b84b074197ca7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
#ifndef ISL_INTERFACE_GENERATOR_H
#define ISL_INTERFACE_GENERATOR_H

#include <map>
#include <set>
#include <string>
#include <vector>

#include <clang/AST/Decl.h>

using namespace std;
using namespace clang;

/* Compare the prefix of "s" to "prefix" up to the length of "prefix".
 */
inline int prefixcmp(const char *s, const char *prefix)
{
	return strncmp(s, prefix, strlen(prefix));
}

/* Information about a single enum value of an enum set by a function.
 * "value" is the enum value.
 * "name" is the corresponding name.
 * "method_name" is the the name of the method that sets this value.
 */
struct set_enum {
	int	value;
	string	name;
	string	method_name;
	set_enum(int value, string name, string method_name) :
		value(value), name(name), method_name(method_name) {}
};

/* Helper structure for sorting FunctionDecl pointers
 * on the corresponding function names.
 */
struct function_name_less {
	bool operator()(FunctionDecl *x, FunctionDecl *y) const {
		return x->getName() < y->getName();
	}
};

/* Set of FunctionDecl pointers sorted on function name.
 */
typedef std::set<FunctionDecl *, function_name_less> function_set;

/* isl_class collects all constructors and methods for an isl "class".
 * "name" is the name of the class.
 * If this object describes a subclass of a C type, then
 * "subclass_name" is the name of that subclass and "superclass_name"
 * is the name of the immediate superclass of that subclass.  Otherwise,
 * "subclass_name" is equal to "name" and "superclass_name" is undefined.
 * "type" is the declaration that introduces the type.
 * "persistent_callbacks" contains the set of functions that
 * set a persistent callback.
 * "set_enums" maps the set of functions that set an enum value
 * to information associated to each value.
 * A function is considered to set an enum value if it returns
 * an object of the same type and if its last argument is of an enum type.
 * "methods" contains the set of methods, grouped by method name.
 * "fn_to_str" is a reference to the *_to_str method of this class, if any.
 * "fn_copy" is a reference to the *_copy method of this class, if any.
 * "fn_free" is a reference to the *_free method of this class, if any.
 * "fn_type" is a reference to a function that described subclasses, if any.
 * If "fn_type" is set, then "type_subclasses" maps the values returned
 * by that function to the names of the corresponding subclasses.
 *
 * The following fields are only used for the C++ bindings.
 * For methods that are not derived from a function that applies
 * directly to this class, but are rather copied from some ancestor,
 * "copied_from" records the direct superclass from which the method
 * was copied (where it may have been copied from a further ancestor) and
 * "copy_depth" records the distance to the ancestor to which
 * the function applies.
 * "construction_types" contains the set of isl classes that can be
 * implicitly converted to this class through a unary constructor,
 * mapped to the single argument
 * of this unary constructor.
 */
struct isl_class {
	string name;
	string superclass_name;
	string subclass_name;
	RecordDecl *type;
	function_set constructors;
	set<FunctionDecl *> persistent_callbacks;
	map<FunctionDecl *, vector<set_enum> > set_enums;
	map<string, function_set> methods;
	map<int, string> type_subclasses;
	FunctionDecl *fn_type;
	FunctionDecl *fn_to_str;
	FunctionDecl *fn_copy;
	FunctionDecl *fn_free;

	std::map<clang::FunctionDecl *, const isl_class &> copied_from;
	std::map<clang::FunctionDecl *, int> copy_depth;
	std::map<std::string, clang::ParmVarDecl *> construction_types;

	/* Is the first argument an instance of the class? */
	bool first_arg_matches_class(FunctionDecl *method) const;
	/* Does "method" correspond to a static method? */
	bool is_static(FunctionDecl *method) const;
	/* Is this class a subclass based on a type function? */
	bool is_type_subclass() const { return name != subclass_name; }
	/* Return name of "fd" without type suffixes, if any. */
	static string name_without_type_suffixes(FunctionDecl *fd);
	/* Extract the method name corresponding to "fd"
	 * (including "get" method prefix if any).
	 */
	string base_method_name(FunctionDecl *fd) const {
		string m_name = name_without_type_suffixes(fd);
		return m_name.substr(subclass_name.length() + 1);
	}
	/* The prefix of a "get" method. */
	static const char *get_prefix;
	/* Is function "fd" with the given name a "get" method? */
	bool is_get_method_name(FunctionDecl *fd, const string &name) const;
	/* Is function "fd" a "get" method? */
	bool is_get_method(FunctionDecl *fd) const {
		return is_get_method_name(fd, base_method_name(fd));
	}
	/* Extract the method name corresponding to "fd". */
	string method_name(FunctionDecl *fd) const;
	/* The prefix of any method that may set a (persistent) callback. */
	static const char *set_callback_prefix;
	/* Given a function that sets a persistent callback,
	 * return the name of the callback.
	 */
	string persistent_callback_name(FunctionDecl *fd) const {
		return method_name(fd).substr(strlen(set_callback_prefix));
	}
	/* Does this class have any functions that set a persistent callback?
	 */
	bool has_persistent_callbacks() const {
		return persistent_callbacks.size() != 0;
	}
};

/* Base class for interface generators.
 *
 * "conversions" maps the target type of automatic conversion
 * to the second input argument of the conversion function.
 */
class generator {
protected:
	SourceManager &SM;
	map<string,isl_class> classes;
	map<string, FunctionDecl *> functions_by_name;

public:
	generator(SourceManager &SM, set<RecordDecl *> &exported_types,
		set<FunctionDecl *> exported_functions,
		set<FunctionDecl *> functions);

	virtual void generate() = 0;
	virtual ~generator() {};

protected:
	void add_subclass(RecordDecl *decl, const string &name,
		const string &sub_name);
	void add_class(RecordDecl *decl);
	void add_type_subclasses(FunctionDecl *method);
	isl_class *method2class(FunctionDecl *fd);
	bool callback_takes_argument(ParmVarDecl *param, int pos);
	FunctionDecl *find_by_name(const string &name, bool required);
	std::map<const Type *, ParmVarDecl *> conversions;
private:
	static const std::set<std::string> automatic_conversion_functions;
	void extract_automatic_conversion(FunctionDecl *fd);
	void extract_class_automatic_conversions(const isl_class &clazz);
	void extract_automatic_conversions();
public:
	static std::string drop_suffix(const std::string &s,
		const std::string &suffix);
	static void die(const char *msg) __attribute__((noreturn));
	static void die(string msg) __attribute__((noreturn));
	static vector<string> find_superclasses(Decl *decl);
	static bool is_subclass(FunctionDecl *decl);
	static bool is_overload(Decl *decl);
	static bool is_constructor(Decl *decl);
	static bool takes(Decl *decl);
	static bool keeps(Decl *decl);
	static bool gives(Decl *decl);
	static bool is_isl_ctx(QualType type);
	static bool first_arg_is_isl_ctx(FunctionDecl *fd);
	static bool is_isl_type(QualType type);
	static bool is_isl_neg_error(QualType type);
	static bool is_isl_bool(QualType type);
	static bool is_isl_stat(QualType type);
	static bool is_isl_size(QualType type);
	static bool is_long(QualType type);
	static bool is_callback(QualType type);
	static bool is_callback_arg(FunctionDecl *fd, int i);
	static bool is_string(QualType type);
	static bool is_static(const isl_class &clazz, FunctionDecl *method);
	static bool is_mutator(const isl_class &clazz, FunctionDecl *fd);
	static string extract_type(QualType type);
	static const FunctionProtoType *extract_prototype(QualType type);
	static int prototype_n_args(QualType type);
	static ParmVarDecl *persistent_callback_arg(FunctionDecl *fd);
};

#endif /* ISL_INTERFACE_GENERATOR_H */