// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

// Macro template for inline observations
//
// INLINE_OBSERVATION(name, type, description, impact, target)
//
// name will be used to create an InlineObservation enum member
//    (enum name prepends scope, eg CALLEE_MARKED_AS_SKIPPED)
// type is the data type for the observation
// description is a user string for diagnostics
// impact is one of the members of InlineImpact
// target is one of the members of InlineTarget
//
// Note: the impact classification is work in progress.
//
// Some subset of the FATAL cases here can be refined to SERIOUS,
// LIMITATION, or PERFORMANCE. While the refined observations may
// eventually veto inlining, the jit can safely keep making more
// observations.

// ------ Initial Sentinel -------

INLINE_OBSERVATION(UNUSED_INITIAL,            bool,   "unused initial observation",           FATAL,       CALLEE)

// ------ Callee Fatal -------

INLINE_OBSERVATION(BAD_ARGUMENT_NUMBER,       bool,   "invalid argument number",              FATAL,       CALLEE)
INLINE_OBSERVATION(BAD_LOCAL_NUMBER,          bool,   "invalid local number",                 FATAL,       CALLEE)
INLINE_OBSERVATION(COMPILATION_ERROR,         bool,   "compilation error",                    FATAL,       CALLEE)
INLINE_OBSERVATION(HAS_EH,                    bool,   "has exception handling",               FATAL,       CALLEE)
INLINE_OBSERVATION(HAS_ENDFILTER,             bool,   "has endfilter",                        FATAL,       CALLEE)
INLINE_OBSERVATION(HAS_ENDFINALLY,            bool,   "has endfinally",                       FATAL,       CALLEE)
INLINE_OBSERVATION(HAS_LEAVE,                 bool,   "has leave",                            FATAL,       CALLEE)
INLINE_OBSERVATION(HAS_MANAGED_VARARGS,       bool,   "managed varargs",                      FATAL,       CALLEE)
INLINE_OBSERVATION(HAS_NATIVE_VARARGS,        bool,   "native varargs",                       FATAL,       CALLEE)
INLINE_OBSERVATION(HAS_NO_BODY,               bool,   "has no body",                          FATAL,       CALLEE)
INLINE_OBSERVATION(HAS_NULL_FOR_LDELEM,       bool,   "has null pointer for ldelem",          FATAL,       CALLEE)
INLINE_OBSERVATION(IS_ARRAY_METHOD,           bool,   "is array method",                      FATAL,       CALLEE)
INLINE_OBSERVATION(IS_GENERIC_VIRTUAL,        bool,   "generic virtual",                      FATAL,       CALLEE)
INLINE_OBSERVATION(IS_JIT_NOINLINE,           bool,   "noinline per JitNoinline",             FATAL,       CALLEE)
INLINE_OBSERVATION(IS_NOINLINE,               bool,   "noinline per IL/cached result",        FATAL,       CALLEE)
INLINE_OBSERVATION(IS_SYNCHRONIZED,           bool,   "is synchronized",                      FATAL,       CALLEE)
INLINE_OBSERVATION(IS_VM_NOINLINE,            bool,   "noinline per VM",                      FATAL,       CALLEE)
INLINE_OBSERVATION(LACKS_RETURN,              bool,   "no return opcode",                     FATAL,       CALLEE)
INLINE_OBSERVATION(LDFLD_NEEDS_HELPER,        bool,   "ldfld needs helper",                   FATAL,       CALLEE)
INLINE_OBSERVATION(LOCALLOC_TOO_LARGE,        bool,   "localloc size too large",              FATAL,       CALLEE)
INLINE_OBSERVATION(LOG_REPLAY_REJECT,         bool,   "rejected by log replay",               FATAL,       CALLEE)
INLINE_OBSERVATION(MARKED_AS_SKIPPED,         bool,   "skipped by complus request",           FATAL,       CALLEE)
INLINE_OBSERVATION(MAXSTACK_TOO_BIG,          bool,   "maxstack too big"  ,                   FATAL,       CALLEE)
INLINE_OBSERVATION(NO_METHOD_INFO,            bool,   "cannot get method info",               FATAL,       CALLEE)
INLINE_OBSERVATION(NOT_PROFITABLE_INLINE,     bool,   "unprofitable inline",                  FATAL,       CALLEE)
INLINE_OBSERVATION(RANDOM_REJECT,             bool,   "random reject",                        FATAL,       CALLEE)
INLINE_OBSERVATION(STACK_CRAWL_MARK,          bool,   "uses stack crawl mark",                FATAL,       CALLEE)
INLINE_OBSERVATION(STFLD_NEEDS_HELPER,        bool,   "stfld needs helper",                   FATAL,       CALLEE)
INLINE_OBSERVATION(TOO_MANY_ARGUMENTS,        bool,   "too many arguments",                   FATAL,       CALLEE)
INLINE_OBSERVATION(TOO_MANY_LOCALS,           bool,   "too many locals",                      FATAL,       CALLEE)
INLINE_OBSERVATION(EXPLICIT_TAIL_PREFIX,      bool,   "explicit tail prefix in callee",       FATAL,       CALLEE)

