> Can you post an overview of the implementation? Naively I'd have extended > GENERIC only and lowered all affected scalar accesses to > __builtin_bswapN (<load>) and <store> = __builtin_bswapN (...) and rely > on RTL expansion / combine to generate instructions for a target that > supports such byte-swapping loads/stores in HW.
That's the design, yes, although we don't explicitly lower to __builtin_bswap, except for very specific cases where the FE does some low-level fiddling, in which cases it directly generates a call to the Ada wrapper of the builtin. Only GENERIC is indeed extended (one flag on aggregate types and one flag on some _REF nodes) by using the following guidelines (quoting tree.h): The overall strategy is to preserve the invariant that every scalar in memory is associated with a single storage order, i.e. all accesses to this scalar are done with the same storage order. This invariant makes it possible to factor out the storage order in most transformations, as only the address and/or the value (in target order) matter for them. But, of course, the storage order must be preserved when the accesses themselves are rewritten or transformed. Then the byte swapping operations are made explicit during RTL expansion and, of course, you'd better have bswap<mode>2 patterns defined in your back-end. The storage order is a property attached to aggregate types, but nesting is supported as long as it can be defined consistently (i.e. the storage order only changes at byte boundaries), although you may need FE assistance here. The only (big) limitation is thay you cannot take the address of an individual field in these aggregate types, but in Ada it's not a problem since it's the default for any field in any aggregate type. -- Eric Botcazou