[LLVMdev] Adding Intrinsics for custom processor (frotend problem)

Luke Dalessandro luked at cs.rochester.edu
Tue Mar 3 06:16:56 PST 2009


Gil Dogon wrote:
> I have two questions :
> 
> 1. Is that the right way to go, or is there a simpler/more standard way 
> to have frontend support for new architecture intrinsics ?

Gil, it's really easy to add builtins to the llvm-gcc frontend and have 
them auto-magically converted to the llvm intrinsic versions. The main 
problem with this is that you end up with a non-standard front end that 
you have to somehow distribute to the people who need it. There may be 
funny licensing problems, etc... I don't really know.

Here's a quick how-to based on adding an intrinsic which we want to look 
like:

   void* llvm.my.foo(void**, void*)

1) Get the llvm-gcc source from svn.

2) Edit the file gcc/builtins.def

        The comments at the top are helpful, read them.

    a) Add a macro that looks something like

#undef DEF_MY_BUILTIN
#define DEF_MY_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
   DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_MD, TYPE, TYPE,    \
                false, false, true, ATTRS, false, true)

        You can figure out what this means based on the comments in the
        builtins.def file. Essentially the important magic is the
        BUILT_IN_MD flag trickles through and gets your llvm intrinsic
        generated automatically. Also, all of your builtins will be
        prefixed with __builtin_ --- you could change this if you wanted.

    b) Add an include directive at the bottom of the file,
       "#include my-builtins.def"

        This isn't strictly necessary, you could just add your builtins
        directly to the builtins.def file, but it helps keep them
        separate.

3) Edit the gcc/Makefile.in file (not necessary if you skipped b above)

    a) Find the BUILTINS_DEF line and add your "my-builtins.def" file.

4) Create and edit gcc/my-builtins.def

        The file gcc/builtin-types.def lists the macros you can use to
        declare the function types for your macros, and
        gcc/builtin-attrs.def lists the attributes, though I've only ever
        used ATTR_NOTHROW_LIST.

    a) Use the macro you defined earlier to generate your builtins, in
       our example case it is

DEF_MY_BUILTIN (BUILT_IN_MY_FOO, "my_foo", \
    BT_FN_PTR_PTRPTR_PTR, ATTR_NOTHROW_LIST)

        This is straightforward, the first parameter is an ID for your
        builtin within gcc -- it just needs to be unique. The second is
        the "name" of your builtin, which will be prepended with
        "__builtin_" based on our definition of DEF_MY_BUILTIN. The third
        is the function type from gcc/builtin-types.def, (here a function
        taking a pointer to a pointer, and a pointer, and returning a
        pointer). The fourth is the function attributes which I don't
        really know anything about.

    b) In our case here, the correct function type didn't exist, so an
       additional step is to edit gcc/builtin-types.def. I would add the
       following in the section where the 2-parameter types are defined.

DEF_FUNCTION_TYPE_2 (BT_FN_PTR_PTRPTR_PTR, BT_PTR, BT_PTR_PTR, BT_PTR)

       That's all you need to change within llvm-gcc (I think, I didn't
       bug-test the instructions, but I'm pretty sure it will work.

5) Get llvm source from svn

6) Edit include/llvm/Intrinsics.td

       You can either add your intrinsics directly, or just add an
       include to your own file. Here I'm adding them directly.

    a) Add a definition of your intrinsic. In our case, it looks like

def int_my_foo : Intrinsic<[llvm_ptr_ty],
                            [llvm_ptrptr_ty, llvm_ptr_ty]>,
                  GCCBuiltin<"__builtin_my_foo">;

       Clearly the fun here is the GCCBuiltin tag which is what gets
       everything to /just work/.

7) Build llvm.

8) Configure llvm-gcc with your modified llvm binary directory as it's
    llvm directory.

9) Build llvm-gcc.

10) Configure llvm with the llvm-gcc directory.

11) Rebuild llvm.

And voila, users can now use your gcc builtin as
"void* addr = __builtin_my_foo(&bar, bar)" and compilation will 
naturally generate a llvm.my.foo for it.

One caveat is that I've never actually done this with parameters that 
have address types, but ints, voids, and longs work fine. There's a 
routine in llvm-gcc inside of "gcc/llvm-convert.cpp" called 
TreeToLLVM::EmitBuiltinCall that does the actual conversion, you may 
need to do some work in that area. My guess is that it will /just work/ 
though.

Hope this helps. There may be other ways to do this using gcc asm tags 
and such, but I know that this works and gets parameters in the right 
place, etc.

Let me know if there are any bugs in the instructions.

Luke

> 2. If thats the simplest way , I would like to have a quick advice on 
> how to write the rather trivial pass described in '2'.
>    I guess that I need to replace a given Function object with an 
> allmost identical one, but with a different name (the "llvm.something' name
>   of the intrisic)   What is the correct code to do this ?
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev




More information about the llvm-dev mailing list