// ------ Callee Performance -------

INLINE_OBSERVATION(LDFLD_STATIC_VALUECLASS,   bool,   "ldsfld of value class",                PERFORMANCE, CALLEE)
INLINE_OBSERVATION(TOO_MANY_BASIC_BLOCKS,     bool,   "too many basic blocks",                PERFORMANCE, CALLEE)
INLINE_OBSERVATION(TOO_MUCH_IL,               bool,   "too many il bytes",                    PERFORMANCE, CALLEE)

// ------ Callee Information -------

INLINE_OBSERVATION(ARG_FEEDS_CONSTANT_TEST,   bool,   "argument feeds constant test",         INFORMATION, CALLEE)
INLINE_OBSERVATION(ARG_FEEDS_TEST,            bool,   "argument feeds test",                  INFORMATION, CALLEE)
INLINE_OBSERVATION(ARG_FEEDS_CAST,            int,    "argument feeds castclass or isinst",   INFORMATION, CALLEE)
INLINE_OBSERVATION(ARG_FEEDS_RANGE_CHECK,     bool,   "argument feeds range check",           INFORMATION, CALLEE)
INLINE_OBSERVATION(ARG_FEEDS_ISCONST,         bool,   "argument feeds IsKnownConstant",       INFORMATION, CALLEE)
INLINE_OBSERVATION(CONST_ARG_FEEDS_ISCONST,   bool,   "const argument feeds IsKnownConstant", INFORMATION, CALLEE)
INLINE_OBSERVATION(ARG_STRUCT,                int,    "arg is a struct passed by value",      INFORMATION, CALLEE)
INLINE_OBSERVATION(RETURNS_STRUCT,            bool,   "returns a struct by value",            INFORMATION, CALLEE)
INLINE_OBSERVATION(ARG_STRUCT_FIELD_ACCESS,   int,    "ldfld/stfld over arg (struct)",        INFORMATION, CALLEE)
INLINE_OBSERVATION(BINARY_EXRP_WITH_CNS,      int,    "'X op CNS' pattern",                   INFORMATION, CALLEE)
INLINE_OBSERVATION(BEGIN_OPCODE_SCAN,         bool,   "prepare to look at opcodes",           INFORMATION, CALLEE)
INLINE_OBSERVATION(BELOW_ALWAYS_INLINE_SIZE,  bool,   "below ALWAYS_INLINE size",             INFORMATION, CALLEE)
INLINE_OBSERVATION(CLASS_PROMOTABLE,          bool,   "promotable value class",               INFORMATION, CALLEE)
INLINE_OBSERVATION(CLASS_VALUETYPE,           bool,   "value class",                          INFORMATION, CALLEE)
INLINE_OBSERVATION(FOLDABLE_BOX,              int,    "foldable box/unbox operation",         INFORMATION, CALLEE)
INLINE_OBSERVATION(INTRINSIC,                 int,    "call marked as intrinsic",             INFORMATION, CALLEE)
INLINE_OBSERVATION(BACKWARD_JUMP,             int,    "backward jump",                        INFORMATION, CALLEE)
INLINE_OBSERVATION(THROW_BLOCK,               int,    "throw block",                          INFORMATION, CALLEE)
INLINE_OBSERVATION(DOES_NOT_RETURN,           bool,   "does not return",                      INFORMATION, CALLEE)
INLINE_OBSERVATION(END_OPCODE_SCAN,           bool,   "done looking at opcodes",              INFORMATION, CALLEE)
INLINE_OBSERVATION(HAS_GC_STRUCT,             bool,   "has gc field in struct local",         INFORMATION, CALLEE)
INLINE_OBSERVATION(HAS_LOCALLOC,              bool,   "has localloc",                         INFORMATION, CALLEE)
INLINE_OBSERVATION(HAS_PINNED_LOCALS,         bool,   "has pinned locals",                    INFORMATION, CALLEE)
INLINE_OBSERVATION(HAS_SIMD,                  bool,   "has SIMD arg, local, or ret",          INFORMATION, CALLEE)
INLINE_OBSERVATION(HAS_SWITCH,                bool,   "has switch",                           INFORMATION, CALLEE)
INLINE_OBSERVATION(IL_CODE_SIZE,              int,    "number of bytes of IL",                INFORMATION, CALLEE)
INLINE_OBSERVATION(IS_CLASS_CTOR,             bool,   "class constructor",                    INFORMATION, CALLEE)
INLINE_OBSERVATION(IS_DISCRETIONARY_INLINE,   bool,   "can inline, check heuristics",         INFORMATION, CALLEE)
INLINE_OBSERVATION(IS_FORCE_INLINE,           bool,   "aggressive inline attribute",          INFORMATION, CALLEE)
INLINE_OBSERVATION(IS_INSTANCE_CTOR,          bool,   "instance constructor",                 INFORMATION, CALLEE)
INLINE_OBSERVATION(IS_PROFITABLE_INLINE,      bool,   "profitable inline",                    INFORMATION, CALLEE)
INLINE_OBSERVATION(IS_SIZE_DECREASING_INLINE, bool,   "size decreasing inline",               INFORMATION, CALLEE)
INLINE_OBSERVATION(LOG_REPLAY_ACCEPT,         bool,   "accepted by log replay",               INFORMATION, CALLEE)
INLINE_OBSERVATION(LOOKS_LIKE_WRAPPER,        bool,   "thin wrapper around a call",           INFORMATION, CALLEE)
INLINE_OBSERVATION(MAXSTACK,                  int,    "maxstack",                             INFORMATION, CALLEE)
INLINE_OBSERVATION(OPCODE,                    int,    "next opcode in IL stream",             INFORMATION, CALLEE)
INLINE_OBSERVATION(OPCODE_NORMED,             int,    "next opcode in IL stream",             INFORMATION, CALLEE)
INLINE_OBSERVATION(NUMBER_OF_ARGUMENTS,       int,    "number of arguments",                  INFORMATION, CALLEE)
INLINE_OBSERVATION(NUMBER_OF_BASIC_BLOCKS,    int,    "number of basic blocks",               INFORMATION, CALLEE)
INLINE_OBSERVATION(NUMBER_OF_LOCALS,          int,    "number of locals",                     INFORMATION, CALLEE)
INLINE_OBSERVATION(RANDOM_ACCEPT,             bool,   "random accept",                        INFORMATION, CALLEE)
INLINE_OBSERVATION(UNSUPPORTED_OPCODE,        bool,   "unsupported opcode",                   INFORMATION, CALLEE)

