From 744facb7fc8766212704198d2ea5db42b376dea6 Mon Sep 17 00:00:00 2001 From: Jonas Maebe Date: Sun, 21 May 2017 20:17:15 +0000 Subject: [PATCH] * properly support accepting register parameters of assembler routines in the intel assembler reader: no longer parse them as register tokens, but as local operands that are later converted into registers. This ensures in particular that the type of the operand is set, which is necessary in case this operand later subscripted (as in tasm10a) git-svn-id: trunk@36288 - --- .gitattributes | 1 + compiler/rautils.pas | 74 +++++++++++++++++++++++++++++++++------ compiler/x86/rax86int.pas | 19 +++------- tests/test/tasm10a.pp | 41 ++++++++++++++++++++++ 4 files changed, 109 insertions(+), 26 deletions(-) create mode 100644 tests/test/tasm10a.pp diff --git a/.gitattributes b/.gitattributes index 8f11974467..77da069404 100644 --- a/.gitattributes +++ b/.gitattributes @@ -12099,6 +12099,7 @@ tests/test/tarrconstr6.pp svneol=native#text/pascal tests/test/tarrconstr7.pp svneol=native#text/pascal tests/test/tasm1.pp svneol=native#text/plain tests/test/tasm10.pp svneol=native#text/plain +tests/test/tasm10a.pp svneol=native#text/plain tests/test/tasm2.inc svneol=native#text/plain tests/test/tasm2.pp svneol=native#text/plain tests/test/tasm2a.pp svneol=native#text/plain diff --git a/compiler/rautils.pas b/compiler/rautils.pas index 61932a10af..5d8cf13af4 100644 --- a/compiler/rautils.pas +++ b/compiler/rautils.pas @@ -94,6 +94,9 @@ type Function SetupVar(const s:string;GetOffset : boolean): Boolean; Function CheckOperand: boolean; virtual; Procedure InitRef; + Procedure InitRefConvertLocal; + protected + Procedure InitRefError; end; TCOperand = class of TOperand; @@ -177,7 +180,7 @@ Function GetRecordOffsetSize(s:string;Var Offset: aint;var Size:aint; var mangle Function SearchType(const hs:string;var size:aint): Boolean; Function SearchRecordType(const s:string): boolean; Function SearchIConstant(const s:string; var l:aint): boolean; - +Function AsmRegisterPara(sym: tabstractnormalvarsym): boolean; {--------------------------------------------------------------------- Instruction generation routines @@ -1030,16 +1033,56 @@ Begin opr.ref_farproc_entry:=hsym_farprocentry; end; else - begin - Message(asmr_e_invalid_operand_type); - { Recover } - opr.typ:=OPR_REFERENCE; - opr.varsize:=0; - opr.constoffset:=0; - opr.ref_farproc_entry:=false; - Fillchar(opr.ref,sizeof(treference),0); - end; - end; + InitRefError; + end; +end; + +procedure TOperand.InitRefConvertLocal; +var + localvarsize,localconstoffset: asizeint; + localsym:tabstractnormalvarsym; + localsymofs:aint; + localindexreg:tregister; + localscale:byte; +begin + if opr.typ=OPR_LOCAL then + begin + if AsmRegisterPara(opr.localsym) and + not opr.localgetoffset then + begin + localvarsize:=opr.localvarsize; + localconstoffset:=opr.localconstoffset; + localsym:=opr.localsym; + localsymofs:=opr.localsymofs; + localindexreg:=opr.localindexreg; + localscale:=opr.localscale;; + opr.typ:=OPR_REFERENCE; + hasvar:=false; + Fillchar(opr.ref,sizeof(treference),0); + opr.varsize:=localvarsize; + opr.constoffset:=localconstoffset; + opr.ref_farproc_entry:=false; + opr.ref.base:=tparavarsym(localsym).paraloc[calleeside].Location^.register; + opr.ref.offset:=localsymofs; + opr.ref.index:=localindexreg; + opr.ref.scalefactor:=localscale; + end + else + InitRefError; + end + else + InitRef; +end; + +procedure TOperand.InitRefError; +begin + Message(asmr_e_invalid_operand_type); + { Recover } + opr.typ:=OPR_REFERENCE; + opr.varsize:=0; + opr.constoffset:=0; + opr.ref_farproc_entry:=false; + Fillchar(opr.ref,sizeof(treference),0); end; Function TOperand.CheckOperand: boolean; @@ -1278,6 +1321,15 @@ Begin end; +function AsmRegisterPara(sym: tabstractnormalvarsym): boolean; +begin + result:= + (po_assembler in current_procinfo.procdef.procoptions) and + (sym.typ=paravarsym) and + (tparavarsym(sym).paraloc[calleeside].Location^.Loc=LOC_REGISTER); +end; + + 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. } diff --git a/compiler/x86/rax86int.pas b/compiler/x86/rax86int.pas index c88a9749c3..ffced5c98e 100644 --- a/compiler/x86/rax86int.pas +++ b/compiler/x86/rax86int.pas @@ -229,24 +229,12 @@ Unit Rax86int; function tx86intreader.is_register(const s:string):boolean; - var - entry: TSymEntry; begin is_register:=false; actasmregister:=masm_regnum_search(lower(s)); { don't acceps "flags" as register name in an instruction } if (getsupreg(actasmregister)=RS_DEFAULTFLAGS) and (getregtype(actasmregister)=getregtype(NR_DEFAULTFLAGS)) then actasmregister:=NR_NO; - if (actasmregister=NR_NO) and - (po_assembler in current_procinfo.procdef.procoptions) then - begin - entry:=current_procinfo.procdef.parast.Find(s); - if assigned(entry) and - (entry.typ=paravarsym) and - assigned(tparavarsym(entry).paraloc[calleeside].Location) and - (tparavarsym(entry).paraloc[calleeside].Location^.Loc=LOC_REGISTER) then - actasmregister:=tparavarsym(entry).paraloc[calleeside].Location^.register; - end; if actasmregister<>NR_NO then begin is_register:=true; @@ -1320,9 +1308,10 @@ Unit Rax86int; else if oper.SetupVar(tempstr,GotOffset) then begin - { force OPR_LOCAL to be a reference } - if oper.opr.typ=OPR_LOCAL then - oper.opr.localforceref:=true + { convert OPR_LOCAL register para into a reference base } + if (oper.opr.typ=OPR_LOCAL) and + AsmRegisterPara(oper.opr.localsym) then + oper.InitRefConvertLocal else begin {$ifdef x86_64} diff --git a/tests/test/tasm10a.pp b/tests/test/tasm10a.pp new file mode 100644 index 0000000000..723eccf721 --- /dev/null +++ b/tests/test/tasm10a.pp @@ -0,0 +1,41 @@ +{ %cpu=x86_64 } + +program asmclass; +{$mode delphiunicode} +{$asmmode intel} +type + TMyClass = class + public + Data: longint; + function AsmToClass: longint; ms_abi_default; + end; + +function TMyClass.AsmToClass: longint; ms_abi_default; +asm + mov RAX, Self.Data // Error: Can't access fields directly for parameters +end; + +function AsmToClassProc(Inst: TMyClass): longint; ms_abi_default; +asm + mov RAX, Inst.Data // Error: Can't access fields directly for parameters +end; + +function AsmToClassProc2(Inst: TMyClass): pointer; ms_abi_default; +asm + mov RAX, qword ptr [Inst] +end; + +var + C: TMyClass; +begin + C := TMyClass.Create; + c.data:=123548; + if C.AsmToClass<>123548 then + halt(1); + if AsmToClassProc(C)<>123548 then + halt(2); + + if AsmToClassProc2(C)<>ppointer(c)^ then + halt(3); + C.Free; +end.