示例#1
0
 private static bool IsDereferenceableType(IType Type)
 {
     if (Type.GetIsPointer())
     {
         var ptrType = Type.AsPointerType();
         if (ptrType.PointerKind.Equals(PointerKind.ReferencePointer))
         {
             return(true);
         }
     }
     else if (Type is LLVMType && ((LLVMType)Type).IsSingleValue)
     {
         return(IsDereferenceableType(((LLVMType)Type).InstanceFields[0].FieldType));
     }
     return(false);
 }
示例#2
0
        private static string EncodeTypeName(IType Type, bool IncludeNamespace)
        {
            string result;

            if (builtinTypeNames.TryGetValue(Type, out result))
            {
                return(result);
            }
            else if (Type.GetIsPointer())
            {
                var    ptrType = Type.AsPointerType();
                string prefix;
                if (!pointerKindNames.TryGetValue(ptrType.PointerKind, out prefix))
                {
                    // Use a vendor-specific prefix if we can't map the pointer kind
                    // to a C++ pointer kind.
                    prefix = "U" + EncodeUnqualifiedName("P" + ptrType.PointerKind.Extension);
                }
                return(prefix + EncodeTypeName(ptrType.ElementType));
            }
            else if (Type.GetIsArray())
            {
                var arrayType = Type.AsArrayType();
                return("U" + EncodeUnqualifiedName("Array" + arrayType.ArrayRank + "D" + EncodeTypeName(arrayType.ElementType)));
            }
            else if (Type.GetIsGenericInstance())
            {
                return(EncodeGenericInstanceName(
                           EncodeTypeName(Type.GetGenericDeclaration(), IncludeNamespace),
                           Type.GetGenericArguments()));
            }
            else if (IncludeNamespace)
            {
                return(EncodeQualifiedName(Type));
            }
            else
            {
                return(EncodeUnqualifiedName(Type.Name));
            }
        }
