Exemplo n.º 1
0
        /// <summary>
        /// Realizes an indirect load instruction.
        /// </summary>
        /// <param name="type">The target type.</param>
        private void MakeLoadObject(Type type)
        {
            var address = CurrentBlock.Pop();

            address = CreateConversion(address, type.MakePointerType());
            CurrentBlock.Push(type, BuildLoad(Builder, address.LLVMValue, string.Empty));
        }
Exemplo n.º 2
0
        /// <summary>
        /// Realizes an arithmetic mul operation.
        /// </summary>
        /// <param name="overflow">True, if an overflow has to be checked.</param>
        private void MakeArithmeticMul(bool overflow)
        {
            if (overflow)
            {
                throw new NotSupportedException();
            }
            Type type           = CurrentBlock.PopArithmeticArgs(out LLVMValueRef left, out LLVMValueRef right);
            var  name           = string.Empty;
            var  basicValueType = type.GetBasicValueType();

            if (basicValueType.IsFloat())
            {
                if (Unit.HasFlags(CompileUnitFlags.UseGPUMath))
                {
                    MakeIntrinsicMathOperation(
                        type,
                        basicValueType == BasicValueType.Single ? MathMulF32 : MathMulF64,
                        left,
                        right);
                }
                else
                {
                    CurrentBlock.Push(type, BuildFMul(Builder, left, right, name));
                }
            }
            else
            {
                CurrentBlock.Push(type, BuildMul(Builder, left, right, name));
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Realizes an arithmetic div operation.
        /// </summary>
        /// <param name="forceUnsigned">True, if the comparison should be forced to be unsigned.</param>
        private void MakeArithmeticDiv(bool forceUnsigned = false)
        {
            Type type           = CurrentBlock.PopArithmeticArgs(out LLVMValueRef left, out LLVMValueRef right);
            var  name           = string.Empty;
            var  basicValueType = type.GetBasicValueType();

            if (basicValueType.IsFloat())
            {
                if (Unit.HasFlags(CompileUnitFlags.UseGPUMath))
                {
                    MakeIntrinsicMathOperation(
                        type,
                        basicValueType == BasicValueType.Single ? MathDivF32 : MathDivF64,
                        left,
                        right);
                }
                else
                {
                    CurrentBlock.Push(type, BuildFDiv(Builder, left, right, name));
                }
            }
            else if (forceUnsigned || basicValueType.IsUnsignedInt())
            {
                CurrentBlock.Push(type, BuildUDiv(Builder, left, right, name));
            }
            else
            {
                CurrentBlock.Push(type, BuildSDiv(Builder, left, right, name));
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Creates a call instruction to the given method with the given arguments.
        /// </summary>
        /// <param name="target">The target method to invoke.</param>
        /// <param name="args">The call arguments</param>
        private void CreateCall(MethodBase target, Value[] args)
        {
            var intrinsicContext = new InvocationContext(Builder, Method, target, args, this);
            // Check for remapping first
            var remappedContext = Unit.RemapIntrinsic(intrinsicContext);

            if (remappedContext != null)
            {
                intrinsicContext = remappedContext.Value;
            }

            // Early rejection for runtime-dependent methods
            VerifyNotRuntimeMethod(CompilationContext, intrinsicContext.Method);

            // Handle device functions
            if (!Unit.HandleIntrinsic(intrinsicContext, out Value? methodInvocationResult))
            {
                var method   = Unit.GetMethod(intrinsicContext.Method);
                var llvmArgs = new LLVMValueRef[args.Length];
                for (int i = 0, e = args.Length; i < e; ++i)
                {
                    llvmArgs[i] = args[i].LLVMValue;
                }
                var call = BuildCall(Builder, method.LLVMFunction, llvmArgs);
                if (!method.IsVoid)
                {
                    methodInvocationResult = new Value(method.ReturnType, call);
                }
            }
            if (methodInvocationResult.HasValue)
            {
                CurrentBlock.Push(methodInvocationResult.Value);
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Realizes a new-object operation that creates a new instance of a specified type.
        /// </summary>
        /// <param name="method">The target method.</param>
        private void MakeNewObject(MethodBase method)
        {
            var constructor = method as ConstructorInfo;

            if (constructor == null)
            {
                throw CompilationContext.GetInvalidILCodeException();
            }
            var type     = constructor.DeclaringType;
            var llvmType = Unit.GetType(type);

            // Use a temporary alloca to realize object creation
            // and initialize object with zero
            var tempAlloca = CreateTempAlloca(llvmType);

            BuildStore(Builder, ConstNull(llvmType), tempAlloca);

            // Invoke constructor for type
            Value[] values = new Value[constructor.GetParameters().Length + 1];
            values[0] = new Value(type.MakePointerType(), tempAlloca);
            CurrentBlock.PopMethodArgs(constructor, values, 1);
            CreateCall(constructor, values);

            // Push created instance on the stack
            if (type.IsValueType)
            {
                CurrentBlock.Push(type, BuildLoad(Builder, values[0].LLVMValue, string.Empty));
            }
            else
            {
                CurrentBlock.Push(values[0]);
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Loads the constant null.
        /// </summary>
        private void LoadNull()
        {
            var t = typeof(object);

            CurrentBlock.Push(
                t.MakePointerType(),
                ConstNull(Unit.GetType(t)));
        }
Exemplo n.º 7
0
        /// <summary>
        /// Loads a static field specified by the given metadata token.
        /// </summary>
        /// <param name="field">The field.</param>
        private void LoadStaticField(FieldInfo field)
        {
            VerifyStaticFieldLoad(CompilationContext, Unit.Flags, field);

            var value = field.GetValue(null);

            CurrentBlock.Push(field.FieldType, Unit.GetValue(field.FieldType, value));
        }
Exemplo n.º 8
0
        /// <summary>
        /// Loads the address of an array element.
        /// </summary>
        private void LoadArrayElementAddress()
        {
            var idx   = CurrentBlock.PopInt();
            var array = CurrentBlock.Pop();

            Debug.Assert(array.ValueType.IsArray);
            var addr = ComputeArrayAddress(array.LLVMValue, idx.LLVMValue);

            CurrentBlock.Push(array.ValueType.GetElementType().MakePointerType(), addr);
        }
Exemplo n.º 9
0
        /// <summary>
        /// Loads an array element.
        /// </summary>
        /// <param name="type">The type of element to load.</param>
        private void LoadArrayElement(Type type)
        {
            var idx   = CurrentBlock.PopInt();
            var array = CurrentBlock.Pop();

            Debug.Assert(array.ValueType.IsArray);
            var addr  = ComputeArrayAddress(array.LLVMValue, idx.LLVMValue);
            var value = BuildLoad(Builder, addr, string.Empty);

            CurrentBlock.Push(CreateConversion(new Value(array.ValueType.GetElementType(), value), type));
        }
Exemplo n.º 10
0
 /// <summary>
 /// Loads a variable. This can be an argument or a local reference.
 /// </summary>
 /// <param name="var">The variable reference.</param>
 private void LoadVariable(VariableRef var)
 {
     Debug.Assert(var.RefType == VariableRefType.Argument || var.RefType == VariableRefType.Local);
     if (variables.TryGetValue(var, out Value nonSSAValue))
     {
         var load = BuildLoad(Builder, nonSSAValue.LLVMValue, string.Empty);
         CurrentBlock.Push(nonSSAValue.ValueType, load);
     }
     else
     {
         CurrentBlock.Push(CurrentBlock.GetValue(var));
     }
 }
Exemplo n.º 11
0
 /// <summary>
 /// Loads a double.
 /// </summary>
 private void Load(double value)
 {
     if (Unit.Force32BitFloats)
     {
         Load((float)value);
     }
     else
     {
         CurrentBlock.Push(
             typeof(double),
             ConstReal(LLVMContext.DoubleType, value));
     }
 }
Exemplo n.º 12
0
        /// <summary>
        /// Realizes a numeric-neg instruction.
        /// </summary>
        private void MakeNumericNeg()
        {
            var value = CurrentBlock.Pop();
            var name  = string.Empty;

            if (value.ValueType.IsFloat())
            {
                CurrentBlock.Push(value.ValueType, BuildFNeg(Builder, value.LLVMValue, name));
            }
            else
            {
                CurrentBlock.Push(value.ValueType, BuildNeg(Builder, value.LLVMValue, name));
            }
        }
Exemplo n.º 13
0
        /// <summary>
        /// Realizes a numeric-shr instruction.
        /// </summary>
        /// <param name="forceUnsigned">True if the comparison should be forced to be unsigned.</param>
        private void MakeNumericShr(bool forceUnsigned = false)
        {
            var type = CurrentBlock.PopArithmeticArgs(out LLVMValueRef left, out LLVMValueRef right);
            var name = string.Empty;

            if (forceUnsigned || type.IsUnsignedInt())
            {
                CurrentBlock.Push(type, BuildLShr(Builder, left, right, name));
            }
            else
            {
                CurrentBlock.Push(type, BuildAShr(Builder, left, right, name));
            }
        }
Exemplo n.º 14
0
        /// <summary>
        /// Realizes a local stackalloc instruction.
        /// </summary>
        private void MakeLocalAlloc()
        {
            var size        = CurrentBlock.Pop();
            var arrayLength = size.LLVMValue;

            if (!IsConstant(arrayLength))
            {
                throw CompilationContext.GetNotSupportedException(
                          ErrorMessages.NotSupportedUnsafeAllocation);
            }
            // Allocate the element data first in a local alloca
            var llvmElementType = LLVMContext.Int8Type;
            var arrayData       = BuildArrayAlloca(Builder, llvmElementType, arrayLength, "localloc");

            CurrentBlock.Push(typeof(byte).MakePointerType(), arrayData);
        }
Exemplo n.º 15
0
 /// <summary>
 /// Constructs general math intrinsics.
 /// </summary>
 /// <param name="type">The type of the operation.</param>
 /// <param name="targetMethod">A reference to a specific target method.</param>
 /// <param name="left">The left param.</param>
 /// <param name="right">The right param.</param>
 private void MakeIntrinsicMathOperation(
     Type type,
     MethodInfo targetMethod,
     LLVMValueRef left,
     LLVMValueRef right)
 {
     if (!Unit.HandleIntrinsic(new InvocationContext(
                                   Builder,
                                   Method,
                                   targetMethod, new Value[]
     {
         new Value(type, left),
         new Value(type, right),
     }, this), out Value? result) || !result.HasValue)
     {
         throw CompilationContext.GetInvalidOperationException(
                   ErrorMessages.InvalidMathIntrinsic, targetMethod.Name);
     }
     CurrentBlock.Push(result.Value);
 }
Exemplo n.º 16
0
        /// <summary>
        /// Realizes an arithmetic add operation.
        /// </summary>
        /// <param name="overflow">True, if an overflow has to be checked.</param>
        private void MakeArithmeticAdd(bool overflow)
        {
            if (overflow)
            {
                throw new NotSupportedException();
            }
            Type type = CurrentBlock.PopArithmeticArgs(out LLVMValueRef left, out LLVMValueRef right);
            var  name = string.Empty;

            if (type.GetBasicValueType() == BasicValueType.Ptr)
            {
                CurrentBlock.Push(type, BuildInBoundsGEP(Builder, left, right));
            }
            else if (type.IsFloat())
            {
                CurrentBlock.Push(type, BuildFAdd(Builder, left, right, name));
            }
            else
            {
                Debug.Assert(type.IsInt());
                CurrentBlock.Push(type, BuildAdd(Builder, left, right, name));
            }
        }
Exemplo n.º 17
0
        /// <summary>
        /// Realizes an arithmetic sub operation.
        /// </summary>
        /// <param name="overflow">True, if an overflow has to be checked.</param>
        private void MakeArithmeticSub(bool overflow)
        {
            if (overflow)
            {
                throw new NotSupportedException();
            }
            Type type = CurrentBlock.PopArithmeticArgs(out LLVMValueRef left, out LLVMValueRef right);
            var  name = string.Empty;

            if (type.GetBasicValueType() == BasicValueType.Ptr)
            {
                right = BuildSub(Builder, ConstPointerNull(TypeOf(right)), right, name);
                CurrentBlock.Push(type, BuildInBoundsGEP(Builder, left, right));
            }
            if (type.IsFloat())
            {
                CurrentBlock.Push(type, BuildFSub(Builder, left, right, name));
            }
            else
            {
                CurrentBlock.Push(type, BuildSub(Builder, left, right, name));
            }
        }
Exemplo n.º 18
0
        /// <summary>
        /// Realizes a numeric-shl instruction.
        /// </summary>
        private void MakeNumericShl()
        {
            var type = CurrentBlock.PopArithmeticArgs(out LLVMValueRef left, out LLVMValueRef right);

            CurrentBlock.Push(type, BuildShl(Builder, left, right, string.Empty));
        }
Exemplo n.º 19
0
 /// <summary>
 /// Loads a long.
 /// </summary>
 private void Load(long value)
 {
     CurrentBlock.Push(
         typeof(long),
         ConstInt(LLVMContext.Int64Type, value, true));
 }
Exemplo n.º 20
0
        /// <summary>
        /// Realizes a numeric-not instruction.
        /// </summary>
        private void MakeNumericNot()
        {
            var value = CurrentBlock.Pop();

            CurrentBlock.Push(value.ValueType, BuildNot(Builder, value.LLVMValue, string.Empty));
        }
Exemplo n.º 21
0
        /// <summary>
        /// Realizes a cast operation that casts a given class to another type.
        /// </summary>
        /// <param name="targetType">The target type.</param>
        private void MakeCastClass(Type targetType)
        {
            var value = CurrentBlock.Pop();

            CurrentBlock.Push(CreateCastClass(value, targetType));
        }
Exemplo n.º 22
0
 /// <summary>
 /// Loads an int.
 /// </summary>
 private void Load(int value)
 {
     CurrentBlock.Push(
         typeof(int),
         ConstInt(LLVMContext.Int32Type, value, true));
 }
Exemplo n.º 23
0
        /// <summary>
        /// Realizes a convert instruction.
        /// </summary>
        /// <param name="targetType">The target type.</param>
        /// <param name="forceUnsigned">True, if the comparison should be forced to be unsigned.</param>
        private void MakeConvert(Type targetType, bool forceUnsigned = false)
        {
            var value = CurrentBlock.Pop();

            CurrentBlock.Push(CreateConversion(value, targetType, forceUnsigned));
        }
Exemplo n.º 24
0
 /// <summary>
 /// Loads a float.
 /// </summary>
 private void Load(float value)
 {
     CurrentBlock.Push(
         typeof(float),
         ConstReal(LLVMContext.FloatType, value));
 }
Exemplo n.º 25
0
        /// <summary>
        /// Loads the address of a field specified by the given metadata token.
        /// </summary>
        /// <param name="field">The field.</param>
        private void LoadFieldAddress(FieldInfo field)
        {
            var value = CurrentBlock.Pop();

            CurrentBlock.Push(field.FieldType.MakePointerType(), LoadFieldAddress(field, value));
        }
Exemplo n.º 26
0
 /// <summary>
 /// Loads a string.
 /// </summary>
 private void LoadString(string value)
 {
     CurrentBlock.Push(
         typeof(string),
         BuildGlobalStringPtr(Builder, value, string.Empty));
 }
Exemplo n.º 27
0
 /// <summary>
 /// Realizes a compare instruction of the given type.
 /// </summary>
 /// <param name="compareType">The comparison type to use.</param>
 /// <param name="forceUnsigned">True, if the comparison should be forced to be unsigned.</param>
 private void MakeCompare(CompareType compareType, bool forceUnsigned = false)
 {
     CurrentBlock.Push(CreateCompare(compareType, forceUnsigned));
 }