Blame isl-0.14/interface/extract_interface.cc

Packit fb9d21
/*
Packit fb9d21
 * Copyright 2011 Sven Verdoolaege. All rights reserved.
Packit fb9d21
 * 
Packit fb9d21
 * Redistribution and use in source and binary forms, with or without
Packit fb9d21
 * modification, are permitted provided that the following conditions
Packit fb9d21
 * are met:
Packit fb9d21
 * 
Packit fb9d21
 *    1. Redistributions of source code must retain the above copyright
Packit fb9d21
 *       notice, this list of conditions and the following disclaimer.
Packit fb9d21
 * 
Packit fb9d21
 *    2. Redistributions in binary form must reproduce the above
Packit fb9d21
 *       copyright notice, this list of conditions and the following
Packit fb9d21
 *       disclaimer in the documentation and/or other materials provided
Packit fb9d21
 *       with the distribution.
Packit fb9d21
 * 
Packit fb9d21
 * THIS SOFTWARE IS PROVIDED BY SVEN VERDOOLAEGE ''AS IS'' AND ANY
Packit fb9d21
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit fb9d21
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
Packit fb9d21
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SVEN VERDOOLAEGE OR
Packit fb9d21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
Packit fb9d21
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
Packit fb9d21
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
Packit fb9d21
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Packit fb9d21
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit fb9d21
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit fb9d21
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit fb9d21
 * 
Packit fb9d21
 * The views and conclusions contained in the software and documentation
Packit fb9d21
 * are those of the authors and should not be interpreted as
Packit fb9d21
 * representing official policies, either expressed or implied, of
Packit fb9d21
 * Sven Verdoolaege.
Packit fb9d21
 */ 
Packit fb9d21
Packit fb9d21
#include "isl_config.h"
Packit fb9d21
Packit fb9d21
#include <assert.h>
Packit fb9d21
#include <iostream>
Packit fb9d21
#ifdef HAVE_ADT_OWNINGPTR_H
Packit fb9d21
#include <llvm/ADT/OwningPtr.h>
Packit fb9d21
#else
Packit fb9d21
#include <memory>
Packit fb9d21
#endif
Packit fb9d21
#include <llvm/Support/raw_ostream.h>
Packit fb9d21
#include <llvm/Support/CommandLine.h>
Packit fb9d21
#include <llvm/Support/Host.h>
Packit fb9d21
#include <llvm/Support/ManagedStatic.h>
Packit fb9d21
#include <clang/AST/ASTContext.h>
Packit fb9d21
#include <clang/AST/ASTConsumer.h>
Packit fb9d21
#include <clang/Basic/FileSystemOptions.h>
Packit fb9d21
#include <clang/Basic/FileManager.h>
Packit fb9d21
#include <clang/Basic/TargetOptions.h>
Packit fb9d21
#include <clang/Basic/TargetInfo.h>
Packit fb9d21
#include <clang/Basic/Version.h>
Packit fb9d21
#include <clang/Driver/Compilation.h>
Packit fb9d21
#include <clang/Driver/Driver.h>
Packit fb9d21
#include <clang/Driver/Tool.h>
Packit fb9d21
#include <clang/Frontend/CompilerInstance.h>
Packit fb9d21
#include <clang/Frontend/CompilerInvocation.h>
Packit fb9d21
#ifdef HAVE_BASIC_DIAGNOSTICOPTIONS_H
Packit fb9d21
#include <clang/Basic/DiagnosticOptions.h>
Packit fb9d21
#else
Packit fb9d21
#include <clang/Frontend/DiagnosticOptions.h>
Packit fb9d21
#endif
Packit fb9d21
#include <clang/Frontend/TextDiagnosticPrinter.h>
Packit fb9d21
#include <clang/Frontend/Utils.h>
Packit fb9d21
#include <clang/Lex/HeaderSearch.h>
Packit fb9d21
#include <clang/Lex/Preprocessor.h>
Packit fb9d21
#include <clang/Parse/ParseAST.h>
Packit fb9d21
#include <clang/Sema/Sema.h>
Packit fb9d21
Packit fb9d21
#include "extract_interface.h"
Packit fb9d21
#include "python.h"
Packit fb9d21
Packit fb9d21
using namespace std;
Packit fb9d21
using namespace clang;
Packit fb9d21
using namespace clang::driver;
Packit fb9d21
Packit fb9d21
#ifdef HAVE_ADT_OWNINGPTR_H
Packit fb9d21
#define unique_ptr	llvm::OwningPtr
Packit fb9d21
#endif
Packit fb9d21
Packit fb9d21
static llvm::cl::opt<string> InputFilename(llvm::cl::Positional,
Packit fb9d21
			llvm::cl::Required, llvm::cl::desc("<input file>"));
