public static ESIR_CastExpression CastExpression(ESIR_Expression expression, ESIR_TypeNode destType) { var node = ESIR_NodeCache.Shared.TryGetNode(ESIR_NodeKind.CastExpression, expression, destType, out var hash); if (node is not null) { return((ESIR_CastExpression)node); } var ret = new ESIR_CastExpression(expression, destType); if (hash >= 0) { ESIR_NodeCache.Shared.AddNode(ret, hash); } return(ret); }
private static ExpressionData CompileExpression_Cast( ref PassData passData, ref FunctionData funcData, ESIR_CastExpression expr ) { var origExpr = CompileExpression(ref passData, ref funcData, expr.Expression); var destType = StripFirstConst(expr.DestType.Pointer); StripFirstConst(ref origExpr); var origVal = origExpr.Value !; Debug.Assert(origVal is not null); ES_TypeInfo * retType; ExpressionSyntax retValue; if (IsTypeEquivalent(origExpr.Type, destType)) { retType = destType; var origTypeRoslyn = GetRoslynType(origExpr.Type); var destTypeRoslyn = GetRoslynType(destType); if (!origTypeRoslyn.IsEquivalentTo(destTypeRoslyn)) { retValue = CastExpression(destTypeRoslyn, origVal); } else { retValue = origVal; } } else { switch (origExpr.Type->TypeTag) { case ES_TypeTag.Int: { var intSrc = (ES_IntTypeData *)origExpr.Type; if (destType->TypeTag == ES_TypeTag.Int) { var intDest = (ES_IntTypeData *)destType; if (intDest->IntSize == intSrc->IntSize && intDest->Unsigned == intSrc->Unsigned) { origExpr.Writable = false; return(origExpr); } var roslynDestType = GetIntType(intDest->IntSize, intDest->Unsigned); retValue = CastExpression(roslynDestType, origVal); } else if (destType->TypeTag == ES_TypeTag.Float) { var floatDest = (ES_FloatTypeData *)destType; var roslynDestType = GetFloatType(floatDest->FloatSize); retValue = CastExpression(roslynDestType, origVal); } else { throw new CompilationException(ES_BackendErrors.FrontendError); } retType = destType; break; } case ES_TypeTag.Float: { var floatSrc = (ES_FloatTypeData *)origExpr.Type; if (destType->TypeTag == ES_TypeTag.Float) { var floatDest = (ES_FloatTypeData *)destType; if (floatSrc->FloatSize == floatDest->FloatSize) { origExpr.Writable = false; return(origExpr); } var roslynDestType = GetFloatType(floatDest->FloatSize); retValue = CastExpression(roslynDestType, origVal); } else if (destType->TypeTag == ES_TypeTag.Int) { var intDest = (ES_IntTypeData *)destType; var roslynDestType = GetIntType(intDest->IntSize, intDest->Unsigned); retValue = CastExpression(roslynDestType, origVal); } else { throw new CompilationException(ES_BackendErrors.FrontendError); } retType = destType; break; } default: throw new NotImplementedException("Cast not implemented."); } } return(new ExpressionData { Type = retType, Value = retValue, }); }