10b57cec5SDimitry Andric //===- LangOptions.cpp - C Language Family Language Options ---------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file defines the LangOptions class. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "clang/Basic/LangOptions.h" 146e75b2fbSDimitry Andric #include "llvm/ADT/SmallString.h" 156e75b2fbSDimitry Andric #include "llvm/Support/Path.h" 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric using namespace clang; 180b57cec5SDimitry Andric 19e8d8bef9SDimitry Andric LangOptions::LangOptions() : LangStd(LangStandard::lang_unspecified) { 200b57cec5SDimitry Andric #define LANGOPT(Name, Bits, Default, Description) Name = Default; 210b57cec5SDimitry Andric #define ENUM_LANGOPT(Name, Type, Bits, Default, Description) set##Name(Default); 220b57cec5SDimitry Andric #include "clang/Basic/LangOptions.def" 230b57cec5SDimitry Andric } 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric void LangOptions::resetNonModularOptions() { 260b57cec5SDimitry Andric #define LANGOPT(Name, Bits, Default, Description) 270b57cec5SDimitry Andric #define BENIGN_LANGOPT(Name, Bits, Default, Description) Name = Default; 280b57cec5SDimitry Andric #define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description) \ 295ffd83dbSDimitry Andric Name = static_cast<unsigned>(Default); 300b57cec5SDimitry Andric #include "clang/Basic/LangOptions.def" 310b57cec5SDimitry Andric 3206c3fb27SDimitry Andric // Reset "benign" options with implied values (Options.td ImpliedBy relations) 3306c3fb27SDimitry Andric // rather than their defaults. This avoids unexpected combinations and 3406c3fb27SDimitry Andric // invocations that cannot be round-tripped to arguments. 3506c3fb27SDimitry Andric // FIXME: we should derive this automatically from ImpliedBy in tablegen. 3606c3fb27SDimitry Andric AllowFPReassoc = UnsafeFPMath; 3706c3fb27SDimitry Andric NoHonorNaNs = FiniteMathOnly; 3806c3fb27SDimitry Andric NoHonorInfs = FiniteMathOnly; 3906c3fb27SDimitry Andric 400b57cec5SDimitry Andric // These options do not affect AST generation. 41fe6060f1SDimitry Andric NoSanitizeFiles.clear(); 420b57cec5SDimitry Andric XRayAlwaysInstrumentFiles.clear(); 430b57cec5SDimitry Andric XRayNeverInstrumentFiles.clear(); 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric CurrentModule.clear(); 460b57cec5SDimitry Andric IsHeaderFile = false; 470b57cec5SDimitry Andric } 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric bool LangOptions::isNoBuiltinFunc(StringRef FuncName) const { 500b57cec5SDimitry Andric for (unsigned i = 0, e = NoBuiltinFuncs.size(); i != e; ++i) 51*0fca6ea1SDimitry Andric if (FuncName == NoBuiltinFuncs[i]) 520b57cec5SDimitry Andric return true; 530b57cec5SDimitry Andric return false; 540b57cec5SDimitry Andric } 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric VersionTuple LangOptions::getOpenCLVersionTuple() const { 570b57cec5SDimitry Andric const int Ver = OpenCLCPlusPlus ? OpenCLCPlusPlusVersion : OpenCLVersion; 58349cc55cSDimitry Andric if (OpenCLCPlusPlus && Ver != 100) 59349cc55cSDimitry Andric return VersionTuple(Ver / 100); 600b57cec5SDimitry Andric return VersionTuple(Ver / 100, (Ver % 100) / 10); 610b57cec5SDimitry Andric } 625ffd83dbSDimitry Andric 63349cc55cSDimitry Andric unsigned LangOptions::getOpenCLCompatibleVersion() const { 64349cc55cSDimitry Andric if (!OpenCLCPlusPlus) 65349cc55cSDimitry Andric return OpenCLVersion; 66349cc55cSDimitry Andric if (OpenCLCPlusPlusVersion == 100) 67349cc55cSDimitry Andric return 200; 68349cc55cSDimitry Andric if (OpenCLCPlusPlusVersion == 202100) 69349cc55cSDimitry Andric return 300; 70349cc55cSDimitry Andric llvm_unreachable("Unknown OpenCL version"); 71349cc55cSDimitry Andric } 72349cc55cSDimitry Andric 7381ad6265SDimitry Andric void LangOptions::remapPathPrefix(SmallVectorImpl<char> &Path) const { 746e75b2fbSDimitry Andric for (const auto &Entry : MacroPrefixMap) 756e75b2fbSDimitry Andric if (llvm::sys::path::replace_path_prefix(Path, Entry.first, Entry.second)) 766e75b2fbSDimitry Andric break; 776e75b2fbSDimitry Andric } 786e75b2fbSDimitry Andric 79349cc55cSDimitry Andric std::string LangOptions::getOpenCLVersionString() const { 80349cc55cSDimitry Andric std::string Result; 81349cc55cSDimitry Andric { 82349cc55cSDimitry Andric llvm::raw_string_ostream Out(Result); 83349cc55cSDimitry Andric Out << (OpenCLCPlusPlus ? "C++ for OpenCL" : "OpenCL C") << " version " 84349cc55cSDimitry Andric << getOpenCLVersionTuple().getAsString(); 85349cc55cSDimitry Andric } 86349cc55cSDimitry Andric return Result; 87349cc55cSDimitry Andric } 88349cc55cSDimitry Andric 8981ad6265SDimitry Andric void LangOptions::setLangDefaults(LangOptions &Opts, Language Lang, 9081ad6265SDimitry Andric const llvm::Triple &T, 9181ad6265SDimitry Andric std::vector<std::string> &Includes, 9281ad6265SDimitry Andric LangStandard::Kind LangStd) { 9381ad6265SDimitry Andric // Set some properties which depend solely on the input kind; it would be nice 9481ad6265SDimitry Andric // to move these to the language standard, and have the driver resolve the 9581ad6265SDimitry Andric // input kind + language standard. 9681ad6265SDimitry Andric // 9781ad6265SDimitry Andric // FIXME: Perhaps a better model would be for a single source file to have 9881ad6265SDimitry Andric // multiple language standards (C / C++ std, ObjC std, OpenCL std, OpenMP std) 9981ad6265SDimitry Andric // simultaneously active? 10081ad6265SDimitry Andric if (Lang == Language::Asm) { 10181ad6265SDimitry Andric Opts.AsmPreprocessor = 1; 10281ad6265SDimitry Andric } else if (Lang == Language::ObjC || Lang == Language::ObjCXX) { 10381ad6265SDimitry Andric Opts.ObjC = 1; 10481ad6265SDimitry Andric } 10581ad6265SDimitry Andric 10681ad6265SDimitry Andric if (LangStd == LangStandard::lang_unspecified) 10781ad6265SDimitry Andric LangStd = getDefaultLanguageStandard(Lang, T); 10881ad6265SDimitry Andric const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd); 10981ad6265SDimitry Andric Opts.LangStd = LangStd; 11081ad6265SDimitry Andric Opts.LineComment = Std.hasLineComments(); 11181ad6265SDimitry Andric Opts.C99 = Std.isC99(); 11281ad6265SDimitry Andric Opts.C11 = Std.isC11(); 11381ad6265SDimitry Andric Opts.C17 = Std.isC17(); 1145f757f3fSDimitry Andric Opts.C23 = Std.isC23(); 115*0fca6ea1SDimitry Andric Opts.C2y = Std.isC2y(); 11681ad6265SDimitry Andric Opts.CPlusPlus = Std.isCPlusPlus(); 11781ad6265SDimitry Andric Opts.CPlusPlus11 = Std.isCPlusPlus11(); 11881ad6265SDimitry Andric Opts.CPlusPlus14 = Std.isCPlusPlus14(); 11981ad6265SDimitry Andric Opts.CPlusPlus17 = Std.isCPlusPlus17(); 12081ad6265SDimitry Andric Opts.CPlusPlus20 = Std.isCPlusPlus20(); 12106c3fb27SDimitry Andric Opts.CPlusPlus23 = Std.isCPlusPlus23(); 12206c3fb27SDimitry Andric Opts.CPlusPlus26 = Std.isCPlusPlus26(); 12381ad6265SDimitry Andric Opts.GNUMode = Std.isGNUMode(); 12481ad6265SDimitry Andric Opts.GNUCVersion = 0; 12581ad6265SDimitry Andric Opts.HexFloats = Std.hasHexFloats(); 12681ad6265SDimitry Andric Opts.WChar = Std.isCPlusPlus(); 12781ad6265SDimitry Andric Opts.Digraphs = Std.hasDigraphs(); 128*0fca6ea1SDimitry Andric Opts.RawStringLiterals = Std.hasRawStringLiterals(); 12981ad6265SDimitry Andric 13081ad6265SDimitry Andric Opts.HLSL = Lang == Language::HLSL; 13181ad6265SDimitry Andric if (Opts.HLSL && Opts.IncludeDefaultHeader) 13281ad6265SDimitry Andric Includes.push_back("hlsl.h"); 13381ad6265SDimitry Andric 13481ad6265SDimitry Andric // Set OpenCL Version. 13581ad6265SDimitry Andric Opts.OpenCL = Std.isOpenCL(); 13681ad6265SDimitry Andric if (LangStd == LangStandard::lang_opencl10) 13781ad6265SDimitry Andric Opts.OpenCLVersion = 100; 13881ad6265SDimitry Andric else if (LangStd == LangStandard::lang_opencl11) 13981ad6265SDimitry Andric Opts.OpenCLVersion = 110; 14081ad6265SDimitry Andric else if (LangStd == LangStandard::lang_opencl12) 14181ad6265SDimitry Andric Opts.OpenCLVersion = 120; 14281ad6265SDimitry Andric else if (LangStd == LangStandard::lang_opencl20) 14381ad6265SDimitry Andric Opts.OpenCLVersion = 200; 14481ad6265SDimitry Andric else if (LangStd == LangStandard::lang_opencl30) 14581ad6265SDimitry Andric Opts.OpenCLVersion = 300; 14681ad6265SDimitry Andric else if (LangStd == LangStandard::lang_openclcpp10) 14781ad6265SDimitry Andric Opts.OpenCLCPlusPlusVersion = 100; 14881ad6265SDimitry Andric else if (LangStd == LangStandard::lang_openclcpp2021) 14981ad6265SDimitry Andric Opts.OpenCLCPlusPlusVersion = 202100; 15081ad6265SDimitry Andric else if (LangStd == LangStandard::lang_hlsl2015) 15181ad6265SDimitry Andric Opts.HLSLVersion = (unsigned)LangOptions::HLSL_2015; 15281ad6265SDimitry Andric else if (LangStd == LangStandard::lang_hlsl2016) 15381ad6265SDimitry Andric Opts.HLSLVersion = (unsigned)LangOptions::HLSL_2016; 15481ad6265SDimitry Andric else if (LangStd == LangStandard::lang_hlsl2017) 15581ad6265SDimitry Andric Opts.HLSLVersion = (unsigned)LangOptions::HLSL_2017; 15681ad6265SDimitry Andric else if (LangStd == LangStandard::lang_hlsl2018) 15781ad6265SDimitry Andric Opts.HLSLVersion = (unsigned)LangOptions::HLSL_2018; 15881ad6265SDimitry Andric else if (LangStd == LangStandard::lang_hlsl2021) 15981ad6265SDimitry Andric Opts.HLSLVersion = (unsigned)LangOptions::HLSL_2021; 16081ad6265SDimitry Andric else if (LangStd == LangStandard::lang_hlsl202x) 16181ad6265SDimitry Andric Opts.HLSLVersion = (unsigned)LangOptions::HLSL_202x; 16281ad6265SDimitry Andric 16381ad6265SDimitry Andric // OpenCL has some additional defaults. 16481ad6265SDimitry Andric if (Opts.OpenCL) { 16581ad6265SDimitry Andric Opts.AltiVec = 0; 16681ad6265SDimitry Andric Opts.ZVector = 0; 16781ad6265SDimitry Andric Opts.setDefaultFPContractMode(LangOptions::FPM_On); 16881ad6265SDimitry Andric Opts.OpenCLCPlusPlus = Opts.CPlusPlus; 16981ad6265SDimitry Andric Opts.OpenCLPipes = Opts.getOpenCLCompatibleVersion() == 200; 17081ad6265SDimitry Andric Opts.OpenCLGenericAddressSpace = Opts.getOpenCLCompatibleVersion() == 200; 17181ad6265SDimitry Andric 17281ad6265SDimitry Andric // Include default header file for OpenCL. 17381ad6265SDimitry Andric if (Opts.IncludeDefaultHeader) { 17481ad6265SDimitry Andric if (Opts.DeclareOpenCLBuiltins) { 17581ad6265SDimitry Andric // Only include base header file for builtin types and constants. 17681ad6265SDimitry Andric Includes.push_back("opencl-c-base.h"); 17781ad6265SDimitry Andric } else { 17881ad6265SDimitry Andric Includes.push_back("opencl-c.h"); 17981ad6265SDimitry Andric } 18081ad6265SDimitry Andric } 18181ad6265SDimitry Andric } 18281ad6265SDimitry Andric 18381ad6265SDimitry Andric Opts.HIP = Lang == Language::HIP; 18481ad6265SDimitry Andric Opts.CUDA = Lang == Language::CUDA || Opts.HIP; 18581ad6265SDimitry Andric if (Opts.HIP) { 18681ad6265SDimitry Andric // HIP toolchain does not support 'Fast' FPOpFusion in backends since it 18781ad6265SDimitry Andric // fuses multiplication/addition instructions without contract flag from 18881ad6265SDimitry Andric // device library functions in LLVM bitcode, which causes accuracy loss in 18981ad6265SDimitry Andric // certain math functions, e.g. tan(-1e20) becomes -0.933 instead of 0.8446. 19081ad6265SDimitry Andric // For device library functions in bitcode to work, 'Strict' or 'Standard' 19181ad6265SDimitry Andric // FPOpFusion options in backends is needed. Therefore 'fast-honor-pragmas' 19281ad6265SDimitry Andric // FP contract option is used to allow fuse across statements in frontend 19381ad6265SDimitry Andric // whereas respecting contract flag in backend. 19481ad6265SDimitry Andric Opts.setDefaultFPContractMode(LangOptions::FPM_FastHonorPragmas); 19581ad6265SDimitry Andric } else if (Opts.CUDA) { 19681ad6265SDimitry Andric if (T.isSPIRV()) { 19781ad6265SDimitry Andric // Emit OpenCL version metadata in LLVM IR when targeting SPIR-V. 19881ad6265SDimitry Andric Opts.OpenCLVersion = 200; 19981ad6265SDimitry Andric } 20081ad6265SDimitry Andric // Allow fuse across statements disregarding pragmas. 20181ad6265SDimitry Andric Opts.setDefaultFPContractMode(LangOptions::FPM_Fast); 20281ad6265SDimitry Andric } 20381ad6265SDimitry Andric 20481ad6265SDimitry Andric Opts.RenderScript = Lang == Language::RenderScript; 20581ad6265SDimitry Andric 2065f757f3fSDimitry Andric // OpenCL, C++ and C23 have bool, true, false keywords. 2075f757f3fSDimitry Andric Opts.Bool = Opts.OpenCL || Opts.CPlusPlus || Opts.C23; 20881ad6265SDimitry Andric 20981ad6265SDimitry Andric // OpenCL and HLSL have half keyword 21081ad6265SDimitry Andric Opts.Half = Opts.OpenCL || Opts.HLSL; 21181ad6265SDimitry Andric } 21281ad6265SDimitry Andric 2135ffd83dbSDimitry Andric FPOptions FPOptions::defaultWithoutTrailingStorage(const LangOptions &LO) { 2145ffd83dbSDimitry Andric FPOptions result(LO); 2155ffd83dbSDimitry Andric return result; 2165ffd83dbSDimitry Andric } 2175ffd83dbSDimitry Andric 21881ad6265SDimitry Andric FPOptionsOverride FPOptions::getChangesSlow(const FPOptions &Base) const { 21981ad6265SDimitry Andric FPOptions::storage_type OverrideMask = 0; 22081ad6265SDimitry Andric #define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \ 22181ad6265SDimitry Andric if (get##NAME() != Base.get##NAME()) \ 22281ad6265SDimitry Andric OverrideMask |= NAME##Mask; 22381ad6265SDimitry Andric #include "clang/Basic/FPOptions.def" 22481ad6265SDimitry Andric return FPOptionsOverride(*this, OverrideMask); 22581ad6265SDimitry Andric } 22681ad6265SDimitry Andric 2275ffd83dbSDimitry Andric LLVM_DUMP_METHOD void FPOptions::dump() { 2285ffd83dbSDimitry Andric #define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \ 2295ffd83dbSDimitry Andric llvm::errs() << "\n " #NAME " " << get##NAME(); 2305ffd83dbSDimitry Andric #include "clang/Basic/FPOptions.def" 2315ffd83dbSDimitry Andric llvm::errs() << "\n"; 2325ffd83dbSDimitry Andric } 2335ffd83dbSDimitry Andric 2345ffd83dbSDimitry Andric LLVM_DUMP_METHOD void FPOptionsOverride::dump() { 2355ffd83dbSDimitry Andric #define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \ 2365ffd83dbSDimitry Andric if (has##NAME##Override()) \ 2375ffd83dbSDimitry Andric llvm::errs() << "\n " #NAME " Override is " << get##NAME##Override(); 2385ffd83dbSDimitry Andric #include "clang/Basic/FPOptions.def" 2395ffd83dbSDimitry Andric llvm::errs() << "\n"; 2405ffd83dbSDimitry Andric } 241