// ------ Caller Correctness -------

INLINE_OBSERVATION(DEBUG_CODEGEN,             bool,   "debug codegen",                        FATAL,       CALLER)
INLINE_OBSERVATION(IS_JIT_NOINLINE,           bool,   "noinline per JitNoInlineRange",        FATAL,       CALLER)
INLINE_OBSERVATION(USES_NEXT_CALL_RET_ADDR,   bool,   "uses NextCallReturnAddress intrinsic", FATAL,       CALLER)

// ------ Caller Information -------

INLINE_OBSERVATION(HAS_NEWARRAY,              bool,   "has newarray",                         INFORMATION, CALLER)
INLINE_OBSERVATION(HAS_NEWOBJ,                bool,   "has newobj",                           INFORMATION, CALLER)

// ------ Call Site Correctness -------

INLINE_OBSERVATION(ARG_HAS_NULL_THIS,         bool,   "this pointer argument is null",        FATAL,       CALLSITE)
INLINE_OBSERVATION(ARG_NO_BASH_TO_INT,        bool,   "argument can't bash to int",           FATAL,       CALLSITE)
INLINE_OBSERVATION(ARG_NO_BASH_TO_REF,        bool,   "argument can't bash to ref",           FATAL,       CALLSITE)
INLINE_OBSERVATION(ARG_TYPES_INCOMPATIBLE,    bool,   "argument types incompatible",          FATAL,       CALLSITE)
INLINE_OBSERVATION(CANT_EMBED_PINVOKE_COOKIE, bool,   "can't embed pinvoke cookie",           FATAL,       CALLSITE)
INLINE_OBSERVATION(CANT_EMBED_VARARGS_COOKIE, bool,   "can't embed varargs cookie",           FATAL,       CALLSITE)
INLINE_OBSERVATION(CANT_CLASS_INIT,           bool,   "can't class init",                     FATAL,       CALLSITE)
INLINE_OBSERVATION(COMPILATION_ERROR,         bool,   "compilation error",                    FATAL,       CALLSITE)
INLINE_OBSERVATION(COMPILATION_FAILURE,       bool,   "failed to compile",                    FATAL,       CALLSITE)
INLINE_OBSERVATION(EXPLICIT_TAIL_PREFIX,      bool,   "explicit tail prefix",                 FATAL,       CALLSITE)
INLINE_OBSERVATION(GENERIC_DICTIONARY_LOOKUP, bool,   "runtime dictionary lookup",            FATAL,       CALLSITE)
INLINE_OBSERVATION(HAS_CALL_VIA_LDVIRTFTN,    bool,   "call via ldvirtftn",                   FATAL,       CALLSITE)
INLINE_OBSERVATION(HAS_COMPLEX_HANDLE,        bool,   "complex handle access",                FATAL,       CALLSITE)
INLINE_OBSERVATION(IMPLICIT_REC_TAIL_CALL,    bool,   "implicit recursive tail call",         FATAL,       CALLSITE)
INLINE_OBSERVATION(IS_CALL_TO_HELPER,         bool,   "target is helper",                     FATAL,       CALLSITE)
INLINE_OBSERVATION(IS_NOT_DIRECT,             bool,   "target not direct",                    FATAL,       CALLSITE)
INLINE_OBSERVATION(IS_NOT_DIRECT_MANAGED,     bool,   "target not direct managed",            FATAL,       CALLSITE)
INLINE_OBSERVATION(IS_RECURSIVE,              bool,   "recursive",                            FATAL,       CALLSITE)
INLINE_OBSERVATION(IS_TOO_DEEP,               bool,   "too deep",                             FATAL,       CALLSITE)
INLINE_OBSERVATION(IS_VIRTUAL,                bool,   "virtual",                              FATAL,       CALLSITE)
INLINE_OBSERVATION(IS_VM_NOINLINE,            bool,   "noinline per VM",                      FATAL,       CALLSITE)
INLINE_OBSERVATION(IS_WITHIN_CATCH,           bool,   "within catch region",                  FATAL,       CALLSITE)
INLINE_OBSERVATION(IS_WITHIN_FILTER,          bool,   "within filter region",                 FATAL,       CALLSITE)
INLINE_OBSERVATION(LDARGA_NOT_LOCAL_VAR,      bool,   "ldarga not on local var",              FATAL,       CALLSITE)
INLINE_OBSERVATION(LDFLD_NEEDS_HELPER,        bool,   "ldfld needs helper",                   FATAL,       CALLSITE)
INLINE_OBSERVATION(LDVIRTFN_ON_NON_VIRTUAL,   bool,   "ldvirtfn on non-virtual",              FATAL,       CALLSITE)
INLINE_OBSERVATION(LOCALLOC_IN_LOOP,          bool,   "within loop, has localloc",            FATAL,       CALLSITE)
INLINE_OBSERVATION(LOCALLOC_SIZE_UNKNOWN,     bool,   "localloc size unknown",                FATAL,       CALLSITE)
INLINE_OBSERVATION(LOG_REPLAY_REJECT,         bool,   "rejected by log replay",               FATAL,       CALLSITE)
INLINE_OBSERVATION(NOT_CANDIDATE,             bool,   "not inline candidate",                 FATAL,       CALLSITE)
INLINE_OBSERVATION(NOT_PROFITABLE_INLINE,     bool,   "unprofitable inline",                  FATAL,       CALLSITE)
INLINE_OBSERVATION(OVER_BUDGET,               bool,   "inline exceeds budget",                FATAL,       CALLSITE)
INLINE_OBSERVATION(OVER_INLINE_LIMIT,         bool,   "limited by JitInlineLimit",            FATAL,       CALLSITE)
INLINE_OBSERVATION(PIN_IN_TRY_REGION,         bool,   "within try region, pinned",            FATAL,       CALLSITE)
INLINE_OBSERVATION(RANDOM_REJECT,             bool,   "random reject",                        FATAL,       CALLSITE)
INLINE_OBSERVATION(RETURN_TYPE_MISMATCH,      bool,   "return type mismatch",                 FATAL,       CALLSITE)
INLINE_OBSERVATION(STFLD_NEEDS_HELPER,        bool,   "stfld needs helper",                   FATAL,       CALLSITE)
INLINE_OBSERVATION(TOO_MANY_LOCALS,           bool,   "too many locals",                      FATAL,       CALLSITE)
INLINE_OBSERVATION(PINVOKE_EH,                bool,   "PInvoke call site with EH",            FATAL,       CALLSITE)

