Ver código fonte

* fixed calling qualified methods in assembler + tests for ppc/ppc64/
i386/x86_64

git-svn-id: trunk@6112 -

Jonas Maebe 18 anos atrás
pai
commit
302a2a3ec2

+ 2 - 0
.gitattributes

@@ -7968,6 +7968,8 @@ tests/webtbs/tw7803.pp svneol=native#text/plain
 tests/webtbs/tw7817a.pp svneol=native#text/plain
 tests/webtbs/tw7817b.pp svneol=native#text/plain
 tests/webtbs/tw7847.pp svneol=native#text/plain
+tests/webtbs/tw7851.pp svneol=native#text/plain
+tests/webtbs/tw7851a.pp svneol=native#text/plain
 tests/webtbs/tw7963.pp svneol=native#text/plain
 tests/webtbs/tw7975.pp svneol=native#text/plain
 tests/webtbs/tw7975a.pp svneol=native#text/plain

+ 20 - 4
compiler/arm/raarmgas.pas

@@ -120,7 +120,7 @@ Unit raarmgas;
 
     procedure tarmattreader.ReadSym(oper : tarmoperand);
       var
-         tempstr : string;
+         tempstr, mangledname : string;
          typesize,l,k : longint;
       begin
         tempstr:=actasmpattern;
@@ -142,7 +142,9 @@ Unit raarmgas;
         { record.field ? }
         if actasmtoken=AS_DOT then
          begin
-           BuildRecordOffsetSize(tempstr,l,k);
+           BuildRecordOffsetSize(tempstr,l,k,mangledname);
+           if (mangledname<>'') then
+             Message(asmr_e_invalid_reference_syntax);
            inc(oper.opr.ref.offset,l);
          end;
       end;
@@ -293,6 +295,7 @@ Unit raarmgas;
 
         procedure MaybeRecordOffset;
           var
+            mangledname: string;
             hasdot  : boolean;
             l,
             toffset,
@@ -306,7 +309,10 @@ Unit raarmgas;
               begin
                 if expr<>'' then
                   begin
-                    BuildRecordOffsetSize(expr,toffset,tsize);
+                    BuildRecordOffsetSize(expr,toffset,tsize,mangledname);
+                    if (oper.opr.typ<>OPR_CONSTANT) and
+                       (mangledname<>'') then
+                      Message(asmr_e_wrong_sym_type);
                     inc(l,toffset);
                     oper.SetSize(tsize,true);
                   end;
@@ -328,7 +334,17 @@ Unit raarmgas;
               OPR_CONSTANT :
                 inc(oper.opr.val,l);
               OPR_REFERENCE :
-                inc(oper.opr.ref.offset,l);
+                if (mangledname<>'') then
+                  begin
+                    if (oper.opr.val<>0) then
+                      Message(asmr_e_wrong_sym_type);
+                    oper.opr.typ:=OPR_SYMBOL;
+                    oper.opr.symbol:=current_asmdata.RefAsmSymbol(mangledname);
+                  end
+                else
+                  inc(oper.opr.val,l);
+              OPR_SYMBOL:
+                Message(asmr_e_invalid_symbol_ref);
               else
                 internalerror(200309221);
             end;

+ 20 - 4
compiler/powerpc/rappcgas.pas

@@ -61,7 +61,7 @@ Unit rappcgas;
 
     procedure tppcattreader.ReadSym(oper : tppcoperand);
       var
-         tempstr : string;
+         tempstr, mangledname : string;
          typesize,l,k : aint;
       begin
         tempstr:=actasmpattern;
@@ -83,7 +83,9 @@ Unit rappcgas;
         { record.field ? }
         if actasmtoken=AS_DOT then
          begin
-           BuildRecordOffsetSize(tempstr,l,k);
+           BuildRecordOffsetSize(tempstr,l,k,mangledname);
+           if (mangledname<>'') then
+             Message(asmr_e_invalid_reference_syntax);
            inc(oper.opr.ref.offset,l);
          end;
       end;
