Mapping stack to IR on x86 backend


I’m currently working on a project in which I start from a semantic description of an assembly basic block, and I want to output a semantically similar basic block through LLVM.

For instance:

  • Semantic:
    EAX = EBX + 2
    ECX = EBX

  • Expected output:

lea eax, [ebx + 2]

mov ebx, ecx

For now, I have a working PoC using inline asm (for loading a register and saving to it). I also load and save registers to avoid having them erased with temporary values.

But I get an unexpected behavior using the ESP register. It seems that the backend “ignores” the relation between ESP value and the stack.

For instance:

  • Semantic:

@32[ESP - 4] = EAX (that is to say, write at (ESP - 4) a 32 bits value, EAX)

  • Output:

0: 55 push %ebp
1: 53 push %ebx
2: 57 push %edi
3: 56 push %esi
4: 89 44 24 fc mov %eax,-0x4(%esp)
8: 5e pop %esi
9: 5f pop %edi
b: 5d pop %ebp

Which is obviously wrong.

The corresponding IR LLVM:

define void @“fc”()
%".2" = call i32 asm “”, “={eax}”
%".3" = call i32 asm “”, “={ecx}”

%".6" = call i32 asm “”, “={esp}”

%".18" = add i32 %".6", 4294967292
%".19" = inttoptr i32 %".18" to i32*
store i32 %".2", i32* %".19"
call void asm sideeffect “”, “{eax}”
(i32 %".2")

call void asm sideeffect “”, “{esp}”
(i32 %".6")

ret void

I understand that LLVM is not intended to work with this kind of ASM mix, but maybe I’m missing a feature or something.

A hack would be to use an alloca at the beginning of the first basic block, assuming that it will be mapped relatively to ESP, and then re-arranging my memory accesses based on it. But it seems to be a very hacky way to do it…

If you have any idea, I will be happy to test it and provide you feedback.

Thanks in advance,

– commial