diff --git a/packages/fcl-passrc/src/pasresolveeval.pas b/packages/fcl-passrc/src/pasresolveeval.pas index c570595277..847d909d79 100644 --- a/packages/fcl-passrc/src/pasresolveeval.pas +++ b/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); diff --git a/packages/fcl-passrc/src/pasresolver.pp b/packages/fcl-passrc/src/pasresolver.pp index 4ab775a5a3..ce62008175 100644 --- a/packages/fcl-passrc/src/pasresolver.pp +++ b/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); - ComputeBinaryExprRes(Bin,ResolvedEl,Flags,LeftResolved,RightResolved); + // 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); + + // ToDo: check operator overloading + ComputeBinaryExprRes(Bin,ResolvedEl,Flags,LeftResolved,RightResolved); + end; end; procedure TPasResolver.ComputeBinaryExprRes(Bin: TBinaryExpr; out