// ------ Call Site Performance -------

INLINE_OBSERVATION(RARE_GC_STRUCT,            bool,   "rarely called, has gc struct",         INFORMATION, CALLSITE)

// ------ Call Site Information -------

INLINE_OBSERVATION(NONGENERIC_CALLS_GENERIC,  bool,   "callee is generic and caller is not",  INFORMATION, CALLSITE)
INLINE_OBSERVATION(ARG_EXACT_CLS,             int,    "arg is of an exact class",             INFORMATION, CALLSITE)
INLINE_OBSERVATION(ARG_EXACT_CLS_SIG_IS_NOT,  int,    "arg is more concrete than in sig.",    INFORMATION, CALLSITE)
INLINE_OBSERVATION(ARG_CONST,                 int,    "arg is a constant",                    INFORMATION, CALLSITE)
INLINE_OBSERVATION(ARG_BOXED,                 int,    "arg is boxed at call site",            INFORMATION, CALLSITE)
INLINE_OBSERVATION(FOLDABLE_INTRINSIC,        int,    "foldable intrinsic",                   INFORMATION, CALLSITE)
INLINE_OBSERVATION(FOLDABLE_EXPR,             int,    "foldable binary expression",           INFORMATION, CALLSITE)
INLINE_OBSERVATION(FOLDABLE_EXPR_UN,          int,    "foldable unary expression",            INFORMATION, CALLSITE)
INLINE_OBSERVATION(FOLDABLE_BRANCH,           int,    "foldable branch",                      INFORMATION, CALLSITE)
INLINE_OBSERVATION(FOLDABLE_SWITCH,           int,    "foldable switch",                      INFORMATION, CALLSITE)
INLINE_OBSERVATION(UNROLLABLE_MEMOP,          int,    "unrollable memmove/memcmp",            INFORMATION, CALLSITE)
INLINE_OBSERVATION(DIV_BY_CNS,                int,    "dividy by const",                      INFORMATION, CALLSITE)
INLINE_OBSERVATION(CONSTANT_ARG_FEEDS_TEST,   bool,   "constant argument feeds test",         INFORMATION, CALLSITE)
INLINE_OBSERVATION(DEPTH,                     int,    "depth",                                INFORMATION, CALLSITE)
INLINE_OBSERVATION(FREQUENCY,                 int,    "rough call site frequency",            INFORMATION, CALLSITE)
INLINE_OBSERVATION(HAS_PROFILE_WEIGHTS,       bool,   "profile weights are available",        INFORMATION, CALLSITE)
INLINE_OBSERVATION(INSIDE_THROW_BLOCK,        bool,   "inside throw block",                   INFORMATION, CALLSITE)
INLINE_OBSERVATION(IN_LOOP,                   bool,   "call site is in a loop",               INFORMATION, CALLSITE)
INLINE_OBSERVATION(IN_TRY_REGION,             bool,   "call site is in a try region",         INFORMATION, CALLSITE)
INLINE_OBSERVATION(IN_NORETURN_REGION,        bool,   "call site is in a no-return region",   INFORMATION, CALLSITE)
INLINE_OBSERVATION(IS_PROFITABLE_INLINE,      bool,   "profitable inline",                    INFORMATION, CALLSITE)
INLINE_OBSERVATION(IS_SAME_THIS,              bool,   "same this as root caller",             INFORMATION, CALLSITE)
INLINE_OBSERVATION(IS_SIZE_DECREASING_INLINE, bool,   "size decreasing inline",               INFORMATION, CALLSITE)
INLINE_OBSERVATION(LOG_REPLAY_ACCEPT,         bool,   "accepted by log replay",               INFORMATION, CALLSITE)
INLINE_OBSERVATION(PROFILE_FREQUENCY,         double, "frequency from profile data",          INFORMATION, CALLSITE)
INLINE_OBSERVATION(RANDOM_ACCEPT,             bool,   "random accept",                        INFORMATION, CALLSITE)
INLINE_OBSERVATION(WEIGHT,                    int,    "frequency from block weight",          INFORMATION, CALLSITE)

// ------ Final Sentinel -------

INLINE_OBSERVATION(UNUSED_FINAL,              bool,   "unused final observation",             FATAL,       CALLEE)

