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

Generated by: LCOV version 1.14