byval attr for base+range parameters

Hello guys,

For single scalar pointer parameter, we have 'byval' to specify the
pointee is not changed. But for base+range parameters like:
declare void @_gfortran_transfer_integer_write(%struct.__st_parameter_dt*,
i8*, i32)
(This is the fortran runtime api to 'printf' one integer) The 2nd &
3rd args are used to specify the memory of that integer. I didn't find
a comfortable way to specify that it's 'byval'. I need this to make
argpromotion work. Right now I just create an alloca, load value into
it, and specify this alloca(base+range) as parameter. Is it a
missing feature or there is a solution already?

thanks,
yuanfang

That is not what byval does. byval implicitly copies the pointee into the argument slots used for the call or registers on some architectures.

Thanks Reid. I looked into the argpromotion code and you are right.
'byval' does not work for this case. I think I'll stick to my
workaround for now. But I don't quite understand why argpromotion
does not check for readonly use other than (GEPorNonGEP) LoadInst.
For case like

define void @checksum_(i32* noalias %i) {
  . . . load %i
  call void @_gfortran_transfer_integer_write(%xx, %i, 4)
}

If type of
@_gfortran_transfer_integer_write(%struct.__st_parameter_dt*, i8*,
i32) is changed to
@_gfortran_transfer_integer_write(%struct.__st_parameter_dt*, i8* byval, i32)

It makes sense to argpro %i of checksum_ , right?

Your example doesn’t seem complete enough, but I don’t think arg promotion is the tool you want here.

Adding byval in this example would be equivalent to:
%i.load = load i8* %i
@_gfortran_transfer_integer_write(%struct.__st_parameter_dt*, i8 %i.load, i32)

Arg promotion is really designed to eliminate awkward constructs like byval when possible and extra indirection when possible (say, a min implementation that takes const int references).