I wanted to discuss this at the meeting yesterday but we ran out of time.
We had touched on this briefly in our Oct 14th meeting. Here’s the recap IIRC: There are two different ways we could “lower” to SystemVerilog code: 1) provide an Interface for Ops and Types so they can worry about it themselves. 2) Make everything lower to the SV dialect before outputting.
My thoughts: Interfaces provide the most flexibility and can be used along with types/ops in the SV dialect for common SystemVerilog constructs (e.g. SV Interfaces). This prevents us from having to write a complete (for some definition of complete) syntax tree in the SV dialect when the slightly-higher level Ops in the RTL dialect suffice. (How much value is there in having an AndOp defined both in the RTL and SV dialects?)
Assuming everyone likes this hybrid approach, what should this interface look like? The strawman is just pass around a
raw_ostream and have code write raw text. A few possible improvements and problems with that strawman:
- SystemVerilog (like every language except perl) has syntactic restrictions. Do we want to enforce the syntactic restrictions? (I think this it the primary advantage of requiring everything to lower to the SV dialect.) If so, how should we do that?
- Some Ops have to output code in various places around the output code. For instance, declaring wires before using them is often necessary.
- I think there is value in providing a SystemVerilogPrinter which knows about basic SV syntax and provides SV specific helper functions. (Kind of like DialectAsmPrinter.) What should this helpers API look like?
- There’s information which needs to be shared both globally and at particular scopes. (e.g. allocation of text identifiers.) Should we handle this in the proposed printer?
The other question is how do we structure this in terms of code structure logistics. My preference would be developing a new system which exists in parallel with EmitVerilog.cpp, stealing as much as possible from EmitVerilog.cpp. This has the advantage of not worrying about breaking something in EmitVerilog.cpp.
@clattner this kind of thing is probably present in other places in LLVM. (The MC asm printers are probably a rather simple example.) Can you provide some code pointers and/or suggestions for this? Can you speak to the advantages / pitfalls of DialectAsmPrinter or other such things?
I’d like to get the ball rolling on this since I’m about to start emitting SystemVerilog for ESI and don’t want to be writing throw-away code or for the API to change. I’m even willing to throw together a prototype and iterate on it a bit.