Zero-extending function parameters on x86_64

Hi llvm-dev,

Yesterday we've noticed (
that on x86_64 a function declaration created by getOrInsertFunction()
must set the zeroext attribute for each parameter that is smaller than
64 bits.
Failing to do so may result in LLVM passing garbage in the upper bits
of the registers instead of zeroing them out in the caller. In some
cases the garbage may be passed on from the called function.

I've started going through sanitizer instrumentation passes and
noticed some of them also declare functions with e.g. i32 parameters
lacking the zeroext attribute. There also are other LLVM passes that
don't set the zeroext attribute for function parameters.

I find this a little counterintuitive that every user of
getOrInsertFunction() should think about whatever possible ABI
conventions and opt-in into the zeroext attribute.
Is it feasible to make getOrInsertFunction() take care of this
automatically depending on the target?


I think for x86_64, everything is supposed to be extended to 32-bits, but it doesn’t need to go wider. At least, that was the conclusion that I took away from the last time this came up:

In that case, LLVM combined two i32 loads to one i64 load and left the second i32 in the high bits of the register passed into libjpegturbo assembly. It was decided that this was correct, and libjpegturbo needed to zext.

For i8s and i16s, those have to be extended to i32, but LLVM doesn’t know if they are signed or unsigned, so it doesn’t guess. Leaving behind garbage is pretty useless and maybe even inefficient (partial register dependency). I’m still inclined to chalk this up to another LLVM usability issue for non-C frontends. There’s still a lot of work to be done in that area, and this is just one of many usability problems.