diff --git a/compiler/aggas.pas b/compiler/aggas.pas index 764b810d3f..0a3114ec6a 100644 --- a/compiler/aggas.pas +++ b/compiler/aggas.pas @@ -376,7 +376,10 @@ implementation { they don't work and gcc doesn't use them either... } system_powerpc_darwin, system_powerpc64_darwin: - AsmWriteln('__TEXT,__symbol_stub1,symbol_stubs,pure_instructions,16'); + if (cs_create_pic in current_settings.moduleswitches) then + AsmWriteln('__TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32') + else + AsmWriteln('__TEXT,__symbol_stub1,symbol_stubs,pure_instructions,16'); system_i386_darwin: AsmWriteln('__IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5'); { darwin/x86-64 uses RIP-based GOT addressing } diff --git a/compiler/cgobj.pas b/compiler/cgobj.pas index 20f88d1974..62e130e740 100644 --- a/compiler/cgobj.pas +++ b/compiler/cgobj.pas @@ -70,7 +70,7 @@ unit cgobj; {# Clean up the register allocators needed for the codegenerator.} procedure done_register_allocators;virtual; {# Set whether live_start or live_end should be updated when allocating registers, needed when e.g. generating initcode after the rest of the code. } - procedure set_regalloc_extend_backwards(b: boolean); + procedure set_regalloc_live_range_direction(dir: TRADirection); {$ifdef flowgraph} procedure init_flowgraph; @@ -479,6 +479,9 @@ unit cgobj; The default implementation issues a jump instruction to the external name. } procedure g_external_wrapper(list : TAsmList; procdef: tprocdef; const externalname: string); virtual; + + { initialize the pic/got register } + procedure g_maybe_got_init(list: TAsmList); virtual; protected procedure get_subsetref_load_info(const sref: tsubsetreference; out loadsize: tcgsize; out extra_load: boolean); procedure a_load_subsetref_regs_noindex(list: TAsmList; subsetsize: tcgsize; loadbitsize: byte; const sref: tsubsetreference; valuereg, extra_value_reg: tregister); virtual; @@ -769,14 +772,14 @@ implementation end; - procedure tcg.set_regalloc_extend_backwards(b: boolean); + procedure tcg.set_regalloc_live_range_direction(dir: TRADirection); var rt : tregistertype; begin for rt:=low(rg) to high(rg) do begin if assigned(rg[rt]) then - rg[rt].extend_live_range_backwards := b; + rg[rt].live_range_direction:=dir; end; end; @@ -3733,7 +3736,7 @@ implementation l:=current_asmdata.getasmsymbol('L'+symname+'$non_lazy_ptr'); if not(assigned(l)) then begin - l:=current_asmdata.DefineAsmSymbol('L'+symname+'$non_lazy_ptr',AB_COMMON,AT_DATA); + l:=current_asmdata.DefineAsmSymbol('L'+symname+'$non_lazy_ptr',AB_LOCAL,AT_DATA); current_asmdata.asmlists[al_picdata].concat(tai_symbol.create(l,0)); current_asmdata.asmlists[al_picdata].concat(tai_const.create_indirect_sym(current_asmdata.RefAsmSymbol(symname))); {$ifdef cpu64bit} @@ -3752,6 +3755,10 @@ implementation end; + procedure tcg.g_maybe_got_init(list: TAsmList); + begin + end; + {***************************************************************************** TCG64 *****************************************************************************} diff --git a/compiler/globtype.pas b/compiler/globtype.pas index 74d133e38c..bbde2b89f5 100644 --- a/compiler/globtype.pas +++ b/compiler/globtype.pas @@ -345,6 +345,10 @@ interface s64comp,s64currency,s128real ); + type + { register allocator live range extension direction } + TRADirection = (rad_forward, rad_backwards, rad_backwards_reinit); + type TIDString = string[maxidlen]; diff --git a/compiler/i386/cgcpu.pas b/compiler/i386/cgcpu.pas index ee76aaa520..46b8035c3d 100644 --- a/compiler/i386/cgcpu.pas +++ b/compiler/i386/cgcpu.pas @@ -52,6 +52,7 @@ unit cgcpu; procedure g_exception_reason_save_const(list : TAsmList; const href : treference; a: aint);override; procedure g_exception_reason_load(list : TAsmList; const href : treference);override; procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override; + procedure g_maybe_got_init(list: TAsmList); override; end; tcg64f386 = class(tcg64f32) @@ -485,6 +486,23 @@ unit cgcpu; end; + procedure g_maybe_got_init(list: TAsmList); + begin + { allocate PIC register } + if (cs_create_pic in current_settings.moduleswitches) and + (tf_pic_uses_got in target_info.flags) and + (pi_needs_got in current_procinfo.flags) and + not(po_kylixlocal in current_procinfo.procdef.procoptions) then + begin + current_module.requires_ebx_pic_helper:=true; + cg.a_call_name_static(list,'fpc_geteipasebx'); + list.concat(taicpu.op_sym_ofs_reg(A_ADD,S_L,current_asmdata.RefAsmSymbol('_GLOBAL_OFFSET_TABLE_'),0,NR_PIC_OFFSET_REG)); + list.concat(tai_regalloc.alloc(NR_PIC_OFFSET_REG,nil)); + { ecx could be used in leave procedures } + current_procinfo.got:=NR_EBX; + end; + end; + procedure tcg386.g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint); { diff --git a/compiler/ncgutil.pas b/compiler/ncgutil.pas index 0f626b0cb0..396dc6c925 100644 --- a/compiler/ncgutil.pas +++ b/compiler/ncgutil.pas @@ -150,7 +150,6 @@ interface function getprocalign : shortint; procedure gen_pic_helpers(list : TAsmList); - procedure gen_got_load(list : TAsmList); implementation @@ -2142,27 +2141,6 @@ implementation end; - procedure gen_got_load(list : TAsmList); - begin - { if loading got is necessary for more cpus, it can be moved - to the cg } -{$ifdef i386} - { allocate PIC register } - if (cs_create_pic in current_settings.moduleswitches) and - (tf_pic_uses_got in target_info.flags) and - (pi_needs_got in current_procinfo.flags) and - not(po_kylixlocal in current_procinfo.procdef.procoptions) then - begin - current_module.requires_ebx_pic_helper:=true; - cg.a_call_name_static(list,'fpc_geteipasebx'); - list.concat(taicpu.op_sym_ofs_reg(A_ADD,S_L,current_asmdata.RefAsmSymbol('_GLOBAL_OFFSET_TABLE_'),0,NR_PIC_OFFSET_REG)); - list.concat(tai_regalloc.alloc(NR_PIC_OFFSET_REG,nil)); - { ecx could be used in leave procedures } - current_procinfo.got:=NR_EBX; - end; -{$endif i386} - end; - {**************************************************************************** External handling ****************************************************************************} @@ -2786,7 +2764,7 @@ implementation href : treference; {$endif i386} begin - { if other cpus require such helpers as well, it can be solved more cleaner } + { if other cpus require such helpers as well, it can be solved more cleanly } {$ifdef i386} if current_module.requires_ebx_pic_helper then begin diff --git a/compiler/powerpc/cgcpu.pas b/compiler/powerpc/cgcpu.pas index 4d30b7c078..acb1afbbf4 100644 --- a/compiler/powerpc/cgcpu.pas +++ b/compiler/powerpc/cgcpu.pas @@ -889,9 +889,7 @@ const var regcounter,firstregfpu,firstregint: TSuperRegister; href : treference; - usesfpr,usesgpr,gotgot : boolean; -{ cond : tasmcond; - instr : taicpu; } + usesfpr,usesgpr : boolean; begin { CR and LR only have to be saved in case they are modified by the current } @@ -905,8 +903,7 @@ const if not(po_assembler in current_procinfo.procdef.procoptions) then begin { save link register? } - if (pi_do_call in current_procinfo.flags) or - ([cs_lineinfo,cs_debuginfo,cs_profile] * current_settings.moduleswitches <> []) then + if save_lr_in_prologue then begin a_reg_alloc(list,NR_R0); { save return address... } @@ -950,20 +947,8 @@ const end; end; - { no GOT pointer loaded yet } - gotgot:=false; if usesfpr then begin -{ save floating-point registers - if (cs_create_pic in current_settings.moduleswitches) and not(usesgpr) then - begin - a_call_name(current_asmdata.RefAsmSymbol('_savefpr_'+tostr(ord(firstregfpu)-ord(R_F14)+14)+'_g')); - gotgot:=true; - end - else - a_call_name(current_asmdata.RefAsmSymbol('_savefpr_'+tostr(ord(firstregfpu)-ord(R_F14)+14))); -} - reference_reset_base(href,NR_R1,-8); for regcounter:=firstregfpu to RS_F31 do begin @@ -980,15 +965,6 @@ const { save gprs and fetch GOT pointer } if usesgpr then begin - { - if cs_create_pic in current_settings.moduleswitches then - begin - a_call_name(current_asmdata.RefAsmSymbol('_savegpr_'+tostr(ord(firstreggpr)-ord(R_14)+14)+'_g')); - gotgot:=true; - end - else - a_call_name(current_asmdata.RefAsmSymbol('_savegpr_'+tostr(ord(firstreggpr)-ord(R_14)+14))) - } if (firstregint <= RS_R22) or ((cs_opt_size in current_settings.optimizerswitches) and { with RS_R30 it's also already smaller, but too big a speed trade-off to make } @@ -1010,34 +986,6 @@ const { if (tppcprocinfo(current_procinfo).needs_frame_pointer) then } { a_reg_dealloc(list,NR_R12); } - - { if we didn't get the GOT pointer till now, we've to calculate it now } -(* - if not(gotgot) and (pi_needs_got in current_procinfo.flags) then - case target_info.system of - system_powerpc_darwin: - begin - list.concat(taicpu.op_reg_reg(A_MFSPR,NR_R0,NR_LR)); - fillchar(cond,sizeof(cond),0); - cond.simple:=false; - cond.bo:=20; - cond.bi:=31; - instr:=taicpu.op_sym(A_BCL,current_procinfo.CurrGOTLabel); - instr.setcondition(cond); - list.concat(instr); - a_label(list,current_procinfo.CurrGOTLabel); - list.concat(taicpu.op_reg_reg(A_MFSPR,current_procinfo.got,NR_LR)); - list.concat(taicpu.op_reg_reg(A_MTSPR,NR_LR,NR_R0)); - end; - else - begin - a_reg_alloc(list,NR_R31); - { place GOT ptr in r31 } - list.concat(taicpu.op_reg_reg(A_MFSPR,NR_R31,NR_LR)); - end; - end; -*) - if (not nostackframe) and tppcprocinfo(current_procinfo).needstackframe and (localsize <> 0) then @@ -1052,9 +1000,17 @@ const reference_reset_base(href,NR_STACK_POINTER_REG,0); { can't use getregisterint here, the register colouring } { is already done when we get here } - href.index := NR_R11; + { R12 may hold previous stack pointer, R11 may be in } + { use as got => use R0 (but then we can't use } + { a_load_const_reg) } + href.index := NR_R0; a_reg_alloc(list,href.index); - a_load_const_reg(list,OS_S32,-localsize,href.index); + list.concat(taicpu.op_reg_const(A_LI,NR_R0,smallint((-localsize) and $ffff))); + if (smallint((-localsize) and $ffff) < 0) then + { upper 16 bits are now $ffff -> xor with inverse } + list.concat(taicpu.op_reg_reg_const(A_XORIS,NR_R0,NR_R0,word(not(((-localsize) shr 16) and $ffff)))) + else + list.concat(taicpu.op_reg_reg_const(A_ORIS,NR_R0,NR_R0,word(((-localsize) shr 16) and $ffff))); a_load_store(list,A_STWUX,NR_STACK_POINTER_REG,href); a_reg_dealloc(list,href.index); end; @@ -1709,9 +1665,25 @@ const if (target_info.system = system_powerpc_darwin) and assigned(ref.symbol) and - (ref.symbol.bind = AB_EXTERNAL) then + not assigned(ref.relsymbol) and + ((ref.symbol.bind = AB_EXTERNAL) or + (cs_create_pic in current_settings.moduleswitches))then begin - tmpreg := g_indirect_sym_load(list,ref.symbol.name); + if (ref.symbol.bind = AB_EXTERNAL) or + ((cs_create_pic in current_settings.moduleswitches) and + (ref.symbol.bind in [AB_COMMON,AB_GLOBAL])) then + begin + tmpreg := g_indirect_sym_load(list,ref.symbol.name); + ref.symbol:=nil; + end + else + begin + include(current_procinfo.flags,pi_needs_got); + tmpreg := current_procinfo.got; + if assigned(ref.relsymbol) then + internalerror(2007093501); + ref.relsymbol := current_procinfo.CurrGOTLabel; + end; if (ref.base = NR_NO) then ref.base := tmpreg else if (ref.index = NR_NO) then @@ -1721,7 +1693,6 @@ const list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg)); ref.base := tmpreg; end; - ref.symbol := nil; end; if (ref.base = NR_NO) then diff --git a/compiler/powerpc/cpupi.pas b/compiler/powerpc/cpupi.pas index 80c99f1929..b7ec2aae3d 100644 --- a/compiler/powerpc/cpupi.pas +++ b/compiler/powerpc/cpupi.pas @@ -29,7 +29,7 @@ unit cpupi; uses cutils,globtype, - cgbase, + cgbase,aasmdata, procinfo,cpuinfo,psub; type @@ -43,6 +43,7 @@ unit cpupi; function calc_stackframe_size:longint;override; function uses_stack_temps: boolean; + procedure allocate_got_register(list: TAsmList);override; private first_save_int_reg, first_save_fpu_reg: tsuperregister; public @@ -58,7 +59,7 @@ unit cpupi; uses globals,systems, cpubase, - aasmtai,aasmdata, + aasmtai, tgobj,cgobj, symconst,symsym,paramgr,symutil,symtable, verbose; @@ -184,7 +185,17 @@ unit cpupi; else begin result := align(tg.lasttemp,16); - needstackframe:=result<>0; + needstackframe := result<>0; + end; + end; + + + procedure tppcprocinfo.allocate_got_register(list: TAsmList); + begin + if (target_info.system = system_powerpc_darwin) and + (cs_create_pic in current_settings.moduleswitches) then + begin + got := cg.getaddressregister(list); end; end; diff --git a/compiler/powerpc/rappcgas.pas b/compiler/powerpc/rappcgas.pas index fdffd92bcb..1a3ca2a518 100644 --- a/compiler/powerpc/rappcgas.pas +++ b/compiler/powerpc/rappcgas.pas @@ -140,6 +140,8 @@ Unit rappcgas; var l : aint; + relsym: string; + asmsymtyp: tasmsymtype; begin Consume(AS_LPAREN); @@ -195,21 +197,51 @@ Unit rappcgas; AS_ID: Begin ReadSym(oper); - { add a constant expression? } - if (actasmtoken=AS_PLUS) then - begin - l:=BuildConstExpression(true,true); - case oper.opr.typ of - OPR_CONSTANT : - inc(oper.opr.val,l); - OPR_LOCAL : - inc(oper.opr.localsymofs,l); - OPR_REFERENCE : - inc(oper.opr.ref.offset,l); - else - internalerror(200309202); - end; - end; + case actasmtoken of + AS_PLUS: + begin + { add a constant expression? } + l:=BuildConstExpression(true,true); + case oper.opr.typ of + OPR_CONSTANT : + inc(oper.opr.val,l); + OPR_LOCAL : + inc(oper.opr.localsymofs,l); + OPR_REFERENCE : + inc(oper.opr.ref.offset,l); + else + internalerror(200309202); + end; + end; + AS_MINUS: + begin + Consume(AS_MINUS); + BuildConstSymbolExpression(false,true,false,l,relsym,asmsymtyp); + if (relsym<>'') then + begin + if (oper.opr.typ = OPR_REFERENCE) then + oper.opr.ref.relsymbol:=current_asmdata.RefAsmSymbol(relsym) + else + begin + Message(asmr_e_invalid_reference_syntax); + RecoverConsume(false); + end + end + else + begin + case oper.opr.typ of + OPR_CONSTANT : + dec(oper.opr.val,l); + OPR_LOCAL : + dec(oper.opr.localsymofs,l); + OPR_REFERENCE : + dec(oper.opr.ref.offset,l); + else + internalerror(2007092601); + end; + end; + end; + end; Consume(AS_RPAREN); if actasmtoken=AS_AT then ReadAt(oper); diff --git a/compiler/ppcgen/cgppc.pas b/compiler/ppcgen/cgppc.pas index b085b31bb2..bc75ab76b1 100644 --- a/compiler/ppcgen/cgppc.pas +++ b/compiler/ppcgen/cgppc.pas @@ -61,6 +61,8 @@ unit cgppc; procedure a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel); procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override; + + procedure g_maybe_got_init(list: TAsmList); override; protected function get_darwin_call_stub(const s: string): tasmsymbol; procedure a_load_subsetref_regs_noindex(list: TAsmList; subsetsize: tcgsize; loadbitsize: byte; const sref: tsubsetreference; valuereg, extra_value_reg: tregister); override; @@ -77,6 +79,8 @@ unit cgppc; { represented by a 16 bit immediate as required by some PowerPC } { instructions } function hasLargeOffset(const ref : TReference) : Boolean; inline; + + function save_lr_in_prologue: boolean; end; const @@ -98,6 +102,14 @@ unit cgppc; end; + function tcgppcgen.save_lr_in_prologue: boolean; + begin + result:= + ((pi_do_call in current_procinfo.flags) or + ([cs_lineinfo,cs_debuginfo,cs_profile] * current_settings.moduleswitches <> [])); + end; + + procedure tcgppcgen.a_param_const(list: TAsmList; size: tcgsize; a: aint; const paraloc: tcgpara); var @@ -145,11 +157,49 @@ unit cgppc; end; + procedure tcgppcgen.g_maybe_got_init(list: TAsmList); + var + instr: taicpu; + cond: tasmcond; + savedlr: boolean; + begin + if not(po_assembler in current_procinfo.procdef.procoptions) then + begin + if (cs_create_pic in current_settings.moduleswitches) and + (pi_needs_got in current_procinfo.flags) then + case target_info.system of + system_powerpc_darwin: + begin + savedlr:=save_lr_in_prologue; + if not savedlr then + list.concat(taicpu.op_reg_reg(A_MFSPR,NR_R0,NR_LR)); + fillchar(cond,sizeof(cond),0); + cond.simple:=false; + cond.bo:=20; + cond.bi:=31; + instr:=taicpu.op_sym(A_BCL,current_procinfo.CurrGOTLabel); + instr.setcondition(cond); + list.concat(instr); + a_label(list,current_procinfo.CurrGOTLabel); + a_reg_alloc(list,current_procinfo.got); + list.concat(taicpu.op_reg_reg(A_MFSPR,current_procinfo.got,NR_LR)); + if not savedlr then + list.concat(taicpu.op_reg_reg(A_MTSPR,NR_LR,NR_R0)); + end; + end; + end; + end; + + function tcgppcgen.get_darwin_call_stub(const s: string): tasmsymbol; var stubname: string; + instr: taicpu; href: treference; l1: tasmsymbol; + localgotlab: tasmlabel; + cond: tasmcond; + stubalign: byte; begin { function declared in the current unit? } { doesn't work correctly, because this will also return a hit if we } @@ -164,14 +214,36 @@ unit cgppc; current_asmdata.asmlists[al_imports]:=TAsmList.create; current_asmdata.asmlists[al_imports].concat(Tai_section.create(sec_stub,'',0)); - current_asmdata.asmlists[al_imports].concat(Tai_align.Create(16)); + if (cs_create_pic in current_settings.moduleswitches) then + stubalign:=32 + else + stubalign:=16; + current_asmdata.asmlists[al_imports].concat(Tai_align.Create(stubalign)); result := current_asmdata.RefAsmSymbol(stubname); current_asmdata.asmlists[al_imports].concat(Tai_symbol.Create(result,0)); current_asmdata.asmlists[al_imports].concat(tai_directive.create(asd_indirect_symbol,s)); l1 := current_asmdata.RefAsmSymbol('L'+s+'$lazy_ptr'); reference_reset_symbol(href,l1,0); href.refaddr := addr_higha; - current_asmdata.asmlists[al_imports].concat(taicpu.op_reg_ref(A_LIS,NR_R11,href)); + if (cs_create_pic in current_settings.moduleswitches) then + begin + current_asmdata.getjumplabel(localgotlab); + href.relsymbol:=localgotlab; + fillchar(cond,sizeof(cond),0); + cond.simple:=false; + cond.bo:=20; + cond.bi:=31; + current_asmdata.asmlists[al_imports].concat(taicpu.op_reg(A_MFLR,NR_R0)); + instr:=taicpu.op_sym(A_BCL,localgotlab); + instr.setcondition(cond); + current_asmdata.asmlists[al_imports].concat(instr); + a_label(current_asmdata.asmlists[al_imports],localgotlab); + current_asmdata.asmlists[al_imports].concat(taicpu.op_reg(A_MFLR,NR_R11)); + current_asmdata.asmlists[al_imports].concat(taicpu.op_reg_reg_ref(A_ADDIS,NR_R11,NR_R11,href)); + current_asmdata.asmlists[al_imports].concat(taicpu.op_reg(A_MTLR,NR_R0)); + end + else + current_asmdata.asmlists[al_imports].concat(taicpu.op_reg_ref(A_LIS,NR_R11,href)); href.refaddr := addr_low; href.base := NR_R11; {$ifndef cpu64bit} diff --git a/compiler/procinfo.pas b/compiler/procinfo.pas index af6cda0834..9628588937 100644 --- a/compiler/procinfo.pas +++ b/compiler/procinfo.pas @@ -116,6 +116,9 @@ unit procinfo; { Generate parameter information } procedure generate_parameter_info;virtual; + + { Allocate got register } + procedure allocate_got_register(list: TAsmList);virtual; end; tcprocinfo = class of tprocinfo; @@ -194,4 +197,10 @@ implementation end; + procedure tprocinfo.allocate_got_register(list: TAsmList); + begin + { most os/cpu combo's don't use this yet, so not yet abstract } + end; + + end. diff --git a/compiler/psub.pas b/compiler/psub.pas index c7c2e4f660..ae142b357a 100644 --- a/compiler/psub.pas +++ b/compiler/psub.pas @@ -872,6 +872,9 @@ implementation set_first_temp_offset; generate_parameter_info; + { allocate got register if needed } + current_procinfo.allocate_got_register(aktproccode); + { Allocate space in temp/registers for parast and localst } current_filepos:=entrypos; gen_alloc_symtable(aktproccode,procdef.parast); @@ -891,9 +894,10 @@ implementation current_filepos:=entrypos; { record which registers are allocated here, since all code } { allocating registers comes after it } - cg.set_regalloc_extend_backwards(true); + cg.set_regalloc_live_range_direction(rad_backwards); + gen_load_para_value(templist); - cg.set_regalloc_extend_backwards(false); + cg.set_regalloc_live_range_direction(rad_forward); { caller paraloc info is also necessary in the stackframe_entry code of the ppc (and possibly other processors) } @@ -918,7 +922,7 @@ implementation current_filepos:=entrypos; current_settings.localswitches:=entryswitches; - cg.set_regalloc_extend_backwards(true); + cg.set_regalloc_live_range_direction(rad_backwards); gen_entry_code(templist); aktproccode.insertlistafter(entry_asmnode.currenttai,templist); @@ -930,7 +934,7 @@ implementation current_filepos:=exitpos; current_settings.localswitches:=exitswitches; - cg.set_regalloc_extend_backwards(false); + cg.set_regalloc_live_range_direction(rad_forward); gen_finalize_code(templist); { the finalcode must be concated if there was no position available, @@ -973,6 +977,14 @@ implementation { Free space in temp/registers for parast and localst, must be done after gen_entry_code } current_filepos:=exitpos; + + { make sure the got/pic register doesn't get freed in the } + { middle of a loop } + if (cs_create_pic in current_settings.moduleswitches) and + (pi_needs_got in current_procinfo.flags) and + (current_procinfo.got<>NR_NO) then + cg.a_reg_sync(aktproccode,current_procinfo.got); + gen_free_symtable(aktproccode,procdef.localst); gen_free_symtable(aktproccode,procdef.parast); @@ -993,13 +1005,27 @@ implementation aktproccode.insertlistafter(stackcheck_asmnode.currenttai,templist) end; - { load got if necessary } - cg.set_regalloc_extend_backwards(true); + { this code (got loading) comes before everything which has } + { already been generated, so reset the info about already } + { backwards extended registers (so their live range can be } + { extended backwards even further if needed) } + { This code must be } + { a) generated after do_secondpass has been called } + { (because pi_needs_got may be set there) } + { b) generated before register allocation, because the } + { got/pic register can be a virtual one } + { c) inserted before the entry code, because the entry } + { code may need global symbols such as init rtti } + { d) inserted after the stackframe allocation, because } + { this register may have to be spilled } + cg.set_regalloc_live_range_direction(rad_backwards_reinit); current_filepos:=entrypos; - gen_got_load(templist); + { load got if necessary } + cg.g_maybe_got_init(templist); + aktproccode.insertlistafter(headertai,templist); - cg.set_regalloc_extend_backwards(false); + cg.set_regalloc_live_range_direction(rad_forward); { The procedure body is finished, we can now allocate the registers } @@ -1011,6 +1037,10 @@ implementation maintain location lists } current_procinfo.procdef.parast.SymList.ForEachCall(@translate_registers,templist); current_procinfo.procdef.localst.SymList.ForEachCall(@translate_registers,templist); + if (cs_create_pic in current_settings.moduleswitches) and + (pi_needs_got in current_procinfo.flags) and + not(cs_no_regalloc in current_settings.globalswitches) then + cg.translate_register(current_procinfo.got); { Add save and restore of used registers } current_filepos:=entrypos; diff --git a/compiler/rgobj.pas b/compiler/rgobj.pas index 022e9dc1b7..a0c596eff5 100644 --- a/compiler/rgobj.pas +++ b/compiler/rgobj.pas @@ -175,7 +175,7 @@ unit rgobj; const r:Tsuperregisterset; const spilltemplist:Tspill_temp_list): boolean;virtual; private - do_extend_live_range_backwards: boolean; + int_live_range_direction: TRADirection; {# First imaginary register.} first_imaginary : Tsuperregister; {# Highest register allocated until now.} @@ -236,9 +236,9 @@ unit rgobj; procedure select_spill; procedure assign_colours; procedure clear_interferences(u:Tsuperregister); - procedure set_live_range_backwards(b: boolean); + procedure set_live_range_direction(dir: TRADirection); public - property extend_live_range_backwards: boolean read do_extend_live_range_backwards write set_live_range_backwards; + property live_range_direction: TRADirection read int_live_range_direction write set_live_range_direction; end; const @@ -370,8 +370,9 @@ unit rgobj; { empty super register sets can cause very strange problems } if high(Ausable)=-1 then internalerror(200210181); - extend_live_range_backwards := false; + live_range_direction:=rad_forward; supregset_reset(extended_backwards,false,high(tsuperregister)); + supregset_reset(backwards_was_first,false,high(tsuperregister)); first_imaginary:=Afirst_imaginary; maxreg:=Afirst_imaginary; regtype:=Aregtype; @@ -678,16 +679,18 @@ unit rgobj; end; - procedure trgobj.set_live_range_backwards(b: boolean); + procedure trgobj.set_live_range_direction(dir: TRADirection); begin - if (b) then + if (dir in [rad_backwards,rad_backwards_reinit]) then begin + if (dir=rad_backwards_reinit) then + supregset_reset(extended_backwards,false,high(tsuperregister)); + int_live_range_direction:=rad_backwards; { new registers may be allocated } supregset_reset(backwards_was_first,false,high(tsuperregister)); - do_extend_live_range_backwards := true; end else - do_extend_live_range_backwards := false; + int_live_range_direction:=rad_forward; end; @@ -704,7 +707,7 @@ unit rgobj; if supreg>=first_imaginary then with reginfo[supreg] do begin - if not(extend_live_range_backwards) then + if (live_range_direction=rad_forward) then begin if not assigned(live_start) then live_start:=instr; diff --git a/rtl/powerpc/math.inc b/rtl/powerpc/math.inc index 74a83e811d..30800b22e8 100644 --- a/rtl/powerpc/math.inc +++ b/rtl/powerpc/math.inc @@ -75,12 +75,26 @@ const fabs f1,f1 // load 2^32 in f2 {$ifndef macos} + {$ifdef FPC_PIC} + {$ifdef darwin} + mflr r0 + bcl 20,31,.Lpiclab +.Lpiclab: + mflr r5 + mtlr r0 + addis r4,r5,(factor-.Lpiclab)@ha + lfd f2,(factor-.Lpiclab)@l(r4) + {$else darwin} + {$error Add pic code for linux/ppc32} + {$endif darwin} + {$else FPC_PIC} lis r4,factor@ha lfd f2,factor@l(r4) - {$else} + {$endif FPC_PIC} + {$else not macos} lwz r4,factor(r2) lfd f2,0(r4) - {$endif} + {$endif not macos} // check if value is < 0 // f3 := d / 2^32; fdiv f3,f1,f2 @@ -96,12 +110,21 @@ const xoris r0,r3,0x8000 stw r0,temp+4 {$ifndef macos} + {$ifdef FPC_PIC} + {$ifdef darwin} + addis r4,r5,(longint_to_real_helper-.Lpiclab)@ha + lfd f0,(longint_to_real_helper-.Lpiclab)@l(r4) + {$else darwin} + {$error Add pic code for linux/ppc32} + {$endif darwin} + {$else FPC_PIC} lis r4,longint_to_real_helper@ha lfd f0,longint_to_real_helper@l(r4) - {$else} + {$endif FPC_PIC} + {$else not macos} lwz r4,longint_to_real_helper(r2) lfd f0,0(r4) - {$endif} + {$endif not macos} lfd f3,temp fsub f3,f3,f0 @@ -113,12 +136,21 @@ const // load 2^31 in f2 {$ifndef macos} + {$ifdef FPC_PIC} + {$ifdef darwin} + addis r4,r5,(factor2-.Lpiclab)@ha + lfd f2,(factor2-.Lpiclab)@l(r4) + {$else darwin} + {$error Add pic code for linux/ppc32} + {$endif darwin} + {$else FPC_PIC} lis r4,factor2@ha lfd f2,factor2@l(r4) - {$else} + {$endif FPC_PIC} + {$else not macos} lwz r4,factor2(r2) lfd f2,0(r4) - {$endif} + {$endif not macos} // subtract 2^31 fsub f3,f4,f2 @@ -261,28 +293,54 @@ asm xoris r3,r3,0x8000 stw r3,temp+4 {$ifndef macos} + {$ifdef FPC_PIC} + {$ifdef darwin} + mflr r0 + bcl 20,31,.Lpiclab + .Lpiclab: + mflr r5 + mtlr r0 + addis r3,r5,(longint_to_real_helper-.Lpiclab)@ha + lfd f1,(longint_to_real_helper-.Lpiclab)@l(r3) + {$else darwin} + {$error Add pic code for linux/ppc32} + {$endif darwin} + {$else FPC_PIC} lis r3,longint_to_real_helper@ha lfd f1,longint_to_real_helper@l(r3) - {$else} + {$endif FPC_PIC} + {$else not macos} lwz r3,longint_to_real_helper(r2) lfd f1,0(r3) - {$endif} + {$endif not mac os} lfd f0,temp stw r4,temp+4 fsub f0,f0,f1 {$ifndef macos} + {$ifdef FPC_PIC} + {$ifdef darwin} + addis r4,r5,(cardinal_to_real_helper-.Lpiclab)@ha + lfd f1,(cardinal_to_real_helper-.Lpiclab)@l(r4) + addis r4,r5,(int_to_real_factor-.Lpiclab)@ha + lfd f3,temp + lfd f2,(int_to_real_factor-.Lpiclab)@l(r4) + {$else darwin} + {$error Add pic code for linux/ppc32} + {$endif darwin} + {$else FPC_PIC} lis r4,cardinal_to_real_helper@ha lfd f1,cardinal_to_real_helper@l(r4) lis r4,int_to_real_factor@ha lfd f3,temp lfd f2,int_to_real_factor@l(r4) - {$else} + {$endif FPC_PIC} + {$else not macos} lwz r4,cardinal_to_real_helper(r2) lwz r3,int_to_real_factor(r2) lfd f3,temp lfd f1,0(r4) lfd f2,0(r3) - {$endif} + {$endif not macos} fsub f3,f3,f1 fmadd f1,f0,f2,f3 end; @@ -305,22 +363,45 @@ asm stw r3,temp+4 lfd f0,temp {$ifndef macos} + {$ifdef FPC_PIC} + {$ifdef darwin} + mflr r0 + bcl 20,31,.Lpiclab + .Lpiclab: + mflr r5 + mtlr r0 + addis r3,r5,(cardinal_to_real_helper-.Lpiclab)@ha + lfd f1,(cardinal_to_real_helper-.Lpiclab)@l(r3) + {$else darwin} + {$error Add pic code for linux/ppc32} + {$endif darwin} + {$else FPC_PIC} lis r3,cardinal_to_real_helper@ha lfd f1,cardinal_to_real_helper@l(r3) - {$else} + {$endif FPC_PIC} + {$else not macos} lwz r3,longint_to_real_helper(r2) lfd f1,0(r3) - {$endif} + {$endif not macos} stw r4,temp+4 fsub f0,f0,f1 lfd f3,temp {$ifndef macos} + {$ifdef FPC_PIC} + {$ifdef darwin} + addis r4,r5,(int_to_real_factor-.Lpiclab)@ha + lfd f2,(int_to_real_factor-.Lpiclab)@l(r4) + {$else darwin} + {$error Add pic code for linux/ppc32} + {$endif darwin} + {$else FPC_PIC} lis r4,int_to_real_factor@ha lfd f2,int_to_real_factor@l(r4) - {$else} + {$endif FPC_PIC} + {$else not macos} lwz r4,int_to_real_factor(r2) lfd f2,0(r4) - {$endif} + {$endif not macos} fsub f3,f3,f1 fmadd f1,f0,f2,f3 end;