Porting Pass to New PassManager

Hi all,

I'm attempting to move the AddressSanitizer pass from the legacy
PassManager to the new one because the new one has various benefits
over legacy and wanted to clarify on something. Does creating the
static RegisterPass struct register the pass with the new PassManager?

It seems that RegisterPass does the same things that the
INITIALIZE_PASS_* macros do but it registers the pass with
PassRegistry::getPassRegistry(). What I'm not sure of is if this uses
the new PassManager infrastructure. Exploring the code doesn't seem to
show that this PassRegistry touches anything in the legacy namespace,
but I wanted double confirmation on this.

Thanks,
Leonard

Leonard,

nope, the PassRegistry stuff is all about legacy pass manager.
legacy namespace has not been extensively used to mark all the legacy-related stuff
(say, even Pass class which is a base for legacy passes is not under legacy namespace).

Registration for new-pass-manager passes happens in lib/Passes/PassRegistry.def.

Usually, when porting from legacy to new the main difference is analysis handling,
so people factor out the worker code into a method that takes analyses and call
this function both in legacy and new-pm passes.
In many cases it takes just a handful lines of code.

Feel free to ask questions, if any.

regards,
Fedor.

Hi Leonard, Fedor,

while it’s true that RegisterPass is not applicable for new-pm passes, PassRegistry.def is not the whole story. Passes in PassRegistry are available for the opt tool. The sanitizers are passes that usually get added to the pipeline by the frontend. There, you need to use PassBuilder’s callbacks mechanism to hook the sanitizer into the optimizer.

Assuming you’re willing to contribute your changes, please share your progress! Thank you for making a move on this!

Cheers,
Philip

Hmm… frontends should be using PassBuilder anyway.
And if they are using PassBuilder then they are using PassRegistry.def as well - all the
PassBuilder::register*/parse*/is* methods do include PassRegistry.def in their bodies.

I was under impression that callbacks are primarily for plugins usage.

regards,
Fedor.

Frontends are using PassBuilder, but they need to hook into the default pipeline creation to insert the sanitizer passes.

Hi Fedor,

Thanks for the starting point of looking through PassRegistry.def. Do
you happen to have any specific examples or knowledge of previous
patches of passes that were part of the legacy PM but moved to the new
PM? I'm not sure if historically when the new PM was proposed, people
actually did move passes from legacy or people just add new passes
onto the new one.

Thanks,
Leonard

Leonard,

pretty much every single IR (not MachineIR) pass right now has a port from legacy to new
(bar a very few passes that were specifically written for new-pm, like SimpleLoopUnswitch or Inliner).

Take any Module/Function pass and it will definitely be a port.

regards,
Fedor.

So I think I have the AddressSanitizer working with the new PM seeing
that I can replace '-asan' with ' -passes='asan' ' and the IR gets
instrumented. The next thing I'm having trouble understanding is that
the AddressSanitizerModule pass doesn't seem to be running even with
'-asan-module'. That is, running

`opt < %s -passed='asan' -asan-module -S`

doesn't produce the same IR as

`opt < %s -asan -asan-module -S`

More specifically, the only thing missing seems to be the
`asan.module_ctor` that should get added to the global ctors list.
What I'm not sure of is if I'm missing something when I made the new
pass or it's something in the pipeline regarding which passes run
first between both PMs. I could just make an AddressSanitizerModule
pass for the new PM, but feel like this should still work even if
AddressSanitizer is added in the new PM and AddressSanitizerModule is
added in legacy.

- Leo

opt < %s -passed='asan' -asan-module -S

asan-module is another ModulePass, not a commandline option. You can’t mix that like this.

Cheers,
Philip

opt < %s -passed='asan' -asan-module -S

asan-module is another ModulePass, not a commandline option. You can’t mix that like this.

I’m inclined to consider this as a deficiency of our command line interface.
We really should be giving some noise about newpm’s -passes overriding any legacy-pass options.

Especially since these legacy-pass options sometimes are hard to distinguish from non-pass options.

regards,
Fedor.

Is there a reason for why `-asan` and `-asan-module` can be mixed but
Function passes and Module passes with the new PM can't be mixed?

- Leo

Actually I figured out how to run both a module and function pass. So
now for the test `test/Instrumentation/AddressSanitizer/basic.ll`,
both `-asan -asan-module` and
`-passes='function(asan),module(asan-module)` produce the same
instrumented code.

Its not a problem of Function vs Module.
It is a problem of New vs Legacy.

-asan and -asan-module are legacy pm.
-passes=asan is new pm.

If you implement asan-module for new pm you can use it
something like this:
-passes=function(asan),asan-module

(exact syntax depends on how do you register the passes)

regards,
Fedor.

I made a patch at https://reviews.llvm.org/D52739 that I think
implements all I need for the porting. I'm able to use them with
`opt`, but still need to figure out how to use this new PM
infrastructure with clang when running `-fsanitize=address`.

- Leonard