Packit fb9d21
static llvm::cl::list<string> Includes("I",
Packit fb9d21
			llvm::cl::desc("Header search path"),
Packit fb9d21
			llvm::cl::value_desc("path"), llvm::cl::Prefix);
Packit fb9d21
Packit fb9d21
static const char *ResourceDir =
Packit fb9d21
	CLANG_PREFIX "/lib/clang/" CLANG_VERSION_STRING;
Packit fb9d21
Packit fb9d21
/* Does decl have an attribute of the following form?
Packit fb9d21
 *
Packit fb9d21
 *	__attribute__((annotate("name")))
Packit fb9d21
 */
Packit fb9d21
bool has_annotation(Decl *decl, const char *name)
Packit fb9d21
{
Packit fb9d21
	if (!decl->hasAttrs())
Packit fb9d21
		return false;
Packit fb9d21
Packit fb9d21
	AttrVec attrs = decl->getAttrs();
Packit fb9d21
	for (AttrVec::const_iterator i = attrs.begin() ; i != attrs.end(); ++i) {
Packit fb9d21
		const AnnotateAttr *ann = dyn_cast<AnnotateAttr>(*i);
Packit fb9d21
		if (!ann)
Packit fb9d21
			continue;
Packit fb9d21
		if (ann->getAnnotation().str() == name)
Packit fb9d21
			return true;
Packit fb9d21
	}
Packit fb9d21
Packit fb9d21
	return false;
Packit fb9d21
}
Packit fb9d21
Packit fb9d21
/* Is decl marked as exported?
Packit fb9d21
 */
Packit fb9d21
static bool is_exported(Decl *decl)
Packit fb9d21
{
Packit fb9d21
	return has_annotation(decl, "isl_export");
Packit fb9d21
}
Packit fb9d21
Packit fb9d21
/* Collect all types and functions that are annotated "isl_export"
Packit fb9d21
 * in "types" and "function".
Packit fb9d21
 *
Packit fb9d21
 * We currently only consider single declarations.
Packit fb9d21
 */
Packit fb9d21
struct MyASTConsumer : public ASTConsumer {
Packit fb9d21
	set<RecordDecl *> types;
Packit fb9d21
	set<FunctionDecl *> functions;
Packit fb9d21
Packit fb9d21
	virtual HandleTopLevelDeclReturn HandleTopLevelDecl(DeclGroupRef D) {
Packit fb9d21
		Decl *decl;
Packit fb9d21
Packit fb9d21
		if (!D.isSingleDecl())
Packit fb9d21
			return HandleTopLevelDeclContinue;
Packit fb9d21
		decl = D.getSingleDecl();
Packit fb9d21
		if (!is_exported(decl))
Packit fb9d21
			return HandleTopLevelDeclContinue;
Packit fb9d21
		switch (decl->getKind()) {
Packit fb9d21
		case Decl::Record:
Packit fb9d21
			types.insert(cast<RecordDecl>(decl));
Packit fb9d21
			break;
Packit fb9d21
		case Decl::Function:
Packit fb9d21
			functions.insert(cast<FunctionDecl>(decl));
Packit fb9d21
			break;
Packit fb9d21
		default:
Packit fb9d21
			break;
Packit fb9d21
		}
Packit fb9d21
		return HandleTopLevelDeclContinue;
Packit fb9d21
	}
Packit fb9d21
};
Packit fb9d21
Packit fb9d21
#ifdef USE_ARRAYREF
Packit fb9d21
Packit fb9d21
#ifdef HAVE_CXXISPRODUCTION
Packit fb9d21
static Driver *construct_driver(const char *binary, DiagnosticsEngine &Diags)
Packit fb9d21
{
Packit fb9d21
	return new Driver(binary, llvm::sys::getDefaultTargetTriple(),
Packit fb9d21
			    "", false, false, Diags);
Packit fb9d21
}
Packit fb9d21
#elif defined(HAVE_ISPRODUCTION)
Packit fb9d21
static Driver *construct_driver(const char *binary, DiagnosticsEngine &Diags)
Packit fb9d21
{
Packit fb9d21
	return new Driver(binary, llvm::sys::getDefaultTargetTriple(),
Packit fb9d21
			    "", false, Diags);
Packit fb9d21
}
Packit fb9d21
#elif defined(DRIVER_CTOR_TAKES_DEFAULTIMAGENAME)
Packit fb9d21
static Driver *construct_driver(const char *binary, DiagnosticsEngine &Diags)
Packit fb9d21
{
Packit fb9d21
	return new Driver(binary, llvm::sys::getDefaultTargetTriple(),
Packit fb9d21
			    "", Diags);
Packit fb9d21
}
Packit fb9d21
#else
Packit fb9d21
static Driver *construct_driver(const char *binary, DiagnosticsEngine &Diags)
Packit fb9d21
{
Packit fb9d21
	return new Driver(binary, llvm::sys::getDefaultTargetTriple(), Diags);
Packit fb9d21
}
Packit fb9d21
#endif
Packit fb9d21
Packit fb9d21
/* Create a CompilerInvocation object that stores the command line
Packit fb9d21
 * arguments constructed by the driver.
Packit fb9d21
 * The arguments are mainly useful for setting up the system include
Packit fb9d21
 * paths on newer clangs and on some platforms.
Packit fb9d21
 */