@@ -260,6 +262,7 @@ Unit rappcgas;
 
         procedure MaybeRecordOffset;
           var
+            mangledname: string;
             hasdot  : boolean;
             l,
             toffset,
@@ -273,7 +276,10 @@ Unit rappcgas;
               begin
                 if expr<>'' then
                   begin
-                    BuildRecordOffsetSize(expr,toffset,tsize);
+                    BuildRecordOffsetSize(expr,toffset,tsize,mangledname);
+                    if (oper.opr.typ<>OPR_CONSTANT) and
+                       (mangledname<>'') then
+                      Message(asmr_e_wrong_sym_type);
                     inc(l,toffset);
                     oper.SetSize(tsize,true);
                   end;
@@ -293,9 +299,19 @@ Unit rappcgas;
                   inc(oper.opr.localsymofs,l)
                 end;
               OPR_CONSTANT :
-                inc(oper.opr.val,l);
+                if (mangledname<>'') then
+                  begin
+                    if (oper.opr.val<>0) then
+                      Message(asmr_e_wrong_sym_type);
+                    oper.opr.typ:=OPR_SYMBOL;
+                    oper.opr.symbol:=current_asmdata.RefAsmSymbol(mangledname);
+                  end
+                else
+                  inc(oper.opr.val,l);
               OPR_REFERENCE :
                 inc(oper.opr.ref.offset,l);
+              OPR_SYMBOL:
+                Message(asmr_e_invalid_symbol_ref);
               else
                 internalerror(200309221);
             end;

+ 20 - 4
compiler/powerpc64/rappcgas.pas

@@ -61,7 +61,7 @@ uses
 
 procedure tppcattreader.ReadSym(oper: tppcoperand);
 var
-  tempstr: string;
+  tempstr, mangledname: string;
   typesize, l, k: aint;
 begin
   tempstr := actasmpattern;
@@ -82,7 +82,9 @@ begin
   { record.field ? }
   if actasmtoken = AS_DOT then
   begin
-    BuildRecordOffsetSize(tempstr, l, k);
+    BuildRecordOffsetSize(tempstr, l, k, mangledname);
+    if (mangledname<>'') then
+      Message(asmr_e_invalid_reference_syntax);
     inc(oper.opr.ref.offset, l);
   end;
 end;
@@ -265,6 +267,7 @@ var
 
   procedure MaybeRecordOffset;
   var
+    mangledname : string;
     hasdot: boolean;
     l,
       toffset,
@@ -278,7 +281,10 @@ var
     begin
       if expr <> '' then
       begin
-        BuildRecordOffsetSize(expr, toffset, tsize);
+        BuildRecordOffsetSize(expr, toffset, tsize, mangledname);
+        if (oper.opr.typ<>OPR_CONSTANT) and
+           (mangledname<>'') then
+          Message(asmr_e_wrong_sym_type);
         inc(l, toffset);
         oper.SetSize(tsize, true);
       end;
@@ -299,9 +305,19 @@ var
           inc(oper.opr.localsymofs, l)
         end;
       OPR_CONSTANT:
-        inc(oper.opr.val, l);
+        if (mangledname<>'') then
+          begin
+            if (oper.opr.val<>0) then
+              Message(asmr_e_wrong_sym_type);
+            oper.opr.typ:=OPR_SYMBOL;
+            oper.opr.symbol:=current_asmdata.RefAsmSymbol(mangledname);
+          end
+        else
+          inc(oper.opr.val,l);
       OPR_REFERENCE:
         inc(oper.opr.ref.offset, l);
+      OPR_SYMBOL:
+        Message(asmr_e_invalid_symbol_ref);
     else
       internalerror(200309221);
     end;

+ 17 - 8
compiler/raatt.pas

@@ -86,7 +86,7 @@ unit raatt;
          procedure BuildConstantOperand(oper : toperand);
          procedure BuildRealConstant(typ : tfloattype);
          procedure BuildStringConstant(asciiz: boolean);
