fpc/compiler/ncgbas.pas
peter 4285e99853 * internal linker
* reorganized aasm layer
2002-07-01 18:46:20 +00:00

365 lines
12 KiB
ObjectPascal

{
$Id$
Copyright (c) 2000-2002 by Florian Klaempfl
This unit implements some basic nodes
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
****************************************************************************
}
unit ncgbas;
{$i fpcdefs.inc}
interface
uses
node,nbas;
type
tcgnothingnode = class(tnothingnode)
procedure pass_2;override;
end;
tcgasmnode = class(tasmnode)
procedure pass_2;override;
end;
tcgstatementnode = class(tstatementnode)
procedure pass_2;override;
end;
tcgblocknode = class(tblocknode)
procedure pass_2;override;
end;
tcgtempcreatenode = class(ttempcreatenode)
procedure pass_2;override;
end;
tcgtemprefnode = class(ttemprefnode)
procedure pass_2;override;
end;
tcgtempdeletenode = class(ttempdeletenode)
procedure pass_2;override;
end;
implementation
uses
globtype,systems,
cutils,verbose,globals,
aasmbase,aasmtai,aasmcpu,symsym,
cpubase,
nflw,pass_2,
cgbase,cgobj,tgobj,rgobj
;
{*****************************************************************************
TNOTHING
*****************************************************************************}
procedure tcgnothingnode.pass_2;
begin
{ avoid an abstract rte }
end;
{*****************************************************************************
TSTATEMENTNODE
*****************************************************************************}
procedure tcgstatementnode.pass_2;
var
hp : tnode;
begin
hp:=self;
while assigned(hp) do
begin
if assigned(tstatementnode(hp).right) then
begin
rg.cleartempgen;
secondpass(tstatementnode(hp).right);
{ Compiler inserted blocks can return values }
location_copy(location,tstatementnode(hp).right.location);
end;
hp:=tstatementnode(hp).left;
end;
end;
{*****************************************************************************
TASMNODE
*****************************************************************************}
procedure tcgasmnode.pass_2;
procedure ReLabel(var p:tasmsymbol);
begin
if p.proclocal then
begin
if not assigned(p.altsymbol) then
begin
{ generatealtsymbol will also increase the refs }
p.GenerateAltSymbol;
UsedAsmSymbolListInsert(p);
end
else
begin
{ increase the refs, they will be decreased when the
asmnode is destroyed }
inc(p.refs);
end;
p:=p.altsymbol;
end;
end;
var
hp,hp2 : tai;
localfixup,parafixup,
i : longint;
skipnode : boolean;
begin
if inlining_procedure then
begin
CreateUsedAsmSymbolList;
localfixup:=aktprocdef.localst.address_fixup;
parafixup:=aktprocdef.parast.address_fixup;
hp:=tai(p_asm.first);
while assigned(hp) do
begin
hp2:=tai(hp.getcopy);
skipnode:=false;
case hp2.typ of
ait_label :
begin
{ regenerate the labels by setting altsymbol }
ReLabel(tasmsymbol(tai_label(hp2).l));
end;
ait_const_rva,
ait_const_symbol :
begin
ReLabel(tai_const_symbol(hp2).sym);
end;
ait_instruction :
begin
{ remove cached insentry, because the new code can
require an other less optimized instruction }
{$ifdef i386}
{$ifndef NOAG386BIN}
taicpu(hp2).ResetPass1;
{$endif}
{$endif}
{ fixup the references }
for i:=1 to taicpu(hp2).ops do
begin
with taicpu(hp2).oper[i-1] do
begin
case typ of
top_ref :
begin
case ref^.options of
ref_parafixup :
ref^.offsetfixup:=parafixup;
ref_localfixup :
ref^.offsetfixup:=localfixup;
end;
if assigned(ref^.symbol) then
ReLabel(ref^.symbol);
end;
top_symbol :
begin
ReLabel(sym);
end;
end;
end;
end;
end;
ait_marker :
begin
{ it's not an assembler block anymore }
if (tai_marker(hp2).kind in [AsmBlockStart, AsmBlockEnd]) then
skipnode:=true;
end;
else
end;
if not skipnode then
exprasmList.concat(hp2)
else
hp2.free;
hp:=tai(hp.next);
end;
{ restore used symbols }
UsedAsmSymbolListResetAltSym;
DestroyUsedAsmSymbolList;
end
else
begin
{ if the routine is an inline routine, then we must hold a copy
because it can be necessary for inlining later }
if (aktprocdef.proccalloption=pocall_inline) then
exprasmList.concatlistcopy(p_asm)
else
exprasmList.concatlist(p_asm);
end;
if not (nf_object_preserved in flags) then
cg.g_maybe_loadself(exprasmlist);
end;
{*****************************************************************************
TBLOCKNODE
*****************************************************************************}
procedure tcgblocknode.pass_2;
begin
{ do second pass on left node }
if assigned(left) then
begin
secondpass(left);
{ Compiler inserted blocks can return values }
location_copy(location,left.location);
end;
end;
{*****************************************************************************
TTEMPCREATENODE
*****************************************************************************}
procedure tcgtempcreatenode.pass_2;
begin
{ if we're secondpassing the same tcgtempcreatenode twice, we have a bug }
if tempinfo^.valid then
internalerror(200108222);
{ get a (persistent) temp }
if persistent then
tg.gettempofsizereferencepersistant(exprasmlist,size,tempinfo^.ref)
else
tg.gettempofsizereference(exprasmlist,size,tempinfo^.ref);
tempinfo^.valid := true;
end;
{*****************************************************************************
TTEMPREFNODE
*****************************************************************************}
procedure tcgtemprefnode.pass_2;
begin
{ check if the temp is valid }
if not tempinfo^.valid then
internalerror(200108231);
{ set the temp's location }
location_reset(location,LOC_REFERENCE,def_cgsize(tempinfo^.restype.def));
location.reference := tempinfo^.ref;
inc(location.reference.offset,offset);
end;
{*****************************************************************************
TTEMPDELETENODE
*****************************************************************************}
procedure tcgtempdeletenode.pass_2;
begin
if release_to_normal then
tg.persistanttemptonormal(tempinfo^.ref.offset)
else
tg.ungetpersistanttempreference(exprasmlist,tempinfo^.ref);
end;
begin
cnothingnode:=tcgnothingnode;
casmnode:=tcgasmnode;
cstatementnode:=tcgstatementnode;
cblocknode:=tcgblocknode;
ctempcreatenode:=tcgtempcreatenode;
ctemprefnode:=tcgtemprefnode;
ctempdeletenode:=tcgtempdeletenode;
end.
{
$Log$
Revision 1.20 2002-07-01 18:46:22 peter
* internal linker
* reorganized aasm layer
Revision 1.19 2002/05/18 13:34:09 peter
* readded missing revisions
Revision 1.18 2002/05/16 19:46:37 carl
+ defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
+ try to fix temp allocation (still in ifdef)
+ generic constructor calls
+ start of tassembler / tmodulebase class cleanup
Revision 1.16 2002/05/13 19:54:37 peter
* removed n386ld and n386util units
* maybe_save/maybe_restore added instead of the old maybe_push
Revision 1.15 2002/05/12 16:53:07 peter
* moved entry and exitcode to ncgutil and cgobj
* foreach gets extra argument for passing local data to the
iterator function
* -CR checks also class typecasts at runtime by changing them
into as
* fixed compiler to cycle with the -CR option
* fixed stabs with elf writer, finally the global variables can
be watched
* removed a lot of routines from cga unit and replaced them by
calls to cgobj
* u32bit-s32bit updates for and,or,xor nodes. When one element is
u32bit then the other is typecasted also to u32bit without giving
a rangecheck warning/error.
* fixed pascal calling method with reversing also the high tree in
the parast, detected by tcalcst3 test
Revision 1.14 2002/04/23 19:16:34 peter
* add pinline unit that inserts compiler supported functions using
one or more statements
* moved finalize and setlength from ninl to pinline
Revision 1.13 2002/04/21 19:02:03 peter
* removed newn and disposen nodes, the code is now directly
inlined from pexpr
* -an option that will write the secondpass nodes to the .s file, this
requires EXTDEBUG define to actually write the info
* fixed various internal errors and crashes due recent code changes
Revision 1.12 2002/04/04 19:05:57 peter
* removed unused units
* use tlocation.size in cg.a_*loc*() routines
Revision 1.11 2002/03/31 20:26:34 jonas
+ a_loadfpu_* and a_loadmm_* methods in tcg
* register allocation is now handled by a class and is mostly processor
independent (+rgobj.pas and i386/rgcpu.pas)
* temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
* some small improvements and fixes to the optimizer
* some register allocation fixes
* some fpuvaroffset fixes in the unary minus node
* push/popusedregisters is now called rg.save/restoreusedregisters and
(for i386) uses temps instead of push/pop's when using -Op3 (that code is
also better optimizable)
* fixed and optimized register saving/restoring for new/dispose nodes
* LOC_FPU locations now also require their "register" field to be set to
R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
- list field removed of the tnode class because it's not used currently
and can cause hard-to-find bugs
}