LCOV - code coverage report
Current view: top level - src/include/jit - llvmjit_emit.h (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 0.0 % 73 0
Test Date: 2026-07-14 19:15:46 Functions: 0.0 % 24 0
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 0.0 % 2 0

             Branch data     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                 :           0 : l_ptr_const(void *ptr, LLVMTypeRef type)
      29                 :             : {
      30                 :           0 :     LLVMValueRef c = LLVMConstInt(TypeSizeT, (uintptr_t) ptr, false);
      31                 :             : 
      32                 :           0 :     return LLVMConstIntToPtr(c, type);
      33                 :             : }
      34                 :             : 
      35                 :             : /*
      36                 :             :  * Emit pointer.
      37                 :             :  */
      38                 :             : static inline LLVMTypeRef
      39                 :           0 : l_ptr(LLVMTypeRef t)
      40                 :             : {
      41                 :           0 :     return LLVMPointerType(t, 0);
      42                 :             : }
      43                 :             : 
      44                 :             : /*
      45                 :             :  * Emit constant integer.
      46                 :             :  */
      47                 :             : static inline LLVMValueRef
      48                 :           0 : l_int8_const(LLVMContextRef lc, int8 i)
      49                 :             : {
      50                 :           0 :     return LLVMConstInt(LLVMInt8TypeInContext(lc), i, false);
      51                 :             : }
      52                 :             : 
      53                 :             : /*
      54                 :             :  * Emit constant integer.
      55                 :             :  */
      56                 :             : static inline LLVMValueRef
      57                 :           0 : l_int16_const(LLVMContextRef lc, int16 i)
      58                 :             : {
      59                 :           0 :     return LLVMConstInt(LLVMInt16TypeInContext(lc), i, false);
      60                 :             : }
      61                 :             : 
      62                 :             : /*
      63                 :             :  * Emit constant integer.
      64                 :             :  */
      65                 :             : static inline LLVMValueRef
      66                 :           0 : l_int32_const(LLVMContextRef lc, int32 i)
      67                 :             : {
      68                 :           0 :     return LLVMConstInt(LLVMInt32TypeInContext(lc), i, false);
      69                 :             : }
      70                 :             : 
      71                 :             : /*
      72                 :             :  * Emit constant integer.
      73                 :             :  */
      74                 :             : static inline LLVMValueRef
      75                 :           0 : l_int64_const(LLVMContextRef lc, int64 i)
      76                 :             : {
      77                 :           0 :     return LLVMConstInt(LLVMInt64TypeInContext(lc), i, false);
      78                 :             : }
      79                 :             : 
      80                 :             : /*
      81                 :             :  * Emit constant integer.
      82                 :             :  */
      83                 :             : static inline LLVMValueRef
      84                 :           0 : l_sizet_const(size_t i)
      85                 :             : {
      86                 :           0 :     return LLVMConstInt(TypeSizeT, i, false);
      87                 :             : }
      88                 :             : 
      89                 :             : /*
      90                 :             :  * Emit constant integer.
      91                 :             :  */
      92                 :             : static inline LLVMValueRef
      93                 :           0 : l_datum_const(Datum i)
      94                 :             : {
      95                 :           0 :     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                 :           0 : l_sbool_const(bool i)
     103                 :             : {
     104                 :           0 :     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                 :           0 : l_struct_gep(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, int32 idx, const char *name)
     118                 :             : {
     119                 :           0 :     return LLVMBuildStructGEP2(b, t, v, idx, "");
     120                 :             : }
     121                 :             : 
     122                 :             : static inline LLVMValueRef
     123                 :           0 : l_gep(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, LLVMValueRef *indices, int32 nindices, const char *name)
     124                 :             : {
     125                 :           0 :     return LLVMBuildGEP2(b, t, v, indices, nindices, name);
     126                 :             : }
     127                 :             : 
     128                 :             : static inline LLVMValueRef
     129                 :           0 : l_load(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, const char *name)
     130                 :             : {
     131                 :           0 :     return LLVMBuildLoad2(b, t, v, name);
     132                 :             : }
     133                 :             : 
     134                 :             : static inline LLVMValueRef
     135                 :           0 : l_call(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef fn, LLVMValueRef *args, int32 nargs, const char *name)
     136                 :             : {
     137                 :           0 :     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                 :           0 : l_load_struct_gep(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, int32 idx, const char *name)
     145                 :             : {
     146                 :           0 :     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                 :           0 : l_load_gep1(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, LLVMValueRef idx, const char *name)
     157                 :             : {
     158                 :           0 :     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                 :           0 : l_bb_before_v(LLVMBasicBlockRef r, const char *fmt, ...)
     170                 :             : {
     171                 :             :     char        buf[512];
     172                 :             :     va_list     args;
     173                 :             :     LLVMContextRef lc;
     174                 :             : 
     175                 :           0 :     va_start(args, fmt);
     176                 :           0 :     vsnprintf(buf, sizeof(buf), fmt, args);
     177                 :           0 :     va_end(args);
     178                 :             : 
     179                 :           0 :     lc = LLVMGetTypeContext(LLVMTypeOf(LLVMGetBasicBlockParent(r)));
     180                 :             : 
     181                 :           0 :     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                 :           0 : l_bb_append_v(LLVMValueRef f, const char *fmt, ...)
     193                 :             : {
     194                 :             :     char        buf[512];
     195                 :             :     va_list     args;
     196                 :             :     LLVMContextRef lc;
     197                 :             : 
     198                 :           0 :     va_start(args, fmt);
     199                 :           0 :     vsnprintf(buf, sizeof(buf), fmt, args);
     200                 :           0 :     va_end(args);
     201                 :             : 
     202                 :           0 :     lc = LLVMGetTypeContext(LLVMTypeOf(f));
     203                 :             : 
     204                 :           0 :     return LLVMAppendBasicBlockInContext(lc, f, buf);
     205                 :             : }
     206                 :             : 
     207                 :             : /*
     208                 :             :  * Mark a callsite as readonly.
     209                 :             :  */
     210                 :             : static inline void
     211                 :           0 : l_callsite_ro(LLVMValueRef f)
     212                 :             : {
     213                 :           0 :     const char  argname[] = "readonly";
     214                 :             :     LLVMAttributeRef ref;
     215                 :             : 
     216                 :           0 :     ref = LLVMCreateStringAttribute(LLVMGetTypeContext(LLVMTypeOf(f)),
     217                 :             :                                     argname,
     218                 :             :                                     sizeof(argname) - 1,
     219                 :             :                                     NULL, 0);
     220                 :             : 
     221                 :           0 :     LLVMAddCallSiteAttribute(f, LLVMAttributeFunctionIndex, ref);
     222                 :           0 : }
     223                 :             : 
     224                 :             : /*
     225                 :             :  * Mark a callsite as alwaysinline.
     226                 :             :  */
     227                 :             : static inline void
     228                 :           0 : l_callsite_alwaysinline(LLVMValueRef f)
     229                 :             : {
     230                 :           0 :     const char  argname[] = "alwaysinline";
     231                 :             :     int         id;
     232                 :             :     LLVMAttributeRef attr;
     233                 :             : 
     234                 :           0 :     id = LLVMGetEnumAttributeKindForName(argname,
     235                 :             :                                          sizeof(argname) - 1);
     236                 :           0 :     attr = LLVMCreateEnumAttribute(LLVMGetTypeContext(LLVMTypeOf(f)), id, 0);
     237                 :           0 :     LLVMAddCallSiteAttribute(f, LLVMAttributeFunctionIndex, attr);
     238                 :           0 : }
     239                 :             : 
     240                 :             : /*
     241                 :             :  * Emit code to switch memory context.
     242                 :             :  */
     243                 :             : static inline LLVMValueRef
     244                 :           0 : l_mcxt_switch(LLVMModuleRef mod, LLVMBuilderRef b, LLVMValueRef nc)
     245                 :             : {
     246                 :           0 :     const char *cmc = "CurrentMemoryContext";
     247                 :             :     LLVMValueRef cur;
     248                 :             :     LLVMValueRef ret;
     249                 :             : 
     250         [ #  # ]:           0 :     if (!(cur = LLVMGetNamedGlobal(mod, cmc)))
     251                 :           0 :         cur = LLVMAddGlobal(mod, l_ptr(StructMemoryContextData), cmc);
     252                 :           0 :     ret = l_load(b, l_ptr(StructMemoryContextData), cur, cmc);
     253                 :           0 :     LLVMBuildStore(b, nc, cur);
     254                 :             : 
     255                 :           0 :     return ret;
     256                 :             : }
     257                 :             : 
     258                 :             : /*
     259                 :             :  * Return pointer to the argno'th argument nullness.
     260                 :             :  */
     261                 :             : static inline LLVMValueRef
     262                 :           0 : l_funcnullp(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
     263                 :             : {
     264                 :             :     LLVMValueRef v_args;
     265                 :             :     LLVMValueRef v_argn;
     266                 :             : 
     267                 :           0 :     v_args = l_struct_gep(b,
     268                 :             :                           StructFunctionCallInfoData,
     269                 :             :                           v_fcinfo,
     270                 :             :                           FIELDNO_FUNCTIONCALLINFODATA_ARGS,
     271                 :             :                           "");
     272                 :           0 :     v_argn = l_struct_gep(b,
     273                 :             :                           LLVMArrayType(StructNullableDatum, 0),
     274                 :             :                           v_args,
     275                 :             :                           argno,
     276                 :             :                           "");
     277                 :           0 :     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                 :           0 : l_funcvaluep(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
     289                 :             : {
     290                 :             :     LLVMValueRef v_args;
     291                 :             :     LLVMValueRef v_argn;
     292                 :             : 
     293                 :           0 :     v_args = l_struct_gep(b,
     294                 :             :                           StructFunctionCallInfoData,
     295                 :             :                           v_fcinfo,
     296                 :             :                           FIELDNO_FUNCTIONCALLINFODATA_ARGS,
     297                 :             :                           "");
     298                 :           0 :     v_argn = l_struct_gep(b,
     299                 :             :                           LLVMArrayType(StructNullableDatum, 0),
     300                 :             :                           v_args,
     301                 :             :                           argno,
     302                 :             :                           "");
     303                 :           0 :     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                 :           0 : l_funcnull(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
     315                 :             : {
     316                 :           0 :     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