@@ -56,6 +56,8 @@ enum class WellKnownFunction {
56
56
StringEquals,
57
57
// String.percentEscapedString.getter
58
58
StringEscapePercent,
59
+ // BinaryInteger.description.getter
60
+ BinaryIntegerDescription,
59
61
// _assertionFailure(_: StaticString, _: StaticString, file: StaticString,...)
60
62
AssertionFailure,
61
63
// A function taking one argument that prints the symbolic value of the
@@ -83,6 +85,8 @@ static llvm::Optional<WellKnownFunction> classifyFunction(SILFunction *fn) {
83
85
return WellKnownFunction::StringEquals;
84
86
if (fn->hasSemanticsAttr (semantics::STRING_ESCAPE_PERCENT_GET))
85
87
return WellKnownFunction::StringEscapePercent;
88
+ if (fn->hasSemanticsAttr (semantics::BINARY_INTEGER_DESCRIPTION))
89
+ return WellKnownFunction::BinaryIntegerDescription;
86
90
if (fn->hasSemanticsAttrThatStartsWith (" programtermination_point" ))
87
91
return WellKnownFunction::AssertionFailure;
88
92
// A call to a function with the following semantics annotation will be
@@ -789,6 +793,28 @@ static Type getArrayElementType(Type ty) {
789
793
return Type ();
790
794
}
791
795
796
+ // / Check if the given type \p ty is a stdlib integer type and if so return
797
+ // / whether the type is signed. Returns \c None if \p ty is not a stdlib integer
798
+ // / type, \c true if it is a signed integer type and \c false if it is an
799
+ // / unsigned integer type.
800
+ static Optional<bool > getSignIfStdlibIntegerType (Type ty) {
801
+ StructDecl *decl = ty->getStructOrBoundGenericStruct ();
802
+ if (!decl)
803
+ return None;
804
+ ASTContext &astCtx = ty->getASTContext ();
805
+ if (decl == astCtx.getIntDecl () || decl == astCtx.getInt8Decl () ||
806
+ decl == astCtx.getInt16Decl () || decl == astCtx.getInt32Decl () ||
807
+ decl == astCtx.getInt64Decl ()) {
808
+ return true ;
809
+ }
810
+ if (decl == astCtx.getUIntDecl () || decl == astCtx.getUInt8Decl () ||
811
+ decl == astCtx.getUInt16Decl () || decl == astCtx.getUInt32Decl () ||
812
+ decl == astCtx.getUInt64Decl ()) {
813
+ return false ;
814
+ }
815
+ return None;
816
+ }
817
+
792
818
// / Given a call to a well known function, collect its arguments as constants,
793
819
// / fold it, and return None. If any of the arguments are not constants, marks
794
820
// / the call's results as Unknown, and return an Unknown with information about
@@ -1064,6 +1090,42 @@ ConstExprFunctionState::computeWellKnownCallResult(ApplyInst *apply,
1064
1090
setValue (apply, resultVal);
1065
1091
return None;
1066
1092
}
1093
+ case WellKnownFunction::BinaryIntegerDescription: {
1094
+ // BinaryInteger.description.getter
1095
+ assert (conventions.getNumDirectSILResults () == 1 &&
1096
+ conventions.getNumIndirectSILResults () == 0 &&
1097
+ conventions.getNumParameters () == 1 && apply->hasSubstitutions () &&
1098
+ " unexpected BinaryInteger.description.getter signature" );
1099
+ // Get the type of the argument and check if it is a signed or
1100
+ // unsigned integer.
1101
+ SILValue integerArgument = apply->getOperand (1 );
1102
+ CanType argumentType = substituteGenericParamsAndSimpify (
1103
+ integerArgument->getType ().getASTType ());
1104
+ Optional<bool > isSignedIntegerType =
1105
+ getSignIfStdlibIntegerType (argumentType);
1106
+ if (!isSignedIntegerType.hasValue ()) {
1107
+ return getUnknown (evaluator, (SILInstruction *)apply,
1108
+ UnknownReason::InvalidOperandValue);
1109
+ }
1110
+ // Load the stdlib integer's value and convert it to a string.
1111
+ SymbolicValue stdlibIntegerValue =
1112
+ getConstAddrAndLoadResult (integerArgument);
1113
+ if (!stdlibIntegerValue.isConstant ()) {
1114
+ return stdlibIntegerValue;
1115
+ }
1116
+ SymbolicValue builtinIntegerValue =
1117
+ stdlibIntegerValue.lookThroughSingleElementAggregates ();
1118
+ assert (builtinIntegerValue.getKind () == SymbolicValue::Integer &&
1119
+ " stdlib integer type must store only a builtin integer" );
1120
+ APInt integer = builtinIntegerValue.getIntegerValue ();
1121
+ SmallString<8 > integerString;
1122
+ isSignedIntegerType.getValue () ? integer.toStringSigned (integerString)
1123
+ : integer.toStringUnsigned (integerString);
1124
+ SymbolicValue resultVal =
1125
+ SymbolicValue::getString (integerString.str (), evaluator.getAllocator ());
1126
+ setValue (apply, resultVal);
1127
+ return None;
1128
+ }
1067
1129
case WellKnownFunction::DebugPrint: {
1068
1130
assert (apply->getNumArguments () == 1 &&
1069
1131
" debug_print function must take exactly one argument" );
0 commit comments