public static void AssertCanAssignImplicitly(this Type type, Type other) { if (!type.CanAssignImplicitly(other)) { throw new TypeMismatchException(type.ToString(), other.ToString()); } }
public static Register MakeRegisterWithCorrectSize(this Type type, Register64 intRegister, XmmRegister floatRegister) { if (!type.IsIntegerRegisterType()) { return(floatRegister); } switch (type.SizeOf()) { case 8: return(intRegister); case 4: return((Register32)intRegister); case 2: return((Register16)intRegister); case 1: return((Register8)intRegister); default: throw new NotImplementedException($"Proper register for type {type} (size {type.SizeOf()}) has not been implemented yet"); } }
public ExpressionResult(Type valueType, Register64 ptr, int offset, Segment segment = Segment.DS) { ValueType = valueType ?? throw new ArgumentNullException(nameof(valueType)); Ptr = ptr; Offset = offset; Segment = segment; Kind = ResultKind.Pointer; }
public static Register MakeRegisterWithCorrectSize(this Type type, Register register) { if (register.FloatingPoint) { return(register); } return(MakeRegisterWithCorrectSize(type, register.AsR64(), default)); }
public static Register OtherVolatileFloatRegister(this Type targetType, params Register[] occupiedRegisters) { if (targetType == null) { throw new ArgumentNullException(nameof(targetType)); } if (occupiedRegisters.Length >= VolatileFloatRegisters.Length) { throw new ArgumentException("No registers left", nameof(occupiedRegisters)); } return(VolatileFloatRegisters.First(vol => occupiedRegisters.All(occ => !occ.IsSameRegister(vol)))); }
public ExpressionResult(Type valueType, Register64 ptr, byte ptrMul, int offsetFlat = 0, Segment segment = Segment.DS) { if (ptrMul != 1 && ptrMul != 2 && ptrMul != 4 && ptrMul != 8) { throw new ArgumentOutOfRangeException("The multiplicative offset may only be 1, 2, 4 or 8"); } ValueType = valueType ?? throw new ArgumentNullException(nameof(valueType)); Ptr = ptr; OffsetMul = ptrMul; Offset = offsetFlat; Segment = segment; Kind = ResultKind.Pointer3; }
public static bool CanAssignImplicitly(this Type type, Type source) { if (type.ChildRelation != source.ChildRelation) // cannot do weird stuff implicitly { return(false); } if (type.ChildRelation == Type.WrappingType.None) // if they are the same type, or can be promoted to the same type, we are good { return(type.PrimitiveType == source.PrimitiveType || CanPromote(type.PrimitiveType, source.PrimitiveType)); } return(CanAssignImplicitly(type.Child, source.Child)); // unwrap pointer/array/... and check type underneath }
public void GenerateMoveTo(Register target, Type targetType, CodeGen codeGen, ILinkingInfo fixer, bool isExplicitCast = false) { if (!isExplicitCast && !targetType.CanAssignImplicitly(ValueType)) { throw new TypeMismatchException(targetType.ToString(), ValueType.ToString()); } if (!target.FloatingPoint && target.BitSize / 8 != targetType.SizeOf()) { throw new ArgumentException($"Value of type {targetType} can not be moved to register {target}"); } if (targetType == ValueType) { GenerateMoveTo(target, codeGen, fixer); return; } if (targetType.SizeOf() < ValueType.SizeOf()) { throw new ArgumentException($"Cannot narrow type from {ValueType} to {targetType} without a cast", nameof(targetType)); } var signed = targetType.IsSignedInteger(); switch (Kind) { case ResultKind.Value: GenerateUpgradeToValue(target, codeGen, signed); return; case ResultKind.Pointer: GenerateUpgradeToPointer(target, codeGen, signed); return; case ResultKind.Pointer2: GenerateUpgradeToPointer2(target, codeGen, signed); return; case ResultKind.Pointer3: GenerateUpgradeToPointer3(target, codeGen, signed); return; case ResultKind.Offset: GenerateUpgradeToOffset(target, codeGen, fixer, signed); return; default: throw new NotImplementedException($"{nameof(ExpressionResult)}: {nameof(GenerateMoveTo)} has not implemented kind: {Kind}"); } }
/// <summary> /// Returns if a value of this type should be stored in general purpose (int) registers, or SSE2 registers (e.g. float, /// double) /// </summary> /// <param name="type"></param> /// <returns></returns> public static bool IsIntegerRegisterType(this Type type) { if (type.ChildRelation != Type.WrappingType.None) { return(true); } switch (type.PrimitiveType) { case "float": case "double": return(false); } return(true); }
public static int SizeOf(this Type type) { switch (type.ChildRelation) { case Type.WrappingType.None: return(SizeOfPrimitiveType(type.PrimitiveType)); case Type.WrappingType.PointerOf: return(8); case Type.WrappingType.ArrayOf: return(8); default: throw new ArgumentOutOfRangeException(); } }
public static bool IsSignedInteger(this Type type) { if (type.ChildRelation != Type.WrappingType.None) { return(false); } switch (type.PrimitiveType) { case "long": case "int": case "short": case "sbyte": return(true); } return(false); }
public ExpressionResult(Type valueType, Register valueRegister) { if (valueType == null) { throw new ArgumentNullException(nameof(valueType)); } if (valueRegister == null) { throw new ArgumentNullException(nameof(valueRegister)); } if (valueType.IsIntegerRegisterType() == valueRegister.FloatingPoint) { throw new ArgumentException("Type does not match register"); } if (!valueRegister.FloatingPoint && valueType.SizeOf() != valueRegister.BitSize / 8) { throw new ArgumentException($"Bad register for type: {valueRegister} {valueType}"); } ValueType = valueType; Value = valueRegister; Kind = ResultKind.Value; }
public ExpressionResult(Type valueType, Action <ILinkingInfo, CodeGen> offsetFixup) { ValueType = valueType ?? throw new ArgumentNullException(nameof(valueType)); OffsetFixup = offsetFixup ?? throw new ArgumentNullException(nameof(offsetFixup)); Kind = ResultKind.Offset; }
public Register GetOccupiedOrVolatile(Type type) {
public void ChangeTypeUnsafe(Type newTypeUnsafe) => ValueType = newTypeUnsafe;