xref: /netbsd-src/external/mit/isl/dist/interface/extract_interface.cc (revision 5971e316fdea024efff6be8f03536623db06833e)
1*5971e316Smrg /*
2*5971e316Smrg  * Copyright 2011 Sven Verdoolaege. All rights reserved.
3*5971e316Smrg  *
4*5971e316Smrg  * Redistribution and use in source and binary forms, with or without
5*5971e316Smrg  * modification, are permitted provided that the following conditions
6*5971e316Smrg  * are met:
7*5971e316Smrg  *
8*5971e316Smrg  *    1. Redistributions of source code must retain the above copyright
9*5971e316Smrg  *       notice, this list of conditions and the following disclaimer.
10*5971e316Smrg  *
11*5971e316Smrg  *    2. Redistributions in binary form must reproduce the above
12*5971e316Smrg  *       copyright notice, this list of conditions and the following
13*5971e316Smrg  *       disclaimer in the documentation and/or other materials provided
14*5971e316Smrg  *       with the distribution.
15*5971e316Smrg  *
16*5971e316Smrg  * THIS SOFTWARE IS PROVIDED BY SVEN VERDOOLAEGE ''AS IS'' AND ANY
17*5971e316Smrg  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*5971e316Smrg  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19*5971e316Smrg  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SVEN VERDOOLAEGE OR
20*5971e316Smrg  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21*5971e316Smrg  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22*5971e316Smrg  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
23*5971e316Smrg  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24*5971e316Smrg  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25*5971e316Smrg  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26*5971e316Smrg  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27*5971e316Smrg  *
28*5971e316Smrg  * The views and conclusions contained in the software and documentation
29*5971e316Smrg  * are those of the authors and should not be interpreted as
30*5971e316Smrg  * representing official policies, either expressed or implied, of
31*5971e316Smrg  * Sven Verdoolaege.
32*5971e316Smrg  */
33*5971e316Smrg 
34*5971e316Smrg #include "isl_config.h"
35*5971e316Smrg #undef PACKAGE
36*5971e316Smrg 
37*5971e316Smrg #include <assert.h>
38*5971e316Smrg #include <iostream>
39*5971e316Smrg #include <stdlib.h>
40*5971e316Smrg #ifdef HAVE_ADT_OWNINGPTR_H
41*5971e316Smrg #include <llvm/ADT/OwningPtr.h>
42*5971e316Smrg #else
43*5971e316Smrg #include <memory>
44*5971e316Smrg #endif
45*5971e316Smrg #ifdef HAVE_LLVM_OPTION_ARG_H
46*5971e316Smrg #include <llvm/Option/Arg.h>
47*5971e316Smrg #endif
48*5971e316Smrg #include <llvm/Support/raw_ostream.h>
49*5971e316Smrg #include <llvm/Support/CommandLine.h>
50*5971e316Smrg #ifdef HAVE_TARGETPARSER_HOST_H
51*5971e316Smrg #include <llvm/TargetParser/Host.h>
52*5971e316Smrg #else
53*5971e316Smrg #include <llvm/Support/Host.h>
54*5971e316Smrg #endif
55*5971e316Smrg #include <llvm/Support/ManagedStatic.h>
56*5971e316Smrg #include <clang/AST/ASTContext.h>
57*5971e316Smrg #include <clang/AST/ASTConsumer.h>
58*5971e316Smrg #include <clang/Basic/Builtins.h>
59*5971e316Smrg #include <clang/Basic/FileSystemOptions.h>
60*5971e316Smrg #include <clang/Basic/FileManager.h>
61*5971e316Smrg #include <clang/Basic/TargetOptions.h>
62*5971e316Smrg #include <clang/Basic/TargetInfo.h>
63*5971e316Smrg #include <clang/Basic/Version.h>
64*5971e316Smrg #include <clang/Driver/Compilation.h>
65*5971e316Smrg #include <clang/Driver/Driver.h>
66*5971e316Smrg #include <clang/Driver/Tool.h>
67*5971e316Smrg #include <clang/Frontend/CompilerInstance.h>
68*5971e316Smrg #include <clang/Frontend/CompilerInvocation.h>
69*5971e316Smrg #ifdef HAVE_BASIC_DIAGNOSTICOPTIONS_H
70*5971e316Smrg #include <clang/Basic/DiagnosticOptions.h>
71*5971e316Smrg #else
72*5971e316Smrg #include <clang/Frontend/DiagnosticOptions.h>
73*5971e316Smrg #endif
74*5971e316Smrg #include <clang/Frontend/TextDiagnosticPrinter.h>
75*5971e316Smrg #include <clang/Frontend/Utils.h>
76*5971e316Smrg #include <clang/Lex/HeaderSearch.h>
77*5971e316Smrg #ifdef HAVE_LEX_PREPROCESSOROPTIONS_H
78*5971e316Smrg #include <clang/Lex/PreprocessorOptions.h>
79*5971e316Smrg #else
80*5971e316Smrg #include <clang/Frontend/PreprocessorOptions.h>
81*5971e316Smrg #endif
82*5971e316Smrg #include <clang/Lex/Preprocessor.h>
83*5971e316Smrg #include <clang/Parse/ParseAST.h>
84*5971e316Smrg #include <clang/Sema/Sema.h>
85*5971e316Smrg 
86*5971e316Smrg #include "extract_interface.h"
87*5971e316Smrg #include "generator.h"
88*5971e316Smrg #include "python.h"
89*5971e316Smrg #include "plain_cpp.h"
90*5971e316Smrg #include "cpp_conversion.h"
91*5971e316Smrg #include "template_cpp.h"
92*5971e316Smrg 
93*5971e316Smrg using namespace std;
94*5971e316Smrg using namespace clang;
95*5971e316Smrg using namespace clang::driver;
96*5971e316Smrg #ifdef HAVE_LLVM_OPTION_ARG_H
97*5971e316Smrg using namespace llvm::opt;
98*5971e316Smrg #endif
99*5971e316Smrg 
100*5971e316Smrg #ifdef HAVE_ADT_OWNINGPTR_H
101*5971e316Smrg #define unique_ptr	llvm::OwningPtr
102*5971e316Smrg #endif
103*5971e316Smrg 
104*5971e316Smrg static llvm::cl::opt<string> InputFilename(llvm::cl::Positional,
105*5971e316Smrg 			llvm::cl::Required, llvm::cl::desc("<input file>"));
106*5971e316Smrg static llvm::cl::list<string> Includes("I",
107*5971e316Smrg 			llvm::cl::desc("Header search path"),
108*5971e316Smrg 			llvm::cl::value_desc("path"), llvm::cl::Prefix);
109*5971e316Smrg 
110*5971e316Smrg static llvm::cl::opt<string> OutputLanguage(llvm::cl::Required,
111*5971e316Smrg 	llvm::cl::ValueRequired, "language",
112*5971e316Smrg 	llvm::cl::desc("Bindings to generate"),
113*5971e316Smrg 	llvm::cl::value_desc("name"));
114*5971e316Smrg 
115*5971e316Smrg static const char *ResourceDir =
116*5971e316Smrg 	CLANG_PREFIX "/lib/clang/" CLANG_VERSION_STRING;
117*5971e316Smrg 
118*5971e316Smrg /* Does decl have an attribute of the following form?
119*5971e316Smrg  *
120*5971e316Smrg  *	__attribute__((annotate("name")))
121*5971e316Smrg  */
has_annotation(Decl * decl,const char * name)122*5971e316Smrg bool has_annotation(Decl *decl, const char *name)
123*5971e316Smrg {
124*5971e316Smrg 	if (!decl->hasAttrs())
125*5971e316Smrg 		return false;
126*5971e316Smrg 
127*5971e316Smrg 	AttrVec attrs = decl->getAttrs();
128*5971e316Smrg 	for (AttrVec::const_iterator i = attrs.begin() ; i != attrs.end(); ++i) {
129*5971e316Smrg 		const AnnotateAttr *ann = dyn_cast<AnnotateAttr>(*i);
130*5971e316Smrg 		if (!ann)
131*5971e316Smrg 			continue;
132*5971e316Smrg 		if (ann->getAnnotation().str() == name)
133*5971e316Smrg 			return true;
134*5971e316Smrg 	}
135*5971e316Smrg 
136*5971e316Smrg 	return false;
137*5971e316Smrg }
138*5971e316Smrg 
139*5971e316Smrg /* Is decl marked as exported?
140*5971e316Smrg  */
is_exported(Decl * decl)141*5971e316Smrg static bool is_exported(Decl *decl)
142*5971e316Smrg {
143*5971e316Smrg 	return has_annotation(decl, "isl_export");
144*5971e316Smrg }
145*5971e316Smrg 
146*5971e316Smrg /* Collect all types and functions that are annotated "isl_export"
147*5971e316Smrg  * in "exported_types" and "exported_function".  Collect all function
148*5971e316Smrg  * declarations in "functions".
149*5971e316Smrg  *
150*5971e316Smrg  * We currently only consider single declarations.
151*5971e316Smrg  */
152*5971e316Smrg struct MyASTConsumer : public ASTConsumer {
153*5971e316Smrg 	set<RecordDecl *> exported_types;
154*5971e316Smrg 	set<FunctionDecl *> exported_functions;
155*5971e316Smrg 	set<FunctionDecl *> functions;
156*5971e316Smrg 
HandleTopLevelDeclMyASTConsumer157*5971e316Smrg 	virtual HandleTopLevelDeclReturn HandleTopLevelDecl(DeclGroupRef D) {
158*5971e316Smrg 		Decl *decl;
159*5971e316Smrg 
160*5971e316Smrg 		if (!D.isSingleDecl())
161*5971e316Smrg 			return HandleTopLevelDeclContinue;
162*5971e316Smrg 		decl = D.getSingleDecl();
163*5971e316Smrg 		if (isa<FunctionDecl>(decl))
164*5971e316Smrg 			functions.insert(cast<FunctionDecl>(decl));
165*5971e316Smrg 		if (!is_exported(decl))
166*5971e316Smrg 			return HandleTopLevelDeclContinue;
167*5971e316Smrg 		switch (decl->getKind()) {
168*5971e316Smrg 		case Decl::Record:
169*5971e316Smrg 			exported_types.insert(cast<RecordDecl>(decl));
170*5971e316Smrg 			break;
171*5971e316Smrg 		case Decl::Function:
172*5971e316Smrg 			exported_functions.insert(cast<FunctionDecl>(decl));
173*5971e316Smrg 			break;
174*5971e316Smrg 		default:
175*5971e316Smrg 			break;
176*5971e316Smrg 		}
177*5971e316Smrg 		return HandleTopLevelDeclContinue;
178*5971e316Smrg 	}
179*5971e316Smrg };
180*5971e316Smrg 
181*5971e316Smrg #ifdef USE_ARRAYREF
182*5971e316Smrg 
183*5971e316Smrg #ifdef HAVE_CXXISPRODUCTION
construct_driver(const char * binary,DiagnosticsEngine & Diags)184*5971e316Smrg static Driver *construct_driver(const char *binary, DiagnosticsEngine &Diags)
185*5971e316Smrg {
186*5971e316Smrg 	return new Driver(binary, llvm::sys::getDefaultTargetTriple(),
187*5971e316Smrg 			    "", false, false, Diags);
188*5971e316Smrg }
189*5971e316Smrg #elif defined(HAVE_ISPRODUCTION)
construct_driver(const char * binary,DiagnosticsEngine & Diags)190*5971e316Smrg static Driver *construct_driver(const char *binary, DiagnosticsEngine &Diags)
191*5971e316Smrg {
192*5971e316Smrg 	return new Driver(binary, llvm::sys::getDefaultTargetTriple(),
193*5971e316Smrg 			    "", false, Diags);
194*5971e316Smrg }
195*5971e316Smrg #elif defined(DRIVER_CTOR_TAKES_DEFAULTIMAGENAME)
construct_driver(const char * binary,DiagnosticsEngine & Diags)196*5971e316Smrg static Driver *construct_driver(const char *binary, DiagnosticsEngine &Diags)
197*5971e316Smrg {
198*5971e316Smrg 	return new Driver(binary, llvm::sys::getDefaultTargetTriple(),
199*5971e316Smrg 			    "", Diags);
200*5971e316Smrg }
201*5971e316Smrg #else
construct_driver(const char * binary,DiagnosticsEngine & Diags)202*5971e316Smrg static Driver *construct_driver(const char *binary, DiagnosticsEngine &Diags)
203*5971e316Smrg {
204*5971e316Smrg 	return new Driver(binary, llvm::sys::getDefaultTargetTriple(), Diags);
205*5971e316Smrg }
206*5971e316Smrg #endif
207*5971e316Smrg 
208*5971e316Smrg namespace clang { namespace driver { class Job; } }
209*5971e316Smrg 
210*5971e316Smrg /* Clang changed its API from 3.5 to 3.6 and once more in 3.7.
211*5971e316Smrg  * We fix this with a simple overloaded function here.
212*5971e316Smrg  */
213*5971e316Smrg struct ClangAPI {
commandClangAPI214*5971e316Smrg 	static Job *command(Job *J) { return J; }
commandClangAPI215*5971e316Smrg 	static Job *command(Job &J) { return &J; }
commandClangAPI216*5971e316Smrg 	static Command *command(Command &C) { return &C; }
217*5971e316Smrg };
218*5971e316Smrg 
219*5971e316Smrg #ifdef CREATE_FROM_ARGS_TAKES_ARRAYREF
220*5971e316Smrg 
221*5971e316Smrg /* Call CompilerInvocation::CreateFromArgs with the right arguments.
222*5971e316Smrg  * In this case, an ArrayRef<const char *>.
223*5971e316Smrg  */
create_from_args(CompilerInvocation & invocation,const ArgStringList * args,DiagnosticsEngine & Diags)224*5971e316Smrg static void create_from_args(CompilerInvocation &invocation,
225*5971e316Smrg 	const ArgStringList *args, DiagnosticsEngine &Diags)
226*5971e316Smrg {
227*5971e316Smrg 	CompilerInvocation::CreateFromArgs(invocation, *args, Diags);
228*5971e316Smrg }
229*5971e316Smrg 
230*5971e316Smrg #else
231*5971e316Smrg 
232*5971e316Smrg /* Call CompilerInvocation::CreateFromArgs with the right arguments.
233*5971e316Smrg  * In this case, two "const char *" pointers.
234*5971e316Smrg  */
create_from_args(CompilerInvocation & invocation,const ArgStringList * args,DiagnosticsEngine & Diags)235*5971e316Smrg static void create_from_args(CompilerInvocation &invocation,
236*5971e316Smrg 	const ArgStringList *args, DiagnosticsEngine &Diags)
237*5971e316Smrg {
238*5971e316Smrg 	CompilerInvocation::CreateFromArgs(invocation, args->data() + 1,
239*5971e316Smrg 						args->data() + args->size(),
240*5971e316Smrg 						Diags);
241*5971e316Smrg }
242*5971e316Smrg 
243*5971e316Smrg #endif
244*5971e316Smrg 
245*5971e316Smrg #ifdef CLANG_SYSROOT
246*5971e316Smrg /* Set sysroot if required.
247*5971e316Smrg  *
248*5971e316Smrg  * If CLANG_SYSROOT is defined, then set it to this value.
249*5971e316Smrg  */
set_sysroot(ArgStringList & args)250*5971e316Smrg static void set_sysroot(ArgStringList &args)
251*5971e316Smrg {
252*5971e316Smrg 	args.push_back("-isysroot");
253*5971e316Smrg 	args.push_back(CLANG_SYSROOT);
254*5971e316Smrg }
255*5971e316Smrg #else
256*5971e316Smrg /* Set sysroot if required.
257*5971e316Smrg  *
258*5971e316Smrg  * If CLANG_SYSROOT is not defined, then it does not need to be set.
259*5971e316Smrg  */
set_sysroot(ArgStringList & args)260*5971e316Smrg static void set_sysroot(ArgStringList &args)
261*5971e316Smrg {
262*5971e316Smrg }
263*5971e316Smrg #endif
264*5971e316Smrg 
265*5971e316Smrg /* Create a CompilerInvocation object that stores the command line
266*5971e316Smrg  * arguments constructed by the driver.
267*5971e316Smrg  * The arguments are mainly useful for setting up the system include
268*5971e316Smrg  * paths on newer clangs and on some platforms.
269*5971e316Smrg  */
construct_invocation(const char * filename,DiagnosticsEngine & Diags)270*5971e316Smrg static CompilerInvocation *construct_invocation(const char *filename,
271*5971e316Smrg 	DiagnosticsEngine &Diags)
272*5971e316Smrg {
273*5971e316Smrg 	const char *binary = CLANG_PREFIX"/bin/clang";
274*5971e316Smrg 	const unique_ptr<Driver> driver(construct_driver(binary, Diags));
275*5971e316Smrg 	std::vector<const char *> Argv;
276*5971e316Smrg 	Argv.push_back(binary);
277*5971e316Smrg 	Argv.push_back(filename);
278*5971e316Smrg 	const unique_ptr<Compilation> compilation(
279*5971e316Smrg 		driver->BuildCompilation(llvm::ArrayRef<const char *>(Argv)));
280*5971e316Smrg 	JobList &Jobs = compilation->getJobs();
281*5971e316Smrg 
282*5971e316Smrg 	Command *cmd = cast<Command>(ClangAPI::command(*Jobs.begin()));
283*5971e316Smrg 	if (strcmp(cmd->getCreator().getName(), "clang"))
284*5971e316Smrg 		return NULL;
285*5971e316Smrg 
286*5971e316Smrg 	ArgStringList args = cmd->getArguments();
287*5971e316Smrg 	set_sysroot(args);
288*5971e316Smrg 
289*5971e316Smrg 	CompilerInvocation *invocation = new CompilerInvocation;
290*5971e316Smrg 	create_from_args(*invocation, &args, Diags);
291*5971e316Smrg 	return invocation;
292*5971e316Smrg }
293*5971e316Smrg 
294*5971e316Smrg #else
295*5971e316Smrg 
construct_invocation(const char * filename,DiagnosticsEngine & Diags)296*5971e316Smrg static CompilerInvocation *construct_invocation(const char *filename,
297*5971e316Smrg 	DiagnosticsEngine &Diags)
298*5971e316Smrg {
299*5971e316Smrg 	return NULL;
300*5971e316Smrg }
301*5971e316Smrg 
302*5971e316Smrg #endif
303*5971e316Smrg 
304*5971e316Smrg #ifdef HAVE_BASIC_DIAGNOSTICOPTIONS_H
305*5971e316Smrg 
construct_printer(void)306*5971e316Smrg static TextDiagnosticPrinter *construct_printer(void)
307*5971e316Smrg {
308*5971e316Smrg 	return new TextDiagnosticPrinter(llvm::errs(), new DiagnosticOptions());
309*5971e316Smrg }
310*5971e316Smrg 
311*5971e316Smrg #else
312*5971e316Smrg 
construct_printer(void)313*5971e316Smrg static TextDiagnosticPrinter *construct_printer(void)
314*5971e316Smrg {
315*5971e316Smrg 	DiagnosticOptions DO;
316*5971e316Smrg 	return new TextDiagnosticPrinter(llvm::errs(), DO);
317*5971e316Smrg }
318*5971e316Smrg 
319*5971e316Smrg #endif
320*5971e316Smrg 
321*5971e316Smrg #ifdef CREATETARGETINFO_TAKES_SHARED_PTR
322*5971e316Smrg 
create_target_info(CompilerInstance * Clang,DiagnosticsEngine & Diags)323*5971e316Smrg static TargetInfo *create_target_info(CompilerInstance *Clang,
324*5971e316Smrg 	DiagnosticsEngine &Diags)
325*5971e316Smrg {
326*5971e316Smrg 	shared_ptr<TargetOptions> TO = Clang->getInvocation().TargetOpts;
327*5971e316Smrg 	TO->Triple = llvm::sys::getDefaultTargetTriple();
328*5971e316Smrg 	return TargetInfo::CreateTargetInfo(Diags, TO);
329*5971e316Smrg }
330*5971e316Smrg 
331*5971e316Smrg #elif defined(CREATETARGETINFO_TAKES_POINTER)
332*5971e316Smrg 
create_target_info(CompilerInstance * Clang,DiagnosticsEngine & Diags)333*5971e316Smrg static TargetInfo *create_target_info(CompilerInstance *Clang,
334*5971e316Smrg 	DiagnosticsEngine &Diags)
335*5971e316Smrg {
336*5971e316Smrg 	TargetOptions &TO = Clang->getTargetOpts();
337*5971e316Smrg 	TO.Triple = llvm::sys::getDefaultTargetTriple();
338*5971e316Smrg 	return TargetInfo::CreateTargetInfo(Diags, &TO);
339*5971e316Smrg }
340*5971e316Smrg 
341*5971e316Smrg #else
342*5971e316Smrg 
create_target_info(CompilerInstance * Clang,DiagnosticsEngine & Diags)343*5971e316Smrg static TargetInfo *create_target_info(CompilerInstance *Clang,
344*5971e316Smrg 	DiagnosticsEngine &Diags)
345*5971e316Smrg {
346*5971e316Smrg 	TargetOptions &TO = Clang->getTargetOpts();
347*5971e316Smrg 	TO.Triple = llvm::sys::getDefaultTargetTriple();
348*5971e316Smrg 	return TargetInfo::CreateTargetInfo(Diags, TO);
349*5971e316Smrg }
350*5971e316Smrg 
351*5971e316Smrg #endif
352*5971e316Smrg 
353*5971e316Smrg #ifdef CREATEDIAGNOSTICS_TAKES_ARG
354*5971e316Smrg 
create_diagnostics(CompilerInstance * Clang)355*5971e316Smrg static void create_diagnostics(CompilerInstance *Clang)
356*5971e316Smrg {
357*5971e316Smrg 	Clang->createDiagnostics(0, NULL, construct_printer());
358*5971e316Smrg }
359*5971e316Smrg 
360*5971e316Smrg #else
361*5971e316Smrg 
create_diagnostics(CompilerInstance * Clang)362*5971e316Smrg static void create_diagnostics(CompilerInstance *Clang)
363*5971e316Smrg {
364*5971e316Smrg 	Clang->createDiagnostics(construct_printer());
365*5971e316Smrg }
366*5971e316Smrg 
367*5971e316Smrg #endif
368*5971e316Smrg 
369*5971e316Smrg #ifdef CREATEPREPROCESSOR_TAKES_TUKIND
370*5971e316Smrg 
create_preprocessor(CompilerInstance * Clang)371*5971e316Smrg static void create_preprocessor(CompilerInstance *Clang)
372*5971e316Smrg {
373*5971e316Smrg 	Clang->createPreprocessor(TU_Complete);
374*5971e316Smrg }
375*5971e316Smrg 
376*5971e316Smrg #else
377*5971e316Smrg 
create_preprocessor(CompilerInstance * Clang)378*5971e316Smrg static void create_preprocessor(CompilerInstance *Clang)
379*5971e316Smrg {
380*5971e316Smrg 	Clang->createPreprocessor();
381*5971e316Smrg }
382*5971e316Smrg 
383*5971e316Smrg #endif
384*5971e316Smrg 
385*5971e316Smrg #ifdef ADDPATH_TAKES_4_ARGUMENTS
386*5971e316Smrg 
387*5971e316Smrg /* Add "Path" to the header search options.
388*5971e316Smrg  *
389*5971e316Smrg  * Do not take into account sysroot, i.e., set ignoreSysRoot to true.
390*5971e316Smrg  */
add_path(HeaderSearchOptions & HSO,string Path)391*5971e316Smrg void add_path(HeaderSearchOptions &HSO, string Path)
392*5971e316Smrg {
393*5971e316Smrg 	HSO.AddPath(Path, frontend::Angled, false, true);
394*5971e316Smrg }
395*5971e316Smrg 
396*5971e316Smrg #else
397*5971e316Smrg 
398*5971e316Smrg /* Add "Path" to the header search options.
399*5971e316Smrg  *
400*5971e316Smrg  * Do not take into account sysroot, i.e., set IsSysRootRelative to false.
401*5971e316Smrg  */
add_path(HeaderSearchOptions & HSO,string Path)402*5971e316Smrg void add_path(HeaderSearchOptions &HSO, string Path)
403*5971e316Smrg {
404*5971e316Smrg 	HSO.AddPath(Path, frontend::Angled, true, false, false);
405*5971e316Smrg }
406*5971e316Smrg 
407*5971e316Smrg #endif
408*5971e316Smrg 
409*5971e316Smrg #ifdef HAVE_SETMAINFILEID
410*5971e316Smrg 
create_main_file_id(SourceManager & SM,const FileEntry * file)411*5971e316Smrg static void create_main_file_id(SourceManager &SM, const FileEntry *file)
412*5971e316Smrg {
413*5971e316Smrg 	SM.setMainFileID(SM.createFileID(file, SourceLocation(),
414*5971e316Smrg 					SrcMgr::C_User));
415*5971e316Smrg }
416*5971e316Smrg 
417*5971e316Smrg #else
418*5971e316Smrg 
create_main_file_id(SourceManager & SM,const FileEntry * file)419*5971e316Smrg static void create_main_file_id(SourceManager &SM, const FileEntry *file)
420*5971e316Smrg {
421*5971e316Smrg 	SM.createMainFileID(file);
422*5971e316Smrg }
423*5971e316Smrg 
424*5971e316Smrg #endif
425*5971e316Smrg 
426*5971e316Smrg #ifdef SETLANGDEFAULTS_TAKES_5_ARGUMENTS
427*5971e316Smrg 
428*5971e316Smrg #include "set_lang_defaults_arg4.h"
429*5971e316Smrg 
set_lang_defaults(CompilerInstance * Clang)430*5971e316Smrg static void set_lang_defaults(CompilerInstance *Clang)
431*5971e316Smrg {
432*5971e316Smrg 	PreprocessorOptions &PO = Clang->getPreprocessorOpts();
433*5971e316Smrg 	TargetOptions &TO = Clang->getTargetOpts();
434*5971e316Smrg 	llvm::Triple T(TO.Triple);
435*5971e316Smrg 	SETLANGDEFAULTS::setLangDefaults(Clang->getLangOpts(), IK_C, T,
436*5971e316Smrg 					    setLangDefaultsArg4(PO),
437*5971e316Smrg 					    LangStandard::lang_unspecified);
438*5971e316Smrg }
439*5971e316Smrg 
440*5971e316Smrg #else
441*5971e316Smrg 
set_lang_defaults(CompilerInstance * Clang)442*5971e316Smrg static void set_lang_defaults(CompilerInstance *Clang)
443*5971e316Smrg {
444*5971e316Smrg 	CompilerInvocation::setLangDefaults(Clang->getLangOpts(), IK_C,
445*5971e316Smrg 					    LangStandard::lang_unspecified);
446*5971e316Smrg }
447*5971e316Smrg 
448*5971e316Smrg #endif
449*5971e316Smrg 
450*5971e316Smrg #ifdef SETINVOCATION_TAKES_SHARED_PTR
451*5971e316Smrg 
set_invocation(CompilerInstance * Clang,CompilerInvocation * invocation)452*5971e316Smrg static void set_invocation(CompilerInstance *Clang,
453*5971e316Smrg 	CompilerInvocation *invocation)
454*5971e316Smrg {
455*5971e316Smrg 	Clang->setInvocation(std::make_shared<CompilerInvocation>(*invocation));
456*5971e316Smrg }
457*5971e316Smrg 
458*5971e316Smrg #else
459*5971e316Smrg 
set_invocation(CompilerInstance * Clang,CompilerInvocation * invocation)460*5971e316Smrg static void set_invocation(CompilerInstance *Clang,
461*5971e316Smrg 	CompilerInvocation *invocation)
462*5971e316Smrg {
463*5971e316Smrg 	Clang->setInvocation(invocation);
464*5971e316Smrg }
465*5971e316Smrg 
466*5971e316Smrg #endif
467*5971e316Smrg 
468*5971e316Smrg /* Helper function for ignore_error that only gets enabled if T
469*5971e316Smrg  * (which is either const FileEntry * or llvm::ErrorOr<const FileEntry *>)
470*5971e316Smrg  * has getError method, i.e., if it is llvm::ErrorOr<const FileEntry *>.
471*5971e316Smrg  */
472*5971e316Smrg template <class T>
ignore_error_helper(const T obj,int,int[1][sizeof (obj.getError ())])473*5971e316Smrg static const FileEntry *ignore_error_helper(const T obj, int,
474*5971e316Smrg 	int[1][sizeof(obj.getError())])
475*5971e316Smrg {
476*5971e316Smrg 	return *obj;
477*5971e316Smrg }
478*5971e316Smrg 
479*5971e316Smrg /* Helper function for ignore_error that is always enabled,
480*5971e316Smrg  * but that only gets selected if the variant above is not enabled,
481*5971e316Smrg  * i.e., if T is const FileEntry *.
482*5971e316Smrg  */
483*5971e316Smrg template <class T>
ignore_error_helper(const T obj,long,void *)484*5971e316Smrg static const FileEntry *ignore_error_helper(const T obj, long, void *)
485*5971e316Smrg {
486*5971e316Smrg 	return obj;
487*5971e316Smrg }
488*5971e316Smrg 
489*5971e316Smrg /* Given either a const FileEntry * or a llvm::ErrorOr<const FileEntry *>,
490*5971e316Smrg  * extract out the const FileEntry *.
491*5971e316Smrg  */
492*5971e316Smrg template <class T>
ignore_error(const T obj)493*5971e316Smrg static const FileEntry *ignore_error(const T obj)
494*5971e316Smrg {
495*5971e316Smrg 	return ignore_error_helper(obj, 0, NULL);
496*5971e316Smrg }
497*5971e316Smrg 
498*5971e316Smrg /* Return the FileEntry corresponding to the given file name
499*5971e316Smrg  * in the given compiler instances, ignoring any error.
500*5971e316Smrg  */
getFile(CompilerInstance * Clang,std::string Filename)501*5971e316Smrg static const FileEntry *getFile(CompilerInstance *Clang, std::string Filename)
502*5971e316Smrg {
503*5971e316Smrg 	return ignore_error(Clang->getFileManager().getFile(Filename));
504*5971e316Smrg }
505*5971e316Smrg 
506*5971e316Smrg /* Create an interface generator for the selected language and
507*5971e316Smrg  * then use it to generate the interface.
508*5971e316Smrg  */
generate(MyASTConsumer & consumer,SourceManager & SM)509*5971e316Smrg static void generate(MyASTConsumer &consumer, SourceManager &SM)
510*5971e316Smrg {
511*5971e316Smrg 	generator *gen;
512*5971e316Smrg 
513*5971e316Smrg 	if (OutputLanguage.compare("python") == 0) {
514*5971e316Smrg 		gen = new python_generator(SM, consumer.exported_types,
515*5971e316Smrg 			consumer.exported_functions, consumer.functions);
516*5971e316Smrg 	} else if (OutputLanguage.compare("cpp") == 0) {
517*5971e316Smrg 		gen = new plain_cpp_generator(SM, consumer.exported_types,
518*5971e316Smrg 			consumer.exported_functions, consumer.functions);
519*5971e316Smrg 	} else if (OutputLanguage.compare("cpp-checked") == 0) {
520*5971e316Smrg 		gen = new plain_cpp_generator(SM, consumer.exported_types,
521*5971e316Smrg 			consumer.exported_functions, consumer.functions, true);
522*5971e316Smrg 	} else if (OutputLanguage.compare("cpp-checked-conversion") == 0) {
523*5971e316Smrg 		gen = new cpp_conversion_generator(SM, consumer.exported_types,
524*5971e316Smrg 			consumer.exported_functions, consumer.functions);
525*5971e316Smrg 	} else if (OutputLanguage.compare("template-cpp") == 0) {
526*5971e316Smrg 		gen = new template_cpp_generator(SM, consumer.exported_types,
527*5971e316Smrg 			consumer.exported_functions, consumer.functions);
528*5971e316Smrg 	} else {
529*5971e316Smrg 		cerr << "Language '" << OutputLanguage
530*5971e316Smrg 		     << "' not recognized." << endl
531*5971e316Smrg 		     << "Not generating bindings." << endl;
532*5971e316Smrg 		exit(EXIT_FAILURE);
533*5971e316Smrg 	}
534*5971e316Smrg 
535*5971e316Smrg 	gen->generate();
536*5971e316Smrg }
537*5971e316Smrg 
main(int argc,char * argv[])538*5971e316Smrg int main(int argc, char *argv[])
539*5971e316Smrg {
540*5971e316Smrg 	llvm::cl::ParseCommandLineOptions(argc, argv);
541*5971e316Smrg 
542*5971e316Smrg 	CompilerInstance *Clang = new CompilerInstance();
543*5971e316Smrg 	create_diagnostics(Clang);
544*5971e316Smrg 	DiagnosticsEngine &Diags = Clang->getDiagnostics();
545*5971e316Smrg 	Diags.setSuppressSystemWarnings(true);
546*5971e316Smrg 	TargetInfo *target = create_target_info(Clang, Diags);
547*5971e316Smrg 	Clang->setTarget(target);
548*5971e316Smrg 	set_lang_defaults(Clang);
549*5971e316Smrg 	CompilerInvocation *invocation =
550*5971e316Smrg 		construct_invocation(InputFilename.c_str(), Diags);
551*5971e316Smrg 	if (invocation)
552*5971e316Smrg 		set_invocation(Clang, invocation);
553*5971e316Smrg 	Clang->createFileManager();
554*5971e316Smrg 	Clang->createSourceManager(Clang->getFileManager());
555*5971e316Smrg 	HeaderSearchOptions &HSO = Clang->getHeaderSearchOpts();
556*5971e316Smrg 	LangOptions &LO = Clang->getLangOpts();
557*5971e316Smrg 	PreprocessorOptions &PO = Clang->getPreprocessorOpts();
558*5971e316Smrg 	HSO.ResourceDir = ResourceDir;
559*5971e316Smrg 
560*5971e316Smrg 	for (llvm::cl::list<string>::size_type i = 0; i < Includes.size(); ++i)
561*5971e316Smrg 		add_path(HSO, Includes[i]);
562*5971e316Smrg 
563*5971e316Smrg 	PO.addMacroDef("__isl_give=__attribute__((annotate(\"isl_give\")))");
564*5971e316Smrg 	PO.addMacroDef("__isl_keep=__attribute__((annotate(\"isl_keep\")))");
565*5971e316Smrg 	PO.addMacroDef("__isl_take=__attribute__((annotate(\"isl_take\")))");
566*5971e316Smrg 	PO.addMacroDef("__isl_export=__attribute__((annotate(\"isl_export\")))");
567*5971e316Smrg 	PO.addMacroDef("__isl_overload="
568*5971e316Smrg 	    "__attribute__((annotate(\"isl_overload\"))) "
569*5971e316Smrg 	    "__attribute__((annotate(\"isl_export\")))");
570*5971e316Smrg 	PO.addMacroDef("__isl_constructor=__attribute__((annotate(\"isl_constructor\"))) __attribute__((annotate(\"isl_export\")))");
571*5971e316Smrg 	PO.addMacroDef("__isl_subclass(super)=__attribute__((annotate(\"isl_subclass(\" #super \")\"))) __attribute__((annotate(\"isl_export\")))");
572*5971e316Smrg 
573*5971e316Smrg 	create_preprocessor(Clang);
574*5971e316Smrg 	Preprocessor &PP = Clang->getPreprocessor();
575*5971e316Smrg 
576*5971e316Smrg 	PP.getBuiltinInfo().initializeBuiltins(PP.getIdentifierTable(), LO);
577*5971e316Smrg 
578*5971e316Smrg 	const FileEntry *file = getFile(Clang, InputFilename);
579*5971e316Smrg 	assert(file);
580*5971e316Smrg 	create_main_file_id(Clang->getSourceManager(), file);
581*5971e316Smrg 
582*5971e316Smrg 	Clang->createASTContext();
583*5971e316Smrg 	MyASTConsumer consumer;
584*5971e316Smrg 	Sema *sema = new Sema(PP, Clang->getASTContext(), consumer);
585*5971e316Smrg 
586*5971e316Smrg 	Diags.getClient()->BeginSourceFile(LO, &PP);
587*5971e316Smrg 	ParseAST(*sema);
588*5971e316Smrg 	Diags.getClient()->EndSourceFile();
589*5971e316Smrg 
590*5971e316Smrg 	generate(consumer, Clang->getSourceManager());
591*5971e316Smrg 
592*5971e316Smrg 	delete sema;
593*5971e316Smrg 	delete Clang;
594*5971e316Smrg 	llvm::llvm_shutdown();
595*5971e316Smrg 
596*5971e316Smrg 	if (Diags.hasErrorOccurred())
597*5971e316Smrg 		return EXIT_FAILURE;
598*5971e316Smrg 	return EXIT_SUCCESS;
599*5971e316Smrg }
600