CPS is great
a new calling convention sketched above could be useful as well
Rust being one of the languages that could use it
The most awkward part is the requirement to order items on stack. I still see it as necessary. This comment is to spell out the "rule" better:
- I see a case for introducing a new kind of local
let
bindings in anfn
: so calleddyn
let bindings- already existing unsized local traits:
dyn Trait
- already existing unsized arrays - suggestion here is to change syntax from
T[]
todyn T[]
; I'm suggesting to change syntax so as to avoid false similarity with unsized members of structs - new kind of local
let
bindings:- regular local variables of known concrete type but allocated dynamically via
alloca
struct S {..} fn ...() .. { let s : dyn S = ...;
- the difference is that programmer has a degree of control over where exactly on the stack they will be located
- if such a variable is assigned to after an unsized local like
dyn Trait
has been assigned to then the programmer can be assured that it will be allocated on stack after the saiddyn Trait
- further when concrete types are returned via the new CC they become exactly this:
dyn ConcreteType
- regular local variables of known concrete type but allocated dynamically via
- already existing unsized local traits:
- once we have introduced the new kind of local
let
bindings the rule is now this:- when constructing a tuple with
dyn
members to be returned via the new CC - only regular (non-
dyn
) local bindings, onlydyn
local bindings or a mix thereof can be used - if a mix is used all regular (non-
dyn
) local bindings have to come before alldyn
local bindings - all bindings used to construct such tuples
dyn
or not have to be declared in the order they are used to construct them - all
dyn
bindings used to construct such tuples which are unsized (dyn Trait
,dyn T[]
) have to be assigned to in the order they have been declared - all
dyn
bindings used to construct such tuples which are sized (dyn ConcreteType
) have to be assigned to only after all preceding unsizeddyn
bindings (dyn Trait
,dyn T[]
) used to construct such tuples have been assigned too; this is because only after that has happened the exact location of the saiddyn ConcreteType
on stack can be determined - the compiler then guarantees to lay them them out on stack - both
dyn
and notdyn
- in the order they were declared; so alldyn
will come after all non-dyn
- if these rules cannot be followed the programmer needs to resort to explicitly creating new copies of some of the local variables involved or to invoke some sort of compiler provided facility to automate this; the surface syntax for the new facility may look like a macro invocation
- when constructing a tuple with
- the purpose of introducing this rather complex rule is that the objects returned via such tuple can be compacted - shifted up the stack - in the simplest possible manner
- in particular the goal is to ensure that the code doing the shifting doesn't have any conditional branches; just a sequence of straight-forward size/location calculations and
memcpy
-s
- in particular the goal is to ensure that the code doing the shifting doesn't have any conditional branches; just a sequence of straight-forward size/location calculations and
- the purpose of not always automating this - and indeed forcing programmer to manually create extra copies or to manually invoke the built-in mechanism helping with this - is to make programmer aware that the
fn
as written is indeed incurring extra costs and to push programmer where possible into writingfn
-s in such a manner that this extra shifting of objects is not necessary