-         procedure BuildRecordOffsetSize(const expr: string;var offset:aint;var size:aint);
+         procedure BuildRecordOffsetSize(const expr: string;var offset:aint;var size:aint; var mangledname: string);
          procedure BuildConstSymbolExpression(allowref,betweenbracket,needofs:boolean;var value:aint;var asmsym:string;var asmsymtyp:TAsmsymtype);
          function BuildConstExpression(allowref,betweenbracket:boolean): aint;
          function Assemble: tlinkedlist;override;
@@ -1165,7 +1165,7 @@ unit raatt;
                                Parsing Helpers
 *****************************************************************************}
 
-    Procedure tattreader.BuildRecordOffsetSize(const expr: string;var offset:aint;var size:aint);
+    Procedure tattreader.BuildRecordOffsetSize(const expr: string;var offset:aint;var size:aint; var mangledname: string);
       { Description: This routine builds up a record offset after a AS_DOT }
       { token is encountered.                                              }
       { On entry actasmtoken should be equal to AS_DOT                     }
@@ -1186,7 +1186,7 @@ unit raatt;
               break;
             end;
          end;
-        if not GetRecordOffsetSize(s,offset,size) then
+        if not GetRecordOffsetSize(s,offset,size,mangledname) then
          Message(asmr_e_building_record_offset);
       end;
 
@@ -1194,7 +1194,7 @@ unit raatt;
     procedure tattreader.BuildConstSymbolExpression(allowref,betweenbracket,needofs:boolean;var value:aint;var asmsym:string;var asmsymtyp:TAsmsymtype);
       var
         hssymtyp : TAsmSymType;
-        hs,tempstr,expr : string;
+        hs,tempstr,expr,mangledname : string;
         parenlevel : longint;
         l,k : aint;
         errorflag : boolean;
@@ -1340,7 +1340,11 @@ unit raatt;
                    tempstr:=actasmpattern;
                    Consume(AS_ID);
                    if actasmtoken=AS_DOT then
-                    BuildRecordOffsetSize(tempstr,k,l)
+                    begin
+                      BuildRecordOffsetSize(tempstr,k,l,mangledname);
+                      if mangledname<>'' then
+                        Message(asmr_e_wrong_sym_type);
+                    end
                    else
                     begin
                       searchsym(tempstr,sym,srsymtable);
@@ -1443,9 +1447,14 @@ unit raatt;
                     end;
                    if actasmtoken=AS_DOT then
                     begin
-                      BuildRecordOffsetSize(tempstr,l,k);
-                      str(l, tempstr);
-                      expr:=expr + tempstr;
+                      BuildRecordOffsetSize(tempstr,l,k,hs);
+                      if (hs<>'') then
+                        hssymtyp:=AT_FUNCTION
+                      else
+                        begin
+                          str(l, tempstr);
+                          expr:=expr + tempstr;
+                        end
                     end
                    else
                     begin

+ 12 - 2
compiler/rautils.pas

@@ -184,7 +184,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):boolean;
+Function GetRecordOffsetSize(s:string;Var Offset: aint;var Size:aint; var mangledname: string):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;
@@ -1259,7 +1259,7 @@ Begin
 end;
 
 
-Function GetRecordOffsetSize(s:string;Var Offset: aint;var Size:aint):boolean;
+Function GetRecordOffsetSize(s:string;Var Offset: aint;var Size:aint; var mangledname: string):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.                                  }
@@ -1275,6 +1275,7 @@ Begin
   GetRecordOffsetSize:=FALSE;
   Offset:=0;
   Size:=0;
+  mangledname:='';
   i:=pos('.',s);
   if i=0 then
    i:=255;
@@ -1348,6 +1349,15 @@ Begin
                  st:=tobjectdef(vardef).symtable;
              end;
            end;
