diff options
author | mattias <mattias@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2019-02-28 21:57:28 +0000 |
---|---|---|
committer | mattias <mattias@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2019-02-28 21:57:28 +0000 |
commit | 098f5744e414d4e0af697b6235ce765225d71369 (patch) | |
tree | 35fb095b96bbda4ccdbf85cf65745b21e8a02e9a /packages/pastojs | |
parent | d4a98c301671e8784a48ab12413f8616f2566c0f (diff) | |
download | fpc-098f5744e414d4e0af697b6235ce765225d71369.tar.gz |
pastojs: and/or/xor with nativeint, warn nativeint shl/shr
git-svn-id: https://svn.freepascal.org/svn/fpc/trunk@41528 3ad0048d-3df7-0310-abae-a5850022a9f2
Diffstat (limited to 'packages/pastojs')
-rw-r--r-- | packages/pastojs/src/fppas2js.pp | 96 | ||||
-rw-r--r-- | packages/pastojs/tests/tcmodules.pas | 63 |
2 files changed, 118 insertions, 41 deletions
diff --git a/packages/pastojs/src/fppas2js.pp b/packages/pastojs/src/fppas2js.pp index 29e75a32ef..dd8ed8538d 100644 --- a/packages/pastojs/src/fppas2js.pp +++ b/packages/pastojs/src/fppas2js.pp @@ -520,6 +520,7 @@ const nCantCallExtBracketAccessor = 4025; nJSNewNotSupported = 4026; nHelperClassMethodForExtClassMustBeStatic = 4027; + nBitWiseOperationIs32Bit = 4028; // resourcestring patterns of messages resourcestring sPasElementNotSupported = 'Pascal element not supported: %s'; @@ -549,6 +550,7 @@ resourcestring sCantCallExtBracketAccessor = 'cannot call external bracket accessor, use a property instead'; sJSNewNotSupported = 'Pascal class does not support the "new" constructor'; sHelperClassMethodForExtClassMustBeStatic = 'Helper class method for external class must be static'; + sBitWiseOperationIs32Bit = 'Bitwise operation is 32-bit'; const ExtClassBracketAccessor = '[]'; // external name '[]' marks the array param getter/setter @@ -566,6 +568,9 @@ type pbifnArray_Static_Clone, pbifnAs, pbifnAsExt, + pbifnBitwiseNativeIntAnd, + pbifnBitwiseNativeIntOr, + pbifnBitwiseNativeIntXor, pbifnCheckMethodCall, pbifnCheckVersion, pbifnClassInstanceFree, @@ -725,6 +730,9 @@ const '$clone', 'as', // rtl.as 'asExt', // rtl.asExt + 'and', // pbifnBitwiseNativeIntAnd, + 'or', // pbifnBitwiseNativeIntOr, + 'xor', // pbifnBitwiseNativeIntXor, 'checkMethodCall', 'checkVersion', '$destroy', @@ -6812,9 +6820,7 @@ begin Result:=Call; exit; end; - eopAnd, - eopOr, - eopXor: + eopAnd: begin if aResolver<>nil then begin @@ -6823,26 +6829,74 @@ begin if UseBitwiseOp and (LeftResolved.BaseType in [btIntDouble,btUIntDouble]) and (RightResolved.BaseType in [btIntDouble,btUIntDouble]) then - aResolver.LogMsg(20190124233439,mtWarning,nBitWiseOperationsAre32Bit, - sBitWiseOperationsAre32Bit,[],El); + begin + Call:=CreateCallExpression(El); + Call.Expr:=CreateMemberExpression([GetBIName(pbivnRTL),GetBIName(pbifnBitwiseNativeIntAnd)]); + Call.AddArg(A); + Call.AddArg(B); + Result:=Call; + exit; + end; end else UseBitwiseOp:=(GetExpressionValueType(El.left,AContext)=jstNumber) or (GetExpressionValueType(El.right,AContext)=jstNumber); if UseBitwiseOp then - Case El.OpCode of - eopAnd : C:=TJSBitwiseAndExpression; - eopOr : C:=TJSBitwiseOrExpression; - eopXor : C:=TJSBitwiseXOrExpression; + C:=TJSBitwiseAndExpression + else + C:=TJSLogicalAndExpression; + end; + eopOr: + begin + if aResolver<>nil then + begin + UseBitwiseOp:=((LeftResolved.BaseType in btAllJSInteger) + or (RightResolved.BaseType in btAllJSInteger)); + if UseBitwiseOp + and ((LeftResolved.BaseType in [btIntDouble,btUIntDouble]) + or (RightResolved.BaseType in [btIntDouble,btUIntDouble])) then + begin + Call:=CreateCallExpression(El); + Call.Expr:=CreateMemberExpression([GetBIName(pbivnRTL),GetBIName(pbifnBitwiseNativeIntOr)]); + Call.AddArg(A); + Call.AddArg(B); + Result:=Call; + exit; + end; end else - Case El.OpCode of - eopAnd : C:=TJSLogicalAndExpression; - eopOr : C:=TJSLogicalOrExpression; - eopXor : C:=TJSBitwiseXOrExpression; - else - DoError(20161024191234,nBinaryOpcodeNotSupported,sBinaryOpcodeNotSupported,['logical XOR'],El); - end; + UseBitwiseOp:=(GetExpressionValueType(El.left,AContext)=jstNumber) + or (GetExpressionValueType(El.right,AContext)=jstNumber); + if UseBitwiseOp then + C:=TJSBitwiseOrExpression + else + C:=TJSLogicalOrExpression; + end; + eopXor: + begin + if aResolver<>nil then + begin + UseBitwiseOp:=((LeftResolved.BaseType in btAllJSInteger) + or (RightResolved.BaseType in btAllJSInteger)); + if UseBitwiseOp + and ((LeftResolved.BaseType in [btIntDouble,btUIntDouble]) + or (RightResolved.BaseType in [btIntDouble,btUIntDouble])) then + begin + Call:=CreateCallExpression(El); + Call.Expr:=CreateMemberExpression([GetBIName(pbivnRTL),GetBIName(pbifnBitwiseNativeIntXor)]); + Call.AddArg(A); + Call.AddArg(B); + Result:=Call; + exit; + end; + end + else + UseBitwiseOp:=(GetExpressionValueType(El.left,AContext)=jstNumber) + or (GetExpressionValueType(El.right,AContext)=jstNumber); + if UseBitwiseOp then + C:=TJSBitwiseXOrExpression + else + C:=TJSBitwiseXOrExpression; end; eopPower: begin @@ -6851,7 +6905,7 @@ begin Call.AddArg(A); Call.AddArg(B); Result:=Call; - end + end; else if C=nil then DoError(20161024191244,nBinaryOpcodeNotSupported,sBinaryOpcodeNotSupported,[OpcodeStrings[El.OpCode]],El); @@ -6863,11 +6917,17 @@ begin R.B:=B; B:=nil; Result:=R; - if El.OpCode=eopDiv then + case El.OpCode of + eopDiv: begin // convert "a div b" to "Math.floor(a/b)" Result:=CreateMathFloor(El,Result); end; + eopShl,eopShr: + if (aResolver<>nil) and (LeftResolved.BaseType in [btIntDouble,btUIntDouble]) then + aResolver.LogMsg(20190228220225,mtWarning,nBitWiseOperationIs32Bit, + sBitWiseOperationIs32Bit,[],El); + end; if (bsOverflowChecks in AContext.ScannerBoolSwitches) and (aResolver<>nil) then case El.OpCode of diff --git a/packages/pastojs/tests/tcmodules.pas b/packages/pastojs/tests/tcmodules.pas index 09fb3091fe..855cfedb1d 100644 --- a/packages/pastojs/tests/tcmodules.pas +++ b/packages/pastojs/tests/tcmodules.pas @@ -263,7 +263,7 @@ type Procedure TestInteger; Procedure TestIntegerRange; Procedure TestIntegerTypecasts; - Procedure TestBitwiseAndNativeIntWarn; + Procedure TestBitwiseShlNativeIntWarn; Procedure TestCurrency; Procedure TestForBoolDo; Procedure TestForIntDo; @@ -3080,24 +3080,36 @@ end; procedure TTestModule.TestBitwiseOperators; begin StartProgram(false); - Add('var'); - Add(' vA,vB,vC:longint;'); - Add('begin'); - Add(' va:=vb and vc;'); - Add(' va:=vb or vc;'); - Add(' va:=vb xor vc;'); - Add(' va:=vb shl vc;'); - Add(' va:=vb shr vc;'); - Add(' va:=3 and vc;'); - Add(' va:=(vb and vc) or (va and vb);'); - Add(' va:=not vb;'); + Add([ + 'var', + ' vA,vB,vC:longint;', + ' X,Y,Z: nativeint;', + 'begin', + ' va:=vb and vc;', + ' va:=vb or vc;', + ' va:=vb xor vc;', + ' va:=vb shl vc;', + ' va:=vb shr vc;', + ' va:=3 and vc;', + ' va:=(vb and vc) or (va and vb);', + ' va:=not vb;', + ' X:=Y and Z;', + ' X:=Y and va;', + ' X:=Y or Z;', + ' X:=Y or va;', + ' X:=Y xor Z;', + ' X:=Y xor va;', + '']); ConvertProgram; CheckSource('TestBitwiseOperators', LinesToStr([ // statements 'this.vA = 0;', 'this.vB = 0;', - 'this.vC = 0;' - ]), + 'this.vC = 0;', + 'this.X = 0;', + 'this.Y = 0;', + 'this.Z = 0;', + '']), LinesToStr([ // this.$main '$mod.vA = $mod.vB & $mod.vC;', '$mod.vA = $mod.vB | $mod.vC;', @@ -3106,8 +3118,14 @@ begin '$mod.vA = $mod.vB >>> $mod.vC;', '$mod.vA = 3 & $mod.vC;', '$mod.vA = ($mod.vB & $mod.vC) | ($mod.vA & $mod.vB);', - '$mod.vA = ~$mod.vB;' - ])); + '$mod.vA = ~$mod.vB;', + '$mod.X = rtl.and($mod.Y, $mod.Z);', + '$mod.X = $mod.Y & $mod.vA;', + '$mod.X = rtl.or($mod.Y, $mod.Z);', + '$mod.X = rtl.or($mod.Y, $mod.vA);', + '$mod.X = rtl.xor($mod.Y, $mod.Z);', + '$mod.X = rtl.xor($mod.Y, $mod.vA);', + ''])); end; procedure TTestModule.TestPrgProcVar; @@ -6414,25 +6432,24 @@ begin ''])); end; -procedure TTestModule.TestBitwiseAndNativeIntWarn; +procedure TTestModule.TestBitwiseShlNativeIntWarn; begin StartProgram(false); Add([ 'var', - ' i,j: nativeint;', + ' i: nativeint;', 'begin', - ' i:=i and j;', + ' i:=i shl 3;', '']); ConvertProgram; - CheckSource('TestBitwiseAndNativeIntWarn', + CheckSource('TestBitwiseShlNativeIntWarn', LinesToStr([ 'this.i = 0;', - 'this.j = 0;', '']), LinesToStr([ - '$mod.i = $mod.i & $mod.j;', + '$mod.i = $mod.i << 3;', ''])); - CheckHint(mtWarning,nBitWiseOperationsAre32Bit,sBitWiseOperationsAre32Bit); + CheckHint(mtWarning,nBitWiseOperationIs32Bit,sBitWiseOperationIs32Bit); end; procedure TTestModule.TestCurrency; |