Use typedef to represent storage type in FPOption and FPOptionsOverride

Size of FPOption is now 14 bit, which is closed to the current limit
of 16 bits. Adding new properties to FPOption would require change of
the types, which represent storage of FPOption and FPOptionsOverride.
To facilitate this change, the storage types were changed from standard
integer types to typedefs defined inside the proper classes. Checks for
size of these storage types were added.

No functional changes intended.

Differential Revision: https://reviews.llvm.org/D84147
This commit is contained in:
Serge Pavlov 2020-07-20 14:47:45 +07:00
parent b847859f37
commit 21cd7b72a3
4 changed files with 60 additions and 20 deletions

View File

@ -7,7 +7,7 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// This file defines the Floating Point language options. Users of this file // This file defines the Floating Point language options. Users of this file
// must define the FPOPT macro to make use of this information. // must define the OPTION macro to make use of this information.
#ifndef OPTION #ifndef OPTION
# error Define the OPTION macro to handle floating point language options # error Define the OPTION macro to handle floating point language options
#endif #endif

View File

@ -374,6 +374,8 @@ public:
using RoundingMode = llvm::RoundingMode; 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 // Define a fake option named "First" so that we have a PREVIOUS even for the
// real first option. // real first option.
static constexpr storage_type FirstShift = 0, FirstWidth = 0; static constexpr storage_type FirstShift = 0, FirstWidth = 0;
@ -385,6 +387,12 @@ public:
<< NAME##Shift; << NAME##Shift;
#include "clang/Basic/FPOptions.def" #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: private:
storage_type Value; storage_type Value;
@ -402,8 +410,8 @@ public:
setFPContractMode(LO.getDefaultFPContractMode()); setFPContractMode(LO.getDefaultFPContractMode());
setRoundingMode(LO.getFPRoundingMode()); setRoundingMode(LO.getFPRoundingMode());
setFPExceptionMode(LO.getFPExceptionMode()); setFPExceptionMode(LO.getFPExceptionMode());
setAllowFEnvAccess(LangOptions::FPM_Off), setAllowFEnvAccess(LangOptions::FPM_Off);
setAllowFPReassociate(LO.AllowFPReassoc); setAllowFPReassociate(LO.AllowFPReassoc);
setNoHonorNaNs(LO.NoHonorNaNs); setNoHonorNaNs(LO.NoHonorNaNs);
setNoHonorInfs(LO.NoHonorInfs); setNoHonorInfs(LO.NoHonorInfs);
setNoSignedZero(LO.NoSignedZero); setNoSignedZero(LO.NoSignedZero);
@ -453,18 +461,45 @@ public:
LLVM_DUMP_METHOD void dump(); LLVM_DUMP_METHOD void dump();
}; };
/// The FPOptions override type is value of the new FPOptions /// Represents difference between two FPOptions values.
/// plus a mask showing which fields are actually set in it: ///
/// 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 { class FPOptionsOverride {
FPOptions Options; FPOptions Options;
FPOptions::storage_type OverrideMask = 0; FPOptions::storage_type OverrideMask = 0;
public: public:
using RoundingMode = llvm::RoundingMode; 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() {}
FPOptionsOverride(FPOptions::storage_type Value, FPOptions::storage_type Mask)
: Options(Value), OverrideMask(Mask) {}
FPOptionsOverride(const LangOptions &LO)
: Options(LO), OverrideMask(OverrideMaskBits) {}
// Used for serializing. // Used for serializing.
explicit FPOptionsOverride(unsigned I) { getFromOpaqueInt(I); } explicit FPOptionsOverride(storage_type I) { getFromOpaqueInt(I); }
bool requiresTrailingStorage() const { return OverrideMask != 0; } bool requiresTrailingStorage() const { return OverrideMask != 0; }
@ -495,19 +530,24 @@ public:
setAllowFPContractAcrossStatement(); setAllowFPContractAcrossStatement();
} }
unsigned getAsOpaqueInt() const { storage_type getAsOpaqueInt() const {
return Options.getAsOpaqueInt() << 16 | OverrideMask; return (static_cast<storage_type>(Options.getAsOpaqueInt())
<< FPOptions::StorageBitSize) |
OverrideMask;
} }
void getFromOpaqueInt(unsigned I) { void getFromOpaqueInt(storage_type I) {
OverrideMask = I & 0xffff; OverrideMask = I & OverrideMaskBits;
Options.getFromOpaqueInt(I >> 16); Options.getFromOpaqueInt(I >> FPOptions::StorageBitSize);
}
FPOptions applyOverrides(FPOptions Base) {
FPOptions Result((Base.getAsOpaqueInt() & ~OverrideMask) |
(Options.getAsOpaqueInt() & OverrideMask));
return Result;
} }
FPOptions applyOverrides(const LangOptions &LO) { FPOptions applyOverrides(const LangOptions &LO) {
FPOptions Base(LO); return applyOverrides(FPOptions(LO));
FPOptions result((Base.getAsOpaqueInt() & ~OverrideMask) |
(Options.getAsOpaqueInt() & OverrideMask));
return result;
} }
bool operator==(FPOptionsOverride other) const { bool operator==(FPOptionsOverride other) const {

View File

@ -587,7 +587,7 @@ public:
PragmaStack<StringLiteral *> CodeSegStack; PragmaStack<StringLiteral *> CodeSegStack;
// This stack tracks the current state of Sema.CurFPFeatures. // This stack tracks the current state of Sema.CurFPFeatures.
PragmaStack<unsigned> FpPragmaStack; PragmaStack<FPOptionsOverride::storage_type> FpPragmaStack;
FPOptionsOverride CurFPFeatureOverrides() { FPOptionsOverride CurFPFeatureOverrides() {
FPOptionsOverride result; FPOptionsOverride result;
if (!FpPragmaStack.hasValue()) { if (!FpPragmaStack.hasValue()) {
@ -1405,12 +1405,12 @@ public:
S.CurFPFeatures = OldFPFeaturesState; S.CurFPFeatures = OldFPFeaturesState;
S.FpPragmaStack.CurrentValue = OldOverrides; S.FpPragmaStack.CurrentValue = OldOverrides;
} }
unsigned getOverrides() { return OldOverrides; } FPOptionsOverride::storage_type getOverrides() { return OldOverrides; }
private: private:
Sema& S; Sema& S;
FPOptions OldFPFeaturesState; FPOptions OldFPFeaturesState;
unsigned OldOverrides; FPOptionsOverride::storage_type OldOverrides;
}; };
void addImplicitTypedef(StringRef Name, QualType T); void addImplicitTypedef(StringRef Name, QualType T);

View File

@ -858,10 +858,10 @@ private:
SourceLocation PointersToMembersPragmaLocation; SourceLocation PointersToMembersPragmaLocation;
/// The pragma float_control state. /// The pragma float_control state.
Optional<unsigned> FpPragmaCurrentValue; Optional<FPOptionsOverride::storage_type> FpPragmaCurrentValue;
SourceLocation FpPragmaCurrentLocation; SourceLocation FpPragmaCurrentLocation;
struct FpPragmaStackEntry { struct FpPragmaStackEntry {
unsigned Value; FPOptionsOverride::storage_type Value;
SourceLocation Location; SourceLocation Location;
SourceLocation PushLocation; SourceLocation PushLocation;
StringRef SlotLabel; StringRef SlotLabel;