LCOV - code coverage report
Current view: top level - src/include/jit - llvmjit_emit.h (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 97.3 % 73 71
Test Date: 2026-03-05 02:14:55 Functions: 95.8 % 24 23
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-2026, 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        55231 : l_ptr_const(void *ptr, LLVMTypeRef type)
      29              : {
      30        55231 :     LLVMValueRef c = LLVMConstInt(TypeSizeT, (uintptr_t) ptr, false);
      31              : 
      32        55231 :     return LLVMConstIntToPtr(c, type);
      33              : }
      34              : 
      35              : /*
      36              :  * Emit pointer.
      37              :  */
      38              : static inline LLVMTypeRef
      39        67281 : l_ptr(LLVMTypeRef t)
      40              : {
      41        67281 :     return LLVMPointerType(t, 0);
      42              : }
      43              : 
      44              : /*
      45              :  * Emit constant integer.
      46              :  */
      47              : static inline LLVMValueRef
      48        20684 : l_int8_const(LLVMContextRef lc, int8 i)
      49              : {
      50        20684 :     return LLVMConstInt(LLVMInt8TypeInContext(lc), i, false);
      51              : }
      52              : 
      53              : /*
      54              :  * Emit constant integer.
      55              :  */
      56              : static inline LLVMValueRef
      57        27054 : l_int16_const(LLVMContextRef lc, int16 i)
      58              : {
      59        27054 :     return LLVMConstInt(LLVMInt16TypeInContext(lc), i, false);
      60              : }
      61              : 
      62              : /*
      63              :  * Emit constant integer.
      64              :  */
      65              : static inline LLVMValueRef
      66        19615 : l_int32_const(LLVMContextRef lc, int32 i)
      67              : {
      68        19615 :     return LLVMConstInt(LLVMInt32TypeInContext(lc), i, false);
      69              : }
      70              : 
      71              : /*
      72              :  * Emit constant integer.
      73              :  */
      74              : static inline LLVMValueRef
      75         5062 : l_int64_const(LLVMContextRef lc, int64 i)
      76              : {
      77         5062 :     return LLVMConstInt(LLVMInt64TypeInContext(lc), i, false);
      78              : }
      79              : 
      80              : /*
      81              :  * Emit constant integer.
      82              :  */
      83              : static inline LLVMValueRef
      84        14231 : l_sizet_const(size_t i)
      85              : {
      86        14231 :     return LLVMConstInt(TypeSizeT, i, false);
      87              : }
      88              : 
      89              : /*
      90              :  * Emit constant integer.
      91              :  */
      92              : static inline LLVMValueRef
      93        11689 : l_datum_const(Datum i)
      94              : {
      95        11689 :     return LLVMConstInt(TypeDatum, i, false);
      96              : }
      97              : 
      98              : /*
      99              :  * Emit constant boolean, as used for storage (e.g. global vars, structs).
     100              :  */
     101              : static inline LLVMValueRef
     102        13290 : l_sbool_const(bool i)
     103              : {
     104        13290 :     return LLVMConstInt(TypeStorageBool, (int) i, false);
     105              : }
     106              : 
     107              : /*
     108              :  * Emit constant boolean, as used for parameters (e.g. function parameters).
     109              :  */
     110              : static inline LLVMValueRef
     111              : l_pbool_const(bool i)
     112              : {
     113              :     return LLVMConstInt(TypeParamBool, (int) i, false);
     114              : }
     115              : 
     116              : static inline LLVMValueRef
     117       131068 : l_struct_gep(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, int32 idx, const char *name)
     118              : {
     119       131068 :     return LLVMBuildStructGEP2(b, t, v, idx, "");
     120              : }
     121              : 
     122              : static inline LLVMValueRef
     123        56381 : l_gep(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, LLVMValueRef *indices, int32 nindices, const char *name)
     124              : {
     125        56381 :     return LLVMBuildGEP2(b, t, v, indices, nindices, name);
     126              : }
     127              : 
     128              : static inline LLVMValueRef
     129       159276 : l_load(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, const char *name)
     130              : {
     131       159276 :     return LLVMBuildLoad2(b, t, v, name);
     132              : }
     133              : 
     134              : static inline LLVMValueRef
     135        15570 : l_call(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef fn, LLVMValueRef *args, int32 nargs, const char *name)
     136              : {
     137        15570 :     return LLVMBuildCall2(b, t, fn, args, nargs, name);
     138              : }
     139              : 
     140              : /*
     141              :  * Load a pointer member idx from a struct.
     142              :  */
     143              : static inline LLVMValueRef
     144        95613 : l_load_struct_gep(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, int32 idx, const char *name)
     145              : {
     146        95613 :     return l_load(b,
     147              :                   LLVMStructGetTypeAtIndex(t, idx),
     148              :                   l_struct_gep(b, t, v, idx, ""),
     149              :                   name);
     150              : }
     151              : 
     152              : /*
     153              :  * Load value of a pointer, after applying one index operation.
     154              :  */
     155              : static inline LLVMValueRef
     156        18665 : l_load_gep1(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, LLVMValueRef idx, const char *name)
     157              : {
     158        18665 :     return l_load(b, t, l_gep(b, t, v, &idx, 1, ""), name);
     159              : }
     160              : 
     161              : /* separate, because pg_attribute_printf(2, 3) can't appear in definition */
     162              : static inline LLVMBasicBlockRef l_bb_before_v(LLVMBasicBlockRef r, const char *fmt,...) pg_attribute_printf(2, 3);
     163              : 
     164              : /*
     165              :  * Insert a new basic block, just before r, the name being determined by fmt
     166              :  * and arguments.
     167              :  */
     168              : static inline LLVMBasicBlockRef
     169        11981 : l_bb_before_v(LLVMBasicBlockRef r, const char *fmt,...)
     170              : {
     171              :     char        buf[512];
     172              :     va_list     args;
     173              :     LLVMContextRef lc;
     174              : 
     175        11981 :     va_start(args, fmt);
     176        11981 :     vsnprintf(buf, sizeof(buf), fmt, args);
     177        11981 :     va_end(args);
     178              : 
     179        11981 :     lc = LLVMGetTypeContext(LLVMTypeOf(LLVMGetBasicBlockParent(r)));
     180              : 
     181        11981 :     return LLVMInsertBasicBlockInContext(lc, r, buf);
     182              : }
     183              : 
     184              : /* separate, because pg_attribute_printf(2, 3) can't appear in definition */
     185              : static inline LLVMBasicBlockRef l_bb_append_v(LLVMValueRef f, const char *fmt,...) pg_attribute_printf(2, 3);
     186              : 
     187              : /*
     188              :  * Insert a new basic block after previous basic blocks, the name being
     189              :  * determined by fmt and arguments.
     190              :  */
     191              : static inline LLVMBasicBlockRef
     192        54596 : l_bb_append_v(LLVMValueRef f, const char *fmt,...)
     193              : {
     194              :     char        buf[512];
     195              :     va_list     args;
     196              :     LLVMContextRef lc;
     197              : 
     198        54596 :     va_start(args, fmt);
     199        54596 :     vsnprintf(buf, sizeof(buf), fmt, args);
     200        54596 :     va_end(args);
     201              : 
     202        54596 :     lc = LLVMGetTypeContext(LLVMTypeOf(f));
     203              : 
     204        54596 :     return LLVMAppendBasicBlockInContext(lc, f, buf);
     205              : }
     206              : 
     207              : /*
     208              :  * Mark a callsite as readonly.
     209              :  */
     210              : static inline void
     211          587 : l_callsite_ro(LLVMValueRef f)
     212              : {
     213          587 :     const char  argname[] = "readonly";
     214              :     LLVMAttributeRef ref;
     215              : 
     216          587 :     ref = LLVMCreateStringAttribute(LLVMGetTypeContext(LLVMTypeOf(f)),
     217              :                                     argname,
     218              :                                     sizeof(argname) - 1,
     219              :                                     NULL, 0);
     220              : 
     221          587 :     LLVMAddCallSiteAttribute(f, LLVMAttributeFunctionIndex, ref);
     222          587 : }
     223              : 
     224              : /*
     225              :  * Mark a callsite as alwaysinline.
     226              :  */
     227              : static inline void
     228          587 : l_callsite_alwaysinline(LLVMValueRef f)
     229              : {
     230          587 :     const char  argname[] = "alwaysinline";
     231              :     int         id;
     232              :     LLVMAttributeRef attr;
     233              : 
     234          587 :     id = LLVMGetEnumAttributeKindForName(argname,
     235              :                                          sizeof(argname) - 1);
     236          587 :     attr = LLVMCreateEnumAttribute(LLVMGetTypeContext(LLVMTypeOf(f)), id, 0);
     237          587 :     LLVMAddCallSiteAttribute(f, LLVMAttributeFunctionIndex, attr);
     238          587 : }
     239              : 
     240              : /*
     241              :  * Emit code to switch memory context.
     242              :  */
     243              : static inline LLVMValueRef
     244         1279 : l_mcxt_switch(LLVMModuleRef mod, LLVMBuilderRef b, LLVMValueRef nc)
     245              : {
     246         1279 :     const char *cmc = "CurrentMemoryContext";
     247              :     LLVMValueRef cur;
     248              :     LLVMValueRef ret;
     249              : 
     250         1279 :     if (!(cur = LLVMGetNamedGlobal(mod, cmc)))
     251          119 :         cur = LLVMAddGlobal(mod, l_ptr(StructMemoryContextData), cmc);
     252         1279 :     ret = l_load(b, l_ptr(StructMemoryContextData), cur, cmc);
     253         1279 :     LLVMBuildStore(b, nc, cur);
     254              : 
     255         1279 :     return ret;
     256              : }
     257              : 
     258              : /*
     259              :  * Return pointer to the argno'th argument nullness.
     260              :  */
     261              : static inline LLVMValueRef
     262         3942 : l_funcnullp(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
     263              : {
     264              :     LLVMValueRef v_args;
     265              :     LLVMValueRef v_argn;
     266              : 
     267         3942 :     v_args = l_struct_gep(b,
     268              :                           StructFunctionCallInfoData,
     269              :                           v_fcinfo,
     270              :                           FIELDNO_FUNCTIONCALLINFODATA_ARGS,
     271              :                           "");
     272         3942 :     v_argn = l_struct_gep(b,
     273              :                           LLVMArrayType(StructNullableDatum, 0),
     274              :                           v_args,
     275              :                           argno,
     276              :                           "");
     277         3942 :     return l_struct_gep(b,
     278              :                         StructNullableDatum,
     279              :                         v_argn,
     280              :                         FIELDNO_NULLABLE_DATUM_ISNULL,
     281              :                         "");
     282              : }
     283              : 
     284              : /*
     285              :  * Return pointer to the argno'th argument datum.
     286              :  */
     287              : static inline LLVMValueRef
     288          689 : l_funcvaluep(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
     289              : {
     290              :     LLVMValueRef v_args;
     291              :     LLVMValueRef v_argn;
     292              : 
     293          689 :     v_args = l_struct_gep(b,
     294              :                           StructFunctionCallInfoData,
     295              :                           v_fcinfo,
     296              :                           FIELDNO_FUNCTIONCALLINFODATA_ARGS,
     297              :                           "");
     298          689 :     v_argn = l_struct_gep(b,
     299              :                           LLVMArrayType(StructNullableDatum, 0),
     300              :                           v_args,
     301              :                           argno,
     302              :                           "");
     303          689 :     return l_struct_gep(b,
     304              :                         StructNullableDatum,
     305              :                         v_argn,
     306              :                         FIELDNO_NULLABLE_DATUM_DATUM,
     307              :                         "");
     308              : }
     309              : 
     310              : /*
     311              :  * Return argno'th argument nullness.
     312              :  */
     313              : static inline LLVMValueRef
     314         3253 : l_funcnull(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
     315              : {
     316         3253 :     return l_load(b, TypeStorageBool, l_funcnullp(b, v_fcinfo, argno), "");
     317              : }
     318              : 
     319              : /*
     320              :  * Return argno'th argument datum.
     321              :  */
     322              : static inline LLVMValueRef
     323            0 : l_funcvalue(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
     324              : {
     325            0 :     return l_load(b, TypeDatum, l_funcvaluep(b, v_fcinfo, argno), "");
     326              : }
     327              : 
     328              : #endif                          /* USE_LLVM */
     329              : #endif
        

Generated by: LCOV version 2.0-1