* fixed several issues with powerpc

+ applied a patch from Jonas for nested function calls (PowerPC only)
  * ...
This commit is contained in:
florian 2003-04-23 12:35:34 +00:00
parent 7dae726270
commit 0284016ee9
21 changed files with 640 additions and 156 deletions

View File

@ -72,6 +72,8 @@ unit cgbase;
procdef : tprocdef;
{# offset from frame pointer to get parent frame pointer reference
(used in nested routines only)
On the PowerPC, this is used to store the offset where the
frame pointer from the outer procedure is stored.
}
framepointer_offset : longint;
{# offset from frame pointer to get self reference }
@ -217,6 +219,8 @@ unit cgbase;
{ save the size of pushed parameter, needed for aligning }
pushedparasize : longint;
{ procinfo instance which is used in procedures created automatically by the compiler }
voidprocpi : tprocinfo;
{ message calls with codegenerror support }
procedure cgmessage(t : longint);
@ -515,6 +519,14 @@ implementation
ResourceStrings:=TResourceStrings.Create;
{ use the librarydata from current_module }
objectlibrary:=current_module.librarydata;
{ for the implicitly generated init/final. procedures for global init. variables,
a dummy procinfo is necessary }
voidprocpi:=cprocinfo.create;
with voidprocpi do
begin
framepointer.enum:=R_INTREGISTER;
framepointer.number:=NR_FRAME_POINTER_REG;
end;
end;
@ -549,6 +561,7 @@ implementation
{ resource strings }
ResourceStrings.free;
objectlibrary:=nil;
// voidprocpi.free;
end;
@ -644,7 +657,6 @@ implementation
commutativeop := list[op];
end;
{$ifdef fixLeaksOnError}
procedure hcodegen_do_stop;
var p: pprocinfo;
@ -652,7 +664,8 @@ begin
p := pprocinfo(procinfoStack.pop);
while p <> nil Do
begin
dispose(p,done);
if p<>voidprocpi then
p.free;
p := pprocinfo(procinfoStack.pop);
end;
procinfoStack.done;
@ -668,7 +681,12 @@ begin
end.
{
$Log$
Revision 1.40 2003-04-22 13:47:08 peter
Revision 1.41 2003-04-23 12:35:34 florian
* fixed several issues with powerpc
+ applied a patch from Jonas for nested function calls (PowerPC only)
* ...
Revision 1.40 2003/04/22 13:47:08 peter
* fixed C style array of const
* fixed C array passing
* fixed left to right with high parameters

View File

@ -44,9 +44,14 @@ interface
LOC_FPUREGISTER, { FPU stack }
LOC_CFPUREGISTER, { if it is a FPU register variable on the fpu stack }
LOC_MMXREGISTER, { MMX register }
LOC_CMMXREGISTER, { MMX register variable }
{ MMX register variable }
LOC_CMMXREGISTER,
LOC_SSEREGISTER,
LOC_CSSEREGISTER
LOC_CSSEREGISTER,
{ multimedia register }
LOC_MMREGISTER,
{ Constant multimedia reg which shouldn't be modified }
LOC_CMMREGISTER
);
{# Generic opcodes, which must be supported by all processors
@ -126,7 +131,12 @@ implementation
end.
{
$Log$
Revision 1.19 2003-04-22 23:50:22 peter
Revision 1.20 2003-04-23 12:35:34 florian
* fixed several issues with powerpc
+ applied a patch from Jonas for nested function calls (PowerPC only)
* ...
Revision 1.19 2003/04/22 23:50:22 peter
* firstpass uses expectloc
* checks if there are differences between the expectloc and
location.loc from secondpass in EXTDEBUG

View File

@ -1808,7 +1808,7 @@ unit cgobj;
var r:Tregister;
begin
r.enum:=R_INTREGISTER;;
r.enum:=R_INTREGISTER;
r.number:=NR_ACCUMULATOR;
a_load_ref_reg(list, OS_S32, href, r);
end;
@ -1838,7 +1838,12 @@ finalization
end.
{
$Log$
Revision 1.84 2003-04-22 14:33:38 peter
Revision 1.85 2003-04-23 12:35:34 florian
* fixed several issues with powerpc
+ applied a patch from Jonas for nested function calls (PowerPC only)
* ...
Revision 1.84 2003/04/22 14:33:38 peter
* removed some notes/hints
Revision 1.83 2003/04/22 13:47:08 peter

View File

@ -52,6 +52,9 @@
{$define cpu64bit}
{$undef cpuflags}
{$endif alpha}
{$ifdef powerpc}
{$define callparatemp}
{$endif powerpc}
{ FPU Emulator support }
{$ifdef m68k}
@ -60,7 +63,12 @@
{
$Log$
Revision 1.14 2002-12-06 16:56:57 peter
Revision 1.15 2003-04-23 12:35:34 florian
* fixed several issues with powerpc
+ applied a patch from Jonas for nested function calls (PowerPC only)
* ...
Revision 1.14 2002/12/06 16:56:57 peter
* only compile cs_fp_emulation support when cpufpuemu is defined
* define cpufpuemu for m68k only

View File

@ -114,7 +114,7 @@ uses
R_INTREGISTER,R_FLOATREGISTER);
Tnewregister=word;
Tregister=record
enum:Toldregister;
number:word;
@ -151,14 +151,14 @@ uses
NR_D6 = $0700; NR_D7 = $0800; NR_A0 = $0900;
NR_A1 = $0A00; NR_A2 = $0B00; NR_A3 = $0C00;
NR_A4 = $0D00; NR_A5 = $0E00; NR_A6 = $0F00;
NR_A7 = $1000;
NR_A7 = $1000;
{Super registers.}
RS_D0 = $01; RS_D1 = $02; RS_D2 = $03;
RS_D3 = $04; RS_D4 = $05; RS_D5 = $06;
RS_D6 = $07; RS_D7 = $08; RS_A0 = $09;
RS_A1 = $0A; RS_A2 = $0B; RS_A3 = $0C;
RS_A4 = $0D; RS_A5 = $0E; RS_A6 = $0F;
RS_D0 = $01; RS_D1 = $02; RS_D2 = $03;
RS_D3 = $04; RS_D4 = $05; RS_D5 = $06;
RS_D6 = $07; RS_D7 = $08; RS_A0 = $09;
RS_A1 = $0A; RS_A2 = $0B; RS_A3 = $0C;
RS_A4 = $0D; RS_A5 = $0E; RS_A6 = $0F;
RS_A7 = $10;
{Sub register numbers:}
@ -288,35 +288,15 @@ uses
*****************************************************************************}
type
TLoc=(
LOC_INVALID, { added for tracking problems}
LOC_CONSTANT, { constant value }
LOC_JUMP, { boolean results only, jump to false or true label }
LOC_FLAGS, { boolean results only, flags are set }
LOC_CREFERENCE, { in memory constant value reference (cannot change) }
LOC_REFERENCE, { in memory value }
LOC_REGISTER, { in a processor register }
LOC_CREGISTER, { Constant register which shouldn't be modified }
LOC_FPUREGISTER, { FPU stack }
LOC_CFPUREGISTER, { if it is a FPU register variable on the fpu stack }
{ The m68k doesn't know multi media registers but this is for easier porting
because several generic parts of the compiler use it. }
LOC_MMREGISTER,
{ The m68k doesn't know multi media registers but this is for easier porting
because several generic parts of the compiler use it. }
LOC_CMMREGISTER
);
{ tparamlocation describes where a parameter for a procedure is stored.
References are given from the caller's point of view. The usual
TLocation isn't used, because contains a lot of unnessary fields.
}
tparalocation = packed record
size : TCGSize;
loc : TLoc;
loc : TCGLoc;
sp_fixup : longint;
case TLoc of
case TCGLoc of
LOC_REFERENCE : (reference : tparareference);
{ segment in reference at the same place as in loc_register }
LOC_REGISTER,LOC_CREGISTER : (
@ -331,9 +311,9 @@ uses
end;
tlocation = packed record
loc : TLoc;
loc : TCGLoc;
size : TCGSize;
case TLoc of
case TCGLoc of
LOC_FLAGS : (resflags : tresflags);
LOC_CONSTANT : (
case longint of
@ -646,7 +626,7 @@ implementation
function flags_to_cond(const f: TResFlags) : TAsmCond;
const flags2cond: array[tresflags] of tasmcond = (
C_EQ,{F_E equal}
C_EQ,{F_E equal}
C_NE,{F_NE not equal}
C_GT,{F_G gt signed}
C_LT,{F_L lt signed}
@ -726,7 +706,12 @@ implementation
end.
{
$Log$
Revision 1.18 2003-02-19 22:00:16 daniel
Revision 1.19 2003-04-23 12:35:35 florian
* fixed several issues with powerpc
+ applied a patch from Jonas for nested function calls (PowerPC only)
* ...
Revision 1.18 2003/02/19 22:00:16 daniel
* Code generator converted to new register notation
- Horribily outdated todo.txt removed

View File

@ -29,7 +29,7 @@ interface
uses
cutils,cclasses,
globtype,cpuinfo,
node,
node,nbas,
{$ifdef state_tracking}
nstate,
{$endif state_tracking}
@ -113,6 +113,9 @@ interface
function docompare(p: tnode): boolean; override;
procedure set_procvar(procvar:tnode);
private
{$ifdef callparatemp}
function extract_functioncall_paras: tblocknode;
{$endif callparatemp}
AbstractMethodsList : TStringList;
end;
tcallnodeclass = class of tcallnode;
@ -179,7 +182,8 @@ implementation
verbose,globals,
symconst,paramgr,defutil,defcmp,
htypechk,pass_1,cpubase,
nbas,ncnv,nld,ninl,nadd,ncon,nmem,
ncnv,nld,ninl,nadd,ncon,nmem,
nutils,
rgobj,cginfo,cgbase
;
@ -1958,6 +1962,58 @@ type
end;
{$ifdef callparatemp}
function tree_contains_function_call(var n: tnode): foreachnoderesult;
begin
result := fen_false;
if n.nodetype = calln then
{ stop when we encounter a call node }
result := fen_norecurse_true;
end;
function tcallnode.extract_functioncall_paras: tblocknode;
var
curpara: tcallparanode;
newblock: tblocknode;
newstatement: tstatementnode;
temp: ttempcreatenode;
foundcall: boolean;
begin
foundcall := false;
curpara := tcallparanode(left);
if assigned(curpara) then
curpara := tcallparanode(curpara.right);
newblock := nil;
while assigned(curpara) do
begin
if foreachnodestatic(curpara.left,@tree_contains_function_call) then
begin
if (not foundcall) then
begin
foundcall := true;
newblock := internalstatements(newstatement);
end;
temp := ctempcreatenode.create(curpara.left.resulttype,curpara.left.resulttype.def.size,true);
addstatement(newstatement,temp);
resulttypepass(newstatement);
addstatement(newstatement,
cassignmentnode.create(ctemprefnode.create(temp),curpara.left));
resulttypepass(newstatement);
{ after the assignment, turn the temp into a non-persistent one, so }
{ that it will be freed once it's used as parameter }
addstatement(newstatement,ctempdeletenode.create_normal_temp(temp));
resulttypepass(newstatement);
curpara.left := ctemprefnode.create(temp);
{ the para's themselves are "resulttypepassed" in in tcallnode.pass_1 }
end;
curpara := tcallparanode(curpara.right);
end;
result := newblock;
end;
{$endif callparatemp}
function tcallnode.pass_1 : tnode;
var
inlinecode : tnode;
@ -1965,6 +2021,11 @@ type
{$ifdef m68k}
regi : tregister;
{$endif}
{$ifdef callparatemp}
callparatemps, newblock: tblocknode;
statement: tstatementnode;
paras, oldright, newcall: tnode;
{$endif callparatemp}
label
errorexit;
begin
@ -1972,6 +2033,10 @@ type
inlined:=false;
inlinecode := nil;
{$ifdef callparatemp}
callparatemps := extract_functioncall_paras;
{$endif callparatemp}
{ work trough all parameters to get the register requirements }
if assigned(left) then
tcallparanode(left).det_registers;
@ -2176,9 +2241,39 @@ type
registersmmx:=max(left.registersmmx,registersmmx);
{$endif SUPPORT_MMX}
end;
{$ifdef callparatemp}
if (callparatemps <> nil) then
begin
{ we have to replace the callnode with a blocknode. firstpass will }
{ free the original call node. Avoid copying all subnodes though }
paras := left;
oldright := right;
left := nil;
right := nil;
newcall := self.getcopy;
tcallnode(newcall).left := paras;
tcallnode(newcall).right := oldright;
newblock := internalstatements(statement);
addstatement(statement,callparatemps);
{ add the copy of the call node after the callparatemps block }
{ and return that. The last statement of a bocknode determines }
{ the resulttype & location of the block -> ok. Working with a }
{ new block is easier than going to the end of the callparatemps }
{ block (JM) }
addstatement(statement,newcall);
result := newblock;
{ set to nil so we can free this one in case of an errorexit }
callparatemps := nil;
end;
{$endif callparatemp}
errorexit:
if inlined then
procdefinition.proccalloption:=pocall_inline;
{$ifdef callparatemp}
if assigned(callparatemps) then
callparatemps.free;
{$endif callparatemp}
end;
{$ifdef state_tracking}
@ -2391,7 +2486,12 @@ begin
end.
{
$Log$
Revision 1.139 2003-04-22 23:50:22 peter
Revision 1.140 2003-04-23 12:35:34 florian
* fixed several issues with powerpc
+ applied a patch from Jonas for nested function calls (PowerPC only)
* ...
Revision 1.139 2003/04/22 23:50:22 peter
* firstpass uses expectloc
* checks if there are differences between the expectloc and
location.loc from secondpass in EXTDEBUG

View File

@ -2000,7 +2000,11 @@ implementation
procedure genimplicitunitinit(list : TAAsmoutput);
var
oldprocinfo : tprocinfo;
begin
oldprocinfo:=procinfo;
procinfo:=voidprocpi;
{$ifdef GDB}
if (cs_debuginfo in aktmoduleswitches) and
target_info.use_function_relative_addresses then
@ -2008,17 +2012,26 @@ implementation
{$endif GDB}
list.concat(Tai_symbol.Createname_global('INIT$$'+current_module.modulename^,0));
list.concat(Tai_symbol.Createname_global(target_info.cprefix+current_module.modulename^+'_init',0));
{$ifndef i386}
{ on the 386, g_return_from_proc is a simple return, so we don't need a real stack frame }
cg.g_stackframe_entry(list,0);
{$endif i386}
{ using current_module.globalsymtable is hopefully }
{ more robust than symtablestack and symtablestack.next }
if assigned(current_module.globalsymtable) then
tsymtable(current_module.globalsymtable).foreach_static({$ifdef FPCPROCVAR}@{$endif}finalize_data,list);
tsymtable(current_module.localsymtable).foreach_static({$ifdef FPCPROCVAR}@{$endif}finalize_data,list);
cg.g_return_from_proc(list,0);
procinfo:=oldprocinfo;
end;
procedure genimplicitunitfinal(list : TAAsmoutput);
var
oldprocinfo : tprocinfo;
begin
oldprocinfo:=procinfo;
procinfo:=voidprocpi;
{$ifdef GDB}
if (cs_debuginfo in aktmoduleswitches) and
target_info.use_function_relative_addresses then
@ -2026,20 +2039,28 @@ implementation
{$endif GDB}
list.concat(Tai_symbol.Createname_global('FINALIZE$$'+current_module.modulename^,0));
list.concat(Tai_symbol.Createname_global(target_info.cprefix+current_module.modulename^+'_finalize',0));
{$ifndef i386}
{ on the 386, g_return_from_proc is a simple return, so we don't need a real stack frame }
cg.g_stackframe_entry(list,0);
{$endif i386}
{ using current_module.globalsymtable is hopefully }
{ more robust than symtablestack and symtablestack.next }
if assigned(current_module.globalsymtable) then
tsymtable(current_module.globalsymtable).foreach_static({$ifdef FPCPROCVAR}@{$endif}finalize_data,list);
tsymtable(current_module.localsymtable).foreach_static({$ifdef FPCPROCVAR}@{$endif}finalize_data,list);
cg.g_return_from_proc(list,0);
procinfo:=oldprocinfo;
end;
end.
{
$Log$
Revision 1.87 2003-04-22 14:33:38 peter
Revision 1.88 2003-04-23 12:35:34 florian
* fixed several issues with powerpc
+ applied a patch from Jonas for nested function calls (PowerPC only)
* ...
Revision 1.87 2003/04/22 14:33:38 peter
* removed some notes/hints
Revision 1.86 2003/04/22 13:47:08 peter

156
compiler/nutils.pas Normal file
View File

@ -0,0 +1,156 @@
{
$Id$
Copyright (c) 1998-2002 by Florian Klaempfl
Type checking and register allocation for inline 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 nutils;
{$i fpcdefs.inc}
interface
uses
node;
type
{ resulttype of functions that process on all nodes in a (sub)tree }
foreachnoderesult = (
{ false, continue recursion }
fen_false,
{ false, stop recursion }
fen_norecurse_false,
{ true, continue recursion }
fen_true,
{ true, stop recursion }
fen_norecurse_true
);
foreachnodefunction = function(var n: tnode): foreachnoderesult of object;
staticforeachnodefunction = function(var n: tnode): foreachnoderesult;
function foreachnode(var n: tnode; f: foreachnodefunction): boolean;
function foreachnodestatic(var n: tnode; f: staticforeachnodefunction): boolean;
implementation
uses nflw,nset,ncal;
function foreachnode(var n: tnode; f: foreachnodefunction): boolean;
begin
result := false;
if not assigned(n) then
exit;
case f(n) of
fen_norecurse_false:
exit;
fen_norecurse_true:
begin
result := true;
exit;
end;
fen_true:
result := true;
{ result is already false
fen_false:
result := false; }
end;
case n.nodetype of
calln:
result := foreachnode(tcallnode(n).methodpointer,f) or result;
procinlinen:
result := foreachnode(tprocinlinenode(n).inlinetree,f) or result;
ifn, whilerepeatn, forn:
begin
{ not in one statement, won't work because of b- }
result := foreachnode(tloopnode(n).t1,f) or result;
result := foreachnode(tloopnode(n).t2,f) or result;
end;
raisen:
result := foreachnode(traisenode(n).frametree,f) or result;
casen:
result := foreachnode(tcasenode(n). elseblock,f) or result;
end;
if n.inheritsfrom(tbinarynode) then
begin
result := foreachnode(tbinarynode(n).right,f) or result;
result := foreachnode(tbinarynode(n).left,f) or result;
end
else if n.inheritsfrom(tunarynode) then
result := foreachnode(tunarynode(n).left,f) or result;
end;
function foreachnodestatic(var n: tnode; f: staticforeachnodefunction): boolean;
begin
result := false;
if not assigned(n) then
exit;
case f(n) of
fen_norecurse_false:
exit;
fen_norecurse_true:
begin
result := true;
exit;
end;
fen_true:
result := true;
{ result is already false
fen_false:
result := false; }
end;
case n.nodetype of
calln:
result := foreachnodestatic(tcallnode(n).methodpointer,f) or result;
procinlinen:
result := foreachnodestatic(tprocinlinenode(n).inlinetree,f) or result;
ifn, whilerepeatn, forn:
begin
{ not in one statement, won't work because of b- }
result := foreachnodestatic(tloopnode(n).t1,f) or result;
result := foreachnodestatic(tloopnode(n).t2,f) or result;
end;
raisen:
result := foreachnodestatic(traisenode(n).frametree,f) or result;
casen:
result := foreachnodestatic(tcasenode(n). elseblock,f) or result;
end;
if n.inheritsfrom(tbinarynode) then
begin
result := foreachnodestatic(tbinarynode(n).right,f) or result;
result := foreachnodestatic(tbinarynode(n).left,f) or result;
end
else if n.inheritsfrom(tunarynode) then
result := foreachnodestatic(tunarynode(n).left,f) or result;
end;
end.
{
$Log$
Revision 1.1 2003-04-23 12:35:34 florian
* fixed several issues with powerpc
+ applied a patch from Jonas for nested function calls (PowerPC only)
* ...
}

View File

@ -774,7 +774,9 @@ implementation
store_crc,store_interface_crc : cardinal;
s2 : ^string; {Saves stack space}
force_init_final : boolean;
initfinalcode : taasmoutput;
begin
initfinalcode:=taasmoutput.create;
consume(_UNIT);
if compile_level=1 then
Status.IsExe:=false;
@ -999,7 +1001,9 @@ implementation
{ now we can insert a cut }
if (cs_create_smart in aktmoduleswitches) then
codeSegment.concat(Tai_cut.Create);
genimplicitunitinit(codesegment);
genimplicitunitinit(initfinalcode);
initfinalcode.convert_registers;
codesegment.concatlist(initfinalcode);
end;
{ finalize? }
if token=_FINALIZATION then
@ -1021,7 +1025,9 @@ implementation
{ now we can insert a cut }
if (cs_create_smart in aktmoduleswitches) then
codeSegment.concat(Tai_cut.Create);
genimplicitunitfinal(codesegment);
genimplicitunitfinal(initfinalcode);
initfinalcode.convert_registers;
codesegment.concatlist(initfinalcode);
end;
{ the last char should always be a point }
@ -1166,7 +1172,10 @@ implementation
exit;
end;
initfinalcode.free;
Comment(V_Used,'Finished compiling module '+current_module.modulename^);
end;
@ -1175,7 +1184,9 @@ implementation
main_file: tinputfile;
st : tsymtable;
hp : tmodule;
initfinalcode : taasmoutput;
begin
initfinalcode:=taasmoutput.create;
DLLsource:=islibrary;
Status.IsLibrary:=IsLibrary;
Status.IsExe:=true;
@ -1318,11 +1329,15 @@ So, all parameters are passerd into registers in sparc architecture.}
{ Add initialize section }
if (cs_create_smart in aktmoduleswitches) then
codeSegment.concat(Tai_cut.Create);
genimplicitunitinit(codesegment);
genimplicitunitinit(initfinalcode);
initfinalcode.convert_registers;
codesegment.concatlist(initfinalcode);
{ Add finalize section }
if (cs_create_smart in aktmoduleswitches) then
codeSegment.concat(Tai_cut.Create);
genimplicitunitfinal(codesegment);
genimplicitunitfinal(initfinalcode);
initfinalcode.convert_registers;
codesegment.concatlist(initfinalcode);
end;
{ Add symbol to the exports section for win32 so smartlinking a
@ -1448,12 +1463,18 @@ So, all parameters are passerd into registers in sparc architecture.}
linker.MakeExecutable;
end;
end;
initfinalcode.free;
end;
end.
{
$Log$
Revision 1.100 2003-04-12 15:13:03 peter
Revision 1.101 2003-04-23 12:35:34 florian
* fixed several issues with powerpc
+ applied a patch from Jonas for nested function calls (PowerPC only)
* ...
Revision 1.100 2003/04/12 15:13:03 peter
* Use the original unitname when defining a unitsym
Revision 1.99 2003/03/23 23:21:42 hajny

View File

@ -174,10 +174,10 @@ unit agppcgas;
if (symaddr <> refs_full) then
s := s+')'+symaddr2str[symaddr];
if (index.enum < firstreg) or (index.enum > lastreg) then
internalerror(20030312);
if (base.enum < firstreg) or (base.enum > lastreg) then
internalerror(200303123);
if (index.enum < firstreg) or (index.enum > lastreg) then
internalerror(20030312);
if (base.enum < firstreg) or (base.enum > lastreg) then
internalerror(200303123);
if (index.enum=R_NO) and (base.enum<>R_NO) then
begin
if offset=0 then
@ -192,7 +192,7 @@ unit agppcgas;
else if (index.enum<>R_NO) and (base.enum<>R_NO) and (offset=0) then
s:=s+gas_reg2str[base.enum]+','+gas_reg2str[index.enum]
else if ((index.enum<>R_NO) or (base.enum<>R_NO)) then
internalerror(19992);
internalerror(19992);
end;
getreferencestring:=s;
end;
@ -364,6 +364,9 @@ unit agppcgas;
sep:=#9;
for i:=0 to taicpu(hp).ops-1 do
begin
// debug code
// writeln(s);
// writeln(taicpu(hp).fileinfo.line);
s:=s+sep+getopstr(taicpu(hp).oper[i]);
sep:=',';
end;
@ -377,7 +380,12 @@ begin
end.
{
$Log$
Revision 1.21 2003-03-12 22:43:38 jonas
Revision 1.22 2003-04-23 12:35:35 florian
* fixed several issues with powerpc
+ applied a patch from Jonas for nested function calls (PowerPC only)
* ...
Revision 1.21 2003/03/12 22:43:38 jonas
* more powerpc and generic fixes related to the new register allocator
Revision 1.20 2003/01/08 18:43:57 daniel

View File

@ -76,7 +76,7 @@ unit cgcpu;
procedure g_flags2reg(list: taasmoutput; size: TCgSize; const f: TResFlags; reg: TRegister); override;
procedure g_copyvaluepara_openarray(list : taasmoutput;const ref:treference;elesize:integer);override;
procedure g_stackframe_entry(list : taasmoutput;localsize : longint);override;
procedure g_return_from_proc(list : taasmoutput;parasize : aword); override;
procedure g_restore_frame_pointer(list : taasmoutput);override;
@ -958,7 +958,7 @@ const
{ following is the entry code as described in "Altivec Programming }
{ Interface Manual", bar the saving of AltiVec registers }
rsp.enum:=R_INTREGISTER;
rsp.number:=NR_STACK_POINTER_REG;;
rsp.number:=NR_STACK_POINTER_REG;
a_reg_alloc(list,rsp);
r.enum:=R_INTREGISTER;
r.number:=NR_R0;
@ -1824,6 +1824,128 @@ const
free_scratch_reg(list,dst.base);
end;
procedure tcgppc.g_copyvaluepara_openarray(list : taasmoutput;const ref:treference;elesize:integer);
var
lenref : treference;
power,len : longint;
{$ifndef __NOWINPECOFF__}
again,ok : tasmlabel;
{$endif}
r,r2,rsp:Tregister;
begin
{$warning !!!! FIX ME !!!!}
{!!!!
lenref:=ref;
inc(lenref.offset,4);
{ get stack space }
r.enum:=R_INTREGISTER;
r.number:=NR_EDI;
rsp.enum:=R_INTREGISTER;
rsp.number:=NR_ESP;
r2.enum:=R_INTREGISTER;
rg.getexplicitregisterint(list,NR_EDI);
list.concat(Taicpu.op_ref_reg(A_MOV,S_L,lenref,r));
list.concat(Taicpu.op_reg(A_INC,S_L,r));
if (elesize<>1) then
begin
if ispowerof2(elesize, power) then
list.concat(Taicpu.op_const_reg(A_SHL,S_L,power,r))
else
list.concat(Taicpu.op_const_reg(A_IMUL,S_L,elesize,r));
end;
{$ifndef __NOWINPECOFF__}
{ windows guards only a few pages for stack growing, }
{ so we have to access every page first }
if target_info.system=system_i386_win32 then
begin
objectlibrary.getlabel(again);
objectlibrary.getlabel(ok);
a_label(list,again);
list.concat(Taicpu.op_const_reg(A_CMP,S_L,winstackpagesize,r));
a_jmp_cond(list,OC_B,ok);
list.concat(Taicpu.op_const_reg(A_SUB,S_L,winstackpagesize-4,rsp));
r2.number:=NR_EAX;
list.concat(Taicpu.op_reg(A_PUSH,S_L,r));
list.concat(Taicpu.op_const_reg(A_SUB,S_L,winstackpagesize,r));
a_jmp_always(list,again);
a_label(list,ok);
list.concat(Taicpu.op_reg_reg(A_SUB,S_L,r,rsp));
rg.ungetregisterint(list,r);
{ now reload EDI }
rg.getexplicitregisterint(list,NR_EDI);
list.concat(Taicpu.op_ref_reg(A_MOV,S_L,lenref,r));
list.concat(Taicpu.op_reg(A_INC,S_L,r));
if (elesize<>1) then
begin
if ispowerof2(elesize, power) then
list.concat(Taicpu.op_const_reg(A_SHL,S_L,power,r))
else
list.concat(Taicpu.op_const_reg(A_IMUL,S_L,elesize,r));
end;
end
else
{$endif __NOWINPECOFF__}
list.concat(Taicpu.op_reg_reg(A_SUB,S_L,r,rsp));
{ align stack on 4 bytes }
list.concat(Taicpu.op_const_reg(A_AND,S_L,$fffffff4,rsp));
{ load destination }
a_load_reg_reg(list,OS_INT,OS_INT,rsp,r);
{ don't destroy the registers! }
r2.number:=NR_ECX;
list.concat(Taicpu.op_reg(A_PUSH,S_L,r2));
r2.number:=NR_ESI;
list.concat(Taicpu.op_reg(A_PUSH,S_L,r2));
{ load count }
r2.number:=NR_ECX;
a_load_ref_reg(list,OS_INT,lenref,r2);
{ load source }
r2.number:=NR_ESI;
a_load_ref_reg(list,OS_INT,ref,r2);
{ scheduled .... }
r2.number:=NR_ECX;
list.concat(Taicpu.op_reg(A_INC,S_L,r2));
{ calculate size }
len:=elesize;
opsize:=S_B;
if (len and 3)=0 then
begin
opsize:=S_L;
len:=len shr 2;
end
else
if (len and 1)=0 then
begin
opsize:=S_W;
len:=len shr 1;
end;
if ispowerof2(len, power) then
list.concat(Taicpu.op_const_reg(A_SHL,S_L,power,r2))
else
list.concat(Taicpu.op_const_reg(A_IMUL,S_L,len,r2));
list.concat(Taicpu.op_none(A_REP,S_NO));
case opsize of
S_B : list.concat(Taicpu.Op_none(A_MOVSB,S_NO));
S_W : list.concat(Taicpu.Op_none(A_MOVSW,S_NO));
S_L : list.concat(Taicpu.Op_none(A_MOVSD,S_NO));
end;
rg.ungetregisterint(list,r);
r2.number:=NR_ESI;
list.concat(Taicpu.op_reg(A_POP,S_L,r2));
r2.number:=NR_ECX;
list.concat(Taicpu.op_reg(A_POP,S_L,r2));
{ patch the new address }
a_load_reg_ref(list,OS_INT,rsp,ref);
!!!!}
end;
procedure tcgppc.g_overflowcheck(list: taasmoutput; const p: tnode);
@ -2215,7 +2337,12 @@ begin
end.
{
$Log$
Revision 1.78 2003-04-16 09:26:55 jonas
Revision 1.79 2003-04-23 12:35:35 florian
* fixed several issues with powerpc
+ applied a patch from Jonas for nested function calls (PowerPC only)
* ...
Revision 1.78 2003/04/16 09:26:55 jonas
* assembler procedures now again get a stackframe if they have local
variables. No space is reserved for a function result however.
Also, the register parameters aren't automatically saved on the stack

View File

@ -395,33 +395,6 @@ uses
*****************************************************************************}
type
TLoc=(
{ added for tracking problems}
LOC_INVALID,
{ ordinal constant }
LOC_CONSTANT,
{ in a processor register }
LOC_REGISTER,
{ Constant register which shouldn't be modified }
LOC_CREGISTER,
{ FPU register}
LOC_FPUREGISTER,
{ Constant FPU register which shouldn't be modified }
LOC_CFPUREGISTER,
{ multimedia register }
LOC_MMREGISTER,
{ Constant multimedia reg which shouldn't be modified }
LOC_CMMREGISTER,
{ in memory }
LOC_REFERENCE,
{ in memory (constant) }
LOC_CREFERENCE,
{ boolean results only, jump to false or true label }
LOC_JUMP,
{ boolean results only, flags are set }
LOC_FLAGS
);
{ tparamlocation describes where a parameter for a procedure is stored.
References are given from the caller's point of view. The usual
TLocation isn't used, because contains a lot of unnessary fields.
@ -431,7 +404,7 @@ uses
{ The location type where the parameter is passed, usually
LOC_REFERENCE,LOC_REGISTER or LOC_FPUREGISTER
}
loc : TLoc;
loc : TCGLoc;
{ The stack pointer must be decreased by this value before
the parameter is copied to the given destination.
This allows to "encode" pushes with tparalocation.
@ -439,7 +412,7 @@ uses
because several generic code accesses it.
}
sp_fixup : longint;
case TLoc of
case TCGLoc of
LOC_REFERENCE : (reference : tparareference);
LOC_FPUREGISTER, LOC_CFPUREGISTER, LOC_MMREGISTER, LOC_CMMREGISTER,
LOC_REGISTER,LOC_CREGISTER : (
@ -466,8 +439,8 @@ uses
tlocation = packed record
size : TCGSize;
loc : tloc;
case tloc of
loc : tcgloc;
case tcgloc of
LOC_CREFERENCE,LOC_REFERENCE : (reference : treference);
LOC_CONSTANT : (
case longint of
@ -879,7 +852,12 @@ implementation
end.
{
$Log$
Revision 1.47 2003-04-22 11:27:48 florian
Revision 1.48 2003-04-23 12:35:35 florian
* fixed several issues with powerpc
+ applied a patch from Jonas for nested function calls (PowerPC only)
* ...
Revision 1.47 2003/04/22 11:27:48 florian
+ added first_ and last_imreg
Revision 1.46 2003/03/19 14:26:26 jonas

View File

@ -67,7 +67,7 @@ unit cpupara;
end;
end;
function getparaloc(p : tdef) : tloc;
function getparaloc(p : tdef) : tcgloc;
begin
{ Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER
@ -129,7 +129,7 @@ unit cpupara;
paradef : tdef;
stack_offset : aword;
hp : tparaitem;
loc : tloc;
loc : tcgloc;
is_64bit: boolean;
procedure assignintreg;
@ -301,7 +301,12 @@ begin
end.
{
$Log$
Revision 1.25 2003-04-17 18:52:35 jonas
Revision 1.26 2003-04-23 12:35:35 florian
* fixed several issues with powerpc
+ applied a patch from Jonas for nested function calls (PowerPC only)
* ...
Revision 1.25 2003/04/17 18:52:35 jonas
* process para's from first to last instead of the other way round
Revision 1.24 2003/04/16 07:55:07 jonas

View File

@ -73,7 +73,7 @@ interface
result := nil;
firstpass(left);
firstpass(right);
location.loc := LOC_FLAGS;
expectloc := LOC_FLAGS;
calcregisters(self,2,0,0);
exit;
end;
@ -1479,7 +1479,12 @@ begin
end.
{
$Log$
Revision 1.24 2003-03-11 21:46:24 jonas
Revision 1.25 2003-04-23 12:35:35 florian
* fixed several issues with powerpc
+ applied a patch from Jonas for nested function calls (PowerPC only)
* ...
Revision 1.24 2003/03/11 21:46:24 jonas
* lots of new regallocator fixes, both in generic and ppc-specific code
(ppc compiler still can't compile the linux system unit though)

View File

@ -72,38 +72,43 @@ implementation
end;
procedure tppccallnode.push_framepointer;
var
href : treference;
hregister1,hregister2 : tregister;
i : longint;
begin
{
if lexlevel=(tprocdef(procdefinition).parast.symtablelevel) then
begin
reference_reset_base(href,procinfo^.framepointer,procinfo^.framepointer_offset);
cg.a_param_ref(exprasmlist,OS_ADDR,href,paramanager.getframepointerloc(procinfo.procdef));
{ pass the same framepointer as the current procedure got }
hregister2.enum:=R_INTREGISTER;
hregister2.number:=NR_R11;
cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,procinfo.framepointer,hregister2);
{ it must be adjusted! }
end
{ this is only true if the difference is one !!
but it cannot be more !! }
else if (lexlevel=(tprocdef(procdefinition).parast.symtablelevel)-1) then
begin
cg.a_param_reg(exprasmlist,OS_ADDR,procinfo^.framepointer,paramanager.getframepointerloc(procinfo.procdef));
// cg.a_param_reg(exprasmlist,OS_ADDR,procinfo.framepointer,paramanager.getframepointerloc(procinfo.procdef));
end
else if (lexlevel>(tprocdef(procdefinition).parast.symtablelevel)) then
begin
hregister:=rg.getregisterint(exprasmlist);
reference_reset_base(href,procinfo^.framepointer,procinfo^.framepointer_offset);
cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister);
hregister1:=rg.getregisterint(exprasmlist,OS_ADDR);
reference_reset_base(href,procinfo.framepointer,procinfo.framepointer_offset);
cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister1);
for i:=(tprocdef(procdefinition).parast.symtablelevel) to lexlevel-1 do
begin
{we should get the correct frame_pointer_offset at each level
how can we do this !!! }
reference_reset_base(href,hregister,procinfo^.framepointer_offset);
cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister);
reference_reset_base(href,hregister2,procinfo.framepointer_offset);
cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister1);
end;
cg.a_param_reg(exprasmlist,OS_ADDR,hregister,-1);
rg.ungetregisterint(exprasmlist,hregister);
hregister2.enum:=R_11;
cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,hregister1,hregister2);
rg.ungetregisterint(exprasmlist,hregister1);
end
else
internalerror(2002081303);
}
end;
begin
@ -111,7 +116,12 @@ begin
end.
{
$Log$
Revision 1.5 2003-04-04 15:38:56 peter
Revision 1.6 2003-04-23 12:35:35 florian
* fixed several issues with powerpc
+ applied a patch from Jonas for nested function calls (PowerPC only)
* ...
Revision 1.5 2003/04/04 15:38:56 peter
* moved generic code from n386cal to ncgcal, i386 now also
uses the generic ncgcal

View File

@ -272,7 +272,7 @@ implementation
begin
{ byte(boolean) or word(wordbool) or longint(longbool) must }
{ be accepted for var parameters }
if (nf_explizit in flags) and
if (nf_explicit in flags) and
(left.resulttype.def.size=resulttype.def.size) and
(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CREGISTER]) then
begin
@ -394,7 +394,12 @@ begin
end.
{
$Log$
Revision 1.30 2003-03-11 21:46:24 jonas
Revision 1.31 2003-04-23 12:35:35 florian
* fixed several issues with powerpc
+ applied a patch from Jonas for nested function calls (PowerPC only)
* ...
Revision 1.30 2003/03/11 21:46:24 jonas
* lots of new regallocator fixes, both in generic and ppc-specific code
(ppc compiler still can't compile the linux system unit though)

View File

@ -64,7 +64,7 @@ implementation
function tppcinlinenode.first_abs_real : tnode;
begin
location.loc:=LOC_FPUREGISTER;
expectloc:=LOC_FPUREGISTER;
registers32:=left.registers32;
registersfpu:=max(left.registersfpu,1);
{$ifdef SUPPORT_MMX}
@ -75,7 +75,7 @@ implementation
function tppcinlinenode.first_sqr_real : tnode;
begin
location.loc:=LOC_FPUREGISTER;
expectloc:=LOC_FPUREGISTER;
registers32:=left.registers32;
registersfpu:=max(left.registersfpu,1);
{$ifdef SUPPORT_MMX}
@ -86,7 +86,7 @@ implementation
function tppcinlinenode.first_sqrt_real : tnode;
begin
location.loc:=LOC_FPUREGISTER;
expectloc:=LOC_FPUREGISTER;
registers32:=left.registers32;
registersfpu:=max(left.registersfpu,1);
{$ifdef SUPPORT_MMX}
@ -126,6 +126,7 @@ implementation
procedure tppcinlinenode.second_abs_real;
begin
location.loc:=LOC_FPUREGISTER;
load_fpu_location;
exprasmlist.concat(taicpu.op_reg_reg(A_FABS,location.register,
left.location.register));
@ -133,6 +134,7 @@ implementation
procedure tppcinlinenode.second_sqr_real;
begin
location.loc:=LOC_FPUREGISTER;
load_fpu_location;
exprasmlist.concat(taicpu.op_reg_reg_reg(A_FMUL,location.register,
left.location.register,left.location.register));
@ -140,6 +142,7 @@ implementation
procedure tppcinlinenode.second_sqrt_real;
begin
location.loc:=LOC_FPUREGISTER;
load_fpu_location;
exprasmlist.concat(taicpu.op_reg_reg(A_FSQRT,location.register,
left.location.register));
@ -150,7 +153,12 @@ begin
end.
{
$Log$
Revision 1.4 2002-11-25 17:43:28 peter
Revision 1.5 2003-04-23 12:35:35 florian
* fixed several issues with powerpc
+ applied a patch from Jonas for nested function calls (PowerPC only)
* ...
Revision 1.4 2002/11/25 17:43:28 peter
* splitted defbase in defutil,symutil,defcmp
* merged isconvertable and is_equal into compare_defs(_ext)
* made operator search faster by walking the list only once

View File

@ -329,7 +329,7 @@ implementation
{When we are called to compile the body of a unit, aktprocsym should
point to the unit initialization. If the unit has no initialization,
aktprocsym=nil. But in that case code=nil. hus we should check for
aktprocsym=nil. But in that case code=nil. Thus we should check for
code=nil, when we use aktprocsym.}
{ set the start offset to the start of the temp area in the stack }
@ -884,7 +884,12 @@ implementation
end.
{
$Log$
Revision 1.101 2003-04-22 14:33:38 peter
Revision 1.102 2003-04-23 12:35:34 florian
* fixed several issues with powerpc
+ applied a patch from Jonas for nested function calls (PowerPC only)
* ...
Revision 1.101 2003/04/22 14:33:38 peter
* removed some notes/hints
Revision 1.100 2003/04/22 13:47:08 peter

View File

@ -281,7 +281,7 @@ const
{Subregisters; nothing known about.}
R_SUBWHOLE=$00;
R_SUBL=$00;
type
reg2strtable=ARRAY[TOldRegister] OF STRING[7];
@ -366,30 +366,14 @@ TYPE
Generic Location
*****************************************************************************}
TYPE
TLoc=( {information about the location of an operand}
LOC_INVALID, { added for tracking problems}
LOC_CONSTANT, { CONSTant value }
LOC_JUMP, { boolean results only, jump to false or true label }
LOC_FLAGS, { boolean results only, flags are set }
LOC_CREFERENCE, { in memory CONSTant value }
LOC_REFERENCE, { in memory value }
LOC_REGISTER, { in a processor register }
LOC_CREGISTER, { Constant register which shouldn't be modified }
LOC_FPUREGISTER, { FPU stack }
LOC_CFPUREGISTER, { if it is a FPU register variable on the fpu stack }
LOC_MMXREGISTER, { MMX register }
LOC_CMMXREGISTER, { MMX register variable }
LOC_MMREGISTER,
LOC_CMMREGISTER
);
{tparamlocation describes where a parameter for a procedure is stored.
References are given from the caller's point of view. The usual TLocation isn't
used, because contains a lot of unnessary fields.}
TParaLocation=PACKED RECORD
Size:TCGSize;
Loc:TLoc;
Loc:TCGLoc;
sp_fixup:LongInt;
CASE TLoc OF
CASE TCGLoc OF
LOC_REFERENCE:(reference:tparareference);
{ segment in reference at the same place as in loc_register }
LOC_REGISTER,LOC_CREGISTER : (
@ -405,9 +389,9 @@ used, because contains a lot of unnessary fields.}
LOC_MMXREGISTER,LOC_CMMXREGISTER : (mmxreg : tregister);
END;
TLocation=PACKED RECORD
loc : TLoc;
loc : TCGLoc;
size : TCGSize;
case TLoc of
case TCGLoc of
LOC_FLAGS : (resflags : tresflags);
LOC_CONSTANT : (
case longint of
@ -455,13 +439,13 @@ const
mmregs=[];
usableregsmm=[];
c_countusableregsmm=0;
{ no distinction on this platform }
{ no distinction on this platform }
maxaddrregs = 0;
addrregs = [];
usableregsaddr = [];
c_countusableregsaddr = 0;
firstsaveintreg = RS_O0;
lastsaveintreg = RS_I7;
firstsavefpureg = R_F0;
@ -591,8 +575,8 @@ const
max_operands = 3;
maxintregs = maxvarregs;
maxfpuregs = maxfpuvarregs;
FUNCTION is_calljmp(o:tasmop):boolean;
FUNCTION flags_to_cond(CONST f:TResFlags):TAsmCond;
@ -676,7 +660,12 @@ END.
{
$Log$
Revision 1.25 2003-03-10 21:59:54 mazen
Revision 1.26 2003-04-23 12:35:35 florian
* fixed several issues with powerpc
+ applied a patch from Jonas for nested function calls (PowerPC only)
* ...
Revision 1.25 2003/03/10 21:59:54 mazen
* fixing index overflow in handling new registers arrays.
Revision 1.24 2003/02/26 22:06:27 mazen

View File

@ -63,7 +63,7 @@ function TSparcParaManager.GetIntParaLoc(nr:longint):TParaLocation;
reference.offset:=-68-nr*4;
end;
end;
function GetParaLoc(p:TDef):TLoc;
function GetParaLoc(p:TDef):TCGLoc;
begin
{Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER if
push_addr_param for the def is true}
@ -124,7 +124,7 @@ procedure TSparcParaManager.create_param_loc_info(p:TAbstractProcDef);
nextintreg,nextfloatreg:tregister;
stack_offset:aword;
hp:tparaitem;
loc:tloc;
loc:tcgloc;
is_64bit:boolean;
begin
nextintreg.enum:=R_O0;
@ -281,7 +281,12 @@ begin
end.
{
$Log$
Revision 1.14 2003-01-08 18:43:58 daniel
Revision 1.15 2003-04-23 12:35:35 florian
* fixed several issues with powerpc
+ applied a patch from Jonas for nested function calls (PowerPC only)
* ...
Revision 1.14 2003/01/08 18:43:58 daniel
* Tregister changed into a record
Revision 1.13 2003/01/05 21:32:35 mazen

View File

@ -687,11 +687,19 @@ interface
ordpointertype,
pvmttype : ttype; { type of classrefs, used for stabs }
{ pointer to the anchestor of all classes }
class_tobject : tobjectdef;
{ pointer to the ancestor of all COM interfaces }
interface_iunknown : tobjectdef;
{ pointer to the TGUID type
of all interfaces }
rec_tguid : trecorddef;
class_tobject : tobjectdef; { pointer to the anchestor of all classes }
interface_iunknown : tobjectdef; { KAZ: pointer to the ancestor }
rec_tguid : trecorddef; { KAZ: pointer to the TGUID type }
{ of all interfaces }
{ Pointer to a procdef with no parameters and no return value.
This is used for procedures which are generated automatically
by the compiler.
}
voidprocdef : tprocdef;
const
{$ifdef i386}
@ -5706,10 +5714,17 @@ implementation
(tobjectdef(def).objecttype in [odt_class,odt_interfacecom,odt_interfacecorba]);
end;
begin
voidprocdef:=tprocdef.create;
end.
{
$Log$
Revision 1.133 2003-04-10 17:57:53 peter
Revision 1.134 2003-04-23 12:35:34 florian
* fixed several issues with powerpc
+ applied a patch from Jonas for nested function calls (PowerPC only)
* ...
Revision 1.133 2003/04/10 17:57:53 peter
* vs_hidden released
Revision 1.132 2003/03/18 16:25:50 peter