Pointer ownership semantics, Attaching debug info and "unsigned" usage in LLVM - llvm

I've recently started using LLVM IR generation APIs for my project. The documentation and LLC tool are pretty helpful, but I haven't been able to find answer to the following -
Question-1 - Pointer ownership semantics
All code that creates LLVM IR instructions using their APIs seems to "new" instructions instead of creating them as stack variables.
auto x = new Alloca(...) vs. Alloca(...) x;
I am wondering what the ownership semantics are for the pointers that are created? Do I have to call delete on these instruction objects. All code that I've seen calls "delete engine;".
I am guessing that all this memory is owned by this Module object and when the module is destroyed, all the memory occupied by these instructions are also destroyed. By looking at some of the code, it seems that all these instruction objects are created by using "placement new" ... Is this understanding correct?
Question-2 - Why doe LLVM IR APIs take "unsigned" data-type args. (e.g. unsigned addresspace is one common argument. Why not a sized type like uint32_t ?)
Question-3 - How to attach debug information to an IR instruction? Pointers to LLVM APIs to attach debug info would be really useful.

It's probably best to split this up into 3 questions, but to answer the 3rd question I did a talk at this year's US LLVM Developer Conference on exactly this:
http://llvm.org/devmtg/2014-10/#tutorial3
and you can also use the documentation I wrote after as a guideline:
http://llvm.org/docs/tutorial/LangImpl8.html

Related

Shall the caller deallocate the return value of `SHCreateMemStream`?

This is a dumb question, but I'm sorry I cannot find this information in the online manual of the function. I came from Linux realm. I'm not familiar with convention in Windows world.
All examples I found use smart pointer, e.g. wil::com_ptr, but GCC obviously doesn't provide those tools. Shall I call Release on the return value? Or leave it alone? Thanks.
IStream is built on top of the classic COM IUnknown interface, and as such any COM interface pointer returned from a function has had IUnknown::AddRef() called on it, and so you must call IUnknown::Release() when you're done using the interface pointer or else you'll leak memory.
GCC obviously doesn't provide those tools
Just in case you needed a reason to use cl on Windows and the Windows SDK, you found it.

Pinning Unsafe pointer

I'm designing a JNI interface that passes string parameters from Java to C++. I need high performance and have been able to use Direct ByteBuffer and String.getBytes() to do that fairly well, but the penalty for passing strings to C/C++ still remains fairly high. I recently read about the Open JDK's Unsafe class. This excellent page got me started, but I'm finding Unsafe to be woefully, but understandably poorly documented.
I'm wondering, if I use the Unsafe class to obtain a pointer to a string and pass it to C++, is there a risk that the object has moved before the C++ code is entered? And even while C++ is executing? Or are these addresses provided by the Unsafe code somehow pinned? If they aren't pinned, how are these Unsafe pointers ever useful?
Unsafe is not meant to interop with JNI. So obtained via Unsafe could change any time (even in parallel with your C++).
JNI API has ability to pin object in memory to access array content (in HotSpot JVM it would block GC thus may have negative effect on GC pause duration).
In particular, Get*ArrayElements would pin array until you explicitly do Release*ArrayElements. GetStringChars work similar way.
Direct ByteBuffer hold pointer to memory buffer outside of heap, hense this buffer is not moving and you can access it for Native code.
I've read the Java source for java.misc.Unsafe and have a bit more insight.
Unsafe has at least two ways of dealing with memory.
allocateMemory/reallocateMemory/freeMemory/etc -- As far as I can tell this allocation of memory is outside the heap so faces no GC'ing challenges. I have indirectly tested this and it seems that the long returned is simply a pointer to the memory. It seems very likely that this type of memory is safe to pass through JNI to native code. And the application Java code should be able to quickly modify/query it before and after JNI calls by using some of the other intrinsic Unsafe methods that support this style of memory pointer.
object+offset - These methods accept a pointer to an object and an "offset" token to indicate where in the object to fetch/modify the value. The objects presumably are always in the Java heap, but passing the object to these methods probably helps resolve GC complications. It does sounds like the "offset" is sometimes a "cookie" rather than an actual offset, but it also sounds like that in the case of arrays, arrayBaseOffset() returns an "offset" that one can manipulate arithmetically. I don't know if this object+offset is safe for JNI code. I don't see a method to generate a pointer directly to the Java object in the heap that one could (dangerously) pass through JNI. One could pass an object and offset, but given the cost of passing Objects through JNI, this approach is not appealing anyway.
Like (1), the code associated with the page I referenced in my posting is probably pretty safe for JNI interactions. It takes the object+offset approach when dealing with String, but uses approach (1) when dealing with the direct ByteBuffer, which always reside outside the Java heap. Direct ByteBuffer's are very JNI friendly and often they can be used in ways that avoids the JNI Object passing costs I allude to in my comment to Tom above.

