[cfe-dev] [RFC] Module Flags Metadata

Bill Wendling wendling at apple.com
Wed Jan 18 13:36:25 PST 2012


Hello,

This is a proposal for implementing "module flags". Please take a look at this and give any feedback you may have.

Thanks!
-bw

                         Module Flags Metadata

Information about the module as a whole is difficult to convey to LLVM's
subsystems. The LLVM IR isn't sufficient to transmit this information. One
should instead use the llvm.module.flags named metadata. These flags are in the
form of a key / value pair -- much like a dictionary -- making it easy for any
subsystem who cares about a flag to look it up.

The llvm.module.flags metadata contains a list of metadata triplets. Each
triplet has the following form:

  - The first element is a "behavior" flag, which specifies the behavior when
    two (or more) modules are merged together, and it encounters two (or more)
    metadata with the same ID. The supported behaviors are described below.

  - The second element is a metadata string that is a unique ID for the
    metadata. How each ID is interpreted is documented below.

  - The third element is the value of the metadata.

When two (or more) modules are merged together, the resulting llvm.module.flags
metadata is the union of the modules' llvm.module.flags metadata. The only
exception being a flag with the 'Override' behavior, which may override another
flag's value (see below).

The following behavior flags are supported:

   Value        Behavior
   -----        --------
     1          Error
                  Emits an error if two values disagree.

     2          Warning
                  Emits a warning if two values disagree.

     3          Require

                  Emits an error when the specified value is not present or
                  doesn't have the specified value. It is an error for two (or
                  more) llvm.module.flags with the same ID to have the Require
                  behavior but different values. There may be multiple Require
                  flags per ID.

     4          Override
                  Uses the specified value if the two values disagree. It is an
                  error for two (or more) llvm.module.flags with the same ID to
                  have the Override behavior but different values.

An example of module flags:

  !0 = metadata !{ i32 1, metadata !"foo", i32 1 }
  !1 = metadata !{ i32 4, metadata !"bar", i32 37 }
  !2 = metadata !{ i32 2, metadata !"qux", i32 42 }
  !3 = metadata !{ i32 3, metadata !"qux",
    metadata !{
      metadata !"foo", i32 1
    }
  }
  !llvm.module.flags = !{ !0, !1, !2, !3 }

- Metadata !0 has the ID !"foo" and the value '1'. The behavior if two or more
  !"foo" flags are seen is to emit an error if their values are not equal.

- Metadata !1 has the ID !"bar" and the value '37'. The behavior if two or more
  !"bar" flags are seen is to use the value '37' if their values are not equal.

- Metadata !2 has the ID !"qux" and the value '42'. The behavior if two or more
  !"qux" flags are seen is to emit a warning if their values are not equal.

- Metadata !3 has the ID !"qux" and the value:

           metadata !{ metadata !"foo", i32 1 }

  The behavior is to emit an error if the llvm.module.flags does not contain a
  flag with the ID !"foo" that has the value '1'. If two or more !"qux" flags
  exist, then they must have the same value or an error will be issued.


Objective-C Metadata
--------------------

To correctly link two or more Objective-C modules, the linker needs to know
quite a bit of information about the language and how the modules were
compiled. These flags are concerned with ABI versions and garbage collection,
since they cannot conflict. The MachO writer uses these values to generate the
"image info" section, and merges the values from different modules in an
"intelligent" fashion rather than append them together.

The supported names are:

* Objective-C Version
   - The version of the Objective-C ABI. Valid values are '1' and '2'. It's an
     error for two or more Objective-C Version flags to have different values.

* Objective-C Garbage Collection Version
   - The garbage collection version, used by the image info section. Currently
     always '0'. It is an error for two or more "Objective-C Garbage Collection
     Value" flags to have different values.

* Objective-C Garbage Collection
   - Specifies that this module supports garbage collection. Valid values are
     '0' and '2'. A flag with the value of '0' will override one with the value
     of '2'.

* Objective-C GC Only
   - Specifies that this module requires garbage collection. This requires that
     the "Objective-C Garbage Collection" metadata is present and has a value of
     '2'. If present the valid value is '4'.

* Objective-C Image Info Section
   - The image info section holds information about Objective-C garbage
     collection. The "Objective-C Image Info Section" specifies the name of the
     section where the image info is placed. This flag is required if the
     "Objective-C Garbage Collection" flag is present and has the value of
     '2'. It is an error for two or more of these flags to have different
     values.

Here is an example of how to use the Objective-C metadata:

Module A
--------
!0 = metadata !{ i32 1, metadata !"Objective-C Version", i32 2 }
!1 = metadata !{ i32 1, metadata !"Objective-C Garbage Collection Version", i32 0 }
!2 = metadata !{ i32 1, metadata !"Objective-C Garbage Collection", i32 2 }
!3 = metadata !{ i32 3, metadata !"Objective-C Garbage Collection",
  metadata !{
    metadata !"Objective-C Image Info Section",
    metadata !"__DATA, __objc_imageinfo, regular, no_dead_strip"
  }
}
!4 = metadata !{ i32 1, metadata !"Objective-C Image Info Section",
                 metadata !"__DATA, __objc_imageinfo, regular, no_dead_strip" }
!llvm.module.flags = !{ !0, !1, !2, !3, !4 }

Module B
--------
!0 = metadata !{ i32 1, metadata !"Objective-C Version", i32 2 }
!1 = metadata !{ i32 1, metadata !"Objective-C Garbage Collection Version", i32 0 }
!2 = metadata !{ i32 1, metadata !"Objective-C Garbage Collection", i32 2 }
!3 = metadata !{ i32 3, metadata !"Objective-C Garbage Collection",
  metadata !{
    metadata !"Objective-C Image Info Section",
    metadata !"__DATA, __objc_imageinfo, regular, no_dead_strip"
  }
}
!4 = metadata !{ i32 1, metadata !"Objective-C GC Only", i32 4 }
!5 = metadata !{ i32 3, metadata !"Objective-C GC Only",
 metadata !{
   metadata !"Objective-C Garbage Collection", i32 2
 }
}
!6 = metadata !{ i32 1, metadata !"Objective-C Image Info Section",
                 metadata !"__DATA, __objc_imageinfo, regular, no_dead_strip" }
!llvm.module.flags = !{ !0, !1, !2, !3, !4, !5, !6 }

Linked Module
-------------
!0 = metadata !{ i32 1, metadata !"Objective-C Version", i32 2 }
!1 = metadata !{ i32 1, metadata !"Objective-C Garbage Collection Version", i32 0 }
!2 = metadata !{ i32 1, metadata !"Objective-C Garbage Collection", i32 2 }
!3 = metadata !{ i32 3, metadata !"Objective-C Garbage Collection",
  metadata !{
    metadata !"Objective-C Image Info Section",
    metadata !"__DATA, __objc_imageinfo, regular, no_dead_strip"
  }
}
!4 = metadata !{ i32 1, metadata !"Objective-C GC Only", i32 4 }
!5 = metadata !{ i32 3, metadata !"Objective-C GC Only",
  metadata !{
    metadata !"Objective-C Garbage Collection", i32 2
  }
}
!6 = metadata !{ i32 1, metadata !"Objective-C Image Info Section",
                 metadata !"__DATA, __objc_imageinfo, regular, no_dead_strip" }
!llvm.module.flags = !{ !0, !1, !2, !3, !4, !5, !6 }




More information about the cfe-dev mailing list