+       procsym:
+         begin
+           st:=nil;
+           if Tprocsym(sym).ProcdefList.Count>1 then
+             Message(asmr_w_calling_overload_func);
+           mangledname:=tprocdef(tprocsym(sym).ProcdefList[0]).mangledname;
+           GetRecordOffsetSize:=(s='');
+           exit;
+         end;
      end;
    end;
    { Support Field.Type as typecasting }

+ 20 - 4
compiler/sparc/racpugas.pas

@@ -63,7 +63,7 @@ Interface
 
     procedure TSparcReader.ReadSym(oper : tSparcoperand);
       var
-         tempstr : string;
+         tempstr, mangledname : string;
          typesize,l,k : aint;
       begin
         tempstr:=actasmpattern;
@@ -85,7 +85,9 @@ Interface
         { record.field ? }
         if actasmtoken=AS_DOT then
           begin
-            BuildRecordOffsetSize(tempstr,l,k);
+            BuildRecordOffsetSize(tempstr,l,k,mangledname);
+           if (mangledname<>'') then
+             Message(asmr_e_invalid_reference_syntax);
             inc(oper.opr.ref.offset,l);
           end;
       end;
@@ -236,6 +238,7 @@ Interface
 
         procedure MaybeRecordOffset;
           var
+            mangledname: string;
             hasdot  : boolean;
             l,
             toffset,
@@ -249,7 +252,10 @@ Interface
               begin
                 if expr<>'' then
                   begin
-                    BuildRecordOffsetSize(expr,toffset,tsize);
+                    BuildRecordOffsetSize(expr,toffset,tsize,mangledname);
+                    if (oper.opr.typ<>OPR_CONSTANT) and
+                       (mangledname<>'') then
+                      Message(asmr_e_wrong_sym_type);
                     inc(l,toffset);
                     oper.SetSize(tsize,true);
                   end;
@@ -269,9 +275,19 @@ Interface
                   inc(oper.opr.localsymofs,l)
                 end;
               OPR_CONSTANT :
-                inc(oper.opr.val,l);
+                if (mangledname<>'') then
+                  begin
+                    if (oper.opr.val<>0) then
+                      Message(asmr_e_wrong_sym_type);
+                    oper.opr.typ:=OPR_SYMBOL;
+                    oper.opr.symbol:=current_asmdata.RefAsmSymbol(mangledname);
+                  end
+                else
+                  inc(oper.opr.val,l);
               OPR_REFERENCE :
                 inc(oper.opr.ref.offset,l);
+              OPR_SYMBOL:
+                Message(asmr_e_invalid_symbol_ref);
               else
                 internalerror(200309221);
             end;

+ 21 - 3
compiler/x86/rax86att.pas

@@ -284,6 +284,7 @@ Implementation
 
         procedure MaybeRecordOffset;
           var
+            mangledname: string;
             hasdot  : boolean;
             l,
             toffset,
@@ -297,7 +298,10 @@ Implementation
              begin
                if expr<>'' then
                  begin
-                   BuildRecordOffsetSize(expr,toffset,tsize);
+                   BuildRecordOffsetSize(expr,toffset,tsize,mangledname);
+                   if (oper.opr.typ<>OPR_CONSTANT) and
+                      (mangledname<>'') then
+                    Message(asmr_e_wrong_sym_type);
                    inc(l,toffset);
                    oper.SetSize(tsize,true);
                  end;
@@ -317,9 +321,19 @@ Implementation
                   inc(oper.opr.localsymofs,l)
                 end;
               OPR_CONSTANT :
-                inc(oper.opr.val,l);
+                if (mangledname<>'') then
+                  begin
+                    if (oper.opr.val<>0) then
+                      Message(asmr_e_wrong_sym_type);
+                    oper.opr.typ:=OPR_SYMBOL;
+                    oper.opr.symbol:=current_asmdata.RefAsmSymbol(mangledname);
+                  end
+                else
+                  inc(oper.opr.val,l);
               OPR_REFERENCE :
                 inc(oper.opr.ref.offset,l);
