#### 16.19.1 Defining Attributes and their Values

The `define_attr` expression is used to define each attribute required by the target machine. It looks like:

         (define_attr name list-of-values default)

name is a string specifying the name of the attribute being defined. Some attributes are used in a special way by the rest of the compiler. The `enabled` attribute can be used to conditionally enable or disable insn alternatives (see Disable Insn Alternatives). The `predicable` attribute, together with a suitable `define_cond_exec` (see Conditional Execution), can be used to automatically generate conditional variants of instruction patterns. The compiler internally uses the names `ce_enabled` and `nonce_enabled`, so they should not be used elsewhere as alternative names.

list-of-values is either a string that specifies a comma-separated list of values that can be assigned to the attribute, or a null string to indicate that the attribute takes numeric values.

default is an attribute expression that gives the value of this attribute for insns that match patterns whose definition does not include an explicit value for this attribute. See Attr Example, for more information on the handling of defaults. See Constant Attributes, for information on attributes that do not depend on any particular insn.

For each defined attribute, a number of definitions are written to the `insn-attr.h` file. For cases where an explicit set of values is specified for an attribute, the following are defined:

- A ‘`#define`’ is written for the symbol ‘`HAVE_ATTR_name`’.
- An enumerated class is defined for ‘`attr_name`’ with elements of the form ‘`upper-name_upper-value`’ where the attribute name and value are first converted to uppercase.
- A function ‘`get_attr_name`’ is defined that is passed an insn and returns the attribute value for that insn.

For example, if the following is present in the `md` file:

         (define_attr "type" "branch,fp,load,store,arith" ...)

the following lines will be written to the file `insn-attr.h`.

         #define HAVE_ATTR_type
         enum attr_type {TYPE_BRANCH, TYPE_FP, TYPE_LOAD,
                          TYPE_STORE, TYPE_ARITH};
         extern enum attr_type get_attr_type ();

If the attribute takes numeric values, no `enum` type will be defined and the function to obtain the attribute's value will return `int`.

There are attributes which are tied to a specific meaning. These attributes are not free to use for other purposes:

`length`
  The `length` attribute is used to calculate the length of emitted code chunks. This is especially important when verifying branch distances. See Insn Lengths.
`enabled`
  The `enabled` attribute can be defined to prevent certain alternatives of an insn definition from being used during code generation. See Disable Insn Alternatives.

Another way of defining an attribute is to use:

         (define_enum_attr "attr" "enum" default)

This works in just the same way as `define_attr`, except that the list of values is taken from a separate enumeration called enum (see define_enum). This form allows you to use the same list of values for several attributes without having to repeat the list each time. For example:

         (define_enum "processor" [
           model_a
           model_b
           ...
         ])
         (define_enum_attr "arch" "processor"
           (const (symbol_ref "target_arch")))
         (define_enum_attr "tune" "processor"
           (const (symbol_ref "target_tune")))

defines the same attributes as:

         (define_attr "arch" "model_a,model_b,..."
           (const (symbol_ref "target_arch")))
         (define_attr "tune" "model_a,model_b,..."
           (const (symbol_ref "target_tune")))

but without duplicating the processor list. The second example defines two separate C enums (`attr_arch` and `attr_tune`) whereas the first defines a single C enum (`processor`).