1 // Copyright Contributors to the Open Shading Language project.
2 // SPDX-License-Identifier: BSD-3-Clause
3 // https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
4 
5 #pragma once
6 
7 #include <vector>
8 #include <map>
9 
10 #include "oslexec_pvt.h"
11 using namespace OSL;
12 using namespace OSL::pvt;
13 
14 #include "runtimeoptimize.h"
15 #include <OSL/llvm_util.h>
16 
17 // additional includes for creating global OptiX variables
18 #include "llvm/IR/Constants.h"
19 #include "llvm/IR/GlobalVariable.h"
20 #include "llvm/IR/Module.h"
21 
22 
23 OSL_NAMESPACE_ENTER
24 
25 namespace pvt {   // OSL::pvt
26 
27 
28 
29 /// OSOProcessor that generates LLVM IR and JITs it to give machine
30 /// code to implement a shader group.
31 class BackendLLVM final : public OSOProcessorBase {
32 public:
33     BackendLLVM (ShadingSystemImpl &shadingsys, ShaderGroup &group,
34                 ShadingContext *context);
35 
36     virtual ~BackendLLVM ();
37 
38     virtual void set_inst (int layer);
39 
40     /// Create an llvm function for the whole shader group, JIT it,
41     /// and store the llvm::Function* handle to it with the ShaderGroup.
42     virtual void run ();
43 
44 
45     /// What LLVM debug level are we at?
46     int llvm_debug() const;
47 
48     /// Set up a bunch of static things we'll need for the whole group.
49     ///
50     void initialize_llvm_group ();
51 
layer_remap(int origlayer)52     int layer_remap (int origlayer) const { return m_layer_remap[origlayer]; }
53 
54     /// Create an llvm function for the current shader instance.
55     /// This will end up being the group entry if 'groupentry' is true.
56     llvm::Function* build_llvm_instance (bool groupentry);
57 
58     /// Create an llvm function for group initialization code.
59     llvm::Function* build_llvm_init ();
60 
61     /// Build up LLVM IR code for the given range [begin,end) or
62     /// opcodes, putting them (initially) into basic block bb (or the
63     /// current basic block if bb==NULL).
64     bool build_llvm_code (int beginop, int endop, llvm::BasicBlock *bb=NULL);
65 
66     typedef std::map<std::string, llvm::Value*> AllocationMap;
67 
68     void llvm_assign_initial_value (const Symbol& sym, bool force = false);
llvm_context()69     llvm::LLVMContext &llvm_context () const { return ll.context(); }
named_values()70     AllocationMap &named_values () { return m_named_values; }
71 
72     /// Return an llvm::Value* corresponding to the address of the given
73     /// symbol element, with derivative (0=value, 1=dx, 2=dy) and array
74     /// index (NULL if it's not an array).
75     llvm::Value *llvm_get_pointer (const Symbol& sym, int deriv=0,
76                                    llvm::Value *arrayindex=NULL);
77 
78     /// Return the llvm::Value* corresponding to the given element
79     /// value, with derivative (0=value, 1=dx, 2=dy), array index (NULL
80     /// if it's not an array), and component (x=0 or scalar, y=1, z=2).
81     /// If deriv >0 and the symbol doesn't have derivatives, return 0
82     /// for the derivative.  If the component >0 and it's a scalar,
83     /// return the scalar -- this allows automatic casting to triples.
84     /// Finally, auto-cast int<->float if requested (no conversion is
85     /// performed if cast is the default of UNKNOWN).
86     llvm::Value *llvm_load_value (const Symbol& sym, int deriv,
87                                   llvm::Value *arrayindex, int component,
88                                   TypeDesc cast=TypeDesc::UNKNOWN);
89 
90 
91     /// Given an llvm::Value* of a pointer (and the type of the data
92     /// that it points to), Return the llvm::Value* corresponding to the
93     /// given element value, with derivative (0=value, 1=dx, 2=dy),
94     /// array index (NULL if it's not an array), and component (x=0 or
95     /// scalar, y=1, z=2).  If deriv >0 and the symbol doesn't have
96     /// derivatives, return 0 for the derivative.  If the component >0
97     /// and it's a scalar, return the scalar -- this allows automatic
98     /// casting to triples.  Finally, auto-cast int<->float if requested
99     /// (no conversion is performed if cast is the default of UNKNOWN).
100     llvm::Value *llvm_load_value (llvm::Value *ptr, const TypeSpec &type,
101                               int deriv, llvm::Value *arrayindex,
102                               int component, TypeDesc cast=TypeDesc::UNKNOWN);
103 
104     /// Just like llvm_load_value, but when both the symbol and the
105     /// array index are known to be constants.  This can even handle
106     /// pulling constant-indexed elements out of constant arrays.  Use
107     /// arrayindex==-1 to indicate that it's not an array dereference.
108     llvm::Value *llvm_load_constant_value (const Symbol& sym,
109                                            int arrayindex, int component,
110                                            TypeDesc cast=TypeDesc::UNKNOWN);
111 
112     /// llvm_load_value with non-constant component designation.  Does
113     /// not work with arrays or do type casts!
114     llvm::Value *llvm_load_component_value (const Symbol& sym, int deriv,
115                                             llvm::Value *component);
116 
117     /// Non-array version of llvm_load_value, with default deriv &
118     /// component.
119     llvm::Value *llvm_load_value (const Symbol& sym, int deriv = 0,
120                                   int component = 0,
121                                   TypeDesc cast=TypeDesc::UNKNOWN) {
122         return (use_optix() && ! sym.typespec().is_closure() && sym.typespec().is_string())
123             ? llvm_load_device_string (sym, /*follow*/ true)
124             : llvm_load_value (sym, deriv, NULL, component, cast);
125     }
126 
127     /// Load the address of a global device-side string pointer, which may
128     /// reside in a global variable, the groupdata struct, or a local value.
129     llvm::Value *llvm_load_device_string (const Symbol& sym, bool follow);
130 
131     /// Convenience function to load a string for CPU or GPU device
llvm_load_string(const Symbol & sym)132     llvm::Value *llvm_load_string (const Symbol& sym) {
133         OSL_DASSERT(sym.typespec().is_string());
134         return use_optix()
135             ? llvm_load_device_string(sym, /*follow*/ true)
136             : llvm_load_value(sym);
137     }
138 
139     /// Legacy version
140     ///
141     llvm::Value *loadLLVMValue (const Symbol& sym, int component=0,
142                                 int deriv=0, TypeDesc cast=TypeDesc::UNKNOWN) {
143         return llvm_load_value (sym, deriv, NULL, component, cast);
144     }
145 
146     /// Return an llvm::Value* that is either a scalar and derivs is
147     /// false, or a pointer to sym's values (if sym is an aggregate or
148     /// derivs == true).  Furthermore, if deriv == true and sym doesn't
149     /// have derivs, coerce it into a variable with zero derivs.
150     llvm::Value *llvm_load_arg (const Symbol& sym, bool derivs);
151 
152     /// Just like llvm_load_arg(sym,deriv), except use use sym's derivs
153     /// as-is, no coercion.
llvm_load_arg(const Symbol & sym)154     llvm::Value *llvm_load_arg (const Symbol& sym) {
155         return llvm_load_arg (sym, sym.has_derivs());
156     }
157 
158     /// Store new_val into the given symbol, given the derivative
159     /// (0=value, 1=dx, 2=dy), array index (NULL if it's not an array),
160     /// and component (x=0 or scalar, y=1, z=2).  If deriv>0 and the
161     /// symbol doesn't have a deriv, it's a nop.  If the component >0
162     /// and it's a scalar, set the scalar.  Returns true if ok, false
163     /// upon failure.
164     bool llvm_store_value (llvm::Value *new_val, const Symbol& sym, int deriv,
165                            llvm::Value *arrayindex, int component);
166 
167     /// Store new_val into the memory pointed to by dst_ptr, given the
168     /// derivative (0=value, 1=dx, 2=dy), array index (NULL if it's not
169     /// an array), and component (x=0 or scalar, y=1, z=2).  If deriv>0
170     /// and the symbol doesn't have a deriv, it's a nop.  If the
171     /// component >0 and it's a scalar, set the scalar.  Returns true if
172     /// ok, false upon failure.
173     bool llvm_store_value (llvm::Value* new_val, llvm::Value* dst_ptr,
174                            const TypeSpec &type, int deriv,
175                            llvm::Value* arrayindex, int component);
176 
177     /// Non-array version of llvm_store_value, with default deriv &
178     /// component.
179     bool llvm_store_value (llvm::Value *new_val, const Symbol& sym,
180                            int deriv=0, int component=0) {
181         return llvm_store_value (new_val, sym, deriv, NULL, component);
182     }
183 
184     /// llvm_store_value with non-constant component designation.  Does
185     /// not work with arrays or do type casts!
186     bool llvm_store_component_value (llvm::Value *new_val, const Symbol& sym,
187                                      int deriv, llvm::Value *component);
188 
189     /// Legacy version
190     ///
191     bool storeLLVMValue (llvm::Value* new_val, const Symbol& sym,
192                          int component=0, int deriv=0) {
193         return llvm_store_value (new_val, sym, deriv, component);
194     }
195 
196     /// Generate an alloca instruction to allocate space for the given
197     /// type, with derivs if derivs==true, and return the its pointer.
198     llvm::Value *llvm_alloca (const TypeSpec &type, bool derivs,
199                               const std::string &name="", int align=0);
200 
201     /// Given the OSL symbol, return the llvm::Value* corresponding to the
202     /// address of the start of that symbol (first element, first component,
203     /// and just the plain value if it has derivatives).  This is retrieved
204     /// from the allocation map if already there; and if not yet in the
205     /// map, the symbol is alloca'd and placed in the map.
206     llvm::Value *getOrAllocateLLVMSymbol (const Symbol& sym);
207 
208     /// Allocate a CUDA variable for the given OSL symbol and return a pointer
209     /// to the corresponding LLVM GlobalVariable, or return the pointer if it
210     /// has already been allocated.
211     llvm::Value *getOrAllocateCUDAVariable (const Symbol& sym, bool addMetadata=false);
212 
213     /// Create a CUDA global variable and add it to the current Module
214     llvm::Value *addCUDAVariable (const std::string& name, int size, int alignment,
215                                   const void* data, TypeDesc type=TypeDesc::UNKNOWN);
216 
217     /// Create the extra semantic information needed for OptiX variables
218     void createOptixMetadata (const std::string& name, const Symbol& sym );
219 
220     /// Retrieve an llvm::Value that is a pointer holding the start address
221     /// of the specified symbol. This always works for globals and params;
222     /// for stack variables (locals/temps) is succeeds only if the symbol is
223     /// already in the allocation table (will fail otherwise). This method
224     /// is not designed to retrieve constants.
225     llvm::Value *getLLVMSymbolBase (const Symbol &sym);
226 
227     /// Retrieve the named global ("P", "N", etc.).
228     llvm::Value *llvm_global_symbol_ptr (ustring name);
229 
230     /// Test whether val is nonzero, return the llvm::Value* that's the
231     /// result of a CreateICmpNE or CreateFCmpUNE (depending on the
232     /// type).  If test_derivs is true, it it also tests whether the
233     /// derivs are zero.
234     llvm::Value *llvm_test_nonzero (Symbol &val, bool test_derivs = false);
235 
236     /// Implementaiton of Simple assignment.  If arrayindex >= 0, in
237     /// designates a particular array index to assign.
238     bool llvm_assign_impl (Symbol &Result, Symbol &Src, int arrayindex = -1,
239                            int srccomp = -1, int dstcomp = -1);
240 
241 
242     /// Convert the name of a global (and its derivative index) into the
243     /// field number of the ShaderGlobals struct.
244     int ShaderGlobalNameToIndex (ustring name);
245 
246     /// Return the LLVM type handle for the ShaderGlobals struct.
247     ///
248     llvm::Type *llvm_type_sg ();
249 
250     /// Return the LLVM type handle for a pointer to a
251     /// ShaderGlobals struct.
252     llvm::Type *llvm_type_sg_ptr ();
253 
254     /// Return the ShaderGlobals pointer.
255     ///
sg_ptr()256     llvm::Value *sg_ptr () const { return m_llvm_shaderglobals_ptr; }
257 
258     llvm::Type *llvm_type_closure_component ();
259     llvm::Type *llvm_type_closure_component_ptr ();
260 
261     /// Return the ShaderGlobals pointer cast as a void*.
262     ///
sg_void_ptr()263     llvm::Value *sg_void_ptr () {
264         return ll.void_ptr (m_llvm_shaderglobals_ptr);
265     }
266 
llvm_ptr_cast(llvm::Value * val,const TypeSpec & type)267     llvm::Value *llvm_ptr_cast (llvm::Value* val, const TypeSpec &type) {
268         return ll.ptr_cast (val, type.simpletype());
269     }
270 
271     llvm::Value *llvm_void_ptr (const Symbol &sym, int deriv=0) {
272         return ll.void_ptr (llvm_get_pointer(sym, deriv));
273     }
274 
275     /// Return the LLVM type handle for a structure of the common group
276     /// data that holds all the shader params.
277     llvm::Type *llvm_type_groupdata ();
278 
279     /// Return the LLVM type handle for a pointer to the common group
280     /// data that holds all the shader params.
281     llvm::Type *llvm_type_groupdata_ptr ();
282 
283     /// Return the group data pointer.
284     ///
groupdata_ptr()285     llvm::Value *groupdata_ptr () const { return m_llvm_groupdata_ptr; }
286 
287     /// Return the group data pointer cast as a void*.
288     ///
groupdata_void_ptr()289     llvm::Value *groupdata_void_ptr () {
290         return ll.void_ptr (m_llvm_groupdata_ptr);
291     }
292 
293     /// Return a reference to the specified field within the group data.
294     llvm::Value *groupdata_field_ref (int fieldnum);
295 
296     /// Return a pointer to the specified field within the group data,
297     /// optionally cast to pointer to a particular data type.
298     llvm::Value *groupdata_field_ptr (int fieldnum,
299                                       TypeDesc type = TypeDesc::UNKNOWN);
300 
301     /// Return a ref to the bool where the "layer_run" flag is stored for
302     /// the specified layer.
303     llvm::Value *layer_run_ref (int layer);
304 
305     /// Return a ref to the bool where the "userdata_initialized" flag is
306     /// stored for the specified userdata index.
307     llvm::Value *userdata_initialized_ref (int userdata_index=0);
308 
309     /// Generate LLVM code to zero out the variable (including derivs)
310     ///
311     void llvm_assign_zero (const Symbol &sym);
312 
313     /// Generate LLVM code to zero out the derivatives of sym.
314     ///
315     void llvm_zero_derivs (const Symbol &sym);
316 
317     /// Generate LLVM code to zero out the derivatives of an array
318     /// only for the first count elements of it.
319     ///
320     void llvm_zero_derivs (const Symbol &sym, llvm::Value *count);
321 
322     /// Generate a debugging printf at shader execution time.
323     void llvm_gen_debug_printf (string_view message);
324 
325     /// Generate a warning message at shader execution time.
326     void llvm_gen_warning (string_view message);
327 
328     /// Generate an error message at shader execution time.
329     void llvm_gen_error (string_view message);
330 
331     /// Generate code to call the given layer.  If 'unconditional' is
332     /// true, call it without even testing if the layer has already been
333     /// called.
334     void llvm_call_layer (int layer, bool unconditional = false);
335 
336     /// Execute the upstream connection (if any, and if not yet run) that
337     /// establishes the value of symbol sym, which has index 'symindex'
338     /// within the current layer rop.inst().  If already_run is not NULL,
339     /// it points to a vector of layer indices that are known to have been
340     /// run -- those can be skipped without dynamically checking their
341     /// execution status.
342     void llvm_run_connected_layers (Symbol &sym, int symindex, int opnum = -1,
343                                     std::set<int> *already_run = NULL);
344 
345     /// Generate code for a call to the named function with the given
346     /// arg list as symbols -- float & ints will be passed by value,
347     /// triples and matrices will be passed by address.  If deriv_ptrs
348     /// is true, pass pointers even for floats if they have derivs.
349     /// Return an llvm::Value* corresponding to the return value of the
350     /// function, if any.
351     llvm::Value *llvm_call_function (const char *name, cspan<const Symbol *> args,
352                                      bool deriv_ptrs=false);
353     llvm::Value *llvm_call_function (const char *name, const Symbol &A,
354                                      bool deriv_ptrs=false) {
355         return llvm_call_function (name, { &A }, deriv_ptrs);
356     }
357     llvm::Value *llvm_call_function (const char *name, const Symbol &A,
358                                      const Symbol &B, bool deriv_ptrs=false) {
359         return llvm_call_function (name, { &A, &B }, deriv_ptrs);
360     }
361     llvm::Value *llvm_call_function (const char *name, const Symbol &A,
362                                      const Symbol &B, const Symbol &C,
363                                      bool deriv_ptrs=false) {
364         return llvm_call_function (name, { &A, &B, &C }, deriv_ptrs);
365     }
366 
llvm_typedesc(const TypeSpec & typespec)367     TypeDesc llvm_typedesc (const TypeSpec &typespec) {
368         return typespec.is_closure_based()
369            ? TypeDesc(TypeDesc::PTR, typespec.arraylength())
370            : typespec.simpletype();
371     }
372 
373     /// Generate the appropriate llvm type definition for a TypeSpec
374     /// (this is the actual type, for example when we allocate it).
375     /// Allocates ptrs for closures.
llvm_type(const TypeSpec & typespec)376     llvm::Type *llvm_type (const TypeSpec &typespec) {
377         return ll.llvm_type (llvm_typedesc(typespec));
378     }
379 
380     /// Generate the parameter-passing llvm type definition for an OSL
381     /// TypeSpec.
382     llvm::Type *llvm_pass_type (const TypeSpec &typespec);
383 
llvm_type_prepare_closure_func()384     llvm::PointerType *llvm_type_prepare_closure_func() { return m_llvm_type_prepare_closure_func; }
llvm_type_setup_closure_func()385     llvm::PointerType *llvm_type_setup_closure_func() { return m_llvm_type_setup_closure_func; }
386 
387     /// Return the basic block of the exit for the whole instance.
388     ///
llvm_has_exit_instance_block()389     bool llvm_has_exit_instance_block () const {
390         return m_exit_instance_block;
391     }
392 
393     /// Return the basic block of the exit for the whole instance.
394     ///
llvm_exit_instance_block()395     llvm::BasicBlock *llvm_exit_instance_block () {
396         if (! m_exit_instance_block) {
397             std::string name = Strutil::sprintf ("%s_%d_exit_", inst()->layername(), inst()->id());
398             m_exit_instance_block = ll.new_basic_block (name);
399         }
400         return m_exit_instance_block;
401     }
402 
403     /// Check for inf/nan in all written-to arguments of the op
404     void llvm_generate_debugnan (const Opcode &op);
405     /// Check for uninitialized values in all read-from arguments to the op
406     void llvm_generate_debug_uninit (const Opcode &op);
407     /// Print debugging line for the op
408     void llvm_generate_debug_op_printf (const Opcode &op);
409 
layer_func()410     llvm::Function *layer_func () const { return ll.current_function(); }
411 
412     /// Call this when JITing a texture-like call, to track how many.
generated_texture_call(bool handle)413     void generated_texture_call (bool handle) {
414         shadingsys().m_stat_tex_calls_codegened += 1;
415         if (handle)
416             shadingsys().m_stat_tex_calls_as_handles += 1;
417     }
418 
419     /// Return the mapping from symbol names to GlobalVariables.
get_const_map()420     std::map<std::string,llvm::GlobalVariable*>& get_const_map() { return m_const_map; }
421 
422     /// Return whether or not we are compiling for an OptiX-based renderer.
use_optix()423     bool use_optix() { return m_use_optix; }
424 
425     /// Return the userdata index for the given Symbol.  Return -1 if the Symbol
426     /// is not an input parameter or is constant and therefore doesn't have an
427     /// entry in the groupdata struct.
428     int find_userdata_index (const Symbol& sym);
429 
430     LLVM_Util ll;
431 
432 private:
433     std::vector<int> m_layer_remap;     ///< Remapping of layer ordering
434     std::set<int> m_layers_already_run; ///< List of layers run
435     int m_num_used_layers;              ///< Number of layers actually used
436 
437     double m_stat_total_llvm_time;        ///<   total time spent on LLVM
438     double m_stat_llvm_setup_time;        ///<     llvm setup time
439     double m_stat_llvm_irgen_time;        ///<     llvm IR generation time
440     double m_stat_llvm_opt_time;          ///<     llvm IR optimization time
441     double m_stat_llvm_jit_time;          ///<     llvm JIT time
442 
443     // LLVM stuff
444     AllocationMap m_named_values;
445     std::map<const Symbol*,int> m_param_order_map;
446     llvm::Value *m_llvm_shaderglobals_ptr;
447     llvm::Value *m_llvm_groupdata_ptr;
448     llvm::BasicBlock * m_exit_instance_block;  // exit point for the instance
449     llvm::Type *m_llvm_type_sg;  // LLVM type of ShaderGlobals struct
450     llvm::Type *m_llvm_type_groupdata;  // LLVM type of group data
451     llvm::Type *m_llvm_type_closure_component; // LLVM type for ClosureComponent
452     llvm::PointerType *m_llvm_type_prepare_closure_func;
453     llvm::PointerType *m_llvm_type_setup_closure_func;
454     int m_llvm_local_mem;             // Amount of memory we use for locals
455 
456     // A mapping from symbol names to llvm::GlobalVariables
457     std::map<std::string,llvm::GlobalVariable*> m_const_map;
458 
459     // A mapping from canonical strings to string variable names, used to
460     // detect collisions that might occur due to using the string hash to
461     // create variable names.
462     std::map<std::string,std::string>           m_varname_map;
463 
464     bool m_use_optix;                   ///< Compile for OptiX?
465 
466     friend class ShadingSystemImpl;
467 };
468 
469 
470 }; // namespace pvt
471 OSL_NAMESPACE_EXIT
472