John McCall via llvm-dev
2016-Mar-03 21:08 UTC
[llvm-dev] RFC: Implementing the Swift calling convention in LLVM and Clang
> On Mar 3, 2016, at 10:06 AM, Renato Golin <renato.golin at linaro.org> wrote: > On 3 March 2016 at 17:36, John McCall <rjmccall at apple.com> wrote: >> I’m not sure of your point here. We don’t use the Swift CC to call C functions. >> It does not matter, at all, whether the frontend lowering of an aggregate under >> the Swift CC resembles the frontend lowering of the same aggregate under AAPCS. > > Right, ignore me, then. > > >> I’m not sure why you say that. We already do have parameter ABI override >> attributes with target-specific behavior in LLVM IR: sret and inreg. > > Their meaning is somewhat confused and hard-coded in the back-end. I > once wanted to use inreg for lowering register-based divmod in > SelectionDAG, but ended up implementing custom lowering in the ARM > back-end because inreg wasn't used correctly. It's possible that now > it's better, but you'll always be at the mercy of what the back-end > does with the attributes, especially in custom lowering. > > Also, for different back-ends, "inreg" means different things. If the > PCS allows multiple argument/return registers, then sret inreg is > possible for a structure with up to X/Y words, where X and Y are > different for different targets and could very well be zero. > > Example, in a machine with *two* PCS registers: > > i64 @foo (i32) > > returning in registers becomes: sret { i32, i32 } @foo (inreg i32) > > then you add your error: sret { i32, i32, i8* } @foo (inreg i32, inreg i8*) > > You can fit the two arguments in registers, but you can't fit the > result + error in your sret. > > Targets will have to deal with that in the DAG, if you don't do that > in IR. The ARM target would put the error pointer in the stack, which > is not where you want it to go. > > You'd probably need a way to mark portions of your sret as *must be > inreg* and others to be "nice to be inreg", so that you can spill the > result and not the error, if that's what you want.Right, this is one very good reason I would prefer to keep the error-result modelled as a parameter rather than mixing it in with the return value. Also, recall that the error-result is supposed to be assigned to a register that isn’t normally used for return values (or arguments, for that matter).>> Having that sort of ability might make some special cases easier for C lowering, >> too, come to think of it. Imagine an x86 ABI that — based on type information >> otherwise erased by the conversion to LLVM IR — sometimes returns a float in >> an SSE register and sometimes on the x86 stack. It would be very awkward to >> express that today, but some sort of abi(“x87”) attribute would make it easy. > > If this is kept in Swift PCS only, and if the compiler always agree on > which registers you're using, that's ok. > > But if you call a C function, or a new version of LLVM decides to use > a different register, you'll have run-time problems.A new version of LLVM really can’t just decide to use a different register once there’s an agreed interpretation. It sounds like the problem you were running into with “inreg” was that the ARM backend didn’t have a stable meaning for it, probably because the ARM target doesn’t allow the frontend features (regparm/sseregparm) that inreg is designed for. But there are targets — i386, chiefly — where inreg has a defined, stable meaning precisely because regparm has a defined, stable meaning. It seems to me that an abi(“context”) attribute would be more like the latter than the former: any target that supports swiftcc would also have to assign a stable meaning for abi(“context”). John.> > That's why ARM has different standards for hard and soft float, which > cannot mix. > > cheers, > --renato
Renato Golin via llvm-dev
2016-Mar-04 14:03 UTC
[llvm-dev] RFC: Implementing the Swift calling convention in LLVM and Clang
On 3 March 2016 at 21:08, John McCall <rjmccall at apple.com> wrote:> Right, this is one very good reason I would prefer to keep the error-result > modelled as a parameter rather than mixing it in with the return value.Ok, so we're on the same page here.> Also, recall that the error-result is supposed to be assigned to a register > that isn’t normally used for return values (or arguments, for that matter).This looks more complicated, though. The back-end knows how to lower standard PCS, so you'll have to teach that this particular argument violates that agreement in a very predictable fashion, ie. another ABI. If the non-PCS register you use is always the same (say the platform register), then you'll have to save/restore whenever you cross the boundaries between using/not-using (ex. between C and Swift functions). This sounds hard to get right. One way to know would be to identify all calls in IR that have different number of parameters, and do the save/restore there. Example: define @foo() { ... call @bar(i32, i8*) ... } define @bar(i32) You'd need to change the frame lowering code to identify the difference and, instead of bailing out, create the additional spills.> A new version of LLVM really can’t just decide to use a different register > once there’s an agreed interpretation.Good, so there will be a defined ABI. It originally sounded like you could choose "any register", but it seems you're actually going to define the exact behaviour in all supported platforms.> It seems to me that an abi(“context”) attribute > would be more like the latter than the former: any target that supports swiftcc > would also have to assign a stable meaning for abi(“context”).Makes sense. cheers, --renato
John McCall via llvm-dev
2016-Mar-04 19:17 UTC
[llvm-dev] RFC: Implementing the Swift calling convention in LLVM and Clang
> On Mar 4, 2016, at 6:03 AM, Renato Golin <renato.golin at linaro.org> wrote: > On 3 March 2016 at 21:08, John McCall <rjmccall at apple.com> wrote: >> Right, this is one very good reason I would prefer to keep the error-result >> modelled as a parameter rather than mixing it in with the return value. > > Ok, so we're on the same page here. > > >> Also, recall that the error-result is supposed to be assigned to a register >> that isn’t normally used for return values (or arguments, for that matter). > > This looks more complicated, though. > > The back-end knows how to lower standard PCS, so you'll have to teach > that this particular argument violates that agreement in a very > predictable fashion, ie. another ABI.We are using a different swiftcc convention in IR already, and we are fine with locking the error-result treatment to that CC.> If the non-PCS register you use is always the same (say the platform > register), then you'll have to save/restore whenever you cross the > boundaries between using/not-using (ex. between C and Swift > functions). This sounds hard to get right. > > One way to know would be to identify all calls in IR that have > different number of parameters, and do the save/restore there. > Example: > > define @foo() { > ... > call @bar(i32, i8*) > ... > } > > define @bar(i32) > > You'd need to change the frame lowering code to identify the > difference and, instead of bailing out, create the additional spills.I don’t think we can make this depend on statically recognizing when we’re passing extra arguments. That’s why, in our current implementation, whether or not the register is treated as an ordinary callee-save register or the magic error result is based on whether there’s an argument to the call (or function on the callee side) with that specific parameter attribute.>> A new version of LLVM really can’t just decide to use a different register >> once there’s an agreed interpretation. > > Good, so there will be a defined ABI. > > It originally sounded like you could choose "any register", but it > seems you're actually going to define the exact behaviour in all > supported platforms.Right. John.