How to control the location of a global variable in LLVM IR?

I'm trying to modify LLVM so that it keeps certain constants and functions contiguous in memory.
In other words, I need to ensure that the machine codes for certain functions are always preceded by some ~4-byte constant in memory. The function body itself must not be modified.
Could I achieve this simply through modifying the LLVM IR somehow?
If yes:
How would I state in the LLVM IR to keep a variable and a function contiguous in memory?
If no:
What part of the code generation process (i.e. which pass(es)) should I modify in order to achieve this? Any links to the projects/files I should look at would be helpful, since I'm not sure where to begin yet.
As far as I know, I don't think you can do that by just modifying the IR; you'd have to write something to handle it, yourself. It shouldn't be a pass, either - it's too low-level, it should run during the target-specific code generation. You can piggyback on an existing target and just modify this aspect, of course, you don't have to write a new target from scratch. I don't know which location exactly will be good for this, though.
I think a good way to pass this information from the IR level to the DAG during the code generation would be using metadata: attach metadata to either the function or the associated constant that will link them with each other, then later on use that link for emitting them together. See this thread on llvm-dev for information how to transfer the metadata.

Precise mode in Boehm Garbage Collector

I've read on the webpage of Mono that they are using the Boehm GC in precise mode. I too use the Boehm GC with C++, however, I have found nothing in its documentation or headers that would indicate a precise mode, much less how to turn it on.
Any information whether it actually has a precise mode by default and how to turn it on, or it was just some kind of modification by Mono developers?
Precise mode in Boehm GC under Mono isn't just GC_MALLOC_ATOMIC. It's only true for arrays of fundamental types.
For managed types, GC_gcj_malloc is used. Mono's compiler generates an object descriptor for every managed type and it then simply calls GC_gcj_malloc with an argument of size, and a pointer to the managed type's descriptor. Boehm GC then refers to the descriptor during mark phase to trace the managed pointers.
You will end up with just the root pointers sitting on the stack as raw pointers (GC_gcj_malloc returns a void* and there's no way to tell the GC where the pointers are on the stack via some sort of a stack descriptor prior to GC collect). This is the reason Mono (prior to SGen) says they scan the stack in conservative mode.
If you want to implement this under C++, you won't be able to simply rely on the C++ compiler to generate the object descriptor for you. What I envisioned a long time ago was to write an intermediate compiler that parses all your C++ header files for class definitions that have been marked as managed class (e.g. _ref class MyManagedObject where _ref is simply a #define to nothing) and generate a header file containing those object descriptors. You would then use the GC_make_descriptor and GC_malloc_explicitly_typed functions to allocate your objects in precise mode rather than GC_gcj_malloc as you would not have control over how your C++ compiler allocates its vtable.
*EDIT: See Managed C++ for GCC (open source GPL v3).
The file doc/gcinterface.html from the garbage collector (archive here) states:
void * GC_MALLOC_ATOMIC(size_t nbytes)
Allocates nbytes of storage. Requires (amortized) time
proportional to nbytes. The resulting object will be automatically
deallocated when unreferenced. The client promises that the resulting
object will never contain any pointers. The memory is not cleared.
This is the preferred way to allocate strings, floating point arrays,
bitmaps, etc. More precise information about pointer locations can be
communicated to the collector using the interface in gc_typed.h in the
distribution.
It looks like there is a "precise" interface that can be used.
I believe the precise mode needs support from the compiler to indicate exactly where pointers are stored. Typecasting in C and C++ makes this next to impossible.
A managed language, with built in reflection, would make this a lot easier.

C++ Memory management

I've learned in College that you always have to free your unused Objects but not how you actually do it. For example structuring your code right and so on.
Are there any general rules on how to handle pointers in C++?
I'm currently not allowed to use boost. I have to stick to pure c++ because the framework I'm using forbids any use of generics.
I have worked with the embedded Symbian OS, which had an excellent system in place for this, based entirely on developer conventions.
Only one object will ever own a pointer. By default this is the creator.
Ownership can be passed on. To indicate passing of ownership, the object is passed as a pointer in the method signature (e.g. void Foo(Bar *zonk);).
The owner will decide when to delete the object.
To pass an object to a method just for use, the object is passed as a reference in the method signature (e.g. void Foo(Bat &zonk);).
Non-owner classes may store references (never pointers) to objects they are given only when they can be certain that the owner will not destroy it during use.
Basically, if a class simply uses something, it uses a reference. If a class owns something, it uses a pointer.
This worked beautifully and was a pleasure to use. Memory issues were very rare.
Rules:
Wherever possible, use a
smart pointer. Boost has some
good ones.
If you
can't use a smart pointer, null out
your pointer after deleting it.
Never work anywhere that won't let you use rule 1.
If someone disallows rule 1, remember that if you grab someone else's code, change the variable names and delete the copyright notices, no-one will ever notice. Unless it's a school project, where they actually check for that kind of shenanigans with quite sophisticated tools. See also, this question.
I would add another rule here:
Don't new/delete an object when an automatic object will do just fine.
We have found that programmers who are new to C++, or programmers coming over from languages like Java, seem to learn about new and then obsessively use it whenever they want to create any object, regardless of the context. This is especially pernicious when an object is created locally within a function purely to do something useful. Using new in this way can be detrimental to performance and can make it all too easy to introduce silly memory leaks when the corresponding delete is forgotten. Yes, smart pointers can help with the latter but it won't solve the performance issues (assuming that new/delete or an equivalent is used behind the scenes). Interestingly (well, maybe), we have found that delete often tends to be more expensive than new when using Visual C++.
Some of this confusion also comes from the fact that functions they call might take pointers, or even smart pointers, as arguments (when references would perhaps be better/clearer). This makes them think that they need to "create" a pointer (a lot of people seem to think that this is what new does) to be able to pass a pointer to a function. Clearly, this requires some rules about how APIs are written to make calling conventions as unambiguous as possible, which are reinforced with clear comments supplied with the function prototype.
In the general case (resource management, where resource is not necessarily memory), you need to be familiar with the RAII pattern. This is one of the most important pieces of information for C++ developers.
In general, avoid allocating from the heap unless you have to. If you have to, use reference counting for objects that are long-lived and need to be shared between diverse parts of your code.
Sometimes you need to allocate objects dynamically, but they will only be used within a certain span of time. For example, in a previous project I needed to create a complex in-memory representation of a database schema -- basically a complex cyclic graph of objects. However, the graph was only needed for the duration of a database connection, after which all the nodes could be freed in one shot. In this kind of scenario, a good pattern to use is something I call the "local GC idiom." I'm not sure if it has an "official" name, as it's something I've only seen in my own code, and in Cocoa (see NSAutoreleasePool in Apple's Cocoa reference).
In a nutshell, you create a "collector" object that keeps pointers to the temporary objects that you allocate using new. It is usually tied to some scope in your program, either a static scope (e.g. -- as a stack-allocated object that implements the RAII idiom) or a dynamic one (e.g. -- tied to the lifetime of a database connection, as in my previous project). When the "collector" object is freed, its destructor frees all of the objects that it points to.
Also, like DrPizza I think the restriction to not use templates is too harsh. However, having done a lot of development on ancient versions of Solaris, AIX, and HP-UX (just recently - yes, these platforms are still alive in the Fortune 50), I can tell you that if you really care about portability, you should use templates as little as possible. Using them for containers and smart pointers ought to be ok, though (it worked for me). Without templates the technique I described is more painful to implement. It would require that all objects managed by the "collector" derive from a common base class.
G'day,
I'd suggest reading the relevant sections of "Effective C++" by Scott Meyers. Easy to read and he covers some interesting gotchas to trap the unwary.
I'm also intrigued by the lack of templates. So no STL or Boost. Wow.
BTW Getting people to agree on conventions is an excellent idea. As is getting everyone to agree on conventions for OOD. BTW The latest edition of Effective C++ doesn't have the excellent chapter about OOD conventions that the first edition had which is a pity, e.g. conventions such as public virtual inheritance always models an "isa" relationship.
Rob
When you have to use manage memory
manually, make sure you call delete
in the same
scope/function/class/module, which
ever applies first, e.g.:
Let the caller of a function allocate the memory that is filled by it,
do not return new'ed pointers.
Always call delete in the same exe/dll as you called new in, because otherwise you may have problems with heap corruptions (different incompatible runtime libraries).
you could derive everything from some base class that implement smart pointer like functionality (using ref()/unref() methods and a counter.
All points highlighted by #Timbo are important when designing that base class.