Skip to content

Add bit shift intrinsic functions #8569

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Apr 7, 2023
29 changes: 16 additions & 13 deletions src/Build.UnitTests/Evaluation/Expander_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3400,22 +3400,25 @@ public void PropertyFunctionStaticMethodIntrinsicMaths()

double expectedResult = 9223372036854775807D + 20D;
Assert.Equal(expectedResult.ToString(), result);
}

result = expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::BitwiseOr(40, 2))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

Assert.Equal((40 | 2).ToString(), result);

result = expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::BitwiseAnd(42, 2))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

Assert.Equal((42 & 2).ToString(), result);

result = expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::BitwiseXor(213, 255))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);

Assert.Equal((213 ^ 255).ToString(), result);
/// <summary>
/// Expand intrinsic property functions that call a bit operator
/// </summary>
[Fact]
public void PropertyFunctionStaticMethodIntrinsicBitOperations()
{
PropertyDictionary<ProjectPropertyInstance> pg = new PropertyDictionary<ProjectPropertyInstance>();

result = expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::BitwiseNot(-43))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
Expander<ProjectPropertyInstance, ProjectItemInstance> expander = new Expander<ProjectPropertyInstance, ProjectItemInstance>(pg, FileSystems.Default);

Assert.Equal((~-43).ToString(), result);
expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::BitwiseOr(40, 2))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance).ShouldBe((40 | 2).ToString());
expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::BitwiseAnd(42, 2))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance).ShouldBe((42 & 2).ToString());
expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::BitwiseXor(213, 255))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance).ShouldBe((213 ^ 255).ToString());
expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::BitwiseNot(-43))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance).ShouldBe((~-43).ToString());
expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::LeftShift(1, 2))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance).ShouldBe((1 << 2).ToString());
expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::RightShift(-8, 2))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance).ShouldBe((-8 >> 2).ToString());
expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::RightShiftUnsigned(-8, 2))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance).ShouldBe((-8 >>> 2).ToString());
}

