Skip to content
This repository was archived by the owner on Nov 1, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 23 additions & 14 deletions src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -820,12 +820,6 @@ private void ImportLoadVar(int index, bool argument)
PushLoadExpression(GetStackValueKind(type), (argument ? "arg" : "loc") + index + "_", typedLoadLocation, type);
}

private LLVMValueRef LoadTemp(int index)
{
LLVMValueRef address = LoadVarAddress(index, LocalVarKind.Temp, out TypeDesc type);
return _builder.BuildLoad(CastToPointerToTypeDesc(address, type, $"Temp{index}_"), $"LdTemp{index}_");
}

internal LLVMValueRef LoadTemp(int index, LLVMTypeRef asType)
{
LLVMValueRef address = LoadVarAddress(index, LocalVarKind.Temp, out TypeDesc type);
Expand Down Expand Up @@ -3814,8 +3808,8 @@ private void ImportBinaryOperation(ILOpcode opcode)
break;

case ILOpcode.add_ovf:
Debug.Assert(type.Category == TypeFlags.Int32 || type.Category == TypeFlags.Int64);
if (type.Category == TypeFlags.Int32)
Debug.Assert(CanPerformSignedOverflowOperations(op1.Kind));
if (Is32BitStackValue(op1.Kind))
{
BuildAddOverflowChecksForSize(ref AddOvf32Function, left, right, LLVMTypeRef.Int32, BuildConstInt32(int.MaxValue), BuildConstInt32(int.MinValue), true);
}
Expand All @@ -3827,8 +3821,8 @@ private void ImportBinaryOperation(ILOpcode opcode)
result = _builder.BuildAdd(left, right, "add");
break;
case ILOpcode.add_ovf_un:
Debug.Assert(type.Category == TypeFlags.UInt32 || type.Category == TypeFlags.Int32 || type.Category == TypeFlags.UInt64 || type.Category == TypeFlags.Int64 || type.Category == TypeFlags.Pointer);
if (type.Category == TypeFlags.UInt32 || type.Category == TypeFlags.Int32 || type.Category == TypeFlags.Pointer)
Debug.Assert(CanPerformUnsignedOverflowOperations(op1.Kind));
if (Is32BitStackValue(op1.Kind))
{
BuildAddOverflowChecksForSize(ref AddOvfUn32Function, left, right, LLVMTypeRef.Int32, BuildConstUInt32(uint.MaxValue), BuildConstInt32(0), false);
}
Expand All @@ -3840,8 +3834,8 @@ private void ImportBinaryOperation(ILOpcode opcode)
result = _builder.BuildAdd(left, right, "add");
break;
case ILOpcode.sub_ovf:
Debug.Assert(type.Category == TypeFlags.Int32 || type.Category == TypeFlags.Int64);
if (type.Category == TypeFlags.Int32)
Debug.Assert(CanPerformSignedOverflowOperations(op1.Kind));
if (Is32BitStackValue(op1.Kind))
{
BuildSubOverflowChecksForSize(ref SubOvf32Function, left, right, LLVMTypeRef.Int32, BuildConstInt32(int.MaxValue), BuildConstInt32(int.MinValue), true);
}
Expand All @@ -3853,8 +3847,8 @@ private void ImportBinaryOperation(ILOpcode opcode)
result = _builder.BuildSub(left, right, "sub");
break;
case ILOpcode.sub_ovf_un:
Debug.Assert(type.Category == TypeFlags.UInt32 || type.Category == TypeFlags.Int32 || type.Category == TypeFlags.UInt64 || type.Category == TypeFlags.Int64 || type.Category == TypeFlags.Pointer);
if (type.Category == TypeFlags.UInt32 || type.Category == TypeFlags.Int32 || type.Category == TypeFlags.Pointer)
Debug.Assert(CanPerformUnsignedOverflowOperations(op1.Kind));
if (Is32BitStackValue(op1.Kind))
{
BuildSubOverflowChecksForSize(ref SubOvfUn32Function, left, right, LLVMTypeRef.Int32, BuildConstUInt32(uint.MaxValue), BuildConstInt32(0), false);
}
Expand Down Expand Up @@ -3885,6 +3879,21 @@ private void ImportBinaryOperation(ILOpcode opcode)
PushExpression(kind, "binop", result, type);
}

bool CanPerformSignedOverflowOperations(StackValueKind kind)
{
return kind == StackValueKind.Int32 || kind == StackValueKind.Int64;
}

bool CanPerformUnsignedOverflowOperations(StackValueKind kind)
{
return CanPerformSignedOverflowOperations(kind) || kind == StackValueKind.ByRef ||
kind == StackValueKind.ObjRef || kind == StackValueKind.NativeInt;
}

bool Is32BitStackValue(StackValueKind kind)
{
return kind == StackValueKind.Int32 || kind == StackValueKind.ByRef || kind == StackValueKind.ObjRef || kind == StackValueKind.NativeInt;
}

LLVMValueRef StartOverflowCheckFunction(LLVMTypeRef sizeTypeRef, bool signed,
string throwFuncName, out LLVMValueRef leftOp, out LLVMValueRef rightOp, out LLVMBuilderRef builder, out LLVMBasicBlockRef elseBlock,
Expand Down
17 changes: 17 additions & 0 deletions tests/src/Simple/HelloWasm/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2272,6 +2272,8 @@ private static unsafe bool CkFinite64(ulong value)

static void TestIntOverflows()
{
TestCharInOvf();

TestSignedIntAddOvf();

TestSignedLongAddOvf();
Expand Down Expand Up @@ -2329,6 +2331,21 @@ private static void TestSignedLongAddOvf()
EndTest(true);
}

private static void TestCharInOvf()
{
// Just checks the compiler can handle the char type
// This was failing for https://github.com/dotnet/corert/blob/f542d97f26e87f633310e67497fb01dad29987a5/src/System.Private.CoreLib/shared/System/Environment.Unix.cs#L111
StartTest("Test char add overflows");
char opChar = '1';
int op32r = 2;
if (checked(opChar + op32r) != 51)
{
FailTest("No overflow for char failed"); // check not always throwing an exception
return;
}
PassTest();
}

private static void TestSignedIntAddOvf()
{
StartTest("Test int add overflows");
Expand Down