The best way to cope with AllocationInst type in old code?

Hi all,

I am working on some old code which was compiled against llvm-2.5.
Anyway, in some places I, AllocationInst is used (e.g. to ensure the
instruction's type). Even in your current documentation
(LLVM Programmer’s Manual — LLVM 16.0.0git documentation), I found an example that
uses this instruction.
If I got it correctly, this istruction (AllocationInst) has been
removed from llvm instruction set. How can I recode the behavior one
can expect from the AllocationInst? Should I check for call
instructions to malloc?

I'm new to llvm and I would really appreciate any comment or suggestion.

Thanks,
Hamid

Hamid 2C wrote:

Hi all,

I am working on some old code which was compiled against llvm-2.5.
Anyway, in some places I, AllocationInst is used (e.g. to ensure the
instruction's type). Even in your current documentation
(LLVM Programmer’s Manual — LLVM 16.0.0git documentation), I found an example that
uses this instruction.
If I got it correctly, this istruction (AllocationInst) has been
removed from llvm instruction set. How can I recode the behavior one
can expect from the AllocationInst? Should I check for call
instructions to malloc?

AllocationInst was a superclass of the AllocaInst and MallocInst, the latter of which was deleted so AllocationInst was removed.

In LLVM, a lot of code was updated to use the isMalloc() out of include/llvm/Analysis/MemoryBuiltins.h, but "isa<AllocaInst>(...) || isMalloc(...)" would be closest to "isa<AllocationInst>(...)".

Nick

Hamid 2C wrote:

Hi all,

I am working on some old code which was compiled against llvm-2.5.
Anyway, in some places I, AllocationInst is used (e.g. to ensure the
instruction's type). Even in your current documentation
(LLVM Programmer’s Manual — LLVM 16.0.0git documentation), I found an example that
uses this instruction.
If I got it correctly, this istruction (AllocationInst) has been
removed from llvm instruction set. How can I recode the behavior one
can expect from the AllocationInst? Should I check for call
instructions to malloc?

AllocationInst was a superclass of the AllocaInst and MallocInst, the
latter of which was deleted so AllocationInst was removed.

In LLVM, a lot of code was updated to use the isMalloc() out of
include/llvm/Analysis/MemoryBuiltins.h, but "isa<AllocaInst>(...) ||
isMalloc(...)" would be closest to "isa<AllocationInst>(...)".

As a related aside, I've been thinking for awhile that it would be nice to have an allocator analysis group. Each pass in the analysis group would recognize the allocators for a particular language or system and be able to return useful information for a call to that allocator (e.g., given a call to an allocator function, return an LLVM value representing the size of the allocation). The passes could chain like alias analysis passes; if one pass doesn't recognize a call instruction as a call to an allocator, it can ask another pass if it can identify the call.

My reasoning for this is that each language has its own allocator, and some of our LLVM passes (e.g., points-to analysis and memory safety instrumentation passes) have to be modified if/when they support new languages or new operating systems (e.g., mmap() is essentially an allocator). Abstracting these language/OS specific issues into their own analysis group appears to be a good idea.

Writing this pass has been on my back burner for awhile, so I mention it in case someone else thinks it's a good idea and wants to tackle it or thinks it's a bad idea and wants to tell me why.
:slight_smile:

-- John T.

I like that idea.
Some thoughts:

1) It would also be useful to be able to find deallocations.
In particular, it'd be nice to be able to detect things like matching
'free(malloc(N))' or 'delete (new T)' pairs so we can delete them
after other uses have been optimized out.
Alternatively, if there uses left but we can prove that the memory
will be deleted before exiting the function (or that the pointer
doesn't escape the function[1]), turn the allocation into an alloca
instead.
Note that for GC allocators, turning an allocation into an alloca may
require some way to insert a destructor call matching an allocation
since it won't be explicitly present in the IR already.
1a) This might also allow deleting of undefined behavior like
mismatched allocation/deallocation, e.g. delete malloc(), free(new T),
delete new T[10], delete new string, etc. if we can figure out that
they *are* mismatched.

[1]: This is particularly useful for GC allocators, but not unique to
them: IIRC unused mallocs are already deleted by one of the current
passes.

2) How (or whether) to handle things like realloc() which might both
allocate *and* deallocate?
(Or a GC variant of this which allocates & copies if needed but leaves
the old allocation around for the GC)