|
@@ -66,6 +66,7 @@ interface
|
|
|
function first_int_real: tnode; virtual;
|
|
|
function first_abs_long: tnode; virtual;
|
|
|
function first_setlength: tnode; virtual;
|
|
|
+ function first_copy: tnode; virtual;
|
|
|
{ This one by default generates an internal error, because such
|
|
|
nodes are not generated by the parser. It's however used internally
|
|
|
by the JVM backend to create new dynamic arrays. }
|
|
@@ -79,6 +80,7 @@ interface
|
|
|
function handle_read_write: tnode;
|
|
|
function handle_val: tnode;
|
|
|
function handle_setlength: tnode;
|
|
|
+ function handle_copy: tnode;
|
|
|
end;
|
|
|
tinlinenodeclass = class of tinlinenode;
|
|
|
|
|
@@ -1429,6 +1431,68 @@ implementation
|
|
|
result:=nil;
|
|
|
end;
|
|
|
|
|
|
+
|
|
|
+ function tinlinenode.handle_copy: tnode;
|
|
|
+ var
|
|
|
+ lowppn,
|
|
|
+ highppn,
|
|
|
+ npara,
|
|
|
+ paras : tnode;
|
|
|
+ ppn : tcallparanode;
|
|
|
+ paradef : tdef;
|
|
|
+ counter : integer;
|
|
|
+ begin
|
|
|
+ result:=nil;
|
|
|
+ { determine copy function to use based on the first argument,
|
|
|
+ also count the number of arguments in this loop }
|
|
|
+ counter:=1;
|
|
|
+ paras:=left;
|
|
|
+ ppn:=tcallparanode(paras);
|
|
|
+ while assigned(ppn.right) do
|
|
|
+ begin
|
|
|
+ inc(counter);
|
|
|
+ ppn:=tcallparanode(ppn.right);
|
|
|
+ end;
|
|
|
+ paradef:=ppn.left.resultdef;
|
|
|
+ if is_ansistring(paradef) or
|
|
|
+ (is_chararray(paradef) and
|
|
|
+ (paradef.size>255)) or
|
|
|
+ ((cs_ansistrings in current_settings.localswitches) and
|
|
|
+ is_pchar(paradef)) then
|
|
|
+ resultdef:=cansistringtype
|
|
|
+ else
|
|
|
+ if is_widestring(paradef) then
|
|
|
+ resultdef:=cwidestringtype
|
|
|
+ else
|
|
|
+ if is_unicodestring(paradef) or
|
|
|
+ is_widechararray(paradef) or
|
|
|
+ is_pwidechar(paradef) then
|
|
|
+ resultdef:=cunicodestringtype
|
|
|
+ else
|
|
|
+ if is_char(paradef) then
|
|
|
+ resultdef:=cshortstringtype
|
|
|
+ else
|
|
|
+ if is_dynamic_array(paradef) then
|
|
|
+ begin
|
|
|
+ { Only allow 1 or 3 arguments }
|
|
|
+ if (counter<>1) and (counter<>3) then
|
|
|
+ begin
|
|
|
+ CGMessage1(parser_e_wrong_parameter_size,'Copy');
|
|
|
+ exit;
|
|
|
+ end;
|
|
|
+ resultdef:=paradef;
|
|
|
+ end
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ { generic fallback that will give an error if a wrong
|
|
|
+ type is passed }
|
|
|
+ if (counter=3) then
|
|
|
+ resultdef:=cshortstringtype
|
|
|
+ else
|
|
|
+ CGMessagePos(ppn.left.fileinfo,type_e_mismatch);
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+
|
|
|
{$maxfpuregisters 0}
|
|
|
|
|
|
function getpi : bestreal;
|
|
@@ -2481,6 +2545,9 @@ implementation
|
|
|
end;
|
|
|
end;
|
|
|
|
|
|
+ in_copy_x:
|
|
|
+ result:=handle_copy;
|
|
|
+
|
|
|
in_initialize_x,
|
|
|
in_finalize_x:
|
|
|
begin
|
|
@@ -2964,6 +3031,8 @@ implementation
|
|
|
|
|
|
in_setlength_x:
|
|
|
result:=first_setlength;
|
|
|
+ in_copy_x:
|
|
|
+ result:=first_copy;
|
|
|
in_initialize_x,
|
|
|
in_finalize_x:
|
|
|
begin
|
|
@@ -3417,6 +3486,70 @@ implementation
|
|
|
result:=newblock;
|
|
|
end;
|
|
|
|
|
|
+ function tinlinenode.first_copy: tnode;
|
|
|
+ var
|
|
|
+ lowppn,
|
|
|
+ highppn,
|
|
|
+ npara,
|
|
|
+ paras : tnode;
|
|
|
+ ppn : tcallparanode;
|
|
|
+ paradef : tdef;
|
|
|
+ counter : integer;
|
|
|
+ begin
|
|
|
+ { determine copy function to use based on the first argument,
|
|
|
+ also count the number of arguments in this loop }
|
|
|
+ counter:=1;
|
|
|
+ paras:=left;
|
|
|
+ ppn:=tcallparanode(paras);
|
|
|
+ while assigned(ppn.right) do
|
|
|
+ begin
|
|
|
+ inc(counter);
|
|
|
+ ppn:=tcallparanode(ppn.right);
|
|
|
+ end;
|
|
|
+ paradef:=ppn.left.resultdef;
|
|
|
+ if is_ansistring(resultdef) then
|
|
|
+ result:=ccallnode.createintern('fpc_ansistr_copy',paras)
|
|
|
+ else if is_widestring(resultdef) then
|
|
|
+ result:=ccallnode.createintern('fpc_widestr_copy',paras)
|
|
|
+ else if is_unicodestring(resultdef) then
|
|
|
+ result:=ccallnode.createintern('fpc_unicodestr_copy',paras)
|
|
|
+ { can't check for resultdef = cchartype, because resultdef=
|
|
|
+ cshortstringtype here }
|
|
|
+ else if is_char(paradef) then
|
|
|
+ result:=ccallnode.createintern('fpc_char_copy',paras)
|
|
|
+ else if is_dynamic_array(resultdef) then
|
|
|
+ begin
|
|
|
+ { create statements with call }
|
|
|
+ if (counter=3) then
|
|
|
+ begin
|
|
|
+ highppn:=tcallparanode(paras).left.getcopy;
|
|
|
+ lowppn:=tcallparanode(tcallparanode(paras).right).left.getcopy;
|
|
|
+ end
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ { use special -1,-1 argument to copy the whole array }
|
|
|
+ highppn:=cordconstnode.create(int64(-1),s32inttype,false);
|
|
|
+ lowppn:=cordconstnode.create(int64(-1),s32inttype,false);
|
|
|
+ end;
|
|
|
+
|
|
|
+ { create call to fpc_dynarray_copy }
|
|
|
+ npara:=ccallparanode.create(highppn,
|
|
|
+ ccallparanode.create(lowppn,
|
|
|
+ ccallparanode.create(caddrnode.create_internal
|
|
|
+ (crttinode.create(tstoreddef(ppn.left.resultdef),initrtti,rdt_normal)),
|
|
|
+ ccallparanode.create
|
|
|
+ (ctypeconvnode.create_internal(ppn.left,voidpointertype),nil))));
|
|
|
+ result:=ccallnode.createinternres('fpc_dynarray_copy',npara,ppn.left.resultdef);
|
|
|
+
|
|
|
+ ppn.left:=nil;
|
|
|
+ paras.free;
|
|
|
+ end
|
|
|
+ else
|
|
|
+ result:=ccallnode.createintern('fpc_shortstr_copy',paras);
|
|
|
+ { parameters are reused }
|
|
|
+ left:=nil;
|
|
|
+ end;
|
|
|
+
|
|
|
function tinlinenode.first_new: tnode;
|
|
|
begin
|
|
|
internalerror(2011012201);
|