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