瀏覽代碼

fcl-passrc: resolver: resolve multi add expressions without stack

git-svn-id: trunk@49027 -
Mattias Gaertner 4 年之前
父節點
當前提交
786688eef6
共有 2 個文件被更改,包括 102 次插入5 次删除
  1. 48 0
      packages/fcl-passrc/src/pasresolveeval.pas
  2. 54 5
      packages/fcl-passrc/src/pasresolver.pp

+ 48 - 0
packages/fcl-passrc/src/pasresolveeval.pas

@@ -1524,6 +1524,8 @@ function TResExprEvaluator.EvalBinaryExpr(Expr: TBinaryExpr;
   Flags: TResEvalFlags): TResEvalValue;
 var
   LeftValue, RightValue: TResEvalValue;
+  Left: TPasExpr;
+  SubBin: TBinaryExpr;
 begin
   Result:=nil;
   if (Expr.Kind=pekBinary) and (Expr.OpCode=eopSubIdent) then
@@ -1534,6 +1536,52 @@ begin
   LeftValue:=nil;
   RightValue:=nil;
   try
+    if Expr.OpCode=eopAdd then
+      begin
+      // handle multi adds without stack
+      Left:=Expr.left;
+      while Left.ClassType=TBinaryExpr do
+        begin
+        SubBin:=TBinaryExpr(Left);
+        if SubBin.OpCode<>eopAdd then break;
+        Left:=SubBin.left;
+        end;
+      LeftValue:=Eval(Expr.left,Flags);
+      while LeftValue<>nil do
+        begin
+        SubBin:=TBinaryExpr(Left.Parent);
+        RightValue:=Eval(SubBin.right,Flags);
+        if RightValue=nil then exit;
+
+        if LeftValue.Kind=revkExternal then
+          begin
+          if [refConst,refConstExt]*Flags=[refConst] then
+            RaiseConstantExprExp(20210321205928,Expr.left);
+          Result:=LeftValue;
+          LeftValue:=nil;
+          exit;
+          end;
+        if RightValue.Kind=revkExternal then
+          begin
+          if [refConst,refConstExt]*Flags=[refConst] then
+            RaiseConstantExprExp(20210321205948,Expr.right);
+          Result:=RightValue;
+          RightValue:=nil;
+          exit;
+          end;
+
+        Result:=EvalBinaryAddExpr(SubBin,LeftValue,RightValue);
+        ReleaseEvalValue(LeftValue);
+        if SubBin=Expr then exit;
+
+        LeftValue:=Result;
+        Result:=nil;
+        Left:=SubBin;
+        end;
+
+      exit;
+      end;
+
     LeftValue:=Eval(Expr.left,Flags);
     if LeftValue=nil then exit;
     RightValue:=Eval(Expr.right,Flags);

+ 54 - 5
packages/fcl-passrc/src/pasresolver.pp

@@ -10585,6 +10585,9 @@ end;
 
 procedure TPasResolver.ResolveBinaryExpr(El: TBinaryExpr;
   Access: TResolvedRefAccess);
+var
+  Left, Next: TPasExpr;
+  Bin: TBinaryExpr;
 begin
   {$IFDEF VerbosePasResolver}
   //writeln('TPasResolver.ResolveBinaryExpr left=',GetObjName(El.left),' right=',GetObjName(El.right),' opcode=',OpcodeStrings[El.OpCode]);
@@ -10611,7 +10614,26 @@ begin
         RaiseNotYetImplemented(20160922163456,El);
         end;
     end;
-  eopAdd,
+  eopAdd:
+    begin
+    Left:=El.left;
+    while (Left.ClassType=TBinaryExpr) do
+      begin
+      Bin:=TBinaryExpr(Left);
+      if Bin.OpCode<>eopAdd then break;
+      Next:=TBinaryExpr(Left).left;
+      if Next.Parent<>Left then
+        RaiseNotYetImplemented(20210321201257,Left);
+      Left:=Next;
+      end;
+    ResolveExpr(Left,rraRead);
+    repeat
+      Bin:=TBinaryExpr(Left.Parent);
+      if Bin.right<>nil then
+        ResolveExpr(Bin.right,rraRead);
+      Left:=Bin;
+    until Left=El;
+    end;
   eopSubtract,
   eopMultiply,
   eopDivide,
@@ -12939,6 +12961,8 @@ procedure TPasResolver.ComputeBinaryExpr(Bin: TBinaryExpr; out
   StartEl: TPasElement);
 var
   LeftResolved, RightResolved: TPasResolverResult;
+  Left: TPasExpr;
+  SubBin: TBinaryExpr;
 begin
   if (Bin.OpCode=eopSubIdent)
   or ((Bin.OpCode=eopNone) and (Bin.left is TInheritedExpr)) then
@@ -12958,11 +12982,36 @@ begin
     exit;
     end;
 
-  ComputeElement(Bin.left,LeftResolved,Flags-[rcNoImplicitProc],StartEl);
-  ComputeElement(Bin.right,RightResolved,Flags-[rcNoImplicitProc],StartEl);
-  // ToDo: check operator overloading
+  if Bin.OpCode=eopAdd then
+    begin
+    // handle multi-adds without stack
+    Left:=Bin.left;
+    while Left.ClassType=TBinaryExpr do
+      begin
+      SubBin:=TBinaryExpr(Left);
+      if SubBin.OpCode<>eopAdd then break;
+      Left:=SubBin.left;
+      end;
+    // Left is now left-most of multi add
+    ComputeElement(Left,LeftResolved,Flags-[rcNoImplicitProc],StartEl);
+    repeat
+      SubBin:=TBinaryExpr(Left.Parent);
+      ComputeElement(Bin.right,RightResolved,Flags-[rcNoImplicitProc],StartEl);
+
+      // ToDo: check operator overloading
+      ComputeBinaryExprRes(SubBin,ResolvedEl,Flags,LeftResolved,RightResolved);
+      LeftResolved:=ResolvedEl;
+      Left:=SubBin;
+    until Left=Bin;
+    end
+  else
+    begin
+    ComputeElement(Bin.left,LeftResolved,Flags-[rcNoImplicitProc],StartEl);
+    ComputeElement(Bin.right,RightResolved,Flags-[rcNoImplicitProc],StartEl);
 
-  ComputeBinaryExprRes(Bin,ResolvedEl,Flags,LeftResolved,RightResolved);
+    // ToDo: check operator overloading
+    ComputeBinaryExprRes(Bin,ResolvedEl,Flags,LeftResolved,RightResolved);
+    end;
 end;
 
 procedure TPasResolver.ComputeBinaryExprRes(Bin: TBinaryExpr; out