+              OPR_SYMBOL:
+                Message(asmr_e_invalid_symbol_ref);
               else
                 internalerror(200309221);
             end;
@@ -334,6 +348,8 @@ Implementation
         function MaybeBuildReference:boolean;
           { Try to create a reference, if not a reference is found then false
             is returned }
+          var
+            mangledname: string;
           begin
             MaybeBuildReference:=true;
             case actasmtoken of
@@ -370,7 +386,9 @@ Implementation
                   { record.field ? }
                   if actasmtoken=AS_DOT then
                    begin
-                     BuildRecordOffsetSize(tempstr,l,k);
+                     BuildRecordOffsetSize(tempstr,l,k,mangledname);
+                     if (mangledname<>'') then
+                       Message(asmr_e_invalid_reference_syntax);
                      inc(oper.opr.ref.offset,l);
                    end;
                   if actasmtoken=AS_AT then

+ 40 - 14
compiler/x86/rax86int.pas

@@ -61,7 +61,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);
+         procedure BuildRecordOffsetSize(const expr: string;var offset:aint;var size:aint; var mangledname: string);
          procedure BuildConstSymbolExpression(needofs,isref:boolean;var value:aint;var asmsym:string;var asmsymtyp:TAsmsymtype);
          function BuildConstExpression:aint;
          function BuildRefConstExpression:aint;
@@ -706,9 +706,9 @@ 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);
+    Procedure tx86intreader.BuildRecordOffsetSize(const expr: string;var offset:aint;var size:aint; var mangledname: string);
       var
-        s : string;
+        s: string;
       Begin
         offset:=0;
         size:=0;
@@ -728,14 +728,14 @@ Unit Rax86int;
               break;
             end;
          end;
-        if not GetRecordOffsetSize(s,offset,size) then
+        if not GetRecordOffsetSize(s,offset,size,mangledname) then
           Message(asmr_e_building_record_offset);
       end;
 
 
     Procedure tx86intreader.BuildConstSymbolExpression(needofs,isref:boolean;var value:aint;var asmsym:string;var asmsymtyp:TAsmsymtype);
       var
-        tempstr,expr,hs : string;
+        tempstr,expr,hs,mangledname : string;
         parenlevel : longint;
         l,k : aint;
         hasparen,
@@ -865,7 +865,12 @@ Unit Rax86int;
                    tempstr:=actasmpattern;
                    Consume(AS_ID);
                    if actasmtoken=AS_DOT then
-                    BuildRecordOffsetSize(tempstr,k,l)
+                     begin
+                       BuildRecordOffsetSize(tempstr,k,l,mangledname);
+                       if mangledname<>'' then
+                         { procsym }
+                         Message(asmr_e_wrong_sym_type);
+                     end                         
                    else
                     begin
                       searchsym(tempstr,sym,srsymtable);
@@ -1011,9 +1016,14 @@ Unit Rax86int;
                     end;
                    if actasmtoken=AS_DOT then
                     begin
-                      BuildRecordOffsetSize(tempstr,l,k);
-                      str(l, tempstr);
-                      expr:=expr + tempstr;
+                      BuildRecordOffsetSize(tempstr,l,k,hs);
+                      if hs <> '' then
+                        hssymtyp:=AT_FUNCTION
+                      else
+                        begin
+                          str(l, tempstr);
+                          expr:=expr + tempstr;
+                        end
                     end
                    else
                     begin
@@ -1200,7 +1210,9 @@ Unit Rax86int;
                    { record.field ? }
                    if actasmtoken=AS_DOT then
                     begin
-                      BuildRecordOffsetSize(tempstr,l,k);
+                      BuildRecordOffsetSize(tempstr,l,k,hs);
+                      if (hs<>'') then
+                        Message(asmr_e_invalid_symbol_ref);
                       case oper.opr.typ of
                         OPR_LOCAL :
                           inc(oper.opr.localsymofs,l);
@@ -1504,7 +1516,8 @@ Unit Rax86int;
         end;
 
       var
