When generating code to access inline assembly operands, clang is either passing them by-value or by-reference depending on the type of data. Input operands that are either scalars or scalarizable aggregates are loaded on registers before the inline assembly call. Similarly, output operands of the same kind are stored in memory following the inline assembly call. To perfrom such loads and stores, clang has to bitcast the operand type to an integer first. This would not work for the ACLE type data512_t, which is essentially an aggregate type { [8 x i64] }: we could in theory use i512 and let the backend deal with it, but clang wouldn't be able to emit the store as there's no qualified type for such a large integer:
(from clang/test/CodeGen/X86/x86_64-PR42672.c)
63 // Check Clang reports an error if attempting to return a big structure via a register. 64 void big_struct(void) { 65 #ifdef IMPOSSIBLE_BIG 66 struct { 67 long long int v1, v2, v3, v4; 68 } str; 69 asm("nop" 70 : "=r"(str)); 71 #endif 72 } 73 // CHECK-IMPOSSIBLE_BIG: impossible constraint in asm: can't store value into a register
Since clang's preference for scalarizable aggregates is be to pass them by-value, we need a way to tell whether a very large scalarazible aggregate could be handled by the backend. In that case we should pass it by-reference instead of emiting a compilation error for large output operands. Input operands are not a problem as clang currently loads them on registers if they are less than or equal to 64 bits and a power of two. Anything else is passed by-reference. This patch adds a target hook to determine whether an aggregate value of a given size can be dealt by the backend.