Преглед изворни кода

* 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 година
родитељ
комит
744facb7fc
4 измењених фајлова са 109 додато и 26 уклоњено
  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/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

+ 63 - 11
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.                              }

+ 4 - 15
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}

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