[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