Polly 23.0.0git
extract_interface.cc
Go to the documentation of this file.
1/*
2 * Copyright 2011 Sven Verdoolaege. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following
13 * disclaimer in the documentation and/or other materials provided
14 * with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY SVEN VERDOOLAEGE ''AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SVEN VERDOOLAEGE OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
23 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * The views and conclusions contained in the software and documentation
29 * are those of the authors and should not be interpreted as
30 * representing official policies, either expressed or implied, of
31 * Sven Verdoolaege.
32 */
33
34#include "isl_config.h"
35#undef PACKAGE
36
37#include <assert.h>
38#include <iostream>
39#include <stdlib.h>
40#include <type_traits>
41#include <memory>
42#include <llvm/Support/raw_ostream.h>
43#include <llvm/Support/CommandLine.h>
44#include <llvm/Support/ManagedStatic.h>
45#include <clang/AST/ASTConsumer.h>
46#include <clang/Basic/DiagnosticOptions.h>
47#include <clang/Basic/FileSystemOptions.h>
48#include <clang/Frontend/CompilerInstance.h>
49#include <clang/Frontend/TextDiagnosticPrinter.h>
50#include <clang/Frontend/Utils.h>
51#include <clang/Lex/HeaderSearch.h>
52#include <clang/Lex/PreprocessorOptions.h>
53#include <clang/Lex/Preprocessor.h>
54#include <clang/Parse/ParseAST.h>
55#include <clang/Sema/Sema.h>
56
58
59#include "extract_interface.h"
60#include "generator.h"
61#include "python.h"
62#include "plain_cpp.h"
63#include "cpp_conversion.h"
64#include "template_cpp.h"
65
66using namespace std;
67using namespace clang;
68using namespace clang::driver;
69#ifdef HAVE_LLVM_OPTION_ARG_H
70using namespace llvm::opt;
71#endif
72
73static llvm::cl::opt<string> InputFilename(llvm::cl::Positional,
74 llvm::cl::Required, llvm::cl::desc("<input file>"));
75static llvm::cl::list<string> Includes("I",
76 llvm::cl::desc("Header search path"),
77 llvm::cl::value_desc("path"), llvm::cl::Prefix);
78
79static llvm::cl::opt<string> OutputLanguage(llvm::cl::Required,
80 llvm::cl::ValueRequired, "language",
81 llvm::cl::desc("Bindings to generate"),
82 llvm::cl::value_desc("name"));
83
84/* Does decl have an attribute of the following form?
85 *
86 * __attribute__((annotate("name")))
87 */
88bool has_annotation(Decl *decl, const char *name)
89{
90 if (!decl->hasAttrs())
91 return false;
92
93 AttrVec attrs = decl->getAttrs();
94 for (AttrVec::const_iterator i = attrs.begin() ; i != attrs.end(); ++i) {
95 const AnnotateAttr *ann = dyn_cast<AnnotateAttr>(*i);
96 if (!ann)
97 continue;
98 if (ann->getAnnotation().str() == name)
99 return true;
100 }
101
102 return false;
103}
104
105/* Is decl marked as exported?
106 */
107static bool is_exported(Decl *decl)
108{
109 return has_annotation(decl, "isl_export");
110}
111
112/* Collect all types and functions that are annotated "isl_export"
113 * in "exported_types" and "exported_function". Collect all function
114 * declarations in "functions".
115 *
116 * We currently only consider single declarations.
117 */
118struct MyASTConsumer : public ASTConsumer {
122
123 virtual HandleTopLevelDeclReturn HandleTopLevelDecl(DeclGroupRef D) {
124 Decl *decl;
125
126 if (!D.isSingleDecl())
127 return HandleTopLevelDeclContinue;
128 decl = D.getSingleDecl();
129 if (isa<FunctionDecl>(decl))
130 functions.insert(cast<FunctionDecl>(decl));
131 if (!is_exported(decl))
132 return HandleTopLevelDeclContinue;
133 switch (decl->getKind()) {
134 case Decl::Record:
135 exported_types.insert(cast<RecordDecl>(decl));
136 break;
137 case Decl::Function:
138 exported_functions.insert(cast<FunctionDecl>(decl));
139 break;
140 default:
141 break;
142 }
143 return HandleTopLevelDeclContinue;
144 }
145};
146
147/* A class specializing the Wrap helper class for
148 * extracting the isl interface.
149 */
151 virtual TextDiagnosticPrinter *construct_printer() override;
152 virtual void suppress_errors(DiagnosticsEngine &Diags) override;
153 virtual void add_paths(HeaderSearchOptions &HSO) override;
154 virtual void add_macros(PreprocessorOptions &PO) override;
155 virtual void handle_error() override;
156 virtual bool handle(CompilerInstance *Clang) override;
157};
158
159/* Construct a TextDiagnosticPrinter.
160 */
161TextDiagnosticPrinter *Extractor::construct_printer(void)
162{
163 return new TextDiagnosticPrinter(llvm::errs(), getDiagnosticOptions());
164}
165
166/* Suppress any errors, if needed.
167 */
168void Extractor::suppress_errors(DiagnosticsEngine &Diags)
169{
170}
171
172/* Add required search paths to "HSO".
173 */
174void Extractor::add_paths(HeaderSearchOptions &HSO)
175{
176 for (llvm::cl::list<string>::size_type i = 0; i < Includes.size(); ++i)
178}
179
180/* Add required macro definitions to "PO".
181 */
182void Extractor::add_macros(PreprocessorOptions &PO)
183{
184 PO.addMacroDef("__isl_give=__attribute__((annotate(\"isl_give\")))");
185 PO.addMacroDef("__isl_keep=__attribute__((annotate(\"isl_keep\")))");
186 PO.addMacroDef("__isl_take=__attribute__((annotate(\"isl_take\")))");
187 PO.addMacroDef("__isl_export=__attribute__((annotate(\"isl_export\")))");
188 PO.addMacroDef("__isl_overload="
189 "__attribute__((annotate(\"isl_overload\"))) "
190 "__attribute__((annotate(\"isl_export\")))");
191 PO.addMacroDef("__isl_constructor=__attribute__((annotate(\"isl_constructor\"))) __attribute__((annotate(\"isl_export\")))");
192 PO.addMacroDef("__isl_subclass(super)=__attribute__((annotate(\"isl_subclass(\" #super \")\"))) __attribute__((annotate(\"isl_export\")))");
193}
194
195/* Handle an error opening the file.
196 */
198{
199 assert(false);
200}
201
202/* Create an interface generator for the selected language and
203 * then use it to generate the interface.
204 */
205static void generate(MyASTConsumer &consumer, SourceManager &SM)
206{
207 generator *gen;
208
209 if (OutputLanguage.compare("python") == 0) {
210 gen = new python_generator(SM, consumer.exported_types,
211 consumer.exported_functions, consumer.functions);
212 } else if (OutputLanguage.compare("cpp") == 0) {
213 gen = new plain_cpp_generator(SM, consumer.exported_types,
214 consumer.exported_functions, consumer.functions);
215 } else if (OutputLanguage.compare("cpp-checked") == 0) {
216 gen = new plain_cpp_generator(SM, consumer.exported_types,
217 consumer.exported_functions, consumer.functions, true);
218 } else if (OutputLanguage.compare("cpp-checked-conversion") == 0) {
219 gen = new cpp_conversion_generator(SM, consumer.exported_types,
220 consumer.exported_functions, consumer.functions);
221 } else if (OutputLanguage.compare("template-cpp") == 0) {
222 gen = new template_cpp_generator(SM, consumer.exported_types,
223 consumer.exported_functions, consumer.functions);
224 } else {
225 cerr << "Language '" << OutputLanguage
226 << "' not recognized." << endl
227 << "Not generating bindings." << endl;
228 exit(EXIT_FAILURE);
229 }
230
231 gen->generate();
232}
233
234/* Parse the current source file, returning true if no error was encountered.
235 */
236bool Extractor::handle(CompilerInstance *Clang)
237{
238 Preprocessor &PP = Clang->getPreprocessor();
239 MyASTConsumer consumer;
240 Sema *sema = new Sema(PP, Clang->getASTContext(), consumer);
241
242 DiagnosticsEngine &Diags = Clang->getDiagnostics();
243 Diags.getClient()->BeginSourceFile(Clang->getLangOpts(), &PP);
244 ParseAST(*sema);
245 Diags.getClient()->EndSourceFile();
246
247 generate(consumer, Clang->getSourceManager());
248
249 delete sema;
250
251 return !Diags.hasErrorOccurred();
252}
253
254int main(int argc, char *argv[])
255{
256 llvm::cl::ParseCommandLineOptions(argc, argv);
257
258 Extractor extractor;
259 bool ok = extractor.invoke(InputFilename.c_str());
260
261 llvm::llvm_shutdown();
262
263 if (!ok)
264 return EXIT_FAILURE;
265 return EXIT_SUCCESS;
266}
virtual void generate()=0
bool has_annotation(Decl *decl, const char *name)
static bool is_exported(Decl *decl)
static void generate(MyASTConsumer &consumer, SourceManager &SM)
static llvm::cl::list< string > Includes("I", llvm::cl::desc("Header search path"), llvm::cl::value_desc("path"), llvm::cl::Prefix)
static llvm::cl::opt< string > InputFilename(llvm::cl::Positional, llvm::cl::Required, llvm::cl::desc("<input file>"))
static llvm::cl::opt< string > OutputLanguage(llvm::cl::Required, llvm::cl::ValueRequired, "language", llvm::cl::desc("Bindings to generate"), llvm::cl::value_desc("name"))
const char * set
Definition isl_test.c:1364
const char * name
Definition isl_test.c:10692
#define assert(exp)
static void add_path(HeaderSearchOptions &HSO, std::string Path)
Definition clang_wrap.h:181
virtual void handle_error() override
virtual void add_paths(HeaderSearchOptions &HSO) override
virtual void suppress_errors(DiagnosticsEngine &Diags) override
virtual TextDiagnosticPrinter * construct_printer() override
virtual void add_macros(PreprocessorOptions &PO) override
virtual bool handle(CompilerInstance *Clang) override
set< FunctionDecl * > functions
set< RecordDecl * > exported_types
set< FunctionDecl * > exported_functions
virtual HandleTopLevelDeclReturn HandleTopLevelDecl(DeclGroupRef D)
DiagOptsType getDiagnosticOptions()
Definition clang_wrap.h:360
bool invoke(const char *filename)
Definition clang_wrap.h:380