66#include < llvm/Passes/PassBuilder.h>
77#include < llvm/Passes/StandardInstrumentations.h>
88#include < llvm/Support/CBindingWrapping.h>
9+ #include < optional>
910
1011using namespace llvm ;
1112
@@ -143,6 +144,167 @@ void LLVMPassBuilderExtensionsSetAAPipeline(LLVMPassBuilderExtensionsRef Extensi
143144}
144145#endif
145146
147+ static bool checkParametrizedPassName (StringRef Name, StringRef PassName) {
148+ if (!Name.consume_front (PassName))
149+ return false ;
150+ // normal pass name w/o parameters == default parameters
151+ if (Name.empty ())
152+ return true ;
153+ #if LLVM_VERSION_MAJOR >= 16
154+ return Name.starts_with (" <" ) && Name.ends_with (" >" );
155+ #else
156+ return Name.startswith (" <" ) && Name.endswith (" >" );
157+ #endif
158+ }
159+
160+ static std::optional<OptimizationLevel> parseOptLevel (StringRef S) {
161+ return StringSwitch<std::optional<OptimizationLevel>>(S)
162+ .Case (" O0" , OptimizationLevel::O0)
163+ .Case (" O1" , OptimizationLevel::O1)
164+ .Case (" O2" , OptimizationLevel::O2)
165+ .Case (" O3" , OptimizationLevel::O3)
166+ .Case (" Os" , OptimizationLevel::Os)
167+ .Case (" Oz" , OptimizationLevel::Oz)
168+ .Default (std::nullopt );
169+ }
170+
171+ static Expected<OptimizationLevel> parseOptLevelParam (StringRef S) {
172+ std::optional<OptimizationLevel> OptLevel = parseOptLevel (S);
173+ if (OptLevel)
174+ return *OptLevel;
175+ return make_error<StringError>(
176+ formatv (" invalid optimization level '{}'" , S).str (),
177+ inconvertibleErrorCode ());
178+ }
179+
180+ template <typename ParametersParseCallableT>
181+ static auto parsePassParameters (ParametersParseCallableT &&Parser,
182+ StringRef Name, StringRef PassName)
183+ -> decltype(Parser(StringRef{})) {
184+ using ParametersT = typename decltype (Parser (StringRef{}))::value_type;
185+
186+ StringRef Params = Name;
187+ if (!Params.consume_front (PassName)) {
188+ llvm_unreachable (
189+ " unable to strip pass name from parametrized pass specification" );
190+ }
191+ if (!Params.empty () &&
192+ (!Params.consume_front (" <" ) || !Params.consume_back (" >" ))) {
193+ llvm_unreachable (" invalid format for parametrized pass name" );
194+ }
195+
196+ Expected<ParametersT> Result = Parser (Params);
197+ assert ((Result || Result.template errorIsA <StringError>()) &&
198+ " Pass parameter parser can only return StringErrors." );
199+ return Result;
200+ }
201+
202+
203+ // Register target specific parsing callbacks
204+ static void registerCallbackParsing (PassBuilder &PB) {
205+ PB.registerPipelineParsingCallback (
206+ [&](StringRef Name, ModulePassManager &PM,
207+ ArrayRef<PassBuilder::PipelineElement>) {
208+ #define MODULE_CALLBACK (NAME, INVOKE ) \
209+ if (checkParametrizedPassName (Name, NAME)) { \
210+ auto L = parsePassParameters (parseOptLevelParam, Name, NAME); \
211+ if (!L) { \
212+ errs () << NAME " : " << toString (L.takeError ()) << ' \n ' ; \
213+ return false ; \
214+ } \
215+ PB.INVOKE (PM, L.get ()); \
216+ return true ; \
217+ }
218+ #include " callbacks.inc"
219+ return false ;
220+ });
221+
222+ // Module-level callbacks with LTO phase (use Phase::None for string API)
223+ PB.registerPipelineParsingCallback (
224+ [&](StringRef Name, ModulePassManager &PM,
225+ ArrayRef<PassBuilder::PipelineElement>) {
226+ #if LLVM_VERSION_MAJOR > 20
227+ #define MODULE_LTO_CALLBACK (NAME, INVOKE ) \
228+ if (checkParametrizedPassName (Name, NAME)) { \
229+ auto L = parsePassParameters (parseOptLevelParam, Name, NAME); \
230+ if (!L) { \
231+ errs () << NAME " : " << toString (L.takeError ()) << ' \n ' ; \
232+ return false ; \
233+ } \
234+ PB.INVOKE (PM, L.get (), ThinOrFullLTOPhase::None); \
235+ return true ; \
236+ }
237+ #include " callbacks.inc"
238+ #else
239+ #define MODULE_LTO_CALLBACK (NAME, INVOKE ) \
240+ if (checkParametrizedPassName (Name, NAME)) { \
241+ auto L = parsePassParameters (parseOptLevelParam, Name, NAME); \
242+ if (!L) { \
243+ errs () << NAME " : " << toString (L.takeError ()) << ' \n ' ; \
244+ return false ; \
245+ } \
246+ PB.INVOKE (PM, L.get ()); \
247+ return true ; \
248+ }
249+ #include " callbacks.inc"
250+ #endif
251+ return false ;
252+ });
253+
254+ // Function-level callbacks
255+ PB.registerPipelineParsingCallback (
256+ [&](StringRef Name, FunctionPassManager &PM,
257+ ArrayRef<PassBuilder::PipelineElement>) {
258+ #define FUNCTION_CALLBACK (NAME, INVOKE ) \
259+ if (checkParametrizedPassName (Name, NAME)) { \
260+ auto L = parsePassParameters (parseOptLevelParam, Name, NAME); \
261+ if (!L) { \
262+ errs () << NAME " : " << toString (L.takeError ()) << ' \n ' ; \
263+ return false ; \
264+ } \
265+ PB.INVOKE (PM, L.get ()); \
266+ return true ; \
267+ }
268+ #include " callbacks.inc"
269+ return false ;
270+ });
271+
272+ // CGSCC-level callbacks
273+ PB.registerPipelineParsingCallback (
274+ [&](StringRef Name, CGSCCPassManager &PM,
275+ ArrayRef<PassBuilder::PipelineElement>) {
276+ #define CGSCC_CALLBACK (NAME, INVOKE ) \
277+ if (checkParametrizedPassName (Name, NAME)) { \
278+ auto L = parsePassParameters (parseOptLevelParam, Name, NAME); \
279+ if (!L) { \
280+ errs () << NAME " : " << toString (L.takeError ()) << ' \n ' ; \
281+ return false ; \
282+ } \
283+ PB.INVOKE (PM, L.get ()); \
284+ return true ; \
285+ }
286+ #include " callbacks.inc"
287+ return false ;
288+ });
289+
290+ // Loop-level callbacks
291+ PB.registerPipelineParsingCallback (
292+ [&](StringRef Name, LoopPassManager &PM,
293+ ArrayRef<PassBuilder::PipelineElement>) {
294+ #define LOOP_CALLBACK (NAME, INVOKE ) \
295+ if (checkParametrizedPassName (Name, NAME)) { \
296+ auto L = parsePassParameters (parseOptLevelParam, Name, NAME); \
297+ if (!L) { \
298+ errs () << NAME " : " << toString (L.takeError ()) << ' \n ' ; \
299+ return false ; \
300+ } \
301+ PB.INVOKE (PM, L.get ()); \
302+ return true ; \
303+ }
304+ #include " callbacks.inc"
305+ return false ;
306+ });
307+ }
146308
147309// Vendored API entrypoint
148310
@@ -165,7 +327,7 @@ static LLVMErrorRef runJuliaPasses(Module *Mod, Function *Fun, const char *Passe
165327 PB.registerPipelineParsingCallback (Callback);
166328 for (auto &Callback : PassExts->FunctionPipelineParsingCallbacks )
167329 PB.registerPipelineParsingCallback (Callback);
168-
330+ registerCallbackParsing (PB); // Parsing for target-specific callbacks
169331 LoopAnalysisManager LAM;
170332 FunctionAnalysisManager FAM;
171333 CGSCCAnalysisManager CGAM;
0 commit comments