static cl::opt<bool> ScalarizeLoadStore("scalarize-load-store", cl::Hidden, cl::init(false),cl::desc("Allow the scalarizer pass to scalarize loads and store"));
cl::OptionRegistry::CreateOption<bool>("ScalarizeLoadStore","scalarize-load-store", cl::Hidden, cl::init(false),cl::desc("Allow the scalarizer pass to scalarize loads and store"));
ScalarizeLoadStore = cl::OptionRegistry::GetValue<bool>("ScalarizeLoadStore");
For the first step it might be better to keep the option value as a
global. That way we only switch to using something like
static bool ScalarizeLoadStore;
cl::OptionRegistry::CreateOption<bool>(&ScalarizeLoadStore,
"ScalarizeLoadStore",
"scalarize-load-store", cl::Hidden, cl::init(false),
cl::desc("Allow the scalarizer pass to scalarize loads and store"));
and everything else remains as is.
Some passes take options directly in the constructor. For example
Inliner::Inliner(char &ID, int Threshold, bool InsertLifetime)
Maybe we could just say that there are two different types of options.
The ones we want to expose to users and the ones which we use for
testing llvm itself. The options we want to expose should be just
constructor arguments. With that distinction we should be able to just
not use the options added by cl::OptionRegistry::CreateOption unless
cl::ParseCommandLineOptions is called. WebKit like clients would just
not call cl::ParseCommandLineOptions. Would that work?
Cheers,
Rafael
_______________________________________________
LLVM Developers mailing list
LLV...@cs.uiuc.edu http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Cheers,
Rafael
You mean PassManagerBuilder, right?
> (2) Not all of our passes have constructors for overriding their cl::opts
> (the legacy Scalarizer is one)
>
> I think it would in general be cleaner to provide a way for library clients
> to use cl::opts without being forced to parse a command line.
I guess it really depends on how many options there are that we want
to expose via an API. I have the impression that there are few, which
would make changing the constructors and PassManagerBuilder better.
If there is a large number of options that we want to expose, then I
can see the value of having a llvm "configuration object" that is
passed around and is queried by the passes. If we do go down this
road, we should change passes like the inliner to use the
configuration object instead of constructor options. We should also
drop the "cl" from the names if it is not going to be handling command
lines :-)
Yes.
>
>> (2) Not all of our passes have constructors for overriding their cl::opts
>> (the legacy Scalarizer is one)
>>
>> I think it would in general be cleaner to provide a way for library clients
>> to use cl::opts without being forced to parse a command line.
>
> I guess it really depends on how many options there are that we want
> to expose via an API. I have the impression that there are few, which
> would make changing the constructors and PassManagerBuilder better.
>
> If there is a large number of options that we want to expose, then I
> can see the value of having a llvm "configuration object" that is
> passed around and is queried by the passes. If we do go down this
> road, we should change passes like the inliner to use the
> configuration object instead of constructor options. We should also
> drop the "cl" from the names if it is not going to be handling command
> lines :-)
I’m curious if Tom Stellard or Filip Pizlo have any input on this as they are more directly involved on the client side.
I do agree that we should ultimately drop the cl namespace if we’re going in this direction.
-Chris
The fewer options we fiddle with, the better for WebKit. Hence we would be fine with a solution that exposes relatively few options.
The main option that we use now - turning on stack map liveness calculation - is something that feels like it shouldn't be an "option" at all but maybe an attribute instead.
For now, please eliminate only the static constructor and leave the
storage. Since it seems only a few options that need to be exposed by
non-command line APIs, we might be able to avoid the need for a
cl::OptionRegistry::GetValue.
> I’d
> also like to add to it that when updating passes I will ensure that each
> pass that has cl::opts also has a default constructor, an overridden
> constructor to populate each option, and the corresponding factory methods
> for the C API.
And *please* don't add anything to the C api unless someone has a real
need for that particular interface and there is a good discussion on
the review thread about it. The C api has more backwards compatibility
promises, which makes it incredibly painful :-(
Even the C++ api is not free, so I would also only modify a pass
constructor if someone wants to pass that option for something other
then llvm development or testing. For that command lines are a
perfectly reasonable solution.
> Does this sound reasonable for a first step?
Removing the static constructors does.
> On Aug 19, 2014, at 11:09 AM, Rafael Espíndola <rafael.e...@gmail.com> wrote:
>
>> On 19 August 2014 13:47, Chris Bieneman <be...@apple.com> wrote:
>> I’d like to propose moving forward with the first phase of my proposal to
>> make the cl::opt structures owned and eliminate global option storage.
>
> For now, please eliminate only the static constructor and leave the
> storage. Since it seems only a few options that need to be exposed by
> non-command line APIs, we might be able to avoid the need for a
> cl::OptionRegistry::GetValue.
>
>> I’d
>> also like to add to it that when updating passes I will ensure that each
>> pass that has cl::opts also has a default constructor, an overridden
>> constructor to populate each option, and the corresponding factory methods
>> for the C API.
>
> And *please* don't add anything to the C api unless someone has a real
> need for that particular interface and there is a good discussion on
> the review thread about it. The C api has more backwards compatibility
> promises, which makes it incredibly painful :-(
This is a good point. I see two sensible options:
1) don't add anything to the C API unless someone specifically asks, as Rafael suggests.
2) make options passed to passes use some kind of loose coupling, like an array of strings or even better an options object where the user sets key/value pairs by some call (eg. LLVMSetOption(optionObject, keyString, valueString).
The upside of (2) is that it preserves current functionality and new options can be added easily. The downside is that we'd have to get very particular about whether an option needs to be supported indefinitely if it is ever exposed. Probably nobody wants that strong of a contract.
-Filip
I strongly feel this is the wrong decision. If you have a single process using two LLVM clients (say WebKit and Mesa), and they both are using an opt pass with different settings. If the storage is global this will not work.
>
>> I’d
>> also like to add to it that when updating passes I will ensure that each
>> pass that has cl::opts also has a default constructor, an overridden
>> constructor to populate each option, and the corresponding factory methods
>> for the C API.
>
> And *please* don't add anything to the C api unless someone has a real
> need for that particular interface and there is a good discussion on
> the review thread about it. The C api has more backwards compatibility
> promises, which makes it incredibly painful :-(
>
> Even the C++ api is not free, so I would also only modify a pass
> constructor if someone wants to pass that option for something other
> then llvm development or testing. For that command lines are a
> perfectly reasonable solution.
I can agree with all of this.
-Chris
How would you suggest we expose cl::opts for modifying these options in tools like opt? A good example of this type of option would be the options in LoopUnrollPass.cpp.
>
> * Options that we use during development of llvm. They are useful for
> testing, tracking a bug or enabling/disabling a feature that is still
> under development. These can use a static storage since external
> clients like webkit will never change them. We do have to avoid these
> options requiring static constructors, since otherwise the client is
> paying for something it will never use.
What about when we're debugging the WebKit JIT? For development of libraries using LLVM it would be nice to be able to toggle these values too, which is why Filip’s suggestion of an API like LLVMConfigSetBoolValue(Config, "ScalarizeLoadStore", 1) would be nice.
-Chris
Opt uses the PassManagerBuilder. Opt itself could have a command line
options controlling its use of PassManagerBuilder. That is probably
fine since we expect very few of these.
>>
>> * Options that we use during development of llvm. They are useful for
>> testing, tracking a bug or enabling/disabling a feature that is still
>> under development. These can use a static storage since external
>> clients like webkit will never change them. We do have to avoid these
>> options requiring static constructors, since otherwise the client is
>> paying for something it will never use.
>
> What about when we're debugging the WebKit JIT? For development of libraries using LLVM it would be nice to be able to toggle these values too, which is why Filip’s suggestion of an API like LLVMConfigSetBoolValue(Config, "ScalarizeLoadStore", 1) would be nice.
Most llvm bugs reproduce with just opt or llc, but if that is not the
case, cl::ParseCommandLineOptions when debugging seems fine.
The advantages of this setup are
* Options that are exposed to the users are done so in a very natural
way (constructor arguments).
* Internal options are still really easy to create, but now don't have
static constructors.
* We don't need a LLVMConfig object that gets passed around.
* No stringly typed interface.
There are two reasons this doesn’t work:
(1) Cases where I might want to set a debug variable for the WebKit JIT but not for Mesa - if the option storage is global it will get overwritten for all users
(2) cl::ParseCommandLineOptions today is C++ API, WebKit restricts itself to the C API, so at the least we’d need to expose it as part of the C API
>
> The advantages of this setup are
>
> * Options that are exposed to the users are done so in a very natural
> way (constructor arguments).
I’m on board with this, but not to the exclusion of other use cases.
> * Internal options are still really easy to create, but now don't have
> static constructors.
We’re in agreement here
> * We don't need a LLVMConfig object that gets passed around.
For the sake of this discussion, let’s just scrap my phase two idea for a configuration object and treat that as a separate issue.
> * No stringly typed interface.
I think that there are advantages to a string-based interface. Sean Silva actually suggested that interface when I first sent out an email about our plans to rework command line options back on 8/6. Based on Sean’s feedback and a few discussions I had offline with other LLVM contributors I thought a stringly typed interface was the best approach to eliminating both the static constructors and the static storage which are explicit goals for our project.
Thanks,
-Chris
This really comes up? Really, we are not talking -O2/-O3 or inlining
thresholds. We are talking things like lcr-max-depth being needed for
a debugging session.
> (2) cl::ParseCommandLineOptions today is C++ API, WebKit restricts itself to the C API, so at the least we’d need to expose it as part of the C API
This seems a much smaller change than adding a LLVMConfig object.
>> * We don't need a LLVMConfig object that gets passed around.
>
> For the sake of this discussion, let’s just scrap my phase two idea for a configuration object and treat that as a separate issue.
But it makes a big difference on how the first phase is handled. If we
don't want the LLVMConfig object, the first phase should really just
remove the static constructors and not add a stringly typed interface.
> I think that there are advantages to a string-based interface. Sean Silva actually suggested that interface when I first sent out an email about our plans to rework command line options back on 8/6. Based on Sean’s feedback and a few discussions I had offline with other LLVM contributors I thought a stringly typed interface was the best approach to eliminating both the static constructors and the static storage which are explicit goals for our project.
Sorry I missed the original discussion. Sean, would you mind
summarizing the why of the stringly interface? Even if we do need a
LLVMConfig object (seems unlikely), I would still suggest using some
other key format. With strings we would suddenly be exposing every
command line option to the C API, which seems highly undesirable.
I’ve toggled on SROA's "sroa-random-shuffle-slices” before for testing, I've played with InstCombine’s "enable-double-float-shrink”, so it does (although admittedly not terribly often).
>
>> (2) cl::ParseCommandLineOptions today is C++ API, WebKit restricts itself to the C API, so at the least we’d need to expose it as part of the C API
>
> This seems a much smaller change than adding a LLVMConfig object.
>
>>> * We don't need a LLVMConfig object that gets passed around.
>>
>> For the sake of this discussion, let’s just scrap my phase two idea for a configuration object and treat that as a separate issue.
>
> But it makes a big difference on how the first phase is handled. If we
> don't want the LLVMConfig object, the first phase should really just
> remove the static constructors and not add a stringly typed interface.
The stringly typed interface doesn’t just have to do with an LLVMConfig object, it also allows you to use non-static storage for options.
>
>> I think that there are advantages to a string-based interface. Sean Silva actually suggested that interface when I first sent out an email about our plans to rework command line options back on 8/6. Based on Sean’s feedback and a few discussions I had offline with other LLVM contributors I thought a stringly typed interface was the best approach to eliminating both the static constructors and the static storage which are explicit goals for our project.
>
> Sorry I missed the original discussion. Sean, would you mind
> summarizing the why of the stringly interface? Even if we do need a
> LLVMConfig object (seems unlikely), I would still suggest using some
> other key format. With strings we would suddenly be exposing every
> command line option to the C API, which seems highly undesirable.
The problem with alternate key formats from strings is it gets tricky when you start talking about supporting dynamically loaded passes and their options (which our current cl::opts do support).
Thanks,
-Chris
> On Aug 19, 2014, at 3:10 PM, Rafael Espíndola <rafael.e...@gmail.com> wrote:I’ve toggled on SROA's "sroa-random-shuffle-slices” before for testing, I've played with InstCombine’s "enable-double-float-shrink”, so it does (although admittedly not terribly often).
>
>> There are two reasons this doesn’t work:
>>
>> (1) Cases where I might want to set a debug variable for the WebKit JIT but not for Mesa - if the option storage is global it will get overwritten for all users
>
> This really comes up? Really, we are not talking -O2/-O3 or inlining
> thresholds. We are talking things like lcr-max-depth being needed for
> a debugging session.
Cheers,
Rafael
On Aug 19, 2014, at 6:45 PM, Chandler Carruth <chan...@google.com> wrote:
FWIW, I largely agree with Rafael's position here, at least in the near term.The nice thing about it is that even if we don't stay there forever, it is a nice incremental improvement over the current state of the world, and we can actually be mindful going forward of whether the restriction it imposes (an inability to use "internal" knobs from within a library context that have multiple different library users in a single address space) proves to be a significant on-going burden.
On Tue, Aug 19, 2014 at 3:57 PM, Chris Bieneman <be...@apple.com> wrote:> On Aug 19, 2014, at 3:10 PM, Rafael Espíndola <rafael.e...@gmail.com> wrote:I’ve toggled on SROA's "sroa-random-shuffle-slices” before for testing, I've played with InstCombine’s "enable-double-float-shrink”, so it does (although admittedly not terribly often).
>
>> There are two reasons this doesn’t work:
>>
>> (1) Cases where I might want to set a debug variable for the WebKit JIT but not for Mesa - if the option storage is global it will get overwritten for all users
>
> This really comes up? Really, we are not talking -O2/-O3 or inlining
> thresholds. We are talking things like lcr-max-depth being needed for
> a debugging session.
I'm somewhat surprised that this comes up much in a context where you *can't* extract a test case and play with it using 'opt' or some other stand-alone context.If these come up so rarely, would it be unreasonable to just flip the flag in the source code, and build a DSO to test with? For example, this is how I have done counter-based bisection and combine-based bisection of things (a similarly rare but necessary activity I suspect) and it seems to work well.-Chandler
_______________________________________________
I actually disagree with this for two reasons.On Aug 19, 2014, at 6:45 PM, Chandler Carruth <chan...@google.com> wrote:FWIW, I largely agree with Rafael's position here, at least in the near term.The nice thing about it is that even if we don't stay there forever, it is a nice incremental improvement over the current state of the world, and we can actually be mindful going forward of whether the restriction it imposes (an inability to use "internal" knobs from within a library context that have multiple different library users in a single address space) proves to be a significant on-going burden.The first is that if there are going to be changes to the code anyway to remove static initializers, and we can move the storage to the pass at the same time, the we should make just one change and not two.
The second reason is that in most cases these knobs should not be globals. If I had a piece of data (not a CL::opt) in global scope, only used by one pass, then I'm sure people would question why it's a global at all and move it inside the class. We're treating cl::opt as special here when there's no reason for the opt or the storage to be global.We frown upon the use of globals, otherwise LLVM would be littered with them like many other C++ code bases. I don't think cl::opts should be special at all in this respect.
-- Sean Silva
Cheers,
Rafael
On Aug 19, 2014, at 9:43 PM, Sean Silva <chiso...@gmail.com> wrote:One interesting issue with moving away from the current system of static initializers for cl::opt is that we will no longer have the automatic registration of all the options so that -help will print everything available and generally we will not be able to issue an error for an "unknown command line option" (without calling into any other code).
The auto-registration is fundamentally tied with the globalness and the static initializers; pondering this has led me down an interesting path that has made me understand better my suggestion in the other thread. As I see it, there are two very different sorts of uses of llvm::cl in LLVM:1. For regular command line processing. E.g. if a tool accepts an output file, then we need something that will parse the argument from the command line.2. As a way to easily set up a conduit from A to B, where A is the command line and B is some place "deep" inside the LLVM library code that will do something in response to the command line.(and, pending discussion, someday point A might include a proper programmatic interface (i.e. in a way other than hijacking the command line processing))
llvm::cl does a decent job for #1 and that is what it was designed for AFAICT; these uses of llvm::cl live outside of library code and everything is pretty happy, despite them being global and having static initializers.The problem is that llvm::cl is not very well-suited to #2, yet it is used for #2, and that is the real problem. We need a solution to problem #2 which does not use llvm::cl. Thus, I don't think that the solution you propose here is the right direction.The first step is to clearly differentiate between #1 and #2. I will say "command line options" for #1 and "configuration/tweak points" for #2. (maybe "library options" is better for #2; neither is perfect terminology)The strawman I suggested in http://lists.cs.uiuc.edu/pipermail/llvmdev/2014-August/075503.html was a stab at #2. There is no way to dodge being stringly typed since command lines are stringly typed, so really it is just a question of how long a solution stays stringly typed.My thought process for staying stringly typed "the whole time" (possibly with some caching) comes from these two desires:- adding a c/t point should require adding just one call into the c/t machinery (this is both for convenience and for DRY/SPOT), and
- this change should be localized to the code being configured/tweakedThis is the thought process:Note that llvm::cl is stringly typed until it parses the options. llvm::cl gives the appearance of a typed interface because it uses static initialization as a backdoor to globally transport the knowledge of the expected type to the option parsing machinery (very early in the program lifetime). Without this backdoor, we need to stay stringly typed longer, at least until we reach the "localized" place where the single call into the c/t machinery is made; this single call is the only place that has the type information needed for the c/t value to become properly typed. But there is no way to know how long it will be until we reach that point (or even *if* we reach that point; consider passes that are not run on this invocation).
Hence my suggestion of just putting a stringly typed key-value store (or whatever) in an easily accessible place (like LLVMContext), and just translating any unrecognized command line options (ones that are not for #1) into that stringly typed storage.
I agree with Rafael that "constructor arguments to passes" are not c/t points. In the future, there might be some way to integrate the two (from the referenced post, you can probably tell that I kind of like the idea of doing so), but for now, I think the clear incremental step is to attack #2 and solve it without llvm::cl. I have suggested a way to do this that I think makes sense.
On Aug 19, 2014, at 10:24 PM, Chandler Carruth <chan...@google.com> wrote:On Tue, Aug 19, 2014 at 10:10 PM, Pete Cooper <peter_...@apple.com> wrote:
I actually disagree with this for two reasons.On Aug 19, 2014, at 6:45 PM, Chandler Carruth <chan...@google.com> wrote:FWIW, I largely agree with Rafael's position here, at least in the near term.The nice thing about it is that even if we don't stay there forever, it is a nice incremental improvement over the current state of the world, and we can actually be mindful going forward of whether the restriction it imposes (an inability to use "internal" knobs from within a library context that have multiple different library users in a single address space) proves to be a significant on-going burden.The first is that if there are going to be changes to the code anyway to remove static initializers, and we can move the storage to the pass at the same time, the we should make just one change and not two.No one is suggesting otherwise that I have seen? At least, my interpretation (perhaps incorrect, I've not had time to read all of this thread in 100% detail) was that the removal of static initializers wouldn't require changing every cl::opt variable.
The second reason is that in most cases these knobs should not be globals. If I had a piece of data (not a CL::opt) in global scope, only used by one pass, then I'm sure people would question why it's a global at all and move it inside the class. We're treating cl::opt as special here when there's no reason for the opt or the storage to be global.We frown upon the use of globals, otherwise LLVM would be littered with them like many other C++ code bases. I don't think cl::opts should be special at all in this respect.
Sure, you're arguing against the core design of cl::opt. However, we have it, and it wasn't an accident or for lack of other patterns that we chose it.For example, we don't require all constants to be per-pass, and instead have per-file constants. Rafael is suggesting that one use case for cl::opt global variables is, in essence, a constant that is somewhat easier for a developer of LLVM (*not* a user) to change during debugging and active development. I don't think the desire for convenience and only supporting the default value in production contexts are completely invalid.
Once you factor those in, we have a tradeoff. Historically, the tradeoff was made in the direction of convenience, relying on a very narrow interpretation of the use cases. It isn't clear to me that we should, today, make a different tradeoff. It certainly doesn't make sense why you would gate removing static initializers (a clear win) on forcing a change on a core design pattern within LLVM which not all of the developers are really supportive of (at this point).
On Aug 19, 2014, at 10:24 PM, Chandler Carruth <chan...@google.com> wrote:On Tue, Aug 19, 2014 at 10:10 PM, Pete Cooper <peter_...@apple.com> wrote:
I actually disagree with this for two reasons.On Aug 19, 2014, at 6:45 PM, Chandler Carruth <chan...@google.com> wrote:FWIW, I largely agree with Rafael's position here, at least in the near term.The nice thing about it is that even if we don't stay there forever, it is a nice incremental improvement over the current state of the world, and we can actually be mindful going forward of whether the restriction it imposes (an inability to use "internal" knobs from within a library context that have multiple different library users in a single address space) proves to be a significant on-going burden.The first is that if there are going to be changes to the code anyway to remove static initializers, and we can move the storage to the pass at the same time, the we should make just one change and not two.No one is suggesting otherwise that I have seen? At least, my interpretation (perhaps incorrect, I've not had time to read all of this thread in 100% detail) was that the removal of static initializers wouldn't require changing every cl::opt variable.
The second reason is that in most cases these knobs should not be globals. If I had a piece of data (not a CL::opt) in global scope, only used by one pass, then I'm sure people would question why it's a global at all and move it inside the class. We're treating cl::opt as special here when there's no reason for the opt or the storage to be global.We frown upon the use of globals, otherwise LLVM would be littered with them like many other C++ code bases. I don't think cl::opts should be special at all in this respect.
Sure, you're arguing against the core design of cl::opt. However, we have it, and it wasn't an accident or for lack of other patterns that we chose it.
For example, we don't require all constants to be per-pass, and instead have per-file constants. Rafael is suggesting that one use case for cl::opt global variables is, in essence, a constant that is somewhat easier for a developer of LLVM (*not* a user) to change during debugging and active development. I don't think the desire for convenience and only supporting the default value in production contexts are completely invalid.
Once you factor those in, we have a tradeoff. Historically, the tradeoff was made in the direction of convenience, relying on a very narrow interpretation of the use cases. It isn't clear to me that we should, today, make a different tradeoff. It certainly doesn't make sense why you would gate removing static initializers (a clear win) on forcing a change on a core design pattern within LLVM which not all of the developers are really supportive of (at this point).
To be honest, I had exactly the same reservations myself, but then i looked in to how we initialize and create passes and there actually isn’t a nice way to do this right now.
The trouble is that INITIALIZE_PASS doesn’t actually construct a pass. It actually constructs a PassInfo which has a pointer to the default constructor of the pass. Later, if the pass manager needs to (say -scalarize was on the commandline), it will get the default constructor from PassInfo and construct the pass.
Unfortunately, this completely detaches the lifetime of the pass instance where we want to store the ScalarizeLoadStore bool, from the option code to hook in to the cl::opt stuff. I originally wanted to do something gross like pass __offset_of(Scalarizer::ScalarizeLoadStore) to the PassInfo and hide the initialization of the option in there. But that doesn’t work either, as there’s no guarantee you’ll even create a instance of Scalarizer, even though you could pass -scalarize-load-store to the command line.
So, we do have 2 solutions: a global variable, and a call to GetValue. As you can see, either way isn’t perfect, but if you can think of another solution i’m sure we can discuss it.
Thanks,
Pete
What if we added a static method to the Scalarizer class. This method takes pointers to each option storage. If a pointer is null, the function is being called from INITIALIZE_PASS and so we create all the options. If a pointer is not null, we’re being called from the pass constructor and we set the value of that option. I think it would look something like this (which can of course be tidied up).
static void addOptions(bool *ScalarizeLoadStore = nullptr) {
Option::iterator ScalarizeLoadStoreOpt =
getOrAddOption<bool>("scalarize-load-store");
if (ScalarizeLoadStore) {
// Get the value of the option.
*ScalarizeLoadStore = ScalarizeLoadStoreOpt.getValue();
} else {
// Adding the option with this name. Set up its properties.
ScalarizeLoadStoreOpt.init(cl::Hidden, cl::init(false),
cl::desc("Allow the scalarizer pass to scalarize loads and store"));
}
}
Pete
Pass the passinfo to the pass constructor maybe?
I still don't understand what the problem with the global is. It has
the same value for all users. As Chandler pointed out, having
static cl::opt<bool> ScalarizeLoadStore
("scalarize-load-store", cl::Hidden, cl::init(false),
cl::desc("Allow the scalarizer pass to scalarize loads and store"));
right now is just our way of making
// Allow the scalarizer pass to scalarize loads and store
const static bool ScalarizeLoadStore = false;
more convenient to developers so they don't have to edit/compile to
test it with a different value. From a library user point of view they
should be exactly the same: a constant that is *always* false.
Another option (not my preference) would be to use globals just as keys:
typedef <something> LLVMOptionKey;
...
static LLVMOptionKey ScalarizeLoadStoreKey; //global
...
cl::OptionRegistry::createOption<bool>(&ScalarizeLoadStoreKey,
"ScalarizeLoadStore",
"scalarize-load-store", cl::Hidden, cl::init(false),
cl::desc("Allow the scalarizer pass to scalarize loads and store"));
....
bool ScalarizeLoadStore =
cl::OptionRegistry::getValue<bool>(&ScalarizeLoadStoreKey); // local
That way we avoid exposing ScalarizeLoadStore to library users since
the getValue takes a key they cannot guess instead of well known
string.
As long as we are careful to make sure only the command line parsing
can set this, it should be fine. It has some nice properties missing
from the original proposal (including stage2)
* "scalarize-load-store" is written once. Not extra string keys.
* It seems easier to hide it.
* We don't need a LLVMConfig object that gets passed around.
* There is exactly one of exposing features to libraries: change the
constructor and maybe the PassManagerBuilder.
I still don't see the advantage over a static storage, but I am not
strongly oppose to it, as long as there is nothing like
cl::OptionRegistry::SetValue<bool>("ScalarizeLoadStore", true) that
libraries can use.
Thanks,
Pete
The Key global is only used for its unique address, so LLVMOptionKey
could be just "void *" for example.
On Aug 19, 2014, at 10:24 PM, Chandler Carruth <chan...@google.com> wrote:For example, we don't require all constants to be per-pass, and instead have per-file constants. Rafael is suggesting that one use case for cl::opt global variables is, in essence, a constant that is somewhat easier for a developer of LLVM (*not* a user) to change during debugging and active development. I don't think the desire for convenience and only supporting the default value in production contexts are completely invalid.
Globals are bad for many reasons: namespace pollution, concurrency issues, lack of access control, etc. etc.. Some of them have been discussed in this thread. Perhaps it’s not a big concern for most of the LLVM users. But we have an unique environment where LLVM is shared by multiple clients, and where the concern around exploits are especially strong. So while eliminating globals is not strictly tied to the elimination of static initializers, it is still a strong goal towards providing a LLVM dylib.
Evan
_______________________________________________
Fair enough. I would still make at separate stage since how to remove
them is the part that is still a bit contentious. Note that from a
security point of view a well known string probably makes things worse
than the global option storage since the address of the storage is at
least randomized.
It seems that both mine and Peter's proposal would avoid the global
storage and not introduce well known string for setting the options.
Not automatic no, but in the proposal Chris puts the addOption call inside the pass initializer which is called before ParseCommandLineOptions. This means you’ll still get options listed as you currently do, so long as you continue to calls the pass initializers before parse (something you have to do anyway to get the pass name visible to the command line)On Aug 19, 2014, at 9:43 PM, Sean Silva <chiso...@gmail.com> wrote:One interesting issue with moving away from the current system of static initializers for cl::opt is that we will no longer have the automatic registration of all the options so that -help will print everything available and generally we will not be able to issue an error for an "unknown command line option" (without calling into any other code).That would be nice. I just suggested in another thread that we expose ParseCommandLineOptions to the C API to hack around this, but a nice clean interface would of course be better.The auto-registration is fundamentally tied with the globalness and the static initializers; pondering this has led me down an interesting path that has made me understand better my suggestion in the other thread. As I see it, there are two very different sorts of uses of llvm::cl in LLVM:1. For regular command line processing. E.g. if a tool accepts an output file, then we need something that will parse the argument from the command line.2. As a way to easily set up a conduit from A to B, where A is the command line and B is some place "deep" inside the LLVM library code that will do something in response to the command line.(and, pending discussion, someday point A might include a proper programmatic interface (i.e. in a way other than hijacking the command line processing))Right. The current point is in the pass initializer.llvm::cl does a decent job for #1 and that is what it was designed for AFAICT; these uses of llvm::cl live outside of library code and everything is pretty happy, despite them being global and having static initializers.The problem is that llvm::cl is not very well-suited to #2, yet it is used for #2, and that is the real problem. We need a solution to problem #2 which does not use llvm::cl. Thus, I don't think that the solution you propose here is the right direction.The first step is to clearly differentiate between #1 and #2. I will say "command line options" for #1 and "configuration/tweak points" for #2. (maybe "library options" is better for #2; neither is perfect terminology)The strawman I suggested in http://lists.cs.uiuc.edu/pipermail/llvmdev/2014-August/075503.html was a stab at #2. There is no way to dodge being stringly typed since command lines are stringly typed, so really it is just a question of how long a solution stays stringly typed.My thought process for staying stringly typed "the whole time" (possibly with some caching) comes from these two desires:- adding a c/t point should require adding just one call into the c/t machinery (this is both for convenience and for DRY/SPOT), andThere is another point in the pass constructor to read the option value. This is the only point at which something will change from being a string to its actual type and value.
The current proposal exposes the type in addOption (as well as later when we get the option). So the type continues to be known to the command line parser. Whether you want to actually type check in the command line is a point i’m open to discuss.- this change should be localized to the code being configured/tweakedThis is the thought process:Note that llvm::cl is stringly typed until it parses the options. llvm::cl gives the appearance of a typed interface because it uses static initialization as a backdoor to globally transport the knowledge of the expected type to the option parsing machinery (very early in the program lifetime). Without this backdoor, we need to stay stringly typed longer, at least until we reach the "localized" place where the single call into the c/t machinery is made; this single call is the only place that has the type information needed for the c/t value to become properly typed. But there is no way to know how long it will be until we reach that point (or even *if* we reach that point; consider passes that are not run on this invocation).
Personally i want a command line option to be type checked because it was registered, even if no-one actually gets the value of the option later.I’m against it being in the context because you may want to set up and reuse passes multiple times with the same options, and use that configuration to compile multiple LLVMContexts. But I do agree that having a store with some lifetime is useful.Hence my suggestion of just putting a stringly typed key-value store (or whatever) in an easily accessible place (like LLVMContext), and just translating any unrecognized command line options (ones that are not for #1) into that stringly typed storage.
I think the current proposal is to have the store be a singleton, but there’s nothing to stop further work to have the storage for options be one per thread for example. If you wanted to have one pass manager per thread with its own set of passes, configured (currently) via their own call to ParseCommandLineOptions then that would be possible with little work beyond the current proposal.If you change the current proposal so that it doesn’t read cl::opt, then I think this reads to me like what is being proposed now. Really its creating a string->string map with addOption, and getting the values with getOption. The passes don’t care (or know) whether the options are set via the command line or any other API. I hope i’ve understood your proposal correctly here. Please correct me otherwise.I agree with Rafael that "constructor arguments to passes" are not c/t points. In the future, there might be some way to integrate the two (from the referenced post, you can probably tell that I kind of like the idea of doing so), but for now, I think the clear incremental step is to attack #2 and solve it without llvm::cl. I have suggested a way to do this that I think makes sense.
On Aug 20, 2014, at 12:16 PM, Rafael Avila de Espindola <rafael.e...@gmail.com> wrote:There nothing magical about llc or opt. If you need to pass debug options to your own tools, you can do that with command line options like llc or opt, but the important factors remain:* this is a debugging session, not regular use.* the option storage can remain static.* we don't need and API for setting the value of the option, command line is sufficient.
Thanks,
-Chris
On Aug 20, 2014, at 3:12 PM, Sean Silva <chiso...@gmail.com> wrote:On Wed, Aug 20, 2014 at 2:16 PM, Chris Bieneman <be...@apple.com> wrote:I think Rafael’s suggestion of using the address of a global as the key to the option store gives us the ability to accomplish all our goals without introducing a string keyed option store.
I’ve updated my patches from the original proposal to reflect those changes.
Does this look reasonable?The design seems to require no less than 4 not-too-close-to-each-other code changes to add an option (and LLVMOptionKey declaration, an LLVMOptionKey initialization, a call to GetValue, and a call to CreateOption). I think that the convenience for developers is an important aspect and this solution regresses significantly on that front.Especially, I think that we need to evaluate the viability of an explicit CreateOption call. Do all uses of cl::opt in the library code have a relatively convenient place to put that call? If not, then we won't be able to migrate them, and we will be stuck with a partial solution. If we are willing to accept a partial solution, then the design discussion needs to change; at the very least we need to consider the scope of the partial solution.
On Aug 20, 2014, at 3:12 PM, Sean Silva <chiso...@gmail.com> wrote:
On Wed, Aug 20, 2014 at 2:16 PM, Chris Bieneman <be...@apple.com> wrote:I think Rafael’s suggestion of using the address of a global as the key to the option store gives us the ability to accomplish all our goals without introducing a string keyed option store.
I’ve updated my patches from the original proposal to reflect those changes.
Does this look reasonable?The design seems to require no less than 4 not-too-close-to-each-other code changes to add an option (and LLVMOptionKey declaration, an LLVMOptionKey initialization, a call to GetValue, and a call to CreateOption). I think that the convenience for developers is an important aspect and this solution regresses significantly on that front.Especially, I think that we need to evaluate the viability of an explicit CreateOption call. Do all uses of cl::opt in the library code have a relatively convenient place to put that call? If not, then we won't be able to migrate them, and we will be stuck with a partial solution. If we are willing to accept a partial solution, then the design discussion needs to change; at the very least we need to consider the scope of the partial solution.Most cl::opts are in the passes, so they do have a convenient place to put the CreateOption call. There are others in places that are less convenient - like ISel lowering. However there are always initialization calls that CreateOption calls can be put into (in targets, libraries, etc).Fundamentally you and I are looking at this problem differently. My proposal has the following requirements:1) Preserve existing command line option function exactly as it is today2) Eliminate all static initializers associated with command line options and their storage3) Design a solution that can be phased in with existing code so we don’t need to change all cl::opts in the same commit
On Aug 20, 2014, at 11:18 PM, Chandler Carruth <chan...@google.com> wrote:I'll try to provide some feedback on this patch assuming that we want to try to completely move away from global variables in a single step (something that I do generally support, although I don't understand why a more incremental approach is unacceptable -- it seems like a bit more work over all but a somewhat smoother transition for the community).
I feel like the APIs you're ending up with are bending around backwards to achieve things that it isn't even clear are valuable:1) They seem to be trying to working very hard to behave similarly to the existing cl::opt interfaces. If we're so radically changing the core design of cl::opt, different interfaces might be in order.
2) Perhaps this was explained up-thread (I'm going to try to read most of the older posts, but I'm still catching up on this thread) but if we're going this direction I would really expect the options to be per-LLVMContext... I feel like these are just "lazy globals with private storage" which don't seem all that conceptually better than globals. They've just engineered around the technical problems caused.
3) I really dislike the whole INITIALIZE_PASS_{BEGIN,END} pattern. I'm not sure if there is any realistic alternative, but I'm expecting to essentially have to rework every single one of these for the new pass manager. =[
I'm going to try to read Sean's proposal, but I'm suspect it is essentially a strongly typed option registry inside the LLVMContext? With some way to collect the options first and then to parse flags? That kind of approach seems more likely to really solve this issue once and for all and be an excellent, and scalable long-term solution... but as I said, I'm still catching up on the thread. I'll try to post more coherent thoughts when I've had time to read the other posts fully and skim through the other proposals.
I’d really prefer if we didn’t gate removing static initializers and global option storage, which I think we can both agree are good things, on a larger change to a core design pattern within LLVM.
Chris’ suggestion is to make an OptionStore class and pass it throughout the APIs where we want to handle options. At first the store should be a global singleton. Users of options don’t need to know about the LLVMContext or any other unrelated data structure. If the options are stored as a field of the context then that can easily be done too.
If we later decide that the OptionStore should live in the LLVMContext or any other location then thats fine, but moving it to that point would be a minimal change as no APIs have to be rewritten. Also, if we decide that we want the LLVMContext to have an option store, but MC level tools to be allowed to define their own, then that would also be possible.
Thanks,
Pete
I disagree with this point. The majority of the fields of the context are IR. An MC only tool should not be required to link the LLVM IR just because they want to use a command line option.>> - I'd like to avoid a separate "option store". My current suggestion is to
>> use the LLVMContext, and to add a context to the layers which don't have an
>> LLVMContext and where these kinds of options make sense.
>
> I agree. There are few places in LLVM without a LLVMContext. For
> example, there is one cl::opt in lib/MC and Joerg already has a patch
> to turn it into a proper API.
-Chandler
more complex metaprogramming based approach (which as I understand it is his suggestion).
I count 15 occurrences of "-backend-option" in clang/lib/Driver/Tools.cpp and most (all? didn't look at them real hard) of those aren't debugging options. Presumably those can all be solved by adding more plumbing, but it would be *really* nice to make that plumbing easier to do.
--paulr
Chandler brought up a lot of really great points. One of his big points was that if we’re going to touch every pass, we may as well fix the cl::opt API too.Toward that end I’ve put together some patches with a new fluent-style API as a starting point of a conversation.Disclaimer: To make these patches work with the existing cl::opts there is some nasty hackery going on in CommandLine.h — For the sake of this conversation I’d like to focus our attention on the API for creating and accessing options in Scalarizer.cpp
My intent with these changes is to provide a groundwork for meeting all of Chandler’s main points. These patches have the following high-level changes from my previous patches:1) I’ve switched to some crazy template-foo for generating IDs to identify options2) I’ve moved all the new API components out of the cl namespace3) There is no option storage outside the OptionRegistry, but I have defined a get API and setup template methods for reading from a store and suggested API for LLVMContext to implement4) I’ve defined a new API for defining options in the form of the opt_builder object. This is intended to be a transitional API only, but it allows us to migrate off the cl::opt template-fooAs with my previous patches, these patches are designed to work with existing cl::opts.
On Wed, Aug 27, 2014 at 2:36 PM, Chris Bieneman <be...@apple.com> wrote:
Chandler brought up a lot of really great points. One of his big points was that if we’re going to touch every pass, we may as well fix the cl::opt API too.Toward that end I’ve put together some patches with a new fluent-style API as a starting point of a conversation.Disclaimer: To make these patches work with the existing cl::opts there is some nasty hackery going on in CommandLine.h — For the sake of this conversation I’d like to focus our attention on the API for creating and accessing options in Scalarizer.cppYep, I'll actually only use that part of the patch to comment on, I agree the rest are largely details.My intent with these changes is to provide a groundwork for meeting all of Chandler’s main points. These patches have the following high-level changes from my previous patches:1) I’ve switched to some crazy template-foo for generating IDs to identify options2) I’ve moved all the new API components out of the cl namespace3) There is no option storage outside the OptionRegistry, but I have defined a get API and setup template methods for reading from a store and suggested API for LLVMContext to implement4) I’ve defined a new API for defining options in the form of the opt_builder object. This is intended to be a transitional API only, but it allows us to migrate off the cl::opt template-fooAs with my previous patches, these patches are designed to work with existing cl::opts.One very high-level comment about this interaction...I think it would be nice to end up with these debugging options fully separated from the 'cl::opt' stuff from the perspective of code registering and querying an option. What I'm thinking is that we should be able to give simple guidance within LLVM: library code doesn't use CommandLine.h, it uses DebugOptions.h (or whatever its called).However, as you say, we obviously need to integrate cleanly with the cl::opt world that exists. =] I would probably structure it such that these debugging options didn't depend on any of the details of the cl::opt infrastructure, and instead the cl::opt stuff queried these debugging options to collect their names and parse them when parsing command line options. I suspect long term the library interface for setting and toggling these may well be unrelated to the cl::opt interface; it would at least be nice to leave that option open, which I why I would suggest layering it in that direction. Does that make sense? Perhaps there are implementation reasons that preclude it, I've not checked as I agree that the current code there isn't important, but I wanted to mention the layering thing just so it was on your radar.
I understand that some layers of LLVM will need to use something other than LLVMContext, but as mentioned in IRC, I'm interested in just having one object that gathers common state for a layer and you can introduce new types/objects for layers that shouldn't be querying LLVMContext.@@ -150,6 +163,18 @@ public:bool visitLoadInst(LoadInst &);bool visitStoreInst(StoreInst &);+ static void RegisterOptions() {+ // This is disabled by default because having separate loads and stores makes+ // it more likely that the -combiner-alias-analysis limits will be reached.+ OptionRegistry::CreateOption<bool,+ Scalarizer,+ &Scalarizer::ScalarizeLoadStore>()+ .setInitialValue(false)+ .setArgStr("scalarize-load-store")+ .setHiddenFlag(cl::Hidden)+ .setDescription("Allow the scalarizer pass to scalarize loads and store");As this is a new interface, I would follow the new naming conventions here.Also, I don't think it being a static method is really useful. What about just making this a free function "registerOption”?
I wouldn't set the initial value here -- I think it is more clear and more flexible to pass that into the "get" API.
The argument string isn't optional, right? The initial idea I was thinking of for a fluent-style API was to have the required parameters as normal ones, and the fluent API for optional. I had also imagined (but I'm not really attached to it, curious what you think here) using it as an option-struct builder for an optional parameter... but I've no idea what to call it. Here is a rough example of what I'm thinking just so that we can both see it:static void registerOptions() {registerOption<bool, Scalarizer, &Scalarizer::ScalarizeLoadStore>("scalarize-load-store",OptionOptions.hidden().description("Allow the scalarizer pass to scalarize loads and stores"));}
However, now that I write all this, I think I was just really wrong about the fluent API. It's not that the fluent API isn't a good way to implement something like what cl::opt is providing, its just that seeing this example makes me think it's doing the wrong thing: these shouldn't be optional flags at all.1) The initial value *should* be optional, but that already can be optional if its in the "get" API, and we can report errors nicely when the option is missing.2) The name of the option is pretty clearly something that should be required I think.3) Making the description optional seems like a mistake in retrospect. Essentially all of them have the description, and *especially* the ones that this API is designed to replace: highly specialized options for configuring the innards of some part of the library.4) I think the "hidden" distinction is no longer needed. All of the options using this new API should be "hidden" options -- they're just debugging tuning knobs. It's the options that continue to use cl::opt from inside of the tools themselves that would want to be non-hidden I think?At that point, I think this becomes something pleasingly simple:
static void registerOptions() {registerOption<bool, Scalarizer, &Scalarizer::ScalarizeLoadStore>("scalarize-load-store","Allow the scalarizer pass to scalarize loads and stores");}Thoughts?
The argument string isn't optional, right? The initial idea I was thinking of for a fluent-style API was to have the required parameters as normal ones, and the fluent API for optional. I had also imagined (but I'm not really attached to it, curious what you think here) using it as an option-struct builder for an optional parameter... but I've no idea what to call it. Here is a rough example of what I'm thinking just so that we can both see it:static void registerOptions() {registerOption<bool, Scalarizer, &Scalarizer::ScalarizeLoadStore>("scalarize-load-store",OptionOptions.hidden().description("Allow the scalarizer pass to scalarize loads and stores"));}However, now that I write all this, I think I was just really wrong about the fluent API. It's not that the fluent API isn't a good way to implement something like what cl::opt is providing, its just that seeing this example makes me think it's doing the wrong thing: these shouldn't be optional flags at all.1) The initial value *should* be optional, but that already can be optional if its in the "get" API, and we can report errors nicely when the option is missing.2) The name of the option is pretty clearly something that should be required I think.3) Making the description optional seems like a mistake in retrospect. Essentially all of them have the description, and *especially* the ones that this API is designed to replace: highly specialized options for configuring the innards of some part of the library.4) I think the "hidden" distinction is no longer needed. All of the options using this new API should be "hidden" options -- they're just debugging tuning knobs. It's the options that continue to use cl::opt from inside of the tools themselves that would want to be non-hidden I think?At that point, I think this becomes something pleasingly simple:
static void registerOptions() {registerOption<bool, Scalarizer, &Scalarizer::ScalarizeLoadStore>("scalarize-load-store","Allow the scalarizer pass to scalarize loads and stores");}Thoughts?Oddly enough the argument string IS optional, but you must have either an argument string or cl::Positional (but not both). It is probably reasonable to define two registerOption() calls one that takes an argument string and description, and one that only takes a description and implies cl::Positional.I also think we still need a fluent-style API for toggling some options that aren’t always default values (like hidden). In the case of hidden, maybe the better way to handle it is to make registerOption default to creating hidden options and have a “.visible()” API for toggling it?It seems to me like you’re suggesting an end solution where cl::opt still exists for tool-specific options, and the register/get API exists for all of the other options littered around the compiler. While I’m not going to object strongly to this idea because it does serve my purposes (getting rid of static initializers in the libraries), I don’t particularly care for this. I think fundamentally if we are aiming to provide a better API for defining options, I don’t think there is any reason not to use that API everywhere and to abandon the existing one completely. If you disagree, please let me know.-Chris
It depends on the specifics, but in general having the default value for the options be specified (potentially differently) on every call to the getter method feels very wrong to me. Perhaps I am misunderstanding the proposal?
Oddly enough the argument string IS optional, but you must have either an argument string or cl::Positional (but not both). It is probably reasonable to define two registerOption() calls one that takes an argument string and description, and one that only takes a description and implies cl::Positional.
It seems to me like you’re suggesting an end solution where cl::opt still exists for tool-specific options, and the register/get API exists for all of the other options littered around the compiler. While I’m not going to object strongly to this idea because it does serve my purposes (getting rid of static initializers in the libraries), I don’t particularly care for this. I think fundamentally if we are aiming to provide a better API for defining options, I don’t think there is any reason not to use that API everywhere and to abandon the existing one completely. If you disagree, please let me know.
So, trying to quickly reply to what I think may be a high-level point of confusion that we should sift through early:
On Fri, Aug 29, 2014 at 8:53 AM, Chris Bieneman <cbie...@apple.com> wrote:Oddly enough the argument string IS optional, but you must have either an argument string or cl::Positional (but not both). It is probably reasonable to define two registerOption() calls one that takes an argument string and description, and one that only takes a description and implies cl::Positional.I think all of this comes down to the point you make below:It seems to me like you’re suggesting an end solution where cl::opt still exists for tool-specific options, and the register/get API exists for all of the other options littered around the compiler. While I’m not going to object strongly to this idea because it does serve my purposes (getting rid of static initializers in the libraries), I don’t particularly care for this. I think fundamentally if we are aiming to provide a better API for defining options, I don’t think there is any reason not to use that API everywhere and to abandon the existing one completely. If you disagree, please let me know.
Ah, ok, here we have uncovered what I suspect is the underpinning set of different assumptions / directions that are creating some of the confusion. Now that you've put your finger on it (thanks!) I'll try actually address this. Sorry if this is a bit of a re-statement, but hopefully it'll at least let you respond directly with where my thinking has gone off the rails.So I am definitely trying to design this as a system totally divorced from the tool-specific options, or actually a command line system of any form. That's why stuff like positional arguments and the cl::opt tie-ins aren't showing up in my thoughts and suggestions. What you say makes perfect sense if we're building a replacement for *all* of cl::opt's functionality. While I would be interested in trying to do that (and we already have one replacement in tree used by Clang and LLD to parse command line options), I'm suggesting that what the LLVM *libraries* need is something completely separable from a command line interface, but which is easy to build a command line interface around.
The way I'm thinking of this is as a generic collection of optional key->value settings. The libraries don't have any business mucking with positional parameters, non-hidden options, or the other concerns of a command line system, and the code it uses (and the APIs it uses) to register and use these options is a *better* interface when it is narrower and doesn't have to support these features.
Now, I think we should still be able to expose these via the 'cl::opt' layer in the tools that are using that layer. But we should also be able to expose it via an API to say webkit or whomever needs it there. And we should be able to wrap it in a nicer command line interface in Clang.
Is that a convincing argument for you to restrict the scope of this interface? Maybe there are other things that you'd like to do here that motivate going the other direction?
While it is true that we probably don’t need to allow the libraries to mess around with positional parameters, non-hidden options are (I think) a different story. If you look at include/llvm/CodeGen/CommandFlags.h, there are a number of flags defined here that are not positional, not hidden, but only relevant to the CodeGen library. It is probably reasonable that these flags be transitioned to the new API, but they also should be exposed on the command line.
Aside from those options there are probably very few cases where it actually makes sense for library options to not be hidden, although I must add the caveat that I’m sure there are plenty of library options that are not hidden today and making this change will make them hidden. I’m ok with this, but it does change one of my original goals because it will actually modify the behavior of the command line.
Is that a convincing argument for you to restrict the scope of this interface? Maybe there are other things that you'd like to do here that motivate going the other direction?How do you feel about also providing a fluent-style API for toggling the (hopefully) uncommon options?
Picking this back up, I think that your patch with some cleanups is probably the right starting point. I think the only really substantive issue I currently have is that I'd rather have the OptionRegistry in the LLVMContext rather than in a singleton method. I understand we'll also have to add similar registries to other context objects (MCContext at least), but I think it's useful to start off with just one context initially.
How do you want to go about the review / cleanups on the patch? Maybe a new thread? I have a couple of significant things and probably a bunch of really minor cleanup stuff.
On Sep 16, 2014, at 5:28 PM, Chandler Carruth <chan...@google.com> wrote:Picking this back up, I think that your patch with some cleanups is probably the right starting point. I think the only really substantive issue I currently have is that I'd rather have the OptionRegistry in the LLVMContext rather than in a singleton method. I understand we'll also have to add similar registries to other context objects (MCContext at least), but I think it's useful to start off with just one context initially.In my last patches I had the OptionRegistry really just being a template type that conformed to the get interface. I was having it be a singleton so that we have a way to gradually transition. To make it the context means we'll need to change all the pass constructors and the pass macros up front. My thoughts on how to phase this in are that we first use the template/singleton that I had in my last patches. Then we can update the context to conform to the API, and migrate the macros and pass construction to pass the context in. After that we can remove the default constructors from the passes and replace the template argument with LLVMContext.Does that sound like a good roadmap for a transition?
How do you want to go about the review / cleanups on the patch? Maybe a new thread? I have a couple of significant things and probably a bunch of really minor cleanup stuff.Sounds good to me. How about I clean up my patches based on your recommendations below and start a Phabricator review?