示例#3
0
        public ICodeBlock EmitTypeBinary(ICodeBlock Value, IType Type, Operator Op)
        {
            var valBlock = (CodeBlock)Value;

            if (Op.Equals(Operator.ReinterpretCast))
            {
                if (valBlock.Type.GetIsValueType() && Type.GetIsValueType())
                {
                    return(new RetypedBlock(this, valBlock, Type));
                }
                else
                {
                    return(new SimpleCastBlock(this, valBlock, Type, BuildPointerCast, ConstPointerCast));
                }
            }
            else if (Op.Equals(Operator.IsInstance))
            {
                // If T is virtual/abstract/interface, then rewrite `x is T` as
                // `x != (decltype(x))null && x->vtable.typeid % T.vtable.typeid == 0`.
                //
                // Otherwise, we can use
                // `x != (decltype(x))null && x->vtable == T.vtable`.
                bool isVirtual = Type.GetIsVirtual() ||
                                 Type.GetIsAbstract() ||
                                 Type.GetIsInterface();

                var valTmp = DeclareLocal(new UniqueTag("is_tmp"), new TypeVariableMember(valBlock.Type));

                var valVTablePtr  = (CodeBlock)EmitDereferencePointer(EmitVTablePtr(valTmp.EmitGet()), true);
                var typeVTablePtr = new TypeVTableBlock(this, (LLVMType)Type);

                return(EmitSequence(
                           valTmp.EmitSet(valBlock),
                           this.EmitLogicalAnd(
                               EmitBinary(
                                   valTmp.EmitGet(),
                                   EmitTypeBinary(EmitNull(), valBlock.Type, Operator.ReinterpretCast),
                                   Operator.CheckInequality),
                               isVirtual
                            ? EmitBinary(
                                   EmitBinary(
                                       new TypeIdBlock(this, valVTablePtr),
                                       new TypeIdBlock(this, typeVTablePtr),
                                       Operator.Remainder),
                                   EmitInteger(new IntegerValue(0UL)),
                                   Operator.CheckEquality)
                            : EmitBinary(
                                   valVTablePtr,
                                   typeVTablePtr,
                                   Operator.CheckEquality))));
            }
            else if (Op.Equals(Operator.AsInstance))
            {
                // Rewrite `x as T` as `x is T ? x : null`.
                var valTmp = DeclareLocal(new UniqueTag("as_tmp"), new TypeVariableMember(valBlock.Type));
                return(EmitSequence(
                           valTmp.EmitSet(valBlock),
                           EmitIfElse(
                               EmitTypeBinary(valTmp.EmitGet(), Type, Operator.IsInstance),
                               EmitTypeBinary(valTmp.EmitGet(), Type, Operator.ReinterpretCast),
                               EmitTypeBinary(EmitNull(), Type, Operator.ReinterpretCast))));
            }
            else if (Op.Equals(Operator.DynamicCast))
            {
                // Rewrite `(T)x` as `x is T ? x : invalid-cast(T)`.
                var valTmp = DeclareLocal(new UniqueTag("dyn_cast_tmp"), new TypeVariableMember(valBlock.Type));
                return(EmitSequence(
                           valTmp.EmitSet(valBlock),
                           EmitIfElse(
                               EmitTypeBinary(valTmp.EmitGet(), Type, Operator.IsInstance),
                               EmitTypeBinary(valTmp.EmitGet(), Type, Operator.ReinterpretCast),
                               EmitThrowInvalidCast((CodeBlock)valTmp.EmitGet(), Type, Type))));
            }
            else if (Op.Equals(Operator.UnboxReference))
            {
                // Rewrite `#unbox_ref(x, T*)` as `x is T ? &x->value : invalid-cast(T)`.
                var elemType = Type.AsPointerType().ElementType;
                var valTmp   = DeclareLocal(new UniqueTag("unbox_ref_tmp"), new TypeVariableMember(valBlock.Type));
                return(EmitSequence(
                           valTmp.EmitSet(valBlock),
                           EmitIfElse(
                               EmitTypeBinary(valTmp.EmitGet(), elemType, Operator.IsInstance),
                               new UnboxBlock(this, (CodeBlock)valTmp.EmitGet(), elemType),
                               EmitThrowInvalidCast((CodeBlock)valTmp.EmitGet(), elemType, Type))));
            }
            else if (Op.Equals(Operator.UnboxValue))
            {
                if (Type.GetIsValueType())
                {
                    // If `T` is a `struct`, then `#unbox_val(x, T)` is equivalent to
                    // `*#unbox_ref(x, T*)`.
                    return(EmitDereferencePointer(
                               EmitTypeBinary(
                                   valBlock,
                                   Type.MakePointerType(PointerKind.TransientPointer),
                                   Operator.UnboxReference)));
                }
                else
                {
                    // If `T` is a `class`, then `#unbox_val(x, T)` is equivalent to
                    // `#dynamic_cast(x, T)`.
                    return(EmitTypeBinary(valBlock, Type, Operator.DynamicCast));
                }
            }
            else if (Op.Equals(Operator.StaticCast))
            {
                var valType = valBlock.Type;
                if (valType.GetIsInteger() && Type.GetIsInteger())
                {
                    var valSpec    = valType.GetIntegerSpec();
                    var targetSpec = Type.GetIntegerSpec();
                    if (valSpec.Size == targetSpec.Size)
                    {
                        return(new RetypedBlock(this, valBlock, Type));
                    }
                    else if (valSpec.Size > targetSpec.Size)
                    {
                        return(new SimpleCastBlock(this, valBlock, Type, BuildTrunc, ConstTrunc));
                    }
                    else if (valSpec.IsSigned)
                    {
                        return(new SimpleCastBlock(this, valBlock, Type, BuildSExt, ConstSExt));
                    }
                    else
                    {
                        return(new SimpleCastBlock(this, valBlock, Type, BuildZExt, ConstZExt));
                    }
                }
                else if (valType == PrimitiveTypes.Char)
                {
                    return(EmitTypeBinary(new RetypedBlock(this, valBlock, PrimitiveTypes.UInt16), Type, Op));
                }
                else if (Type == PrimitiveTypes.Char)
                {
                    return(new RetypedBlock(this, (CodeBlock)EmitTypeBinary(valBlock, PrimitiveTypes.UInt16, Op), Type));
                }
                else if (valType.GetIsPointer() && Type.GetIsInteger())
                {
                    return(new SimpleCastBlock(this, valBlock, Type, BuildPtrToInt, ConstPtrToInt));
                }
                else if (valType.GetIsInteger() && Type.GetIsPointer())
                {
                    return(new SimpleCastBlock(this, valBlock, Type, BuildIntToPtr, ConstIntToPtr));
                }
                else if (valType.GetIsSignedInteger() && Type.GetIsFloatingPoint())
                {
                    return(new SimpleCastBlock(this, valBlock, Type, BuildSIToFP, ConstSIToFP));
                }
                else if (valType.GetIsUnsignedInteger() && Type.GetIsFloatingPoint())
                {
                    return(new SimpleCastBlock(this, valBlock, Type, BuildUIToFP, ConstUIToFP));
                }
                else if (valType.GetIsFloatingPoint() && Type.GetIsSignedInteger())
                {
                    return(new SimpleCastBlock(this, valBlock, Type, BuildFPToSI, ConstFPToSI));
                }
                else if (valType.GetIsFloatingPoint() && Type.GetIsUnsignedInteger())
                {
                    return(new SimpleCastBlock(this, valBlock, Type, BuildFPToUI, ConstFPToUI));
                }
                else if (valType.GetIsFloatingPoint() && Type.GetIsFloatingPoint())
                {
                    return(new SimpleCastBlock(this, valBlock, Type, BuildFPCast, ConstFPCast));
                }
                else if (valType.GetIsEnum())
                {
                    return(EmitTypeBinary(new RetypedBlock(this, valBlock, valType.GetParent()), Type, Op));
                }
                else if (Type.GetIsEnum())
                {
                    return(new RetypedBlock(this, (CodeBlock)EmitTypeBinary(valBlock, Type.GetParent(), Op), Type));
                }
                else if (IsRuntimeDelegate(valType) && IsRuntimeDelegate(Type))
                {
                    if (object.Equals(Type, valType))
                    {
                        return(valBlock);
                    }
                    else if (valBlock is DelegateBlock)
                    {
                        var delegBlock = (DelegateBlock)valBlock;
                        return(new DelegateBlock(
                                   this,
                                   delegBlock.Callee,
                                   delegBlock.Target,
                                   delegBlock.Op,
                                   Type));
                    }
                    else
                    {
                        return(new DelegateCastBlock(this, valBlock, Type));
                    }
                }
            }
            throw new NotImplementedException();
        }
