mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-15 12:09:18 +02:00
* 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 -
This commit is contained in:
parent
61af0fb72d
commit
744facb7fc
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -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
|
||||
|
@ -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. }
|
||||
|
@ -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}
|
||||
|
41
tests/test/tasm10a.pp
Normal file
41
tests/test/tasm10a.pp
Normal file
@ -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.
|
Loading…
Reference in New Issue
Block a user