828 lines
28 KiB
C++
828 lines
28 KiB
C++
//===- LangOptions.h - C Language Family Language Options -------*- C++ -*-===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
/// \file
|
|
/// Defines the clang::LangOptions interface.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_CLANG_BASIC_LANGOPTIONS_H
|
|
#define LLVM_CLANG_BASIC_LANGOPTIONS_H
|
|
|
|
#include "clang/Basic/CommentOptions.h"
|
|
#include "clang/Basic/LLVM.h"
|
|
#include "clang/Basic/LangStandard.h"
|
|
#include "clang/Basic/ObjCRuntime.h"
|
|
#include "clang/Basic/Sanitizers.h"
|
|
#include "clang/Basic/TargetCXXABI.h"
|
|
#include "clang/Basic/Visibility.h"
|
|
#include "llvm/ADT/FloatingPointMode.h"
|
|
#include "llvm/ADT/StringRef.h"
|
|
#include "llvm/ADT/Triple.h"
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
namespace clang {
|
|
|
|
/// Bitfields of LangOptions, split out from LangOptions in order to ensure that
|
|
/// this large collection of bitfields is a trivial class type.
|
|
class LangOptionsBase {
|
|
friend class CompilerInvocation;
|
|
|
|
public:
|
|
// Define simple language options (with no accessors).
|
|
#define LANGOPT(Name, Bits, Default, Description) unsigned Name : Bits;
|
|
#define ENUM_LANGOPT(Name, Type, Bits, Default, Description)
|
|
#include "clang/Basic/LangOptions.def"
|
|
|
|
protected:
|
|
// Define language options of enumeration type. These are private, and will
|
|
// have accessors (below).
|
|
#define LANGOPT(Name, Bits, Default, Description)
|
|
#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
|
|
unsigned Name : Bits;
|
|
#include "clang/Basic/LangOptions.def"
|
|
};
|
|
|
|
/// In the Microsoft ABI, this controls the placement of virtual displacement
|
|
/// members used to implement virtual inheritance.
|
|
enum class MSVtorDispMode { Never, ForVBaseOverride, ForVFTable };
|
|
|
|
/// Shader programs run in specific pipeline stages.
|
|
enum class ShaderStage {
|
|
Pixel = 0,
|
|
Vertex,
|
|
Geometry,
|
|
Hull,
|
|
Domain,
|
|
Compute,
|
|
Library,
|
|
RayGeneration,
|
|
Intersection,
|
|
AnyHit,
|
|
ClosestHit,
|
|
Miss,
|
|
Callable,
|
|
Mesh,
|
|
Amplification,
|
|
Invalid,
|
|
};
|
|
|
|
/// Keeps track of the various options that can be
|
|
/// enabled, which controls the dialect of C or C++ that is accepted.
|
|
class LangOptions : public LangOptionsBase {
|
|
public:
|
|
using Visibility = clang::Visibility;
|
|
using RoundingMode = llvm::RoundingMode;
|
|
|
|
enum GCMode { NonGC, GCOnly, HybridGC };
|
|
enum StackProtectorMode { SSPOff, SSPOn, SSPStrong, SSPReq };
|
|
|
|
// Automatic variables live on the stack, and when trivial they're usually
|
|
// uninitialized because it's undefined behavior to use them without
|
|
// initializing them.
|
|
enum class TrivialAutoVarInitKind { Uninitialized, Zero, Pattern };
|
|
|
|
enum SignedOverflowBehaviorTy {
|
|
// Default C standard behavior.
|
|
SOB_Undefined,
|
|
|
|
// -fwrapv
|
|
SOB_Defined,
|
|
|
|
// -ftrapv
|
|
SOB_Trapping
|
|
};
|
|
|
|
// FIXME: Unify with TUKind.
|
|
enum CompilingModuleKind {
|
|
/// Not compiling a module interface at all.
|
|
CMK_None,
|
|
|
|
/// Compiling a module from a module map.
|
|
CMK_ModuleMap,
|
|
|
|
/// Compiling a module from a list of header files.
|
|
CMK_HeaderModule,
|
|
|
|
/// Compiling a module header unit.
|
|
CMK_HeaderUnit,
|
|
|
|
/// Compiling a C++ modules TS module interface unit.
|
|
CMK_ModuleInterface,
|
|
};
|
|
|
|
enum PragmaMSPointersToMembersKind {
|
|
PPTMK_BestCase,
|
|
PPTMK_FullGeneralitySingleInheritance,
|
|
PPTMK_FullGeneralityMultipleInheritance,
|
|
PPTMK_FullGeneralityVirtualInheritance
|
|
};
|
|
|
|
using MSVtorDispMode = clang::MSVtorDispMode;
|
|
|
|
enum DefaultCallingConvention {
|
|
DCC_None,
|
|
DCC_CDecl,
|
|
DCC_FastCall,
|
|
DCC_StdCall,
|
|
DCC_VectorCall,
|
|
DCC_RegCall
|
|
};
|
|
|
|
enum AddrSpaceMapMangling { ASMM_Target, ASMM_On, ASMM_Off };
|
|
|
|
// Corresponds to _MSC_VER
|
|
enum MSVCMajorVersion {
|
|
MSVC2010 = 1600,
|
|
MSVC2012 = 1700,
|
|
MSVC2013 = 1800,
|
|
MSVC2015 = 1900,
|
|
MSVC2017 = 1910,
|
|
MSVC2017_5 = 1912,
|
|
MSVC2017_7 = 1914,
|
|
MSVC2019 = 1920,
|
|
MSVC2019_5 = 1925,
|
|
MSVC2019_8 = 1928,
|
|
};
|
|
|
|
enum SYCLMajorVersion {
|
|
SYCL_None,
|
|
SYCL_2017,
|
|
SYCL_2020,
|
|
// The "default" SYCL version to be used when none is specified on the
|
|
// frontend command line.
|
|
SYCL_Default = SYCL_2020
|
|
};
|
|
|
|
enum HLSLLangStd {
|
|
HLSL_Unset = 0,
|
|
HLSL_2015 = 2015,
|
|
HLSL_2016 = 2016,
|
|
HLSL_2017 = 2017,
|
|
HLSL_2018 = 2018,
|
|
HLSL_2021 = 2021,
|
|
HLSL_202x = 2029,
|
|
};
|
|
|
|
/// Clang versions with different platform ABI conformance.
|
|
enum class ClangABI {
|
|
/// Attempt to be ABI-compatible with code generated by Clang 3.8.x
|
|
/// (SVN r257626). This causes <1 x long long> to be passed in an
|
|
/// integer register instead of an SSE register on x64_64.
|
|
Ver3_8,
|
|
|
|
/// Attempt to be ABI-compatible with code generated by Clang 4.0.x
|
|
/// (SVN r291814). This causes move operations to be ignored when
|
|
/// determining whether a class type can be passed or returned directly.
|
|
Ver4,
|
|
|
|
/// Attempt to be ABI-compatible with code generated by Clang 6.0.x
|
|
/// (SVN r321711). This causes determination of whether a type is
|
|
/// standard-layout to ignore collisions between empty base classes
|
|
/// and between base classes and member subobjects, which affects
|
|
/// whether we reuse base class tail padding in some ABIs.
|
|
Ver6,
|
|
|
|
/// Attempt to be ABI-compatible with code generated by Clang 7.0.x
|
|
/// (SVN r338536). This causes alignof (C++) and _Alignof (C11) to be
|
|
/// compatible with __alignof (i.e., return the preferred alignment)
|
|
/// rather than returning the required alignment.
|
|
Ver7,
|
|
|
|
/// Attempt to be ABI-compatible with code generated by Clang 9.0.x
|
|
/// (SVN r351319). This causes vectors of __int128 to be passed in memory
|
|
/// instead of passing in multiple scalar registers on x86_64 on Linux and
|
|
/// NetBSD.
|
|
Ver9,
|
|
|
|
/// Attempt to be ABI-compatible with code generated by Clang 11.0.x
|
|
/// (git 2e10b7a39b93). This causes clang to pass unions with a 256-bit
|
|
/// vector member on the stack instead of using registers, to not properly
|
|
/// mangle substitutions for template names in some cases, and to mangle
|
|
/// declaration template arguments without a cast to the parameter type
|
|
/// even when that can lead to mangling collisions.
|
|
Ver11,
|
|
|
|
/// Attempt to be ABI-compatible with code generated by Clang 12.0.x
|
|
/// (git 8e464dd76bef). This causes clang to mangle lambdas within
|
|
/// global-scope inline variables incorrectly.
|
|
Ver12,
|
|
|
|
/// Attempt to be ABI-compatible with code generated by Clang 13.0.x.
|
|
/// This causes clang to not pack non-POD members of packed structs.
|
|
Ver13,
|
|
|
|
/// Attempt to be ABI-compatible with code generated by Clang 14.0.x.
|
|
/// This causes clang to mangle dependent nested names incorrectly.
|
|
Ver14,
|
|
|
|
/// Conform to the underlying platform's C and C++ ABIs as closely
|
|
/// as we can.
|
|
Latest
|
|
};
|
|
|
|
enum class CoreFoundationABI {
|
|
/// No interoperability ABI has been specified
|
|
Unspecified,
|
|
/// CoreFoundation does not have any language interoperability
|
|
Standalone,
|
|
/// Interoperability with the ObjectiveC runtime
|
|
ObjectiveC,
|
|
/// Interoperability with the latest known version of the Swift runtime
|
|
Swift,
|
|
/// Interoperability with the Swift 5.0 runtime
|
|
Swift5_0,
|
|
/// Interoperability with the Swift 4.2 runtime
|
|
Swift4_2,
|
|
/// Interoperability with the Swift 4.1 runtime
|
|
Swift4_1,
|
|
};
|
|
|
|
enum FPModeKind {
|
|
// Disable the floating point pragma
|
|
FPM_Off,
|
|
|
|
// Enable the floating point pragma
|
|
FPM_On,
|
|
|
|
// Aggressively fuse FP ops (E.g. FMA) disregarding pragmas.
|
|
FPM_Fast,
|
|
|
|
// Aggressively fuse FP ops and honor pragmas.
|
|
FPM_FastHonorPragmas
|
|
};
|
|
|
|
/// Alias for RoundingMode::NearestTiesToEven.
|
|
static constexpr unsigned FPR_ToNearest =
|
|
static_cast<unsigned>(llvm::RoundingMode::NearestTiesToEven);
|
|
|
|
/// Possible floating point exception behavior.
|
|
enum FPExceptionModeKind {
|
|
/// Assume that floating-point exceptions are masked.
|
|
FPE_Ignore,
|
|
/// Transformations do not cause new exceptions but may hide some.
|
|
FPE_MayTrap,
|
|
/// Strictly preserve the floating-point exception semantics.
|
|
FPE_Strict
|
|
};
|
|
|
|
/// Possible float expression evaluation method choices.
|
|
enum FPEvalMethodKind {
|
|
/// The evaluation method cannot be determined or is inconsistent for this
|
|
/// target.
|
|
FEM_Indeterminable = -1,
|
|
/// Use the declared type for fp arithmetic.
|
|
FEM_Source = 0,
|
|
/// Use the type double for fp arithmetic.
|
|
FEM_Double = 1,
|
|
/// Use extended type for fp arithmetic.
|
|
FEM_Extended = 2,
|
|
/// Used only for FE option processing; this is only used to indicate that
|
|
/// the user did not specify an explicit evaluation method on the command
|
|
/// line and so the target should be queried for its default evaluation
|
|
/// method instead.
|
|
FEM_UnsetOnCommandLine = 3
|
|
};
|
|
|
|
/// Possible exception handling behavior.
|
|
enum class ExceptionHandlingKind { None, SjLj, WinEH, DwarfCFI, Wasm };
|
|
|
|
enum class LaxVectorConversionKind {
|
|
/// Permit no implicit vector bitcasts.
|
|
None,
|
|
/// Permit vector bitcasts between integer vectors with different numbers
|
|
/// of elements but the same total bit-width.
|
|
Integer,
|
|
/// Permit vector bitcasts between all vectors with the same total
|
|
/// bit-width.
|
|
All,
|
|
};
|
|
|
|
enum class AltivecSrcCompatKind {
|
|
// All vector compares produce scalars except vector pixel and vector bool.
|
|
// The types vector pixel and vector bool return vector results.
|
|
Mixed,
|
|
// All vector compares produce vector results as in GCC.
|
|
GCC,
|
|
// All vector compares produce scalars as in XL.
|
|
XL,
|
|
// Default clang behaviour.
|
|
Default = Mixed,
|
|
};
|
|
|
|
enum class SignReturnAddressScopeKind {
|
|
/// No signing for any function.
|
|
None,
|
|
/// Sign the return address of functions that spill LR.
|
|
NonLeaf,
|
|
/// Sign the return address of all functions,
|
|
All
|
|
};
|
|
|
|
enum class SignReturnAddressKeyKind {
|
|
/// Return address signing uses APIA key.
|
|
AKey,
|
|
/// Return address signing uses APIB key.
|
|
BKey
|
|
};
|
|
|
|
enum class ThreadModelKind {
|
|
/// POSIX Threads.
|
|
POSIX,
|
|
/// Single Threaded Environment.
|
|
Single
|
|
};
|
|
|
|
enum class ExtendArgsKind {
|
|
/// Integer arguments are sign or zero extended to 32/64 bits
|
|
/// during default argument promotions.
|
|
ExtendTo32,
|
|
ExtendTo64
|
|
};
|
|
|
|
enum class GPUDefaultStreamKind {
|
|
/// Legacy default stream
|
|
Legacy,
|
|
/// Per-thread default stream
|
|
PerThread,
|
|
};
|
|
|
|
public:
|
|
/// The used language standard.
|
|
LangStandard::Kind LangStd;
|
|
|
|
/// Set of enabled sanitizers.
|
|
SanitizerSet Sanitize;
|
|
/// Is at least one coverage instrumentation type enabled.
|
|
bool SanitizeCoverage = false;
|
|
|
|
/// Paths to files specifying which objects
|
|
/// (files, functions, variables) should not be instrumented.
|
|
std::vector<std::string> NoSanitizeFiles;
|
|
|
|
/// Paths to the XRay "always instrument" files specifying which
|
|
/// objects (files, functions, variables) should be imbued with the XRay
|
|
/// "always instrument" attribute.
|
|
/// WARNING: This is a deprecated field and will go away in the future.
|
|
std::vector<std::string> XRayAlwaysInstrumentFiles;
|
|
|
|
/// Paths to the XRay "never instrument" files specifying which
|
|
/// objects (files, functions, variables) should be imbued with the XRay
|
|
/// "never instrument" attribute.
|
|
/// WARNING: This is a deprecated field and will go away in the future.
|
|
std::vector<std::string> XRayNeverInstrumentFiles;
|
|
|
|
/// Paths to the XRay attribute list files, specifying which objects
|
|
/// (files, functions, variables) should be imbued with the appropriate XRay
|
|
/// attribute(s).
|
|
std::vector<std::string> XRayAttrListFiles;
|
|
|
|
/// Paths to special case list files specifying which entities
|
|
/// (files, functions) should or should not be instrumented.
|
|
std::vector<std::string> ProfileListFiles;
|
|
|
|
clang::ObjCRuntime ObjCRuntime;
|
|
|
|
CoreFoundationABI CFRuntime = CoreFoundationABI::Unspecified;
|
|
|
|
std::string ObjCConstantStringClass;
|
|
|
|
/// The name of the handler function to be called when -ftrapv is
|
|
/// specified.
|
|
///
|
|
/// If none is specified, abort (GCC-compatible behaviour).
|
|
std::string OverflowHandler;
|
|
|
|
/// The module currently being compiled as specified by -fmodule-name.
|
|
std::string ModuleName;
|
|
|
|
/// The name of the current module, of which the main source file
|
|
/// is a part. If CompilingModule is set, we are compiling the interface
|
|
/// of this module, otherwise we are compiling an implementation file of
|
|
/// it. This starts as ModuleName in case -fmodule-name is provided and
|
|
/// changes during compilation to reflect the current module.
|
|
std::string CurrentModule;
|
|
|
|
/// The names of any features to enable in module 'requires' decls
|
|
/// in addition to the hard-coded list in Module.cpp and the target features.
|
|
///
|
|
/// This list is sorted.
|
|
std::vector<std::string> ModuleFeatures;
|
|
|
|
/// Options for parsing comments.
|
|
CommentOptions CommentOpts;
|
|
|
|
/// A list of all -fno-builtin-* function names (e.g., memset).
|
|
std::vector<std::string> NoBuiltinFuncs;
|
|
|
|
/// A prefix map for __FILE__, __BASE_FILE__ and __builtin_FILE().
|
|
std::map<std::string, std::string, std::greater<std::string>> MacroPrefixMap;
|
|
|
|
/// Triples of the OpenMP targets that the host code codegen should
|
|
/// take into account in order to generate accurate offloading descriptors.
|
|
std::vector<llvm::Triple> OMPTargetTriples;
|
|
|
|
/// Name of the IR file that contains the result of the OpenMP target
|
|
/// host code generation.
|
|
std::string OMPHostIRFile;
|
|
|
|
/// The user provided compilation unit ID, if non-empty. This is used to
|
|
/// externalize static variables which is needed to support accessing static
|
|
/// device variables in host code for single source offloading languages
|
|
/// like CUDA/HIP.
|
|
std::string CUID;
|
|
|
|
/// C++ ABI to compile with, if specified by the frontend through -fc++-abi=.
|
|
/// This overrides the default ABI used by the target.
|
|
llvm::Optional<TargetCXXABI::Kind> CXXABI;
|
|
|
|
/// Indicates whether the front-end is explicitly told that the
|
|
/// input is a header file (i.e. -x c-header).
|
|
bool IsHeaderFile = false;
|
|
|
|
/// The default stream kind used for HIP kernel launching.
|
|
GPUDefaultStreamKind GPUDefaultStream;
|
|
|
|
/// The seed used by the randomize structure layout feature.
|
|
std::string RandstructSeed;
|
|
|
|
LangOptions();
|
|
|
|
/// Set language defaults for the given input language and
|
|
/// language standard in the given LangOptions object.
|
|
///
|
|
/// \param Opts - The LangOptions object to set up.
|
|
/// \param Lang - The input language.
|
|
/// \param T - The target triple.
|
|
/// \param Includes - If the language requires extra headers to be implicitly
|
|
/// included, they will be appended to this list.
|
|
/// \param LangStd - The input language standard.
|
|
static void
|
|
setLangDefaults(LangOptions &Opts, Language Lang, const llvm::Triple &T,
|
|
std::vector<std::string> &Includes,
|
|
LangStandard::Kind LangStd = LangStandard::lang_unspecified);
|
|
|
|
// Define accessors/mutators for language options of enumeration type.
|
|
#define LANGOPT(Name, Bits, Default, Description)
|
|
#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
|
|
Type get##Name() const { return static_cast<Type>(Name); } \
|
|
void set##Name(Type Value) { Name = static_cast<unsigned>(Value); }
|
|
#include "clang/Basic/LangOptions.def"
|
|
|
|
/// Are we compiling a module interface (.cppm or module map)?
|
|
bool isCompilingModule() const {
|
|
return getCompilingModule() != CMK_None;
|
|
}
|
|
|
|
/// Do we need to track the owning module for a local declaration?
|
|
bool trackLocalOwningModule() const {
|
|
return isCompilingModule() || ModulesLocalVisibility;
|
|
}
|
|
|
|
bool isSignedOverflowDefined() const {
|
|
return getSignedOverflowBehavior() == SOB_Defined;
|
|
}
|
|
|
|
bool isSubscriptPointerArithmetic() const {
|
|
return ObjCRuntime.isSubscriptPointerArithmetic() &&
|
|
!ObjCSubscriptingLegacyRuntime;
|
|
}
|
|
|
|
bool isCompatibleWithMSVC(MSVCMajorVersion MajorVersion) const {
|
|
return MSCompatibilityVersion >= MajorVersion * 100000U;
|
|
}
|
|
|
|
/// Reset all of the options that are not considered when building a
|
|
/// module.
|
|
void resetNonModularOptions();
|
|
|
|
/// Is this a libc/libm function that is no longer recognized as a
|
|
/// builtin because a -fno-builtin-* option has been specified?
|
|
bool isNoBuiltinFunc(StringRef Name) const;
|
|
|
|
/// True if any ObjC types may have non-trivial lifetime qualifiers.
|
|
bool allowsNonTrivialObjCLifetimeQualifiers() const {
|
|
return ObjCAutoRefCount || ObjCWeak;
|
|
}
|
|
|
|
bool assumeFunctionsAreConvergent() const {
|
|
return ConvergentFunctions;
|
|
}
|
|
|
|
/// Return the OpenCL C or C++ version as a VersionTuple.
|
|
VersionTuple getOpenCLVersionTuple() const;
|
|
|
|
/// Return the OpenCL version that kernel language is compatible with
|
|
unsigned getOpenCLCompatibleVersion() const;
|
|
|
|
/// Return the OpenCL C or C++ for OpenCL language name and version
|
|
/// as a string.
|
|
std::string getOpenCLVersionString() const;
|
|
|
|
/// Returns true if functions without prototypes or functions with an
|
|
/// identifier list (aka K&R C functions) are not allowed.
|
|
bool requiresStrictPrototypes() const {
|
|
return CPlusPlus || C2x || DisableKNRFunctions;
|
|
}
|
|
|
|
/// Returns true if implicit function declarations are allowed in the current
|
|
/// language mode.
|
|
bool implicitFunctionsAllowed() const {
|
|
return !requiresStrictPrototypes() && !OpenCL;
|
|
}
|
|
|
|
/// Returns true if implicit int is part of the language requirements.
|
|
bool isImplicitIntRequired() const { return !CPlusPlus && !C99; }
|
|
|
|
/// Returns true if implicit int is supported at all.
|
|
bool isImplicitIntAllowed() const { return !CPlusPlus && !C2x; }
|
|
|
|
/// Check if return address signing is enabled.
|
|
bool hasSignReturnAddress() const {
|
|
return getSignReturnAddressScope() != SignReturnAddressScopeKind::None;
|
|
}
|
|
|
|
/// Check if return address signing uses AKey.
|
|
bool isSignReturnAddressWithAKey() const {
|
|
return getSignReturnAddressKey() == SignReturnAddressKeyKind::AKey;
|
|
}
|
|
|
|
/// Check if leaf functions are also signed.
|
|
bool isSignReturnAddressScopeAll() const {
|
|
return getSignReturnAddressScope() == SignReturnAddressScopeKind::All;
|
|
}
|
|
|
|
bool hasSjLjExceptions() const {
|
|
return getExceptionHandling() == ExceptionHandlingKind::SjLj;
|
|
}
|
|
|
|
bool hasSEHExceptions() const {
|
|
return getExceptionHandling() == ExceptionHandlingKind::WinEH;
|
|
}
|
|
|
|
bool hasDWARFExceptions() const {
|
|
return getExceptionHandling() == ExceptionHandlingKind::DwarfCFI;
|
|
}
|
|
|
|
bool hasWasmExceptions() const {
|
|
return getExceptionHandling() == ExceptionHandlingKind::Wasm;
|
|
}
|
|
|
|
bool isSYCL() const { return SYCLIsDevice || SYCLIsHost; }
|
|
|
|
/// Remap path prefix according to -fmacro-prefix-path option.
|
|
void remapPathPrefix(SmallString<256> &Path) const;
|
|
};
|
|
|
|
/// Floating point control options
|
|
class FPOptionsOverride;
|
|
class FPOptions {
|
|
public:
|
|
// We start by defining the layout.
|
|
using storage_type = uint16_t;
|
|
|
|
using RoundingMode = llvm::RoundingMode;
|
|
|
|
static constexpr unsigned StorageBitSize = 8 * sizeof(storage_type);
|
|
|
|
// Define a fake option named "First" so that we have a PREVIOUS even for the
|
|
// real first option.
|
|
static constexpr storage_type FirstShift = 0, FirstWidth = 0;
|
|
#define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \
|
|
static constexpr storage_type NAME##Shift = \
|
|
PREVIOUS##Shift + PREVIOUS##Width; \
|
|
static constexpr storage_type NAME##Width = WIDTH; \
|
|
static constexpr storage_type NAME##Mask = ((1 << NAME##Width) - 1) \
|
|
<< NAME##Shift;
|
|
#include "clang/Basic/FPOptions.def"
|
|
|
|
static constexpr storage_type TotalWidth = 0
|
|
#define OPTION(NAME, TYPE, WIDTH, PREVIOUS) +WIDTH
|
|
#include "clang/Basic/FPOptions.def"
|
|
;
|
|
static_assert(TotalWidth <= StorageBitSize, "Too short type for FPOptions");
|
|
|
|
private:
|
|
storage_type Value;
|
|
|
|
public:
|
|
FPOptions() : Value(0) {
|
|
setFPContractMode(LangOptions::FPM_Off);
|
|
setRoundingMode(static_cast<RoundingMode>(LangOptions::FPR_ToNearest));
|
|
setFPExceptionMode(LangOptions::FPE_Ignore);
|
|
}
|
|
explicit FPOptions(const LangOptions &LO) {
|
|
Value = 0;
|
|
// The language fp contract option FPM_FastHonorPragmas has the same effect
|
|
// as FPM_Fast in frontend. For simplicity, use FPM_Fast uniformly in
|
|
// frontend.
|
|
auto LangOptContractMode = LO.getDefaultFPContractMode();
|
|
if (LangOptContractMode == LangOptions::FPM_FastHonorPragmas)
|
|
LangOptContractMode = LangOptions::FPM_Fast;
|
|
setFPContractMode(LangOptContractMode);
|
|
setRoundingMode(LO.getFPRoundingMode());
|
|
setFPExceptionMode(LO.getFPExceptionMode());
|
|
setAllowFPReassociate(LO.AllowFPReassoc);
|
|
setNoHonorNaNs(LO.NoHonorNaNs);
|
|
setNoHonorInfs(LO.NoHonorInfs);
|
|
setNoSignedZero(LO.NoSignedZero);
|
|
setAllowReciprocal(LO.AllowRecip);
|
|
setAllowApproxFunc(LO.ApproxFunc);
|
|
if (getFPContractMode() == LangOptions::FPM_On &&
|
|
getRoundingMode() == llvm::RoundingMode::Dynamic &&
|
|
getFPExceptionMode() == LangOptions::FPE_Strict)
|
|
// If the FP settings are set to the "strict" model, then
|
|
// FENV access is set to true. (ffp-model=strict)
|
|
setAllowFEnvAccess(true);
|
|
else
|
|
setAllowFEnvAccess(LangOptions::FPM_Off);
|
|
}
|
|
|
|
bool allowFPContractWithinStatement() const {
|
|
return getFPContractMode() == LangOptions::FPM_On;
|
|
}
|
|
void setAllowFPContractWithinStatement() {
|
|
setFPContractMode(LangOptions::FPM_On);
|
|
}
|
|
|
|
bool allowFPContractAcrossStatement() const {
|
|
return getFPContractMode() == LangOptions::FPM_Fast;
|
|
}
|
|
void setAllowFPContractAcrossStatement() {
|
|
setFPContractMode(LangOptions::FPM_Fast);
|
|
}
|
|
|
|
bool isFPConstrained() const {
|
|
return getRoundingMode() != llvm::RoundingMode::NearestTiesToEven ||
|
|
getFPExceptionMode() != LangOptions::FPE_Ignore ||
|
|
getAllowFEnvAccess();
|
|
}
|
|
|
|
bool operator==(FPOptions other) const { return Value == other.Value; }
|
|
|
|
/// Return the default value of FPOptions that's used when trailing
|
|
/// storage isn't required.
|
|
static FPOptions defaultWithoutTrailingStorage(const LangOptions &LO);
|
|
|
|
storage_type getAsOpaqueInt() const { return Value; }
|
|
static FPOptions getFromOpaqueInt(storage_type Value) {
|
|
FPOptions Opts;
|
|
Opts.Value = Value;
|
|
return Opts;
|
|
}
|
|
|
|
// We can define most of the accessors automatically:
|
|
#define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \
|
|
TYPE get##NAME() const { \
|
|
return static_cast<TYPE>((Value & NAME##Mask) >> NAME##Shift); \
|
|
} \
|
|
void set##NAME(TYPE value) { \
|
|
Value = (Value & ~NAME##Mask) | (storage_type(value) << NAME##Shift); \
|
|
}
|
|
#include "clang/Basic/FPOptions.def"
|
|
LLVM_DUMP_METHOD void dump();
|
|
};
|
|
|
|
/// Represents difference between two FPOptions values.
|
|
///
|
|
/// The effect of language constructs changing the set of floating point options
|
|
/// is usually a change of some FP properties while leaving others intact. This
|
|
/// class describes such changes by keeping information about what FP options
|
|
/// are overridden.
|
|
///
|
|
/// The integral set of FP options, described by the class FPOptions, may be
|
|
/// represented as a default FP option set, defined by language standard and
|
|
/// command line options, with the overrides introduced by pragmas.
|
|
///
|
|
/// The is implemented as a value of the new FPOptions plus a mask showing which
|
|
/// fields are actually set in it.
|
|
class FPOptionsOverride {
|
|
FPOptions Options = FPOptions::getFromOpaqueInt(0);
|
|
FPOptions::storage_type OverrideMask = 0;
|
|
|
|
public:
|
|
using RoundingMode = llvm::RoundingMode;
|
|
|
|
/// The type suitable for storing values of FPOptionsOverride. Must be twice
|
|
/// as wide as bit size of FPOption.
|
|
using storage_type = uint32_t;
|
|
static_assert(sizeof(storage_type) >= 2 * sizeof(FPOptions::storage_type),
|
|
"Too short type for FPOptionsOverride");
|
|
|
|
/// Bit mask selecting bits of OverrideMask in serialized representation of
|
|
/// FPOptionsOverride.
|
|
static constexpr storage_type OverrideMaskBits =
|
|
(static_cast<storage_type>(1) << FPOptions::StorageBitSize) - 1;
|
|
|
|
FPOptionsOverride() {}
|
|
FPOptionsOverride(const LangOptions &LO)
|
|
: Options(LO), OverrideMask(OverrideMaskBits) {}
|
|
FPOptionsOverride(FPOptions FPO)
|
|
: Options(FPO), OverrideMask(OverrideMaskBits) {}
|
|
|
|
bool requiresTrailingStorage() const { return OverrideMask != 0; }
|
|
|
|
void setAllowFPContractWithinStatement() {
|
|
setFPContractModeOverride(LangOptions::FPM_On);
|
|
}
|
|
|
|
void setAllowFPContractAcrossStatement() {
|
|
setFPContractModeOverride(LangOptions::FPM_Fast);
|
|
}
|
|
|
|
void setDisallowFPContract() {
|
|
setFPContractModeOverride(LangOptions::FPM_Off);
|
|
}
|
|
|
|
void setFPPreciseEnabled(bool Value) {
|
|
setAllowFPReassociateOverride(!Value);
|
|
setNoHonorNaNsOverride(!Value);
|
|
setNoHonorInfsOverride(!Value);
|
|
setNoSignedZeroOverride(!Value);
|
|
setAllowReciprocalOverride(!Value);
|
|
setAllowApproxFuncOverride(!Value);
|
|
if (Value)
|
|
/* Precise mode implies fp_contract=on and disables ffast-math */
|
|
setAllowFPContractWithinStatement();
|
|
else
|
|
/* Precise mode disabled sets fp_contract=fast and enables ffast-math */
|
|
setAllowFPContractAcrossStatement();
|
|
}
|
|
|
|
storage_type getAsOpaqueInt() const {
|
|
return (static_cast<storage_type>(Options.getAsOpaqueInt())
|
|
<< FPOptions::StorageBitSize) |
|
|
OverrideMask;
|
|
}
|
|
static FPOptionsOverride getFromOpaqueInt(storage_type I) {
|
|
FPOptionsOverride Opts;
|
|
Opts.OverrideMask = I & OverrideMaskBits;
|
|
Opts.Options = FPOptions::getFromOpaqueInt(I >> FPOptions::StorageBitSize);
|
|
return Opts;
|
|
}
|
|
|
|
FPOptions applyOverrides(FPOptions Base) {
|
|
FPOptions Result =
|
|
FPOptions::getFromOpaqueInt((Base.getAsOpaqueInt() & ~OverrideMask) |
|
|
(Options.getAsOpaqueInt() & OverrideMask));
|
|
return Result;
|
|
}
|
|
|
|
FPOptions applyOverrides(const LangOptions &LO) {
|
|
return applyOverrides(FPOptions(LO));
|
|
}
|
|
|
|
bool operator==(FPOptionsOverride other) const {
|
|
return Options == other.Options && OverrideMask == other.OverrideMask;
|
|
}
|
|
bool operator!=(FPOptionsOverride other) const { return !(*this == other); }
|
|
|
|
#define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \
|
|
bool has##NAME##Override() const { \
|
|
return OverrideMask & FPOptions::NAME##Mask; \
|
|
} \
|
|
TYPE get##NAME##Override() const { \
|
|
assert(has##NAME##Override()); \
|
|
return Options.get##NAME(); \
|
|
} \
|
|
void clear##NAME##Override() { \
|
|
/* Clear the actual value so that we don't have spurious differences when \
|
|
* testing equality. */ \
|
|
Options.set##NAME(TYPE(0)); \
|
|
OverrideMask &= ~FPOptions::NAME##Mask; \
|
|
} \
|
|
void set##NAME##Override(TYPE value) { \
|
|
Options.set##NAME(value); \
|
|
OverrideMask |= FPOptions::NAME##Mask; \
|
|
}
|
|
#include "clang/Basic/FPOptions.def"
|
|
LLVM_DUMP_METHOD void dump();
|
|
};
|
|
|
|
/// Describes the kind of translation unit being processed.
|
|
enum TranslationUnitKind {
|
|
/// The translation unit is a complete translation unit.
|
|
TU_Complete,
|
|
|
|
/// The translation unit is a prefix to a translation unit, and is
|
|
/// not complete.
|
|
TU_Prefix,
|
|
|
|
/// The translation unit is a module.
|
|
TU_Module,
|
|
|
|
/// The translation unit is a is a complete translation unit that we might
|
|
/// incrementally extend later.
|
|
TU_Incremental
|
|
};
|
|
|
|
} // namespace clang
|
|
|
|
#endif // LLVM_CLANG_BASIC_LANGOPTIONS_H
|