mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-16 23:21:57 +02:00
* procinlinenode removed
* aktexit2label removed, fast exit removed + tcallnode.inlined_pass_2 added
This commit is contained in:
parent
75394a788e
commit
047a066711
@ -188,9 +188,6 @@ unit cgbase;
|
||||
{ label to leave the sub routine }
|
||||
aktexitlabel : tasmlabel;
|
||||
|
||||
{ also an exit label, only used we need to clear only the stack }
|
||||
aktexit2label : tasmlabel;
|
||||
|
||||
{# true, if there was an error while code generation occurs }
|
||||
codegenerror : boolean;
|
||||
|
||||
@ -582,7 +579,12 @@ implementation
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.51 2003-05-23 14:27:35 peter
|
||||
Revision 1.52 2003-05-26 21:17:17 peter
|
||||
* procinlinenode removed
|
||||
* aktexit2label removed, fast exit removed
|
||||
+ tcallnode.inlined_pass_2 added
|
||||
|
||||
Revision 1.51 2003/05/23 14:27:35 peter
|
||||
* remove some unit dependencies
|
||||
* current_procinfo changes to store more info
|
||||
|
||||
|
@ -1180,8 +1180,7 @@ implementation
|
||||
if (m_delphi in aktmodeswitches) then
|
||||
exclude(po_comp,po_varargs);
|
||||
if ((po_comp * def1.procoptions)= (po_comp * def2.procoptions)) and
|
||||
equal_defs(def1.rettype.def,def2.rettype.def) and
|
||||
(def1.para_size(target_info.alignment.paraalign)=def2.para_size(target_info.alignment.paraalign)) then
|
||||
equal_defs(def1.rettype.def,def2.rettype.def) then
|
||||
begin
|
||||
{ return equal type based on the parameters, but a proc->procvar
|
||||
is never exact, so map an exact match of the parameters to
|
||||
@ -1211,7 +1210,12 @@ implementation
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.25 2003-05-15 18:58:53 peter
|
||||
Revision 1.26 2003-05-26 21:17:17 peter
|
||||
* procinlinenode removed
|
||||
* aktexit2label removed, fast exit removed
|
||||
+ tcallnode.inlined_pass_2 added
|
||||
|
||||
Revision 1.25 2003/05/15 18:58:53 peter
|
||||
* removed selfpointer_offset, vmtpointer_offset
|
||||
* tvarsym.adjusted_address
|
||||
* address in localsymtable is now in the real direction
|
||||
|
@ -456,19 +456,19 @@ begin
|
||||
funcResRegs := funcResRegs - [R_EAX,R_EBX,R_ECX,R_EDX,R_ESI];
|
||||
funcResReg := reg.enum in funcResRegs;
|
||||
hp1 := p;
|
||||
while not(funcResReg and
|
||||
{ while not(funcResReg and
|
||||
(p.typ = ait_instruction) and
|
||||
(Taicpu(p).opcode = A_JMP) and
|
||||
(tasmlabel(Taicpu(p).oper[0].sym) = aktexit2label)) and
|
||||
getLastInstruction(p, p) And
|
||||
not(regInInstruction(reg.enum, p)) Do
|
||||
hp1 := p;
|
||||
hp1 := p; }
|
||||
{ don't insert a dealloc for registers which contain the function result }
|
||||
{ if they are followed by a jump to the exit label (for exit(...)) }
|
||||
if not(funcResReg) or
|
||||
{if not(funcResReg) or
|
||||
not((hp1.typ = ait_instruction) and
|
||||
(Taicpu(hp1).opcode = A_JMP) and
|
||||
(tasmlabel(Taicpu(hp1).oper[0].sym) = aktexit2label)) then
|
||||
(tasmlabel(Taicpu(hp1).oper[0].sym) = aktexit2label)) then }
|
||||
begin
|
||||
p := tai_regalloc.deAlloc(reg);
|
||||
insertLLItem(AsmL, hp1.previous, hp1, p);
|
||||
@ -2669,7 +2669,12 @@ End.
|
||||
|
||||
{
|
||||
$Log$
|
||||
Revision 1.49 2003-04-27 11:21:35 peter
|
||||
Revision 1.50 2003-05-26 21:17:18 peter
|
||||
* procinlinenode removed
|
||||
* aktexit2label removed, fast exit removed
|
||||
+ tcallnode.inlined_pass_2 added
|
||||
|
||||
Revision 1.49 2003/04/27 11:21:35 peter
|
||||
* aktprocdef renamed to current_procdef
|
||||
* procinfo renamed to current_procinfo
|
||||
* procinfo will now be stored in current_module so it can be
|
||||
|
@ -34,7 +34,7 @@ interface
|
||||
type
|
||||
ti386callnode = class(tcgcallnode)
|
||||
protected
|
||||
function align_parasize(parasize,para_alignment:longint):longint;override;
|
||||
function align_parasize:longint;override;
|
||||
procedure pop_parasize(pop_size:longint);override;
|
||||
procedure extra_interrupt_code;override;
|
||||
end;
|
||||
@ -76,7 +76,7 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
function ti386callnode.align_parasize(parasize,para_alignment:longint):longint;
|
||||
function ti386callnode.align_parasize:longint;
|
||||
var
|
||||
pop_size : longint;
|
||||
{$ifdef OPTALIGN}
|
||||
@ -87,12 +87,8 @@ implementation
|
||||
rsp : tregister;
|
||||
begin
|
||||
pop_size:=0;
|
||||
{ Old pushedsize aligned on 4 ? }
|
||||
i:=parasize and 3;
|
||||
if i>0 then
|
||||
inc(pop_size,4-i);
|
||||
{ This parasize aligned on 4 ? }
|
||||
i:=procdefinition.para_size(para_alignment) and 3;
|
||||
i:=procdefinition.parast.datasize and 3;
|
||||
if i>0 then
|
||||
inc(pop_size,4-i);
|
||||
{ insert the opcode and update pushedparasize }
|
||||
@ -114,7 +110,7 @@ implementation
|
||||
if pop_allowed and (cs_align in aktglobalswitches) then
|
||||
begin
|
||||
pop_esp:=true;
|
||||
push_size:=procdefinition.para_size(para_alignment);
|
||||
push_size:=procdefinition.parast.datasize;
|
||||
{ !!!! here we have to take care of return type, self
|
||||
and nested procedures
|
||||
}
|
||||
@ -201,7 +197,12 @@ begin
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.91 2003-05-22 21:32:29 peter
|
||||
Revision 1.92 2003-05-26 21:17:18 peter
|
||||
* procinlinenode removed
|
||||
* aktexit2label removed, fast exit removed
|
||||
+ tcallnode.inlined_pass_2 added
|
||||
|
||||
Revision 1.91 2003/05/22 21:32:29 peter
|
||||
* removed some unit dependencies
|
||||
|
||||
Revision 1.90 2003/04/23 14:42:08 daniel
|
||||
|
@ -82,6 +82,8 @@ interface
|
||||
{ function return node, this is used to pass the data for a
|
||||
ret_in_param return value }
|
||||
funcretnode : tnode;
|
||||
{ inline function body }
|
||||
inlinecode : tnode;
|
||||
|
||||
{ separately specified resulttype for some compilerprocs (e.g. }
|
||||
{ you can't have a function with an "array of char" resulttype }
|
||||
@ -158,30 +160,12 @@ interface
|
||||
end;
|
||||
tcallparanodeclass = class of tcallparanode;
|
||||
|
||||
tprocinlinenode = class(tnode)
|
||||
inlinetree : tnode;
|
||||
inlineprocdef : tprocdef;
|
||||
retoffset,para_offset,para_size : longint;
|
||||
constructor create(p:tprocdef);virtual;
|
||||
destructor destroy;override;
|
||||
constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
|
||||
procedure ppuwrite(ppufile:tcompilerppufile);override;
|
||||
procedure derefimpl;override;
|
||||
function getcopy : tnode;override;
|
||||
function det_resulttype : tnode;override;
|
||||
procedure insertintolist(l : tnodelist);override;
|
||||
function pass_1 : tnode;override;
|
||||
function docompare(p: tnode): boolean; override;
|
||||
end;
|
||||
tprocinlinenodeclass = class of tprocinlinenode;
|
||||
|
||||
function reverseparameters(p: tcallparanode): tcallparanode;
|
||||
|
||||
|
||||
var
|
||||
ccallnode : tcallnodeclass;
|
||||
ccallparanode : tcallparanodeclass;
|
||||
cprocinlinenode : tprocinlinenodeclass;
|
||||
|
||||
implementation
|
||||
|
||||
@ -888,6 +872,7 @@ type
|
||||
procdefinition:=nil;
|
||||
restypeset:=false;
|
||||
funcretnode:=nil;
|
||||
inlinecode:=nil;
|
||||
paralength:=-1;
|
||||
end;
|
||||
|
||||
@ -902,6 +887,7 @@ type
|
||||
procdefinition:=def;
|
||||
restypeset:=false;
|
||||
funcretnode:=nil;
|
||||
inlinecode:=nil;
|
||||
paralength:=-1;
|
||||
end;
|
||||
|
||||
@ -916,6 +902,7 @@ type
|
||||
procdefinition:=nil;
|
||||
restypeset:=false;
|
||||
funcretnode:=nil;
|
||||
inlinecode:=nil;
|
||||
paralength:=-1;
|
||||
end;
|
||||
|
||||
@ -974,6 +961,7 @@ type
|
||||
begin
|
||||
methodpointer.free;
|
||||
funcretnode.free;
|
||||
inlinecode.free;
|
||||
inherited destroy;
|
||||
end;
|
||||
|
||||
@ -990,6 +978,7 @@ type
|
||||
restypeset:=boolean(ppufile.getbyte);
|
||||
methodpointer:=ppuloadnode(ppufile);
|
||||
funcretnode:=ppuloadnode(ppufile);
|
||||
inlinecode:=ppuloadnode(ppufile);
|
||||
end;
|
||||
|
||||
|
||||
@ -1001,6 +990,7 @@ type
|
||||
ppufile.putbyte(byte(restypeset));
|
||||
ppuwritenode(ppufile,methodpointer);
|
||||
ppuwritenode(ppufile,funcretnode);
|
||||
ppuwritenode(ppufile,inlinecode);
|
||||
end;
|
||||
|
||||
|
||||
@ -1014,6 +1004,8 @@ type
|
||||
methodpointer.derefimpl;
|
||||
if assigned(funcretnode) then
|
||||
funcretnode.derefimpl;
|
||||
if assigned(inlinecode) then
|
||||
inlinecode.derefimpl;
|
||||
end;
|
||||
|
||||
|
||||
@ -1035,6 +1027,10 @@ type
|
||||
n.funcretnode:=funcretnode.getcopy
|
||||
else
|
||||
n.funcretnode:=nil;
|
||||
if assigned(inlinecode) then
|
||||
n.inlinecode:=inlinecode.getcopy
|
||||
else
|
||||
n.inlinecode:=nil;
|
||||
result:=n;
|
||||
end;
|
||||
|
||||
@ -2270,13 +2266,12 @@ type
|
||||
|
||||
|
||||
function tcallnode.pass_1 : tnode;
|
||||
var
|
||||
inlinecode : tnode;
|
||||
inlined : boolean;
|
||||
{$ifdef m68k}
|
||||
var
|
||||
regi : tregister;
|
||||
{$endif}
|
||||
{$ifdef callparatemp}
|
||||
var
|
||||
callparatemps, newblock: tblocknode;
|
||||
statement: tstatementnode;
|
||||
paras, oldright, newcall: tnode;
|
||||
@ -2285,8 +2280,6 @@ type
|
||||
errorexit;
|
||||
begin
|
||||
result:=nil;
|
||||
inlined:=false;
|
||||
inlinecode := nil;
|
||||
|
||||
{ work trough all parameters to get the register requirements }
|
||||
if assigned(left) then
|
||||
@ -2300,15 +2293,6 @@ type
|
||||
if assigned(funcretnode) then
|
||||
firstpass(funcretnode);
|
||||
|
||||
if assigned(procdefinition) and
|
||||
(procdefinition.proccalloption=pocall_inline) then
|
||||
begin
|
||||
inlinecode:=right;
|
||||
if assigned(inlinecode) then
|
||||
inlined:=true;
|
||||
right:=nil;
|
||||
end;
|
||||
|
||||
{ procedure variable ? }
|
||||
if assigned(right) then
|
||||
begin
|
||||
@ -2329,22 +2313,20 @@ type
|
||||
begin
|
||||
if assigned(methodpointer) then
|
||||
CGMessage(cg_e_unable_inline_object_methods);
|
||||
if assigned(right) and (right.nodetype<>procinlinen) then
|
||||
if assigned(right) then
|
||||
CGMessage(cg_e_unable_inline_procvar);
|
||||
if not assigned(inlinecode) then
|
||||
if assigned(inlinecode) then
|
||||
internalerror(200305261);
|
||||
if assigned(tprocdef(procdefinition).code) then
|
||||
inlinecode:=tprocdef(procdefinition).code.getcopy
|
||||
else
|
||||
CGMessage(cg_e_no_code_for_inline_stored);
|
||||
if assigned(inlinecode) then
|
||||
begin
|
||||
if assigned(tprocdef(procdefinition).code) then
|
||||
inlinecode:=cprocinlinenode.create(tprocdef(procdefinition))
|
||||
else
|
||||
CGMessage(cg_e_no_code_for_inline_stored);
|
||||
if assigned(inlinecode) then
|
||||
begin
|
||||
{ consider it has not inlined if called
|
||||
again inside the args }
|
||||
procdefinition.proccalloption:=pocall_fpccall;
|
||||
firstpass(inlinecode);
|
||||
inlined:=true;
|
||||
end;
|
||||
{ consider it has not inlined if called
|
||||
again inside the args }
|
||||
procdefinition.proccalloption:=pocall_fpccall;
|
||||
firstpass(inlinecode);
|
||||
end;
|
||||
end
|
||||
else
|
||||
@ -2356,7 +2338,6 @@ type
|
||||
{ It doesn't hurt to calculate it already though :) (JM) }
|
||||
rg.incrementintregisterpushed(tprocdef(procdefinition).usedintregisters);
|
||||
rg.incrementotherregisterpushed(tprocdef(procdefinition).usedotherregisters);
|
||||
|
||||
end;
|
||||
|
||||
{ get a register for the return value }
|
||||
@ -2458,8 +2439,16 @@ type
|
||||
verifyabstractcalls;
|
||||
end;
|
||||
|
||||
if inlined then
|
||||
right:=inlinecode;
|
||||
{ determine the registers of the procedure variable }
|
||||
{ is this OK for inlined procs also ?? (PM) }
|
||||
if assigned(inlinecode) then
|
||||
begin
|
||||
registersfpu:=max(inlinecode.registersfpu,registersfpu);
|
||||
registers32:=max(inlinecode.registers32,registers32);
|
||||
{$ifdef SUPPORT_MMX}
|
||||
registersmmx:=max(inlinecode.registersmmx,registersmmx);
|
||||
{$endif SUPPORT_MMX}
|
||||
end;
|
||||
{ determine the registers of the procedure variable }
|
||||
{ is this OK for inlined procs also ?? (PM) }
|
||||
if assigned(right) then
|
||||
@ -2506,7 +2495,7 @@ type
|
||||
end;
|
||||
{$endif callparatemp}
|
||||
errorexit:
|
||||
if inlined then
|
||||
if assigned(inlinecode) then
|
||||
procdefinition.proccalloption:=pocall_inline;
|
||||
{$ifdef callparatemp}
|
||||
if assigned(callparatemps) then
|
||||
@ -2574,168 +2563,18 @@ type
|
||||
end;
|
||||
|
||||
|
||||
{****************************************************************************
|
||||
TPROCINLINENODE
|
||||
****************************************************************************}
|
||||
|
||||
constructor tprocinlinenode.create(p:tprocdef);
|
||||
|
||||
begin
|
||||
inherited create(procinlinen);
|
||||
inlineprocdef:=p;
|
||||
retoffset:=-POINTER_SIZE; { less dangerous as zero (PM) }
|
||||
para_offset:=0;
|
||||
para_size:=0;
|
||||
{ copy inlinetree }
|
||||
if assigned(p.code) then
|
||||
inlinetree:=p.code.getcopy
|
||||
else
|
||||
inlinetree:=nil;
|
||||
end;
|
||||
|
||||
|
||||
destructor tprocinlinenode.destroy;
|
||||
begin
|
||||
if assigned(inlinetree) then
|
||||
inlinetree.free;
|
||||
inherited destroy;
|
||||
end;
|
||||
|
||||
|
||||
constructor tprocinlinenode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
|
||||
begin
|
||||
inherited ppuload(t,ppufile);
|
||||
inlineprocdef:=tprocdef(ppufile.getderef);
|
||||
inlinetree:=ppuloadnode(ppufile);
|
||||
retoffset:=-POINTER_SIZE; { less dangerous as zero (PM) }
|
||||
para_offset:=0;
|
||||
para_size:=0;
|
||||
end;
|
||||
|
||||
|
||||
procedure tprocinlinenode.ppuwrite(ppufile:tcompilerppufile);
|
||||
begin
|
||||
inherited ppuwrite(ppufile);
|
||||
ppufile.putderef(inlineprocdef);
|
||||
ppuwritenode(ppufile,inlinetree);
|
||||
end;
|
||||
|
||||
|
||||
procedure tprocinlinenode.derefimpl;
|
||||
begin
|
||||
inherited derefimpl;
|
||||
if assigned(inlinetree) then
|
||||
inlinetree.derefimpl;
|
||||
resolvedef(pointer(inlineprocdef));
|
||||
end;
|
||||
|
||||
|
||||
function tprocinlinenode.getcopy : tnode;
|
||||
|
||||
var
|
||||
n : tprocinlinenode;
|
||||
|
||||
begin
|
||||
n:=tprocinlinenode(inherited getcopy);
|
||||
n.inlineprocdef:=inlineprocdef;
|
||||
if assigned(inlinetree) then
|
||||
n.inlinetree:=inlinetree.getcopy
|
||||
else
|
||||
n.inlinetree:=nil;
|
||||
n.retoffset:=retoffset;
|
||||
n.para_offset:=para_offset;
|
||||
n.para_size:=para_size;
|
||||
getcopy:=n;
|
||||
end;
|
||||
|
||||
procedure tprocinlinenode.insertintolist(l : tnodelist);
|
||||
|
||||
begin
|
||||
end;
|
||||
|
||||
|
||||
function tprocinlinenode.det_resulttype : tnode;
|
||||
var
|
||||
storesymtablelevel : longint;
|
||||
storeparasymtable,
|
||||
storelocalsymtable : tsymtabletype;
|
||||
oldprocdef : tprocdef;
|
||||
oldprocinfo : tprocinfo;
|
||||
oldinlining_procedure : boolean;
|
||||
begin
|
||||
result:=nil;
|
||||
oldinlining_procedure:=inlining_procedure;
|
||||
oldprocdef:=current_procdef;
|
||||
oldprocinfo:=current_procinfo;
|
||||
{ we're inlining a procedure }
|
||||
inlining_procedure:=true;
|
||||
|
||||
{ create temp procinfo }
|
||||
current_procinfo:=cprocinfo.create(nil);
|
||||
current_procinfo.procdef:=inlineprocdef;
|
||||
current_procinfo.return_offset:=retoffset;
|
||||
current_procdef:=current_procinfo.procdef;
|
||||
|
||||
{ set it to the same lexical level }
|
||||
storesymtablelevel:=current_procdef.localst.symtablelevel;
|
||||
storelocalsymtable:=current_procdef.localst.symtabletype;
|
||||
storeparasymtable:=current_procdef.parast.symtabletype;
|
||||
current_procdef.localst.symtablelevel:=oldprocdef.localst.symtablelevel;
|
||||
current_procdef.localst.symtabletype:=inlinelocalsymtable;
|
||||
current_procdef.parast.symtabletype:=inlineparasymtable;
|
||||
|
||||
{ pass inlinetree }
|
||||
resulttypepass(inlinetree);
|
||||
resulttype:=inlineprocdef.rettype;
|
||||
|
||||
{ retrieve info from inlineprocdef }
|
||||
retoffset:=-POINTER_SIZE; { less dangerous as zero (PM) }
|
||||
para_offset:=0;
|
||||
para_size:=inlineprocdef.para_size(target_info.alignment.paraalign);
|
||||
if paramanager.ret_in_param(inlineprocdef.rettype.def,inlineprocdef.proccalloption) then
|
||||
inc(para_size,POINTER_SIZE);
|
||||
|
||||
{ restore current_procinfo }
|
||||
current_procinfo.free;
|
||||
current_procinfo:=oldprocinfo;
|
||||
{ restore symtable }
|
||||
current_procdef.localst.symtablelevel:=storesymtablelevel;
|
||||
current_procdef.localst.symtabletype:=storelocalsymtable;
|
||||
current_procdef.parast.symtabletype:=storeparasymtable;
|
||||
{ restore }
|
||||
current_procdef:=oldprocdef;
|
||||
inlining_procedure:=oldinlining_procedure;
|
||||
end;
|
||||
|
||||
|
||||
function tprocinlinenode.pass_1 : tnode;
|
||||
begin
|
||||
firstpass(inlinetree);
|
||||
registers32:=inlinetree.registers32;
|
||||
registersfpu:=inlinetree.registersfpu;
|
||||
{$ifdef SUPPORT_MMX}
|
||||
registersmmx:=inlinetree.registersmmx;
|
||||
{$endif SUPPORT_MMX}
|
||||
result:=nil;
|
||||
end;
|
||||
|
||||
|
||||
function tprocinlinenode.docompare(p: tnode): boolean;
|
||||
begin
|
||||
docompare :=
|
||||
inherited docompare(p) and
|
||||
inlinetree.isequal(tprocinlinenode(p).inlinetree) and
|
||||
(inlineprocdef = tprocinlinenode(p).inlineprocdef);
|
||||
end;
|
||||
|
||||
begin
|
||||
ccallnode:=tcallnode;
|
||||
ccallparanode:=tcallparanode;
|
||||
cprocinlinenode:=tprocinlinenode;
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.161 2003-05-25 11:34:17 peter
|
||||
Revision 1.162 2003-05-26 21:17:17 peter
|
||||
* procinlinenode removed
|
||||
* aktexit2label removed, fast exit removed
|
||||
+ tcallnode.inlined_pass_2 added
|
||||
|
||||
Revision 1.161 2003/05/25 11:34:17 peter
|
||||
* methodpointer self pushing fixed
|
||||
|
||||
Revision 1.160 2003/05/25 08:59:16 peter
|
||||
|
@ -40,9 +40,13 @@ interface
|
||||
end;
|
||||
|
||||
tcgcallnode = class(tcallnode)
|
||||
private
|
||||
procedure release_para_temps;
|
||||
procedure normal_pass_2;
|
||||
procedure inlined_pass_2;
|
||||
protected
|
||||
refcountedtemp : treference;
|
||||
procedure handle_return_value(inlined:boolean);
|
||||
procedure handle_return_value;
|
||||
{# This routine is used to push the current frame pointer
|
||||
on the stack. This is used in nested routines where the
|
||||
value of the frame pointer is always pushed as an extra
|
||||
@ -52,7 +56,7 @@ interface
|
||||
most stack based machines, where the frame pointer is
|
||||
the first invisible parameter.
|
||||
}
|
||||
function align_parasize(parasize,para_alignment:longint):longint;virtual;
|
||||
function align_parasize:longint;virtual;
|
||||
procedure pop_parasize(pop_size:longint);virtual;
|
||||
procedure push_framepointer;virtual;
|
||||
procedure extra_interrupt_code;virtual;
|
||||
@ -60,10 +64,6 @@ interface
|
||||
procedure pass_2;override;
|
||||
end;
|
||||
|
||||
tcgprocinlinenode = class(tprocinlinenode)
|
||||
procedure pass_2;override;
|
||||
end;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
@ -123,12 +123,8 @@ implementation
|
||||
{ push from left to right if specified }
|
||||
if push_from_left_to_right and assigned(right) then
|
||||
begin
|
||||
if (nf_varargs_para in flags) then
|
||||
tcallparanode(right).secondcallparan(push_from_left_to_right,
|
||||
calloption,para_alignment,para_offset)
|
||||
else
|
||||
tcallparanode(right).secondcallparan(push_from_left_to_right,
|
||||
calloption,para_alignment,para_offset);
|
||||
tcallparanode(right).secondcallparan(push_from_left_to_right,
|
||||
calloption,para_alignment,para_offset);
|
||||
end;
|
||||
|
||||
otlabel:=truelabel;
|
||||
@ -347,10 +343,6 @@ implementation
|
||||
{ push from right to left }
|
||||
if not push_from_left_to_right and assigned(right) then
|
||||
begin
|
||||
if (nf_varargs_para in flags) then
|
||||
tcallparanode(right).secondcallparan(push_from_left_to_right,
|
||||
calloption,para_alignment,para_offset)
|
||||
else
|
||||
tcallparanode(right).secondcallparan(push_from_left_to_right,
|
||||
calloption,para_alignment,para_offset);
|
||||
end;
|
||||
@ -366,7 +358,7 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
function tcgcallnode.align_parasize(parasize,para_alignment:longint):longint;
|
||||
function tcgcallnode.align_parasize:longint;
|
||||
begin
|
||||
result:=0;
|
||||
end;
|
||||
@ -413,7 +405,7 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
procedure tcgcallnode.handle_return_value(inlined:boolean);
|
||||
procedure tcgcallnode.handle_return_value;
|
||||
var
|
||||
cgsize : tcgsize;
|
||||
r,hregister : tregister;
|
||||
@ -465,8 +457,7 @@ implementation
|
||||
cgsize:=def_cgsize(resulttype.def);
|
||||
|
||||
{ an object constructor is a function with pointer result }
|
||||
if (inlined or (right=nil)) and
|
||||
(procdefinition.proctypeoption=potype_constructor) then
|
||||
if (procdefinition.proctypeoption=potype_constructor) then
|
||||
cgsize:=OS_ADDR;
|
||||
|
||||
if cgsize<>OS_NO then
|
||||
@ -541,7 +532,41 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
procedure tcgcallnode.pass_2;
|
||||
procedure tcgcallnode.release_para_temps;
|
||||
var
|
||||
hp : tnode;
|
||||
ppn : tcallparanode;
|
||||
begin
|
||||
{ Release temps from parameters }
|
||||
ppn:=tcallparanode(left);
|
||||
while assigned(ppn) do
|
||||
begin
|
||||
if assigned(ppn.left) then
|
||||
begin
|
||||
{ don't release the funcret temp }
|
||||
if not(vo_is_funcret in tvarsym(ppn.paraitem.parasym).varoptions) then
|
||||
location_freetemp(exprasmlist,ppn.left.location);
|
||||
{ process also all nodes of an array of const }
|
||||
if ppn.left.nodetype=arrayconstructorn then
|
||||
begin
|
||||
if assigned(tarrayconstructornode(ppn.left).left) then
|
||||
begin
|
||||
hp:=ppn.left;
|
||||
while assigned(hp) do
|
||||
begin
|
||||
location_freetemp(exprasmlist,tarrayconstructornode(hp).left.location);
|
||||
hp:=tarrayconstructornode(hp).right;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
ppn:=tcallparanode(ppn.right);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
|
||||
procedure tcgcallnode.normal_pass_2;
|
||||
var
|
||||
regs_to_push_int : Tsupregset;
|
||||
regs_to_push_other : tregisterset;
|
||||
@ -553,23 +578,16 @@ implementation
|
||||
iolabel : tasmlabel;
|
||||
{ help reference pointer }
|
||||
href : treference;
|
||||
hp : tnode;
|
||||
pp : tcallparanode;
|
||||
inlined : boolean;
|
||||
inlinecode : tprocinlinenode;
|
||||
pushedregs : tmaybesave;
|
||||
store_parast_fixup,
|
||||
para_alignment,
|
||||
para_offset : longint;
|
||||
pop_size : longint;
|
||||
returnref,
|
||||
pararef : treference;
|
||||
accreg : tregister;
|
||||
oldaktcallnode : tcallnode;
|
||||
begin
|
||||
if not assigned(procdefinition) then
|
||||
internalerror(200305264);
|
||||
|
||||
iolabel:=nil;
|
||||
inlinecode:=nil;
|
||||
inlined:=false;
|
||||
rg.saveunusedstate(unusedstate);
|
||||
|
||||
{ if we allocate the temp. location for ansi- or widestrings }
|
||||
@ -590,38 +608,8 @@ implementation
|
||||
else
|
||||
para_alignment:=aktalignment.paraalign;
|
||||
|
||||
if not assigned(procdefinition) then
|
||||
exit;
|
||||
|
||||
if (procdefinition.proccalloption=pocall_inline) then
|
||||
begin
|
||||
inlined:=true;
|
||||
inlinecode:=tprocinlinenode(right);
|
||||
right:=nil;
|
||||
{ set it to the same lexical level as the local symtable, becuase
|
||||
the para's are stored there }
|
||||
tprocdef(procdefinition).parast.symtablelevel:=current_procdef.localst.symtablelevel;
|
||||
if assigned(left) then
|
||||
begin
|
||||
inlinecode.para_size:=tprocdef(procdefinition).para_size(para_alignment);
|
||||
tg.GetTemp(exprasmlist,inlinecode.para_size,tt_persistent,pararef);
|
||||
inlinecode.para_offset:=pararef.offset;
|
||||
end;
|
||||
store_parast_fixup:=tprocdef(procdefinition).parast.address_fixup;
|
||||
tprocdef(procdefinition).parast.address_fixup:=inlinecode.para_offset;
|
||||
{$ifdef extdebug}
|
||||
Comment(V_debug,
|
||||
'inlined parasymtable is at offset '
|
||||
+tostr(tprocdef(procdefinition).parast.address_fixup));
|
||||
exprasmList.concat(tai_comment.Create(
|
||||
strpnew('inlined parasymtable is at offset '
|
||||
+tostr(tprocdef(procdefinition).parast.address_fixup))));
|
||||
{$endif extdebug}
|
||||
end;
|
||||
|
||||
{ proc variables destroy all registers }
|
||||
if (inlined or
|
||||
(right=nil)) and
|
||||
if (right=nil) and
|
||||
{ virtual methods too }
|
||||
not(po_virtualmethod in procdefinition.procoptions) then
|
||||
begin
|
||||
@ -669,11 +657,9 @@ implementation
|
||||
{ Initialize for pushing the parameters }
|
||||
oldpushedparasize:=pushedparasize;
|
||||
pushedparasize:=0;
|
||||
pop_size:=0;
|
||||
|
||||
{ Align stack if required }
|
||||
if not inlined then
|
||||
pop_size:=align_parasize(oldpushedparasize,para_alignment);
|
||||
pop_size:=align_parasize;
|
||||
|
||||
{ Push parameters }
|
||||
oldaktcallnode:=aktcallnode;
|
||||
@ -683,31 +669,26 @@ implementation
|
||||
{ destroy registers containing a parameter for the actual }
|
||||
{ function call (e.g. if it's a function, its result will }
|
||||
{ overwrite r3, which contains the first parameter) (JM) }
|
||||
if not(inlined) and
|
||||
assigned(right) then
|
||||
if assigned(right) then
|
||||
secondpass(right);
|
||||
|
||||
if inlined or
|
||||
(right = nil) then
|
||||
begin
|
||||
if (po_virtualmethod in procdefinition.procoptions) and
|
||||
assigned(methodpointer) then
|
||||
begin
|
||||
secondpass(methodpointer);
|
||||
location_force_reg(exprasmlist,methodpointer.location,OS_ADDR,false);
|
||||
if (po_virtualmethod in procdefinition.procoptions) and
|
||||
assigned(methodpointer) then
|
||||
begin
|
||||
secondpass(methodpointer);
|
||||
location_force_reg(exprasmlist,methodpointer.location,OS_ADDR,false);
|
||||
|
||||
{ virtual methods require an index }
|
||||
if tprocdef(procdefinition).extnumber=-1 then
|
||||
internalerror(200304021);
|
||||
{ VMT should already be loaded in a register }
|
||||
if methodpointer.location.register.number=NR_NO then
|
||||
internalerror(200304022);
|
||||
{ virtual methods require an index }
|
||||
if tprocdef(procdefinition).extnumber=-1 then
|
||||
internalerror(200304021);
|
||||
{ VMT should already be loaded in a register }
|
||||
if methodpointer.location.register.number=NR_NO then
|
||||
internalerror(200304022);
|
||||
|
||||
{ test validity of VMT }
|
||||
if not(is_interface(tprocdef(procdefinition)._class)) and
|
||||
not(is_cppclass(tprocdef(procdefinition)._class)) then
|
||||
cg.g_maybe_testvmt(exprasmlist,methodpointer.location.register,tprocdef(procdefinition)._class);
|
||||
end;
|
||||
{ test validity of VMT }
|
||||
if not(is_interface(tprocdef(procdefinition)._class)) and
|
||||
not(is_cppclass(tprocdef(procdefinition)._class)) then
|
||||
cg.g_maybe_testvmt(exprasmlist,methodpointer.location.register,tprocdef(procdefinition)._class);
|
||||
end;
|
||||
|
||||
if assigned(left) then
|
||||
@ -720,21 +701,9 @@ implementation
|
||||
maybe_save(exprasmlist,left.registers32,methodpointer.location,pushedregs);
|
||||
|
||||
{$endif}
|
||||
{ be found elsewhere }
|
||||
if inlined then
|
||||
para_offset:=tprocdef(procdefinition).parast.address_fixup+
|
||||
tprocdef(procdefinition).parast.datasize
|
||||
else
|
||||
para_offset:=0;
|
||||
if not(inlined) and
|
||||
assigned(right) then
|
||||
tcallparanode(left).secondcallparan(
|
||||
(po_leftright in procdefinition.procoptions),procdefinition.proccalloption,
|
||||
para_alignment,para_offset)
|
||||
else
|
||||
tcallparanode(left).secondcallparan(
|
||||
(po_leftright in procdefinition.procoptions),procdefinition.proccalloption,
|
||||
para_alignment,para_offset);
|
||||
tcallparanode(left).secondcallparan(
|
||||
(po_leftright in procdefinition.procoptions),procdefinition.proccalloption,
|
||||
para_alignment,0);
|
||||
{$ifndef newra}
|
||||
if assigned(right) then
|
||||
maybe_restore(exprasmlist,right.location,pushedregs)
|
||||
@ -745,27 +714,14 @@ implementation
|
||||
end;
|
||||
aktcallnode:=oldaktcallnode;
|
||||
|
||||
{ Allocate return value for inlined routines }
|
||||
if inlined and
|
||||
(resulttype.def.size>0) then
|
||||
begin
|
||||
tg.GetTemp(exprasmlist,Align(resulttype.def.size,aktalignment.paraalign),tt_persistent,returnref);
|
||||
inlinecode.retoffset:=returnref.offset;
|
||||
end;
|
||||
|
||||
{ procedure variable or normal function call ? }
|
||||
if inlined or
|
||||
(right=nil) then
|
||||
if (right=nil) then
|
||||
begin
|
||||
{ push base pointer ?}
|
||||
{ never when inlining, since if necessary, the base pointer }
|
||||
{ can/will be gottten from the current procedure's symtable }
|
||||
{ (JM) }
|
||||
if not inlined then
|
||||
if (current_procdef.parast.symtablelevel>=normal_function_level) and
|
||||
assigned(tprocdef(procdefinition).parast) and
|
||||
((tprocdef(procdefinition).parast.symtablelevel)>normal_function_level) then
|
||||
push_framepointer;
|
||||
if (current_procdef.parast.symtablelevel>=normal_function_level) and
|
||||
assigned(tprocdef(procdefinition).parast) and
|
||||
((tprocdef(procdefinition).parast.symtablelevel)>normal_function_level) then
|
||||
push_framepointer;
|
||||
|
||||
rg.saveintregvars(exprasmlist,regs_to_push_int);
|
||||
rg.saveotherregvars(exprasmlist,regs_to_push_other);
|
||||
@ -778,28 +734,17 @@ implementation
|
||||
tprocdef(procdefinition)._class.vmtmethodoffset(tprocdef(procdefinition).extnumber));
|
||||
cg.a_call_ref(exprasmlist,href);
|
||||
|
||||
{ release self }
|
||||
{ release vmt register }
|
||||
rg.ungetaddressregister(exprasmlist,methodpointer.location.register);
|
||||
end
|
||||
else
|
||||
begin
|
||||
if not inlined then
|
||||
begin
|
||||
{ Calling interrupt from the same code requires some
|
||||
extra code }
|
||||
if (po_interrupt in procdefinition.procoptions) then
|
||||
extra_interrupt_code;
|
||||
{ Calling interrupt from the same code requires some
|
||||
extra code }
|
||||
if (po_interrupt in procdefinition.procoptions) then
|
||||
extra_interrupt_code;
|
||||
|
||||
cg.a_call_name(exprasmlist,tprocdef(procdefinition).mangledname);
|
||||
end
|
||||
else { inlined proc }
|
||||
begin
|
||||
{ process the inlinecode }
|
||||
secondpass(tnode(inlinecode));
|
||||
{ free the args }
|
||||
if tprocdef(procdefinition).parast.datasize>0 then
|
||||
tg.UnGetTemp(exprasmlist,pararef);
|
||||
end;
|
||||
cg.a_call_name(exprasmlist,tprocdef(procdefinition).mangledname);
|
||||
end;
|
||||
end
|
||||
else
|
||||
@ -818,7 +763,7 @@ implementation
|
||||
end;
|
||||
|
||||
{ Need to remove the parameters from the stack? }
|
||||
if (not inlined) and (po_clearstack in procdefinition.procoptions) then
|
||||
if (po_clearstack in procdefinition.procoptions) then
|
||||
begin
|
||||
{ the old pop_size was already included in pushedparasize }
|
||||
pop_size:=pushedparasize;
|
||||
@ -832,7 +777,6 @@ implementation
|
||||
if pop_size>0 then
|
||||
pop_parasize(pop_size);
|
||||
|
||||
|
||||
{$ifdef powerpc}
|
||||
{ this calculation must be done in pass_1 anyway, so don't worry }
|
||||
if tppcprocinfo(current_procinfo).maxpushedparasize<pushedparasize then
|
||||
@ -848,7 +792,7 @@ implementation
|
||||
|
||||
{ handle function results }
|
||||
if (not is_void(resulttype.def)) then
|
||||
handle_return_value(inlined)
|
||||
handle_return_value
|
||||
else
|
||||
location_reset(location,LOC_VOID,OS_NO);
|
||||
|
||||
@ -864,44 +808,8 @@ implementation
|
||||
rg.restoreusedotherregisters(exprasmlist,pushedother);
|
||||
rg.restoreusedintregisters(exprasmlist,pushedint);
|
||||
|
||||
{ Release temps from parameters }
|
||||
pp:=tcallparanode(left);
|
||||
while assigned(pp) do
|
||||
begin
|
||||
if assigned(pp.left) then
|
||||
begin
|
||||
{ don't release the funcret temp }
|
||||
if not(vo_is_funcret in tvarsym(pp.paraitem.parasym).varoptions) then
|
||||
location_freetemp(exprasmlist,pp.left.location);
|
||||
{ process also all nodes of an array of const }
|
||||
if pp.left.nodetype=arrayconstructorn then
|
||||
begin
|
||||
if assigned(tarrayconstructornode(pp.left).left) then
|
||||
begin
|
||||
hp:=pp.left;
|
||||
while assigned(hp) do
|
||||
begin
|
||||
location_freetemp(exprasmlist,tarrayconstructornode(hp).left.location);
|
||||
hp:=tarrayconstructornode(hp).right;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
pp:=tcallparanode(pp.right);
|
||||
end;
|
||||
|
||||
if inlined then
|
||||
begin
|
||||
if (resulttype.def.size>0) then
|
||||
tg.UnGetTemp(exprasmlist,returnref);
|
||||
tprocdef(procdefinition).parast.address_fixup:=store_parast_fixup;
|
||||
right:=inlinecode;
|
||||
|
||||
{ from now on the result can be freed normally }
|
||||
if assigned(funcretnode) and
|
||||
paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption) then
|
||||
tg.ChangeTempType(exprasmlist,funcretnode.location.reference,tt_normal);
|
||||
end;
|
||||
{ release temps of paras }
|
||||
release_para_temps;
|
||||
|
||||
{ if return value is not used }
|
||||
if (not(nf_return_value_used in flags)) and (not is_void(resulttype.def)) then
|
||||
@ -931,186 +839,387 @@ implementation
|
||||
|
||||
|
||||
|
||||
{*****************************************************************************
|
||||
TCGPROCINLINENODE
|
||||
*****************************************************************************}
|
||||
|
||||
|
||||
procedure tcgprocinlinenode.pass_2;
|
||||
var st : tsymtable;
|
||||
oldprocdef : tprocdef;
|
||||
ps, i : longint;
|
||||
oldprocinfo : tprocinfo;
|
||||
oldinlining_procedure,
|
||||
nostackframe : boolean;
|
||||
inlineentrycode,inlineexitcode : TAAsmoutput;
|
||||
oldexitlabel,oldexit2label:tasmlabel;
|
||||
oldregstate: pointer;
|
||||
localsref : treference;
|
||||
procedure tcgcallnode.inlined_pass_2;
|
||||
var
|
||||
regs_to_push_int : Tsupregset;
|
||||
regs_to_push_other : tregisterset;
|
||||
unusedstate: pointer;
|
||||
pushedother : tpushedsavedother;
|
||||
pushedint : tpushedsavedint;
|
||||
oldpushedparasize : longint;
|
||||
{ adress returned from an I/O-error }
|
||||
iolabel : tasmlabel;
|
||||
{ help reference pointer }
|
||||
href : treference;
|
||||
pushedregs : tmaybesave;
|
||||
accreg : tregister;
|
||||
oldaktcallnode : tcallnode;
|
||||
oldprocdef : tprocdef;
|
||||
i : longint;
|
||||
oldprocinfo : tprocinfo;
|
||||
oldinlining_procedure : boolean;
|
||||
inlineentrycode,inlineexitcode : TAAsmoutput;
|
||||
oldexitlabel:tasmlabel;
|
||||
oldregstate: pointer;
|
||||
old_local_fixup,
|
||||
old_para_fixup : longint;
|
||||
pararef,
|
||||
localsref : treference;
|
||||
{$ifdef GDB}
|
||||
startlabel,endlabel : tasmlabel;
|
||||
pp : pchar;
|
||||
mangled_length : longint;
|
||||
startlabel,endlabel : tasmlabel;
|
||||
pp : pchar;
|
||||
mangled_length : longint;
|
||||
{$endif GDB}
|
||||
begin
|
||||
{ deallocate the registers used for the current procedure's regvars }
|
||||
if assigned(current_procdef.regvarinfo) then
|
||||
begin
|
||||
with pregvarinfo(current_procdef.regvarinfo)^ do
|
||||
for i := 1 to maxvarregs do
|
||||
if assigned(regvars[i]) then
|
||||
store_regvar(exprasmlist,regvars[i].reg);
|
||||
rg.saveStateForInline(oldregstate);
|
||||
{ make sure the register allocator knows what the regvars in the }
|
||||
{ inlined code block are (JM) }
|
||||
rg.resetusableregisters;
|
||||
rg.clearregistercount;
|
||||
{$ifndef newra}
|
||||
rg.cleartempgen;
|
||||
{$endif}
|
||||
if assigned(inlineprocdef.regvarinfo) then
|
||||
with pregvarinfo(inlineprocdef.regvarinfo)^ do
|
||||
for i := 1 to maxvarregs do
|
||||
if assigned(regvars[i]) then
|
||||
begin
|
||||
{Fix me!!}
|
||||
{tmpreg:=rg.makeregsize(regvars[i].reg,OS_INT);
|
||||
rg.makeregvar(tmpreg);}
|
||||
internalerror(200301232);
|
||||
end;
|
||||
end;
|
||||
oldinlining_procedure:=inlining_procedure;
|
||||
oldexitlabel:=aktexitlabel;
|
||||
oldexit2label:=aktexit2label;
|
||||
oldprocdef:=current_procdef;
|
||||
oldprocinfo:=current_procinfo;
|
||||
objectlibrary.getlabel(aktexitlabel);
|
||||
objectlibrary.getlabel(aktexit2label);
|
||||
{ we're inlining a procedure }
|
||||
inlining_procedure:=true;
|
||||
begin
|
||||
if not(assigned(procdefinition) and (procdefinition.deftype=procdef)) then
|
||||
internalerror(200305262);
|
||||
|
||||
{ create temp procinfo }
|
||||
current_procinfo:=cprocinfo.create(nil);
|
||||
current_procinfo.procdef:=inlineprocdef;
|
||||
current_procinfo.return_offset:=retoffset;
|
||||
current_procdef:=current_procinfo.procdef;
|
||||
oldinlining_procedure:=inlining_procedure;
|
||||
oldexitlabel:=aktexitlabel;
|
||||
oldprocdef:=current_procdef;
|
||||
oldprocinfo:=current_procinfo;
|
||||
objectlibrary.getlabel(aktexitlabel);
|
||||
{ we're inlining a procedure }
|
||||
inlining_procedure:=true;
|
||||
|
||||
{ arg space has been filled by the parent secondcall }
|
||||
st:=current_procdef.localst;
|
||||
{ set it to the same lexical level }
|
||||
st.symtablelevel:=oldprocdef.localst.symtablelevel;
|
||||
if st.datasize>0 then
|
||||
begin
|
||||
tg.GetTemp(exprasmlist,st.datasize,tt_persistent,localsref);
|
||||
if tg.direction>0 then
|
||||
st.address_fixup:=localsref.offset
|
||||
else
|
||||
st.address_fixup:=localsref.offset+st.datasize;
|
||||
{ deallocate the registers used for the current procedure's regvars }
|
||||
if assigned(current_procdef.regvarinfo) then
|
||||
begin
|
||||
with pregvarinfo(current_procdef.regvarinfo)^ do
|
||||
for i := 1 to maxvarregs do
|
||||
if assigned(regvars[i]) then
|
||||
store_regvar(exprasmlist,regvars[i].reg);
|
||||
rg.saveStateForInline(oldregstate);
|
||||
{ make sure the register allocator knows what the regvars in the }
|
||||
{ inlined code block are (JM) }
|
||||
rg.resetusableregisters;
|
||||
rg.clearregistercount;
|
||||
{$ifndef newra}
|
||||
rg.cleartempgen;
|
||||
{$endif}
|
||||
if assigned(tprocdef(procdefinition).regvarinfo) then
|
||||
with pregvarinfo(tprocdef(procdefinition).regvarinfo)^ do
|
||||
for i := 1 to maxvarregs do
|
||||
if assigned(regvars[i]) then
|
||||
begin
|
||||
{Fix me!!}
|
||||
{tmpreg:=rg.makeregsize(regvars[i].reg,OS_INT);
|
||||
rg.makeregvar(tmpreg);}
|
||||
internalerror(200301232);
|
||||
end;
|
||||
end;
|
||||
|
||||
{ create temp procinfo }
|
||||
current_procinfo:=cprocinfo.create(nil);
|
||||
current_procinfo.procdef:=tprocdef(procdefinition);
|
||||
current_procdef:=current_procinfo.procdef;
|
||||
|
||||
{ Localsymtable }
|
||||
current_procdef.localst.symtablelevel:=oldprocdef.localst.symtablelevel;
|
||||
if current_procdef.localst.datasize>0 then
|
||||
begin
|
||||
old_local_fixup:=current_procdef.localst.address_fixup;
|
||||
tg.GetTemp(exprasmlist,current_procdef.localst.datasize,tt_persistent,localsref);
|
||||
if tg.direction>0 then
|
||||
current_procdef.localst.address_fixup:=localsref.offset
|
||||
else
|
||||
current_procdef.localst.address_fixup:=localsref.offset+current_procdef.localst.datasize;
|
||||
{$ifdef extdebug}
|
||||
Comment(V_debug,'local symtable is at offset '+tostr(st.address_fixup));
|
||||
exprasmList.concat(tai_comment.Create(strpnew(
|
||||
'local symtable is at offset '+tostr(st.address_fixup))));
|
||||
Comment(V_debug,'inlined local symtable ('+tostr(current_procdef.localst.datasize)+' bytes) is at offset '+tostr(current_procdef.localst.address_fixup));
|
||||
exprasmList.concat(tai_comment.Create(strpnew(
|
||||
'inlined local symtable ('+tostr(current_procdef.localst.datasize)+' bytes) is at offset '+tostr(current_procdef.localst.address_fixup))));
|
||||
{$endif extdebug}
|
||||
end;
|
||||
exprasmList.concat(Tai_Marker.Create(InlineStart));
|
||||
end;
|
||||
|
||||
{ Parasymtable }
|
||||
current_procdef.parast.symtablelevel:=oldprocdef.localst.symtablelevel;
|
||||
if current_procdef.parast.datasize>0 then
|
||||
begin
|
||||
old_para_fixup:=current_procdef.parast.address_fixup;
|
||||
tg.GetTemp(exprasmlist,current_procdef.parast.datasize,tt_persistent,pararef);
|
||||
current_procdef.parast.address_fixup:=pararef.offset;
|
||||
{$ifdef extdebug}
|
||||
exprasmList.concat(tai_comment.Create(strpnew('Start of inlined proc')));
|
||||
Comment(V_debug,'inlined para symtable ('+tostr(current_procdef.parast.datasize)+' bytes) is at offset '+tostr(current_procdef.parast.address_fixup));
|
||||
exprasmList.concat(tai_comment.Create(strpnew(
|
||||
'inlined para symtable ('+tostr(current_procdef.parast.datasize)+' bytes) is at offset '+tostr(current_procdef.parast.address_fixup))));
|
||||
{$endif extdebug}
|
||||
end;
|
||||
|
||||
{ Calculate offsets }
|
||||
current_procinfo.after_header;
|
||||
|
||||
exprasmList.concat(Tai_Marker.Create(InlineStart));
|
||||
{$ifdef extdebug}
|
||||
exprasmList.concat(tai_comment.Create(strpnew('Start of inlined proc')));
|
||||
{$endif extdebug}
|
||||
{$ifdef GDB}
|
||||
if (cs_debuginfo in aktmoduleswitches) then
|
||||
begin
|
||||
objectlibrary.getaddrlabel(startlabel);
|
||||
objectlibrary.getaddrlabel(endlabel);
|
||||
cg.a_label(exprasmlist,startlabel);
|
||||
inlineprocdef.localst.symtabletype:=inlinelocalsymtable;
|
||||
inlineprocdef.parast.symtabletype:=inlineparasymtable;
|
||||
if (cs_debuginfo in aktmoduleswitches) then
|
||||
begin
|
||||
objectlibrary.getaddrlabel(startlabel);
|
||||
objectlibrary.getaddrlabel(endlabel);
|
||||
cg.a_label(exprasmlist,startlabel);
|
||||
tprocdef(procdefinition).localst.symtabletype:=inlinelocalsymtable;
|
||||
procdefinition.parast.symtabletype:=inlineparasymtable;
|
||||
|
||||
{ Here we must include the para and local symtable info }
|
||||
inlineprocdef.concatstabto(withdebuglist);
|
||||
{ Here we must include the para and local symtable info }
|
||||
procdefinition.concatstabto(withdebuglist);
|
||||
|
||||
{ set it back for safety }
|
||||
inlineprocdef.localst.symtabletype:=localsymtable;
|
||||
inlineprocdef.parast.symtabletype:=parasymtable;
|
||||
{ set it back for safety }
|
||||
tprocdef(procdefinition).localst.symtabletype:=localsymtable;
|
||||
procdefinition.parast.symtabletype:=parasymtable;
|
||||
|
||||
mangled_length:=length(oldprocdef.mangledname);
|
||||
getmem(pp,mangled_length+50);
|
||||
strpcopy(pp,'192,0,0,'+startlabel.name);
|
||||
if (target_info.use_function_relative_addresses) then
|
||||
begin
|
||||
strpcopy(strend(pp),'-');
|
||||
strpcopy(strend(pp),oldprocdef.mangledname);
|
||||
end;
|
||||
withdebugList.concat(Tai_stabn.Create(strnew(pp)));
|
||||
end;
|
||||
{$endif GDB}
|
||||
{ takes care of local data initialization }
|
||||
inlineentrycode:=TAAsmoutput.Create;
|
||||
inlineexitcode:=TAAsmoutput.Create;
|
||||
ps:=para_size;
|
||||
genentrycode(inlineentrycode,0,ps,nostackframe,true);
|
||||
if po_assembler in current_procdef.procoptions then
|
||||
inlineentrycode.insert(Tai_marker.Create(asmblockstart));
|
||||
exprasmList.concatlist(inlineentrycode);
|
||||
secondpass(inlinetree);
|
||||
genexitcode(inlineexitcode,0,false,true);
|
||||
if po_assembler in current_procdef.procoptions then
|
||||
inlineexitcode.concat(Tai_marker.Create(asmblockend));
|
||||
exprasmList.concatlist(inlineexitcode);
|
||||
|
||||
inlineentrycode.free;
|
||||
inlineexitcode.free;
|
||||
{$ifdef extdebug}
|
||||
exprasmList.concat(tai_comment.Create(strpnew('End of inlined proc')));
|
||||
{$endif extdebug}
|
||||
exprasmList.concat(Tai_Marker.Create(InlineEnd));
|
||||
|
||||
{we can free the local data now, reset also the fixup address }
|
||||
if st.datasize>0 then
|
||||
begin
|
||||
tg.UnGetTemp(exprasmlist,localsref);
|
||||
st.address_fixup:=0;
|
||||
end;
|
||||
{ restore procinfo }
|
||||
current_procinfo.free;
|
||||
current_procinfo:=oldprocinfo;
|
||||
{$ifdef GDB}
|
||||
if (cs_debuginfo in aktmoduleswitches) then
|
||||
begin
|
||||
cg.a_label(exprasmlist,endlabel);
|
||||
strpcopy(pp,'224,0,0,'+endlabel.name);
|
||||
mangled_length:=length(oldprocdef.mangledname);
|
||||
getmem(pp,mangled_length+50);
|
||||
strpcopy(pp,'192,0,0,'+startlabel.name);
|
||||
if (target_info.use_function_relative_addresses) then
|
||||
begin
|
||||
strpcopy(strend(pp),'-');
|
||||
strpcopy(strend(pp),oldprocdef.mangledname);
|
||||
end;
|
||||
withdebugList.concat(Tai_stabn.Create(strnew(pp)));
|
||||
freemem(pp,mangled_length+50);
|
||||
end;
|
||||
withdebugList.concat(Tai_stabn.Create(strnew(pp)));
|
||||
end;
|
||||
{$endif GDB}
|
||||
{ restore }
|
||||
current_procdef:=oldprocdef;
|
||||
aktexitlabel:=oldexitlabel;
|
||||
aktexit2label:=oldexit2label;
|
||||
inlining_procedure:=oldinlining_procedure;
|
||||
|
||||
{ reallocate the registers used for the current procedure's regvars, }
|
||||
{ since they may have been used and then deallocated in the inlined }
|
||||
{ procedure (JM) }
|
||||
if assigned(current_procdef.regvarinfo) then
|
||||
begin
|
||||
rg.restoreStateAfterInline(oldregstate);
|
||||
end;
|
||||
end;
|
||||
iolabel:=nil;
|
||||
rg.saveunusedstate(unusedstate);
|
||||
|
||||
{ if we allocate the temp. location for ansi- or widestrings }
|
||||
{ already here, we avoid later a push/pop }
|
||||
if is_widestring(resulttype.def) then
|
||||
begin
|
||||
tg.GetTemp(exprasmlist,pointer_size,tt_widestring,refcountedtemp);
|
||||
cg.g_decrrefcount(exprasmlist,resulttype.def,refcountedtemp,false);
|
||||
end
|
||||
else if is_ansistring(resulttype.def) then
|
||||
begin
|
||||
tg.GetTemp(exprasmlist,pointer_size,tt_ansistring,refcountedtemp);
|
||||
cg.g_decrrefcount(exprasmlist,resulttype.def,refcountedtemp,false);
|
||||
end;
|
||||
|
||||
if (cs_check_io in aktlocalswitches) and
|
||||
(po_iocheck in procdefinition.procoptions) and
|
||||
not(po_iocheck in current_procdef.procoptions) then
|
||||
begin
|
||||
objectlibrary.getaddrlabel(iolabel);
|
||||
cg.a_label(exprasmlist,iolabel);
|
||||
end
|
||||
else
|
||||
iolabel:=nil;
|
||||
|
||||
{ save all used registers and possible registers
|
||||
used for the return value }
|
||||
regs_to_push_int := tprocdef(procdefinition).usedintregisters;
|
||||
regs_to_push_other := tprocdef(procdefinition).usedotherregisters;
|
||||
if (not is_void(resulttype.def)) and
|
||||
(not paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption)) then
|
||||
begin
|
||||
include(regs_to_push_int,RS_ACCUMULATOR);
|
||||
{$ifndef cpu64bit}
|
||||
if resulttype.def.size>sizeof(aword) then
|
||||
include(regs_to_push_int,RS_ACCUMULATORHIGH);
|
||||
{$endif cpu64bit}
|
||||
end;
|
||||
rg.saveusedintregisters(exprasmlist,pushedint,regs_to_push_int);
|
||||
rg.saveusedotherregisters(exprasmlist,pushedother,regs_to_push_other);
|
||||
|
||||
{ give used registers through }
|
||||
rg.usedintinproc:=rg.usedintinproc + tprocdef(procdefinition).usedintregisters;
|
||||
rg.usedinproc:=rg.usedinproc + tprocdef(procdefinition).usedotherregisters;
|
||||
|
||||
{ Initialize for pushing the parameters }
|
||||
oldpushedparasize:=pushedparasize;
|
||||
pushedparasize:=0;
|
||||
|
||||
{ Push parameters }
|
||||
oldaktcallnode:=aktcallnode;
|
||||
aktcallnode:=self;
|
||||
|
||||
if assigned(left) then
|
||||
begin
|
||||
{$ifndef newra}
|
||||
if assigned(right) then
|
||||
maybe_save(exprasmlist,left.registers32,right.location,pushedregs)
|
||||
else
|
||||
if assigned(methodpointer) then
|
||||
maybe_save(exprasmlist,left.registers32,methodpointer.location,pushedregs);
|
||||
|
||||
{$endif}
|
||||
{ we push from right to left, so start with parameters at the end of
|
||||
the parameter block }
|
||||
tcallparanode(left).secondcallparan(
|
||||
(po_leftright in procdefinition.procoptions),procdefinition.proccalloption,
|
||||
0,procdefinition.parast.address_fixup+procdefinition.parast.datasize);
|
||||
{$ifndef newra}
|
||||
if assigned(right) then
|
||||
maybe_restore(exprasmlist,right.location,pushedregs)
|
||||
else
|
||||
if assigned(methodpointer) then
|
||||
maybe_restore(exprasmlist,methodpointer.location,pushedregs);
|
||||
{$endif newra}
|
||||
end;
|
||||
aktcallnode:=oldaktcallnode;
|
||||
|
||||
rg.saveintregvars(exprasmlist,regs_to_push_int);
|
||||
rg.saveotherregvars(exprasmlist,regs_to_push_other);
|
||||
|
||||
{ takes care of local data initialization }
|
||||
inlineentrycode:=TAAsmoutput.Create;
|
||||
inlineexitcode:=TAAsmoutput.Create;
|
||||
|
||||
geninlineentrycode(inlineentrycode,0);
|
||||
if po_assembler in current_procdef.procoptions then
|
||||
inlineentrycode.insert(Tai_marker.Create(asmblockstart));
|
||||
exprasmList.concatlist(inlineentrycode);
|
||||
|
||||
{ process the inline code }
|
||||
secondpass(inlinecode);
|
||||
|
||||
{$ifdef powerpc}
|
||||
{ this calculation must be done in pass_1 anyway, so don't worry }
|
||||
if tppcprocinfo(current_procinfo).maxpushedparasize<pushedparasize then
|
||||
tppcprocinfo(current_procinfo).maxpushedparasize:=pushedparasize;
|
||||
{$endif powerpc}
|
||||
|
||||
{ Restore }
|
||||
pushedparasize:=oldpushedparasize;
|
||||
rg.restoreunusedstate(unusedstate);
|
||||
{$ifdef TEMPREGDEBUG}
|
||||
testregisters32;
|
||||
{$endif TEMPREGDEBUG}
|
||||
|
||||
geninlineexitcode(inlineexitcode,true);
|
||||
if po_assembler in current_procdef.procoptions then
|
||||
inlineexitcode.concat(Tai_marker.Create(asmblockend));
|
||||
exprasmList.concatlist(inlineexitcode);
|
||||
|
||||
inlineentrycode.free;
|
||||
inlineexitcode.free;
|
||||
{$ifdef extdebug}
|
||||
exprasmList.concat(tai_comment.Create(strpnew('End of inlined proc')));
|
||||
{$endif extdebug}
|
||||
exprasmList.concat(Tai_Marker.Create(InlineEnd));
|
||||
|
||||
{we can free the local data now, reset also the fixup address }
|
||||
if current_procdef.localst.datasize>0 then
|
||||
begin
|
||||
tg.UnGetTemp(exprasmlist,localsref);
|
||||
current_procdef.localst.address_fixup:=old_local_fixup;
|
||||
end;
|
||||
{we can free the para data now, reset also the fixup address }
|
||||
if current_procdef.parast.datasize>0 then
|
||||
begin
|
||||
tg.UnGetTemp(exprasmlist,pararef);
|
||||
current_procdef.parast.address_fixup:=old_para_fixup;
|
||||
end;
|
||||
{ free return reference }
|
||||
if (resulttype.def.size>0) then
|
||||
begin
|
||||
{ from now on the result can be freed normally }
|
||||
// if assigned(funcretnode) and
|
||||
// paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption) then
|
||||
// tg.ChangeTempType(exprasmlist,funcretnode.location.reference,tt_normal);
|
||||
end;
|
||||
|
||||
{ handle function results }
|
||||
if (not is_void(resulttype.def)) then
|
||||
handle_return_value
|
||||
else
|
||||
location_reset(location,LOC_VOID,OS_NO);
|
||||
|
||||
{ perhaps i/o check ? }
|
||||
if iolabel<>nil then
|
||||
begin
|
||||
reference_reset_symbol(href,iolabel,0);
|
||||
cg.a_paramaddr_ref(exprasmlist,href,paramanager.getintparaloc(1));
|
||||
cg.a_call_name(exprasmlist,'FPC_IOCHECK');
|
||||
end;
|
||||
|
||||
{ restore registers }
|
||||
rg.restoreusedotherregisters(exprasmlist,pushedother);
|
||||
rg.restoreusedintregisters(exprasmlist,pushedint);
|
||||
|
||||
{ release temps of paras }
|
||||
release_para_temps;
|
||||
|
||||
{ if return value is not used }
|
||||
if (not is_void(resulttype.def)) and
|
||||
(not(nf_return_value_used in flags)) then
|
||||
begin
|
||||
if location.loc in [LOC_CREFERENCE,LOC_REFERENCE] then
|
||||
begin
|
||||
{ data which must be finalized ? }
|
||||
if (resulttype.def.needs_inittable) then
|
||||
cg.g_finalize(exprasmlist,resulttype.def,location.reference,false);
|
||||
{ release unused temp }
|
||||
tg.ungetiftemp(exprasmlist,location.reference)
|
||||
end
|
||||
else if location.loc=LOC_FPUREGISTER then
|
||||
begin
|
||||
{$ifdef x86}
|
||||
{ release FPU stack }
|
||||
accreg.enum:=FPU_RESULT_REG;
|
||||
emit_reg(A_FSTP,S_NO,accreg);
|
||||
{
|
||||
dec(trgcpu(rg).fpuvaroffset);
|
||||
do NOT decrement as the increment before
|
||||
is not called for unused results PM }
|
||||
{$endif x86}
|
||||
end;
|
||||
end;
|
||||
|
||||
{ release procinfo }
|
||||
current_procinfo.free;
|
||||
current_procinfo:=oldprocinfo;
|
||||
|
||||
{$ifdef GDB}
|
||||
if (cs_debuginfo in aktmoduleswitches) then
|
||||
begin
|
||||
cg.a_label(exprasmlist,endlabel);
|
||||
strpcopy(pp,'224,0,0,'+endlabel.name);
|
||||
if (target_info.use_function_relative_addresses) then
|
||||
begin
|
||||
strpcopy(strend(pp),'-');
|
||||
strpcopy(strend(pp),oldprocdef.mangledname);
|
||||
end;
|
||||
withdebugList.concat(Tai_stabn.Create(strnew(pp)));
|
||||
freemem(pp,mangled_length+50);
|
||||
end;
|
||||
{$endif GDB}
|
||||
|
||||
{ restore }
|
||||
current_procdef:=oldprocdef;
|
||||
aktexitlabel:=oldexitlabel;
|
||||
inlining_procedure:=oldinlining_procedure;
|
||||
|
||||
{ reallocate the registers used for the current procedure's regvars, }
|
||||
{ since they may have been used and then deallocated in the inlined }
|
||||
{ procedure (JM) }
|
||||
if assigned(current_procdef.regvarinfo) then
|
||||
rg.restoreStateAfterInline(oldregstate);
|
||||
end;
|
||||
|
||||
|
||||
procedure tcgcallnode.pass_2;
|
||||
begin
|
||||
if assigned(inlinecode) then
|
||||
inlined_pass_2
|
||||
else
|
||||
normal_pass_2;
|
||||
end;
|
||||
|
||||
|
||||
begin
|
||||
ccallparanode:=tcgcallparanode;
|
||||
ccallnode:=tcgcallnode;
|
||||
cprocinlinenode:=tcgprocinlinenode;
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.74 2003-05-25 11:34:17 peter
|
||||
Revision 1.75 2003-05-26 21:17:17 peter
|
||||
* procinlinenode removed
|
||||
* aktexit2label removed, fast exit removed
|
||||
+ tcallnode.inlined_pass_2 added
|
||||
|
||||
Revision 1.74 2003/05/25 11:34:17 peter
|
||||
* methodpointer self pushing fixed
|
||||
|
||||
Revision 1.73 2003/05/25 08:59:16 peter
|
||||
|
@ -695,152 +695,14 @@ implementation
|
||||
*****************************************************************************}
|
||||
|
||||
procedure tcgexitnode.pass_2;
|
||||
|
||||
var
|
||||
otlabel,oflabel : tasmlabel;
|
||||
cgsize : tcgsize;
|
||||
r,hreg : tregister;
|
||||
allocated_acc,
|
||||
allocated_acchigh: boolean;
|
||||
label
|
||||
do_jmp;
|
||||
begin
|
||||
location_reset(location,LOC_VOID,OS_NO);
|
||||
|
||||
include(flowcontrol,fc_exit);
|
||||
if assigned(left) then
|
||||
begin
|
||||
if onlyassign then
|
||||
begin
|
||||
{ just do a normal assignment followed by exit }
|
||||
secondpass(left);
|
||||
cg.a_jmp_always(exprasmlist,aktexitlabel);
|
||||
end
|
||||
else
|
||||
begin
|
||||
allocated_acc := false;
|
||||
allocated_acchigh := false;
|
||||
otlabel:=truelabel;
|
||||
oflabel:=falselabel;
|
||||
objectlibrary.getlabel(truelabel);
|
||||
objectlibrary.getlabel(falselabel);
|
||||
secondpass(left);
|
||||
{ increment reference counter, this is
|
||||
useless for string constants }
|
||||
if (left.resulttype.def.needs_inittable) and
|
||||
(left.nodetype<>stringconstn) then
|
||||
cg.g_incrrefcount(exprasmlist,left.resulttype.def,left.location.reference,false);
|
||||
{ the result of left is not needed anymore after this
|
||||
node }
|
||||
location_freetemp(exprasmlist,left.location);
|
||||
location_release(exprasmlist,left.location);
|
||||
case left.location.loc of
|
||||
LOC_FPUREGISTER :
|
||||
goto do_jmp;
|
||||
{$ifdef cpuflags}
|
||||
LOC_FLAGS :
|
||||
begin
|
||||
r.enum:=R_INTREGISTER;
|
||||
r.number:=NR_ACCUMULATOR;
|
||||
cg.a_reg_alloc(exprasmlist,r);
|
||||
allocated_acc := true;
|
||||
cg.g_flags2reg(exprasmlist,OS_INT,left.location.resflags,r);
|
||||
goto do_jmp;
|
||||
end;
|
||||
{$endif cpuflags}
|
||||
LOC_JUMP :
|
||||
begin
|
||||
r.enum:=R_INTREGISTER;
|
||||
r.number:=(RS_ACCUMULATOR shl 8) or R_SUBL;
|
||||
cg.a_reg_alloc(exprasmlist,r);
|
||||
{ get an 8-bit register }
|
||||
allocated_acc := true;
|
||||
cg.a_label(exprasmlist,truelabel);
|
||||
cg.a_load_const_reg(exprasmlist,OS_8,1,r);
|
||||
cg.a_jmp_always(exprasmlist,aktexit2label);
|
||||
cg.a_label(exprasmlist,falselabel);
|
||||
cg.a_load_const_reg(exprasmlist,OS_8,0,r);
|
||||
goto do_jmp;
|
||||
end;
|
||||
end;
|
||||
case current_procdef.rettype.def.deftype of
|
||||
pointerdef,
|
||||
procvardef :
|
||||
begin
|
||||
r.enum:=R_INTREGISTER;
|
||||
r.number:=NR_ACCUMULATOR;
|
||||
cg.a_reg_alloc(exprasmlist,r);
|
||||
allocated_acc := true;
|
||||
cg.a_load_loc_reg(exprasmlist,left.location,r);
|
||||
end;
|
||||
floatdef :
|
||||
begin
|
||||
{$ifdef cpufpemu}
|
||||
if cs_fp_emulation in aktmoduleswitches then
|
||||
r.enum := accumulator
|
||||
else
|
||||
{$endif cpufpemu}
|
||||
r.enum:=fpu_result_reg;
|
||||
{$ifndef i386}
|
||||
cg.a_reg_alloc(exprasmlist,r);
|
||||
{$endif not i386}
|
||||
cg.a_loadfpu_loc_reg(exprasmlist,left.location,r);
|
||||
end;
|
||||
else
|
||||
begin
|
||||
cgsize:=def_cgsize(current_procdef.rettype.def);
|
||||
allocated_acc := true;
|
||||
{$ifndef cpu64bit}
|
||||
secondpass(left);
|
||||
|
||||
if cgsize in [OS_64,OS_S64] then
|
||||
begin
|
||||
r.enum:=R_INTREGISTER;
|
||||
r.number:=NR_ACCUMULATOR;
|
||||
hreg.enum:=R_INTREGISTER;
|
||||
hreg.number:=NR_ACCUMULATORHIGH;
|
||||
cg.a_reg_alloc(exprasmlist,r);
|
||||
cg.a_reg_alloc(exprasmlist,hreg);
|
||||
allocated_acchigh := true;
|
||||
cg64.a_load64_loc_reg(exprasmlist,left.location,
|
||||
joinreg64(r,hreg));
|
||||
end
|
||||
else
|
||||
{$endif cpu64bit}
|
||||
begin
|
||||
r.enum:=R_INTREGISTER;
|
||||
r.number:=(RS_ACCUMULATOR shl 8) or cgsize2subreg(cgsize);
|
||||
cg.a_reg_alloc(exprasmlist,r);
|
||||
cg.a_load_loc_reg(exprasmlist,left.location,r);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
do_jmp:
|
||||
truelabel:=otlabel;
|
||||
falselabel:=oflabel;
|
||||
cg.a_jmp_always(exprasmlist,aktexit2label);
|
||||
r.enum:=R_INTREGISTER;
|
||||
r.number:=NR_ACCUMULATOR;
|
||||
{$ifndef cpu64bit}
|
||||
hreg.enum:=R_INTREGISTER;
|
||||
hreg.number:=NR_ACCUMULATORHIGH;
|
||||
{$endif cpu64bit}
|
||||
|
||||
if allocated_acc then
|
||||
cg.a_reg_dealloc(exprasmlist,r);
|
||||
{$ifndef cpu64bit}
|
||||
if allocated_acchigh then
|
||||
cg.a_reg_dealloc(exprasmlist,hreg);
|
||||
{$endif cpu64bit}
|
||||
{$ifndef i386}
|
||||
r.enum:=fpu_result_reg;
|
||||
if (current_procdef.rettype.def.deftype = floatdef) then
|
||||
cg.a_reg_dealloc(exprasmlist,r);
|
||||
{$endif not i386}
|
||||
end;
|
||||
end
|
||||
else
|
||||
cg.a_jmp_always(exprasmlist,aktexitlabel);
|
||||
cg.a_jmp_always(exprasmlist,aktexitlabel);
|
||||
end;
|
||||
|
||||
|
||||
@ -1033,7 +895,6 @@ implementation
|
||||
doobjectdestroy,
|
||||
doobjectdestroyandreraise,
|
||||
oldaktexitlabel,
|
||||
oldaktexit2label,
|
||||
oldaktcontinuelabel,
|
||||
oldaktbreaklabel : tasmlabel;
|
||||
oldflowcontrol,tryflowcontrol,
|
||||
@ -1054,7 +915,6 @@ implementation
|
||||
|
||||
{ save the old labels for control flow statements }
|
||||
oldaktexitlabel:=aktexitlabel;
|
||||
oldaktexit2label:=aktexit2label;
|
||||
if assigned(aktbreaklabel) then
|
||||
begin
|
||||
oldaktcontinuelabel:=aktcontinuelabel;
|
||||
@ -1082,7 +942,6 @@ implementation
|
||||
{ try block }
|
||||
{ set control flow labels for the try block }
|
||||
aktexitlabel:=exittrylabel;
|
||||
aktexit2label:=exittrylabel;
|
||||
if assigned(oldaktbreaklabel) then
|
||||
begin
|
||||
aktcontinuelabel:=continuetrylabel;
|
||||
@ -1104,7 +963,6 @@ implementation
|
||||
{ set control flow labels for the except block }
|
||||
{ and the on statements }
|
||||
aktexitlabel:=exitexceptlabel;
|
||||
aktexit2label:=exitexceptlabel;
|
||||
if assigned(oldaktbreaklabel) then
|
||||
begin
|
||||
aktcontinuelabel:=continueexceptlabel;
|
||||
@ -1228,7 +1086,6 @@ implementation
|
||||
|
||||
{ restore the control flow labels }
|
||||
aktexitlabel:=oldaktexitlabel;
|
||||
aktexit2label:=oldaktexit2label;
|
||||
if assigned(oldaktbreaklabel) then
|
||||
begin
|
||||
aktcontinuelabel:=oldaktcontinuelabel;
|
||||
@ -1248,7 +1105,6 @@ implementation
|
||||
continueonlabel,
|
||||
breakonlabel,
|
||||
oldaktexitlabel,
|
||||
oldaktexit2label,
|
||||
oldaktcontinuelabel,
|
||||
doobjectdestroyandreraise,
|
||||
doobjectdestroy,
|
||||
@ -1295,10 +1151,8 @@ implementation
|
||||
if assigned(right) then
|
||||
begin
|
||||
oldaktexitlabel:=aktexitlabel;
|
||||
oldaktexit2label:=aktexit2label;
|
||||
objectlibrary.getlabel(exitonlabel);
|
||||
aktexitlabel:=exitonlabel;
|
||||
aktexit2label:=exitonlabel;
|
||||
if assigned(aktbreaklabel) then
|
||||
begin
|
||||
oldaktcontinuelabel:=aktcontinuelabel;
|
||||
@ -1354,7 +1208,6 @@ implementation
|
||||
end;
|
||||
|
||||
aktexitlabel:=oldaktexitlabel;
|
||||
aktexit2label:=oldaktexit2label;
|
||||
if assigned(oldaktbreaklabel) then
|
||||
begin
|
||||
aktcontinuelabel:=oldaktcontinuelabel;
|
||||
@ -1387,7 +1240,6 @@ implementation
|
||||
continuefinallylabel,
|
||||
breakfinallylabel,
|
||||
oldaktexitlabel,
|
||||
oldaktexit2label,
|
||||
oldaktcontinuelabel,
|
||||
oldaktbreaklabel : tasmlabel;
|
||||
oldflowcontrol,tryflowcontrol : tflowcontrol;
|
||||
@ -1409,13 +1261,11 @@ implementation
|
||||
{ the finally block must catch break, continue and exit }
|
||||
{ statements }
|
||||
oldaktexitlabel:=aktexitlabel;
|
||||
oldaktexit2label:=aktexit2label;
|
||||
if implicitframe then
|
||||
exitfinallylabel:=finallylabel
|
||||
else
|
||||
objectlibrary.getlabel(exitfinallylabel);
|
||||
aktexitlabel:=exitfinallylabel;
|
||||
aktexit2label:=exitfinallylabel;
|
||||
if assigned(aktbreaklabel) then
|
||||
begin
|
||||
oldaktcontinuelabel:=aktcontinuelabel;
|
||||
@ -1528,7 +1378,6 @@ implementation
|
||||
cg.a_label(exprasmlist,endfinallylabel);
|
||||
|
||||
aktexitlabel:=oldaktexitlabel;
|
||||
aktexit2label:=oldaktexit2label;
|
||||
if assigned(aktbreaklabel) then
|
||||
begin
|
||||
aktcontinuelabel:=oldaktcontinuelabel;
|
||||
@ -1554,7 +1403,12 @@ begin
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.63 2003-05-23 14:27:35 peter
|
||||
Revision 1.64 2003-05-26 21:17:17 peter
|
||||
* procinlinenode removed
|
||||
* aktexit2label removed, fast exit removed
|
||||
+ tcallnode.inlined_pass_2 added
|
||||
|
||||
Revision 1.63 2003/05/23 14:27:35 peter
|
||||
* remove some unit dependencies
|
||||
* current_procinfo changes to store more info
|
||||
|
||||
|
@ -62,12 +62,11 @@ interface
|
||||
para_offset:longint;alignment : longint;
|
||||
const locpara : tparalocation);
|
||||
|
||||
procedure genentrycode(list : TAAsmoutput;
|
||||
stackframe:longint;
|
||||
var parasize:longint;
|
||||
var nostackframe:boolean;
|
||||
inlined : boolean);
|
||||
procedure genexitcode(list : TAAsmoutput;parasize:longint;nostackframe:boolean;inlined:boolean);
|
||||
procedure genentrycode(list : TAAsmoutput;stackframe:longint;inlined : boolean);
|
||||
procedure genexitcode(list : TAAsmoutput;inlined:boolean);
|
||||
|
||||
procedure geninlineentrycode(list : TAAsmoutput;stackframe:longint);
|
||||
procedure geninlineexitcode(list : TAAsmoutput;inlined:boolean);
|
||||
|
||||
{#
|
||||
Allocate the buffers for exception management and setjmp environment.
|
||||
@ -1185,8 +1184,57 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
procedure initretvalue(list:taasmoutput);
|
||||
var
|
||||
paraloc : tparalocation;
|
||||
href : treference;
|
||||
begin
|
||||
if not is_void(current_procdef.rettype.def) then
|
||||
begin
|
||||
{ for now the pointer to the result can't be a register }
|
||||
if paramanager.ret_in_param(current_procdef.rettype.def,current_procdef.proccalloption) then
|
||||
begin
|
||||
{$ifdef powerpc}
|
||||
{ no stack space is allocated in this case -> can't save the result reg on the stack }
|
||||
if not(po_assembler in current_procdef.procoptions) then
|
||||
{$endif powerpc}
|
||||
begin
|
||||
paraloc:=paramanager.getfuncretparaloc(current_procdef);
|
||||
reference_reset_base(href,current_procinfo.framepointer,current_procinfo.return_offset);
|
||||
case paraloc.loc of
|
||||
LOC_CREGISTER,
|
||||
LOC_REGISTER:
|
||||
if not(paraloc.size in [OS_64,OS_S64]) then
|
||||
cg.a_load_reg_ref(list,paraloc.size,paraloc.register,href)
|
||||
else
|
||||
cg64.a_load64_reg_ref(list,paraloc.register64,href);
|
||||
LOC_CFPUREGISTER,
|
||||
LOC_FPUREGISTER:
|
||||
cg.a_load_reg_ref(list,paraloc.size,paraloc.register,href);
|
||||
LOC_CMMREGISTER,
|
||||
LOC_MMREGISTER:
|
||||
cg.a_loadmm_reg_ref(list,paraloc.register,href);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure handle_return_value(list:TAAsmoutput; inlined : boolean;var uses_acc,uses_acchi,uses_fpu : boolean);
|
||||
{ initialize return value }
|
||||
if (current_procdef.rettype.def.needs_inittable) then
|
||||
begin
|
||||
{$ifdef powerpc}
|
||||
if (po_assembler in current_procdef.procoptions) then
|
||||
internalerror(200304161);
|
||||
{$endif powerpc}
|
||||
if (cs_implicit_exceptions in aktmoduleswitches) then
|
||||
include(current_procinfo.flags,pi_needs_implicit_finally);
|
||||
reference_reset_base(href,current_procinfo.framepointer,current_procinfo.return_offset);
|
||||
cg.g_initialize(list,current_procdef.rettype.def,href,paramanager.ret_in_param(current_procdef.rettype.def,current_procdef.proccalloption));
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure handle_return_value(list:TAAsmoutput; var uses_acc,uses_acchi,uses_fpu : boolean);
|
||||
var
|
||||
href : treference;
|
||||
hreg,r,r2 : tregister;
|
||||
@ -1267,65 +1315,12 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
procedure handle_fast_exit_return_value(list:TAAsmoutput);
|
||||
var
|
||||
href : treference;
|
||||
hreg : tregister;
|
||||
cgsize : TCGSize;
|
||||
r,r2 : Tregister;
|
||||
begin
|
||||
if not is_void(current_procdef.rettype.def) then
|
||||
begin
|
||||
reference_reset_base(href,current_procinfo.framepointer,current_procinfo.return_offset);
|
||||
cgsize:=def_cgsize(current_procdef.rettype.def);
|
||||
case current_procdef.rettype.def.deftype of
|
||||
orddef,
|
||||
enumdef :
|
||||
begin
|
||||
{$ifndef cpu64bit}
|
||||
r.enum:=accumulator;
|
||||
r2.enum:=accumulatorhigh;
|
||||
if cgsize in [OS_64,OS_S64] then
|
||||
cg64.a_load64_reg_ref(list,joinreg64(r,r2),href)
|
||||
else
|
||||
{$endif cpu64bit}
|
||||
begin
|
||||
hreg:=rg.makeregsize(r,cgsize);
|
||||
cg.a_load_reg_ref(list,cgsize,hreg,href);
|
||||
end;
|
||||
end;
|
||||
floatdef :
|
||||
begin
|
||||
{$ifdef cpufpemu}
|
||||
if cs_fp_emulation in aktmoduleswitches then
|
||||
r.enum := accumulator
|
||||
else
|
||||
{$endif cpufpemu}
|
||||
r.enum:=fpu_result_reg;
|
||||
cg.a_loadfpu_reg_ref(list,cgsize,r,href);
|
||||
end;
|
||||
else
|
||||
begin
|
||||
r.enum:=accumulator;
|
||||
if not paramanager.ret_in_param(current_procdef.rettype.def,current_procdef.proccalloption) then
|
||||
cg.a_load_reg_ref(list,cgsize,r,href);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure genentrycode(list : TAAsmoutput;
|
||||
stackframe:longint;
|
||||
var parasize:longint;
|
||||
var nostackframe:boolean;
|
||||
inlined : boolean);
|
||||
procedure genentrycode(list : TAAsmoutput;stackframe:longint;inlined : boolean);
|
||||
var
|
||||
hs : string;
|
||||
href : treference;
|
||||
stackalloclist : taasmoutput;
|
||||
hp : tparaitem;
|
||||
paraloc : tparalocation;
|
||||
rsp : tregister;
|
||||
begin
|
||||
if not inlined then
|
||||
@ -1424,48 +1419,8 @@ implementation
|
||||
cg.g_profilecode(list);
|
||||
end;
|
||||
|
||||
if not is_void(current_procdef.rettype.def) then
|
||||
begin
|
||||
{ for now the pointer to the result can't be a register }
|
||||
if paramanager.ret_in_param(current_procdef.rettype.def,current_procdef.proccalloption) then
|
||||
begin
|
||||
{$ifdef powerpc}
|
||||
{ no stack space is allocated in this case -> can't save the result reg on the stack }
|
||||
if not(po_assembler in current_procdef.procoptions) then
|
||||
{$endif powerpc}
|
||||
begin
|
||||
paraloc:=paramanager.getfuncretparaloc(current_procdef);
|
||||
reference_reset_base(href,current_procinfo.framepointer,current_procinfo.return_offset);
|
||||
case paraloc.loc of
|
||||
LOC_CREGISTER,
|
||||
LOC_REGISTER:
|
||||
if not(paraloc.size in [OS_64,OS_S64]) then
|
||||
cg.a_load_reg_ref(list,paraloc.size,paraloc.register,href)
|
||||
else
|
||||
cg64.a_load64_reg_ref(list,paraloc.register64,href);
|
||||
LOC_CFPUREGISTER,
|
||||
LOC_FPUREGISTER:
|
||||
cg.a_load_reg_ref(list,paraloc.size,paraloc.register,href);
|
||||
LOC_CMMREGISTER,
|
||||
LOC_MMREGISTER:
|
||||
cg.a_loadmm_reg_ref(list,paraloc.register,href);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ initialize return value }
|
||||
if (current_procdef.rettype.def.needs_inittable) then
|
||||
begin
|
||||
{$ifdef powerpc}
|
||||
if (po_assembler in current_procdef.procoptions) then
|
||||
internalerror(200304161);
|
||||
{$endif powerpc}
|
||||
if (cs_implicit_exceptions in aktmoduleswitches) then
|
||||
include(current_procinfo.flags,pi_needs_implicit_finally);
|
||||
reference_reset_base(href,current_procinfo.framepointer,current_procinfo.return_offset);
|
||||
cg.g_initialize(list,current_procdef.rettype.def,href,paramanager.ret_in_param(current_procdef.rettype.def,current_procdef.proccalloption));
|
||||
end;
|
||||
end;
|
||||
{ initialize return value }
|
||||
initretvalue(list);
|
||||
|
||||
{ initialize local data like ansistrings }
|
||||
case current_procdef.proctypeoption of
|
||||
@ -1508,9 +1463,9 @@ implementation
|
||||
(cs_profile in aktmoduleswitches) then
|
||||
begin
|
||||
reference_reset_symbol(href,objectlibrary.newasmsymboldata('etext'),0);
|
||||
cg.a_paramaddr_ref(list,href,paraloc);
|
||||
cg.a_paramaddr_ref(list,href,paramanager.getintparaloc(2));
|
||||
reference_reset_symbol(href,objectlibrary.newasmsymboldata('__image_base__'),0);
|
||||
cg.a_paramaddr_ref(list,href,paraloc);
|
||||
cg.a_paramaddr_ref(list,href,paramanager.getintparaloc(2));
|
||||
cg.a_call_name(list,'_monstartup');
|
||||
end;
|
||||
|
||||
@ -1577,23 +1532,12 @@ implementation
|
||||
if (current_procinfo.framepointer.number=NR_STACK_POINTER_REG) then
|
||||
begin
|
||||
CGMessage(cg_d_stackframe_omited);
|
||||
nostackframe:=true;
|
||||
if (current_procdef.proctypeoption in [potype_unitinit,potype_proginit,potype_unitfinalize]) then
|
||||
parasize:=0
|
||||
else
|
||||
parasize:=current_procdef.parast.datasize+current_procdef.parast.address_fixup-4;
|
||||
if stackframe<>0 then
|
||||
cg.g_stackpointer_alloc(stackalloclist,stackframe);
|
||||
end
|
||||
else
|
||||
{$endif powerpc}
|
||||
begin
|
||||
nostackframe:=false;
|
||||
if (current_procdef.proctypeoption in [potype_unitinit,potype_proginit,potype_unitfinalize]) then
|
||||
parasize:=0
|
||||
else
|
||||
parasize:=current_procdef.parast.datasize+current_procdef.parast.address_fixup-target_info.first_parm_offset;
|
||||
|
||||
if (po_interrupt in current_procdef.procoptions) then
|
||||
cg.g_interrupt_stackframe_entry(stackalloclist);
|
||||
|
||||
@ -1612,7 +1556,7 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
procedure genexitcode(list : TAAsmoutput;parasize:longint;nostackframe:boolean;inlined:boolean);
|
||||
procedure genexitcode(list : TAAsmoutput;inlined:boolean);
|
||||
var
|
||||
{$ifdef GDB}
|
||||
stabsendlabel : tasmlabel;
|
||||
@ -1627,15 +1571,6 @@ implementation
|
||||
usesfpu : boolean;
|
||||
rsp,r : Tregister;
|
||||
begin
|
||||
if aktexit2label.is_used and
|
||||
((pi_needs_implicit_finally in current_procinfo.flags) or
|
||||
(pi_uses_exceptions in current_procinfo.flags)) then
|
||||
begin
|
||||
cg.a_jmp_always(list,aktexitlabel);
|
||||
cg.a_label(list,aktexit2label);
|
||||
handle_fast_exit_return_value(list);
|
||||
end;
|
||||
|
||||
if aktexitlabel.is_used then
|
||||
cg.a_label(list,aktexitlabel);
|
||||
|
||||
@ -1701,12 +1636,9 @@ implementation
|
||||
usesacc:=true;
|
||||
end
|
||||
else
|
||||
handle_return_value(list,inlined,usesacc,usesacchi,usesfpu)
|
||||
handle_return_value(list,usesacc,usesacchi,usesfpu)
|
||||
end;
|
||||
|
||||
if aktexit2label.is_used and not aktexit2label.is_set then
|
||||
cg.a_label(list,aktexit2label);
|
||||
|
||||
{$ifdef GDB}
|
||||
if ((cs_debuginfo in aktmoduleswitches) and not inlined) then
|
||||
begin
|
||||
@ -1739,14 +1671,13 @@ implementation
|
||||
{ remove stackframe }
|
||||
if not inlined then
|
||||
begin
|
||||
if (not nostackframe) then
|
||||
cg.g_restore_frame_pointer(list)
|
||||
if (current_procinfo.framepointer.number=NR_STACK_POINTER_REG) then
|
||||
begin
|
||||
if (tg.gettempsize<>0) then
|
||||
cg.a_op_const_reg(list,OP_ADD,tg.gettempsize,current_procinfo.framepointer);
|
||||
end
|
||||
else
|
||||
if (tg.gettempsize<>0) then
|
||||
begin
|
||||
r.enum:=stack_pointer_reg;
|
||||
cg.a_op_const_reg(list,OP_ADD,tg.gettempsize,r);
|
||||
end;
|
||||
cg.g_restore_frame_pointer(list);
|
||||
end;
|
||||
|
||||
{ at last, the return is generated }
|
||||
@ -1755,16 +1686,7 @@ implementation
|
||||
if (po_interrupt in current_procdef.procoptions) then
|
||||
cg.g_interrupt_stackframe_exit(list,usesacc,usesacchi)
|
||||
else
|
||||
begin
|
||||
{$ifndef i386}
|
||||
{ give a warning if the limit of parameters allowed for
|
||||
certain processors is reached.
|
||||
}
|
||||
if (parasize > maxparasize) then
|
||||
Message(cg_w_parasize_too_big);
|
||||
{$endif}
|
||||
cg.g_return_from_proc(list,parasize);
|
||||
end;
|
||||
cg.g_return_from_proc(list,current_procdef.parast.datasize);
|
||||
end;
|
||||
|
||||
if not inlined then
|
||||
@ -1833,10 +1755,143 @@ implementation
|
||||
cleanup_regvars(list);
|
||||
end;
|
||||
|
||||
|
||||
{****************************************************************************
|
||||
Inlining
|
||||
****************************************************************************}
|
||||
|
||||
procedure handle_inlined_return_value(list:TAAsmoutput);
|
||||
var
|
||||
href : treference;
|
||||
r,r2 : tregister;
|
||||
cgsize : TCGSize;
|
||||
begin
|
||||
if not is_void(current_procdef.rettype.def) then
|
||||
begin
|
||||
reference_reset_base(href,current_procinfo.framepointer,current_procinfo.return_offset);
|
||||
cgsize:=def_cgsize(current_procdef.rettype.def);
|
||||
{ Here, we return the function result. In most architectures, the value is
|
||||
passed into the accumulator, but in a windowed architecure like sparc a
|
||||
function returns in a register and the caller receives it in an other one }
|
||||
case current_procdef.rettype.def.deftype of
|
||||
orddef,
|
||||
enumdef :
|
||||
begin
|
||||
{$ifndef cpu64bit}
|
||||
if cgsize in [OS_64,OS_S64] then
|
||||
begin
|
||||
r:=rg.getregisterint(list,OS_INT);
|
||||
r2:=rg.getregisterint(list,OS_INT);
|
||||
cg64.a_load64_ref_reg(list,href,joinreg64(r,r2));
|
||||
end
|
||||
else
|
||||
{$endif cpu64bit}
|
||||
begin
|
||||
r:=rg.getregisterint(list,cgsize);
|
||||
cg.a_load_ref_reg(list,cgsize,href,r);
|
||||
end;
|
||||
end;
|
||||
floatdef :
|
||||
begin
|
||||
{$ifdef cpufpemu}
|
||||
if cs_fp_emulation in aktmoduleswitches then
|
||||
r.enum := accumulator
|
||||
else
|
||||
{$endif cpufpemu}
|
||||
r.enum:=fpu_result_reg;
|
||||
cg.a_loadfpu_ref_reg(list,cgsize,href,r);
|
||||
end;
|
||||
else
|
||||
begin
|
||||
if not paramanager.ret_in_param(current_procdef.rettype.def,current_procdef.proccalloption) then
|
||||
begin
|
||||
{$ifndef cpu64bit}
|
||||
{ Win32 can return records in EAX:EDX }
|
||||
if cgsize in [OS_64,OS_S64] then
|
||||
begin
|
||||
r:=rg.getregisterint(list,OS_INT);
|
||||
r2:=rg.getregisterint(list,OS_INT);
|
||||
cg64.a_load64_ref_reg(list,href,joinreg64(r,r2));
|
||||
end
|
||||
else
|
||||
{$endif cpu64bit}
|
||||
begin
|
||||
r:=rg.getregisterint(list,cgsize);
|
||||
cg.a_load_ref_reg(list,cgsize,href,r);
|
||||
end;
|
||||
end
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure geninlineentrycode(list : TAAsmoutput;stackframe:longint);
|
||||
begin
|
||||
{ initialize return value }
|
||||
initretvalue(list);
|
||||
|
||||
current_procdef.localst.foreach_static({$ifndef TP}@{$endif}initialize_data,list);
|
||||
|
||||
{ initialisizes temp. ansi/wide string data }
|
||||
inittempvariables(list);
|
||||
|
||||
{ initialize ansi/widesstring para's }
|
||||
if assigned(current_procdef.parast) then
|
||||
current_procdef.parast.foreach_static({$ifndef TP}@{$endif}init_paras,list);
|
||||
|
||||
{ generate copies of call by value parameters }
|
||||
if not(po_assembler in current_procdef.procoptions) then
|
||||
current_procdef.parast.foreach_static({$ifndef TP}@{$endif}copyvalueparas,list);
|
||||
|
||||
load_regvars(list,nil);
|
||||
end;
|
||||
|
||||
|
||||
procedure geninlineexitcode(list : TAAsmoutput;inlined:boolean);
|
||||
var
|
||||
usesacc,
|
||||
usesacchi,
|
||||
usesfpu : boolean;
|
||||
begin
|
||||
if aktexitlabel.is_used then
|
||||
cg.a_label(list,aktexitlabel);
|
||||
|
||||
cleanup_regvars(list);
|
||||
|
||||
{ finalize temporary data }
|
||||
finalizetempvariables(list);
|
||||
|
||||
current_procdef.localst.foreach_static({$ifndef TP}@{$endif}finalize_data,list);
|
||||
|
||||
{ finalize paras data }
|
||||
if assigned(current_procdef.parast) then
|
||||
current_procdef.parast.foreach_static({$ifndef TP}@{$endif}final_paras,list);
|
||||
|
||||
{ handle return value, this is not done for assembler routines when
|
||||
they didn't reference the result variable }
|
||||
if not(po_assembler in current_procdef.procoptions) or
|
||||
(assigned(current_procdef.funcretsym) and
|
||||
(tvarsym(current_procdef.funcretsym).refcount>1)) then
|
||||
begin
|
||||
if (current_procdef.proctypeoption=potype_constructor) then
|
||||
internalerror(200305263);
|
||||
// handle_inlined_return_value(list);
|
||||
handle_return_value(list,usesacc,usesacchi,usesfpu)
|
||||
end;
|
||||
|
||||
cleanup_regvars(list);
|
||||
end;
|
||||
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.106 2003-05-24 11:59:42 jonas
|
||||
Revision 1.107 2003-05-26 21:17:17 peter
|
||||
* procinlinenode removed
|
||||
* aktexit2label removed, fast exit removed
|
||||
+ tcallnode.inlined_pass_2 added
|
||||
|
||||
Revision 1.106 2003/05/24 11:59:42 jonas
|
||||
* fixed integer typeconversion problems
|
||||
|
||||
Revision 1.105 2003/05/23 14:27:35 peter
|
||||
|
@ -93,7 +93,6 @@ interface
|
||||
tfornodeclass = class of tfornode;
|
||||
|
||||
texitnode = class(tunarynode)
|
||||
onlyassign : boolean;
|
||||
constructor create(l:tnode);virtual;
|
||||
constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
|
||||
procedure ppuwrite(ppufile:tcompilerppufile);override;
|
||||
@ -835,56 +834,34 @@ implementation
|
||||
constructor texitnode.create(l:tnode);
|
||||
begin
|
||||
inherited create(exitn,l);
|
||||
onlyassign:=false;
|
||||
end;
|
||||
|
||||
|
||||
constructor texitnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
|
||||
begin
|
||||
inherited ppuload(t,ppufile);
|
||||
onlyassign:=boolean(ppufile.getbyte);
|
||||
end;
|
||||
|
||||
|
||||
procedure texitnode.ppuwrite(ppufile:tcompilerppufile);
|
||||
begin
|
||||
inherited ppuwrite(ppufile);
|
||||
ppufile.putbyte(byte(onlyassign));
|
||||
end;
|
||||
|
||||
|
||||
function texitnode.det_resulttype:tnode;
|
||||
begin
|
||||
result:=nil;
|
||||
{ Check the 2 types }
|
||||
if not inlining_procedure then
|
||||
begin
|
||||
if assigned(left) then
|
||||
begin
|
||||
inserttypeconv(left,current_procdef.rettype);
|
||||
if paramanager.ret_in_param(current_procdef.rettype.def,current_procdef.proccalloption) or
|
||||
(current_procdef.proctypeoption=potype_constructor) or
|
||||
(pi_needs_implicit_finally in current_procinfo.flags) or
|
||||
(pi_uses_exceptions in current_procinfo.flags) then
|
||||
begin
|
||||
left:=cassignmentnode.create(
|
||||
cloadnode.create(current_procdef.funcretsym,current_procdef.funcretsym.owner),
|
||||
left);
|
||||
onlyassign:=true;
|
||||
end
|
||||
else
|
||||
begin
|
||||
{ mark funcretsym as assigned }
|
||||
inc(tvarsym(current_procdef.funcretsym).refs);
|
||||
tvarsym(current_procdef.funcretsym).varstate:=vs_assigned;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
if assigned(left) then
|
||||
begin
|
||||
resulttypepass(left);
|
||||
set_varstate(left,true);
|
||||
end;
|
||||
begin
|
||||
{ add assignment to funcretsym }
|
||||
inserttypeconv(left,current_procdef.rettype);
|
||||
left:=cassignmentnode.create(
|
||||
cloadnode.create(current_procdef.funcretsym,current_procdef.funcretsym.owner),
|
||||
left);
|
||||
resulttypepass(left);
|
||||
set_varstate(left,true);
|
||||
end;
|
||||
resulttype:=voidtype;
|
||||
end;
|
||||
|
||||
@ -1449,7 +1426,12 @@ begin
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.74 2003-05-13 19:14:41 peter
|
||||
Revision 1.75 2003-05-26 21:17:17 peter
|
||||
* procinlinenode removed
|
||||
* aktexit2label removed, fast exit removed
|
||||
+ tcallnode.inlined_pass_2 added
|
||||
|
||||
Revision 1.74 2003/05/13 19:14:41 peter
|
||||
* failn removed
|
||||
* inherited result code check moven to pexpr
|
||||
|
||||
|
@ -109,7 +109,6 @@ interface
|
||||
asn, {Represents the as typecast}
|
||||
caretn, {Represents the ^ operator}
|
||||
starstarn, {Represents the ** operator exponentiation }
|
||||
procinlinen, {Procedures that can be inlined }
|
||||
arrayconstructorn, {Construction node for [...] parsing}
|
||||
arrayconstructorrangen, {Range element to allow sets in array construction tree}
|
||||
tempcreaten, { for temps in the result/firstpass }
|
||||
@ -188,7 +187,6 @@ interface
|
||||
'asn',
|
||||
'caretn',
|
||||
'starstarn',
|
||||
'procinlinen',
|
||||
'arrayconstructn',
|
||||
'arrayconstructrangen',
|
||||
'tempcreaten',
|
||||
@ -984,7 +982,12 @@ implementation
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.61 2003-05-13 19:14:41 peter
|
||||
Revision 1.62 2003-05-26 21:17:17 peter
|
||||
* procinlinenode removed
|
||||
* aktexit2label removed, fast exit removed
|
||||
+ tcallnode.inlined_pass_2 added
|
||||
|
||||
Revision 1.61 2003/05/13 19:14:41 peter
|
||||
* failn removed
|
||||
* inherited result code check moven to pexpr
|
||||
|
||||
|
@ -84,9 +84,11 @@ implementation
|
||||
end;
|
||||
case n.nodetype of
|
||||
calln:
|
||||
result := foreachnode(tcallnode(n).methodpointer,f) or result;
|
||||
procinlinen:
|
||||
result := foreachnode(tprocinlinenode(n).inlinetree,f) or result;
|
||||
begin
|
||||
{ not in one statement, won't work because of b- }
|
||||
result := foreachnode(tcallnode(n).methodpointer,f) or result;
|
||||
result := foreachnode(tcallnode(n).inlinecode,f) or result;
|
||||
end;
|
||||
ifn, whilerepeatn, forn:
|
||||
begin
|
||||
{ not in one statement, won't work because of b- }
|
||||
@ -129,9 +131,10 @@ implementation
|
||||
end;
|
||||
case n.nodetype of
|
||||
calln:
|
||||
result := foreachnodestatic(tcallnode(n).methodpointer,f) or result;
|
||||
procinlinen:
|
||||
result := foreachnodestatic(tprocinlinenode(n).inlinetree,f) or result;
|
||||
begin
|
||||
result := foreachnodestatic(tcallnode(n).methodpointer,f) or result;
|
||||
result := foreachnodestatic(tcallnode(n).inlinecode,f) or result;
|
||||
end;
|
||||
ifn, whilerepeatn, forn:
|
||||
begin
|
||||
{ not in one statement, won't work because of b- }
|
||||
@ -250,7 +253,12 @@ end.
|
||||
|
||||
{
|
||||
$Log$
|
||||
Revision 1.4 2003-05-16 14:33:31 peter
|
||||
Revision 1.5 2003-05-26 21:17:17 peter
|
||||
* procinlinenode removed
|
||||
* aktexit2label removed, fast exit removed
|
||||
+ tcallnode.inlined_pass_2 added
|
||||
|
||||
Revision 1.4 2003/05/16 14:33:31 peter
|
||||
* regvar fixes
|
||||
|
||||
Revision 1.3 2003/05/13 20:54:06 peter
|
||||
|
@ -134,7 +134,6 @@ implementation
|
||||
'as', {asn}
|
||||
'error-caret', {caretn}
|
||||
'add-starstar', {starstarn}
|
||||
'procinline', {procinlinen}
|
||||
'arrayconstruc', {arrayconstructn}
|
||||
'noth-arrcnstr', {arrayconstructrangen}
|
||||
'tempcreaten',
|
||||
@ -301,7 +300,12 @@ implementation
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.52 2003-05-15 18:58:53 peter
|
||||
Revision 1.53 2003-05-26 21:17:17 peter
|
||||
* procinlinenode removed
|
||||
* aktexit2label removed, fast exit removed
|
||||
+ tcallnode.inlined_pass_2 added
|
||||
|
||||
Revision 1.52 2003/05/15 18:58:53 peter
|
||||
* removed selfpointer_offset, vmtpointer_offset
|
||||
* tvarsym.adjusted_address
|
||||
* address in localsymtable is now in the real direction
|
||||
|
@ -768,11 +768,8 @@ implementation
|
||||
|
||||
procedure gen_implicit_initfinal(list:taasmoutput;flag:word;st:tsymtable);
|
||||
var
|
||||
parasize : longint;
|
||||
nostackframe : boolean;
|
||||
pd : tprocdef;
|
||||
oldexitlabel,
|
||||
oldexit2label : tasmlabel;
|
||||
oldexitlabel : tasmlabel;
|
||||
begin
|
||||
{ update module flags }
|
||||
current_module.flags:=current_module.flags or flag;
|
||||
@ -793,20 +790,15 @@ implementation
|
||||
end;
|
||||
{ save labels }
|
||||
oldexitlabel:=aktexitlabel;
|
||||
oldexit2label:=aktexit2label;
|
||||
{ generate a dummy function }
|
||||
parasize:=0;
|
||||
nostackframe:=false;
|
||||
objectlibrary.getlabel(aktexitlabel);
|
||||
objectlibrary.getlabel(aktexit2label);
|
||||
include(current_procinfo.flags,pi_do_call);
|
||||
genentrycode(list,0,parasize,nostackframe,false);
|
||||
genexitcode(list,parasize,nostackframe,false);
|
||||
genentrycode(list,0,false);
|
||||
genexitcode(list,false);
|
||||
list.convert_registers;
|
||||
release_main_proc(pd);
|
||||
{ restore }
|
||||
aktexitlabel:=oldexitlabel;
|
||||
aktexit2label:=oldexit2label;
|
||||
end;
|
||||
|
||||
|
||||
@ -1482,7 +1474,12 @@ So, all parameters are passerd into registers in sparc architecture.}
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.108 2003-05-25 10:27:12 peter
|
||||
Revision 1.109 2003-05-26 21:17:17 peter
|
||||
* procinlinenode removed
|
||||
* aktexit2label removed, fast exit removed
|
||||
+ tcallnode.inlined_pass_2 added
|
||||
|
||||
Revision 1.108 2003/05/25 10:27:12 peter
|
||||
* moved Comment calls to messge file
|
||||
|
||||
Revision 1.107 2003/05/22 21:31:35 peter
|
||||
|
@ -551,14 +551,9 @@ implementation
|
||||
var
|
||||
oldprocdef : tprocdef;
|
||||
oldprocinfo : tprocinfo;
|
||||
oldexitlabel,
|
||||
oldexit2label : tasmlabel;
|
||||
oldexitlabel : tasmlabel;
|
||||
oldaktmaxfpuregisters : longint;
|
||||
oldfilepos : tfileposinfo;
|
||||
{ true when no stackframe is required }
|
||||
nostackframe:boolean;
|
||||
{ number of bytes which have to be cleared by RET }
|
||||
parasize:longint;
|
||||
begin
|
||||
{ the initialization procedure can be empty, then we
|
||||
don't need to generate anything. When it was an empty
|
||||
@ -576,10 +571,8 @@ implementation
|
||||
|
||||
{ save old labels }
|
||||
oldexitlabel:=aktexitlabel;
|
||||
oldexit2label:=aktexit2label;
|
||||
{ get new labels }
|
||||
objectlibrary.getlabel(aktexitlabel);
|
||||
objectlibrary.getlabel(aktexit2label);
|
||||
aktbreaklabel:=nil;
|
||||
aktcontinuelabel:=nil;
|
||||
|
||||
@ -599,12 +592,12 @@ implementation
|
||||
{ first generate entry code with the correct position and switches }
|
||||
aktfilepos:=current_procinfo.entrypos;
|
||||
aktlocalswitches:=current_procinfo.entryswitches;
|
||||
genentrycode(current_procinfo.aktentrycode,0,parasize,nostackframe,false);
|
||||
genentrycode(current_procinfo.aktentrycode,0,false);
|
||||
|
||||
{ now generate exit code with the correct position and switches }
|
||||
aktfilepos:=current_procinfo.exitpos;
|
||||
aktlocalswitches:=current_procinfo.exitswitches;
|
||||
genexitcode(current_procinfo.aktexitcode,parasize,nostackframe,false);
|
||||
genexitcode(current_procinfo.aktexitcode,false);
|
||||
|
||||
{ now all the registers used are known }
|
||||
current_procdef.usedintregisters:=rg.usedintinproc;
|
||||
@ -666,7 +659,6 @@ implementation
|
||||
|
||||
{ restore labels }
|
||||
aktexitlabel:=oldexitlabel;
|
||||
aktexit2label:=oldexit2label;
|
||||
|
||||
{ restore }
|
||||
aktmaxfpuregisters:=oldaktmaxfpuregisters;
|
||||
@ -1216,7 +1208,12 @@ begin
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.117 2003-05-25 08:59:47 peter
|
||||
Revision 1.118 2003-05-26 21:17:18 peter
|
||||
* procinlinenode removed
|
||||
* aktexit2label removed, fast exit removed
|
||||
+ tcallnode.inlined_pass_2 added
|
||||
|
||||
Revision 1.117 2003/05/25 08:59:47 peter
|
||||
* do not generate code when there was an error
|
||||
|
||||
Revision 1.116 2003/05/23 18:49:55 jonas
|
||||
|
@ -423,7 +423,6 @@ implementation
|
||||
nodeclass[asn]:=casnode;
|
||||
nodeclass[caretn]:=caddnode;
|
||||
nodeclass[starstarn]:=caddnode;
|
||||
nodeclass[procinlinen]:=cprocinlinenode;
|
||||
nodeclass[arrayconstructorn]:=carrayconstructornode;
|
||||
nodeclass[arrayconstructorrangen]:=carrayconstructorrangenode;
|
||||
nodeclass[tempcreaten]:=ctempcreatenode;
|
||||
@ -494,7 +493,12 @@ implementation
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.51 2003-05-25 11:34:17 peter
|
||||
Revision 1.52 2003-05-26 21:17:18 peter
|
||||
* procinlinenode removed
|
||||
* aktexit2label removed, fast exit removed
|
||||
+ tcallnode.inlined_pass_2 added
|
||||
|
||||
Revision 1.51 2003/05/25 11:34:17 peter
|
||||
* methodpointer self pushing fixed
|
||||
|
||||
Revision 1.50 2003/05/13 19:14:41 peter
|
||||
|
@ -429,7 +429,6 @@ interface
|
||||
function concatpara(afterpara:tparaitem;const tt:ttype;sym : tsym;defval:tsym;vhidden:boolean):tparaitem;
|
||||
function insertpara(const tt:ttype;sym : tsym;defval:tsym;vhidden:boolean):tparaitem;
|
||||
procedure removepara(currpara:tparaitem);
|
||||
function para_size(alignsize:longint) : longint;
|
||||
function typename_paras(showhidden:boolean): string;
|
||||
procedure test_if_fpu_result;
|
||||
function is_methodpointer:boolean;virtual;
|
||||
@ -3278,29 +3277,6 @@ implementation
|
||||
|
||||
|
||||
|
||||
function tabstractprocdef.para_size(alignsize:longint) : longint;
|
||||
var
|
||||
pdc : TParaItem;
|
||||
l : longint;
|
||||
begin
|
||||
l:=0;
|
||||
pdc:=TParaItem(Para.first);
|
||||
while assigned(pdc) do
|
||||
begin
|
||||
inc(l,paramanager.push_size(pdc.paratyp,pdc.paratype.def,proccalloption));
|
||||
l:=align(l,alignsize);
|
||||
if assigned(pdc.paratype.def) and
|
||||
is_special_array(pdc.paratype.def) then
|
||||
begin
|
||||
inc(l,POINTER_SIZE);
|
||||
l:=align(l,alignsize);
|
||||
end;
|
||||
pdc:=TParaItem(pdc.next);
|
||||
end;
|
||||
para_size:=l;
|
||||
end;
|
||||
|
||||
|
||||
function tabstractprocdef.typename_paras(showhidden:boolean) : string;
|
||||
var
|
||||
hs,s : string;
|
||||
@ -5762,7 +5738,12 @@ implementation
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.145 2003-05-25 11:34:17 peter
|
||||
Revision 1.146 2003-05-26 21:17:18 peter
|
||||
* procinlinenode removed
|
||||
* aktexit2label removed, fast exit removed
|
||||
+ tcallnode.inlined_pass_2 added
|
||||
|
||||
Revision 1.145 2003/05/25 11:34:17 peter
|
||||
* methodpointer self pushing fixed
|
||||
|
||||
Revision 1.144 2003/05/15 18:58:53 peter
|
||||
|
Loading…
Reference in New Issue
Block a user