[Mono-list] MCS -cppoutput C# to C++ generator work in progress
Ben Cooley
bencooley@cinematix.com
Fri, 5 Jul 2002 12:19:10 +0900
> Hello!
>
> > Since porting last may's rev of mono to MSVC , I've been working on the
C++
> > output module for mcs. Basically, cppoutput.cs is added to the mcs
core,
> > and from the parse tree generated by the main compiler, it generates a
> > compatible set of .cpp, .h, and .inl files complete with nice #line
> > directives for .cs debugging, and with the limited set of statements
> > compiling, it seems to work nicely.
>
> I am not sure that you will be able to do a complete translator by using
> the internal parse tree, as this parse tree is lacking the semantic
> analysis phase.
>
> For instance, during the `DoResolve' phase, names are resolved to their
> actual meaning. For instance:
>
> A += X;
>
> A could mean a number of things depending on its context. An assignment
> to field variable; An assignment to a property; An event addition or
> even an error if A is a type.
>
> My suggestion would be to add a different "Emit" method to the Statement
> and Expression base classes (EmitCpp) that would generate the code that
> you want, but the resulting code would look less than C#, and more close
> to the real internal representation.
>
> Btw, someone could also write an EmitJava method, and for some cases
> generate code for a JVM.
Actually the call to the cpp output stuff comes right before the code
generation
phase of the compiler, when all of the type information, etc. has been
deduced
and all of the pre-types have been generated, so that's really not a
problem. The only
thing I needed to do was to make one or two internal properties in
expresions.cs
have a public interface.
Also, I thought about adding a CppEmit() method to the various mono classes,
figured that would dirty up the code something fierce. Primarily the
problem is
in storing all of the necessary internal state variables and whatnot in your
classes. So I decided the best and probably cleanest way to implement the
system would be to pack it into a single (or small set) of Cpp generator
classes
in my own file. That requires only the tiniest changes in the core
compiler, and
makes the whole thing more self contained. To add the --cppoutput to the
mcs compiler, all you need to do is add the cppoutput.cs file, and change
the
compiler options to support it, and then call the output methods in the main
compiler driver function right before the "EmitCode" stuff, (and right after
emit code again to grab the metadata .exe and .dll files generated by the
main
compiler.) Small footprint, and everybody working on the core compiler
need not worry about it.
> > I tweaked mono's and binary vtable representations to coexist with C++
> > efficiently so that mono could easily marshall and call c++ code as if
it
> > was doing an "internal_call", and c++ could call mono as well using
> > mono_execute(). The solution I came up with was to put mono's vtable
> > "before" the vtable structure, and the c++ vtable after it. When you
> > inherit in C++ from the Object class, you automatically get a set of 6
> > vtable entries which reserve space in the C++ vtable for the mono vtable
> > structure. That way mono objects are C++ objects, and vica-versa, and
each
> > side conveniently marshals to the other transparently.
>
> Pretty cool hack, I am reading with excitement the rest of your
> message. It looks really interesting.
Thanks. I'll have more of the manual processes (metadata inclusion) working
automatically by this weekend, and possibly support for more statements.
I'm
still working with my ancient MSVC build of mono, so I need to do a merge
eventually. I use a program called "beyond compare" to do complex merges
in Windows.. works extremely well. Don't know if it produces diff or patch
output though.
Question: What precisely does the "internal call" marshaling/trampoline code
do in the JIT? Can mono be technically made to directly call the C++
code directly (and vica versa) if careful control of the C++ stack is
excercised?
Ben