{ $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,cgbase, aasmbase,aasmtai,aasmcpu, symconst,symbase,symdef,symsym,symtype,symtable {$ifndef cpu64bit} ,cg64f32 {$endif cpu64bit} ; 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); procedure location_force_mmregscalar(list:TAAsmoutput;var l: tlocation;maybeconst:boolean); function maybe_pushfpu(list:taasmoutput;needed : byte;var l:tlocation) : boolean; procedure gen_proc_symbol(list:Taasmoutput); procedure gen_proc_symbol_end(list:Taasmoutput); procedure gen_stackalloc_code(list:Taasmoutput); procedure gen_stackfree_code(list:Taasmoutput;usesacc,usesacchi:boolean); procedure gen_save_used_regs(list:TAAsmoutput); procedure gen_restore_used_regs(list:TAAsmoutput;const funcretparaloc:tparalocation); procedure gen_initialize_code(list:TAAsmoutput;inlined:boolean); procedure gen_finalize_code(list:TAAsmoutput;inlined:boolean); procedure gen_entry_code(list:TAAsmoutput); procedure gen_exit_code(list:TAAsmoutput); procedure gen_load_para_value(list:TAAsmoutput); procedure gen_load_return_value(list:TAAsmoutput; var uses_acc,uses_acchi,uses_fpu : 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. } const EXCEPT_BUF_SIZE = 12; type texceptiontemps=record jmpbuf, envbuf, reasonbuf : treference; end; procedure get_exception_temps(list:taasmoutput;var t:texceptiontemps); procedure unget_exception_temps(list:taasmoutput;const t:texceptiontemps); procedure new_exception(list:TAAsmoutput;const t:texceptiontemps;a:aword;exceptlabel:tasmlabel); procedure free_exception(list:TAAsmoutput;const t:texceptiontemps;a:aword;endexceptlabel:tasmlabel;onlyfree:boolean); procedure insertconstdata(sym : ttypedconstsym); procedure insertbssdata(sym : tvarsym); procedure gen_alloc_localst(list:TAAsmoutput;st:tlocalsymtable); procedure gen_free_localst(list:TAAsmoutput;st:tlocalsymtable); procedure gen_alloc_parast(list:TAAsmoutput;st:tparasymtable); procedure gen_alloc_inline_parast(list:TAAsmoutput;st:tparasymtable); procedure gen_free_parast(list:TAAsmoutput;st:tparasymtable); { rtti and init/final } procedure generate_rtti(p:Ttypesym); procedure generate_inittable(p:tsym); implementation uses {$ifdef Delphi} Sysutils, {$else} strings, {$endif} cutils,cclasses, globals,systems,verbose, ppu,defutil, procinfo,paramgr,fmodule, regvars, {$ifdef GDB} gdb, {$endif GDB} pass_1,pass_2, ncon,nld,nutils, tgobj,cgutils,cgobj; {***************************************************************************** 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.registersint