From 7e7160d9d720316a581e6a7a8001ed110127588f Mon Sep 17 00:00:00 2001 From: Sergey Andreenko Date: Fri, 9 Jun 2017 00:07:46 -0700 Subject: [PATCH] delete DECLARE_TYPED_ENUM (dotnet/coreclr#12177) * delete DECLARE_TYPED_ENUM delete the workaroung for g++ c++11, that was fixes in gcc 4.4.1 many years ago. The workaround makes code dirty and sometimes we have typos like: }; END_DECLARE_TYPED_ENUM(insFlags,unsigned) or END_DECLARE_TYPED_ENUM(ChunkExtraAttribs, BYTE); with double ;; * jit-format Commit migrated from https://github.com/dotnet/coreclr/commit/47afd9434be8c0b5997a0a5618569abc30596546 --- src/coreclr/src/jit/block.h | 5 ++- src/coreclr/src/jit/compiler.h | 13 ++++--- src/coreclr/src/jit/emit.h | 39 +++++++++++--------- src/coreclr/src/jit/gentree.h | 30 ++++++++-------- src/coreclr/src/jit/instr.h | 43 +++++++++------------- src/coreclr/src/jit/jit.h | 15 -------- src/coreclr/src/jit/target.h | 82 +++++++++++++++++++++--------------------- src/coreclr/src/jit/valuenum.h | 27 +++++++------- src/coreclr/src/jit/vartype.h | 7 ++-- 9 files changed, 118 insertions(+), 143 deletions(-) diff --git a/src/coreclr/src/jit/block.h b/src/coreclr/src/jit/block.h index 461eadc..ad120fc 100644 --- a/src/coreclr/src/jit/block.h +++ b/src/coreclr/src/jit/block.h @@ -49,7 +49,7 @@ typedef BitVec_ValRet_T ASSERT_VALRET_TP; // clang-format off -DECLARE_TYPED_ENUM(BBjumpKinds, BYTE) +enum BBjumpKinds : BYTE { BBJ_EHFINALLYRET,// block ends with 'endfinally' (for finally or fault) BBJ_EHFILTERRET, // block ends with 'endfilter' @@ -64,8 +64,7 @@ DECLARE_TYPED_ENUM(BBjumpKinds, BYTE) BBJ_SWITCH, // block ends with a switch statement BBJ_COUNT -} -END_DECLARE_TYPED_ENUM(BBjumpKinds, BYTE) +}; // clang-format on diff --git a/src/coreclr/src/jit/compiler.h b/src/coreclr/src/jit/compiler.h index d438862..fbdbaf4 100644 --- a/src/coreclr/src/jit/compiler.h +++ b/src/coreclr/src/jit/compiler.h @@ -1131,14 +1131,13 @@ public: #endif // FEATURE_JIT_METHOD_PERF //------------------- Function/Funclet info ------------------------------- -DECLARE_TYPED_ENUM(FuncKind, BYTE) +enum FuncKind : BYTE { - FUNC_ROOT, // The main/root function (always id==0) - FUNC_HANDLER, // a funclet associated with an EH handler (finally, fault, catch, filter handler) - FUNC_FILTER, // a funclet associated with an EH filter - FUNC_COUNT -} -END_DECLARE_TYPED_ENUM(FuncKind, BYTE) + FUNC_ROOT, // The main/root function (always id==0) + FUNC_HANDLER, // a funclet associated with an EH handler (finally, fault, catch, filter handler) + FUNC_FILTER, // a funclet associated with an EH filter + FUNC_COUNT +}; class emitLocation; diff --git a/src/coreclr/src/jit/emit.h b/src/coreclr/src/jit/emit.h index a925f1f..e1af052 100644 --- a/src/coreclr/src/jit/emit.h +++ b/src/coreclr/src/jit/emit.h @@ -220,15 +220,15 @@ private: /* The following describes an instruction group */ /************************************************************************/ -DECLARE_TYPED_ENUM(insGroupPlaceholderType, unsigned char) +enum insGroupPlaceholderType : unsigned char { IGPT_PROLOG, // currently unused - IGPT_EPILOG, + IGPT_EPILOG, #if FEATURE_EH_FUNCLETS - IGPT_FUNCLET_PROLOG, IGPT_FUNCLET_EPILOG, + IGPT_FUNCLET_PROLOG, + IGPT_FUNCLET_EPILOG, #endif // FEATURE_EH_FUNCLETS -} -END_DECLARE_TYPED_ENUM(insGroupPlaceholderType, unsigned char) +}; #if defined(_MSC_VER) && defined(_TARGET_ARM_) // ARM aligns structures that contain 64-bit ints or doubles on 64-bit boundaries. This causes unwanted @@ -452,16 +452,21 @@ protected: void* emitGetMem(size_t sz); - DECLARE_TYPED_ENUM(opSize, unsigned) + enum opSize : unsigned { - OPSZ1 = 0, OPSZ2 = 1, OPSZ4 = 2, OPSZ8 = 3, OPSZ16 = 4, OPSZ32 = 5, OPSZ_COUNT = 6, + OPSZ1 = 0, + OPSZ2 = 1, + OPSZ4 = 2, + OPSZ8 = 3, + OPSZ16 = 4, + OPSZ32 = 5, + OPSZ_COUNT = 6, #ifdef _TARGET_AMD64_ OPSZP = OPSZ8, #else OPSZP = OPSZ4, #endif - } - END_DECLARE_TYPED_ENUM(opSize, unsigned) + }; #define OPSIZE_INVALID ((opSize)0xffff) @@ -507,14 +512,13 @@ protected: /* The following describes a single instruction */ /************************************************************************/ - DECLARE_TYPED_ENUM(insFormat, unsigned) + enum insFormat : unsigned { #define IF_DEF(en, op1, op2) IF_##en, #include "emitfmts.h" IF_COUNT - } - END_DECLARE_TYPED_ENUM(insFormat, unsigned) + }; #define AM_DISP_BITS ((sizeof(unsigned) * 8) - 2 * (REGNUM_BITS + 1) - 2) #define AM_DISP_BIG_VAL (-(1 << (AM_DISP_BITS - 1))) @@ -553,12 +557,13 @@ protected: #ifdef _TARGET_ARM_ unsigned insEncodeSetFlags(insFlags sf); - DECLARE_TYPED_ENUM(insSize, unsigned) + enum insSize : unsigned { - ISZ_16BIT, ISZ_32BIT, ISZ_48BIT // pseudo-instruction for conditional branch with imm24 range, - // encoded as IT of condition followed by an unconditional branch - } - END_DECLARE_TYPED_ENUM(insSize, unsigned) + ISZ_16BIT, + ISZ_32BIT, + ISZ_48BIT // pseudo-instruction for conditional branch with imm24 range, + // encoded as IT of condition followed by an unconditional branch + }; unsigned insEncodeShiftOpts(insOpts opt); unsigned insEncodePUW_G0(insOpts opt, int imm); diff --git a/src/coreclr/src/jit/gentree.h b/src/coreclr/src/jit/gentree.h index 747784b..32ef952 100644 --- a/src/coreclr/src/jit/gentree.h +++ b/src/coreclr/src/jit/gentree.h @@ -66,7 +66,7 @@ enum SpecialCodeKind /*****************************************************************************/ -DECLARE_TYPED_ENUM(genTreeOps, BYTE) +enum genTreeOps : BYTE { #define GTNODE(en, st, cm, ok) GT_##en, #include "gtlist.h" @@ -74,16 +74,15 @@ DECLARE_TYPED_ENUM(genTreeOps, BYTE) GT_COUNT, #ifdef _TARGET_64BIT_ - // GT_CNS_NATIVELONG is the gtOper symbol for GT_CNS_LNG or GT_CNS_INT, depending on the target. - // For the 64-bit targets we will only use GT_CNS_INT as it used to represent all the possible sizes - GT_CNS_NATIVELONG = GT_CNS_INT, + // GT_CNS_NATIVELONG is the gtOper symbol for GT_CNS_LNG or GT_CNS_INT, depending on the target. + // For the 64-bit targets we will only use GT_CNS_INT as it used to represent all the possible sizes + GT_CNS_NATIVELONG = GT_CNS_INT, #else - // For the 32-bit targets we use a GT_CNS_LNG to hold a 64-bit integer constant and GT_CNS_INT for all others. - // In the future when we retarget the JIT for x86 we should consider eliminating GT_CNS_LNG - GT_CNS_NATIVELONG = GT_CNS_LNG, + // For the 32-bit targets we use a GT_CNS_LNG to hold a 64-bit integer constant and GT_CNS_INT for all others. + // In the future when we retarget the JIT for x86 we should consider eliminating GT_CNS_LNG + GT_CNS_NATIVELONG = GT_CNS_LNG, #endif -} -END_DECLARE_TYPED_ENUM(genTreeOps, BYTE) +}; /***************************************************************************** * @@ -133,15 +132,14 @@ enum genTreeKinds /*****************************************************************************/ -DECLARE_TYPED_ENUM(gtCallTypes, BYTE) +enum gtCallTypes : BYTE { - CT_USER_FUNC, // User function - CT_HELPER, // Jit-helper - CT_INDIRECT, // Indirect call + CT_USER_FUNC, // User function + CT_HELPER, // Jit-helper + CT_INDIRECT, // Indirect call - CT_COUNT // fake entry (must be last) -} -END_DECLARE_TYPED_ENUM(gtCallTypes, BYTE) + CT_COUNT // fake entry (must be last) +}; /*****************************************************************************/ diff --git a/src/coreclr/src/jit/instr.h b/src/coreclr/src/jit/instr.h index 2d50234..309a2f5 100644 --- a/src/coreclr/src/jit/instr.h +++ b/src/coreclr/src/jit/instr.h @@ -12,7 +12,7 @@ /*****************************************************************************/ // clang-format off -DECLARE_TYPED_ENUM(instruction,unsigned) +enum instruction : unsigned { #if defined(_TARGET_XARCH_) #define INST0(id, nm, fp, um, rf, wf, mr ) INS_##id, @@ -53,8 +53,7 @@ DECLARE_TYPED_ENUM(instruction,unsigned) INS_none, INS_count = INS_none -} -END_DECLARE_TYPED_ENUM(instruction,unsigned) +}; /*****************************************************************************/ @@ -79,25 +78,23 @@ enum emitJumpKind /*****************************************************************************/ -DECLARE_TYPED_ENUM(GCtype,unsigned) +enum GCtype : unsigned { GCT_NONE, GCT_GCREF, GCT_BYREF -} -END_DECLARE_TYPED_ENUM(GCtype,unsigned) +}; // TODO-Cleanup: Move 'insFlags' under _TARGET_ARM_ -DECLARE_TYPED_ENUM(insFlags,unsigned) +enum insFlags: unsigned { INS_FLAGS_NOT_SET, INS_FLAGS_SET, INS_FLAGS_DONT_CARE }; -END_DECLARE_TYPED_ENUM(insFlags,unsigned) #if defined(_TARGET_ARM_) -DECLARE_TYPED_ENUM(insOpts,unsigned) +enum insOpts: unsigned { INS_OPTS_NONE, INS_OPTS_LDST_PRE_DEC, @@ -108,10 +105,9 @@ DECLARE_TYPED_ENUM(insOpts,unsigned) INS_OPTS_LSR, INS_OPTS_ASR, INS_OPTS_ROR -} -END_DECLARE_TYPED_ENUM(insOpts,unsigned) +}; #elif defined(_TARGET_ARM64_) -DECLARE_TYPED_ENUM(insOpts,unsigned) +enum insOpts : unsigned { INS_OPTS_NONE, @@ -165,10 +161,9 @@ DECLARE_TYPED_ENUM(insOpts,unsigned) INS_OPTS_S_TO_H, // Single to Half INS_OPTS_D_TO_H, // Double to Half -} -END_DECLARE_TYPED_ENUM(insOpts,unsigned) +}; -DECLARE_TYPED_ENUM(insCond,unsigned) +enum insCond : unsigned { INS_COND_EQ, INS_COND_NE, @@ -187,10 +182,9 @@ DECLARE_TYPED_ENUM(insCond,unsigned) INS_COND_GT, INS_COND_LE, -} -END_DECLARE_TYPED_ENUM(insCond,unsigned) +}; -DECLARE_TYPED_ENUM(insCflags,unsigned) +enum insCflags : unsigned { INS_FLAGS_NONE, INS_FLAGS_V, @@ -211,10 +205,9 @@ DECLARE_TYPED_ENUM(insCflags,unsigned) INS_FLAGS_NZV, INS_FLAGS_NZC, INS_FLAGS_NZCV, -} -END_DECLARE_TYPED_ENUM(insCFlags,unsigned) +}; -DECLARE_TYPED_ENUM(insBarrier,unsigned) +enum insBarrier : unsigned { INS_BARRIER_OSHLD = 1, INS_BARRIER_OSHST = 2, @@ -231,12 +224,11 @@ DECLARE_TYPED_ENUM(insBarrier,unsigned) INS_BARRIER_LD = 13, INS_BARRIER_ST = 14, INS_BARRIER_SY = 15, -} -END_DECLARE_TYPED_ENUM(insBarrier,unsigned) +}; #endif #undef EA_UNKNOWN -DECLARE_TYPED_ENUM(emitAttr,unsigned) +enum emitAttr : unsigned { EA_UNKNOWN = 0x000, EA_1BYTE = 0x001, @@ -261,8 +253,7 @@ DECLARE_TYPED_ENUM(emitAttr,unsigned) EA_BYREF = EA_BYREF_FLG | EA_PTRSIZE, /* size == -2 */ EA_DSP_RELOC_FLG = 0x200, EA_CNS_RELOC_FLG = 0x400, -} -END_DECLARE_TYPED_ENUM(emitAttr,unsigned) +}; #define EA_ATTR(x) ((emitAttr)(x)) #define EA_SIZE(x) ((emitAttr)(((unsigned)(x)) & EA_SIZE_MASK)) diff --git a/src/coreclr/src/jit/jit.h b/src/coreclr/src/jit/jit.h index 5120449..2810b96 100644 --- a/src/coreclr/src/jit/jit.h +++ b/src/coreclr/src/jit/jit.h @@ -225,21 +225,6 @@ #endif #endif -// Macros for defining strongly-typed enums. Use as follows: -// -// DECLARE_TYPED_ENUM(FooEnum,BYTE) -// { -// fooTag1, fooTag2 -// } -// END_DECLARE_TYPED_ENUM(FooEnum, BYTE) -// -// VC++ understands the syntax to declare these directly, e.g., "enum FooEnum : BYTE", -// but GCC does not, so we use typedefs. - -#define DECLARE_TYPED_ENUM(tag, baseType) enum tag : baseType - -#define END_DECLARE_TYPED_ENUM(tag, baseType) ; - #include "corhdr.h" #include "corjit.h" #include "jitee.h" diff --git a/src/coreclr/src/jit/target.h b/src/coreclr/src/jit/target.h index ac5456e..2db02cb 100644 --- a/src/coreclr/src/jit/target.h +++ b/src/coreclr/src/jit/target.h @@ -56,113 +56,115 @@ // REG_NA - Used to indicate that a register is either not yet assigned or not required. // #if defined(_TARGET_ARM_) -DECLARE_TYPED_ENUM(_regNumber_enum, unsigned) +enum _regNumber_enum : unsigned { #define REGDEF(name, rnum, mask, sname) REG_##name = rnum, #define REGALIAS(alias, realname) REG_##alias = REG_##realname, #include "register.h" - REG_COUNT, REG_NA = REG_COUNT, ACTUAL_REG_COUNT = REG_COUNT - 1 // everything but REG_STK (only real regs) -} -END_DECLARE_TYPED_ENUM(_regNumber_enum, unsigned) + REG_COUNT, + REG_NA = REG_COUNT, + ACTUAL_REG_COUNT = REG_COUNT - 1 // everything but REG_STK (only real regs) +}; -DECLARE_TYPED_ENUM(_regMask_enum, unsigned __int64) +enum _regMask_enum : unsigned __int64 { RBM_NONE = 0, #define REGDEF(name, rnum, mask, sname) RBM_##name = mask, #define REGALIAS(alias, realname) RBM_##alias = RBM_##realname, #include "register.h" -} -END_DECLARE_TYPED_ENUM(_regMask_enum, unsigned __int64) +}; #elif defined(_TARGET_ARM64_) -DECLARE_TYPED_ENUM(_regNumber_enum, unsigned) +enum _regNumber_enum : unsigned { #define REGDEF(name, rnum, mask, xname, wname) REG_##name = rnum, #define REGALIAS(alias, realname) REG_##alias = REG_##realname, #include "register.h" - REG_COUNT, REG_NA = REG_COUNT, ACTUAL_REG_COUNT = REG_COUNT - 1 // everything but REG_STK (only real regs) -} -END_DECLARE_TYPED_ENUM(_regNumber_enum, unsigned) + REG_COUNT, + REG_NA = REG_COUNT, + ACTUAL_REG_COUNT = REG_COUNT - 1 // everything but REG_STK (only real regs) +}; -DECLARE_TYPED_ENUM(_regMask_enum, unsigned __int64) +enum _regMask_enum : unsigned __int64 { RBM_NONE = 0, #define REGDEF(name, rnum, mask, xname, wname) RBM_##name = mask, #define REGALIAS(alias, realname) RBM_##alias = RBM_##realname, #include "register.h" -} -END_DECLARE_TYPED_ENUM(_regMask_enum, unsigned __int64) +}; #elif defined(_TARGET_AMD64_) -DECLARE_TYPED_ENUM(_regNumber_enum, unsigned) +enum _regNumber_enum : unsigned { #define REGDEF(name, rnum, mask, sname) REG_##name = rnum, #define REGALIAS(alias, realname) REG_##alias = REG_##realname, #include "register.h" - REG_COUNT, REG_NA = REG_COUNT, ACTUAL_REG_COUNT = REG_COUNT - 1 // everything but REG_STK (only real regs) -} -END_DECLARE_TYPED_ENUM(_regNumber_enum, unsigned) + REG_COUNT, + REG_NA = REG_COUNT, + ACTUAL_REG_COUNT = REG_COUNT - 1 // everything but REG_STK (only real regs) +}; -DECLARE_TYPED_ENUM(_regMask_enum, unsigned) +enum _regMask_enum : unsigned { RBM_NONE = 0, #define REGDEF(name, rnum, mask, sname) RBM_##name = mask, #define REGALIAS(alias, realname) RBM_##alias = RBM_##realname, #include "register.h" -} -END_DECLARE_TYPED_ENUM(_regMask_enum, unsigned) +}; #elif defined(_TARGET_X86_) #ifndef LEGACY_BACKEND -DECLARE_TYPED_ENUM(_regNumber_enum, unsigned) +enum _regNumber_enum : unsigned { #define REGDEF(name, rnum, mask, sname) REG_##name = rnum, #define REGALIAS(alias, realname) REG_##alias = REG_##realname, #include "register.h" - REG_COUNT, REG_NA = REG_COUNT, ACTUAL_REG_COUNT = REG_COUNT - 1 // everything but REG_STK (only real regs) -} -END_DECLARE_TYPED_ENUM(_regNumber_enum, unsigned) + REG_COUNT, + REG_NA = REG_COUNT, + ACTUAL_REG_COUNT = REG_COUNT - 1 // everything but REG_STK (only real regs) +}; -DECLARE_TYPED_ENUM(_regMask_enum, unsigned) +enum _regMask_enum : unsigned { RBM_NONE = 0, #define REGDEF(name, rnum, mask, sname) RBM_##name = mask, #define REGALIAS(alias, realname) RBM_##alias = RBM_##realname, #include "register.h" -} -END_DECLARE_TYPED_ENUM(_regMask_enum, unsigned) +}; + #else // LEGACY_BACKEND -DECLARE_TYPED_ENUM(_regNumber_enum, unsigned) +enum _regNumber_enum : unsigned { #define REGDEF(name, rnum, mask, sname) REG_##name = rnum, #define REGALIAS(alias, realname) REG_##alias = REG_##realname, #include "register.h" - REG_COUNT, REG_NA = REG_COUNT, - ACTUAL_REG_COUNT = REG_COUNT - 1, // everything but REG_STK (only real regs) + REG_COUNT, + REG_NA = REG_COUNT, + ACTUAL_REG_COUNT = REG_COUNT - 1, // everything but REG_STK (only real regs) #define REGDEF(name, rnum, mask, sname) REG_##name = rnum, #include "registerfp.h" - REG_FPCOUNT, REG_FPNONE = REG_FPCOUNT, + REG_FPCOUNT, + REG_FPNONE = REG_FPCOUNT, #define REGDEF(name, rnum, mask, sname) REG_##name = rnum, #include "registerxmm.h" - REG_XMMCOUNT -} -END_DECLARE_TYPED_ENUM(_regNumber_enum, unsigned) + REG_XMMCOUNT +}; -DECLARE_TYPED_ENUM(_regMask_enum, unsigned) +enum _regMask_enum : unsigned { RBM_NONE = 0, @@ -175,8 +177,7 @@ DECLARE_TYPED_ENUM(_regMask_enum, unsigned) #define REGDEF(name, rnum, mask, sname) RBM_##name = mask, #include "registerxmm.h" -} -END_DECLARE_TYPED_ENUM(_regMask_enum, unsigned) +}; #endif // LEGACY_BACKEND #else @@ -212,7 +213,7 @@ C_ASSERT(REG_COUNT < REG_PAIR_FIRST); // make sure the register numbers (includi #define REG_PAIR_FIRST 0 #endif -DECLARE_TYPED_ENUM(_regPairNo_enum, unsigned) +enum _regPairNo_enum : unsigned { #define PAIRDEF(rlo, rhi) REG_PAIR_##rlo##rhi = REG_##rlo + (REG_##rhi << REG_PAIR_NBITS) + REG_PAIR_FIRST, #include "regpair.h" @@ -220,8 +221,7 @@ DECLARE_TYPED_ENUM(_regPairNo_enum, unsigned) REG_PAIR_LAST = (REG_COUNT - 1) + ((REG_COUNT - 1) << REG_PAIR_NBITS) + REG_PAIR_FIRST, REG_PAIR_NONE = REG_PAIR_LAST + 1 -} -END_DECLARE_TYPED_ENUM(_regPairNo_enum, unsigned) +}; enum regPairMask { diff --git a/src/coreclr/src/jit/valuenum.h b/src/coreclr/src/jit/valuenum.h index fcf6d86..ac7e52e 100644 --- a/src/coreclr/src/jit/valuenum.h +++ b/src/coreclr/src/jit/valuenum.h @@ -872,20 +872,19 @@ private: // The base VN of the next chunk to be allocated. Should always be a multiple of ChunkSize. ValueNum m_nextChunkBase; - DECLARE_TYPED_ENUM(ChunkExtraAttribs, BYTE) - { - CEA_None, // No extra attributes. - CEA_Const, // This chunk contains constant values. - CEA_Handle, // This chunk contains handle constants. - CEA_NotAField, // This chunk contains "not a field" values. - CEA_Func0, // Represents functions of arity 0. - CEA_Func1, // ...arity 1. - CEA_Func2, // ...arity 2. - CEA_Func3, // ...arity 3. - CEA_Func4, // ...arity 4. - CEA_Count - } - END_DECLARE_TYPED_ENUM(ChunkExtraAttribs, BYTE); + enum ChunkExtraAttribs : BYTE + { + CEA_None, // No extra attributes. + CEA_Const, // This chunk contains constant values. + CEA_Handle, // This chunk contains handle constants. + CEA_NotAField, // This chunk contains "not a field" values. + CEA_Func0, // Represents functions of arity 0. + CEA_Func1, // ...arity 1. + CEA_Func2, // ...arity 2. + CEA_Func3, // ...arity 3. + CEA_Func4, // ...arity 4. + CEA_Count + }; // A "Chunk" holds "ChunkSize" value numbers, starting at "m_baseVN". All of these share the same // "m_typ" and "m_attribs". These properties determine the interpretation of "m_defs", as discussed below. diff --git a/src/coreclr/src/jit/vartype.h b/src/coreclr/src/jit/vartype.h index 550aeb9..e75bc2a 100644 --- a/src/coreclr/src/jit/vartype.h +++ b/src/coreclr/src/jit/vartype.h @@ -20,7 +20,7 @@ enum var_types_classification VTF_S = 0x0040, // is a struct type }; -DECLARE_TYPED_ENUM(var_types, BYTE) +enum var_types : BYTE { #define DEF_TP(tn, nm, jitType, verType, sz, sze, asze, st, al, tf, howUsed) TYP_##tn, #include "typelist.h" @@ -28,9 +28,8 @@ DECLARE_TYPED_ENUM(var_types, BYTE) TYP_COUNT, - TYP_lastIntrins = TYP_DOUBLE -} -END_DECLARE_TYPED_ENUM(var_types, BYTE) + TYP_lastIntrins = TYP_DOUBLE +}; /***************************************************************************** * C-style pointers are implemented as TYP_INT or TYP_LONG depending on the -- 2.7.4