示例#4
0
        private LLVMTypeRef DeclareTypeImpl(IType Type)
        {
            if (Type.GetIsPointer())
            {
                var ptrType  = Type.AsPointerType();
                var elemType = ptrType.ElementType;
                if (elemType == PrimitiveTypes.Void)
                {
                    return(LLVMSharp.LLVM.PointerType(Int8Type(), 0));
                }
                else if (ptrType.PointerKind.Equals(PointerKind.BoxPointer))
                {
                    // A boxed T is represented as a `{ byte*, T }*`.
                    return(LLVMSharp.LLVM.PointerType(
                               StructType(
                                   new LLVMTypeRef[]
                    {
                        LLVMSharp.LLVM.PointerType(Int8Type(), 0),
                        Declare(elemType)
                    },
                                   false),
                               0));
                }
                else
                {
                    return(LLVMSharp.LLVM.PointerType(Declare(elemType), 0));
                }
            }
            else if (Type.GetIsArray())
            {
                // We'll lay out arrays like so:
                //
                //     { i32, ..., [0 x <type>] }
                //
                // where the first fields are the dimensions and the last field
                // is the data. When we allocate an array, we'll allocate the
                // right amount of tail room for the data by allocating
                // `sizeof(i32, ..., [0 x <type>])` bytes.

                var elemType = Type.AsArrayType().ElementType;
                var fields   = new LLVMTypeRef[Type.AsArrayType().ArrayRank + 1];
                for (int i = 0; i < fields.Length - 1; i++)
                {
                    fields[i] = Int32Type();
                }
                fields[fields.Length - 1] = ArrayType(Declare(elemType), 0);
                return(LLVMSharp.LLVM.PointerType(
                           StructType(fields, false),
                           0));
            }
            else if (Type.GetIsInteger() || Type.GetIsBit())
            {
                return(IntType((uint)Type.GetPrimitiveBitSize()));
            }
            else if (Type == PrimitiveTypes.Float32)
            {
                return(FloatType());
            }
            else if (Type == PrimitiveTypes.Float64)
            {
                return(DoubleType());
            }
            else if (Type == PrimitiveTypes.Void)
            {
                return(VoidType());
            }
            else if (Type == PrimitiveTypes.Char)
            {
                return(IntType(16));
            }
            else if (Type == PrimitiveTypes.Boolean)
            {
                return(Int1Type());
            }
            else if (Type is LLVMType)
            {
                var llvmType = (LLVMType)Type;
                if (llvmType.GetIsValueType() || llvmType.GetIsEnum())
                {
                    return(DeclareDataLayout(llvmType));
                }
                else if (llvmType.GetIsReferenceType())
                {
                    return(PointerType(DeclareDataLayout(llvmType), 0));
                }
            }
            else if (Type is MethodType)
            {
                return(PointerType(DelegateBlock.MethodTypeLayout, 0));
            }
            else if (Type.GetIsReferenceType())
            {
                // We don't know what the reference type's layout is, so the
                // best we can do is to just create a void pointer.
                return(PointerType(Int8Type(), 0));
            }
            throw new NotImplementedException(string.Format("Type not supported: '{0}'", Type));
        }