Packit fb9d21
static CompilerInvocation *construct_invocation(const char *filename,
Packit fb9d21
	DiagnosticsEngine &Diags)
Packit fb9d21
{
Packit fb9d21
	const char *binary = CLANG_PREFIX"/bin/clang";
Packit fb9d21
	const unique_ptr<Driver> driver(construct_driver(binary, Diags));
Packit fb9d21
	std::vector<const char *> Argv;
Packit fb9d21
	Argv.push_back(binary);
Packit fb9d21
	Argv.push_back(filename);
Packit fb9d21
	const unique_ptr<Compilation> compilation(
Packit fb9d21
		driver->BuildCompilation(llvm::ArrayRef<const char *>(Argv)));
Packit fb9d21
	JobList &Jobs = compilation->getJobs();
Packit fb9d21
Packit fb9d21
	Command *cmd = cast<Command>(*Jobs.begin());
Packit fb9d21
	if (strcmp(cmd->getCreator().getName(), "clang"))
Packit fb9d21
		return NULL;
Packit fb9d21
Packit fb9d21
	const ArgStringList *args = &cmd->getArguments();
Packit fb9d21
Packit fb9d21
	CompilerInvocation *invocation = new CompilerInvocation;
Packit fb9d21
	CompilerInvocation::CreateFromArgs(*invocation, args->data() + 1,
Packit fb9d21
						args->data() + args->size(),
Packit fb9d21
						Diags);
Packit fb9d21
	return invocation;
Packit fb9d21
}
Packit fb9d21
Packit fb9d21
#else
Packit fb9d21
Packit fb9d21
static CompilerInvocation *construct_invocation(const char *filename,
Packit fb9d21
	DiagnosticsEngine &Diags)
Packit fb9d21
{
Packit fb9d21
	return NULL;
Packit fb9d21
}
Packit fb9d21
Packit fb9d21
#endif
Packit fb9d21
Packit fb9d21
#ifdef HAVE_BASIC_DIAGNOSTICOPTIONS_H
Packit fb9d21
Packit fb9d21
static TextDiagnosticPrinter *construct_printer(void)
Packit fb9d21
{
Packit fb9d21
	return new TextDiagnosticPrinter(llvm::errs(), new DiagnosticOptions());
Packit fb9d21
}
Packit fb9d21
Packit fb9d21
#else
Packit fb9d21
Packit fb9d21
static TextDiagnosticPrinter *construct_printer(void)
Packit fb9d21
{
Packit fb9d21
	DiagnosticOptions DO;
Packit fb9d21
	return new TextDiagnosticPrinter(llvm::errs(), DO);
Packit fb9d21
}
Packit fb9d21
Packit fb9d21
#endif
Packit fb9d21
Packit fb9d21
#ifdef CREATETARGETINFO_TAKES_SHARED_PTR
Packit fb9d21
Packit fb9d21
static TargetInfo *create_target_info(CompilerInstance *Clang,
Packit fb9d21
	DiagnosticsEngine &Diags)
