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); }
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)); } }
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(); }
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)); }