summaryrefslogtreecommitdiff
path: root/packages/pastojs
diff options
context:
space:
mode:
authormattias <mattias@3ad0048d-3df7-0310-abae-a5850022a9f2>2019-02-28 21:57:28 +0000
committermattias <mattias@3ad0048d-3df7-0310-abae-a5850022a9f2>2019-02-28 21:57:28 +0000
commit098f5744e414d4e0af697b6235ce765225d71369 (patch)
tree35fb095b96bbda4ccdbf85cf65745b21e8a02e9a /packages/pastojs
parentd4a98c301671e8784a48ab12413f8616f2566c0f (diff)
downloadfpc-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.pp96
-rw-r--r--packages/pastojs/tests/tcmodules.pas63
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;