[YAML] Add an optional argument EnumMask to the yaml::IO::bitSetCase().

Some bit-set fields used in ELF file headers in fact contain two parts.
The first one is a regular bit-field. The second one is an enumeraion.
For example ELF header `e_flags` for MIPS target might contain the
following values:

Bit-set values:

  EF_MIPS_NOREORDER = 0x00000001
  EF_MIPS_PIC       = 0x00000002
  EF_MIPS_CPIC      = 0x00000004
  EF_MIPS_ABI2      = 0x00000020

Enumeration:

  EF_MIPS_ARCH_32   = 0x50000000
  EF_MIPS_ARCH_64   = 0x60000000
  EF_MIPS_ARCH_32R2 = 0x70000000
  EF_MIPS_ARCH_64R2 = 0x80000000

For printing bit-sets we use the `yaml::IO::bitSetCase()`. It does not
support bit-set/enumeration combinations and prints too many flags from
an enumeration part. This patch fixes this problem. New method
`yaml::IO::maskedBitSetCase()` handle "enumeration" part of bitset
defined by provided mask.

Patch reviewed by Nick Kledzik and Sean Silva.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@209504 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Simon Atanasyan 2014-05-23 08:07:09 +00:00
parent 7a0a087f28
commit 84a0dc323d
4 changed files with 70 additions and 19 deletions

View File

@ -399,6 +399,42 @@ the above schema, a same valid YAML document is:
name: Tom
flags: [ pointy, flat ]
Sometimes a "flags" field might contains an enumeration part
defined by a bit-mask.
.. code-block:: c++
enum {
flagsFeatureA = 1,
flagsFeatureB = 2,
flagsFeatureC = 4,
flagsCPUMask = 24,
flagsCPU1 = 8,
flagsCPU2 = 16
};
To support reading and writing such fields, you need to use the maskedBitSet()
method and provide the bit values, their names and the enumeration mask.
.. code-block:: c++
template <>
struct ScalarBitSetTraits<MyFlags> {
static void bitset(IO &io, MyFlags &value) {
io.bitSetCase(value, "featureA", flagsFeatureA);
io.bitSetCase(value, "featureB", flagsFeatureB);
io.bitSetCase(value, "featureC", flagsFeatureC);
io.maskedBitSetCase(value, "CPU1", flagsCPU1, flagsCPUMask);
io.maskedBitSetCase(value, "CPU2", flagsCPU2, flagsCPUMask);
}
};
YAML I/O (when writing) will apply the enumeration mask to the flags field,
and compare the result and values from the bitset. As in case of a regular
bitset, each that matches will cause the corresponding string to be added
to the flow sequence.
Custom Scalar
-------------

View File

@ -487,6 +487,19 @@ public:
}
}
template <typename T>
void maskedBitSetCase(T &Val, const char *Str, T ConstVal, T Mask) {
if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal))
Val = Val | ConstVal;
}
template <typename T>
void maskedBitSetCase(T &Val, const char *Str, uint32_t ConstVal,
uint32_t Mask) {
if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal))
Val = Val | ConstVal;
}
void *getContext();
void setContext(void *);

View File

