Implementing sizeof

Hi folks,

Assuming that I'm writing a pass and that for bizarre reasons I need to programmatically do the equivalent of a C/C++ sizeof on a Value (or a Type, it doesn't matter which really), yielding a result in bytes, what is the known-safe way to do this? I notice that doing something like

struct thingy
{
    ... some stuff ...
};

...
    printf("Size = %d", sizeof(thingy));
...

turns into a constant at the bitcode disassembly level, which is fair enough but I can't rely on the source passing down information like that -- I have to be able to work purely at the opt pass level. One of the transformations I need to do is turn load and store instructions into model-checker-specific intrinsics so I can track memory modifications efficiently, but just having the address isn't enough, I really need the size too. Or are reads and writes always guaranteed to be simple types, so the bit width (as given by the Type::getPrimitiveSizeInBits() member function) divided by 8 and rounded up if necessary is enough? (The latter works well for me too, I just don't want to mess myself up by making assumptions).

As usual, thank you in advance.

Sarah

Check out Random LLVM Notes

-Chris

http://nondot.org/sabre
http://llvm.org

Chris Lattner wrote:

Check out Random LLVM Notes

  %Size = getelementptr %T* null, int 1
  %SizeI = cast %T* %Size to uint

How incredibly cunning. :slight_smile: Thanks for that.

Next stupid question. I've put together a simple coroutine/fibre style threading system on top of the Linux setcontext/getcontext stuff, which surprisingly enough seems to work *almost* perfectly under the JITted environment, with the exception that the JITter doesn't like running in anything other than the primary fibre. For example,

#include <stdio.h>
#include "../../mcp/tools/mcp2/mcpapi.h"

void thread1(void *udata)
{
  int i;
  for(i=0; i<10; i++)
  {
    printf("--- thread1: Hello (%d)\n", i);
  }
}

void thread2(void *udata)
{
  int i;
  for(i=0; i<10; i++)
  {
    printf("--- thread2 Hello (%d)\n", i);
  }
}

int main(int argc, char **argv)
{
  printf("--- Running threads serially:\n");
  thread1(0);
  thread2(0);

  printf("--- Running threads in parallel:\n");
  mcp_begin_thread(thread1, 0);
  mcp_begin_thread(thread2, 0);

  printf("--- Waiting for child threads to terminate\n");
  mcp_wait_for_exit();

  printf("--- Bye...\n");
  return 0;
}

works perfectly, because thread1() and thread2() are forced into existence before they are referenced by mcp_begin_thread() (i.e. as a parameter to makecontext). Commenting out the running threads serially section results in a seg fault inside the jitter. Since we have to make so many performance compromises in the name of model checking anyway, it's no big deal for me to just basically force every function in the module to be compiled before execution starts, which should effectively mean that the JITter can never execute at run time (and therefore can never accidentally be run inside a child thread). What is the best/safest way to do this? Is it OK just to enumerate all the functions within the module and resolve them to non-lazy function pointers? I think in V1.8 just taking the address of a function was enough to cause it to be jitted, so something has obviously changed a bit since then.

Thanks,
Sarah

(I have verified that just going through all the Functions in the Module and calling getPointerToFunction for each in turn actually seems to work -- I just wanted to make sure that this is sensible)

Sarah

Sarah,

Indeed, loads and stores must be of first class type: iN, float, double, pointers, or vectors.

http://llvm.org/docs/LangRef.html#i_load
http://llvm.org/docs/LangRef.html#t_primitive

— Gordon

Yep, that is both sensible and is the recommended approach. However, the JIT should lock itself (using pthreads calls) to prevent itself from dying in a multithreaded situation. If you're using pthreads then you found a bug.

One feature you might be interested in is the EE->DisableLazyCompilation() method. This will cause the jit to abort if you ever ask it to do lazy compilation. This is a useful 'assertion' mode if you think your code should compile everything ahead of time and want to know if you ever forgot something. :slight_smile:

-Chris