示例#1
0
        public override BuildResult Build(Instruction instruction, FunctionContext funcContext)
        {
            if (instruction.OpCode == OpCodes.Conv_I)
            {
                var value = funcContext.BuilderStack.Pop();
                if (MiniBCL.IsTypeARealNumber(value.Type))
                {
                    var stackItem = new BuilderStackItem(MiniBCL.Int32Type,
                                                         LLVM.BuildFPToUI(funcContext.Builder, value.ValRef.Value, LLVM.Int8Type(), ""));
                    funcContext.BuilderStack.Push(stackItem);
                    Context.CLRLogger.Debug(
                        $"[Conv_U1] -> Popped {value.ValRef.Value} and Pushed As Unsigned Integer {stackItem.ValRef.Value} to Stack");
                }
                else if (MiniBCL.IsTypeAnInteger(value.Type))
                {
                    var stackItem = new BuilderStackItem(MiniBCL.Int32Type,
                                                         LLVM.BuildZExt(funcContext.Builder, value.ValRef.Value, LLVM.Int8Type(), ""));
                    funcContext.BuilderStack.Push(stackItem);
                    Context.CLRLogger.Debug(
                        $"[Conv_U1] -> Popped {value.ValRef.Value} and Pushed As Unsigned Integer {stackItem.ValRef.Value} to Stack");
                }
                // TODO: Support Decimal Conversion To Int64
                else
                {
                    throw new Exception(
                              "INTEGER 8 BYTES CONVERSION IS NOT SUPPORTED");
                }

                return(new BuildResult(true));
            }

            if (instruction.OpCode == OpCodes.Conv_U1)
            {
                var value = funcContext.BuilderStack.Pop();
                if (MiniBCL.IsTypeARealNumber(value.Type))
                {
                    var stackItem = new BuilderStackItem(MiniBCL.UInt8Type,
                                                         LLVM.BuildFPToUI(funcContext.Builder, value.ValRef.Value, LLVM.Int8Type(), ""));
                    funcContext.BuilderStack.Push(stackItem);
                    Context.CLRLogger.Debug(
                        $"[Conv_U1] -> Popped {value.ValRef.Value} and Pushed As Unsigned Integer {stackItem.ValRef.Value} to Stack");
                }
                else if (MiniBCL.IsTypeAnInteger(value.Type))
                {
                    var stackItem = new BuilderStackItem(MiniBCL.UInt8Type,
                                                         LLVM.BuildZExt(funcContext.Builder, value.ValRef.Value, LLVM.Int8Type(), ""));
                    funcContext.BuilderStack.Push(stackItem);
                    Context.CLRLogger.Debug(
                        $"[Conv_U1] -> Popped {value.ValRef.Value} and Pushed As Unsigned Integer {stackItem.ValRef.Value} to Stack");
                }
                else
                {
                    throw new Exception(
                              "UNSIGNED INTEGER 1 BYTES CONVERSION IS NOT SUPPORTED");
                }

                return(new BuildResult(true));
            }

            if (instruction.OpCode == OpCodes.Conv_U2)
            {
                var value = funcContext.BuilderStack.Pop();
                if (MiniBCL.IsTypeARealNumber(value.Type))
                {
                    var stackItem = new BuilderStackItem(MiniBCL.UInt16Type,
                                                         LLVM.BuildFPToUI(funcContext.Builder, value.ValRef.Value, LLVM.Int16Type(), ""));
                    funcContext.BuilderStack.Push(stackItem);
                    Context.CLRLogger.Debug(
                        $"[Conv_U2] -> Popped {value.ValRef.Value} and Pushed As Unsigned Integer {stackItem.ValRef.Value} to Stack");
                }
                else if (MiniBCL.IsTypeAnInteger(value.Type))
                {
                    var stackItem = new BuilderStackItem(MiniBCL.UInt16Type,
                                                         LLVM.BuildZExt(funcContext.Builder, value.ValRef.Value, LLVM.Int16Type(), ""));
                    funcContext.BuilderStack.Push(stackItem);
                    Context.CLRLogger.Debug(
                        $"[Conv_U2] -> Popped {value.ValRef.Value} and Pushed As Unsigned Integer {stackItem.ValRef.Value} to Stack");
                }
                else
                {
                    throw new Exception(
                              "UNSIGNED INTEGER 2 BYTES CONVERSION IS NOT SUPPORTED");
                }

                return(new BuildResult(true));
            }

            if (instruction.OpCode == OpCodes.Conv_U4)
            {
                var value = funcContext.BuilderStack.Pop();
                if (MiniBCL.IsTypeARealNumber(value.Type))
                {
                    var stackItem = new BuilderStackItem(MiniBCL.UInt32Type,
                                                         LLVM.BuildFPToUI(funcContext.Builder, value.ValRef.Value, LLVM.Int32Type(), ""));
                    funcContext.BuilderStack.Push(stackItem);
                    Context.CLRLogger.Debug(
                        $"[Conv_U4] -> Popped {value.ValRef.Value} and Pushed As Unsigned Integer {stackItem.ValRef.Value} to Stack");
                }
                else if (MiniBCL.IsTypeAnInteger(value.Type))
                {
                    var stackItem = new BuilderStackItem(MiniBCL.UInt32Type,
                                                         LLVM.BuildZExt(funcContext.Builder, value.ValRef.Value, LLVM.Int32Type(), ""));
                    funcContext.BuilderStack.Push(stackItem);
                    Context.CLRLogger.Debug(
                        $"[Conv_U4] -> Popped {value.ValRef.Value} and Pushed As Unsigned Integer {stackItem.ValRef.Value} to Stack");
                }
                else
                {
                    throw new Exception(
                              "UNSIGNED INTEGER 4 BYTES CONVERSION IS NOT SUPPORTED");
                }

                return(new BuildResult(true));
            }

            if (instruction.OpCode == OpCodes.Conv_U8)
            {
                var value = funcContext.BuilderStack.Pop();
                if (MiniBCL.IsTypeARealNumber(value.Type))
                {
                    var stackItem = new BuilderStackItem(MiniBCL.UInt64Type,
                                                         LLVM.BuildFPToUI(funcContext.Builder, value.ValRef.Value, LLVM.Int64Type(), ""));
                    funcContext.BuilderStack.Push(stackItem);
                    Context.CLRLogger.Debug(
                        $"[Conv_U8] -> Popped {value.ValRef.Value} and Pushed As Unsigned Integer {stackItem.ValRef.Value} to Stack");
                }
                else if (MiniBCL.IsTypeAnInteger(value.Type))
                {
                    var stackItem = new BuilderStackItem(MiniBCL.UInt64Type,
                                                         LLVM.BuildZExt(funcContext.Builder, value.ValRef.Value, LLVM.Int64Type(), ""));
                    funcContext.BuilderStack.Push(stackItem);
                    Context.CLRLogger.Debug(
                        $"[Conv_U8] -> Popped {value.ValRef.Value} and Pushed As Unsigned Integer {stackItem.ValRef.Value} to Stack");
                }
                else
                {
                    throw new Exception(
                              "UNSIGNED INTEGER 8 BYTES CONVERSION IS NOT SUPPORTED");
                }

                return(new BuildResult(true));
            }

            if (instruction.OpCode == OpCodes.Conv_I1)
            {
                var value = funcContext.BuilderStack.Pop();
                if (MiniBCL.IsTypeARealNumber(value.Type))
                {
                    var stackItem = new BuilderStackItem(MiniBCL.Int8Type,
                                                         LLVM.BuildFPToSI(funcContext.Builder, value.ValRef.Value, LLVM.Int8Type(), ""));
                    funcContext.BuilderStack.Push(stackItem);
                    Context.CLRLogger.Debug(
                        $"[Conv_I1] -> Popped {value.ValRef.Value} and Pushed As Signed Integer {stackItem.ValRef.Value} to Stack");
                }
                else if (MiniBCL.IsTypeAnInteger(value.Type))
                {
                    var stackItem = new BuilderStackItem(MiniBCL.Int8Type,
                                                         LLVM.BuildZExt(funcContext.Builder, value.ValRef.Value, LLVM.Int8Type(), ""));
                    funcContext.BuilderStack.Push(stackItem);
                    Context.CLRLogger.Debug(
                        $"[Conv_I1] -> Popped {value.ValRef.Value} and Pushed As Signed Integer {stackItem.ValRef.Value} to Stack");
                }
                else
                {
                    throw new Exception(
                              "INTEGER 1 BYTES CONVERSION IS NOT SUPPORTED");
                }

                return(new BuildResult(true));
            }

            if (instruction.OpCode == OpCodes.Conv_I2)
            {
                var value = funcContext.BuilderStack.Pop();
                if (MiniBCL.IsTypeARealNumber(value.Type))
                {
                    var stackItem = new BuilderStackItem(MiniBCL.Int16Type,
                                                         LLVM.BuildFPToSI(funcContext.Builder, value.ValRef.Value, LLVM.Int16Type(), ""));
                    funcContext.BuilderStack.Push(stackItem);
                    Context.CLRLogger.Debug(
                        $"[Conv_I2] -> Popped {value.ValRef.Value} and Pushed As Signed Integer {stackItem.ValRef.Value} to Stack");
                }
                else if (MiniBCL.IsTypeAnInteger(value.Type))
                {
                    var stackItem = new BuilderStackItem(MiniBCL.Int16Type,
                                                         LLVM.BuildZExt(funcContext.Builder, value.ValRef.Value, LLVM.Int16Type(), ""));
                    funcContext.BuilderStack.Push(stackItem);
                    Context.CLRLogger.Debug(
                        $"[Conv_I2] -> Popped {value.ValRef.Value} and Pushed As Signed Integer {stackItem.ValRef.Value} to Stack");
                }
                else
                {
                    throw new Exception(
                              "INTEGER 2 BYTES CONVERSION IS NOT SUPPORTED");
                }

                return(new BuildResult(true));
            }

            if (instruction.OpCode == OpCodes.Conv_I4)
            {
                var value = funcContext.BuilderStack.Pop();
                if (value.Type.IsPointer)
                {
                    var stackItem = new BuilderStackItem(MiniBCL.Int32Type,
                                                         LLVM.BuildPtrToInt(funcContext.Builder, value.ValRef.Value, LLVM.Int32Type(), ""));
                    funcContext.BuilderStack.Push(stackItem);
                    Context.CLRLogger.Debug(
                        $"[Conv_I4] -> Popped {value.ValRef.Value} and Pushed As Signed Integer {stackItem.ValRef.Value} to Stack");
                }
                else if (MiniBCL.IsTypeARealNumber(value.Type))
                {
                    var stackItem = new BuilderStackItem(MiniBCL.Int32Type,
                                                         LLVM.BuildFPToSI(funcContext.Builder, value.ValRef.Value, LLVM.Int32Type(), ""));
                    funcContext.BuilderStack.Push(stackItem);
                    Context.CLRLogger.Debug(
                        $"[Conv_I4] -> Popped {value.ValRef.Value} and Pushed As Signed Integer {stackItem.ValRef.Value} to Stack");
                }
                else if (MiniBCL.IsTypeAnInteger(value.Type))
                {
                    var stackItem = new BuilderStackItem(MiniBCL.Int32Type,
                                                         LLVM.BuildZExt(funcContext.Builder, value.ValRef.Value, LLVM.Int32Type(), ""));
                    funcContext.BuilderStack.Push(stackItem);
                    Context.CLRLogger.Debug(
                        $"[Conv_I4] -> Popped {value.ValRef.Value} and Pushed As Signed Integer {stackItem.ValRef.Value} to Stack");
                }
                else
                {
                    throw new Exception(
                              "INTEGER 4 BYTES CONVERSION IS NOT SUPPORTED");
                }

                return(new BuildResult(true));
            }

            if (instruction.OpCode == OpCodes.Conv_I8)
            {
                var value = funcContext.BuilderStack.Pop();
                if (MiniBCL.IsTypeARealNumber(value.Type))
                {
                    var stackItem = new BuilderStackItem(MiniBCL.Int64Type,
                                                         LLVM.BuildFPToSI(funcContext.Builder, value.ValRef.Value, LLVM.Int64Type(), ""));
                    funcContext.BuilderStack.Push(stackItem);
                    Context.CLRLogger.Debug(
                        $"[Conv_I8] -> Popped {value.ValRef.Value} and Pushed As Signed Integer {stackItem.ValRef.Value} to Stack");
                }
                else if (MiniBCL.IsTypeAnInteger(value.Type))
                {
                    var stackItem = new BuilderStackItem(MiniBCL.Int64Type,
                                                         LLVM.BuildZExt(funcContext.Builder, value.ValRef.Value, LLVM.Int64Type(), ""));
                    funcContext.BuilderStack.Push(stackItem);
                    Context.CLRLogger.Debug(
                        $"[Conv_I8] -> Popped {value.ValRef.Value} and Pushed As Signed Integer {stackItem.ValRef.Value} to Stack");
                }
                else
                {
                    throw new Exception(
                              "INTEGER 8 BYTES CONVERSION IS NOT SUPPORTED");
                }

                return(new BuildResult(true));
            }

            if (instruction.OpCode == OpCodes.Conv_R4)
            {
                var value = funcContext.BuilderStack.Pop();
                if (MiniBCL.IsTypeAnInteger(value.Type))
                {
                    var stackItem = new BuilderStackItem(MiniBCL.FloatType,
                                                         LLVM.BuildSIToFP(funcContext.Builder, value.ValRef.Value,
                                                                          LLVM.FloatTypeInContext(Context.ContextRef),
                                                                          ""));
                    funcContext.BuilderStack.Push(stackItem);
                    Context.CLRLogger.Debug(
                        $"[Conv_R4] -> Popped {value.ValRef.Value} and Pushed As Float {stackItem.ValRef.Value} to Stack");
                }
                else if (MiniBCL.IsTypeARealNumber(value.Type))
                {
                    var stackItem = new BuilderStackItem(MiniBCL.FloatType,
                                                         LLVM.BuildFPCast(funcContext.Builder, value.ValRef.Value,
                                                                          LLVM.FloatTypeInContext(Context.ContextRef),
                                                                          ""));
                    funcContext.BuilderStack.Push(stackItem);
                    Context.CLRLogger.Debug(
                        $"[Conv_R4] -> Popped {value.ValRef.Value} and Pushed As Float {stackItem.ValRef.Value} to Stack");
                }
                else
                {
                    throw new Exception(
                              "REAL 4 BYTES CONVERSION IS NOT SUPPORTED");
                }

                return(new BuildResult(true));
            }

            if (instruction.OpCode == OpCodes.Conv_R8)
            {
                var value = funcContext.BuilderStack.Pop();
                if (MiniBCL.IsTypeAnInteger(value.Type))
                {
                    var stackItem = new BuilderStackItem(MiniBCL.DoubleType,
                                                         LLVM.BuildSIToFP(funcContext.Builder, value.ValRef.Value,
                                                                          LLVM.DoubleTypeInContext(Context.ContextRef),
                                                                          ""));
                    funcContext.BuilderStack.Push(stackItem);
                    Context.CLRLogger.Debug(
                        $"[Conv_R8] -> Popped {value.ValRef.Value} and Pushed As Float {stackItem.ValRef.Value} to Stack");
                }
                else if (MiniBCL.IsTypeARealNumber(value.Type))
                {
                    var stackItem = new BuilderStackItem(MiniBCL.DoubleType,
                                                         LLVM.BuildFPCast(funcContext.Builder, value.ValRef.Value,
                                                                          LLVM.DoubleTypeInContext(Context.ContextRef),
                                                                          ""));
                    funcContext.BuilderStack.Push(stackItem);
                    Context.CLRLogger.Debug(
                        $"[Conv_R8] -> Popped {value.ValRef.Value} and Pushed As Float {stackItem.ValRef.Value} to Stack");
                }
                else
                {
                    throw new Exception(
                              "REAL 8 BYTES CONVERSION IS NOT SUPPORTED");
                }

                return(new BuildResult(true));
            }

            return(new BuildResult(false));
        }
        public override BuildResult Build(Instruction instruction, FunctionContext funcContext)
        {
            if (instruction.OpCode == OpCodes.Add)
            {
                // TODO: Support conversion between Floating Point and Integers
                var rval = funcContext.BuilderStack.Pop();
                var lval = funcContext.BuilderStack.Pop();
                if (MiniBCL.IsTypeAnInteger(lval.Type) && MiniBCL.IsTypeAnInteger(rval.Type))
                {
                    // TODO: Need to determine the size of pointer.
                    LLVMValueRef actualLVal;
                    LLVMValueRef actualRVal;
                    if (lval.ValRef.Value.TypeOf().TypeKind == LLVMTypeKind.LLVMPointerTypeKind)
                    {
                        actualLVal = LLVM.BuildPtrToInt(funcContext.Builder, lval.ValRef.Value, LLVM.Int32Type(),
                                                        "lval");
                    }
                    else
                    {
                        actualLVal = LLVM.BuildZExt(funcContext.Builder, lval.ValRef.Value, LLVM.Int32Type(), "lval");
                    }

                    if (rval.ValRef.Value.TypeOf().TypeKind == LLVMTypeKind.LLVMPointerTypeKind)
                    {
                        actualRVal = LLVM.BuildPtrToInt(funcContext.Builder, rval.ValRef.Value, LLVM.Int32Type(),
                                                        "rval");
                    }
                    else
                    {
                        actualRVal = LLVM.BuildZExt(funcContext.Builder, rval.ValRef.Value, LLVM.Int32Type(), "rval");
                    }

                    var stackItem = new BuilderStackItem(lval.Type,
                                                         LLVM.BuildAdd(funcContext.Builder, actualLVal, actualRVal, ""));
                    funcContext.BuilderStack.Push(stackItem);
                    Context.CLRLogger.Debug(
                        $"[Add] -> Popped {rval.ValRef.Value} and {lval.ValRef.Value.TypeOf()} and Pushed {stackItem.ValRef.Value}");
                }
                else if (MiniBCL.IsTypeARealNumber(lval.Type) && MiniBCL.IsTypeARealNumber(rval.Type))
                {
                    var stackItem = new BuilderStackItem(lval.Type,
                                                         LLVM.BuildFAdd(funcContext.Builder, lval.ValRef.Value, rval.ValRef.Value, ""));
                    funcContext.BuilderStack.Push(stackItem);
                    Context.CLRLogger.Debug(
                        $"[Add] -> Popped {rval.ValRef.Value} and {lval.ValRef.Value} and Pushed {stackItem.ValRef.Value}");
                }
                else
                {
                    throw new Exception("Unknown type, thus cannot add!");
                }

                return(new BuildResult(true));
            }

            if (instruction.OpCode == OpCodes.Sub)
            {
                // TODO: Support conversion between Floating Point and Integers
                var rval = funcContext.BuilderStack.Pop();
                var lval = funcContext.BuilderStack.Pop();
                if (MiniBCL.IsTypeAnInteger(lval.Type) && MiniBCL.IsTypeAnInteger(rval.Type))
                {
                    // TODO: Need to determine the size of pointer.
                    LLVMValueRef actualLVal;
                    LLVMValueRef actualRVal;
                    if (lval.ValRef.Value.TypeOf().TypeKind == LLVMTypeKind.LLVMPointerTypeKind)
                    {
                        actualLVal = LLVM.BuildPtrToInt(funcContext.Builder, lval.ValRef.Value, LLVM.Int32Type(),
                                                        "lval");
                    }
                    else
                    {
                        actualLVal = LLVM.BuildZExt(funcContext.Builder, lval.ValRef.Value, LLVM.Int32Type(), "lval");
                    }

                    if (rval.ValRef.Value.TypeOf().TypeKind == LLVMTypeKind.LLVMPointerTypeKind)
                    {
                        actualRVal = LLVM.BuildPtrToInt(funcContext.Builder, rval.ValRef.Value, LLVM.Int32Type(),
                                                        "rval");
                    }
                    else
                    {
                        actualRVal = LLVM.BuildZExt(funcContext.Builder, rval.ValRef.Value, LLVM.Int32Type(), "rval");
                    }

                    var stackItem = new BuilderStackItem(lval.Type,
                                                         LLVM.BuildSub(funcContext.Builder, actualLVal, actualRVal, ""));
                    funcContext.BuilderStack.Push(stackItem);
                    Context.CLRLogger.Debug(
                        $"[Sub] -> Popped {rval.ValRef.Value} and {lval.ValRef.Value} and Pushed {stackItem.ValRef.Value}");
                }
                else if (MiniBCL.IsTypeARealNumber(lval.Type) && MiniBCL.IsTypeARealNumber(rval.Type))
                {
                    var stackItem = new BuilderStackItem(lval.Type,
                                                         LLVM.BuildFSub(funcContext.Builder, lval.ValRef.Value, rval.ValRef.Value, ""));
                    funcContext.BuilderStack.Push(stackItem);
                    Context.CLRLogger.Debug(
                        $"[Sub] -> Popped {rval.ValRef.Value} and {lval.ValRef.Value} and Pushed {stackItem.ValRef.Value}");
                }
                else
                {
                    throw new Exception("Unknown type, thus cannot add!");
                }

                return(new BuildResult(true));
            }

            if (instruction.OpCode == OpCodes.Mul)
            {
                // TODO: Support conversion between Floating Point and Integers
                var rval = funcContext.BuilderStack.Pop();
                var lval = funcContext.BuilderStack.Pop();
                if (MiniBCL.IsTypeAnInteger(lval.Type) && MiniBCL.IsTypeAnInteger(rval.Type))
                {
                    // TODO: Need to determine the size of pointer.
                    LLVMValueRef actualLVal;
                    LLVMValueRef actualRVal;
                    if (lval.ValRef.Value.TypeOf().TypeKind == LLVMTypeKind.LLVMPointerTypeKind)
                    {
                        actualLVal = LLVM.BuildPtrToInt(funcContext.Builder, lval.ValRef.Value, LLVM.Int32Type(),
                                                        "lval");
                    }
                    else
                    {
                        actualLVal = LLVM.BuildZExt(funcContext.Builder, lval.ValRef.Value, LLVM.Int32Type(), "lval");
                    }

                    if (rval.ValRef.Value.TypeOf().TypeKind == LLVMTypeKind.LLVMPointerTypeKind)
                    {
                        actualRVal = LLVM.BuildPtrToInt(funcContext.Builder, rval.ValRef.Value, LLVM.Int32Type(),
                                                        "rval");
                    }
                    else
                    {
                        actualRVal = LLVM.BuildZExt(funcContext.Builder, rval.ValRef.Value, LLVM.Int32Type(), "rval");
                    }

                    var stackItem = new BuilderStackItem(lval.Type,
                                                         LLVM.BuildMul(funcContext.Builder, actualLVal, actualRVal, ""));
                    funcContext.BuilderStack.Push(stackItem);
                    Context.CLRLogger.Debug(
                        $"[Sub] -> Popped {rval.ValRef.Value} and {lval.ValRef.Value} and Pushed {stackItem.ValRef.Value}");
                }
                else if (MiniBCL.IsTypeARealNumber(lval.Type) && MiniBCL.IsTypeARealNumber(rval.Type))
                {
                    var stackItem = new BuilderStackItem(lval.Type,
                                                         LLVM.BuildFMul(funcContext.Builder, lval.ValRef.Value, rval.ValRef.Value, ""));
                    funcContext.BuilderStack.Push(stackItem);
                    Context.CLRLogger.Debug(
                        $"[Sub] -> Popped {rval.ValRef.Value} and {lval.ValRef.Value} and Pushed {stackItem.ValRef.Value}");
                }
                else
                {
                    throw new Exception("Unknown type, thus cannot add!");
                }

                return(new BuildResult(true));
            }

            if (instruction.OpCode == OpCodes.Div)
            {
                // TODO: Support conversion between Floating Point and Integers
                var rval = funcContext.BuilderStack.Pop();
                var lval = funcContext.BuilderStack.Pop();
                if (MiniBCL.IsTypeAnInteger(lval.Type) && MiniBCL.IsTypeAnInteger(rval.Type))
                {
                    // TODO: Need to determine the size of pointer.
                    LLVMValueRef actualLVal;
                    LLVMValueRef actualRVal;
                    if (lval.ValRef.Value.TypeOf().TypeKind == LLVMTypeKind.LLVMPointerTypeKind)
                    {
                        actualLVal = LLVM.BuildPtrToInt(funcContext.Builder, lval.ValRef.Value, LLVM.Int32Type(),
                                                        "lval");
                    }
                    else
                    {
                        actualLVal = LLVM.BuildZExt(funcContext.Builder, lval.ValRef.Value, LLVM.Int32Type(), "lval");
                    }

                    if (rval.ValRef.Value.TypeOf().TypeKind == LLVMTypeKind.LLVMPointerTypeKind)
                    {
                        actualRVal = LLVM.BuildPtrToInt(funcContext.Builder, rval.ValRef.Value, LLVM.Int32Type(),
                                                        "rval");
                    }
                    else
                    {
                        actualRVal = LLVM.BuildZExt(funcContext.Builder, rval.ValRef.Value, LLVM.Int32Type(), "rval");
                    }

                    var stackItem = new BuilderStackItem(lval.Type,
                                                         LLVM.BuildSDiv(funcContext.Builder, actualLVal, actualRVal, ""));
                    funcContext.BuilderStack.Push(stackItem);

                    Context.CLRLogger.Debug(
                        $"[Sub] -> Popped {rval.ValRef.Value} and {lval.ValRef.Value} and Pushed {stackItem.ValRef.Value}");
                }
                else if (MiniBCL.IsTypeARealNumber(lval.Type) && MiniBCL.IsTypeARealNumber(rval.Type))
                {
                    var stackItem = new BuilderStackItem(lval.Type,
                                                         LLVM.BuildFDiv(funcContext.Builder, lval.ValRef.Value, rval.ValRef.Value, ""));
                    funcContext.BuilderStack.Push(stackItem);

                    Context.CLRLogger.Debug(
                        $"[Sub] -> Popped {rval.ValRef.Value} and {lval.ValRef.Value} and Pushed {stackItem.ValRef.Value}");
                }
                else
                {
                    throw new Exception("Unknown type, thus cannot add!");
                }

                return(new BuildResult(true));
            }

            if (instruction.OpCode == OpCodes.Rem)
            {
                // TODO: Support conversion between Floating Point and Integers
                var rval = funcContext.BuilderStack.Pop();
                var lval = funcContext.BuilderStack.Pop();
                if (MiniBCL.IsTypeAnInteger(lval.Type) && MiniBCL.IsTypeAnInteger(rval.Type))
                {
                    // TODO: Need to determine the size of pointer.
                    LLVMValueRef actualLVal;
                    LLVMValueRef actualRVal;
                    if (lval.ValRef.Value.TypeOf().TypeKind == LLVMTypeKind.LLVMPointerTypeKind)
                    {
                        actualLVal = LLVM.BuildPtrToInt(funcContext.Builder, lval.ValRef.Value, LLVM.Int32Type(),
                                                        "lval");
                    }
                    else
                    {
                        actualLVal = LLVM.BuildZExt(funcContext.Builder, lval.ValRef.Value, LLVM.Int32Type(), "lval");
                    }

                    if (rval.ValRef.Value.TypeOf().TypeKind == LLVMTypeKind.LLVMPointerTypeKind)
                    {
                        actualRVal = LLVM.BuildPtrToInt(funcContext.Builder, rval.ValRef.Value, LLVM.Int32Type(),
                                                        "rval");
                    }
                    else
                    {
                        actualRVal = LLVM.BuildZExt(funcContext.Builder, rval.ValRef.Value, LLVM.Int32Type(), "rval");
                    }

                    var stackItem = new BuilderStackItem(lval.Type,
                                                         LLVM.BuildSRem(funcContext.Builder, actualLVal, actualRVal, ""));
                    funcContext.BuilderStack.Push(stackItem);

                    Context.CLRLogger.Debug(
                        $"[Sub] -> Popped {rval.ValRef.Value} and {lval.ValRef.Value} and Pushed {stackItem.ValRef.Value}");
                }
                else if (MiniBCL.IsTypeARealNumber(lval.Type) && MiniBCL.IsTypeARealNumber(rval.Type))
                {
                    var stackItem = new BuilderStackItem(lval.Type,
                                                         LLVM.BuildFRem(funcContext.Builder, lval.ValRef.Value, rval.ValRef.Value, ""));
                    funcContext.BuilderStack.Push(stackItem);

                    Context.CLRLogger.Debug(
                        $"[Sub] -> Popped {rval.ValRef.Value} and {lval.ValRef.Value} and Pushed {stackItem.ValRef.Value}");
                }
                else
                {
                    throw new Exception("Unknown type, thus cannot add!");
                }

                return(new BuildResult(true));
            }

            return(new BuildResult(false));
        }