@@ -1770,6 +1770,58 @@ void SVEEmitter::createBuiltinZAState(raw_ostream &OS) {
1770
1770
OS << " #endif\n\n " ;
1771
1771
}
1772
1772
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
+
1773
1825
void SVEEmitter::createStreamingAttrs (raw_ostream &OS, ACLEKind Kind) {
1774
1826
std::vector<const Record *> RV = Records.getAllDerivedDefinitions (" Inst" );
1775
1827
SmallVector<std::unique_ptr<Intrinsic>, 128 > Defs;
@@ -1802,9 +1854,29 @@ void SVEEmitter::createStreamingAttrs(raw_ostream &OS, ACLEKind Kind) {
1802
1854
1803
1855
if (Def->isFlagSet (IsStreamingFlag))
1804
1856
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" );
1806
1878
StreamingMap[" VerifyRuntimeMode" ].insert (Def->getMangledName ());
1807
- else if (Def->isFlagSet (IsStreamingCompatibleFlag))
1879
+ } else if (Def->isFlagSet (IsStreamingCompatibleFlag))
1808
1880
StreamingMap[" ArmStreamingCompatible" ].insert (Def->getMangledName ());
1809
1881
else
1810
1882
StreamingMap[" ArmNonStreaming" ].insert (Def->getMangledName ());
0 commit comments