Packit fb9d21
{
Packit fb9d21
	shared_ptr<TargetOptions> TO = Clang->getInvocation().TargetOpts;
Packit fb9d21
	TO->Triple = llvm::sys::getDefaultTargetTriple();
Packit fb9d21
	return TargetInfo::CreateTargetInfo(Diags, TO);
Packit fb9d21
}
Packit fb9d21
Packit fb9d21
#elif defined(CREATETARGETINFO_TAKES_POINTER)
Packit fb9d21
Packit fb9d21
static TargetInfo *create_target_info(CompilerInstance *Clang,
Packit fb9d21
	DiagnosticsEngine &Diags)
Packit fb9d21
{
Packit fb9d21
	TargetOptions &TO = Clang->getTargetOpts();
Packit fb9d21
	TO.Triple = llvm::sys::getDefaultTargetTriple();
Packit fb9d21
	return TargetInfo::CreateTargetInfo(Diags, &TO;;
Packit fb9d21
}
Packit fb9d21
Packit fb9d21
#else
Packit fb9d21
Packit fb9d21
static TargetInfo *create_target_info(CompilerInstance *Clang,
Packit fb9d21
	DiagnosticsEngine &Diags)
Packit fb9d21
{
Packit fb9d21
	TargetOptions &TO = Clang->getTargetOpts();
Packit fb9d21
	TO.Triple = llvm::sys::getDefaultTargetTriple();
Packit fb9d21
	return TargetInfo::CreateTargetInfo(Diags, TO);
Packit fb9d21
}
Packit fb9d21
Packit fb9d21
#endif
Packit fb9d21
Packit fb9d21
#ifdef CREATEDIAGNOSTICS_TAKES_ARG
Packit fb9d21
Packit fb9d21
static void create_diagnostics(CompilerInstance *Clang)
Packit fb9d21
{
Packit fb9d21
	Clang->createDiagnostics(0, NULL, construct_printer());
Packit fb9d21
}
Packit fb9d21
Packit fb9d21
#else
Packit fb9d21
Packit fb9d21
static void create_diagnostics(CompilerInstance *Clang)
Packit fb9d21
{
Packit fb9d21
	Clang->createDiagnostics(construct_printer());
Packit fb9d21
}
Packit fb9d21
Packit fb9d21
#endif
Packit fb9d21
Packit fb9d21
#ifdef CREATEPREPROCESSOR_TAKES_TUKIND
Packit fb9d21
Packit fb9d21
static void create_preprocessor(CompilerInstance *Clang)
Packit fb9d21
{
Packit fb9d21
	Clang->createPreprocessor(TU_Complete);
Packit fb9d21
}
Packit fb9d21
Packit fb9d21
#else
Packit fb9d21
Packit fb9d21
static void create_preprocessor(CompilerInstance *Clang)
Packit fb9d21
{
Packit fb9d21
	Clang->createPreprocessor();
Packit fb9d21
}
Packit fb9d21
Packit fb9d21
#endif
Packit fb9d21
Packit fb9d21
#ifdef ADDPATH_TAKES_4_ARGUMENTS
Packit fb9d21
Packit fb9d21
void add_path(HeaderSearchOptions &HSO, string Path)
Packit fb9d21
{
Packit fb9d21
	HSO.AddPath(Path, frontend::Angled, false, false);
Packit fb9d21
}
Packit fb9d21
Packit fb9d21
#else
Packit fb9d21
Packit fb9d21
void add_path(HeaderSearchOptions &HSO, string Path)
Packit fb9d21
{
Packit fb9d21
	HSO.AddPath(Path, frontend::Angled, true, false, false);
Packit fb9d21
}
Packit fb9d21
Packit fb9d21
#endif
Packit fb9d21
Packit fb9d21
#ifdef HAVE_SETMAINFILEID
Packit fb9d21
Packit fb9d21
static void create_main_file_id(SourceManager &SM, const FileEntry *file)
Packit fb9d21
{
Packit fb9d21
	SM.setMainFileID(SM.createFileID(file, SourceLocation(),
Packit fb9d21
					SrcMgr::C_User));
Packit fb9d21
}
Packit fb9d21
Packit fb9d21
#else
Packit fb9d21
Packit fb9d21
static void create_main_file_id(SourceManager &SM, const FileEntry *file)
Packit fb9d21
{
Packit fb9d21
	SM.createMainFileID(file);
Packit fb9d21
}
Packit fb9d21
Packit fb9d21
#endif
Packit fb9d21
Packit fb9d21
int main(int argc, char *argv[])
Packit fb9d21
{
Packit fb9d21
	llvm::cl::ParseCommandLineOptions(argc, argv);
Packit fb9d21
Packit fb9d21
	CompilerInstance *Clang = new CompilerInstance();
Packit fb9d21
	create_diagnostics(Clang);
Packit fb9d21
	DiagnosticsEngine &Diags = Clang->getDiagnostics();
Packit fb9d21
	Diags.setSuppressSystemWarnings(true);
Packit fb9d21
	CompilerInvocation *invocation =
Packit fb9d21
		construct_invocation(InputFilename.c_str(), Diags);
Packit fb9d21
	if (invocation)
Packit fb9d21
		Clang->setInvocation(invocation);
Packit fb9d21
	Clang->createFileManager();
Packit fb9d21
	Clang->createSourceManager(Clang->getFileManager());
Packit fb9d21
	TargetInfo *target = create_target_info(Clang, Diags);
Packit fb9d21
	Clang->setTarget(target);
Packit fb9d21
	CompilerInvocation::setLangDefaults(Clang->getLangOpts(), IK_C,
Packit fb9d21
					    LangStandard::lang_unspecified);
Packit fb9d21
	HeaderSearchOptions &HSO = Clang->getHeaderSearchOpts();
Packit fb9d21
	LangOptions &LO = Clang->getLangOpts();
Packit fb9d21
	PreprocessorOptions &PO = Clang->getPreprocessorOpts();
Packit fb9d21
	HSO.ResourceDir = ResourceDir;
Packit fb9d21
Packit fb9d21
	for (int i = 0; i < Includes.size(); ++i)
Packit fb9d21
		add_path(HSO, Includes[i]);
Packit fb9d21
Packit fb9d21
	PO.addMacroDef("__isl_give=__attribute__((annotate(\"isl_give\")))");
Packit fb9d21
	PO.addMacroDef("__isl_keep=__attribute__((annotate(\"isl_keep\")))");
Packit fb9d21
	PO.addMacroDef("__isl_take=__attribute__((annotate(\"isl_take\")))");
Packit fb9d21
	PO.addMacroDef("__isl_export=__attribute__((annotate(\"isl_export\")))");
Packit fb9d21
	PO.addMacroDef("__isl_constructor=__attribute__((annotate(\"isl_constructor\"))) __attribute__((annotate(\"isl_export\")))");
Packit fb9d21
	PO.addMacroDef("__isl_subclass(super)=__attribute__((annotate(\"isl_subclass(\" #super \")\"))) __attribute__((annotate(\"isl_export\")))");
Packit fb9d21
Packit fb9d21
	create_preprocessor(Clang);
Packit fb9d21
	Preprocessor &PP = Clang->getPreprocessor();
Packit fb9d21
Packit fb9d21
	PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(), LO);
Packit fb9d21
Packit fb9d21
	const FileEntry *file = Clang->getFileManager().getFile(InputFilename);
Packit fb9d21
	assert(file);
Packit fb9d21
	create_main_file_id(Clang->getSourceManager(), file);
Packit fb9d21
Packit fb9d21
	Clang->createASTContext();
Packit fb9d21
	MyASTConsumer consumer;
Packit fb9d21
	Sema *sema = new Sema(PP, Clang->getASTContext(), consumer);
Packit fb9d21
Packit fb9d21
	Diags.getClient()->BeginSourceFile(LO, &PP;;
Packit fb9d21
	ParseAST(*sema);
Packit fb9d21
	Diags.getClient()->EndSourceFile();
Packit fb9d21
Packit fb9d21
	generate_python(consumer.types, consumer.functions);
Packit fb9d21
Packit fb9d21
	delete sema;
Packit fb9d21
	delete Clang;
Packit fb9d21
	llvm::llvm_shutdown();
Packit fb9d21
Packit fb9d21
	return 0;
Packit fb9d21
}