lp_bld_intr.c revision efc82aef35a2aac5d2ed9774f6d28f2626796416
1/************************************************************************** 2 * 3 * Copyright 2009 VMware, Inc. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 29/** 30 * @file 31 * Helpers for emiting intrinsic calls. 32 * 33 * LLVM vanilla IR doesn't represent all basic arithmetic operations we care 34 * about, and it is often necessary to resort target-specific intrinsics for 35 * performance, convenience. 36 * 37 * Ideally we would like to stay away from target specific intrinsics and 38 * move all the instruction selection logic into upstream LLVM where it belongs. 39 * 40 * These functions are also used for calling C functions provided by us from 41 * generated LLVM code. 42 * 43 * @author Jose Fonseca <jfonseca@vmware.com> 44 */ 45 46 47#include "util/u_debug.h" 48 49#include "lp_bld_const.h" 50#include "lp_bld_intr.h" 51 52 53LLVMValueRef 54lp_declare_intrinsic(LLVMModuleRef module, 55 const char *name, 56 LLVMTypeRef ret_type, 57 LLVMTypeRef *arg_types, 58 unsigned num_args) 59{ 60 LLVMTypeRef function_type; 61 LLVMValueRef function; 62 63 assert(!LLVMGetNamedFunction(module, name)); 64 65 function_type = LLVMFunctionType(ret_type, arg_types, num_args, 0); 66 function = LLVMAddFunction(module, name, function_type); 67 68 LLVMSetFunctionCallConv(function, LLVMCCallConv); 69 LLVMSetLinkage(function, LLVMExternalLinkage); 70 71 assert(LLVMIsDeclaration(function)); 72 73 if(name[0] == 'l' && 74 name[1] == 'l' && 75 name[2] == 'v' && 76 name[3] == 'm' && 77 name[4] == '.') 78 assert(LLVMGetIntrinsicID(function)); 79 80 return function; 81} 82 83 84LLVMValueRef 85lp_build_intrinsic(LLVMBuilderRef builder, 86 const char *name, 87 LLVMTypeRef ret_type, 88 LLVMValueRef *args, 89 unsigned num_args) 90{ 91 LLVMModuleRef module = LLVMGetGlobalParent(LLVMGetBasicBlockParent(LLVMGetInsertBlock(builder))); 92 LLVMValueRef function; 93 94 function = LLVMGetNamedFunction(module, name); 95 if(!function) { 96 LLVMTypeRef arg_types[LP_MAX_FUNC_ARGS]; 97 unsigned i; 98 99 assert(num_args <= LP_MAX_FUNC_ARGS); 100 101 for(i = 0; i < num_args; ++i) { 102 assert(args[i]); 103 arg_types[i] = LLVMTypeOf(args[i]); 104 } 105 106 function = lp_declare_intrinsic(module, name, ret_type, arg_types, num_args); 107 } 108 109 return LLVMBuildCall(builder, function, args, num_args, ""); 110} 111 112 113LLVMValueRef 114lp_build_intrinsic_unary(LLVMBuilderRef builder, 115 const char *name, 116 LLVMTypeRef ret_type, 117 LLVMValueRef a) 118{ 119 return lp_build_intrinsic(builder, name, ret_type, &a, 1); 120} 121 122 123LLVMValueRef 124lp_build_intrinsic_binary(LLVMBuilderRef builder, 125 const char *name, 126 LLVMTypeRef ret_type, 127 LLVMValueRef a, 128 LLVMValueRef b) 129{ 130 LLVMValueRef args[2]; 131 132 args[0] = a; 133 args[1] = b; 134 135 return lp_build_intrinsic(builder, name, ret_type, args, 2); 136} 137 138 139LLVMValueRef 140lp_build_intrinsic_map(struct gallivm_state *gallivm, 141 const char *name, 142 LLVMTypeRef ret_type, 143 LLVMValueRef *args, 144 unsigned num_args) 145{ 146 LLVMBuilderRef builder = gallivm->builder; 147 LLVMTypeRef ret_elem_type = LLVMGetElementType(ret_type); 148 unsigned n = LLVMGetVectorSize(ret_type); 149 unsigned i, j; 150 LLVMValueRef res; 151 152 assert(num_args <= LP_MAX_FUNC_ARGS); 153 154 res = LLVMGetUndef(ret_type); 155 for(i = 0; i < n; ++i) { 156 LLVMValueRef index = lp_build_const_int32(gallivm, i); 157 LLVMValueRef arg_elems[LP_MAX_FUNC_ARGS]; 158 LLVMValueRef res_elem; 159 for(j = 0; j < num_args; ++j) 160 arg_elems[j] = LLVMBuildExtractElement(builder, args[j], index, ""); 161 res_elem = lp_build_intrinsic(builder, name, ret_elem_type, arg_elems, num_args); 162 res = LLVMBuildInsertElement(builder, res, res_elem, index, ""); 163 } 164 165 return res; 166} 167 168 169LLVMValueRef 170lp_build_intrinsic_map_unary(struct gallivm_state *gallivm, 171 const char *name, 172 LLVMTypeRef ret_type, 173 LLVMValueRef a) 174{ 175 return lp_build_intrinsic_map(gallivm, name, ret_type, &a, 1); 176} 177 178 179LLVMValueRef 180lp_build_intrinsic_map_binary(struct gallivm_state *gallivm, 181 const char *name, 182 LLVMTypeRef ret_type, 183 LLVMValueRef a, 184 LLVMValueRef b) 185{ 186 LLVMValueRef args[2]; 187 188 args[0] = a; 189 args[1] = b; 190 191 return lp_build_intrinsic_map(gallivm, name, ret_type, args, 2); 192} 193 194 195