-        expr    : string;
+        expr,
+        hs      : string;
         tempreg : tregister;
         l       : aint;
         hl      : tasmlabel;
@@ -1517,7 +1530,10 @@ Unit Rax86int;
             begin
               if expr<>'' then
                 begin
-                  BuildRecordOffsetSize(expr,toffset,tsize);
+                  BuildRecordOffsetSize(expr,toffset,tsize, hs);
+                  if (oper.opr.typ<>OPR_NONE) and
+                     (hs<>'') then
+                    Message(asmr_e_wrong_sym_type);
                   oper.SetSize(tsize,true);
                   { we have used the size of a field. Reset the typesize of the record }
                   oper.typesize:=0;
@@ -1539,9 +1555,19 @@ Unit Rax86int;
                       inc(oper.opr.ref.offset,toffset);
                     OPR_NONE :
                       begin
-                        oper.opr.typ:=OPR_CONSTANT;
-                        oper.opr.val:=toffset;
+                        if (hs <> '') then
+                          begin
+                            oper.opr.typ:=OPR_SYMBOL;
+                            oper.opr.symbol:=current_asmdata.RefAsmSymbol(hs);
+                          end
+                        else
+                          begin
+                            oper.opr.typ:=OPR_CONSTANT;
+                            oper.opr.val:=toffset;
+                          end;
                       end;
+                    OPR_SYMBOL:
+                      Message(asmr_e_invalid_symbol_ref);
                     else
                       internalerror(200309222);
                   end;

+ 51 - 0
tests/webtbs/tw7851.pp

@@ -0,0 +1,51 @@
+{ %cpu=i386,x86_64 }
+
+program AsmCrash;
+
+{$IFDEF FPC}
+  {$mode delphi}
+{$ENDIF}
+
+uses
+  sysutils;
+
+type
+  TMyRecord = record
+    rField: Integer;
+  end;
+
+  TMyObject = class
+  private
+    oField: TMyRecord;
+  public
+    procedure Test;
+    procedure Test2;
+  end;
+
+{ TMyObject }
+
+var
+  l: cardinal;
+
+procedure TMyObject.Test;
+asm
+  call TMyObject.Test2
+end;
+
+procedure TMyObject.Test2;
+begin
+  l := $cafebabe;
+end;
+
+begin
+  with TMyObject.Create do try
+    Test;
+    if l <> $cafebabe then
+      halt(1);
+    l := $deadbeef;
+  finally
+    Free;
+  end;
+  if l <> $deadbeef then
+    halt(2);
+end.

+ 65 - 0
tests/webtbs/tw7851a.pp

@@ -0,0 +1,65 @@
+{ %cpu=powerpc,powerpc64 }
+
+program AsmCrash;
+
+{$IFDEF FPC}
+  {$mode delphi}
+{$ENDIF}
+
+uses
+  sysutils;
+
+type
+  TMyRecord = record
+    rField: Integer;
+  end;
+
+  TMyObject = class
+  private
+    oField: TMyRecord;
+  public
+    procedure Test;
+    procedure Test2;
+  end;
+
+{ TMyObject }
+
+var
+  l: cardinal;
+
+procedure TMyObject.Test;
+var
+  retaddr: pointer;
+asm
+  mflr r0
+{$ifndef cpu64bit}
+  stw r0, retaddr
+{$else}
+  std r0, retaddr
+{$endif}
+  bl TMyObject.Test2
+{$ifndef cpu64bit}
+  lwz r0, retaddr
+{$else}
+  ld r0, retaddr
+{$endif}
+  mtlr r0
+end;
+
+procedure TMyObject.Test2;
+begin
+  l := $cafebabe;
+end;
+
+begin
+  with TMyObject.Create do try
+    Test;
+    if l <> $cafebabe then
+      halt(1);
+    l := $deadbeef;
+  finally
+    Free;
+  end;
+  if l <> $deadbeef then
+    halt(2);
+end.