123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400 |
- //===--- Types.cpp - Driver input & temporary type information ------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #include "clang/Driver/Types.h"
- #include "clang/Driver/Driver.h"
- #include "clang/Driver/DriverDiagnostic.h"
- #include "clang/Driver/Options.h"
- #include "llvm/ADT/STLExtras.h"
- #include "llvm/ADT/SmallVector.h"
- #include "llvm/ADT/StringSwitch.h"
- #include "llvm/Option/Arg.h"
- #include <cassert>
- #include <cstring>
- using namespace clang::driver;
- using namespace clang::driver::types;
- struct TypeInfo {
- const char *Name;
- const char *TempSuffix;
- ID PreprocessedType;
- const llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> Phases;
- };
- static const TypeInfo TypeInfos[] = {
- #define TYPE(NAME, ID, PP_TYPE, TEMP_SUFFIX, ...) \
- { NAME, TEMP_SUFFIX, TY_##PP_TYPE, { __VA_ARGS__ }, },
- #include "clang/Driver/Types.def"
- #undef TYPE
- };
- static const unsigned numTypes = llvm::array_lengthof(TypeInfos);
- static const TypeInfo &getInfo(unsigned id) {
- assert(id > 0 && id - 1 < numTypes && "Invalid Type ID.");
- return TypeInfos[id - 1];
- }
- const char *types::getTypeName(ID Id) {
- return getInfo(Id).Name;
- }
- types::ID types::getPreprocessedType(ID Id) {
- ID PPT = getInfo(Id).PreprocessedType;
- assert((llvm::is_contained(getInfo(Id).Phases, phases::Preprocess) !=
- (PPT == TY_INVALID)) &&
- "Unexpected Preprocess Type.");
- return PPT;
- }
- static bool isPrepeocessedModuleType(ID Id) {
- return Id == TY_CXXModule || Id == TY_PP_CXXModule;
- }
- types::ID types::getPrecompiledType(ID Id) {
- if (isPrepeocessedModuleType(Id))
- return TY_ModuleFile;
- if (onlyPrecompileType(Id))
- return TY_PCH;
- return TY_INVALID;
- }
- const char *types::getTypeTempSuffix(ID Id, bool CLMode) {
- if (CLMode) {
- switch (Id) {
- case TY_Object:
- case TY_LTO_BC:
- return "obj";
- case TY_Image:
- return "exe";
- case TY_PP_Asm:
- return "asm";
- default:
- break;
- }
- }
- return getInfo(Id).TempSuffix;
- }
- bool types::onlyAssembleType(ID Id) {
- return llvm::is_contained(getInfo(Id).Phases, phases::Assemble) &&
- !llvm::is_contained(getInfo(Id).Phases, phases::Compile) &&
- !llvm::is_contained(getInfo(Id).Phases, phases::Backend);
- }
- bool types::onlyPrecompileType(ID Id) {
- return llvm::is_contained(getInfo(Id).Phases, phases::Precompile) &&
- !isPrepeocessedModuleType(Id);
- }
- bool types::canTypeBeUserSpecified(ID Id) {
- static const clang::driver::types::ID kStaticLangageTypes[] = {
- TY_CUDA_DEVICE, TY_HIP_DEVICE, TY_PP_CHeader,
- TY_PP_ObjCHeader, TY_PP_CXXHeader, TY_PP_ObjCXXHeader,
- TY_PP_CXXModule, TY_LTO_IR, TY_LTO_BC,
- TY_Plist, TY_RewrittenObjC, TY_RewrittenLegacyObjC,
- TY_Remap, TY_PCH, TY_Object,
- TY_Image, TY_dSYM, TY_Dependencies,
- TY_CUDA_FATBIN, TY_HIP_FATBIN};
- return !llvm::is_contained(kStaticLangageTypes, Id);
- }
- bool types::appendSuffixForType(ID Id) {
- return Id == TY_PCH || Id == TY_dSYM || Id == TY_CUDA_FATBIN ||
- Id == TY_HIP_FATBIN;
- }
- bool types::canLipoType(ID Id) {
- return (Id == TY_Nothing ||
- Id == TY_Image ||
- Id == TY_Object ||
- Id == TY_LTO_BC);
- }
- bool types::isAcceptedByClang(ID Id) {
- switch (Id) {
- default:
- return false;
- case TY_Asm:
- case TY_C: case TY_PP_C:
- case TY_CL:
- case TY_CUDA: case TY_PP_CUDA:
- case TY_CUDA_DEVICE:
- case TY_HIP:
- case TY_PP_HIP:
- case TY_HIP_DEVICE:
- case TY_ObjC: case TY_PP_ObjC: case TY_PP_ObjC_Alias:
- case TY_CXX: case TY_PP_CXX:
- case TY_ObjCXX: case TY_PP_ObjCXX: case TY_PP_ObjCXX_Alias:
- case TY_CHeader: case TY_PP_CHeader:
- case TY_CLHeader:
- case TY_ObjCHeader: case TY_PP_ObjCHeader:
- case TY_CXXHeader: case TY_PP_CXXHeader:
- case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader:
- case TY_CXXModule: case TY_PP_CXXModule:
- case TY_AST: case TY_ModuleFile:
- case TY_LLVM_IR: case TY_LLVM_BC:
- return true;
- }
- }
- bool types::isObjC(ID Id) {
- switch (Id) {
- default:
- return false;
- case TY_ObjC: case TY_PP_ObjC: case TY_PP_ObjC_Alias:
- case TY_ObjCXX: case TY_PP_ObjCXX:
- case TY_ObjCHeader: case TY_PP_ObjCHeader:
- case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader: case TY_PP_ObjCXX_Alias:
- return true;
- }
- }
- bool types::isCXX(ID Id) {
- switch (Id) {
- default:
- return false;
- case TY_CXX: case TY_PP_CXX:
- case TY_ObjCXX: case TY_PP_ObjCXX: case TY_PP_ObjCXX_Alias:
- case TY_CXXHeader: case TY_PP_CXXHeader:
- case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader:
- case TY_CXXModule: case TY_PP_CXXModule:
- case TY_CUDA: case TY_PP_CUDA: case TY_CUDA_DEVICE:
- case TY_HIP:
- case TY_PP_HIP:
- case TY_HIP_DEVICE:
- return true;
- }
- }
- bool types::isLLVMIR(ID Id) {
- switch (Id) {
- default:
- return false;
- case TY_LLVM_IR:
- case TY_LLVM_BC:
- case TY_LTO_IR:
- case TY_LTO_BC:
- return true;
- }
- }
- bool types::isCuda(ID Id) {
- switch (Id) {
- default:
- return false;
- case TY_CUDA:
- case TY_PP_CUDA:
- case TY_CUDA_DEVICE:
- return true;
- }
- }
- bool types::isHIP(ID Id) {
- switch (Id) {
- default:
- return false;
- case TY_HIP:
- case TY_PP_HIP:
- case TY_HIP_DEVICE:
- return true;
- }
- }
- bool types::isSrcFile(ID Id) {
- return Id != TY_Object && getPreprocessedType(Id) != TY_INVALID;
- }
- types::ID types::lookupTypeForExtension(llvm::StringRef Ext) {
- return llvm::StringSwitch<types::ID>(Ext)
- .Case("c", TY_C)
- .Case("C", TY_CXX)
- .Case("F", TY_Fortran)
- .Case("f", TY_PP_Fortran)
- .Case("h", TY_CHeader)
- .Case("H", TY_CXXHeader)
- .Case("i", TY_PP_C)
- .Case("m", TY_ObjC)
- .Case("M", TY_ObjCXX)
- .Case("o", TY_Object)
- .Case("S", TY_Asm)
- .Case("s", TY_PP_Asm)
- .Case("bc", TY_LLVM_BC)
- .Case("cc", TY_CXX)
- .Case("CC", TY_CXX)
- .Case("cl", TY_CL)
- .Case("cp", TY_CXX)
- .Case("cu", TY_CUDA)
- .Case("hh", TY_CXXHeader)
- .Case("ii", TY_PP_CXX)
- .Case("ll", TY_LLVM_IR)
- .Case("mi", TY_PP_ObjC)
- .Case("mm", TY_ObjCXX)
- .Case("rs", TY_RenderScript)
- .Case("adb", TY_Ada)
- .Case("ads", TY_Ada)
- .Case("asm", TY_PP_Asm)
- .Case("ast", TY_AST)
- .Case("ccm", TY_CXXModule)
- .Case("cpp", TY_CXX)
- .Case("CPP", TY_CXX)
- .Case("c++", TY_CXX)
- .Case("C++", TY_CXX)
- .Case("cui", TY_PP_CUDA)
- .Case("cxx", TY_CXX)
- .Case("CXX", TY_CXX)
- .Case("F90", TY_Fortran)
- .Case("f90", TY_PP_Fortran)
- .Case("F95", TY_Fortran)
- .Case("f95", TY_PP_Fortran)
- .Case("for", TY_PP_Fortran)
- .Case("FOR", TY_PP_Fortran)
- .Case("fpp", TY_Fortran)
- .Case("FPP", TY_Fortran)
- .Case("gch", TY_PCH)
- .Case("hip", TY_HIP)
- .Case("hpp", TY_CXXHeader)
- .Case("iim", TY_PP_CXXModule)
- .Case("lib", TY_Object)
- .Case("mii", TY_PP_ObjCXX)
- .Case("obj", TY_Object)
- .Case("ifs", TY_IFS)
- .Case("pch", TY_PCH)
- .Case("pcm", TY_ModuleFile)
- .Case("c++m", TY_CXXModule)
- .Case("cppm", TY_CXXModule)
- .Case("cxxm", TY_CXXModule)
- .Default(TY_INVALID);
- }
- types::ID types::lookupTypeForTypeSpecifier(const char *Name) {
- for (unsigned i=0; i<numTypes; ++i) {
- types::ID Id = (types::ID) (i + 1);
- if (canTypeBeUserSpecified(Id) &&
- strcmp(Name, getInfo(Id).Name) == 0)
- return Id;
- }
- return TY_INVALID;
- }
- // FIXME: Why don't we just put this list in the defs file, eh.
- // FIXME: The list is now in Types.def but for now this function will verify
- // the old behavior and a subsequent change will delete most of the body.
- void types::getCompilationPhases(ID Id, llvm::SmallVectorImpl<phases::ID> &P) {
- P = getInfo(Id).Phases;
- assert(0 < P.size() && "Not enough phases in list");
- assert(P.size() <= phases::MaxNumberOfPhases && "Too many phases in list");
- }
- void types::getCompilationPhases(const clang::driver::Driver &Driver,
- llvm::opt::DerivedArgList &DAL, ID Id,
- llvm::SmallVectorImpl<phases::ID> &P) {
- llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> PhaseList;
- types::getCompilationPhases(Id, PhaseList);
- // Filter to compiler mode. When the compiler is run as a preprocessor then
- // compilation is not an option.
- // -S runs the compiler in Assembly listing mode.
- if (Driver.CCCIsCPP() || DAL.getLastArg(options::OPT_E) ||
- DAL.getLastArg(options::OPT__SLASH_EP) ||
- DAL.getLastArg(options::OPT_M, options::OPT_MM) ||
- DAL.getLastArg(options::OPT__SLASH_P))
- llvm::copy_if(PhaseList, std::back_inserter(P),
- [](phases::ID Phase) { return Phase <= phases::Preprocess; });
- // --precompile only runs up to precompilation.
- // This is a clang extension and is not compatible with GCC.
- else if (DAL.getLastArg(options::OPT__precompile))
- llvm::copy_if(PhaseList, std::back_inserter(P),
- [](phases::ID Phase) { return Phase <= phases::Precompile; });
- // Treat Interface Stubs like its own compilation mode.
- else if (DAL.getLastArg(options::OPT_emit_iterface_stubs)) {
- llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> IfsModePhaseList;
- llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> &PL = PhaseList;
- phases::ID LastPhase = phases::IfsMerge;
- if (Id != types::TY_IFS) {
- if (DAL.hasArg(options::OPT_c))
- LastPhase = phases::Compile;
- PL = IfsModePhaseList;
- types::getCompilationPhases(types::TY_IFS_CPP, PL);
- }
- llvm::copy_if(PL, std::back_inserter(P), [&](phases::ID Phase) {
- return Phase <= LastPhase;
- });
- }
- // -{fsyntax-only,-analyze,emit-ast} only run up to the compiler.
- else if (DAL.getLastArg(options::OPT_fsyntax_only) ||
- DAL.getLastArg(options::OPT_print_supported_cpus) ||
- DAL.getLastArg(options::OPT_module_file_info) ||
- DAL.getLastArg(options::OPT_verify_pch) ||
- DAL.getLastArg(options::OPT_rewrite_objc) ||
- DAL.getLastArg(options::OPT_rewrite_legacy_objc) ||
- DAL.getLastArg(options::OPT__migrate) ||
- DAL.getLastArg(options::OPT__analyze) ||
- DAL.getLastArg(options::OPT_emit_ast))
- llvm::copy_if(PhaseList, std::back_inserter(P),
- [](phases::ID Phase) { return Phase <= phases::Compile; });
- else if (DAL.getLastArg(options::OPT_S) ||
- DAL.getLastArg(options::OPT_emit_llvm))
- llvm::copy_if(PhaseList, std::back_inserter(P),
- [](phases::ID Phase) { return Phase <= phases::Backend; });
- else if (DAL.getLastArg(options::OPT_c))
- llvm::copy_if(PhaseList, std::back_inserter(P),
- [](phases::ID Phase) { return Phase <= phases::Assemble; });
- // Generally means, do every phase until Link.
- else
- P = PhaseList;
- }
- ID types::lookupCXXTypeForCType(ID Id) {
- switch (Id) {
- default:
- return Id;
- case types::TY_C:
- return types::TY_CXX;
- case types::TY_PP_C:
- return types::TY_PP_CXX;
- case types::TY_CHeader:
- return types::TY_CXXHeader;
- case types::TY_PP_CHeader:
- return types::TY_PP_CXXHeader;
- }
- }
- ID types::lookupHeaderTypeForSourceType(ID Id) {
- switch (Id) {
- default:
- return Id;
- // FIXME: Handle preprocessed input types.
- case types::TY_C:
- return types::TY_CHeader;
- case types::TY_CXX:
- case types::TY_CXXModule:
- return types::TY_CXXHeader;
- case types::TY_ObjC:
- return types::TY_ObjCHeader;
- case types::TY_ObjCXX:
- return types::TY_ObjCXXHeader;
- case types::TY_CL:
- return types::TY_CLHeader;
- }
- }
|