LDC inline IR

From D Wiki
Revision as of 23:38, 7 April 2017 by Klickverbot (talk | contribs) (Downgrade warning)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

LDC has an interface to the LLVM assembly language (IR). This can be useful if you want to exploit special LLVM features like vector instructions or address space operations. Please be aware that LLVM IR is platform dependent. It is not a platform independent assembler! This pragma is intrinsically very brittle in nature, and should only be used if other facilities (e.g. the ldc.simd module) are not sufficient.

Interface

To use the inline IR feature you have to declare the following magic template:

pragma(LDC_inline_ir)
    R inlineIR(string s, R, P...)(P);

The symbol declared with pragma LDC_inline_ir must be a function template with three template parameters. The first template parameter must be string in LLVM assembly language. The second template parameter must be the return type, and the third template parmeter must be a tuple of function parameter types. When the function template is instantiated, an LLVM function is created. The string passed as the first template parameter is used as the function's body. If the return type is void, "void" is appended to it. The function's return type is determined from the second template parameter and the parameter list is generated from the third template parameter. This function will be inlined if possible. If all the calls to the function are inlined, the function will not appear in the object file.

Inside the IR you refer to the parameters with the special names %0, %1 and so on.

Examples

Adding 2 integers

A simple usage is here:

int add(int a, int b)
{
    return inlineIR!(`
        %r = add i32 %0, %1
        ret i32 %r`, int)(a, b);
}

Using another address space

On Windows 64bit, the bottom of stack is stored at gs:8. Instead of using inline assembler you can use this IR:

void* getStackBottom(){
return inlineIR!(`
           %ptr = inttoptr i64 %0 to i64 addrspace(256)*
           %val = load i64 addrspace(256)* %ptr, align 1
           %tmp = inttoptr i64 %val to i8*
           ret i8* %tmp`,
         void*, ulong)(8);
}

LLVM uses different address spaces to model the segment registers on x86/x86_64. The address space 256 is the gs segment register and address space 257 is the fs segment register.

Using vector instructions

The file ldc.simd contains the source for the LLVM vector instructions.