/// <summary>
Expand Down
92 changes: 88 additions & 4 deletions src/Build/Evaluation/Expander.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3887,6 +3887,14 @@ private bool TryExecuteWellKnownFunction(out object returnVal, object objectInst
return true;
}
}
else if (string.Equals(_methodMethodName, nameof(IntrinsicFunctions.Unescape), StringComparison.OrdinalIgnoreCase))
{
if (TryGetArg(args, out string arg0))
{
returnVal = IntrinsicFunctions.Unescape(arg0);
return true;
}
}
else if (string.Equals(_methodMethodName, nameof(IntrinsicFunctions.GetPathOfFileAbove), StringComparison.OrdinalIgnoreCase))
{
if (TryGetArgs(args, out string arg0, out string arg1))
Expand All @@ -3899,31 +3907,39 @@ private bool TryExecuteWellKnownFunction(out object returnVal, object objectInst
{
if (TryGetArgs(args, out double arg0, out double arg1))
{
returnVal = arg0 + arg1;
returnVal = IntrinsicFunctions.Add(arg0, arg1);
return true;
}
}
else if (string.Equals(_methodMethodName, nameof(IntrinsicFunctions.Subtract), StringComparison.OrdinalIgnoreCase))
{
if (TryGetArgs(args, out double arg0, out double arg1))
{
returnVal = arg0 - arg1;
returnVal = IntrinsicFunctions.Subtract(arg0, arg1);
return true;
}
}
else if (string.Equals(_methodMethodName, nameof(IntrinsicFunctions.Multiply), StringComparison.OrdinalIgnoreCase))
{
if (TryGetArgs(args, out double arg0, out double arg1))
{
returnVal = arg0 * arg1;
returnVal = IntrinsicFunctions.Multiply(arg0, arg1);
return true;
}
}
else if (string.Equals(_methodMethodName, nameof(IntrinsicFunctions.Divide), StringComparison.OrdinalIgnoreCase))
{
if (TryGetArgs(args, out double arg0, out double arg1))
{
returnVal = arg0 / arg1;
returnVal = IntrinsicFunctions.Divide(arg0, arg1);
return true;
}
}
else if (string.Equals(_methodMethodName, nameof(IntrinsicFunctions.Modulo), StringComparison.OrdinalIgnoreCase))
{
if (TryGetArgs(args, out double arg0, out double arg1))
{
returnVal = IntrinsicFunctions.Modulo(arg0, arg1);
return true;
}
}
Expand Down Expand Up @@ -4113,6 +4129,62 @@ private bool TryExecuteWellKnownFunction(out object returnVal, object objectInst
return true;
}
}
else if (string.Equals(_methodMethodName, nameof(IntrinsicFunctions.BitwiseOr), StringComparison.OrdinalIgnoreCase))
{
if (TryGetArgs(args, out int arg0, out int arg1))
{
returnVal = IntrinsicFunctions.BitwiseOr(arg0, arg1);
return true;
}
}
else if (string.Equals(_methodMethodName, nameof(IntrinsicFunctions.BitwiseAnd), StringComparison.OrdinalIgnoreCase))
{
if (TryGetArgs(args, out int arg0, out int arg1))
{
returnVal = IntrinsicFunctions.BitwiseAnd(arg0, arg1);
return true;
}
}
else if (string.Equals(_methodMethodName, nameof(IntrinsicFunctions.BitwiseXor), StringComparison.OrdinalIgnoreCase))
{
if (TryGetArgs(args, out int arg0, out int arg1))
{
returnVal = IntrinsicFunctions.BitwiseXor(arg0, arg1);
return true;
}
}
else if (string.Equals(_methodMethodName, nameof(IntrinsicFunctions.BitwiseNot), StringComparison.OrdinalIgnoreCase))
{
if (TryGetArgs(args, out int arg0))
{
returnVal = IntrinsicFunctions.BitwiseNot(arg0);
return true;
}
}
else if (string.Equals(_methodMethodName, nameof(IntrinsicFunctions.LeftShift), StringComparison.OrdinalIgnoreCase))
{
if (TryGetArgs(args, out int arg0, out int arg1))
{
returnVal = IntrinsicFunctions.LeftShift(arg0, arg1);
return true;
}
}
else if (string.Equals(_methodMethodName, nameof(IntrinsicFunctions.RightShift), StringComparison.OrdinalIgnoreCase))
{
if (TryGetArgs(args, out int arg0, out int arg1))
{
returnVal = IntrinsicFunctions.RightShift(arg0, arg1);
return true;
}
}
else if (string.Equals(_methodMethodName, nameof(IntrinsicFunctions.RightShiftUnsigned), StringComparison.OrdinalIgnoreCase))
{
if (TryGetArgs(args, out int arg0, out int arg1))
{
returnVal = IntrinsicFunctions.RightShiftUnsigned(arg0, arg1);
return true;
}
}
}
else if (_receiverType == typeof(Path))
{
Expand Down Expand Up @@ -4489,6 +4561,18 @@ private static bool TryGetArgs(object[] args, out string arg0, out StringCompari
return Enum.TryParse(comparisonTypeName, out arg1);
}

private static bool TryGetArgs(object[] args, out int arg0)
{
arg0 = 0;

if (args.Length != 1)
{
return false;
}

return TryConvertToInt(args[0], out arg0);
}

private static bool TryGetArgs(object[] args, out int arg0, out int arg1)
{
arg0 = 0;
Expand Down
15 changes: 15 additions & 0 deletions src/Build/Evaluation/IntrinsicFunctions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,21 @@ internal static int BitwiseNot(int first)
return ~first;
}

internal static int LeftShift(int operand, int count)
{
return operand << count;
}

internal static int RightShift(int operand, int count)
{
return operand >> count;
}

internal static int RightShiftUnsigned(int operand, int count)
{
return operand >>> count;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't aware this existed. Always nice to learn something new!

}

/// <summary>
/// Get the value of the registry key and value, default value is null
/// </summary>
Expand Down