mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-21 15:49:26 +02:00
* init/final of procedure data splitted from genentrycode
* use asmnode getposition to insert final at the correct position als for the implicit try...finally
This commit is contained in:
parent
47b691057b
commit
77d641fa2a
@ -89,31 +89,6 @@ unit cgbase;
|
||||
{# register used as frame pointer }
|
||||
framepointer : tregister;
|
||||
|
||||
{# Holds the environment reference for default exceptions
|
||||
|
||||
The exception reference is created when ansistrings
|
||||
or classes are used. It holds buffer for exception
|
||||
frames. It is allocted by g_new_exception.
|
||||
}
|
||||
exception_env_ref : treference;
|
||||
{# Holds the environment reference for default exceptions
|
||||
|
||||
The exception reference is created when ansistrings
|
||||
or classes are used. It holds buffer for setjmp
|
||||
It is allocted by g_new_exception.
|
||||
}
|
||||
exception_jmp_ref :treference;
|
||||
{# Holds the environment reference for default exceptions
|
||||
|
||||
The exception reference is created when ansistrings
|
||||
or classes are used. It holds the location where
|
||||
temporary storage of the setjmp result is stored.
|
||||
|
||||
This reference can be unused, if the result is instead
|
||||
saved on the stack.
|
||||
}
|
||||
exception_result_ref :treference;
|
||||
|
||||
{# Holds the reference used to store the original stackpointer
|
||||
after all registers are saved
|
||||
}
|
||||
@ -125,16 +100,15 @@ unit cgbase;
|
||||
systems
|
||||
}
|
||||
save_regs_ref : treference;
|
||||
|
||||
{ label to leave the sub routine }
|
||||
aktexitlabel : tasmlabel;
|
||||
|
||||
{# The code for the routine itself, excluding entry and
|
||||
exit code. This is a linked list of tai classes.
|
||||
}
|
||||
aktproccode : taasmoutput;
|
||||
{# The code for the routine entry code.
|
||||
}
|
||||
aktentrycode: taasmoutput;
|
||||
{# The code for the routine exit code.
|
||||
}
|
||||
aktexitcode: taasmoutput;
|
||||
{ Data (like jump tables) that belongs to this routine }
|
||||
aktlocaldata : taasmoutput;
|
||||
|
||||
constructor create(aparent:tprocinfo);virtual;
|
||||
@ -183,9 +157,6 @@ unit cgbase;
|
||||
{ label when the result is true or false }
|
||||
truelabel,falselabel : tasmlabel;
|
||||
|
||||
{ label to leave the sub routine }
|
||||
aktexitlabel : tasmlabel;
|
||||
|
||||
{# true, if there was an error while code generation occurs }
|
||||
codegenerror : boolean;
|
||||
|
||||
@ -349,26 +320,22 @@ implementation
|
||||
flags:=[];
|
||||
framepointer.enum:=R_INTREGISTER;
|
||||
framepointer.number:=NR_FRAME_POINTER_REG;
|
||||
|
||||
aktentrycode:=Taasmoutput.Create;
|
||||
aktexitcode:=Taasmoutput.Create;
|
||||
{ asmlists }
|
||||
aktproccode:=Taasmoutput.Create;
|
||||
aktlocaldata:=Taasmoutput.Create;
|
||||
reference_reset(exception_env_ref);
|
||||
reference_reset(exception_jmp_ref);
|
||||
reference_reset(exception_result_ref);
|
||||
reference_reset(save_stackptr_ref);
|
||||
{ labels }
|
||||
objectlibrary.getlabel(aktexitlabel);
|
||||
end;
|
||||
|
||||
|
||||
destructor tprocinfo.destroy;
|
||||
begin
|
||||
aktentrycode.free;
|
||||
aktexitcode.free;
|
||||
aktproccode.free;
|
||||
aktlocaldata.free;
|
||||
end;
|
||||
|
||||
|
||||
procedure tprocinfo.allocate_interrupt_stackframe;
|
||||
begin
|
||||
end;
|
||||
@ -408,8 +375,6 @@ implementation
|
||||
|
||||
|
||||
procedure tprocinfo.after_header;
|
||||
var
|
||||
srsym : tvarsym;
|
||||
begin
|
||||
end;
|
||||
|
||||
@ -531,6 +496,7 @@ implementation
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
function int_cgsize(const a: aword): tcgsize;
|
||||
begin
|
||||
if a > 8 then
|
||||
@ -573,7 +539,12 @@ implementation
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.53 2003-06-02 21:42:05 jonas
|
||||
Revision 1.54 2003-06-09 12:23:29 peter
|
||||
* init/final of procedure data splitted from genentrycode
|
||||
* use asmnode getposition to insert final at the correct position
|
||||
als for the implicit try...finally
|
||||
|
||||
Revision 1.53 2003/06/02 21:42:05 jonas
|
||||
* function results can now also be regvars
|
||||
- removed tprocinfo.return_offset, never use it again since it's invalid
|
||||
if the result is a regvar
|
||||
|
@ -1040,10 +1040,10 @@ implementation
|
||||
oldprocinfo : tprocinfo;
|
||||
oldinlining_procedure : boolean;
|
||||
inlineentrycode,inlineexitcode : TAAsmoutput;
|
||||
oldexitlabel:tasmlabel;
|
||||
oldregstate: pointer;
|
||||
old_local_fixup,
|
||||
old_para_fixup : longint;
|
||||
usesacc,usesacchi,usesfpu : boolean;
|
||||
pararef,
|
||||
localsref : treference;
|
||||
{$ifdef GDB}
|
||||
@ -1056,10 +1056,8 @@ implementation
|
||||
internalerror(200305262);
|
||||
|
||||
oldinlining_procedure:=inlining_procedure;
|
||||
oldexitlabel:=aktexitlabel;
|
||||
oldprocdef:=current_procdef;
|
||||
oldprocinfo:=current_procinfo;
|
||||
objectlibrary.getlabel(aktexitlabel);
|
||||
{ we're inlining a procedure }
|
||||
inlining_procedure:=true;
|
||||
|
||||
@ -1258,7 +1256,7 @@ implementation
|
||||
inlineentrycode:=TAAsmoutput.Create;
|
||||
inlineexitcode:=TAAsmoutput.Create;
|
||||
|
||||
geninlineentrycode(inlineentrycode,0);
|
||||
gen_initialize_code(inlineentrycode,true);
|
||||
if po_assembler in current_procdef.procoptions then
|
||||
inlineentrycode.insert(Tai_marker.Create(asmblockstart));
|
||||
exprasmList.concatlist(inlineentrycode);
|
||||
@ -1279,7 +1277,8 @@ implementation
|
||||
testregisters32;
|
||||
{$endif TEMPREGDEBUG}
|
||||
|
||||
geninlineexitcode(inlineexitcode,true);
|
||||
gen_finalize_code(inlineexitcode,true);
|
||||
gen_load_return_value(inlineexitcode,usesacc,usesacchi,usesfpu);
|
||||
if po_assembler in current_procdef.procoptions then
|
||||
inlineexitcode.concat(Tai_marker.Create(asmblockend));
|
||||
exprasmList.concatlist(inlineexitcode);
|
||||
@ -1383,7 +1382,6 @@ implementation
|
||||
|
||||
{ restore }
|
||||
current_procdef:=oldprocdef;
|
||||
aktexitlabel:=oldexitlabel;
|
||||
inlining_procedure:=oldinlining_procedure;
|
||||
|
||||
{ reallocate the registers used for the current procedure's regvars, }
|
||||
@ -1409,7 +1407,12 @@ begin
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.88 2003-06-08 20:01:53 jonas
|
||||
Revision 1.89 2003-06-09 12:23:29 peter
|
||||
* init/final of procedure data splitted from genentrycode
|
||||
* use asmnode getposition to insert final at the correct position
|
||||
als for the implicit try...finally
|
||||
|
||||
Revision 1.88 2003/06/08 20:01:53 jonas
|
||||
* optimized assignments with on the right side a function that returns
|
||||
an ansi- or widestring
|
||||
|
||||
|
@ -719,7 +719,7 @@ implementation
|
||||
if assigned(left) then
|
||||
secondpass(left);
|
||||
|
||||
cg.a_jmp_always(exprasmlist,aktexitlabel);
|
||||
cg.a_jmp_always(exprasmlist,current_procinfo.aktexitlabel);
|
||||
end;
|
||||
|
||||
|
||||
@ -935,7 +935,7 @@ implementation
|
||||
oldendexceptlabel:=endexceptlabel;
|
||||
|
||||
{ save the old labels for control flow statements }
|
||||
oldaktexitlabel:=aktexitlabel;
|
||||
oldaktexitlabel:=current_procinfo.aktexitlabel;
|
||||
if assigned(aktbreaklabel) then
|
||||
begin
|
||||
oldaktcontinuelabel:=aktcontinuelabel;
|
||||
@ -962,7 +962,7 @@ implementation
|
||||
|
||||
{ try block }
|
||||
{ set control flow labels for the try block }
|
||||
aktexitlabel:=exittrylabel;
|
||||
current_procinfo.aktexitlabel:=exittrylabel;
|
||||
if assigned(oldaktbreaklabel) then
|
||||
begin
|
||||
aktcontinuelabel:=continuetrylabel;
|
||||
@ -983,7 +983,7 @@ implementation
|
||||
|
||||
{ set control flow labels for the except block }
|
||||
{ and the on statements }
|
||||
aktexitlabel:=exitexceptlabel;
|
||||
current_procinfo.aktexitlabel:=exitexceptlabel;
|
||||
if assigned(oldaktbreaklabel) then
|
||||
begin
|
||||
aktcontinuelabel:=continueexceptlabel;
|
||||
@ -1108,7 +1108,7 @@ implementation
|
||||
endexceptlabel:=oldendexceptlabel;
|
||||
|
||||
{ restore the control flow labels }
|
||||
aktexitlabel:=oldaktexitlabel;
|
||||
current_procinfo.aktexitlabel:=oldaktexitlabel;
|
||||
if assigned(oldaktbreaklabel) then
|
||||
begin
|
||||
aktcontinuelabel:=oldaktcontinuelabel;
|
||||
@ -1173,9 +1173,9 @@ implementation
|
||||
|
||||
if assigned(right) then
|
||||
begin
|
||||
oldaktexitlabel:=aktexitlabel;
|
||||
oldaktexitlabel:=current_procinfo.aktexitlabel;
|
||||
objectlibrary.getlabel(exitonlabel);
|
||||
aktexitlabel:=exitonlabel;
|
||||
current_procinfo.aktexitlabel:=exitonlabel;
|
||||
if assigned(aktbreaklabel) then
|
||||
begin
|
||||
oldaktcontinuelabel:=aktcontinuelabel;
|
||||
@ -1231,7 +1231,7 @@ implementation
|
||||
cg.a_jmp_always(exprasmlist,oldaktcontinuelabel);
|
||||
end;
|
||||
|
||||
aktexitlabel:=oldaktexitlabel;
|
||||
current_procinfo.aktexitlabel:=oldaktexitlabel;
|
||||
if assigned(oldaktbreaklabel) then
|
||||
begin
|
||||
aktcontinuelabel:=oldaktcontinuelabel;
|
||||
@ -1284,12 +1284,12 @@ implementation
|
||||
|
||||
{ the finally block must catch break, continue and exit }
|
||||
{ statements }
|
||||
oldaktexitlabel:=aktexitlabel;
|
||||
oldaktexitlabel:=current_procinfo.aktexitlabel;
|
||||
if implicitframe then
|
||||
exitfinallylabel:=finallylabel
|
||||
else
|
||||
objectlibrary.getlabel(exitfinallylabel);
|
||||
aktexitlabel:=exitfinallylabel;
|
||||
current_procinfo.aktexitlabel:=exitfinallylabel;
|
||||
if assigned(aktbreaklabel) then
|
||||
begin
|
||||
oldaktcontinuelabel:=aktcontinuelabel;
|
||||
@ -1401,7 +1401,7 @@ implementation
|
||||
end;
|
||||
cg.a_label(exprasmlist,endfinallylabel);
|
||||
|
||||
aktexitlabel:=oldaktexitlabel;
|
||||
current_procinfo.aktexitlabel:=oldaktexitlabel;
|
||||
if assigned(aktbreaklabel) then
|
||||
begin
|
||||
aktcontinuelabel:=oldaktcontinuelabel;
|
||||
@ -1427,7 +1427,12 @@ begin
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.69 2003-06-07 18:57:04 jonas
|
||||
Revision 1.70 2003-06-09 12:23:30 peter
|
||||
* init/final of procedure data splitted from genentrycode
|
||||
* use asmnode getposition to insert final at the correct position
|
||||
als for the implicit try...finally
|
||||
|
||||
Revision 1.69 2003/06/07 18:57:04 jonas
|
||||
+ added freeintparaloc
|
||||
* ppc get/freeintparaloc now check whether the parameter regs are
|
||||
properly allocated/deallocated (and get an extra list para)
|
||||
|
@ -63,12 +63,18 @@ interface
|
||||
para_offset:longint;alignment : longint;
|
||||
const locpara : tparalocation);
|
||||
|
||||
procedure genentrycode(list:TAAsmoutput;inlined:boolean);
|
||||
procedure gen_stackalloc_code(list:Taasmoutput;stackframe:longint);
|
||||
procedure genexitcode(list:Taasmoutput;inlined:boolean);
|
||||
procedure gen_load_return_value(list:TAAsmoutput; var uses_acc,uses_acchi,uses_fpu : boolean);
|
||||
procedure gen_initialize_code(list:TAAsmoutput;inlined:boolean);
|
||||
procedure gen_finalize_code(list : TAAsmoutput;inlined:boolean);
|
||||
|
||||
procedure gen_entry_code(list:TAAsmoutput;inlined:boolean);
|
||||
procedure gen_stackalloc_code(list:Taasmoutput;stackframe:longint);
|
||||
procedure gen_exit_code(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.
|
||||
@ -993,7 +999,7 @@ implementation
|
||||
|
||||
|
||||
{****************************************************************************
|
||||
Entry/Exit Code
|
||||
Init/Finalize Code
|
||||
****************************************************************************}
|
||||
|
||||
procedure copyvalueparas(p : tnamedindexitem;arg:pointer);
|
||||
@ -1147,6 +1153,7 @@ implementation
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{ generates the code for decrementing the reference count of parameters }
|
||||
procedure final_paras(p : tnamedindexitem;arg:pointer);
|
||||
var
|
||||
@ -1256,40 +1263,103 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
procedure load_return_value(list:TAAsmoutput; var uses_acc,uses_acchi,uses_fpu : boolean);
|
||||
procedure gen_load_return_value(list:TAAsmoutput; var uses_acc,uses_acchi,uses_fpu : boolean);
|
||||
var
|
||||
ressym: tvarsym;
|
||||
resloc: tlocation;
|
||||
ressym : tvarsym;
|
||||
resloc : tlocation;
|
||||
href : treference;
|
||||
hreg,r,r2 : tregister;
|
||||
begin
|
||||
if not is_void(current_procdef.rettype.def) then
|
||||
begin
|
||||
ressym := tvarsym(current_procdef.funcretsym);
|
||||
if ressym.reg.enum <> R_NO then
|
||||
begin
|
||||
if paramanager.ret_in_param(current_procdef.rettype.def,current_procdef.proccalloption) then
|
||||
location_reset(resloc,LOC_CREGISTER,OS_ADDR)
|
||||
else
|
||||
if ressym.vartype.def.deftype = floatdef then
|
||||
location_reset(resloc,LOC_CFPUREGISTER,def_cgsize(current_procdef.rettype.def))
|
||||
else
|
||||
location_reset(resloc,LOC_CREGISTER,def_cgsize(current_procdef.rettype.def));
|
||||
resloc.register := ressym.reg;
|
||||
end
|
||||
else
|
||||
begin
|
||||
location_reset(resloc,LOC_REFERENCE,def_cgsize(current_procdef.rettype.def));
|
||||
reference_reset_base(resloc.reference,current_procinfo.framepointer,tvarsym(current_procdef.funcretsym).adjusted_address);
|
||||
end;
|
||||
{ Here, we return the function result. In most architectures, the value is
|
||||
passed into the FUNCTION_RETURN_REG, 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 :
|
||||
{ Is the loading needed? }
|
||||
if is_void(current_procdef.rettype.def) or
|
||||
(
|
||||
(po_assembler in current_procdef.procoptions) and
|
||||
(not(assigned(current_procdef.funcretsym)) or
|
||||
(tvarsym(current_procdef.funcretsym).refcount=0))
|
||||
) then
|
||||
exit;
|
||||
|
||||
{ Constructors need to return self }
|
||||
if (current_procdef.proctypeoption=potype_constructor) then
|
||||
begin
|
||||
r.enum:=R_INTREGISTER;
|
||||
r.number:=NR_FUNCTION_RETURN_REG;
|
||||
cg.a_reg_alloc(list,r);
|
||||
{ return the self pointer }
|
||||
ressym:=tvarsym(current_procdef.parast.search('self'));
|
||||
if not assigned(ressym) then
|
||||
internalerror(200305058);
|
||||
reference_reset_base(href,current_procinfo.framepointer,tvarsym(ressym).adjusted_address);
|
||||
cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,r);
|
||||
cg.a_reg_dealloc(list,r);
|
||||
uses_acc:=true;
|
||||
exit;
|
||||
end;
|
||||
|
||||
ressym := tvarsym(current_procdef.funcretsym);
|
||||
if ressym.reg.enum <> R_NO then
|
||||
begin
|
||||
if paramanager.ret_in_param(current_procdef.rettype.def,current_procdef.proccalloption) then
|
||||
location_reset(resloc,LOC_CREGISTER,OS_ADDR)
|
||||
else
|
||||
if ressym.vartype.def.deftype = floatdef then
|
||||
location_reset(resloc,LOC_CFPUREGISTER,def_cgsize(current_procdef.rettype.def))
|
||||
else
|
||||
location_reset(resloc,LOC_CREGISTER,def_cgsize(current_procdef.rettype.def));
|
||||
resloc.register := ressym.reg;
|
||||
end
|
||||
else
|
||||
begin
|
||||
location_reset(resloc,LOC_REFERENCE,def_cgsize(current_procdef.rettype.def));
|
||||
reference_reset_base(resloc.reference,current_procinfo.framepointer,tvarsym(current_procdef.funcretsym).adjusted_address);
|
||||
end;
|
||||
{ Here, we return the function result. In most architectures, the value is
|
||||
passed into the FUNCTION_RETURN_REG, 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
|
||||
uses_acc:=true;
|
||||
{$ifndef cpu64bit}
|
||||
if resloc.size in [OS_64,OS_S64] then
|
||||
begin
|
||||
uses_acchi:=true;
|
||||
r.enum:=R_INTREGISTER;
|
||||
r.number:=NR_FUNCTION_RETURN64_LOW_REG;
|
||||
cg.a_reg_alloc(list,r);
|
||||
r2.enum:=R_INTREGISTER;
|
||||
r2.number:=NR_FUNCTION_RETURN64_HIGH_REG;
|
||||
cg.a_reg_alloc(list,r2);
|
||||
cg64.a_load64_loc_reg(list,resloc,joinreg64(r,r2){$ifdef newra},false{$endif});
|
||||
end
|
||||
else
|
||||
{$endif cpu64bit}
|
||||
begin
|
||||
hreg.enum:=R_INTREGISTER;
|
||||
hreg.number:=NR_FUNCTION_RETURN_REG;
|
||||
hreg:=rg.makeregsize(hreg,resloc.size);
|
||||
cg.a_load_loc_reg(list,resloc.size,resloc,hreg);
|
||||
end;
|
||||
end;
|
||||
floatdef :
|
||||
begin
|
||||
uses_fpu := true;
|
||||
{$ifdef cpufpemu}
|
||||
if cs_fp_emulation in aktmoduleswitches then
|
||||
r.enum := FUNCTION_RETURN_REG
|
||||
else
|
||||
{$endif cpufpemu}
|
||||
r.enum:=FPU_RESULT_REG;
|
||||
cg.a_loadfpu_loc_reg(list,resloc,r);
|
||||
end;
|
||||
else
|
||||
begin
|
||||
if not paramanager.ret_in_param(current_procdef.rettype.def,current_procdef.proccalloption) then
|
||||
begin
|
||||
uses_acc:=true;
|
||||
{$ifndef cpu64bit}
|
||||
{ Win32 can return records in EAX:EDX }
|
||||
if resloc.size in [OS_64,OS_S64] then
|
||||
begin
|
||||
uses_acchi:=true;
|
||||
@ -1305,56 +1375,147 @@ implementation
|
||||
{$endif cpu64bit}
|
||||
begin
|
||||
hreg.enum:=R_INTREGISTER;
|
||||
hreg.number:=NR_FUNCTION_RETURN_REG;
|
||||
hreg:=rg.makeregsize(hreg,resloc.size);
|
||||
hreg.number:=(RS_FUNCTION_RETURN_REG shl 8) or cgsize2subreg(resloc.size);
|
||||
cg.a_load_loc_reg(list,resloc.size,resloc,hreg);
|
||||
end;
|
||||
end;
|
||||
floatdef :
|
||||
begin
|
||||
uses_fpu := true;
|
||||
{$ifdef cpufpemu}
|
||||
if cs_fp_emulation in aktmoduleswitches then
|
||||
r.enum := FUNCTION_RETURN_REG
|
||||
else
|
||||
{$endif cpufpemu}
|
||||
r.enum:=FPU_RESULT_REG;
|
||||
cg.a_loadfpu_loc_reg(list,resloc,r);
|
||||
end;
|
||||
else
|
||||
begin
|
||||
if not paramanager.ret_in_param(current_procdef.rettype.def,current_procdef.proccalloption) then
|
||||
begin
|
||||
uses_acc:=true;
|
||||
{$ifndef cpu64bit}
|
||||
{ Win32 can return records in EAX:EDX }
|
||||
if resloc.size in [OS_64,OS_S64] then
|
||||
begin
|
||||
uses_acchi:=true;
|
||||
r.enum:=R_INTREGISTER;
|
||||
r.number:=NR_FUNCTION_RETURN64_LOW_REG;
|
||||
cg.a_reg_alloc(list,r);
|
||||
r2.enum:=R_INTREGISTER;
|
||||
r2.number:=NR_FUNCTION_RETURN64_HIGH_REG;
|
||||
cg.a_reg_alloc(list,r2);
|
||||
cg64.a_load64_loc_reg(list,resloc,joinreg64(r,r2){$ifdef newra},false{$endif});
|
||||
end
|
||||
else
|
||||
{$endif cpu64bit}
|
||||
begin
|
||||
hreg.enum:=R_INTREGISTER;
|
||||
hreg.number:=(RS_FUNCTION_RETURN_REG shl 8) or cgsize2subreg(resloc.size);
|
||||
cg.a_load_loc_reg(list,resloc.size,resloc,hreg);
|
||||
end;
|
||||
end
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure gen_initialize_code(list:TAAsmoutput;inlined:boolean);
|
||||
var
|
||||
href : treference;
|
||||
begin
|
||||
{ the actual profile code can clobber some registers,
|
||||
therefore if the context must be saved, do it before
|
||||
the actual call to the profile code
|
||||
}
|
||||
if (cs_profile in aktmoduleswitches) and
|
||||
not(po_assembler in current_procdef.procoptions) and
|
||||
not(inlined) then
|
||||
begin
|
||||
{ non-win32 can call mcout even in main }
|
||||
if not (target_info.system in [system_i386_win32,system_i386_wdosx]) then
|
||||
cg.g_profilecode(list)
|
||||
else
|
||||
{ wdosx, and win32 should not call mcount before monstartup has been called }
|
||||
if not (current_procdef.proctypeoption=potype_proginit) then
|
||||
cg.g_profilecode(list);
|
||||
end;
|
||||
|
||||
procedure genentrycode(list:TAAsmoutput;inlined:boolean);
|
||||
{ initialize return value }
|
||||
initretvalue(list);
|
||||
|
||||
{ initialize local data like ansistrings }
|
||||
case current_procdef.proctypeoption of
|
||||
potype_unitinit:
|
||||
begin
|
||||
{ this is also used for initialization of variables in a
|
||||
program which does not have a globalsymtable }
|
||||
if assigned(current_module.globalsymtable) then
|
||||
tsymtable(current_module.globalsymtable).foreach_static({$ifndef TP}@{$endif}initialize_data,list);
|
||||
tsymtable(current_module.localsymtable).foreach_static({$ifndef TP}@{$endif}initialize_data,list);
|
||||
end;
|
||||
{ units have seperate code for initilization and finalization }
|
||||
potype_unitfinalize: ;
|
||||
{ program init/final is generated in separate procedure }
|
||||
potype_proginit: ;
|
||||
else
|
||||
current_procdef.localst.foreach_static({$ifndef TP}@{$endif}initialize_data,list);
|
||||
end;
|
||||
|
||||
{ initialisizes temp. ansi/wide string data }
|
||||
inittempvariables(list);
|
||||
|
||||
{ generate copies of call by value parameters, must be done before
|
||||
the initialization because the refcounts are incremented using
|
||||
the local copies }
|
||||
if not(po_assembler in current_procdef.procoptions) then
|
||||
current_procdef.parast.foreach_static({$ifndef TP}@{$endif}copyvalueparas,list);
|
||||
|
||||
{ initialize ansi/widesstring para's }
|
||||
current_procdef.parast.foreach_static({$ifndef TP}@{$endif}init_paras,list);
|
||||
|
||||
if (not inlined) then
|
||||
begin
|
||||
{ call startup helpers from main program }
|
||||
if (current_procdef.proctypeoption=potype_proginit) then
|
||||
begin
|
||||
{ initialize profiling for win32 }
|
||||
if (target_info.system in [system_i386_win32,system_i386_wdosx]) and
|
||||
(cs_profile in aktmoduleswitches) then
|
||||
begin
|
||||
reference_reset_symbol(href,objectlibrary.newasmsymboldata('etext'),0);
|
||||
cg.a_paramaddr_ref(list,href,paramanager.getintparaloc(list,2));
|
||||
reference_reset_symbol(href,objectlibrary.newasmsymboldata('__image_base__'),0);
|
||||
cg.a_paramaddr_ref(list,href,paramanager.getintparaloc(list,1));
|
||||
cg.a_call_name(list,'_monstartup');
|
||||
paramanager.freeintparaloc(list,2);
|
||||
paramanager.freeintparaloc(list,1);
|
||||
end;
|
||||
|
||||
{ initialize units }
|
||||
cg.a_call_name(list,'FPC_INITIALIZEUNITS');
|
||||
end;
|
||||
|
||||
{$ifdef GDB}
|
||||
if (cs_debuginfo in aktmoduleswitches) then
|
||||
list.concat(Tai_force_line.Create);
|
||||
{$endif GDB}
|
||||
end;
|
||||
|
||||
load_regvars(list,nil);
|
||||
end;
|
||||
|
||||
|
||||
procedure gen_finalize_code(list : TAAsmoutput;inlined:boolean);
|
||||
begin
|
||||
cg.a_label(list,current_procinfo.aktexitlabel);
|
||||
|
||||
cleanup_regvars(list);
|
||||
|
||||
{ finalize temporary data }
|
||||
finalizetempvariables(list);
|
||||
|
||||
{ finalize local data like ansistrings}
|
||||
case current_procdef.proctypeoption of
|
||||
potype_unitfinalize:
|
||||
begin
|
||||
{ this is also used for initialization of variables in a
|
||||
program which does not have a globalsymtable }
|
||||
if assigned(current_module.globalsymtable) then
|
||||
tsymtable(current_module.globalsymtable).foreach_static({$ifndef TP}@{$endif}finalize_data,list);
|
||||
tsymtable(current_module.localsymtable).foreach_static({$ifndef TP}@{$endif}finalize_data,list);
|
||||
end;
|
||||
{ units/progs have separate code for initialization and finalization }
|
||||
potype_unitinit: ;
|
||||
{ program init/final is generated in separate procedure }
|
||||
potype_proginit: ;
|
||||
else
|
||||
current_procdef.localst.foreach_static({$ifndef TP}@{$endif}finalize_data,list);
|
||||
end;
|
||||
|
||||
{ finalize paras data }
|
||||
if assigned(current_procdef.parast) then
|
||||
current_procdef.parast.foreach_static({$ifndef TP}@{$endif}final_paras,list);
|
||||
|
||||
{ call __EXIT for main program }
|
||||
if (not DLLsource) and
|
||||
(not inlined) and
|
||||
(current_procdef.proctypeoption=potype_proginit) then
|
||||
cg.a_call_name(list,'FPC_DO_EXIT');
|
||||
|
||||
cleanup_regvars(list);
|
||||
end;
|
||||
|
||||
|
||||
{****************************************************************************
|
||||
Entry/Exit
|
||||
****************************************************************************}
|
||||
|
||||
procedure gen_entry_code(list:TAAsmoutput;inlined:boolean);
|
||||
var
|
||||
href : treference;
|
||||
hp : tparaitem;
|
||||
@ -1367,7 +1528,6 @@ implementation
|
||||
|
||||
if assigned(current_procdef.parast) then
|
||||
begin
|
||||
|
||||
if not (po_assembler in current_procdef.procoptions) then
|
||||
begin
|
||||
{ move register parameters which aren't regable into memory }
|
||||
@ -1423,7 +1583,6 @@ implementation
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{ for the save all registers we can simply use a pusha,popa which
|
||||
push edi,esi,ebp,esp(ignored),ebx,edx,ecx,eax }
|
||||
if (po_saveregisters in current_procdef.procoptions) then
|
||||
@ -1444,91 +1603,9 @@ implementation
|
||||
rsp.number:=NR_STACK_POINTER_REG;
|
||||
cg.a_load_reg_ref(list,OS_ADDR,OS_ADDR,rsp,current_procinfo.save_stackptr_ref);
|
||||
end;
|
||||
|
||||
{ the actual profile code can clobber some registers,
|
||||
therefore if the context must be saved, do it before
|
||||
the actual call to the profile code
|
||||
}
|
||||
if (cs_profile in aktmoduleswitches) and
|
||||
not(po_assembler in current_procdef.procoptions) and
|
||||
not(inlined) then
|
||||
begin
|
||||
{ non-win32 can call mcout even in main }
|
||||
if not (target_info.system in [system_i386_win32,system_i386_wdosx]) then
|
||||
cg.g_profilecode(list)
|
||||
else
|
||||
{ wdosx, and win32 should not call mcount before monstartup has been called }
|
||||
if not (current_procdef.proctypeoption=potype_proginit) then
|
||||
cg.g_profilecode(list);
|
||||
end;
|
||||
|
||||
{ initialize return value }
|
||||
initretvalue(list);
|
||||
|
||||
{ initialize local data like ansistrings }
|
||||
case current_procdef.proctypeoption of
|
||||
potype_unitinit:
|
||||
begin
|
||||
{ this is also used for initialization of variables in a
|
||||
program which does not have a globalsymtable }
|
||||
if assigned(current_module.globalsymtable) then
|
||||
tsymtable(current_module.globalsymtable).foreach_static({$ifndef TP}@{$endif}initialize_data,list);
|
||||
tsymtable(current_module.localsymtable).foreach_static({$ifndef TP}@{$endif}initialize_data,list);
|
||||
end;
|
||||
{ units have seperate code for initilization and finalization }
|
||||
potype_unitfinalize: ;
|
||||
{ program init/final is generated in separate procedure }
|
||||
potype_proginit: ;
|
||||
else
|
||||
current_procdef.localst.foreach_static({$ifndef TP}@{$endif}initialize_data,list);
|
||||
end;
|
||||
|
||||
{ initialisizes temp. ansi/wide string data }
|
||||
inittempvariables(list);
|
||||
|
||||
{ initialize ansi/widesstring para's }
|
||||
if assigned(current_procdef.parast) then
|
||||
begin
|
||||
current_procdef.parast.foreach_static({$ifndef TP}@{$endif}init_paras,list);
|
||||
end;
|
||||
|
||||
{ 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);
|
||||
|
||||
if (not inlined) then
|
||||
begin
|
||||
{ call startup helpers from main program }
|
||||
if (current_procdef.proctypeoption=potype_proginit) then
|
||||
begin
|
||||
{ initialize profiling for win32 }
|
||||
if (target_info.system in [system_i386_win32,system_i386_wdosx]) and
|
||||
(cs_profile in aktmoduleswitches) then
|
||||
begin
|
||||
reference_reset_symbol(href,objectlibrary.newasmsymboldata('etext'),0);
|
||||
cg.a_paramaddr_ref(list,href,paramanager.getintparaloc(list,2));
|
||||
reference_reset_symbol(href,objectlibrary.newasmsymboldata('__image_base__'),0);
|
||||
cg.a_paramaddr_ref(list,href,paramanager.getintparaloc(list,1));
|
||||
cg.a_call_name(list,'_monstartup');
|
||||
paramanager.freeintparaloc(list,2);
|
||||
paramanager.freeintparaloc(list,1);
|
||||
end;
|
||||
|
||||
{ initialize units }
|
||||
cg.a_call_name(list,'FPC_INITIALIZEUNITS');
|
||||
end;
|
||||
|
||||
{$ifdef GDB}
|
||||
if (cs_debuginfo in aktmoduleswitches) then
|
||||
list.concat(Tai_force_line.Create);
|
||||
{$endif GDB}
|
||||
end;
|
||||
|
||||
if inlined then
|
||||
load_regvars(list,nil);
|
||||
|
||||
end;
|
||||
|
||||
|
||||
procedure gen_stackalloc_code(list:Taasmoutput;stackframe:longint);
|
||||
|
||||
var hs:string;
|
||||
@ -1600,7 +1677,8 @@ implementation
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure genexitcode(list : TAAsmoutput;inlined:boolean);
|
||||
|
||||
procedure gen_exit_code(list : TAAsmoutput;inlined:boolean);
|
||||
|
||||
var
|
||||
{$ifdef GDB}
|
||||
@ -1608,82 +1686,18 @@ implementation
|
||||
mangled_length : longint;
|
||||
p : pchar;
|
||||
{$endif GDB}
|
||||
okexitlabel : tasmlabel;
|
||||
href : treference;
|
||||
srsym : tsym;
|
||||
usesacc,
|
||||
usesacchi,
|
||||
usesfpu : boolean;
|
||||
rsp,r : Tregister;
|
||||
rsp : Tregister;
|
||||
retsize : longint;
|
||||
begin
|
||||
if aktexitlabel.is_used then
|
||||
cg.a_label(list,aktexitlabel);
|
||||
|
||||
cleanup_regvars(list);
|
||||
|
||||
{ finalize temporary data }
|
||||
finalizetempvariables(list);
|
||||
|
||||
{ finalize local data like ansistrings}
|
||||
case current_procdef.proctypeoption of
|
||||
potype_unitfinalize:
|
||||
begin
|
||||
{ this is also used for initialization of variables in a
|
||||
program which does not have a globalsymtable }
|
||||
if assigned(current_module.globalsymtable) then
|
||||
tsymtable(current_module.globalsymtable).foreach_static({$ifndef TP}@{$endif}finalize_data,list);
|
||||
tsymtable(current_module.localsymtable).foreach_static({$ifndef TP}@{$endif}finalize_data,list);
|
||||
end;
|
||||
{ units/progs have separate code for initialization and finalization }
|
||||
potype_unitinit: ;
|
||||
{ program init/final is generated in separate procedure }
|
||||
potype_proginit: ;
|
||||
else
|
||||
current_procdef.localst.foreach_static({$ifndef TP}@{$endif}finalize_data,list);
|
||||
end;
|
||||
|
||||
{ finalize paras data }
|
||||
if assigned(current_procdef.parast) then
|
||||
current_procdef.parast.foreach_static({$ifndef TP}@{$endif}final_paras,list);
|
||||
|
||||
{ call __EXIT for main program }
|
||||
if (not DLLsource) and
|
||||
(not inlined) and
|
||||
(current_procdef.proctypeoption=potype_proginit) then
|
||||
begin
|
||||
cg.a_call_name(list,'FPC_DO_EXIT');
|
||||
end;
|
||||
|
||||
{ handle return value, this is not done for assembler routines when
|
||||
they didn't reference the result variable }
|
||||
usesacc:=false;
|
||||
usesfpu:=false;
|
||||
usesacchi:=false;
|
||||
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
|
||||
begin
|
||||
objectlibrary.getlabel(okexitlabel);
|
||||
cg.a_jmp_always(list,okexitlabel);
|
||||
{ Success exit }
|
||||
cg.a_label(list,okexitlabel);
|
||||
r.enum:=R_INTREGISTER;
|
||||
r.number:=NR_FUNCTION_RETURN_REG;
|
||||
cg.a_reg_alloc(list,r);
|
||||
{ return the self pointer }
|
||||
srsym:=tvarsym(current_procdef.parast.search('self'));
|
||||
if not assigned(srsym) then
|
||||
internalerror(200305058);
|
||||
reference_reset_base(href,current_procinfo.framepointer,tvarsym(srsym).adjusted_address);
|
||||
cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,r);
|
||||
cg.a_reg_dealloc(list,r);
|
||||
usesacc:=true;
|
||||
end
|
||||
else
|
||||
load_return_value(list,usesacc,usesacchi,usesfpu)
|
||||
end;
|
||||
gen_load_return_value(list,usesacc,usesacchi,usesfpu);
|
||||
|
||||
{$ifdef GDB}
|
||||
if ((cs_debuginfo in aktmoduleswitches) and not inlined) then
|
||||
@ -1812,9 +1826,6 @@ implementation
|
||||
freemem(p,2*mangled_length+50);
|
||||
end;
|
||||
{$endif GDB}
|
||||
|
||||
if inlined then
|
||||
cleanup_regvars(list);
|
||||
end;
|
||||
|
||||
|
||||
@ -1822,6 +1833,7 @@ implementation
|
||||
Inlining
|
||||
****************************************************************************}
|
||||
|
||||
(*
|
||||
procedure load_inlined_return_value(list:TAAsmoutput);
|
||||
var
|
||||
ressym: tvarsym;
|
||||
@ -1959,11 +1971,17 @@ implementation
|
||||
|
||||
cleanup_regvars(list);
|
||||
end;
|
||||
*)
|
||||
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.123 2003-06-07 18:57:04 jonas
|
||||
Revision 1.124 2003-06-09 12:23:30 peter
|
||||
* init/final of procedure data splitted from genentrycode
|
||||
* use asmnode getposition to insert final at the correct position
|
||||
als for the implicit try...finally
|
||||
|
||||
Revision 1.123 2003/06/07 18:57:04 jonas
|
||||
+ added freeintparaloc
|
||||
* ppc get/freeintparaloc now check whether the parameter regs are
|
||||
properly allocated/deallocated (and get an extra list para)
|
||||
|
@ -279,13 +279,13 @@ implementation
|
||||
|
||||
{ process register variable stuff (JM) }
|
||||
assign_regvars(p);
|
||||
load_regvars(current_procinfo.aktentrycode,p);
|
||||
// load_regvars(current_procinfo.aktentrycode,p);
|
||||
|
||||
{ for the i386 it must be done in genexitcode because it has }
|
||||
{ to add 'fstp' instructions when using fpu regvars and those }
|
||||
{ must come after the "exitlabel" (JM) }
|
||||
{$ifndef i386}
|
||||
cleanup_regvars(current_procinfo.aktexitcode);
|
||||
// cleanup_regvars(current_procinfo.aktexitcode);
|
||||
{$endif i386}
|
||||
{$ifdef newra}
|
||||
if current_procinfo.framepointer.number=NR_EBP then
|
||||
@ -309,7 +309,12 @@ implementation
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.54 2003-06-03 13:01:59 daniel
|
||||
Revision 1.55 2003-06-09 12:23:30 peter
|
||||
* init/final of procedure data splitted from genentrycode
|
||||
* use asmnode getposition to insert final at the correct position
|
||||
als for the implicit try...finally
|
||||
|
||||
Revision 1.54 2003/06/03 13:01:59 daniel
|
||||
* Register allocator finished
|
||||
|
||||
Revision 1.53 2003/05/26 21:17:17 peter
|
||||
|
@ -753,7 +753,6 @@ implementation
|
||||
procedure gen_implicit_initfinal(list:taasmoutput;flag:word;st:tsymtable);
|
||||
var
|
||||
pd : tprocdef;
|
||||
oldexitlabel : tasmlabel;
|
||||
begin
|
||||
{ update module flags }
|
||||
current_module.flags:=current_module.flags or flag;
|
||||
@ -772,18 +771,14 @@ implementation
|
||||
else
|
||||
internalerror(200304253);
|
||||
end;
|
||||
{ save labels }
|
||||
oldexitlabel:=aktexitlabel;
|
||||
{ generate a dummy function }
|
||||
objectlibrary.getlabel(aktexitlabel);
|
||||
include(current_procinfo.flags,pi_do_call);
|
||||
gen_stackalloc_code(list,0);
|
||||
genentrycode(list,false);
|
||||
genexitcode(list,false);
|
||||
gen_entry_code(list,false);
|
||||
gen_initialize_code(list,false);
|
||||
gen_finalize_code(list,false);
|
||||
gen_exit_code(list,false);
|
||||
list.convert_registers;
|
||||
release_main_proc(pd);
|
||||
{ restore }
|
||||
aktexitlabel:=oldexitlabel;
|
||||
end;
|
||||
|
||||
|
||||
@ -1461,7 +1456,12 @@ So, all parameters are passerd into registers in sparc architecture.}
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.112 2003-06-07 20:26:32 peter
|
||||
Revision 1.113 2003-06-09 12:23:30 peter
|
||||
* init/final of procedure data splitted from genentrycode
|
||||
* use asmnode getposition to insert final at the correct position
|
||||
als for the implicit try...finally
|
||||
|
||||
Revision 1.112 2003/06/07 20:26:32 peter
|
||||
* re-resolving added instead of reloading from ppu
|
||||
* tderef object added to store deref info for resolving
|
||||
|
||||
|
@ -35,6 +35,9 @@ interface
|
||||
tcgprocinfo=class(tprocinfo)
|
||||
{ code for the subroutine as tree }
|
||||
code : tnode;
|
||||
{ positions in the tree for init/final }
|
||||
initasmnode,
|
||||
finalasmnode : tnode;
|
||||
{ list to store the procinfo's of the nested procedures }
|
||||
nestedprocs : tlinkedlist;
|
||||
constructor create(aparent:tprocinfo);override;
|
||||
@ -254,6 +257,10 @@ implementation
|
||||
begin
|
||||
result:=internalstatements(newstatement,true);
|
||||
|
||||
{ temp/para/locals initialize code will be inserted here }
|
||||
tcgprocinfo(current_procinfo).initasmnode:=casmnode.create_get_position;
|
||||
addstatement(newstatement,tcgprocinfo(current_procinfo).initasmnode);
|
||||
|
||||
if assigned(current_procdef._class) then
|
||||
begin
|
||||
{ a constructor needs a help procedure }
|
||||
@ -347,7 +354,9 @@ implementation
|
||||
|
||||
function generate_finalize_block:tnode;
|
||||
begin
|
||||
result:=cnothingnode.create;
|
||||
{ temp/para/locals finalize code will be inserted here }
|
||||
tcgprocinfo(current_procinfo).finalasmnode:=casmnode.create_get_position;
|
||||
result:=tcgprocinfo(current_procinfo).finalasmnode;
|
||||
end;
|
||||
|
||||
|
||||
@ -557,9 +566,9 @@ implementation
|
||||
var
|
||||
oldprocdef : tprocdef;
|
||||
oldprocinfo : tprocinfo;
|
||||
oldexitlabel : tasmlabel;
|
||||
oldaktmaxfpuregisters : longint;
|
||||
oldfilepos : tfileposinfo;
|
||||
templist,
|
||||
stackalloccode : Taasmoutput;
|
||||
|
||||
begin
|
||||
@ -577,12 +586,10 @@ implementation
|
||||
current_procinfo:=self;
|
||||
current_procdef:=procdef;
|
||||
|
||||
{ save old labels }
|
||||
oldexitlabel:=aktexitlabel;
|
||||
{ get new labels }
|
||||
objectlibrary.getlabel(aktexitlabel);
|
||||
aktbreaklabel:=nil;
|
||||
aktcontinuelabel:=nil;
|
||||
templist:=Taasmoutput.create;
|
||||
|
||||
{ add parast/localst to symtablestack }
|
||||
add_to_symtablestack;
|
||||
@ -597,25 +604,34 @@ implementation
|
||||
{$endif}
|
||||
|
||||
{ set the start offset to the start of the temp area in the stack }
|
||||
tg.setfirsttemp(current_procinfo.firsttemp_offset);
|
||||
tg.setfirsttemp(firsttemp_offset);
|
||||
|
||||
generatecode(code);
|
||||
|
||||
{ first generate entry code with the correct position and switches }
|
||||
aktfilepos:=current_procinfo.entrypos;
|
||||
aktlocalswitches:=current_procinfo.entryswitches;
|
||||
genentrycode(current_procinfo.aktentrycode,false);
|
||||
{ first generate entry and initialize code with the correct
|
||||
position and switches }
|
||||
aktfilepos:=entrypos;
|
||||
aktlocalswitches:=entryswitches;
|
||||
gen_initialize_code(templist,false);
|
||||
aktproccode.insertlistafter(tasmnode(initasmnode).currenttai,templist);
|
||||
gen_entry_code(templist,false);
|
||||
aktproccode.insertlist(templist);
|
||||
|
||||
{ now generate exit code with the correct position and switches }
|
||||
aktfilepos:=current_procinfo.exitpos;
|
||||
aktlocalswitches:=current_procinfo.exitswitches;
|
||||
genexitcode(current_procinfo.aktexitcode,false);
|
||||
{ now generate finalize and exit code with the correct position
|
||||
and switches }
|
||||
aktfilepos:=exitpos;
|
||||
aktlocalswitches:=exitswitches;
|
||||
gen_finalize_code(templist,false);
|
||||
{ the finalcode must be added if the was no position available,
|
||||
using insertlistafter will result in an insert at the start
|
||||
when currentai=nil }
|
||||
if assigned(tasmnode(finalasmnode).currenttai) then
|
||||
aktproccode.insertlistafter(tasmnode(finalasmnode).currenttai,templist)
|
||||
else
|
||||
aktproccode.concatlist(templist);
|
||||
gen_exit_code(templist,false);
|
||||
aktproccode.concatlist(templist);
|
||||
|
||||
{ now all the registers used are known }
|
||||
{ current_procdef.usedintregisters:=rg.usedintinproc;
|
||||
current_procdef.usedotherregisters:=rg.usedinproc;}
|
||||
current_procinfo.aktproccode.insertlist(current_procinfo.aktentrycode);
|
||||
current_procinfo.aktproccode.concatlist(current_procinfo.aktexitcode);
|
||||
{$ifdef newra}
|
||||
{ rg.writegraph;}
|
||||
{$endif}
|
||||
@ -627,16 +643,16 @@ implementation
|
||||
rg.prepare_colouring;
|
||||
rg.colour_registers;
|
||||
rg.epilogue_colouring;
|
||||
until (rg.spillednodes='') or not rg.spill_registers(current_procinfo.aktproccode,rg.spillednodes);
|
||||
current_procinfo.aktproccode.translate_registers(rg.colour);
|
||||
current_procinfo.aktproccode.convert_registers;
|
||||
until (rg.spillednodes='') or not rg.spill_registers(aktproccode,rg.spillednodes);
|
||||
aktproccode.translate_registers(rg.colour);
|
||||
aktproccode.convert_registers;
|
||||
{$else newra}
|
||||
current_procinfo.aktproccode.convert_registers;
|
||||
aktproccode.convert_registers;
|
||||
{$ifndef NoOpt}
|
||||
if (cs_optimize in aktglobalswitches) and
|
||||
{ do not optimize pure assembler procedures }
|
||||
not(pi_is_assembler in current_procinfo.flags) then
|
||||
optimize(current_procinfo.aktproccode);
|
||||
optimize(aktproccode);
|
||||
{$endif NoOpt}
|
||||
{$endif newra}
|
||||
end;
|
||||
@ -644,31 +660,31 @@ implementation
|
||||
stackalloccode:=Taasmoutput.create;
|
||||
gen_stackalloc_code(stackalloccode,0);
|
||||
stackalloccode.convert_registers;
|
||||
current_procinfo.aktproccode.insertlist(stackalloccode);
|
||||
aktproccode.insertlist(stackalloccode);
|
||||
stackalloccode.destroy;
|
||||
|
||||
{ now all the registers used are known }
|
||||
{ Remove all imaginary registers from the used list.}
|
||||
{$ifdef newra}
|
||||
current_procdef.usedintregisters:=rg.usedintinproc*ALL_INTREGISTERS-rg.savedbyproc;
|
||||
procdef.usedintregisters:=rg.usedintinproc*ALL_INTREGISTERS-rg.savedbyproc;
|
||||
{$else}
|
||||
current_procdef.usedintregisters:=rg.usedintinproc;
|
||||
procdef.usedintregisters:=rg.usedintinproc;
|
||||
{$endif}
|
||||
current_procdef.usedotherregisters:=rg.usedinproc;
|
||||
procdef.usedotherregisters:=rg.usedinproc;
|
||||
|
||||
{ save local data (casetable) also in the same file }
|
||||
if assigned(current_procinfo.aktlocaldata) and
|
||||
(not current_procinfo.aktlocaldata.empty) then
|
||||
if assigned(aktlocaldata) and
|
||||
(not aktlocaldata.empty) then
|
||||
begin
|
||||
current_procinfo.aktproccode.concat(Tai_section.Create(sec_data));
|
||||
current_procinfo.aktproccode.concatlist(current_procinfo.aktlocaldata);
|
||||
current_procinfo.aktproccode.concat(Tai_section.Create(sec_code));
|
||||
aktproccode.concat(Tai_section.Create(sec_data));
|
||||
aktproccode.concatlist(aktlocaldata);
|
||||
aktproccode.concat(Tai_section.Create(sec_code));
|
||||
end;
|
||||
|
||||
{ add the procedure to the codesegment }
|
||||
if (cs_create_smart in aktmoduleswitches) then
|
||||
codesegment.concat(Tai_cut.Create);
|
||||
codesegment.concatlist(current_procinfo.aktproccode);
|
||||
codesegment.concat(Tai_cut.Create);
|
||||
codesegment.concatlist(aktproccode);
|
||||
|
||||
{ all registers can be used again }
|
||||
rg.resetusableregisters;
|
||||
@ -678,10 +694,8 @@ implementation
|
||||
{ restore symtablestack }
|
||||
remove_from_symtablestack;
|
||||
|
||||
{ restore labels }
|
||||
aktexitlabel:=oldexitlabel;
|
||||
|
||||
{ restore }
|
||||
templist.free;
|
||||
aktmaxfpuregisters:=oldaktmaxfpuregisters;
|
||||
aktfilepos:=oldfilepos;
|
||||
current_procdef:=oldprocdef;
|
||||
@ -770,7 +784,6 @@ implementation
|
||||
procedure tcgprocinfo.parse_body;
|
||||
var
|
||||
oldprocdef : tprocdef;
|
||||
stackalloccode : Taasmoutput;
|
||||
oldprocinfo : tprocinfo;
|
||||
begin
|
||||
oldprocdef:=current_procdef;
|
||||
@ -922,9 +935,6 @@ implementation
|
||||
|
||||
|
||||
procedure check_init_paras(p:tnamedindexitem;arg:pointer);
|
||||
var
|
||||
vs : tvarsym;
|
||||
pd : tprocdef;
|
||||
begin
|
||||
if tsym(p).typ<>varsym then
|
||||
exit;
|
||||
@ -1259,7 +1269,12 @@ begin
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.124 2003-06-07 19:37:43 jonas
|
||||
Revision 1.125 2003-06-09 12:23:30 peter
|
||||
* init/final of procedure data splitted from genentrycode
|
||||
* use asmnode getposition to insert final at the correct position
|
||||
als for the implicit try...finally
|
||||
|
||||
Revision 1.124 2003/06/07 19:37:43 jonas
|
||||
* pi_do_call must always be set for the main program, since it always
|
||||
ends with a call to FPC_DO_EXIT
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user