[cfe-dev] Reading execise

Stefan Kanthak via cfe-dev cfe-dev at lists.llvm.org
Wed Sep 16 15:44:09 PDT 2020


<https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention#return-values>

| To return a user-defined type by value in RAX, it must have a length
| of 1, 2, 4, 8, 16, 32, or 64 bits. [...] Otherwise, the caller must
| allocate memory for the return value and pass a pointer to it as the
| first argument. The remaining arguments are then shifted one argument
| to the right. The same pointer must be returned by the callee in RAX.

--- incompatible.c ---
__attribute__((ms_abi))
__uint128_t buggy(__uint128_t a, __uint128_t b, __uint128_t c) {
    return a + b * c;
}
--- EOF ---

clang -mno-sse -o- -O3 -S -target amd64-pc-windows incompatible.c

buggy:                                  # @buggy
# %bb.0:
        movq    (%rdx), %r9             # OUCH: before it was destroyed,
                                        #       r9 held the address of c
        movq    (%r8), %rax
        movq    8(%rdx), %r10
        imulq   %rax, %r10
        mulq    %r9                     # OUCH: the source says b * c,
                                        #       NOT a * <something>
        imulq   8(%r8), %r9             # OUCH: idem
        addq    %r10, %rdx
        addq    %r9, %rdx
        addq    (%rcx), %rax            # OUCH: rcx holds the address of
                                        #       the return value!
                                        # OUCH: rax does NOT point to the
                                        #       return value!
        adcq    8(%rcx), %rdx           # OUCH: rcx holds the address of
                                        #       the return value!
        retq


Stefan


More information about the cfe-dev mailing list