From 45b7358d81a93002ba0c656742d452c0d1a1d784 Mon Sep 17 00:00:00 2001 From: Jonas Maebe Date: Sat, 20 Oct 2007 20:14:45 +0000 Subject: [PATCH] + PIC support for darwin/ppc64 * added {$PIC+} for darwin to all library tests git-svn-id: trunk@8868 - --- compiler/powerpc/cgcpu.pas | 71 ---------------- compiler/powerpc64/cgcpu.pas | 108 ++---------------------- compiler/powerpc64/cpupi.pas | 18 +++- compiler/powerpc64/rappcgas.pas | 60 ++++++++++---- compiler/ppcgen/cgppc.pas | 140 ++++++++++++++++++++++++++++++-- rtl/powerpc64/math.inc | 20 +++-- tests/test/tlibrary1.pp | 6 +- tests/test/tlibrary3.pp | 4 + tests/webtbs/tw3082.pp | 5 ++ tests/webtbs/tw3573.pp | 4 + 10 files changed, 235 insertions(+), 201 deletions(-) diff --git a/compiler/powerpc/cgcpu.pas b/compiler/powerpc/cgcpu.pas index acb1afbbf4..56801ac00f 100644 --- a/compiler/powerpc/cgcpu.pas +++ b/compiler/powerpc/cgcpu.pas @@ -100,14 +100,6 @@ unit cgcpu; { the upper 24/16 bits of a register after an operation } procedure maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister); - { Make sure ref is a valid reference for the PowerPC and sets the } - { base to the value of the index if (base = R_NO). } - { Returns true if the reference contained a base, index and an } - { offset or symbol, in which case the base will have been changed } - { to a tempreg (which has to be freed by the caller) containing } - { the sum of part of the original reference } - function fixref(list: TAsmList; var ref: treference): boolean; override; - { returns whether a reference can be used immediately in a powerpc } { instruction } function issimpleref(const ref: treference): boolean; @@ -1656,69 +1648,6 @@ const end; - function tcgppc.fixref(list: TAsmList; var ref: treference): boolean; - - var - tmpreg: tregister; - begin - result := false; - - if (target_info.system = system_powerpc_darwin) and - assigned(ref.symbol) and - not assigned(ref.relsymbol) and - ((ref.symbol.bind = AB_EXTERNAL) or - (cs_create_pic in current_settings.moduleswitches))then - begin - 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 - ref.index := tmpreg - else - begin - list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg)); - ref.base := tmpreg; - end; - end; - - if (ref.base = NR_NO) then - begin - ref.base := ref.index; - ref.index := NR_NO; - end; - if (ref.base <> NR_NO) then - begin - if (ref.index <> NR_NO) and - ((ref.offset <> 0) or assigned(ref.symbol)) then - begin - result := true; - tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE); - list.concat(taicpu.op_reg_reg_reg( - A_ADD,tmpreg,ref.base,ref.index)); - ref.index := NR_NO; - ref.base := tmpreg; - end - end - else - if ref.index <> NR_NO then - internalerror(200208102); - end; - - { find out whether a is of the form 11..00..11b or 00..11...00. If } { that's the case, we can use rlwinm to do an AND operation } function tcgppc.get_rlwi_const(a: aint; var l1, l2: longint): boolean; diff --git a/compiler/powerpc64/cgcpu.pas b/compiler/powerpc64/cgcpu.pas index c1d9f2798e..e33f288a0a 100644 --- a/compiler/powerpc64/cgcpu.pas +++ b/compiler/powerpc64/cgcpu.pas @@ -107,16 +107,6 @@ type procedure maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister); - { Make sure ref is a valid reference for the PowerPC and sets the } - { base to the value of the index if (base = R_NO). } - { Returns true if the reference contained a base, index and an } - { offset or symbol, in which case the base will have been changed } - { to a tempreg (which has to be freed by the caller) containing } - { the sum of part of the original reference } - function fixref(list: TAsmList; var ref: treference): boolean; override; - - function load_got_symbol(list : TAsmList; symbol : string) : tregister; - { returns whether a reference can be used immediately in a powerpc } { instruction } function issimpleref(const ref: treference): boolean; @@ -1397,7 +1387,8 @@ var { there are two ways to do this: manually, by generating a few "std" instructions, or via the restore helper functions. The latter are selected by the -Og switch, i.e. "optimize for size" } - if (cs_opt_size in current_settings.optimizerswitches) then begin + if (cs_opt_size in current_settings.optimizerswitches) and + (target_info.system <> system_powerpc64_darwin) then begin mayNeedLRStore := false; if ((fprcount > 0) and (gprcount > 0)) then begin a_op_const_reg_reg(list, OP_SUB, OS_INT, 8 * fprcount, NR_R1, NR_R12); @@ -1450,10 +1441,10 @@ begin { determine whether we need to save the link register } needslinkreg := not(nostackframe) and - (((not (po_assembler in current_procinfo.procdef.procoptions)) and - ((pi_do_call in current_procinfo.flags) or (cs_profile in init_settings.moduleswitches))) or - ((cs_opt_size in current_settings.optimizerswitches) and ((fprcount > 0) or (gprcount > 0))) or - ([cs_lineinfo, cs_debuginfo] * current_settings.moduleswitches <> [])); + (save_lr_in_prologue or + ((cs_opt_size in current_settings.optimizerswitches) and + ((fprcount > 0) or + (gprcount > 0)))); a_reg_alloc(list, NR_STACK_POINTER_REG); a_reg_alloc(list, NR_R0); @@ -1944,93 +1935,6 @@ begin (ref.offset = 0))); end; -function tcgppc.load_got_symbol(list: TAsmList; symbol : string) : tregister; -var - l: tasmsymbol; - ref: treference; - symname : string; -begin - l:=current_asmdata.getasmsymbol(symbol); - reference_reset_symbol(ref,l,0); - ref.base := NR_R2; - ref.refaddr := addr_pic; - - result := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE); - {$IFDEF EXTDEBUG} - list.concat(tai_comment.create(strpnew('loading got reference for ' + symbol))); - {$ENDIF EXTDEBUG} -// cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,ref,result); - list.concat(taicpu.op_reg_ref(A_LD, result, ref)); -end; - - -function tcgppc.fixref(list: TAsmList; var ref: treference): boolean; -var - tmpreg: tregister; - name : string; -begin - result := false; - { Avoids recursion. } - if (ref.refaddr = addr_pic) then exit; - {$IFDEF EXTDEBUG} - list.concat(tai_comment.create(strpnew('fixref0 ' + ref2string(ref)))); - {$ENDIF EXTDEBUG} - - if (target_info.system = system_powerpc64_darwin) and - assigned(ref.symbol) and - (ref.symbol.bind = AB_EXTERNAL) then - begin - tmpreg := g_indirect_sym_load(list,ref.symbol.name); - if (ref.base = NR_NO) then - ref.base := tmpreg - else if (ref.index = NR_NO) then - ref.index := tmpreg - else - begin - list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg)); - ref.base := tmpreg; - end; - ref.symbol := nil; - end; - - { if we have to create PIC, add the symbol to the TOC/GOT } - if (target_info.system <> system_powerpc64_darwin) and - (cs_create_pic in current_settings.moduleswitches) and - (assigned(ref.symbol)) then begin - tmpreg := load_got_symbol(list, ref.symbol.name); - if (ref.base = NR_NO) then - ref.base := tmpreg - else if (ref.index = NR_NO) then - ref.index := tmpreg - else begin - a_op_reg_reg_reg(list, OP_ADD, OS_ADDR, ref.base, tmpreg, tmpreg); - ref.base := tmpreg; - end; - ref.symbol := nil; - {$IFDEF EXTDEBUG} - list.concat(tai_comment.create(strpnew('fixref-pic ' + ref2string(ref)))); - {$ENDIF EXTDEBUG} - end; - - if (ref.base = NR_NO) then begin - ref.base := ref.index; - ref.index := NR_NO; - end; - if (ref.base <> NR_NO) and (ref.index <> NR_NO) and - ((ref.offset <> 0) or assigned(ref.symbol)) then begin - result := true; - tmpreg := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE); - a_op_reg_reg_reg(list, OP_ADD, OS_ADDR, ref.base, ref.index, tmpreg); - ref.base := tmpreg; - ref.index := NR_NO; - end; - if (ref.index <> NR_NO) and (assigned(ref.symbol) or (ref.offset <> 0)) then - internalerror(2006010506); - {$IFDEF EXTDEBUG} - list.concat(tai_comment.create(strpnew('fixref1 ' + ref2string(ref)))); - {$ENDIF EXTDEBUG} -end; - procedure tcgppc.a_load_store(list: TAsmList; op: tasmop; reg: tregister; ref: treference); diff --git a/compiler/powerpc64/cpupi.pas b/compiler/powerpc64/cpupi.pas index 135ba73c0f..e52b04149d 100644 --- a/compiler/powerpc64/cpupi.pas +++ b/compiler/powerpc64/cpupi.pas @@ -28,7 +28,7 @@ unit cpupi; interface uses - cutils, + cutils,aasmdata, procinfo, cpuinfo, psub; type @@ -43,6 +43,8 @@ type function calc_stackframe_size(numgpr, numfpr : longint): longint; needs_frame_pointer : boolean; + + procedure allocate_got_register(list: TAsmList); override; end; implementation @@ -50,8 +52,8 @@ implementation uses globtype, globals, systems, cpubase, cgbase, - aasmtai,aasmdata, - tgobj, + aasmtai, + tgobj,cgobj, symconst, symsym, paramgr, symutil, symtable, verbose; @@ -111,6 +113,16 @@ begin end; end; + +procedure tppcprocinfo.allocate_got_register(list: TAsmList); + begin + if (target_info.system = system_powerpc64_darwin) and + (cs_create_pic in current_settings.moduleswitches) then + begin + got := cg.getaddressregister(list); + end; + end; + begin cprocinfo := tppcprocinfo; end. diff --git a/compiler/powerpc64/rappcgas.pas b/compiler/powerpc64/rappcgas.pas index 1b48f94d2a..c70369be53 100644 --- a/compiler/powerpc64/rappcgas.pas +++ b/compiler/powerpc64/rappcgas.pas @@ -151,6 +151,8 @@ procedure tppcattreader.BuildReference(oper: tppcoperand); var l: aint; + relsym: string; + asmsymtyp: tasmsymtype; begin Consume(AS_LPAREN); @@ -207,20 +209,50 @@ begin 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; + 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 diff --git a/compiler/ppcgen/cgppc.pas b/compiler/ppcgen/cgppc.pas index 2c3aa8ee7e..a12e06b14d 100644 --- a/compiler/ppcgen/cgppc.pas +++ b/compiler/ppcgen/cgppc.pas @@ -66,7 +66,13 @@ unit cgppc; 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; - function fixref(list: TAsmList; var ref: treference): boolean; virtual; abstract; + { Make sure ref is a valid reference for the PowerPC and sets the } + { base to the value of the index if (base = R_NO). } + { Returns true if the reference contained a base, index and an } + { offset or symbol, in which case the base will have been changed } + { to a tempreg (which has to be freed by the caller) containing } + { the sum of part of the original reference } + function fixref(list: TAsmList; var ref: treference): boolean; { contains the common code of a_load_reg_ref and a_load_ref_reg } procedure a_load_store(list:TAsmList;op: tasmop;reg:tregister;ref: treference);virtual; @@ -81,6 +87,8 @@ unit cgppc; function hasLargeOffset(const ref : TReference) : Boolean; inline; function save_lr_in_prologue: boolean; + + function load_got_symbol(list : TAsmList; symbol : string) : tregister; end; const @@ -105,8 +113,10 @@ unit cgppc; 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 <> [])); + (not (po_assembler in current_procinfo.procdef.procoptions) and + ((pi_do_call in current_procinfo.flags) or + (cs_profile in init_settings.moduleswitches))) or + ([cs_lineinfo,cs_debuginfo] * current_settings.moduleswitches <> []); end; @@ -168,7 +178,8 @@ unit cgppc; 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: + system_powerpc_darwin, + system_powerpc64_darwin: begin savedlr:=save_lr_in_prologue; if not savedlr then @@ -185,7 +196,7 @@ unit cgppc; list.concat(taicpu.op_reg_reg(A_MFSPR,current_procinfo.got,NR_LR)); if not savedlr or { in the following case lr is saved, but not restored } - { (happens e.g. when generating debug info for leaf } + { (happens e.g. when generating debug info for leaf } { procedures) } not(pi_do_call in current_procinfo.flags) then list.concat(taicpu.op_reg_reg(A_MTSPR,NR_LR,NR_R0)); @@ -687,6 +698,125 @@ unit cgppc; end; + function tcgppcgen.load_got_symbol(list: TAsmList; symbol : string) : tregister; + var + l: tasmsymbol; + ref: treference; + begin + if (target_info.system <> system_powerpc64_linux) then + internalerror(2007102010); + l:=current_asmdata.getasmsymbol(symbol); + reference_reset_symbol(ref,l,0); + ref.base := NR_R2; + ref.refaddr := addr_pic; + + result := rg[R_INTREGISTER].getregister(list, R_SUBWHOLE); + {$IFDEF EXTDEBUG} + list.concat(tai_comment.create(strpnew('loading got reference for ' + symbol))); + {$ENDIF EXTDEBUG} + // cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,ref,result); + +{$ifdef cpu64bit} + list.concat(taicpu.op_reg_ref(A_LD, result, ref)); +{$else cpu64bit} + list.concat(taicpu.op_reg_ref(A_LWZ, result, ref)); +{$endif cpu64bit} + end; + + + function tcgppcgen.fixref(list: TAsmList; var ref: treference): boolean; + var + tmpreg: tregister; + begin + result := false; + + { Avoid recursion. } + if (ref.refaddr = addr_pic) then + exit; + + {$IFDEF EXTDEBUG} + list.concat(tai_comment.create(strpnew('fixref0 ' + ref2string(ref)))); + {$ENDIF EXTDEBUG} + if (target_info.system in [system_powerpc_darwin,system_powerpc64_darwin]) and + assigned(ref.symbol) and + not assigned(ref.relsymbol) and + ((ref.symbol.bind = AB_EXTERNAL) or + (cs_create_pic in current_settings.moduleswitches))then + begin + 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 + ref.index := tmpreg + else + begin + list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.base,tmpreg)); + ref.base := tmpreg; + end; + end; + + { if we have to create PIC, add the symbol to the TOC/GOT } + if (target_info.system = system_powerpc64_linux) and + (cs_create_pic in current_settings.moduleswitches) and + (assigned(ref.symbol)) then + begin + tmpreg := load_got_symbol(list, ref.symbol.name); + if (ref.base = NR_NO) then + ref.base := tmpreg + else if (ref.index = NR_NO) then + ref.index := tmpreg + else begin + a_op_reg_reg_reg(list, OP_ADD, OS_ADDR, ref.base, tmpreg, tmpreg); + ref.base := tmpreg; + end; + ref.symbol := nil; + {$IFDEF EXTDEBUG} + list.concat(tai_comment.create(strpnew('fixref-pic ' + ref2string(ref)))); + {$ENDIF EXTDEBUG} + end; + + if (ref.base = NR_NO) then + begin + ref.base := ref.index; + ref.index := NR_NO; + end; + if (ref.base <> NR_NO) then + begin + if (ref.index <> NR_NO) and + ((ref.offset <> 0) or assigned(ref.symbol)) then + begin + result := true; + tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE); + list.concat(taicpu.op_reg_reg_reg( + A_ADD,tmpreg,ref.base,ref.index)); + ref.index := NR_NO; + ref.base := tmpreg; + end + end; + if (ref.index <> NR_NO) and + (assigned(ref.symbol) or + (ref.offset <> 0)) then + internalerror(200208102); + {$IFDEF EXTDEBUG} + list.concat(tai_comment.create(strpnew('fixref1 ' + ref2string(ref)))); + {$ENDIF EXTDEBUG} + end; + + procedure tcgppcgen.a_load_store(list:TAsmList;op: tasmop;reg:tregister; ref: treference); diff --git a/rtl/powerpc64/math.inc b/rtl/powerpc64/math.inc index dc8107b369..1e0fbdec90 100644 --- a/rtl/powerpc64/math.inc +++ b/rtl/powerpc64/math.inc @@ -99,11 +99,21 @@ asm ori r4, r4, longint_to_real_helper@highera sldi r4, r4, 32 oris r4, r4, longint_to_real_helper@ha -{$else darwin} - lis r4, longint_to_real_helper@ha -{$endif darwin} lfd f4, longint_to_real_helper@l(r4) - +{$else not darwin} +{$ifdef FPC_PIC} + mflr r0 + bcl 20,31,.Lpiclab +.Lpiclab: + mflr r5 + mtlr r0 + addis r4,r5,(longint_to_real_helper-.Lpiclab)@ha + lfd f2,(longint_to_real_helper-.Lpiclab)@l(r4) +{$else FPC_PIC} + lis r4, longint_to_real_helper@ha + lfd f4, longint_to_real_helper@l(r4) +{$endif FPC_PIC} +{$endif not darwin} rldicl r4,r3,32,32 // isolate high half rldicl r0,r3,0,32 // isolate low half std r4,temp1 // store dword both @@ -114,4 +124,4 @@ asm fcfid f0,f0 // fpu int (no rnd) fmadd f0,f4,f2,f0 // (2**32)*high+low (only add can rnd) end; - + diff --git a/tests/test/tlibrary1.pp b/tests/test/tlibrary1.pp index 67abf88d7f..750ccab9e9 100644 --- a/tests/test/tlibrary1.pp +++ b/tests/test/tlibrary1.pp @@ -1,6 +1,10 @@ { %NORUN } { %SKIPTARGET=macos } +{$ifdef darwin} +{$PIC+} +{$endif darwin} + {$ifdef CPUX86_64} {$ifndef WINDOWS} {$PIC+} @@ -32,7 +36,7 @@ const procedure Test;export; begin -// writeln('Hoi'); + writeln('Hoi'); end; exports diff --git a/tests/test/tlibrary3.pp b/tests/test/tlibrary3.pp index 403cb57def..6b556bb9f9 100644 --- a/tests/test/tlibrary3.pp +++ b/tests/test/tlibrary3.pp @@ -1,6 +1,10 @@ { %NORUN } { %SKIPTARGET=macos, win64 } +{$ifdef darwin} +{$PIC+} +{$endif darwin} + {$ifdef CPUX86_64} {$ifndef WINDOWS} {$PIC+} diff --git a/tests/webtbs/tw3082.pp b/tests/webtbs/tw3082.pp index 998a2e0eb7..9feb6f73df 100644 --- a/tests/webtbs/tw3082.pp +++ b/tests/webtbs/tw3082.pp @@ -2,6 +2,11 @@ { %cpu=x86_64,i386,powerpc,sparc} { %skiptarget = go32v2,macos } { execute this test only on reasonable fast cpus } + +{$ifdef darwin} +{$PIC+} +{$endif darwin} + library lib; const s = diff --git a/tests/webtbs/tw3573.pp b/tests/webtbs/tw3573.pp index bdb700c380..878739ec08 100644 --- a/tests/webtbs/tw3573.pp +++ b/tests/webtbs/tw3573.pp @@ -4,6 +4,10 @@ {$ifdef fpc}{$mode delphi}{$endif} +{$ifdef darwin} +{$PIC+} +{$endif darwin} + resourcestring wurst = 'jo' deprecated;