{ $Id$ Copyright (c) 1998-2002 by Florian Klaempfl Helper routines for all code generators 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 ncgutil; {$i fpcdefs.inc} interface uses node,cpuinfo, globtype, cpubase, aasmbase,aasmtai,aasmcpu, cginfo,symbase,symdef,symtype, {$ifndef cpu64bit} cg64f32, {$endif cpu64bit} rgobj; type tloadregvars = (lr_dont_load_regvars, lr_load_regvars); procedure firstcomplex(p : tbinarynode); procedure maketojumpbool(list:TAAsmoutput; p : tnode; loadregvars: tloadregvars); procedure remove_non_regvars_from_loc(const t: tlocation; var regs:Tsuperregisterset); procedure location_force_reg(list: TAAsmoutput;var l:tlocation;dst_size:TCGSize;maybeconst:boolean); procedure location_force_fpureg(list: TAAsmoutput;var l: tlocation;maybeconst:boolean); procedure location_force_mem(list: TAAsmoutput;var l:tlocation); function maybe_pushfpu(list:taasmoutput;needed : byte;var l:tlocation) : boolean; procedure push_value_para(list:taasmoutput;p:tnode;calloption:tproccalloption; para_offset:longint;alignment : longint; const locpara : tparalocation); 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_proc_symbol(list:Taasmoutput); procedure gen_stackalloc_code(list:Taasmoutput); procedure gen_save_used_regs(list : TAAsmoutput); procedure gen_restore_used_regs(list : TAAsmoutput;usesacc,usesacchi,usesfpu:boolean); procedure gen_entry_code(list:TAAsmoutput;inlined:boolean); procedure gen_exit_code(list:TAAsmoutput;inlined,usesacc,usesacchi:boolean); (* procedure geninlineentrycode(list : TAAsmoutput;stackframe:longint); procedure geninlineexitcode(list : TAAsmoutput;inlined:boolean); *) {# Allocate the buffers for exception management and setjmp environment. Return a pointer to these buffers, send them to the utility routine so they are registered, and then call setjmp. Then compare the result of setjmp with 0, and if not equal to zero, then jump to exceptlabel. Also store the result of setjmp to a temporary space by calling g_save_exception_reason It is to note that this routine may be called *after* the stackframe of a routine has been called, therefore on machines where the stack cannot be modified, all temps should be allocated on the heap instead of the stack. } procedure new_exception(list : taasmoutput;const jmpbuf,envbuf, href : treference; a : aword; exceptlabel : tasmlabel); procedure free_exception(list : taasmoutput;const jmpbuf, envbuf, href : treference; a : aword ; endexceptlabel : tasmlabel; onlyfree : boolean); implementation uses {$ifdef Delphi} Sysutils, {$else} strings, {$endif} cutils,cclasses, globals,systems,verbose, symconst,symsym,symtable,defutil, paramgr,fmodule, cgbase,regvars, {$ifdef GDB} gdb, {$endif GDB} ncon, tgobj,cgobj; const { Please leave this here, this module should NOT use exprasmlist, the lists are always passed as arguments. Declaring it as string here results in an error when compiling (PFV) } exprasmlist = 'error'; {***************************************************************************** Misc Helpers *****************************************************************************} { DO NOT RELY on the fact that the tnode is not yet swaped because of inlining code PM } procedure firstcomplex(p : tbinarynode); var hp : tnode; begin { always calculate boolean AND and OR from left to right } if (p.nodetype in [orn,andn]) and is_boolean(p.left.resulttype.def) then begin if nf_swaped in p.flags then internalerror(234234); end else if ( (p.location.loc=LOC_FPUREGISTER) and (p.right.registersfpu > p.left.registersfpu) ) or ( ( ( ((p.left.registersfpu = 0) and (p.right.registersfpu = 0)) or (p.location.loc<>LOC_FPUREGISTER) ) and (p.left.registers32