From aa82e006158c3651778b27b982c00b318d9b43b8 Mon Sep 17 00:00:00 2001 From: Jonas Maebe Date: Wed, 26 Apr 2017 19:43:35 +0000 Subject: [PATCH] * fixed check to determine whether a record parameter can be subscripted directly in inline assembly: that's only possible if it's a register parameter where the address of the record was passed (rather than the record itself), or if a parameter has been explicitly typecasted in Intel-style assembly using ".size" git-svn-id: trunk@35959 - --- compiler/aarch64/racpugas.pas | 7 ++++--- compiler/arm/raarmgas.pas | 7 ++++--- compiler/avr/raavrgas.pas | 7 ++++--- compiler/mips/racpugas.pas | 7 ++++--- compiler/powerpc/rappcgas.pas | 7 ++++--- compiler/powerpc64/rappcgas.pas | 8 ++++---- compiler/raatt.pas | 3 ++- compiler/rautils.pas | 8 +++++--- compiler/sparc/racpugas.pas | 7 ++++--- compiler/x86/rax86att.pas | 9 +++++---- compiler/x86/rax86int.pas | 34 +++++++++++++++++++++------------ 11 files changed, 62 insertions(+), 42 deletions(-) diff --git a/compiler/aarch64/racpugas.pas b/compiler/aarch64/racpugas.pas index c67be52b16..2ea49e97c1 100644 --- a/compiler/aarch64/racpugas.pas +++ b/compiler/aarch64/racpugas.pas @@ -58,7 +58,7 @@ Unit racpugas; symconst,symsym, procinfo, rabase,rautils, - cgbase,cgutils; + cgbase,cgutils,paramgr; function taarch64attreader.is_register(const s:string):boolean; @@ -608,8 +608,9 @@ Unit racpugas; will generate buggy code. Allow it only for explicit typecasting } if hasdot and (not oper.hastype) and - (tabstractnormalvarsym(oper.opr.localsym).owner.symtabletype=parasymtable) and - (current_procinfo.procdef.proccalloption<>pocall_register) then + (oper.opr.localsym.typ=paravarsym) and + ((tparavarsym(oper.opr.localsym).paraloc[calleeside].location^.loc<>LOC_REGISTER) or + not paramanager.push_addr_param(oper.opr.localsym.varspez,oper.opr.localsym.vardef,current_procinfo.procdef.proccalloption)) then Message(asmr_e_cannot_access_field_directly_for_parameters); inc(oper.opr.localsymofs,l) end; diff --git a/compiler/arm/raarmgas.pas b/compiler/arm/raarmgas.pas index fc1a1638fe..5863957f03 100644 --- a/compiler/arm/raarmgas.pas +++ b/compiler/arm/raarmgas.pas @@ -68,7 +68,7 @@ Unit raarmgas; symconst,symsym, procinfo, rabase,rautils, - cgbase,cgutils; + cgbase,cgutils,paramgr; function tarmunifiedattreader.is_unified: boolean; @@ -635,8 +635,9 @@ Unit raarmgas; will generate buggy code. Allow it only for explicit typecasting } if hasdot and (not oper.hastype) and - (tabstractnormalvarsym(oper.opr.localsym).owner.symtabletype=parasymtable) and - (current_procinfo.procdef.proccalloption<>pocall_register) then + (oper.opr.localsym.typ=paravarsym) and + ((tparavarsym(oper.opr.localsym).paraloc[calleeside].location^.loc<>LOC_REGISTER) or + not paramanager.push_addr_param(oper.opr.localsym.varspez,oper.opr.localsym.vardef,current_procinfo.procdef.proccalloption)) then Message(asmr_e_cannot_access_field_directly_for_parameters); inc(oper.opr.localsymofs,l) end; diff --git a/compiler/avr/raavrgas.pas b/compiler/avr/raavrgas.pas index 21f8c1ff4e..75b8efd773 100644 --- a/compiler/avr/raavrgas.pas +++ b/compiler/avr/raavrgas.pas @@ -59,7 +59,7 @@ Unit raavrgas; procinfo, itcpugas, rabase,rautils, - cgbase,cgutils,cgobj + cgbase,cgutils,cgobj,paramgr ; @@ -259,8 +259,9 @@ Unit raavrgas; will generate buggy code. Allow it only for explicit typecasting } if hasdot and (not oper.hastype) and - (tabstractnormalvarsym(oper.opr.localsym).owner.symtabletype=parasymtable) and - (current_procinfo.procdef.proccalloption<>pocall_register) then + (oper.opr.localsym.typ=paravarsym) and + ((tparavarsym(oper.opr.localsym).paraloc[calleeside].location^.loc<>LOC_REGISTER) or + not paramanager.push_addr_param(oper.opr.localsym.varspez,oper.opr.localsym.vardef,current_procinfo.procdef.proccalloption)) then Message(asmr_e_cannot_access_field_directly_for_parameters); inc(oper.opr.localsymofs,l) end; diff --git a/compiler/mips/racpugas.pas b/compiler/mips/racpugas.pas index 8b4f9a2a9f..93847a0520 100644 --- a/compiler/mips/racpugas.pas +++ b/compiler/mips/racpugas.pas @@ -60,7 +60,7 @@ Interface rabase, rgbase, itcpugas, - cgobj + cgobj,paramgr ; @@ -168,8 +168,9 @@ Interface will generate buggy code. Allow it only for explicit typecasting } if hasdot and (not oper.hastype) and - (tabstractnormalvarsym(oper.opr.localsym).owner.symtabletype=parasymtable) and - (current_procinfo.procdef.proccalloption<>pocall_register) then + (oper.opr.localsym.typ=paravarsym) and + ((tparavarsym(oper.opr.localsym).paraloc[calleeside].location^.loc<>LOC_REGISTER) or + not paramanager.push_addr_param(oper.opr.localsym.varspez,oper.opr.localsym.vardef,current_procinfo.procdef.proccalloption)) then Message(asmr_e_cannot_access_field_directly_for_parameters); inc(oper.opr.localsymofs,l) end; diff --git a/compiler/powerpc/rappcgas.pas b/compiler/powerpc/rappcgas.pas index e0d6c1ccba..6e868c0c6a 100644 --- a/compiler/powerpc/rappcgas.pas +++ b/compiler/powerpc/rappcgas.pas @@ -56,7 +56,7 @@ Unit rappcgas; { parser } procinfo, rabase,rautils, - cgbase,cgobj,cgppc + cgbase,cgobj,cgppc,paramgr ; procedure tppcattreader.ReadSym(oper : tppcoperand); @@ -340,8 +340,9 @@ Unit rappcgas; will generate buggy code. Allow it only for explicit typecasting } if hasdot and (not oper.hastype) and - (tabstractvarsym(oper.opr.localsym).owner.symtabletype=parasymtable) and - (current_procinfo.procdef.proccalloption<>pocall_register) then + (oper.opr.localsym.typ=paravarsym) and + ((tparavarsym(oper.opr.localsym).paraloc[calleeside].location^.loc<>LOC_REGISTER) or + not paramanager.push_addr_param(oper.opr.localsym.varspez,oper.opr.localsym.vardef,current_procinfo.procdef.proccalloption)) then Message(asmr_e_cannot_access_field_directly_for_parameters); inc(oper.opr.localsymofs,l) end; diff --git a/compiler/powerpc64/rappcgas.pas b/compiler/powerpc64/rappcgas.pas index 6d29ee49fa..237ecd7531 100644 --- a/compiler/powerpc64/rappcgas.pas +++ b/compiler/powerpc64/rappcgas.pas @@ -58,7 +58,7 @@ uses { parser } procinfo, rabase, rautils, - cgbase, cgobj, cgppc + cgbase, cgobj, cgppc, paramgr ; procedure tppcattreader.ReadSym(oper: tppcoperand); @@ -350,9 +350,9 @@ var will generate buggy code. Allow it only for explicit typecasting } if hasdot and (not oper.hastype) and - (tabstractvarsym(oper.opr.localsym).owner.symtabletype = - parasymtable) and - (current_procinfo.procdef.proccalloption <> pocall_register) then + (oper.opr.localsym.typ=paravarsym) and + ((tparavarsym(oper.opr.localsym).paraloc[calleeside].location^.loc<>LOC_REGISTER) or + not paramanager.push_addr_param(oper.opr.localsym.varspez,oper.opr.localsym.vardef,current_procinfo.procdef.proccalloption)) then Message(asmr_e_cannot_access_field_directly_for_parameters); inc(oper.opr.localsymofs, l) end; diff --git a/compiler/raatt.pas b/compiler/raatt.pas index cfd107be5f..086534a7dd 100644 --- a/compiler/raatt.pas +++ b/compiler/raatt.pas @@ -1331,6 +1331,7 @@ unit raatt; { On entry actasmtoken should be equal to AS_DOT } var s : string; + hastypecast: boolean; Begin offset:=0; size:=0; @@ -1352,7 +1353,7 @@ unit raatt; break; end; end; - if not GetRecordOffsetSize(s,offset,size,mangledname,needvmtofs) then + if not GetRecordOffsetSize(s,offset,size,mangledname,needvmtofs,hastypecast) then Message(asmr_e_building_record_offset); end; diff --git a/compiler/rautils.pas b/compiler/rautils.pas index 9f48dfc185..61932a10af 100644 --- a/compiler/rautils.pas +++ b/compiler/rautils.pas @@ -173,7 +173,7 @@ Function EscapeToPascal(const s:string): string; ---------------------------------------------------------------------} procedure AsmSearchSym(const s:string;var srsym:tsym;var srsymtable:TSymtable); -Function GetRecordOffsetSize(s:string;Var Offset: aint;var Size:aint; var mangledname: string; needvmtofs: boolean):boolean; +Function GetRecordOffsetSize(s:string;Var Offset: aint;var Size:aint; var mangledname: string; needvmtofs: boolean; out hastypecast: boolean):boolean; Function SearchType(const hs:string;var size:aint): Boolean; Function SearchRecordType(const s:string): boolean; Function SearchIConstant(const s:string; var l:aint): boolean; @@ -1278,7 +1278,7 @@ Begin end; -Function GetRecordOffsetSize(s:string;Var Offset: aint;var Size:aint; var mangledname: string; needvmtofs: boolean):boolean; +Function GetRecordOffsetSize(s:string;Var Offset: aint;var Size:aint; var mangledname: string; needvmtofs: boolean; out hastypecast: boolean):boolean; { search and returns the offset and size of records/objects of the base } { with field name setup in field. } { returns FALSE if not found. } @@ -1296,6 +1296,7 @@ Begin Offset:=0; Size:=0; mangledname:=''; + hastypecast:=false; i:=pos('.',s); if i=0 then i:=255; @@ -1407,7 +1408,8 @@ Begin if assigned(sym) and (sym.typ=typesym) then begin size:=ttypesym(sym).typedef.size; - s:='' + s:=''; + hastypecast:=true; end; end; GetRecordOffsetSize:=(s=''); diff --git a/compiler/sparc/racpugas.pas b/compiler/sparc/racpugas.pas index 59fff03580..eb5d6c31bf 100644 --- a/compiler/sparc/racpugas.pas +++ b/compiler/sparc/racpugas.pas @@ -57,7 +57,7 @@ Interface scanner, procinfo, rabase,rautils, - cgobj + cgobj,paramgr ; @@ -221,8 +221,9 @@ Interface will generate buggy code. Allow it only for explicit typecasting } if hasdot and (not oper.hastype) and - (tabstractnormalvarsym(oper.opr.localsym).owner.symtabletype=parasymtable) and - (current_procinfo.procdef.proccalloption<>pocall_register) then + (oper.opr.localsym.typ=paravarsym) and + ((tparavarsym(oper.opr.localsym).paraloc[calleeside].location^.loc<>LOC_REGISTER) or + not paramanager.push_addr_param(oper.opr.localsym.varspez,oper.opr.localsym.vardef,current_procinfo.procdef.proccalloption)) then Message(asmr_e_cannot_access_field_directly_for_parameters); inc(oper.opr.localsymofs,l) end; diff --git a/compiler/x86/rax86att.pas b/compiler/x86/rax86att.pas index 80464b38c9..42ac2e473c 100644 --- a/compiler/x86/rax86att.pas +++ b/compiler/x86/rax86att.pas @@ -63,12 +63,12 @@ Implementation { aasm } aasmbase,aasmtai,aasmdata,aasmcpu, { symtable } - symconst, + symconst,symsym, { parser } scanner, procinfo, itcpugas, - rabase, + rabase,paramgr, cgbase ; @@ -460,8 +460,9 @@ Implementation will generate buggy code. Allow it only for explicit typecasting } if hasdot and (not oper.hastype) and - (oper.opr.localsym.owner.symtabletype=parasymtable) and - (current_procinfo.procdef.proccalloption<>pocall_register) then + (oper.opr.localsym.typ=paravarsym) and + ((tparavarsym(oper.opr.localsym).paraloc[calleeside].location^.loc<>LOC_REGISTER) or + not paramanager.push_addr_param(oper.opr.localsym.varspez,oper.opr.localsym.vardef,current_procinfo.procdef.proccalloption)) then Message(asmr_e_cannot_access_field_directly_for_parameters); inc(oper.opr.localsymofs,l); inc(oper.opr.localconstoffset,l); diff --git a/compiler/x86/rax86int.pas b/compiler/x86/rax86int.pas index 934d2f018c..0b519c0706 100644 --- a/compiler/x86/rax86int.pas +++ b/compiler/x86/rax86int.pas @@ -62,7 +62,7 @@ Unit Rax86int; procedure GetToken; function consume(t : tasmtoken):boolean; procedure RecoverConsume(allowcomma:boolean); - procedure BuildRecordOffsetSize(const expr: string;var offset:aint;var size:aint; var mangledname: string; needvmtofs: boolean); + procedure BuildRecordOffsetSize(const expr: string;var offset:aint;var size:aint; var mangledname: string; needvmtofs: boolean; out hastypecast: boolean); procedure BuildConstSymbolExpression(needofs,isref,startingminus:boolean;var value:aint;var asmsym:string;var asmsymtyp:TAsmsymtype;out isseg,is_farproc_entry:boolean); function BuildConstExpression:aint; function BuildRefConstExpression(startingminus:boolean=false):aint; @@ -91,7 +91,7 @@ Unit Rax86int; { register allocator } rabase,rautils,itx86int, { codegen } - cgbase,cgobj,procinfo + cgbase,cgobj,procinfo,paramgr ; type @@ -232,7 +232,6 @@ Unit Rax86int; if (getsupreg(actasmregister)=RS_DEFAULTFLAGS) and (getregtype(actasmregister)=getregtype(NR_DEFAULTFLAGS)) then actasmregister:=NR_NO; if (actasmregister=NR_NO) and - (current_procinfo.procdef.proccalloption=pocall_register) and (po_assembler in current_procinfo.procdef.procoptions) then begin entry:=current_procinfo.procdef.parast.Find(s); @@ -763,12 +762,13 @@ Unit Rax86int; { This routine builds up a record offset after a AS_DOT token is encountered. On entry actasmtoken should be equal to AS_DOT } - Procedure tx86intreader.BuildRecordOffsetSize(const expr: string;var offset:aint;var size:aint; var mangledname: string; needvmtofs: boolean); + Procedure tx86intreader.BuildRecordOffsetSize(const expr: string;var offset:aint;var size:aint; var mangledname: string; needvmtofs: boolean; out hastypecast: boolean); var s: string; Begin offset:=0; size:=0; + hastypecast:=false; s:=expr; while (actasmtoken=AS_DOT) do begin @@ -785,7 +785,7 @@ Unit Rax86int; break; end; end; - if not GetRecordOffsetSize(s,offset,size,mangledname,needvmtofs) then + if not GetRecordOffsetSize(s,offset,size,mangledname,needvmtofs,hastypecast) then Message(asmr_e_building_record_offset); end; @@ -804,6 +804,7 @@ Unit Rax86int; def : tdef; sym : tsym; srsymtable : TSymtable; + hastypecast : boolean; Begin { reset } value:=0; @@ -943,10 +944,12 @@ Unit Rax86int; Consume(AS_ID); if actasmtoken=AS_DOT then begin - BuildRecordOffsetSize(tempstr,k,l,mangledname,false); + BuildRecordOffsetSize(tempstr,k,l,mangledname,false,hastypecast); if mangledname<>'' then { procsym } Message(asmr_e_wrong_sym_type); + if hastypecast then + end else begin @@ -1114,7 +1117,7 @@ Unit Rax86int; (sym.typ = fieldvarsym) and not(sp_static in sym.symoptions)) then begin - BuildRecordOffsetSize(tempstr,l,k,hs,needvmtofs); + BuildRecordOffsetSize(tempstr,l,k,hs,needvmtofs,hastypecast); if hs <> '' then hssymtyp:=AT_FUNCTION else @@ -1224,7 +1227,8 @@ Unit Rax86int; GotPlus,Negative : boolean; hl : tasmlabel; isseg: boolean; - is_farproc_entry : boolean; + is_farproc_entry, + hastypecast: boolean; Begin Consume(AS_LBRACKET); if not(oper.opr.typ in [OPR_LOCAL,OPR_REFERENCE]) then @@ -1342,7 +1346,7 @@ Unit Rax86int; { record.field ? } if actasmtoken=AS_DOT then begin - BuildRecordOffsetSize(tempstr,l,k,hs,false); + BuildRecordOffsetSize(tempstr,l,k,hs,false,hastypecast); if (hs<>'') then Message(asmr_e_invalid_symbol_ref); case oper.opr.typ of @@ -1351,6 +1355,8 @@ Unit Rax86int; OPR_REFERENCE : inc(oper.opr.ref.offset,l); end; + if hastypecast then + oper.hastype:=true; oper.SetSize(k,false); end; if GotOffset then @@ -1701,6 +1707,7 @@ Unit Rax86int; hl : tasmlabel; toffset, tsize : aint; + hastypecast: boolean; begin expr:=''; repeat @@ -1708,11 +1715,13 @@ Unit Rax86int; begin if expr<>'' then begin - BuildRecordOffsetSize(expr,toffset,tsize,hs,false); + BuildRecordOffsetSize(expr,toffset,tsize,hs,false,hastypecast); if (oper.opr.typ<>OPR_NONE) and (hs<>'') then Message(asmr_e_wrong_sym_type); oper.SetSize(tsize,true); + if hastypecast then + oper.hastype:=true; { we have used the size of a field. Reset the typesize of the record } oper.typesize:=0; case oper.opr.typ of @@ -1722,8 +1731,9 @@ Unit Rax86int; will generate buggy code. Allow it only for explicit typecasting and when the parameter is in a register (delphi compatible) } if (not oper.hastype) and - (oper.opr.localsym.owner.symtabletype=parasymtable) and - (current_procinfo.procdef.proccalloption<>pocall_register) then + (oper.opr.localsym.typ=paravarsym) and + ((tparavarsym(oper.opr.localsym).paraloc[calleeside].location^.loc<>LOC_REGISTER) or + not paramanager.push_addr_param(oper.opr.localsym.varspez,oper.opr.localsym.vardef,current_procinfo.procdef.proccalloption)) then Message(asmr_e_cannot_access_field_directly_for_parameters); oper.opr.localforceref:=true;