forked from OSchip/llvm-project
Revert "[clang][cli] Port ObjCMTAction to new option parsing system"
This reverts commit 09248a5d25
.
Some builds are broken. I suspect a `static constexpr` in a class missing a
definition out of class (required pre-c++17).
This commit is contained in:
parent
dd8723d348
commit
f917356f9c
|
@ -340,53 +340,36 @@ def ccc_objcmt_migrate : Separate<["-"], "ccc-objcmt-migrate">,
|
|||
InternalDriverOpt,
|
||||
HelpText<"Apply modifications and produces temporary files to migrate to "
|
||||
"modern ObjC syntax">;
|
||||
|
||||
def objcmt_migrate_literals : Flag<["-"], "objcmt-migrate-literals">, Flags<[CC1Option]>,
|
||||
HelpText<"Enable migration to modern ObjC literals">,
|
||||
MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_Literals">;
|
||||
HelpText<"Enable migration to modern ObjC literals">;
|
||||
def objcmt_migrate_subscripting : Flag<["-"], "objcmt-migrate-subscripting">, Flags<[CC1Option]>,
|
||||
HelpText<"Enable migration to modern ObjC subscripting">,
|
||||
MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_Subscripting">;
|
||||
HelpText<"Enable migration to modern ObjC subscripting">;
|
||||
def objcmt_migrate_property : Flag<["-"], "objcmt-migrate-property">, Flags<[CC1Option]>,
|
||||
HelpText<"Enable migration to modern ObjC property">,
|
||||
MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_Property">;
|
||||
HelpText<"Enable migration to modern ObjC property">;
|
||||
def objcmt_migrate_all : Flag<["-"], "objcmt-migrate-all">, Flags<[CC1Option]>,
|
||||
HelpText<"Enable migration to modern ObjC">,
|
||||
MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_MigrateDecls">;
|
||||
HelpText<"Enable migration to modern ObjC">;
|
||||
def objcmt_migrate_readonly_property : Flag<["-"], "objcmt-migrate-readonly-property">, Flags<[CC1Option]>,
|
||||
HelpText<"Enable migration to modern ObjC readonly property">,
|
||||
MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_ReadonlyProperty">;
|
||||
HelpText<"Enable migration to modern ObjC readonly property">;
|
||||
def objcmt_migrate_readwrite_property : Flag<["-"], "objcmt-migrate-readwrite-property">, Flags<[CC1Option]>,
|
||||
HelpText<"Enable migration to modern ObjC readwrite property">,
|
||||
MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_ReadwriteProperty">;
|
||||
HelpText<"Enable migration to modern ObjC readwrite property">;
|
||||
def objcmt_migrate_property_dot_syntax : Flag<["-"], "objcmt-migrate-property-dot-syntax">, Flags<[CC1Option]>,
|
||||
HelpText<"Enable migration of setter/getter messages to property-dot syntax">,
|
||||
MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_PropertyDotSyntax">;
|
||||
HelpText<"Enable migration of setter/getter messages to property-dot syntax">;
|
||||
def objcmt_migrate_annotation : Flag<["-"], "objcmt-migrate-annotation">, Flags<[CC1Option]>,
|
||||
HelpText<"Enable migration to property and method annotations">,
|
||||
MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_Annotation">;
|
||||
HelpText<"Enable migration to property and method annotations">;
|
||||
def objcmt_migrate_instancetype : Flag<["-"], "objcmt-migrate-instancetype">, Flags<[CC1Option]>,
|
||||
HelpText<"Enable migration to infer instancetype for method result type">,
|
||||
MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_Instancetype">;
|
||||
HelpText<"Enable migration to infer instancetype for method result type">;
|
||||
def objcmt_migrate_nsmacros : Flag<["-"], "objcmt-migrate-ns-macros">, Flags<[CC1Option]>,
|
||||
HelpText<"Enable migration to NS_ENUM/NS_OPTIONS macros">,
|
||||
MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_NsMacros">;
|
||||
HelpText<"Enable migration to NS_ENUM/NS_OPTIONS macros">;
|
||||
def objcmt_migrate_protocol_conformance : Flag<["-"], "objcmt-migrate-protocol-conformance">, Flags<[CC1Option]>,
|
||||
HelpText<"Enable migration to add protocol conformance on classes">,
|
||||
MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_ProtocolConformance">;
|
||||
HelpText<"Enable migration to add protocol conformance on classes">;
|
||||
def objcmt_atomic_property : Flag<["-"], "objcmt-atomic-property">, Flags<[CC1Option]>,
|
||||
HelpText<"Make migration to 'atomic' properties">,
|
||||
MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_AtomicProperty">;
|
||||
HelpText<"Make migration to 'atomic' properties">;
|
||||
def objcmt_returns_innerpointer_property : Flag<["-"], "objcmt-returns-innerpointer-property">, Flags<[CC1Option]>,
|
||||
HelpText<"Enable migration to annotate property with NS_RETURNS_INNER_POINTER">,
|
||||
MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_ReturnsInnerPointerProperty">;
|
||||
HelpText<"Enable migration to annotate property with NS_RETURNS_INNER_POINTER">;
|
||||
def objcmt_ns_nonatomic_iosonly: Flag<["-"], "objcmt-ns-nonatomic-iosonly">, Flags<[CC1Option]>,
|
||||
HelpText<"Enable migration to use NS_NONATOMIC_IOSONLY macro for setting property's 'atomic' attribute">,
|
||||
MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_NsAtomicIOSOnlyProperty">;
|
||||
HelpText<"Enable migration to use NS_NONATOMIC_IOSONLY macro for setting property's 'atomic' attribute">;
|
||||
def objcmt_migrate_designated_init : Flag<["-"], "objcmt-migrate-designated-init">, Flags<[CC1Option]>,
|
||||
HelpText<"Enable migration to infer NS_DESIGNATED_INITIALIZER for initializer methods">,
|
||||
MarshallingInfoBitfieldFlag<"FrontendOpts.ObjCMTAction", "FrontendOptions::ObjCMT_DesignatedInitializer">;
|
||||
|
||||
HelpText<"Enable migration to infer NS_DESIGNATED_INITIALIZER for initializer methods">;
|
||||
def objcmt_whitelist_dir_path: Joined<["-"], "objcmt-whitelist-dir-path=">, Flags<[CC1Option]>,
|
||||
HelpText<"Only modify files with a filename contained in the provided directory path">;
|
||||
// The misspelt "white-list" [sic] alias is due for removal.
|
||||
|
|
|
@ -125,24 +125,6 @@ CompilerInvocationBase::~CompilerInvocationBase() = default;
|
|||
#include "clang/Driver/Options.inc"
|
||||
#undef SIMPLE_ENUM_VALUE_TABLE
|
||||
|
||||
static llvm::Optional<bool> normalizeSimpleFlag(OptSpecifier Opt,
|
||||
unsigned TableIndex,
|
||||
const ArgList &Args,
|
||||
DiagnosticsEngine &Diags) {
|
||||
if (Args.hasArg(Opt))
|
||||
return true;
|
||||
return None;
|
||||
}
|
||||
|
||||
template <typename T, T Value>
|
||||
static llvm::Optional<T>
|
||||
normalizeFlagToValue(OptSpecifier Opt, unsigned TableIndex, const ArgList &Args,
|
||||
DiagnosticsEngine &Diags) {
|
||||
if (Args.hasArg(Opt))
|
||||
return Value;
|
||||
return None;
|
||||
}
|
||||
|
||||
static llvm::Optional<unsigned> normalizeSimpleEnum(OptSpecifier Opt,
|
||||
unsigned TableIndex,
|
||||
const ArgList &Args,
|
||||
|
@ -164,26 +146,22 @@ static llvm::Optional<unsigned> normalizeSimpleEnum(OptSpecifier Opt,
|
|||
return None;
|
||||
}
|
||||
|
||||
static void denormalizeSimpleEnum(SmallVectorImpl<const char *> &Args,
|
||||
CompilerInvocation::StringAllocator SA,
|
||||
unsigned TableIndex, unsigned Value) {
|
||||
static const char *denormalizeSimpleEnum(CompilerInvocation::StringAllocator SA,
|
||||
unsigned TableIndex, unsigned Value) {
|
||||
assert(TableIndex < SimpleEnumValueTablesSize);
|
||||
const SimpleEnumValueTable &Table = SimpleEnumValueTables[TableIndex];
|
||||
for (int I = 0, E = Table.Size; I != E; ++I) {
|
||||
if (Value == Table.Table[I].Value) {
|
||||
Args.push_back(Table.Table[I].Name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (int I = 0, E = Table.Size; I != E; ++I)
|
||||
if (Value == Table.Table[I].Value)
|
||||
return Table.Table[I].Name;
|
||||
|
||||
llvm_unreachable("The simple enum value was not correctly defined in "
|
||||
"the tablegen option description");
|
||||
}
|
||||
|
||||
static void denormalizeString(SmallVectorImpl<const char *> &Args,
|
||||
CompilerInvocation::StringAllocator SA,
|
||||
unsigned TableIndex, const std::string &Value) {
|
||||
Args.push_back(SA(Value));
|
||||
static const char *denormalizeString(CompilerInvocation::StringAllocator SA,
|
||||
unsigned TableIndex,
|
||||
const std::string &Value) {
|
||||
return SA(Value);
|
||||
}
|
||||
|
||||
static Optional<std::string> normalizeTriple(OptSpecifier Opt, int TableIndex,
|
||||
|
@ -195,24 +173,6 @@ static Optional<std::string> normalizeTriple(OptSpecifier Opt, int TableIndex,
|
|||
return llvm::Triple::normalize(Arg->getValue());
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
static T mergeForwardValue(T KeyPath, U Value) {
|
||||
return Value;
|
||||
}
|
||||
|
||||
template <typename T, typename U> static T mergeMaskValue(T KeyPath, U Value) {
|
||||
return KeyPath | Value;
|
||||
}
|
||||
|
||||
template <typename T> static T extractForwardValue(T KeyPath) {
|
||||
return KeyPath;
|
||||
}
|
||||
|
||||
template <typename T, typename U, U Value>
|
||||
static T extractMaskValue(T KeyPath) {
|
||||
return KeyPath & Value;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Deserialization (from args)
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -2050,6 +2010,37 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
|
|||
Opts.ARCMTMigrateEmitARCErrors
|
||||
= Args.hasArg(OPT_arcmt_migrate_emit_arc_errors);
|
||||
|
||||
if (Args.hasArg(OPT_objcmt_migrate_literals))
|
||||
Opts.ObjCMTAction |= FrontendOptions::ObjCMT_Literals;
|
||||
if (Args.hasArg(OPT_objcmt_migrate_subscripting))
|
||||
Opts.ObjCMTAction |= FrontendOptions::ObjCMT_Subscripting;
|
||||
if (Args.hasArg(OPT_objcmt_migrate_property_dot_syntax))
|
||||
Opts.ObjCMTAction |= FrontendOptions::ObjCMT_PropertyDotSyntax;
|
||||
if (Args.hasArg(OPT_objcmt_migrate_property))
|
||||
Opts.ObjCMTAction |= FrontendOptions::ObjCMT_Property;
|
||||
if (Args.hasArg(OPT_objcmt_migrate_readonly_property))
|
||||
Opts.ObjCMTAction |= FrontendOptions::ObjCMT_ReadonlyProperty;
|
||||
if (Args.hasArg(OPT_objcmt_migrate_readwrite_property))
|
||||
Opts.ObjCMTAction |= FrontendOptions::ObjCMT_ReadwriteProperty;
|
||||
if (Args.hasArg(OPT_objcmt_migrate_annotation))
|
||||
Opts.ObjCMTAction |= FrontendOptions::ObjCMT_Annotation;
|
||||
if (Args.hasArg(OPT_objcmt_returns_innerpointer_property))
|
||||
Opts.ObjCMTAction |= FrontendOptions::ObjCMT_ReturnsInnerPointerProperty;
|
||||
if (Args.hasArg(OPT_objcmt_migrate_instancetype))
|
||||
Opts.ObjCMTAction |= FrontendOptions::ObjCMT_Instancetype;
|
||||
if (Args.hasArg(OPT_objcmt_migrate_nsmacros))
|
||||
Opts.ObjCMTAction |= FrontendOptions::ObjCMT_NsMacros;
|
||||
if (Args.hasArg(OPT_objcmt_migrate_protocol_conformance))
|
||||
Opts.ObjCMTAction |= FrontendOptions::ObjCMT_ProtocolConformance;
|
||||
if (Args.hasArg(OPT_objcmt_atomic_property))
|
||||
Opts.ObjCMTAction |= FrontendOptions::ObjCMT_AtomicProperty;
|
||||
if (Args.hasArg(OPT_objcmt_ns_nonatomic_iosonly))
|
||||
Opts.ObjCMTAction |= FrontendOptions::ObjCMT_NsAtomicIOSOnlyProperty;
|
||||
if (Args.hasArg(OPT_objcmt_migrate_designated_init))
|
||||
Opts.ObjCMTAction |= FrontendOptions::ObjCMT_DesignatedInitializer;
|
||||
if (Args.hasArg(OPT_objcmt_migrate_all))
|
||||
Opts.ObjCMTAction |= FrontendOptions::ObjCMT_MigrateDecls;
|
||||
|
||||
Opts.ObjCMTWhiteListPath =
|
||||
std::string(Args.getLastArgValue(OPT_objcmt_whitelist_dir_path));
|
||||
|
||||
|
@ -3734,18 +3725,26 @@ static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args,
|
|||
|
||||
bool CompilerInvocation::parseSimpleArgs(const ArgList &Args,
|
||||
DiagnosticsEngine &Diags) {
|
||||
#define OPTION_WITH_MARSHALLING( \
|
||||
#define OPTION_WITH_MARSHALLING_FLAG(PREFIX_TYPE, NAME, ID, KIND, GROUP, \
|
||||
ALIAS, ALIASARGS, FLAGS, PARAM, HELPTEXT, \
|
||||
METAVAR, VALUES, SPELLING, ALWAYS_EMIT, \
|
||||
KEYPATH, DEFAULT_VALUE, IS_POSITIVE) \
|
||||
this->KEYPATH = (Args.hasArg(OPT_##ID) && IS_POSITIVE) || (DEFAULT_VALUE);
|
||||
|
||||
#define OPTION_WITH_MARSHALLING_STRING( \
|
||||
PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
|
||||
HELPTEXT, METAVAR, VALUES, SPELLING, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, \
|
||||
TYPE, NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX) \
|
||||
TYPE, NORMALIZER, DENORMALIZER, TABLE_INDEX) \
|
||||
{ \
|
||||
this->KEYPATH = MERGER(this->KEYPATH, DEFAULT_VALUE); \
|
||||
if (auto MaybeValue = NORMALIZER(OPT_##ID, TABLE_INDEX, Args, Diags)) \
|
||||
this->KEYPATH = MERGER(this->KEYPATH, static_cast<TYPE>(*MaybeValue)); \
|
||||
this->KEYPATH = static_cast<TYPE>(*MaybeValue); \
|
||||
else \
|
||||
this->KEYPATH = DEFAULT_VALUE; \
|
||||
}
|
||||
|
||||
#include "clang/Driver/Options.inc"
|
||||
#undef OPTION_WITH_MARSHALLING
|
||||
#undef OPTION_WITH_MARSHALLING_STRING
|
||||
#undef OPTION_WITH_MARSHALLING_FLAG
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -4000,23 +3999,29 @@ std::string CompilerInvocation::getModuleHash() const {
|
|||
|
||||
void CompilerInvocation::generateCC1CommandLine(
|
||||
SmallVectorImpl<const char *> &Args, StringAllocator SA) const {
|
||||
#define OPTION_WITH_MARSHALLING( \
|
||||
#define OPTION_WITH_MARSHALLING_FLAG(PREFIX_TYPE, NAME, ID, KIND, GROUP, \
|
||||
ALIAS, ALIASARGS, FLAGS, PARAM, HELPTEXT, \
|
||||
METAVAR, VALUES, SPELLING, ALWAYS_EMIT, \
|
||||
KEYPATH, DEFAULT_VALUE, IS_POSITIVE) \
|
||||
if ((FLAGS) & options::CC1Option && \
|
||||
(ALWAYS_EMIT || this->KEYPATH != (DEFAULT_VALUE))) \
|
||||
Args.push_back(SPELLING);
|
||||
|
||||
#define OPTION_WITH_MARSHALLING_STRING( \
|
||||
PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
|
||||
HELPTEXT, METAVAR, VALUES, SPELLING, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, \
|
||||
TYPE, NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX) \
|
||||
NORMALIZER_RET_TY, NORMALIZER, DENORMALIZER, TABLE_INDEX) \
|
||||
if (((FLAGS) & options::CC1Option) && \
|
||||
(ALWAYS_EMIT || EXTRACTOR(this->KEYPATH) != (DEFAULT_VALUE))) { \
|
||||
if (Option::KIND##Class == Option::FlagClass) { \
|
||||
Args.push_back(SPELLING); \
|
||||
} \
|
||||
(ALWAYS_EMIT || this->KEYPATH != DEFAULT_VALUE)) { \
|
||||
if (Option::KIND##Class == Option::SeparateClass) { \
|
||||
Args.push_back(SPELLING); \
|
||||
DENORMALIZER(Args, SA, TABLE_INDEX, EXTRACTOR(this->KEYPATH)); \
|
||||
Args.push_back(DENORMALIZER(SA, TABLE_INDEX, this->KEYPATH)); \
|
||||
} \
|
||||
}
|
||||
|
||||
#include "clang/Driver/Options.inc"
|
||||
#undef OPTION_WITH_MARSHALLING
|
||||
#undef OPTION_WITH_MARSHALLING_STRING
|
||||
#undef OPTION_WITH_MARSHALLING_FLAG
|
||||
}
|
||||
|
||||
namespace clang {
|
||||
|
|
|
@ -97,15 +97,17 @@ class Option<list<string> prefixes, string name, OptionKind kind> {
|
|||
OptionGroup Group = ?;
|
||||
Option Alias = ?;
|
||||
list<string> AliasArgs = [];
|
||||
string MarshallingKind = ?;
|
||||
code KeyPath = ?;
|
||||
code DefaultValue = ?;
|
||||
bit ShouldAlwaysEmit = 0;
|
||||
// Used by the Flag option kind.
|
||||
bit IsPositive = 1;
|
||||
// Used by the String option kind.
|
||||
code NormalizerRetTy = ?;
|
||||
code NormalizedValuesScope = "";
|
||||
code Normalizer = "";
|
||||
code Denormalizer = "";
|
||||
code ValueMerger = "mergeForwardValue";
|
||||
code ValueExtractor = "extractForwardValue";
|
||||
list<code> NormalizedValues = ?;
|
||||
}
|
||||
|
||||
|
@ -142,39 +144,29 @@ class ValuesCode<code valuecode> { code ValuesCode = valuecode; }
|
|||
|
||||
// Helpers for defining marshalling information.
|
||||
|
||||
class DefaultAnyOf<list<Option> options, string default = "false", string separator = " || "> {
|
||||
code DefaultValue = !foldl(default, options, accumulator, option,
|
||||
!strconcat(accumulator, separator, !cast<string>(option.KeyPath)));
|
||||
class DefaultAnyOf<list<Option> defaults> {
|
||||
code DefaultValue = !foldl("false", defaults, accumulator, option,
|
||||
!strconcat(accumulator, " || ", !cast<string>(option.KeyPath)));
|
||||
}
|
||||
|
||||
class MarshallingInfo<code keypath, code defaultvalue> {
|
||||
code KeyPath = keypath;
|
||||
code DefaultValue = defaultvalue;
|
||||
}
|
||||
|
||||
class MarshallingInfoString<code keypath, code defaultvalue, code normalizerretty>
|
||||
: MarshallingInfo<keypath, defaultvalue> {
|
||||
string MarshallingKind = "string";
|
||||
code NormalizerRetTy = normalizerretty;
|
||||
}
|
||||
|
||||
class MarshallingInfoFlag<code keypath, DefaultAnyOf defaults = DefaultAnyOf<[]>, code ty="unsigned">
|
||||
class MarshallingInfoFlag<code keypath, DefaultAnyOf defaults = DefaultAnyOf<[]>>
|
||||
: MarshallingInfo<keypath, defaults.DefaultValue> {
|
||||
code NormalizerRetTy = ty;
|
||||
code Normalizer = "normalizeSimpleFlag";
|
||||
}
|
||||
|
||||
class MarshallingInfoBitfieldFlag<code keypath, code value>
|
||||
: MarshallingInfoFlag<keypath, DefaultAnyOf<[], "0u", " | ">, "unsigned"> {
|
||||
code Normalizer = "(normalizeFlagToValue<unsigned, "#value#">)";
|
||||
code ValueMerger = "mergeMaskValue";
|
||||
code ValueExtractor = "(extractMaskValue<unsigned, decltype("#value#"), "#value#">)";
|
||||
string MarshallingKind = "flag";
|
||||
}
|
||||
|
||||
// Mixins for additional marshalling attributes.
|
||||
|
||||
class IsNegative {
|
||||
// todo: create & apply a normalizer for negative flags
|
||||
}
|
||||
class IsNegative { bit IsPositive = 0; }
|
||||
class AlwaysEmit { bit ShouldAlwaysEmit = 1; }
|
||||
class Normalizer<code normalizer> { code Normalizer = normalizer; }
|
||||
class Denormalizer<code denormalizer> { code Denormalizer = denormalizer; }
|
||||
|
@ -185,8 +177,6 @@ class AutoNormalizeEnum {
|
|||
code Normalizer = "normalizeSimpleEnum";
|
||||
code Denormalizer = "denormalizeSimpleEnum";
|
||||
}
|
||||
class ValueMerger<code merger> { code ValueMerger = merger; }
|
||||
class ValueExtractor<code extractor> { code ValueExtractor = extractor; }
|
||||
|
||||
// Predefined options.
|
||||
|
||||
|
|
|
@ -15,33 +15,33 @@ struct OptionWithMarshallingInfo {
|
|||
};
|
||||
|
||||
static const OptionWithMarshallingInfo MarshallingTable[] = {
|
||||
#define OPTION_WITH_MARSHALLING( \
|
||||
PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
|
||||
HELPTEXT, METAVAR, VALUES, SPELLING, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE, \
|
||||
TYPE, NORMALIZER, DENORMALIZER, MERGER, EXTRACTOR, TABLE_INDEX) \
|
||||
{NAME, #KEYPATH, #DEFAULT_VALUE},
|
||||
#define OPTION_WITH_MARSHALLING_FLAG(PREFIX_TYPE, NAME, ID, KIND, GROUP, \
|
||||
ALIAS, ALIASARGS, FLAGS, PARAM, HELPTEXT, \
|
||||
METAVAR, VALUES, SPELLING, ALWAYS_EMIT, \
|
||||
KEYPATH, DEFAULT_VALUE, IS_POSITIVE) \
|
||||
{ NAME, #KEYPATH, #DEFAULT_VALUE },
|
||||
#include "Opts.inc"
|
||||
#undef OPTION_WITH_MARSHALLING
|
||||
#undef OPTION_WITH_MARSHALLING_FLAG
|
||||
};
|
||||
|
||||
TEST(OptionMarshalling, EmittedOrderSameAsDefinitionOrder) {
|
||||
ASSERT_STREQ(MarshallingTable[0].Name, "marshalled-flag-d");
|
||||
ASSERT_STREQ(MarshallingTable[1].Name, "marshalled-flag-c");
|
||||
ASSERT_STREQ(MarshallingTable[2].Name, "marshalled-flag-b");
|
||||
ASSERT_STREQ(MarshallingTable[3].Name, "marshalled-flag-a");
|
||||
ASSERT_STREQ(MarshallingTable[0].Name, "marshalled-flag-0");
|
||||
ASSERT_STREQ(MarshallingTable[1].Name, "marshalled-flag-1");
|
||||
ASSERT_STREQ(MarshallingTable[2].Name, "marshalled-flag-2");
|
||||
ASSERT_STREQ(MarshallingTable[3].Name, "marshalled-flag-3");
|
||||
}
|
||||
|
||||
TEST(OptionMarshalling, EmittedSpecifiedKeyPath) {
|
||||
ASSERT_STREQ(MarshallingTable[0].KeyPath, "MarshalledFlagD");
|
||||
ASSERT_STREQ(MarshallingTable[1].KeyPath, "MarshalledFlagC");
|
||||
ASSERT_STREQ(MarshallingTable[2].KeyPath, "MarshalledFlagB");
|
||||
ASSERT_STREQ(MarshallingTable[3].KeyPath, "MarshalledFlagA");
|
||||
ASSERT_STREQ(MarshallingTable[0].KeyPath, "MarshalledFlag0");
|
||||
ASSERT_STREQ(MarshallingTable[1].KeyPath, "MarshalledFlag1");
|
||||
ASSERT_STREQ(MarshallingTable[2].KeyPath, "MarshalledFlag2");
|
||||
ASSERT_STREQ(MarshallingTable[3].KeyPath, "MarshalledFlag3");
|
||||
}
|
||||
|
||||
TEST(OptionMarshalling, DefaultAnyOfConstructedDisjunctionOfKeypaths) {
|
||||
ASSERT_STREQ(MarshallingTable[0].DefaultValue, "false");
|
||||
ASSERT_STREQ(MarshallingTable[1].DefaultValue, "false || MarshalledFlagD");
|
||||
ASSERT_STREQ(MarshallingTable[2].DefaultValue, "false || MarshalledFlagD");
|
||||
ASSERT_STREQ(MarshallingTable[1].DefaultValue, "false || MarshalledFlag0");
|
||||
ASSERT_STREQ(MarshallingTable[2].DefaultValue, "false || MarshalledFlag0");
|
||||
ASSERT_STREQ(MarshallingTable[3].DefaultValue,
|
||||
"false || MarshalledFlagC || MarshalledFlagB");
|
||||
"false || MarshalledFlag1 || MarshalledFlag2");
|
||||
}
|
||||
|
|
|
@ -45,11 +45,11 @@ def Blurmpq_eq : Flag<["--"], "blurmp=">;
|
|||
|
||||
def DashDash : Option<["--"], "", KIND_REMAINING_ARGS>;
|
||||
|
||||
def marshalled_flag_d : Flag<["-"], "marshalled-flag-d">,
|
||||
MarshallingInfoFlag<"MarshalledFlagD", DefaultAnyOf<[]>>;
|
||||
def marshalled_flag_c : Flag<["-"], "marshalled-flag-c">,
|
||||
MarshallingInfoFlag<"MarshalledFlagC", DefaultAnyOf<[marshalled_flag_d]>>;
|
||||
def marshalled_flag_b : Flag<["-"], "marshalled-flag-b">,
|
||||
MarshallingInfoFlag<"MarshalledFlagB", DefaultAnyOf<[marshalled_flag_d]>>;
|
||||
def marshalled_flag_a : Flag<["-"], "marshalled-flag-a">,
|
||||
MarshallingInfoFlag<"MarshalledFlagA", DefaultAnyOf<[marshalled_flag_c, marshalled_flag_b]>>;
|
||||
def marshalled_flag_0 : Flag<["-"], "marshalled-flag-0">,
|
||||
MarshallingInfoFlag<"MarshalledFlag0", DefaultAnyOf<[]>>;
|
||||
def marshalled_flag_1 : Flag<["-"], "marshalled-flag-1">,
|
||||
MarshallingInfoFlag<"MarshalledFlag1", DefaultAnyOf<[marshalled_flag_0]>>;
|
||||
def marshalled_flag_2 : Flag<["-"], "marshalled-flag-2">,
|
||||
MarshallingInfoFlag<"MarshalledFlag2", DefaultAnyOf<[marshalled_flag_0]>>;
|
||||
def marshalled_flag_3 : Flag<["-"], "marshalled-flag-3">,
|
||||
MarshallingInfoFlag<"MarshalledFlag3", DefaultAnyOf<[marshalled_flag_1, marshalled_flag_2]>>;
|
||||
|
|
|
@ -61,20 +61,74 @@ static void emitNameUsingSpelling(raw_ostream &OS, const Record &R) {
|
|||
OS << "[" << PrefixLength << "]";
|
||||
}
|
||||
|
||||
class MarshallingInfo {
|
||||
class MarshallingKindInfo {
|
||||
public:
|
||||
static constexpr const char *MacroName = "OPTION_WITH_MARSHALLING";
|
||||
|
||||
const Record &R;
|
||||
const char *MacroName;
|
||||
bool ShouldAlwaysEmit;
|
||||
StringRef KeyPath;
|
||||
StringRef DefaultValue;
|
||||
StringRef NormalizedValuesScope;
|
||||
|
||||
void emit(raw_ostream &OS) const {
|
||||
write_cstring(OS, StringRef(getOptionSpelling(R)));
|
||||
OS << ", ";
|
||||
OS << ShouldAlwaysEmit;
|
||||
OS << ", ";
|
||||
OS << KeyPath;
|
||||
OS << ", ";
|
||||
emitScopedNormalizedValue(OS, DefaultValue);
|
||||
OS << ", ";
|
||||
emitSpecific(OS);
|
||||
}
|
||||
|
||||
virtual Optional<StringRef> emitValueTable(raw_ostream &OS) const {
|
||||
return None;
|
||||
}
|
||||
|
||||
virtual ~MarshallingKindInfo() = default;
|
||||
|
||||
static std::unique_ptr<MarshallingKindInfo> create(const Record &R);
|
||||
|
||||
protected:
|
||||
void emitScopedNormalizedValue(raw_ostream &OS,
|
||||
StringRef NormalizedValue) const {
|
||||
if (!NormalizedValuesScope.empty())
|
||||
OS << NormalizedValuesScope << "::";
|
||||
OS << NormalizedValue;
|
||||
}
|
||||
|
||||
virtual void emitSpecific(raw_ostream &OS) const = 0;
|
||||
MarshallingKindInfo(const Record &R, const char *MacroName)
|
||||
: R(R), MacroName(MacroName) {}
|
||||
};
|
||||
|
||||
class MarshallingFlagInfo final : public MarshallingKindInfo {
|
||||
public:
|
||||
bool IsPositive;
|
||||
|
||||
void emitSpecific(raw_ostream &OS) const override { OS << IsPositive; }
|
||||
|
||||
static std::unique_ptr<MarshallingKindInfo> create(const Record &R) {
|
||||
std::unique_ptr<MarshallingFlagInfo> Ret(new MarshallingFlagInfo(R));
|
||||
Ret->IsPositive = R.getValueAsBit("IsPositive");
|
||||
// FIXME: This is a workaround for a bug in older versions of clang (< 3.9)
|
||||
// The constructor that is supposed to allow for Derived to Base
|
||||
// conversion does not work. Remove this if we drop support for such
|
||||
// configurations.
|
||||
return std::unique_ptr<MarshallingKindInfo>(Ret.release());
|
||||
}
|
||||
|
||||
private:
|
||||
MarshallingFlagInfo(const Record &R)
|
||||
: MarshallingKindInfo(R, "OPTION_WITH_MARSHALLING_FLAG") {}
|
||||
};
|
||||
|
||||
class MarshallingStringInfo final : public MarshallingKindInfo {
|
||||
public:
|
||||
StringRef NormalizerRetTy;
|
||||
StringRef Normalizer;
|
||||
StringRef Denormalizer;
|
||||
StringRef ValueMerger;
|
||||
StringRef ValueExtractor;
|
||||
int TableIndex = -1;
|
||||
std::vector<StringRef> Values;
|
||||
std::vector<StringRef> NormalizedValues;
|
||||
|
@ -95,29 +149,17 @@ struct SimpleEnumValueTable {
|
|||
static constexpr const char *ValueTablesDecl =
|
||||
"static const SimpleEnumValueTable SimpleEnumValueTables[] = ";
|
||||
|
||||
void emit(raw_ostream &OS) const {
|
||||
write_cstring(OS, StringRef(getOptionSpelling(R)));
|
||||
OS << ", ";
|
||||
OS << ShouldAlwaysEmit;
|
||||
OS << ", ";
|
||||
OS << KeyPath;
|
||||
OS << ", ";
|
||||
emitScopedNormalizedValue(OS, DefaultValue);
|
||||
OS << ", ";
|
||||
void emitSpecific(raw_ostream &OS) const override {
|
||||
emitScopedNormalizedValue(OS, NormalizerRetTy);
|
||||
OS << ", ";
|
||||
OS << Normalizer;
|
||||
OS << ", ";
|
||||
OS << Denormalizer;
|
||||
OS << ", ";
|
||||
OS << ValueMerger;
|
||||
OS << ", ";
|
||||
OS << ValueExtractor;
|
||||
OS << ", ";
|
||||
OS << TableIndex;
|
||||
}
|
||||
|
||||
Optional<StringRef> emitValueTable(raw_ostream &OS) const {
|
||||
Optional<StringRef> emitValueTable(raw_ostream &OS) const override {
|
||||
if (TableIndex == -1)
|
||||
return {};
|
||||
OS << "static const SimpleEnumValue " << ValueTableName << "[] = {\n";
|
||||
|
@ -133,32 +175,23 @@ struct SimpleEnumValueTable {
|
|||
return StringRef(ValueTableName);
|
||||
}
|
||||
|
||||
static MarshallingInfo create(const Record &R) {
|
||||
assert(!isa<UnsetInit>(R.getValueInit("KeyPath")) &&
|
||||
!isa<UnsetInit>(R.getValueInit("DefaultValue")) &&
|
||||
!isa<UnsetInit>(R.getValueInit("NormalizerRetTy")) &&
|
||||
!isa<UnsetInit>(R.getValueInit("ValueMerger")) &&
|
||||
"MarshallingInfo must have a type");
|
||||
static std::unique_ptr<MarshallingKindInfo> create(const Record &R) {
|
||||
assert(!isa<UnsetInit>(R.getValueInit("NormalizerRetTy")) &&
|
||||
"String options must have a type");
|
||||
|
||||
MarshallingInfo Ret(R);
|
||||
Ret.ShouldAlwaysEmit = R.getValueAsBit("ShouldAlwaysEmit");
|
||||
Ret.KeyPath = R.getValueAsString("KeyPath");
|
||||
Ret.DefaultValue = R.getValueAsString("DefaultValue");
|
||||
Ret.NormalizedValuesScope = R.getValueAsString("NormalizedValuesScope");
|
||||
Ret.NormalizerRetTy = R.getValueAsString("NormalizerRetTy");
|
||||
std::unique_ptr<MarshallingStringInfo> Ret(new MarshallingStringInfo(R));
|
||||
Ret->NormalizerRetTy = R.getValueAsString("NormalizerRetTy");
|
||||
|
||||
Ret.Normalizer = R.getValueAsString("Normalizer");
|
||||
Ret.Denormalizer = R.getValueAsString("Denormalizer");
|
||||
Ret.ValueMerger = R.getValueAsString("ValueMerger");
|
||||
Ret.ValueExtractor = R.getValueAsString("ValueExtractor");
|
||||
Ret->Normalizer = R.getValueAsString("Normalizer");
|
||||
Ret->Denormalizer = R.getValueAsString("Denormalizer");
|
||||
|
||||
if (!isa<UnsetInit>(R.getValueInit("NormalizedValues"))) {
|
||||
assert(!isa<UnsetInit>(R.getValueInit("Values")) &&
|
||||
"Cannot provide normalized values for value-less options");
|
||||
Ret.TableIndex = NextTableIndex++;
|
||||
Ret.NormalizedValues = R.getValueAsListOfStrings("NormalizedValues");
|
||||
Ret.Values.reserve(Ret.NormalizedValues.size());
|
||||
Ret.ValueTableName = getOptionName(R) + "ValueTable";
|
||||
Ret->TableIndex = NextTableIndex++;
|
||||
Ret->NormalizedValues = R.getValueAsListOfStrings("NormalizedValues");
|
||||
Ret->Values.reserve(Ret->NormalizedValues.size());
|
||||
Ret->ValueTableName = getOptionName(R) + "ValueTable";
|
||||
|
||||
StringRef ValuesStr = R.getValueAsString("Values");
|
||||
for (;;) {
|
||||
|
@ -166,34 +199,55 @@ struct SimpleEnumValueTable {
|
|||
if (Idx == StringRef::npos)
|
||||
break;
|
||||
if (Idx > 0)
|
||||
Ret.Values.push_back(ValuesStr.slice(0, Idx));
|
||||
Ret->Values.push_back(ValuesStr.slice(0, Idx));
|
||||
ValuesStr = ValuesStr.slice(Idx + 1, StringRef::npos);
|
||||
}
|
||||
if (!ValuesStr.empty())
|
||||
Ret.Values.push_back(ValuesStr);
|
||||
Ret->Values.push_back(ValuesStr);
|
||||
|
||||
assert(Ret.Values.size() == Ret.NormalizedValues.size() &&
|
||||
assert(Ret->Values.size() == Ret->NormalizedValues.size() &&
|
||||
"The number of normalized values doesn't match the number of "
|
||||
"values");
|
||||
}
|
||||
|
||||
return Ret;
|
||||
// FIXME: This is a workaround for a bug in older versions of clang (< 3.9)
|
||||
// The constructor that is supposed to allow for Derived to Base
|
||||
// conversion does not work. Remove this if we drop support for such
|
||||
// configurations.
|
||||
return std::unique_ptr<MarshallingKindInfo>(Ret.release());
|
||||
}
|
||||
|
||||
private:
|
||||
void emitScopedNormalizedValue(raw_ostream &OS,
|
||||
StringRef NormalizedValue) const {
|
||||
if (!NormalizedValuesScope.empty())
|
||||
OS << NormalizedValuesScope << "::";
|
||||
OS << NormalizedValue;
|
||||
}
|
||||
|
||||
MarshallingInfo(const Record &R) : R(R){};
|
||||
MarshallingStringInfo(const Record &R)
|
||||
: MarshallingKindInfo(R, "OPTION_WITH_MARSHALLING_STRING") {}
|
||||
|
||||
static size_t NextTableIndex;
|
||||
};
|
||||
|
||||
size_t MarshallingInfo::NextTableIndex = 0;
|
||||
size_t MarshallingStringInfo::NextTableIndex = 0;
|
||||
|
||||
std::unique_ptr<MarshallingKindInfo>
|
||||
MarshallingKindInfo::create(const Record &R) {
|
||||
assert(!isa<UnsetInit>(R.getValueInit("KeyPath")) &&
|
||||
!isa<UnsetInit>(R.getValueInit("DefaultValue")) &&
|
||||
"Must provide at least a key-path and a default value for emitting "
|
||||
"marshalling information");
|
||||
|
||||
std::unique_ptr<MarshallingKindInfo> Ret = nullptr;
|
||||
StringRef MarshallingKindStr = R.getValueAsString("MarshallingKind");
|
||||
|
||||
if (MarshallingKindStr == "flag")
|
||||
Ret = MarshallingFlagInfo::create(R);
|
||||
else if (MarshallingKindStr == "string")
|
||||
Ret = MarshallingStringInfo::create(R);
|
||||
|
||||
Ret->ShouldAlwaysEmit = R.getValueAsBit("ShouldAlwaysEmit");
|
||||
Ret->KeyPath = R.getValueAsString("KeyPath");
|
||||
Ret->DefaultValue = R.getValueAsString("DefaultValue");
|
||||
if (!isa<UnsetInit>(R.getValueInit("NormalizedValuesScope")))
|
||||
Ret->NormalizedValuesScope = R.getValueAsString("NormalizedValuesScope");
|
||||
return Ret;
|
||||
}
|
||||
|
||||
/// OptParserEmitter - This tablegen backend takes an input .td file
|
||||
/// describing a list of options and emits a data structure for parsing and
|
||||
|
@ -384,7 +438,7 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
|
|||
};
|
||||
|
||||
auto IsMarshallingOption = [](const Record &R) {
|
||||
return !isa<UnsetInit>(R.getValueInit("KeyPath")) &&
|
||||
return !isa<UnsetInit>(R.getValueInit("MarshallingKind")) &&
|
||||
!R.getValueAsString("KeyPath").empty();
|
||||
};
|
||||
|
||||
|
@ -418,30 +472,30 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
|
|||
array_pod_sort(OptsWithMarshalling.begin(), OptsWithMarshalling.end(),
|
||||
CmpMarshallingOpts);
|
||||
|
||||
std::vector<MarshallingInfo> MarshallingInfos;
|
||||
std::vector<std::unique_ptr<MarshallingKindInfo>> MarshallingKindInfos;
|
||||
for (const auto *R : OptsWithMarshalling)
|
||||
MarshallingInfos.push_back(MarshallingInfo::create(*R));
|
||||
MarshallingKindInfos.push_back(MarshallingKindInfo::create(*R));
|
||||
|
||||
for (const auto &MI : MarshallingInfos) {
|
||||
OS << "#ifdef " << MI.MacroName << "\n";
|
||||
OS << MI.MacroName << "(";
|
||||
WriteOptRecordFields(OS, MI.R);
|
||||
for (const auto &KindInfo : MarshallingKindInfos) {
|
||||
OS << "#ifdef " << KindInfo->MacroName << "\n";
|
||||
OS << KindInfo->MacroName << "(";
|
||||
WriteOptRecordFields(OS, KindInfo->R);
|
||||
OS << ", ";
|
||||
MI.emit(OS);
|
||||
KindInfo->emit(OS);
|
||||
OS << ")\n";
|
||||
OS << "#endif // " << MI.MacroName << "\n";
|
||||
OS << "#endif // " << KindInfo->MacroName << "\n";
|
||||
}
|
||||
|
||||
OS << "\n";
|
||||
OS << "#ifdef SIMPLE_ENUM_VALUE_TABLE";
|
||||
OS << "\n";
|
||||
OS << MarshallingInfo::ValueTablePreamble;
|
||||
OS << MarshallingStringInfo::ValueTablePreamble;
|
||||
std::vector<StringRef> ValueTableNames;
|
||||
for (const auto &MI : MarshallingInfos)
|
||||
if (auto MaybeValueTableName = MI.emitValueTable(OS))
|
||||
for (const auto &KindInfo : MarshallingKindInfos)
|
||||
if (auto MaybeValueTableName = KindInfo->emitValueTable(OS))
|
||||
ValueTableNames.push_back(*MaybeValueTableName);
|
||||
|
||||
OS << MarshallingInfo::ValueTablesDecl << "{";
|
||||
OS << MarshallingStringInfo::ValueTablesDecl << "{";
|
||||
for (auto ValueTableName : ValueTableNames)
|
||||
OS << "{" << ValueTableName << ", sizeof(" << ValueTableName
|
||||
<< ") / sizeof(SimpleEnumValue)"
|
||||
|
|
Loading…
Reference in New Issue