@ -246,16 +246,17 @@ void ScalarBitSetTraits<ELFYAML::ELF_EF>::bitset(IO &IO,
const auto *Object = static_cast<ELFYAML::Object *>(IO.getContext());
assert(Object && "The IO context is not initialized");
#define BCase(X) IO.bitSetCase(Value, #X, ELF::X);
#define BCaseMask(X, M) IO.maskedBitSetCase(Value, #X, ELF::X, ELF::M);
switch (Object->Header.Machine) {
case ELF::EM_ARM:
BCase(EF_ARM_SOFT_FLOAT)
BCase(EF_ARM_VFP_FLOAT)
BCase(EF_ARM_EABI_UNKNOWN)
BCase(EF_ARM_EABI_VER1)
BCase(EF_ARM_EABI_VER2)
BCase(EF_ARM_EABI_VER3)
BCase(EF_ARM_EABI_VER4)
BCase(EF_ARM_EABI_VER5)
BCaseMask(EF_ARM_EABI_UNKNOWN, EF_ARM_EABIMASK)
BCaseMask(EF_ARM_EABI_VER1, EF_ARM_EABIMASK)
BCaseMask(EF_ARM_EABI_VER2, EF_ARM_EABIMASK)
BCaseMask(EF_ARM_EABI_VER3, EF_ARM_EABIMASK)
BCaseMask(EF_ARM_EABI_VER4, EF_ARM_EABIMASK)
BCaseMask(EF_ARM_EABI_VER5, EF_ARM_EABIMASK)
break;
case ELF::EM_MIPS:
BCase(EF_MIPS_NOREORDER)
@ -266,17 +267,17 @@ void ScalarBitSetTraits<ELFYAML::ELF_EF>::bitset(IO &IO,
BCase(EF_MIPS_ABI_O32)
BCase(EF_MIPS_MICROMIPS)
BCase(EF_MIPS_ARCH_ASE_M16)
BCase(EF_MIPS_ARCH_1)
BCase(EF_MIPS_ARCH_2)
BCase(EF_MIPS_ARCH_3)
BCase(EF_MIPS_ARCH_4)
BCase(EF_MIPS_ARCH_5)
BCase(EF_MIPS_ARCH_32)
BCase(EF_MIPS_ARCH_64)
BCase(EF_MIPS_ARCH_32R2)
BCase(EF_MIPS_ARCH_64R2)
BCase(EF_MIPS_ARCH_32R6)
BCase(EF_MIPS_ARCH_64R6)
BCaseMask(EF_MIPS_ARCH_1, EF_MIPS_ARCH)
BCaseMask(EF_MIPS_ARCH_2, EF_MIPS_ARCH)
BCaseMask(EF_MIPS_ARCH_3, EF_MIPS_ARCH)
BCaseMask(EF_MIPS_ARCH_4, EF_MIPS_ARCH)
BCaseMask(EF_MIPS_ARCH_5, EF_MIPS_ARCH)
BCaseMask(EF_MIPS_ARCH_32, EF_MIPS_ARCH)
BCaseMask(EF_MIPS_ARCH_64, EF_MIPS_ARCH)
BCaseMask(EF_MIPS_ARCH_32R2, EF_MIPS_ARCH)
BCaseMask(EF_MIPS_ARCH_64R2, EF_MIPS_ARCH)
BCaseMask(EF_MIPS_ARCH_32R6, EF_MIPS_ARCH)
BCaseMask(EF_MIPS_ARCH_64R6, EF_MIPS_ARCH)
break;
case ELF::EM_HEXAGON:
BCase(EF_HEXAGON_MACH_V2)
@ -292,6 +293,7 @@ void ScalarBitSetTraits<ELFYAML::ELF_EF>::bitset(IO &IO,
llvm_unreachable("Unsupported architecture");
}
#undef BCase
#undef BCaseMask
}
void ScalarEnumerationTraits<ELFYAML::ELF_SHT>::enumeration(

View File

@ -191,7 +191,7 @@ ELF-MIPSEL-NEXT: Class: ELFCLASS32
ELF-MIPSEL-NEXT: Data: ELFDATA2LSB
ELF-MIPSEL-NEXT: Type: ET_REL
ELF-MIPSEL-NEXT: Machine: EM_MIPS
ELF-MIPSEL-NEXT: Flags: [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_1, EF_MIPS_ARCH_2, EF_MIPS_ARCH_5, EF_MIPS_ARCH_32 ]
ELF-MIPSEL-NEXT: Flags: [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32 ]
ELF-MIPSEL-NEXT: Sections:
ELF-MIPSEL-NEXT: - Name: .text
ELF-MIPSEL-NEXT: Type: SHT_PROGBITS
@ -285,7 +285,7 @@ ELF-MIPS64EL-NEXT: Class: ELFCLASS64
ELF-MIPS64EL-NEXT: Data: ELFDATA2LSB
ELF-MIPS64EL-NEXT: Type: ET_REL
ELF-MIPS64EL-NEXT: Machine: EM_MIPS
ELF-MIPS64EL-NEXT: Flags: [ EF_MIPS_ARCH_1, EF_MIPS_ARCH_3 ]
ELF-MIPS64EL-NEXT: Flags: [ EF_MIPS_ARCH_3 ]
ELF-MIPS64EL-NEXT: Sections:
ELF-MIPS64EL-NEXT: - Name: .text
ELF-MIPS64EL-NEXT: Type: SHT_PROGBITS