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