LCOV - code coverage report
Current view: top level - src/include/jit - llvmjit_emit.h (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 69 71 97.2 %
Date: 2024-04-18 17:11:09 Functions: 22 23 95.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * llvmjit_emit.h
       3             :  *    Helpers to make emitting LLVM IR a bit more concise and pgindent proof.
       4             :  *
       5             :  * Copyright (c) 2018-2024, PostgreSQL Global Development Group
       6             :  *
       7             :  * src/include/jit/llvmjit_emit.h
       8             :  */
       9             : #ifndef LLVMJIT_EMIT_H
      10             : #define LLVMJIT_EMIT_H
      11             : 
      12             : /*
      13             :  * To avoid breaking cpluspluscheck, allow including the file even when LLVM
      14             :  * is not available.
      15             :  */
      16             : #ifdef USE_LLVM
      17             : 
      18             : #include <llvm-c/Core.h>
      19             : #include <llvm-c/Target.h>
      20             : 
      21             : #include "jit/llvmjit.h"
      22             : 
      23             : 
      24             : /*
      25             :  * Emit a non-LLVM pointer as an LLVM constant.
      26             :  */
      27             : static inline LLVMValueRef
      28      134738 : l_ptr_const(void *ptr, LLVMTypeRef type)
      29             : {
      30      134738 :     LLVMValueRef c = LLVMConstInt(TypeSizeT, (uintptr_t) ptr, false);
      31             : 
      32      134738 :     return LLVMConstIntToPtr(c, type);
      33             : }
      34             : 
      35             : /*
      36             :  * Emit pointer.
      37             :  */
      38             : static inline LLVMTypeRef
      39      170724 : l_ptr(LLVMTypeRef t)
      40             : {
      41      170724 :     return LLVMPointerType(t, 0);
      42             : }
      43             : 
      44             : /*
      45             :  * Emit constant integer.
      46             :  */
      47             : static inline LLVMValueRef
      48       62338 : l_int8_const(LLVMContextRef lc, int8 i)
      49             : {
      50       62338 :     return LLVMConstInt(LLVMInt8TypeInContext(lc), i, false);
      51             : }
      52             : 
      53             : /*
      54             :  * Emit constant integer.
      55             :  */
      56             : static inline LLVMValueRef
      57       81944 : l_int16_const(LLVMContextRef lc, int16 i)
      58             : {
      59       81944 :     return LLVMConstInt(LLVMInt16TypeInContext(lc), i, false);
      60             : }
      61             : 
      62             : /*
      63             :  * Emit constant integer.
      64             :  */
      65             : static inline LLVMValueRef
      66       52914 : l_int32_const(LLVMContextRef lc, int32 i)
      67             : {
      68       52914 :     return LLVMConstInt(LLVMInt32TypeInContext(lc), i, false);
      69             : }
      70             : 
      71             : /*
      72             :  * Emit constant integer.
      73             :  */
      74             : static inline LLVMValueRef
      75       11144 : l_int64_const(LLVMContextRef lc, int64 i)
      76             : {
      77       11144 :     return LLVMConstInt(LLVMInt64TypeInContext(lc), i, false);
      78             : }
      79             : 
      80             : /*
      81             :  * Emit constant integer.
      82             :  */
      83             : static inline LLVMValueRef
      84       67428 : l_sizet_const(size_t i)
      85             : {
      86       67428 :     return LLVMConstInt(TypeSizeT, i, false);
      87             : }
      88             : 
      89             : /*
      90             :  * Emit constant boolean, as used for storage (e.g. global vars, structs).
      91             :  */
      92             : static inline LLVMValueRef
      93       30238 : l_sbool_const(bool i)
      94             : {
      95       30238 :     return LLVMConstInt(TypeStorageBool, (int) i, false);
      96             : }
      97             : 
      98             : /*
      99             :  * Emit constant boolean, as used for parameters (e.g. function parameters).
     100             :  */
     101             : static inline LLVMValueRef
     102             : l_pbool_const(bool i)
     103             : {
     104             :     return LLVMConstInt(TypeParamBool, (int) i, false);
     105             : }
     106             : 
     107             : static inline LLVMValueRef
     108      319854 : l_struct_gep(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, int32 idx, const char *name)
     109             : {
     110             : #if LLVM_VERSION_MAJOR < 16
     111      319854 :     return LLVMBuildStructGEP(b, v, idx, "");
     112             : #else
     113             :     return LLVMBuildStructGEP2(b, t, v, idx, "");
     114             : #endif
     115             : }
     116             : 
     117             : static inline LLVMValueRef
     118      157298 : l_gep(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, LLVMValueRef *indices, int32 nindices, const char *name)
     119             : {
     120             : #if LLVM_VERSION_MAJOR < 16
     121      157298 :     return LLVMBuildGEP(b, v, indices, nindices, name);
     122             : #else
     123             :     return LLVMBuildGEP2(b, t, v, indices, nindices, name);
     124             : #endif
     125             : }
     126             : 
     127             : static inline LLVMValueRef
     128      411100 : l_load(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, const char *name)
     129             : {
     130             : #if LLVM_VERSION_MAJOR < 16
     131      411100 :     return LLVMBuildLoad(b, v, name);
     132             : #else
     133             :     return LLVMBuildLoad2(b, t, v, name);
     134             : #endif
     135             : }
     136             : 
     137             : static inline LLVMValueRef
     138       38100 : l_call(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef fn, LLVMValueRef *args, int32 nargs, const char *name)
     139             : {
     140             : #if LLVM_VERSION_MAJOR < 16
     141       38100 :     return LLVMBuildCall(b, fn, args, nargs, name);
     142             : #else
     143             :     return LLVMBuildCall2(b, t, fn, args, nargs, name);
     144             : #endif
     145             : }
     146             : 
     147             : /*
     148             :  * Load a pointer member idx from a struct.
     149             :  */
     150             : static inline LLVMValueRef
     151      224358 : l_load_struct_gep(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, int32 idx, const char *name)
     152             : {
     153      224358 :     return l_load(b,
     154             :                   LLVMStructGetTypeAtIndex(t, idx),
     155             :                   l_struct_gep(b, t, v, idx, ""),
     156             :                   name);
     157             : }
     158             : 
     159             : /*
     160             :  * Load value of a pointer, after applying one index operation.
     161             :  */
     162             : static inline LLVMValueRef
     163       49626 : l_load_gep1(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, LLVMValueRef idx, const char *name)
     164             : {
     165       49626 :     return l_load(b, t, l_gep(b, t, v, &idx, 1, ""), name);
     166             : }
     167             : 
     168             : /* separate, because pg_attribute_printf(2, 3) can't appear in definition */
     169             : static inline LLVMBasicBlockRef l_bb_before_v(LLVMBasicBlockRef r, const char *fmt,...) pg_attribute_printf(2, 3);
     170             : 
     171             : /*
     172             :  * Insert a new basic block, just before r, the name being determined by fmt
     173             :  * and arguments.
     174             :  */
     175             : static inline LLVMBasicBlockRef
     176       28934 : l_bb_before_v(LLVMBasicBlockRef r, const char *fmt,...)
     177             : {
     178             :     char        buf[512];
     179             :     va_list     args;
     180             :     LLVMContextRef lc;
     181             : 
     182       28934 :     va_start(args, fmt);
     183       28934 :     vsnprintf(buf, sizeof(buf), fmt, args);
     184       28934 :     va_end(args);
     185             : 
     186       28934 :     lc = LLVMGetTypeContext(LLVMTypeOf(LLVMGetBasicBlockParent(r)));
     187             : 
     188       28934 :     return LLVMInsertBasicBlockInContext(lc, r, buf);
     189             : }
     190             : 
     191             : /* separate, because pg_attribute_printf(2, 3) can't appear in definition */
     192             : static inline LLVMBasicBlockRef l_bb_append_v(LLVMValueRef f, const char *fmt,...) pg_attribute_printf(2, 3);
     193             : 
     194             : /*
     195             :  * Insert a new basic block after previous basic blocks, the name being
     196             :  * determined by fmt and arguments.
     197             :  */
     198             : static inline LLVMBasicBlockRef
     199      152468 : l_bb_append_v(LLVMValueRef f, const char *fmt,...)
     200             : {
     201             :     char        buf[512];
     202             :     va_list     args;
     203             :     LLVMContextRef lc;
     204             : 
     205      152468 :     va_start(args, fmt);
     206      152468 :     vsnprintf(buf, sizeof(buf), fmt, args);
     207      152468 :     va_end(args);
     208             : 
     209      152468 :     lc = LLVMGetTypeContext(LLVMTypeOf(f));
     210             : 
     211      152468 :     return LLVMAppendBasicBlockInContext(lc, f, buf);
     212             : }
     213             : 
     214             : /*
     215             :  * Mark a callsite as readonly.
     216             :  */
     217             : static inline void
     218        1928 : l_callsite_ro(LLVMValueRef f)
     219             : {
     220        1928 :     const char  argname[] = "readonly";
     221             :     LLVMAttributeRef ref;
     222             : 
     223        1928 :     ref = LLVMCreateStringAttribute(LLVMGetTypeContext(LLVMTypeOf(f)),
     224             :                                     argname,
     225             :                                     sizeof(argname) - 1,
     226             :                                     NULL, 0);
     227             : 
     228        1928 :     LLVMAddCallSiteAttribute(f, LLVMAttributeFunctionIndex, ref);
     229        1928 : }
     230             : 
     231             : /*
     232             :  * Mark a callsite as alwaysinline.
     233             :  */
     234             : static inline void
     235        1928 : l_callsite_alwaysinline(LLVMValueRef f)
     236             : {
     237        1928 :     const char  argname[] = "alwaysinline";
     238             :     int         id;
     239             :     LLVMAttributeRef attr;
     240             : 
     241        1928 :     id = LLVMGetEnumAttributeKindForName(argname,
     242             :                                          sizeof(argname) - 1);
     243        1928 :     attr = LLVMCreateEnumAttribute(LLVMGetTypeContext(LLVMTypeOf(f)), id, 0);
     244        1928 :     LLVMAddCallSiteAttribute(f, LLVMAttributeFunctionIndex, attr);
     245        1928 : }
     246             : 
     247             : /*
     248             :  * Emit code to switch memory context.
     249             :  */
     250             : static inline LLVMValueRef
     251        3210 : l_mcxt_switch(LLVMModuleRef mod, LLVMBuilderRef b, LLVMValueRef nc)
     252             : {
     253        3210 :     const char *cmc = "CurrentMemoryContext";
     254             :     LLVMValueRef cur;
     255             :     LLVMValueRef ret;
     256             : 
     257        3210 :     if (!(cur = LLVMGetNamedGlobal(mod, cmc)))
     258         482 :         cur = LLVMAddGlobal(mod, l_ptr(StructMemoryContextData), cmc);
     259        3210 :     ret = l_load(b, l_ptr(StructMemoryContextData), cur, cmc);
     260        3210 :     LLVMBuildStore(b, nc, cur);
     261             : 
     262        3210 :     return ret;
     263             : }
     264             : 
     265             : /*
     266             :  * Return pointer to the argno'th argument nullness.
     267             :  */
     268             : static inline LLVMValueRef
     269        9384 : l_funcnullp(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
     270             : {
     271             :     LLVMValueRef v_args;
     272             :     LLVMValueRef v_argn;
     273             : 
     274        9384 :     v_args = l_struct_gep(b,
     275             :                           StructFunctionCallInfoData,
     276             :                           v_fcinfo,
     277             :                           FIELDNO_FUNCTIONCALLINFODATA_ARGS,
     278             :                           "");
     279        9384 :     v_argn = l_struct_gep(b,
     280             :                           LLVMArrayType(StructNullableDatum, 0),
     281             :                           v_args,
     282             :                           argno,
     283             :                           "");
     284        9384 :     return l_struct_gep(b,
     285             :                         StructNullableDatum,
     286             :                         v_argn,
     287             :                         FIELDNO_NULLABLE_DATUM_ISNULL,
     288             :                         "");
     289             : }
     290             : 
     291             : /*
     292             :  * Return pointer to the argno'th argument datum.
     293             :  */
     294             : static inline LLVMValueRef
     295        1698 : l_funcvaluep(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
     296             : {
     297             :     LLVMValueRef v_args;
     298             :     LLVMValueRef v_argn;
     299             : 
     300        1698 :     v_args = l_struct_gep(b,
     301             :                           StructFunctionCallInfoData,
     302             :                           v_fcinfo,
     303             :                           FIELDNO_FUNCTIONCALLINFODATA_ARGS,
     304             :                           "");
     305        1698 :     v_argn = l_struct_gep(b,
     306             :                           LLVMArrayType(StructNullableDatum, 0),
     307             :                           v_args,
     308             :                           argno,
     309             :                           "");
     310        1698 :     return l_struct_gep(b,
     311             :                         StructNullableDatum,
     312             :                         v_argn,
     313             :                         FIELDNO_NULLABLE_DATUM_DATUM,
     314             :                         "");
     315             : }
     316             : 
     317             : /*
     318             :  * Return argno'th argument nullness.
     319             :  */
     320             : static inline LLVMValueRef
     321        7686 : l_funcnull(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
     322             : {
     323        7686 :     return l_load(b, TypeStorageBool, l_funcnullp(b, v_fcinfo, argno), "");
     324             : }
     325             : 
     326             : /*
     327             :  * Return argno'th argument datum.
     328             :  */
     329             : static inline LLVMValueRef
     330           0 : l_funcvalue(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
     331             : {
     332           0 :     return l_load(b, TypeSizeT, l_funcvaluep(b, v_fcinfo, argno), "");
     333             : }
     334             : 
     335             : #endif                          /* USE_LLVM */
     336             : #endif

Generated by: LCOV version 1.14