@@ -841,6 +841,52 @@ static bool interp__builtin_carryop(InterpState &S, CodePtr OpPC,
841
841
return true ;
842
842
}
843
843
844
+ static bool interp__builtin_clz (InterpState &S, CodePtr OpPC,
845
+ const InterpFrame *Frame, const Function *Func,
846
+ const CallExpr *Call) {
847
+ unsigned BuiltinOp = Func->getBuiltinID ();
848
+ PrimType ValT = *S.getContext ().classify (Call->getArg (0 ));
849
+ const APSInt &Val = peekToAPSInt (S.Stk , ValT);
850
+
851
+ // When the argument is 0, the result of GCC builtins is undefined, whereas
852
+ // for Microsoft intrinsics, the result is the bit-width of the argument.
853
+ bool ZeroIsUndefined = BuiltinOp != Builtin::BI__lzcnt16 &&
854
+ BuiltinOp != Builtin::BI__lzcnt &&
855
+ BuiltinOp != Builtin::BI__lzcnt64;
856
+
857
+ if (ZeroIsUndefined && Val == 0 )
858
+ return false ;
859
+
860
+ pushInt (S, Val.countl_zero ());
861
+ return true ;
862
+ }
863
+
864
+ static bool interp__builtin_ctz (InterpState &S, CodePtr OpPC,
865
+ const InterpFrame *Frame, const Function *Func,
866
+ const CallExpr *Call) {
867
+ PrimType ValT = *S.getContext ().classify (Call->getArg (0 ));
868
+ const APSInt &Val = peekToAPSInt (S.Stk , ValT);
869
+
870
+ if (Val == 0 )
871
+ return false ;
872
+
873
+ pushInt (S, Val.countr_zero ());
874
+ return true ;
875
+ }
876
+
877
+ static bool interp__builtin_bswap (InterpState &S, CodePtr OpPC,
878
+ const InterpFrame *Frame,
879
+ const Function *Func, const CallExpr *Call) {
880
+ PrimType ReturnT = *S.getContext ().classify (Call->getType ());
881
+ PrimType ValT = *S.getContext ().classify (Call->getArg (0 ));
882
+ const APSInt &Val = peekToAPSInt (S.Stk , ValT);
883
+ assert (Val.getActiveBits () <= 64 );
884
+
885
+ INT_TYPE_SWITCH (ReturnT,
886
+ { S.Stk .push <T>(T::from (Val.byteSwap ().getZExtValue ())); });
887
+ return true ;
888
+ }
889
+
844
890
bool InterpretBuiltin (InterpState &S, CodePtr OpPC, const Function *F,
845
891
const CallExpr *Call) {
846
892
InterpFrame *Frame = S.Current ;
@@ -1114,6 +1160,32 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
1114
1160
return false ;
1115
1161
break ;
1116
1162
1163
+ case Builtin::BI__builtin_clz:
1164
+ case Builtin::BI__builtin_clzl:
1165
+ case Builtin::BI__builtin_clzll:
1166
+ case Builtin::BI__builtin_clzs:
1167
+ case Builtin::BI__lzcnt16: // Microsoft variants of count leading-zeroes
1168
+ case Builtin::BI__lzcnt:
1169
+ case Builtin::BI__lzcnt64:
1170
+ if (!interp__builtin_clz (S, OpPC, Frame, F, Call))
1171
+ return false ;
1172
+ break ;
1173
+
1174
+ case Builtin::BI__builtin_ctz:
1175
+ case Builtin::BI__builtin_ctzl:
1176
+ case Builtin::BI__builtin_ctzll:
1177
+ case Builtin::BI__builtin_ctzs:
1178
+ if (!interp__builtin_ctz (S, OpPC, Frame, F, Call))
1179
+ return false ;
1180
+ break ;
1181
+
1182
+ case Builtin::BI__builtin_bswap16:
1183
+ case Builtin::BI__builtin_bswap32:
1184
+ case Builtin::BI__builtin_bswap64:
1185
+ if (!interp__builtin_bswap (S, OpPC, Frame, F, Call))
1186
+ return false ;
1187
+ break ;
1188
+
1117
1189
default :
1118
1190
return false ;
1119
1191
}
0 commit comments