Browse Source

* 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 -

Jonas Maebe 8 years ago
parent
commit
744facb7fc
4 changed files with 109 additions and 26 deletions
  1. 1 0
      .gitattributes
  2. 63 11
      compiler/rautils.pas
  3. 4 15
      compiler/x86/rax86int.pas
  4. 41 0
      tests/test/tasm10a.pp

+ 1 - 0
.gitattributes

@@ -12099,6 +12099,7 @@ tests/test/tarrconstr6.pp svneol=native#text/pascal
 tests/test/tarrconstr7.pp svneol=native#text/pascal
 tests/test/tarrconstr7.pp svneol=native#text/pascal
 tests/test/tasm1.pp svneol=native#text/plain
 tests/test/tasm1.pp svneol=native#text/plain
 tests/test/tasm10.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.inc svneol=native#text/plain
 tests/test/tasm2.pp svneol=native#text/plain
 tests/test/tasm2.pp svneol=native#text/plain
 tests/test/tasm2a.pp svneol=native#text/plain
 tests/test/tasm2a.pp svneol=native#text/plain

+ 63 - 11
compiler/rautils.pas

@@ -94,6 +94,9 @@ type
     Function  SetupVar(const s:string;GetOffset : boolean): Boolean;
     Function  SetupVar(const s:string;GetOffset : boolean): Boolean;
     Function  CheckOperand: boolean; virtual;
     Function  CheckOperand: boolean; virtual;
     Procedure InitRef;
     Procedure InitRef;
+    Procedure InitRefConvertLocal;
+   protected
+    Procedure InitRefError;
   end;
   end;
   TCOperand = class of TOperand;
   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 SearchType(const hs:string;var size:aint): Boolean;
 Function SearchRecordType(const s:string): boolean;
 Function SearchRecordType(const s:string): boolean;
 Function SearchIConstant(const s:string; var l:aint): boolean;
 Function SearchIConstant(const s:string; var l:aint): boolean;
-
+Function AsmRegisterPara(sym: tabstractnormalvarsym): boolean;
 
 
 {---------------------------------------------------------------------
 {---------------------------------------------------------------------
                   Instruction generation routines
                   Instruction generation routines
@@ -1030,16 +1033,56 @@ Begin
         opr.ref_farproc_entry:=hsym_farprocentry;
         opr.ref_farproc_entry:=hsym_farprocentry;
       end;
       end;
     else
     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;
 end;
 
 
 Function TOperand.CheckOperand: boolean;
 Function TOperand.CheckOperand: boolean;
@@ -1278,6 +1321,15 @@ Begin
 end;
 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;
 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 }
 { search and returns the offset and size of records/objects of the base }
 { with field name setup in field.                              }
 { with field name setup in field.                              }

+ 4 - 15
compiler/x86/rax86int.pas

@@ -229,24 +229,12 @@ Unit Rax86int;
 
 
 
 
     function tx86intreader.is_register(const s:string):boolean;
     function tx86intreader.is_register(const s:string):boolean;
-      var
-        entry: TSymEntry;
       begin
       begin
         is_register:=false;
         is_register:=false;
         actasmregister:=masm_regnum_search(lower(s));
         actasmregister:=masm_regnum_search(lower(s));
         { don't acceps "flags" as register name in an instruction }
         { don't acceps "flags" as register name in an instruction }
         if (getsupreg(actasmregister)=RS_DEFAULTFLAGS) and (getregtype(actasmregister)=getregtype(NR_DEFAULTFLAGS)) then
         if (getsupreg(actasmregister)=RS_DEFAULTFLAGS) and (getregtype(actasmregister)=getregtype(NR_DEFAULTFLAGS)) then
           actasmregister:=NR_NO;
           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
         if actasmregister<>NR_NO then
           begin
           begin
             is_register:=true;
             is_register:=true;
@@ -1320,9 +1308,10 @@ Unit Rax86int;
                    else
                    else
                     if oper.SetupVar(tempstr,GotOffset) then
                     if oper.SetupVar(tempstr,GotOffset) then
                      begin
                      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
                        else
                          begin
                          begin
 {$ifdef x86_64}
 {$ifdef x86_64}

+ 41 - 0
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.