@@ -1770,6 +1770,58 @@ void SVEEmitter::createBuiltinZAState(raw_ostream &OS) {
17701770 OS << " #endif\n\n " ;
17711771}
17721772
1773+ static StringRef parseGuardParenExpr (StringRef &S) {
1774+ unsigned N = 0 ;
1775+ assert (S[0 ] == ' (' && " Expected lparen" );
1776+ for (unsigned I = 0 ; I < S.size (); ++I) {
1777+ if (S[I] == ' (' )
1778+ ++N;
1779+ else if (S[I] == ' )' )
1780+ --N;
1781+ if (N == 0 ) {
1782+ StringRef Expr = S.substr (1 , I - 1 );
1783+ S = S.drop_front (I + 1 );
1784+ return Expr;
1785+ }
1786+ }
1787+ llvm_unreachable (" Unmatched parenthesi" );
1788+ }
1789+
1790+ static StringRef parseGuardFeature (StringRef &S) {
1791+ assert (std::isalpha (S[0 ]) && " expected feature name" );
1792+ unsigned I;
1793+ for (I = 0 ; I < S.size (); ++I) {
1794+ if (S[I] == ' ,' || S[I] == ' |' || S[I] == ' )' )
1795+ break ;
1796+ }
1797+ StringRef Expr = S.take_front (I);
1798+ S = S.drop_front (I);
1799+ return Expr;
1800+ }
1801+
1802+ static StringRef parseGuardExpr (StringRef &S) {
1803+ if (S[0 ] == ' (' )
1804+ return parseGuardParenExpr (S);
1805+ if (std::isalpha (S[0 ]))
1806+ return parseGuardFeature (S);
1807+ llvm_unreachable (" Unexpected token in expression" );
1808+ }
1809+
1810+ // Parse the TargetGuard and verify that it satisfies at least one of the
1811+ // features from the Required list.
1812+ static bool verifyGuard (StringRef S, ArrayRef<StringRef> Required) {
1813+ if (S.empty ())
1814+ return false ;
1815+ StringRef LHS = parseGuardExpr (S);
1816+ if (S.empty ())
1817+ return llvm::any_of (Required, [LHS](StringRef R) { return R == LHS; });
1818+ if (S[0 ] == ' |' )
1819+ return verifyGuard (LHS, Required) && verifyGuard (S.drop_front (1 ), Required);
1820+ if (S[0 ] == ' ,' )
1821+ return verifyGuard (LHS, Required) || verifyGuard (S.drop_front (1 ), Required);
1822+ llvm_unreachable (" Unexpected token in expression" );
1823+ }
1824+
17731825void SVEEmitter::createStreamingAttrs (raw_ostream &OS, ACLEKind Kind) {
17741826 std::vector<const Record *> RV = Records.getAllDerivedDefinitions (" Inst" );
17751827 SmallVector<std::unique_ptr<Intrinsic>, 128 > Defs;
@@ -1802,9 +1854,29 @@ void SVEEmitter::createStreamingAttrs(raw_ostream &OS, ACLEKind Kind) {
18021854
18031855 if (Def->isFlagSet (IsStreamingFlag))
18041856 StreamingMap[" ArmStreaming" ].insert (Def->getMangledName ());
1805- else if (Def->isFlagSet (VerifyRuntimeMode))
1857+ else if (Def->isFlagSet (VerifyRuntimeMode)) {
1858+ // Verify that the target guards contain at least one feature that
1859+ // actually enables SVE or SME (explicitly, or implicitly). This is needed
1860+ // for the code in SemaARM.cpp (checkArmStreamingBuiltin) that checks
1861+ // whether the required runtime mode for an intrinsic matches with the
1862+ // given set of target features and function attributes.
1863+ //
1864+ // The feature lists below must match the disabled features in
1865+ // 'checkArmStreamingBuiltin'!
1866+ if (!Def->getSVEGuard ().empty () &&
1867+ !verifyGuard (Def->getSVEGuard (),
1868+ {" sve" , " sve2" , " sve2p1" , " sve2-aes" , " sve2-sha3" ,
1869+ " sve2-sm4" , " sve2-bitperm" }))
1870+ llvm_unreachable (
1871+ " SVE guard must include at least one base SVE version" );
1872+ if (!Def->getSMEGuard ().empty () &&
1873+ !verifyGuard (Def->getSMEGuard (),
1874+ {" sme" , " sme2" , " sme2p1" , " sme-f64f64" , " sme-i16i64" ,
1875+ " sme-b16b16" , " sme-f16f16" , " sme-f8f32" , " sme-f8f16" }))
1876+ llvm_unreachable (
1877+ " SME guard must include at least one base SME version" );
18061878 StreamingMap[" VerifyRuntimeMode" ].insert (Def->getMangledName ());
1807- else if (Def->isFlagSet (IsStreamingCompatibleFlag))
1879+ } else if (Def->isFlagSet (IsStreamingCompatibleFlag))
18081880 StreamingMap[" ArmStreamingCompatible" ].insert (Def->getMangledName ());
18091881 else
18101882 StreamingMap[" ArmNonStreaming" ].insert (Def->getMangledName ());
0 commit comments