* Fixed parameter generation for dispatch calls: assuming that everything is passed by reference and needs only sizeof(ptruint) bytes is wrong. 64-bit primitive types (Double,Int64) are passed by value and require twice more space on 32-bit platforms.

git-svn-id: trunk@16350 -
This commit is contained in:
sergei 2010-11-16 11:55:09 +00:00
parent 6a4ea03acb
commit 2d860e356c

View File

@ -295,7 +295,6 @@ implementation
assignmenttype, assignmenttype,
vardatadef, vardatadef,
pvardatadef : tdef; pvardatadef : tdef;
dispatchbyref : boolean;
useresult: boolean; useresult: boolean;
restype: byte; restype: byte;
@ -313,18 +312,23 @@ implementation
dispintfinvoke, dispintfinvoke,
variantdispatch : boolean; variantdispatch : boolean;
procedure increase_paramssize; function is_byref_para(out assign_type: tdef): boolean;
begin begin
{ for now we pass everything by reference // !! This condition is subject to change, see Mantis #17904
case para.left.resultdef.typ of result:=(assigned(para.parasym) and (para.parasym.varspez in [vs_var,vs_out,vs_constref])) or
variantdef: (para.left.resultdef.typ in [variantdef]);
inc(paramssize,para.left.resultdef.size);
else if result then
} assign_type:=voidpointertype
inc(paramssize,voidpointertype.size); else
{ case para.left.resultdef.size of
end; 1..4:
} assign_type:=u32inttype;
8:
assign_type:=u64inttype;
else
internalerror(2007042801);
end;
end; end;
function getvardef(sourcedef: TDef): longint; function getvardef(sourcedef: TDef): longint;
@ -412,7 +416,8 @@ implementation
CGMessagePos1(para.left.fileinfo,type_e_not_automatable,para.left.resultdef.typename); CGMessagePos1(para.left.fileinfo,type_e_not_automatable,para.left.resultdef.typename);
{ we've to know the parameter size to allocate the temp. space } { we've to know the parameter size to allocate the temp. space }
increase_paramssize; is_byref_para(assignmenttype);
inc(paramssize, assignmenttype.size);
para:=tcallparanode(para.nextpara); para:=tcallparanode(para.nextpara);
end; end;
@ -461,41 +466,29 @@ implementation
internalerror(200611041); internalerror(200611041);
end; end;
dispatchbyref:=(assigned(para.parasym) and (para.parasym.varspez in [vs_var,vs_out,vs_constref])) or calldesc.argtypes[currargpos]:=getvardef(para.left.resultdef);
(para.left.resultdef.typ in [variantdef]);
{ assign the argument/parameter to the temporary location } { assign the argument/parameter to the temporary location }
if dispatchbyref then if is_byref_para(assignmenttype) then
begin
addstatement(statements,cassignmentnode.create(
ctypeconvnode.create_internal(cderefnode.create(caddnode.create(addn,
caddrnode.create(ctemprefnode.create(params)),
cordconstnode.create(qword(paramssize),ptruinttype,false)
)),voidpointertype),
ctypeconvnode.create_internal(caddrnode.create_internal(para.left),voidpointertype)));
calldesc.argtypes[currargpos]:=calldesc.argtypes[currargpos] or $80;
end
else
addstatement(statements,cassignmentnode.create( addstatement(statements,cassignmentnode.create(
ctypeconvnode.create_internal(cderefnode.create(caddnode.create(addn, ctypeconvnode.create_internal(cderefnode.create(caddnode.create(addn,
caddrnode.create(ctemprefnode.create(params)), caddrnode.create(ctemprefnode.create(params)),
cordconstnode.create(qword(paramssize),ptruinttype,false) cordconstnode.create(paramssize,ptruinttype,false)
)),voidpointertype), )),assignmenttype),
ctypeconvnode.create_internal(caddrnode.create_internal(para.left),voidpointertype))) ctypeconvnode.create_internal(para.left,assignmenttype)));
else
begin
case para.left.resultdef.size of
1..4:
assignmenttype:=u32inttype;
8:
assignmenttype:=u64inttype;
else
internalerror(2007042801);
end;
addstatement(statements,cassignmentnode.create(
ctypeconvnode.create_internal(cderefnode.create(caddnode.create(addn,
caddrnode.create(ctemprefnode.create(params)),
cordconstnode.create(paramssize,ptruinttype,false)
)),assignmenttype),
ctypeconvnode.create_internal(para.left,assignmenttype)));
end;
calldesc.argtypes[currargpos]:=getvardef(para.left.resultdef); inc(paramssize,assignmenttype.size);
if dispatchbyref then
calldesc.argtypes[currargpos]:=calldesc.argtypes[currargpos] or $80;
increase_paramssize;
para.left:=nil; para.left:=nil;
inc(currargpos); inc(currargpos);