Vuo  2.2.0
VuoCompilerCodeGenUtilities.cc
Go to the documentation of this file.
1 
12 #include "VuoCompilerException.hh"
13 #include "VuoCompilerIssue.hh"
14 #include "VuoCompilerPort.hh"
16 #include "VuoCompilerType.hh"
17 #include "VuoPort.hh"
18 #include "VuoStringUtilities.hh"
19 #include "VuoType.hh"
20 
29 Value * VuoCompilerCodeGenUtilities::generateCreateDispatchSemaphore(Module *module, BasicBlock *block, int initialValue)
30 {
31  PointerType *dispatch_semaphore_t_type = getDispatchSemaphoreType(module);
32 
33  Function *dispatch_semaphore_create_function = module->getFunction("dispatch_semaphore_create");
34  if (! dispatch_semaphore_create_function)
35  {
36  vector<Type *> dispatch_semaphore_create_functionParams;
37  dispatch_semaphore_create_functionParams.push_back(IntegerType::get(module->getContext(), 64));
38  FunctionType *dispatch_semaphore_create_functionType = FunctionType::get(dispatch_semaphore_t_type,
39  dispatch_semaphore_create_functionParams,
40  false);
41  dispatch_semaphore_create_function = Function::Create(dispatch_semaphore_create_functionType,
42  GlobalValue::ExternalLinkage,
43  "dispatch_semaphore_create",
44  module);
45  }
46 
47  ConstantInt *initialValueConst = ConstantInt::get(module->getContext(), APInt(64, initialValue));
48  return CallInst::Create(dispatch_semaphore_create_function, initialValueConst, "", block);
49 }
50 
59 Value * VuoCompilerCodeGenUtilities::generateWaitForSemaphore(Module *module, BasicBlock *block, AllocaInst *semaphoreVariable)
60 {
61  LoadInst *semaphoreValue = new LoadInst(semaphoreVariable, "", false, block);
62  return generateWaitForSemaphore(module, block, semaphoreValue);
63 }
64 
74 Value * VuoCompilerCodeGenUtilities::generateWaitForSemaphore(Module *module, BasicBlock *block, AllocaInst *semaphoreVariable, Value *timeoutValue)
75 {
76  LoadInst *semaphoreValue = new LoadInst(semaphoreVariable, "", false, block);
77  return generateWaitForSemaphore(module, block, semaphoreValue, timeoutValue);
78 }
79 
83 Value * VuoCompilerCodeGenUtilities::generateWaitForSemaphore(Module *module, BasicBlock *block, Value *semaphoreValue)
84 {
85  IntegerType *dispatch_time_t_type = IntegerType::get(module->getContext(), 64);
86  Value *timeoutValue = ConstantInt::get(dispatch_time_t_type, DISPATCH_TIME_FOREVER);
87  return generateWaitForSemaphore(module, block, semaphoreValue, timeoutValue);
88 }
89 
93 Value * VuoCompilerCodeGenUtilities::generateWaitForSemaphore(Module *module, BasicBlock *block, Value *semaphoreValue, Value *timeoutValue)
94 {
95  PointerType *dispatch_semaphore_t_type = getDispatchSemaphoreType(module);
96  IntegerType *dispatch_time_t_type = IntegerType::get(module->getContext(), 64);
97 
98  vector<Type *> dispatch_semaphore_wait_functionParams;
99  dispatch_semaphore_wait_functionParams.push_back(dispatch_semaphore_t_type);
100  dispatch_semaphore_wait_functionParams.push_back(dispatch_time_t_type);
101  FunctionType *dispatch_semaphore_wait_functionType = FunctionType::get(IntegerType::get(module->getContext(), 64),
102  dispatch_semaphore_wait_functionParams,
103  false);
104 
105  Function *dispatch_semaphore_wait_function = module->getFunction("dispatch_semaphore_wait");
106  if (! dispatch_semaphore_wait_function) {
107  dispatch_semaphore_wait_function = Function::Create(dispatch_semaphore_wait_functionType,
108  GlobalValue::ExternalLinkage,
109  "dispatch_semaphore_wait",
110  module);
111  }
112 
113  vector<Value *> args;
114  args.push_back(semaphoreValue);
115  args.push_back(timeoutValue);
116  return CallInst::Create(dispatch_semaphore_wait_function, args, "", block);
117 }
118 
122 void VuoCompilerCodeGenUtilities::generateSignalForSemaphore(Module *module, BasicBlock *block, AllocaInst *semaphoreVariable)
123 {
124  LoadInst *semaphoreValue = new LoadInst(semaphoreVariable, "", false, block);
125  return generateSignalForSemaphore(module, block, semaphoreValue);
126 }
127 
131 void VuoCompilerCodeGenUtilities::generateSignalForSemaphore(Module *module, BasicBlock *block, Value *semaphoreValue)
132 {
133  PointerType *dispatch_semaphore_t_type = getDispatchSemaphoreType(module);
134 
135  vector<Type *> dispatch_semaphore_signal_functionParams;
136  dispatch_semaphore_signal_functionParams.push_back(dispatch_semaphore_t_type);
137  FunctionType *dispatch_semaphore_signal_functionType = FunctionType::get(IntegerType::get(module->getContext(), 64),
138  dispatch_semaphore_signal_functionParams,
139  false);
140 
141  Function *dispatch_semaphore_signal_function = module->getFunction("dispatch_semaphore_signal");
142  if (! dispatch_semaphore_signal_function) {
143  dispatch_semaphore_signal_function = Function::Create(dispatch_semaphore_signal_functionType,
144  GlobalValue::ExternalLinkage,
145  "dispatch_semaphore_signal",
146  module);
147  }
148 
149  CallInst::Create(dispatch_semaphore_signal_function, semaphoreValue, "", block);
150 }
151 
159 Value * VuoCompilerCodeGenUtilities::generateCreateDispatchGroup(Module *module, BasicBlock *block)
160 {
161  Function *dispatch_group_create_function = module->getFunction("dispatch_group_create");
162  if (! dispatch_group_create_function)
163  {
164  vector<Type *> dispatch_group_create_functionParams;
165  FunctionType *dispatch_group_create_functionType = FunctionType::get(getDispatchGroupType(module),
166  dispatch_group_create_functionParams,
167  false);
168  dispatch_group_create_function = Function::Create(dispatch_group_create_functionType,
169  GlobalValue::ExternalLinkage,
170  "dispatch_group_create", module);
171  }
172 
173  return CallInst::Create(dispatch_group_create_function, "", block);
174 }
175 
179 void VuoCompilerCodeGenUtilities::generateEnterDispatchGroup(Module *module, BasicBlock *block, Value *dispatchGroupValue)
180 {
181  Function *dispatch_group_enter_function = module->getFunction("dispatch_group_enter");
182  if (! dispatch_group_enter_function)
183  {
184  PointerType *dispatch_group_t_type = getDispatchGroupType(module);
185  FunctionType *dispatch_group_enter_functionType = FunctionType::get(Type::getVoidTy(module->getContext()),
186  dispatch_group_t_type,
187  false);
188  dispatch_group_enter_function = Function::Create(dispatch_group_enter_functionType,
189  GlobalValue::ExternalLinkage,
190  "dispatch_group_enter",
191  module);
192  }
193 
194  CallInst::Create(dispatch_group_enter_function, dispatchGroupValue, "", block);
195 }
196 
200 void VuoCompilerCodeGenUtilities::generateLeaveDispatchGroup(Module *module, BasicBlock *block, Value *dispatchGroupValue)
201 {
202  Function *dispatch_group_leave_function = module->getFunction("dispatch_group_leave");
203  if (! dispatch_group_leave_function)
204  {
205  PointerType *dispatch_group_t_type = getDispatchGroupType(module);
206  FunctionType *dispatch_group_leave_functionType = FunctionType::get(Type::getVoidTy(module->getContext()),
207  dispatch_group_t_type,
208  false);
209  dispatch_group_leave_function = Function::Create(dispatch_group_leave_functionType,
210  GlobalValue::ExternalLinkage,
211  "dispatch_group_leave",
212  module);
213  }
214 
215  CallInst::Create(dispatch_group_leave_function, dispatchGroupValue, "", block);
216 }
217 
221 void VuoCompilerCodeGenUtilities::generateWaitForDispatchGroup(Module *module, BasicBlock *block, Value *dispatchGroupValue,
222  dispatch_time_t timeout)
223 {
224  Function *dispatch_group_wait_function = module->getFunction("dispatch_group_wait");
225  if (! dispatch_group_wait_function)
226  {
227  PointerType *dispatch_group_t_type = getDispatchGroupType(module);
228 
229  vector<Type *> dispatch_group_wait_functionParams;
230  dispatch_group_wait_functionParams.push_back(dispatch_group_t_type);
231  dispatch_group_wait_functionParams.push_back(IntegerType::get(module->getContext(), 64));
232  FunctionType *dispatch_group_wait_functionType = FunctionType::get(IntegerType::get(module->getContext(), 64),
233  dispatch_group_wait_functionParams,
234  false);
235 
236  dispatch_group_wait_function = Function::Create(dispatch_group_wait_functionType,
237  GlobalValue::ExternalLinkage,
238  "dispatch_group_wait",
239  module);
240  }
241 
242  ConstantInt *timeout_value = ConstantInt::get(module->getContext(), APInt(64, timeout, true));
243 
244  vector<Value *> args;
245  args.push_back(dispatchGroupValue);
246  args.push_back(timeout_value);
247  CallInst::Create(dispatch_group_wait_function, args, "", block);
248 }
249 
253 Value * VuoCompilerCodeGenUtilities::generateGetGlobalDispatchQueue(Module *module, BasicBlock *block)
254 {
255  PointerType *dispatch_queue_t_type = getDispatchQueueType(module);
256 
257  vector<Type *> dispatch_get_global_queue_functionParams;
258  dispatch_get_global_queue_functionParams.push_back(IntegerType::get(module->getContext(), 64));
259  dispatch_get_global_queue_functionParams.push_back(IntegerType::get(module->getContext(), 64));
260  FunctionType *dispatch_get_global_queue_functionType = FunctionType::get(dispatch_queue_t_type,
261  dispatch_get_global_queue_functionParams,
262  false);
263 
264  Function *dispatch_get_global_queue_function = module->getFunction("dispatch_get_global_queue");
265  if (! dispatch_get_global_queue_function) {
266  dispatch_get_global_queue_function = Function::Create(dispatch_get_global_queue_functionType,
267  GlobalValue::ExternalLinkage,
268  "dispatch_get_global_queue",
269  module);
270  }
271 
272  Constant *zeroValue = ConstantInt::get(dispatch_get_global_queue_functionType->getParamType(0), 0);
273 
274  vector<Value *> args;
275  args.push_back(zeroValue);
276  args.push_back(zeroValue);
277  return CallInst::Create(dispatch_get_global_queue_function, args, "", block);
278 }
279 
288 Value * VuoCompilerCodeGenUtilities::generateCreateDispatchQueue(Module *module, BasicBlock *block, string dispatchQueueName)
289 {
290  PointerType *dispatch_queue_t_type = getDispatchQueueType(module);
291  PointerType *pointerToi8 = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
292 
293  StructType *dispatch_queue_attr_s_type = module->getTypeByName("struct.dispatch_queue_attr_s");
294  if (! dispatch_queue_attr_s_type)
295  dispatch_queue_attr_s_type = StructType::create(module->getContext(), "struct.dispatch_queue_attr_s");
296  PointerType *dispatch_queue_attr_t_type = PointerType::get(dispatch_queue_attr_s_type, 0);
297 
298  vector<Type *> dispatch_queue_create_functionParams;
299  dispatch_queue_create_functionParams.push_back(pointerToi8);
300  dispatch_queue_create_functionParams.push_back(dispatch_queue_attr_t_type);
301  FunctionType *dispatch_queue_create_functionType = FunctionType::get(dispatch_queue_t_type,
302  dispatch_queue_create_functionParams,
303  false);
304 
305  Function *dispatch_queue_create_function = module->getFunction("dispatch_queue_create");
306  if (! dispatch_queue_create_function)
307  {
308  dispatch_queue_create_function = Function::Create(dispatch_queue_create_functionType,
309  GlobalValue::ExternalLinkage,
310  "dispatch_queue_create",
311  module);
312  }
313 
314  ArrayType *dispatchQueueNameType = ArrayType::get(IntegerType::get(module->getContext(), 8), dispatchQueueName.length() + 1);
315  GlobalVariable *dispatchQueueNameVariable = new GlobalVariable(*module,
316  dispatchQueueNameType,
317  true,
318  GlobalValue::InternalLinkage,
319  0,
320  ".str");
321  Constant *dispatchQueueNameValue = ConstantDataArray::getString(module->getContext(), dispatchQueueName, true);
322  dispatchQueueNameVariable->setInitializer(dispatchQueueNameValue);
323 
324  ConstantInt *zeroi64Value = ConstantInt::get(module->getContext(), APInt(64, 0));
325  ConstantPointerNull *nullValue = ConstantPointerNull::get(dispatch_queue_attr_t_type);
326 
327  std::vector<Constant*> dispatchQueueLabel_indices;
328  dispatchQueueLabel_indices.push_back(zeroi64Value);
329  dispatchQueueLabel_indices.push_back(zeroi64Value);
330  Constant *dispatchQueueLabel = ConstantExpr::getGetElementPtr(dispatchQueueNameVariable, dispatchQueueLabel_indices);
331 
332  vector<Value *> args;
333  args.push_back(dispatchQueueLabel);
334  args.push_back(nullValue);
335  return CallInst::Create(dispatch_queue_create_function, args, "", block);
336 }
337 
341 void VuoCompilerCodeGenUtilities::generateAsynchronousSubmissionToDispatchQueue(Module *module, BasicBlock *block, Value *dispatchQueueValue,
342  Function *workerFunction, Value *contextValue)
343 {
344  generateSubmissionToDispatchQueue(module, block, dispatchQueueValue, workerFunction, contextValue, false);
345 }
346 
350 void VuoCompilerCodeGenUtilities::generateSynchronousSubmissionToDispatchQueue(Module *module, BasicBlock *block, Value *dispatchQueueValue,
351  Function *workerFunction, Value *contextValue)
352 {
353  generateSubmissionToDispatchQueue(module, block, dispatchQueueValue, workerFunction, contextValue, true);
354 }
355 
359 void VuoCompilerCodeGenUtilities::generateSubmissionToDispatchQueue(Module *module, BasicBlock *block, Value *dispatchQueueValue,
360  Function *workerFunction, Value *contextValue, bool isSynchronous)
361 {
362  PointerType *dispatch_queue_t_type = getDispatchQueueType(module);
363  PointerType *pointerToi8 = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
364 
365  vector<Type *> dispatchSubmitFunctionParams;
366  dispatchSubmitFunctionParams.push_back(dispatch_queue_t_type);
367  dispatchSubmitFunctionParams.push_back(pointerToi8);
368  dispatchSubmitFunctionParams.push_back(workerFunction->getType());
369  FunctionType *dispatchSubmitFunctionType = FunctionType::get(Type::getVoidTy(module->getContext()),
370  dispatchSubmitFunctionParams,
371  false);
372 
373  const char *dispatchSubmitFunctionName = (isSynchronous ? "dispatch_sync_f" : "dispatch_async_f");
374  Function *dispatchSubmitFunction = module->getFunction(dispatchSubmitFunctionName);
375  if (! dispatchSubmitFunction) {
376  dispatchSubmitFunction = Function::Create(dispatchSubmitFunctionType,
377  GlobalValue::ExternalLinkage,
378  dispatchSubmitFunctionName,
379  module);
380  }
381 
382  vector<Value *> args;
383  args.push_back(dispatchQueueValue);
384  args.push_back(contextValue);
385  args.push_back(workerFunction);
386  CallInst::Create(dispatchSubmitFunction, args, "", block);
387 }
388 
392 Value * VuoCompilerCodeGenUtilities::generateConversionToDispatchObject(Module *module, BasicBlock *block, Value *dispatchObjectVariable)
393 {
394  PointerType *pointerToi8Type = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
395  PointerType *dispatchObjectOriginalType = cast<PointerType>(dispatchObjectVariable->getType());
396  StructType *dispatch_object_t_type = getDispatchObjectType(module);
397 
398  vector<Type *> llvm_memcpy_p0i8_p0i8_i64_functionParams;
399  llvm_memcpy_p0i8_p0i8_i64_functionParams.push_back(pointerToi8Type);
400  llvm_memcpy_p0i8_p0i8_i64_functionParams.push_back(pointerToi8Type);
401  llvm_memcpy_p0i8_p0i8_i64_functionParams.push_back(IntegerType::get(module->getContext(), 64));
402  llvm_memcpy_p0i8_p0i8_i64_functionParams.push_back(IntegerType::get(module->getContext(), 32));
403  llvm_memcpy_p0i8_p0i8_i64_functionParams.push_back(IntegerType::get(module->getContext(), 1));
404  FunctionType *llvm_memcpy_p0i8_p0i8_i64_functionType = FunctionType::get(Type::getVoidTy(module->getContext()), llvm_memcpy_p0i8_p0i8_i64_functionParams, false);
405  Function *llvm_memcpy_p0i8_p0i8_i64_function = module->getFunction("llvm.memcpy.p0i8.p0i8.i64");
406  if (! llvm_memcpy_p0i8_p0i8_i64_function)
407  llvm_memcpy_p0i8_p0i8_i64_function = Function::Create(llvm_memcpy_p0i8_p0i8_i64_functionType, GlobalValue::ExternalLinkage, "llvm.memcpy.p0i8.p0i8.i64", module);
408 
409  ConstantInt *zeroValue32 = ConstantInt::get(module->getContext(), APInt(32, 0));
410  ConstantInt *zeroValue1 = ConstantInt::get(module->getContext(), APInt(1, 0));
411  ConstantInt *eightValue64 = ConstantInt::get(module->getContext(), APInt(64, 8));
412  ConstantInt *eightValue32 = ConstantInt::get(module->getContext(), APInt(32, 8));
413 
414  AllocaInst *dispatchObjectUnion = new AllocaInst(dispatch_object_t_type, "", block);
415  AllocaInst *compoundLiteral = new AllocaInst(dispatch_object_t_type, "", block);
416 
417  CastInst *compoundLiteralAsDispatchObjectOriginalType = new BitCastInst(compoundLiteral, dispatchObjectOriginalType, "", block);
418  LoadInst *dispatchObjectValue = new LoadInst(dispatchObjectVariable, "", false, block);
419  new StoreInst(dispatchObjectValue, compoundLiteralAsDispatchObjectOriginalType, false, block);
420 
421  CastInst *dispatchObjectUnionAsPointerToi8 = new BitCastInst(dispatchObjectUnion, pointerToi8Type, "", block);
422  CastInst *compoundLiteralAsPointerToi8 = new BitCastInst(compoundLiteral, pointerToi8Type, "", block);
423 
424  std::vector<Value *> llvm_memcpy_p0i8_p0i8_i64_functionArgs;
425  llvm_memcpy_p0i8_p0i8_i64_functionArgs.push_back(dispatchObjectUnionAsPointerToi8);
426  llvm_memcpy_p0i8_p0i8_i64_functionArgs.push_back(compoundLiteralAsPointerToi8);
427  llvm_memcpy_p0i8_p0i8_i64_functionArgs.push_back(eightValue64);
428  llvm_memcpy_p0i8_p0i8_i64_functionArgs.push_back(eightValue32);
429  llvm_memcpy_p0i8_p0i8_i64_functionArgs.push_back(zeroValue1);
430  CallInst::Create(llvm_memcpy_p0i8_p0i8_i64_function, llvm_memcpy_p0i8_p0i8_i64_functionArgs, "", block);
431 
432  vector<Value *> gepIndices;
433  gepIndices.push_back(zeroValue32);
434  gepIndices.push_back(zeroValue32);
435  Instruction *dispatchObjectUnionMember = GetElementPtrInst::Create(dispatchObjectUnion, gepIndices, "", block);
436  return new LoadInst(dispatchObjectUnionMember, "", false, block);
437 }
438 
446 void VuoCompilerCodeGenUtilities::generateRetainForDispatchObject(Module *module, BasicBlock *block, Value *dispatchObjectVariable)
447 {
448  Value *dispatchObjectValueAsDispatchObject = generateConversionToDispatchObject(module, block, dispatchObjectVariable);
449 
450  StructType *dispatch_object_s_type = getDispatchObjectElementType(module);
451  PointerType *pointerTo_dispatch_object_s_type = PointerType::get(dispatch_object_s_type, 0);
452 
453  vector<Type*> dispatchRetainFunctionParams;
454  dispatchRetainFunctionParams.push_back(pointerTo_dispatch_object_s_type);
455  FunctionType *dispatchRetainFunctionType = FunctionType::get(Type::getVoidTy(module->getContext()), dispatchRetainFunctionParams, false);
456  Function *dispatchRetainFunction = module->getFunction("dispatch_retain");
457  if (! dispatchRetainFunction)
458  dispatchRetainFunction = Function::Create(dispatchRetainFunctionType, GlobalValue::ExternalLinkage, "dispatch_retain", module);
459 
460  CallInst::Create(dispatchRetainFunction, dispatchObjectValueAsDispatchObject, "", block);
461 }
462 
470 void VuoCompilerCodeGenUtilities::generateFinalizationForDispatchObject(Module *module, BasicBlock *block, Value *dispatchObjectVariable)
471 {
472  Value *dispatchObjectValueAsDispatchObject = generateConversionToDispatchObject(module, block, dispatchObjectVariable);
473 
474  StructType *dispatch_object_s_type = getDispatchObjectElementType(module);
475  PointerType *pointerTo_dispatch_object_s_type = PointerType::get(dispatch_object_s_type, 0);
476 
477  vector<Type*> dispatchReleaseFunctionParams;
478  dispatchReleaseFunctionParams.push_back(pointerTo_dispatch_object_s_type);
479  FunctionType *dispatchReleaseFunctionType = FunctionType::get(Type::getVoidTy(module->getContext()), dispatchReleaseFunctionParams, false);
480  Function *dispatchReleaseFunction = module->getFunction("dispatch_release");
481  if (! dispatchReleaseFunction)
482  dispatchReleaseFunction = Function::Create(dispatchReleaseFunctionType, GlobalValue::ExternalLinkage, "dispatch_release", module);
483 
484  CallInst::Create(dispatchReleaseFunction, dispatchObjectValueAsDispatchObject, "", block);
485 }
486 
495 Value * VuoCompilerCodeGenUtilities::generateCreateDispatchTime(Module *module, BasicBlock *block, Value *deltaValue)
496 {
497  Type *dispatch_time_t_type = IntegerType::get(module->getContext(), 64);
498 
499  vector<Type *> dispatch_time_functionParams;
500  dispatch_time_functionParams.push_back(dispatch_time_t_type);
501  dispatch_time_functionParams.push_back(IntegerType::get(module->getContext(), 64));
502  FunctionType *dispatch_time_functionType = FunctionType::get(dispatch_time_t_type,
503  dispatch_time_functionParams,
504  false);
505 
506  Function *dispatch_time_function = module->getFunction("dispatch_time");
507  if (! dispatch_time_function) {
508  dispatch_time_function = Function::Create(dispatch_time_functionType,
509  GlobalValue::ExternalLinkage,
510  "dispatch_time",
511  module);
512  }
513 
514  ConstantInt *whenValue = ConstantInt::get(module->getContext(), APInt(64, DISPATCH_TIME_NOW));
515 
516  vector<Value *> args;
517  args.push_back(whenValue);
518  args.push_back(deltaValue);
519  return CallInst::Create(dispatch_time_function, args, "", block);
520 }
521 
532 Value * VuoCompilerCodeGenUtilities::generateCreatePortContext(Module *module, BasicBlock *block, Type *dataType,
533  bool isTrigger, string triggerQueueName)
534 {
535  IntegerType *boolType = IntegerType::get(module->getContext(), 64);
536  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
537  PointerType *voidPointerType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
538 
539  const char *functionName = "vuoCreatePortContext";
540  Function *function = module->getFunction(functionName);
541  if (! function)
542  {
543  PointerType *pointerToPortContext = PointerType::get(getPortContextType(module), 0);
544 
545  vector<Type *> params;
546  params.push_back(voidPointerType);
547  params.push_back(boolType);
548  params.push_back(pointerToCharType);
549 
550  FunctionType *functionType = FunctionType::get(pointerToPortContext, params, false);
551  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
552  }
553 
554  Value *pointerToDataAsVoidPointer;
555  if (dataType)
556  {
557  Value *pointerToData = VuoCompilerCodeGenUtilities::generateMemoryAllocation(module, block, dataType, 1);
558  pointerToDataAsVoidPointer = new BitCastInst(pointerToData, voidPointerType, "", block);
559  }
560  else
561  pointerToDataAsVoidPointer = ConstantPointerNull::get(voidPointerType);
562 
563  vector<Value *> args;
564  args.push_back(pointerToDataAsVoidPointer);
565  args.push_back(ConstantInt::get(boolType, isTrigger));
566  args.push_back(generatePointerToConstantString(module, triggerQueueName));
567  return CallInst::Create(function, args, "", block);
568 }
569 
578 void VuoCompilerCodeGenUtilities::generateSetPortContextEvent(Module *module, BasicBlock *block, Value *portContextValue, Value *eventValue)
579 {
580  const char *functionName = "vuoSetPortContextEvent";
581  Function *function = module->getFunction(functionName);
582  if (! function)
583  {
584  StructType *portContextType = getPortContextType(module);
585  PointerType *pointerToPortContext = PointerType::get(portContextType, 0);
586  Type *boolType = portContextType->getElementType(0);
587 
588  vector<Type *> params;
589  params.push_back(pointerToPortContext);
590  params.push_back(boolType);
591  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
592  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
593  }
594 
595  vector<Value *> args;
596  args.push_back(portContextValue);
597  args.push_back(eventValue);
598  CallInst::Create(function, args, "", block);
599 }
600 
609 void VuoCompilerCodeGenUtilities::generateSetPortContextData(Module *module, BasicBlock *block, Value *portContextValue, Value *dataValue)
610 {
611  Value *pointerToData = generateGetPortContextDataVariable(module, block, portContextValue, dataValue->getType());
612  new StoreInst(dataValue, pointerToData, false, block);
613 }
614 
623 void VuoCompilerCodeGenUtilities::generateSetPortContextTriggerFunction(Module *module, BasicBlock *block, Value *portContextValue, Value *triggerFunctionValue)
624 {
625  const char *functionName = "vuoSetPortContextTriggerFunction";
626  Function *function = module->getFunction(functionName);
627  if (! function)
628  {
629  StructType *portContextType = getPortContextType(module);
630  PointerType *pointerToPortContext = PointerType::get(portContextType, 0);
631  Type *triggerFunctionType = portContextType->getElementType(5);
632 
633  vector<Type *> params;
634  params.push_back(pointerToPortContext);
635  params.push_back(triggerFunctionType);
636  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
637  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
638  }
639 
640  PointerType *voidPointerType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
641  Value *triggerFunctionAsVoidPointer = new BitCastInst(triggerFunctionValue, voidPointerType, "", block);
642 
643  vector<Value *> args;
644  args.push_back(portContextValue);
645  args.push_back(triggerFunctionAsVoidPointer);
646  CallInst::Create(function, args, "", block);
647 }
648 
657 Value * VuoCompilerCodeGenUtilities::generateGetPortContextEvent(Module *module, BasicBlock *block, Value *portContextValue)
658 {
659  const char *functionName = "vuoGetPortContextEvent";
660  Function *function = module->getFunction(functionName);
661  if (! function)
662  {
663  StructType *portContextType = getPortContextType(module);
664  PointerType *pointerToPortContext = PointerType::get(portContextType, 0);
665  Type *boolType = portContextType->getElementType(0);
666 
667  FunctionType *functionType = FunctionType::get(boolType, pointerToPortContext, false);
668  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
669  }
670 
671  return CallInst::Create(function, portContextValue, "", block);
672 }
673 
683 Value * VuoCompilerCodeGenUtilities::generateGetPortContextData(Module *module, BasicBlock *block, Value *portContextValue, Type *dataType)
684 {
685  Value *pointerToData = generateGetPortContextDataVariable(module, block, portContextValue, dataType);
686  return new LoadInst(pointerToData, "", false, block);
687 }
688 
698 Value * VuoCompilerCodeGenUtilities::generateGetPortContextDataVariable(Module *module, BasicBlock *block, Value *portContextValue, Type *dataType)
699 {
700  Value *pointerToDataAsVoidPointer = generateGetPortContextDataVariableAsVoidPointer(module, block, portContextValue);
701  return new BitCastInst(pointerToDataAsVoidPointer, PointerType::get(dataType, 0), "", block);
702 }
703 
712 Value * VuoCompilerCodeGenUtilities::generateGetPortContextDataVariableAsVoidPointer(Module *module, BasicBlock *block, Value *portContextValue)
713 {
714  const char *functionName = "vuoGetPortContextData";
715  Function *function = module->getFunction(functionName);
716  if (! function)
717  {
718  StructType *portContextType = getPortContextType(module);
719  PointerType *pointerToPortContext = PointerType::get(portContextType, 0);
720  Type *voidPointerType = portContextType->getElementType(1);
721 
722  FunctionType *functionType = FunctionType::get(voidPointerType, pointerToPortContext, false);
723  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
724  }
725 
726  return CallInst::Create(function, portContextValue, "", block);
727 }
728 
737 Value * VuoCompilerCodeGenUtilities::generateGetPortContextTriggerQueue(Module *module, BasicBlock *block, Value *portContextValue)
738 {
739  const char *functionName = "vuoGetPortContextTriggerQueue";
740  Function *function = module->getFunction(functionName);
741  if (! function)
742  {
743  StructType *portContextType = getPortContextType(module);
744  PointerType *pointerToPortContext = PointerType::get(portContextType, 0);
745  Type *dispatchQueueType = portContextType->getElementType(3);
746 
747  FunctionType *functionType = FunctionType::get(dispatchQueueType, pointerToPortContext, false);
748  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
749  }
750 
751  return CallInst::Create(function, portContextValue, "", block);
752 }
753 
762 Value * VuoCompilerCodeGenUtilities::generateGetPortContextTriggerSemaphore(Module *module, BasicBlock *block, Value *portContextValue)
763 {
764  const char *functionName = "vuoGetPortContextTriggerSemaphore";
765  Function *function = module->getFunction(functionName);
766  if (! function)
767  {
768  StructType *portContextType = getPortContextType(module);
769  PointerType *pointerToPortContext = PointerType::get(portContextType, 0);
770  Type *dispatchSemaphoreType = portContextType->getElementType(4);
771 
772  FunctionType *functionType = FunctionType::get(dispatchSemaphoreType, pointerToPortContext, false);
773  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
774  }
775 
776  return CallInst::Create(function, portContextValue, "", block);
777 }
778 
788 Value * VuoCompilerCodeGenUtilities::generateGetPortContextTriggerFunction(Module *module, BasicBlock *block, Value *portContextValue, FunctionType *functionType)
789 {
790  const char *functionName = "vuoGetPortContextTriggerFunction";
791  Function *function = module->getFunction(functionName);
792  if (! function)
793  {
794  StructType *portContextType = getPortContextType(module);
795  PointerType *pointerToPortContext = PointerType::get(portContextType, 0);
796  Type *triggerFunctionType = portContextType->getElementType(5);
797 
798  FunctionType *functionType = FunctionType::get(triggerFunctionType, pointerToPortContext, false);
799  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
800  }
801 
802  Value *triggerFunctionAsVoidPointer = CallInst::Create(function, portContextValue, "", block);
803  PointerType *pointerToTriggerFunctionType = PointerType::get(functionType, 0);
804  return new BitCastInst(triggerFunctionAsVoidPointer, pointerToTriggerFunctionType, "", block);
805 }
806 
814 void VuoCompilerCodeGenUtilities::generateRetainPortContextData(Module *module, BasicBlock *block, Value *portContextValue)
815 {
816  const char *functionName = "vuoRetainPortContextData";
817  Function *function = module->getFunction(functionName);
818  if (! function)
819  {
820  StructType *portContextType = getPortContextType(module);
821  PointerType *pointerToPortContext = PointerType::get(portContextType, 0);
822 
823  vector<Type *> params;
824  params.push_back(pointerToPortContext);
825  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
826  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
827  }
828 
829  vector<Value *> args;
830  args.push_back(portContextValue);
831  CallInst::Create(function, args, "", block);
832 }
833 
844 Value * VuoCompilerCodeGenUtilities::generateCreateNodeContext(Module *module, BasicBlock *block, bool hasInstanceData,
845  bool isComposition, size_t outputEventCount)
846 {
847  IntegerType *boolType = IntegerType::get(module->getContext(), 64);
848  IntegerType *sizeType = IntegerType::get(module->getContext(), 64);
849 
850  const char *functionName = "vuoCreateNodeContext";
851  Function *function = module->getFunction(functionName);
852  if (! function)
853  {
854  PointerType *pointerToNodeContext = PointerType::get(getNodeContextType(module), 0);
855 
856  vector<Type *> params;
857  params.push_back(boolType);
858  params.push_back(boolType);
859  params.push_back(sizeType);
860 
861  FunctionType *functionType = FunctionType::get(pointerToNodeContext, params, false);
862  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
863  }
864 
865  vector<Value *> args;
866  args.push_back(ConstantInt::get(boolType, hasInstanceData));
867  args.push_back(ConstantInt::get(boolType, isComposition));
868  args.push_back(ConstantInt::get(sizeType, outputEventCount));
869  return CallInst::Create(function, args, "", block);
870 }
871 
880 void VuoCompilerCodeGenUtilities::generateSetNodeContextPortContexts(Module *module, BasicBlock *block, Value *nodeContextValue, vector<Value *> portContextValues)
881 {
882  PointerType *pointerToPortContext = PointerType::get(getPortContextType(module), 0);
883  PointerType *pointerToPointerToPortContext = PointerType::get(pointerToPortContext, 0);
884  IntegerType *sizeType = IntegerType::get(module->getContext(), 64);
885 
886  Value *portContextsArrayValue = generateMemoryAllocation(module, block, pointerToPortContext, portContextValues.size());
887  for (size_t i = 0; i < portContextValues.size(); ++i)
888  generateSetArrayElement(module, block, portContextsArrayValue, i, portContextValues[i]);
889 
890  const char *functionName = "vuoSetNodeContextPortContexts";
891  Function *function = module->getFunction(functionName);
892  if (! function)
893  {
894  StructType *nodeContextType = getNodeContextType(module);
895  PointerType *pointerToNodeContext = PointerType::get(nodeContextType, 0);
896 
897  vector<Type *> params;
898  params.push_back(pointerToNodeContext);
899  params.push_back(pointerToPointerToPortContext);
900  params.push_back(sizeType);
901  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
902  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
903  }
904 
905  vector<Value *> args;
906  args.push_back(nodeContextValue);
907  args.push_back(portContextsArrayValue);
908  args.push_back(ConstantInt::get(sizeType, portContextValues.size()));
909  CallInst::Create(function, args, "", block);
910 }
911 
920 void VuoCompilerCodeGenUtilities::generateSetNodeContextInstanceData(Module *module, BasicBlock *block, Value *nodeContextValue, Value *instanceDataValue)
921 {
922  StructType *nodeContextType = getNodeContextType(module);
923  Type *voidPointerType = nodeContextType->getElementType(2);
924 
925  const char *functionName = "vuoSetNodeContextInstanceData";
926  Function *function = module->getFunction(functionName);
927  if (! function)
928  {
929  PointerType *pointerToNodeContext = PointerType::get(nodeContextType, 0);
930 
931  vector<Type *> params;
932  params.push_back(pointerToNodeContext);
933  params.push_back(voidPointerType);
934  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
935  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
936  }
937 
938  Value *pointerToInstanceData = VuoCompilerCodeGenUtilities::generateMemoryAllocation(module, block, instanceDataValue->getType(), 1);
939  new StoreInst(instanceDataValue, pointerToInstanceData, false, block);
940  Value *pointerToInstanceDataAsVoidPointer = new BitCastInst(pointerToInstanceData, voidPointerType, "", block);
941 
942  vector<Value *> args;
943  args.push_back(nodeContextValue);
944  args.push_back(pointerToInstanceDataAsVoidPointer);
945  CallInst::Create(function, args, "", block);
946 }
947 
956 void VuoCompilerCodeGenUtilities::generateSetNodeContextClaimingEventId(Module *module, BasicBlock *block, Value *nodeContextValue, Value *claimingEventIdValue)
957 {
958  const char *functionName = "vuoSetNodeContextClaimingEventId";
959  Function *function = module->getFunction(functionName);
960  if (! function)
961  {
962  StructType *nodeContextType = getNodeContextType(module);
963  PointerType *pointerToNodeContext = PointerType::get(nodeContextType, 0);
964  Type *eventIdType = nodeContextType->getElementType(4);
965 
966  vector<Type *> params;
967  params.push_back(pointerToNodeContext);
968  params.push_back(eventIdType);
969  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
970  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
971  }
972 
973  vector<Value *> args;
974  args.push_back(nodeContextValue);
975  args.push_back(claimingEventIdValue);
976  CallInst::Create(function, args, "", block);
977 }
978 
988 void VuoCompilerCodeGenUtilities::generateSetNodeContextOutputEvent(Module *module, BasicBlock *block, Value *nodeContextValue, size_t index, Value *eventValue)
989 {
990  Type *sizeType = IntegerType::get(module->getContext(), 64);
991 
992  const char *functionName = "vuoSetNodeContextOutputEvent";
993  Function *function = module->getFunction(functionName);
994  if (! function)
995  {
996  StructType *nodeContextType = getNodeContextType(module);
997  PointerType *pointerToNodeContext = PointerType::get(nodeContextType, 0);
998  Type *boolType = IntegerType::get(module->getContext(), 64);
999 
1000  vector<Type *> params;
1001  params.push_back(pointerToNodeContext);
1002  params.push_back(sizeType);
1003  params.push_back(boolType);
1004  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
1005  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1006  }
1007 
1008  eventValue = new ZExtInst(eventValue, sizeType, "", block);
1009 
1010  vector<Value *> args;
1011  args.push_back(nodeContextValue);
1012  args.push_back(ConstantInt::get(sizeType, index));
1013  args.push_back(eventValue);
1014  CallInst::Create(function, args, "", block);
1015 }
1016 
1026 Value * VuoCompilerCodeGenUtilities::generateGetNodeContextPortContext(Module *module, BasicBlock *block, Value *nodeContextValue, int index)
1027 {
1028  Type *indexType = IntegerType::get(module->getContext(), 64);
1029 
1030  const char *functionName = "vuoGetNodeContextPortContext";
1031  Function *function = module->getFunction(functionName);
1032  if (! function)
1033  {
1034  StructType *nodeContextType = getNodeContextType(module);
1035  PointerType *pointerToNodeContext = PointerType::get(nodeContextType, 0);
1036  StructType *portContextType = getPortContextType(module);
1037  PointerType *pointerToPortContext = PointerType::get(portContextType, 0);
1038 
1039  vector<Type *> params;
1040  params.push_back(pointerToNodeContext);
1041  params.push_back(indexType);
1042 
1043  FunctionType *functionType = FunctionType::get(pointerToPortContext, params, false);
1044  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1045  }
1046 
1047  vector<Value *> args;
1048  args.push_back(nodeContextValue);
1049  args.push_back(ConstantInt::get(indexType, index));
1050  return CallInst::Create(function, args, "", block);
1051 }
1052 
1062 Value * VuoCompilerCodeGenUtilities::generateGetNodeContextInstanceData(Module *module, BasicBlock *block, Value *nodeContextValue, Type *instanceDataType)
1063 {
1064  Value *pointerToInstanceData = generateGetNodeContextInstanceDataVariable(module, block, nodeContextValue, instanceDataType);
1065  return new LoadInst(pointerToInstanceData, "", false, block);
1066 }
1067 
1077 Value * VuoCompilerCodeGenUtilities::generateGetNodeContextInstanceDataVariable(Module *module, BasicBlock *block, Value *nodeContextValue, Type *instanceDataType)
1078 {
1079  const char *functionName = "vuoGetNodeContextInstanceData";
1080  Function *function = module->getFunction(functionName);
1081  if (! function)
1082  {
1083  StructType *nodeContextType = getNodeContextType(module);
1084  PointerType *pointerToNodeContext = PointerType::get(nodeContextType, 0);
1085  Type *voidPointerType = nodeContextType->getElementType(2);
1086 
1087  FunctionType *functionType = FunctionType::get(voidPointerType, pointerToNodeContext, false);
1088  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1089  }
1090 
1091  Value *pointerToInstanceDataAsVoidPointer = CallInst::Create(function, nodeContextValue, "", block);
1092  return new BitCastInst(pointerToInstanceDataAsVoidPointer, PointerType::get(instanceDataType, 0), "", block);
1093 }
1094 
1103 Value * VuoCompilerCodeGenUtilities::generateGetNodeContextClaimingEventId(Module *module, BasicBlock *block, Value *nodeContextValue)
1104 {
1105  const char *functionName = "vuoGetNodeContextClaimingEventId";
1106  Function *function = module->getFunction(functionName);
1107  if (! function)
1108  {
1109  StructType *nodeContextType = getNodeContextType(module);
1110  PointerType *pointerToNodeContext = PointerType::get(nodeContextType, 0);
1111  Type *eventIdType = nodeContextType->getElementType(4);
1112 
1113  FunctionType *functionType = FunctionType::get(eventIdType, pointerToNodeContext, false);
1114  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1115  }
1116 
1117  return CallInst::Create(function, nodeContextValue, "", block);
1118 }
1119 
1128 Value * VuoCompilerCodeGenUtilities::generateGetNodeContextExecutingGroup(Module *module, BasicBlock *block, Value *nodeContextValue)
1129 {
1130  const char *functionName = "vuoGetNodeContextExecutingGroup";
1131  Function *function = module->getFunction(functionName);
1132  if (! function)
1133  {
1134  StructType *nodeContextType = getNodeContextType(module);
1135  PointerType *pointerToNodeContext = PointerType::get(nodeContextType, 0);
1136  Type *dispatchGroupType = nodeContextType->getElementType(5);
1137 
1138  FunctionType *functionType = FunctionType::get(dispatchGroupType, pointerToNodeContext, false);
1139  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1140  }
1141 
1142  return CallInst::Create(function, nodeContextValue, "", block);
1143 }
1144 
1154 Value * VuoCompilerCodeGenUtilities::generateGetNodeContextOutputEvent(Module *module, BasicBlock *block, Value *nodeContextValue, size_t index)
1155 {
1156  Type *sizeType = IntegerType::get(module->getContext(), 64);
1157 
1158  const char *functionName = "vuoGetNodeContextOutputEvent";
1159  Function *function = module->getFunction(functionName);
1160  if (! function)
1161  {
1162  StructType *nodeContextType = getNodeContextType(module);
1163  PointerType *pointerToNodeContext = PointerType::get(nodeContextType, 0);
1164  Type *boolType = IntegerType::get(module->getContext(), 64);
1165 
1166  vector<Type *> params;
1167  params.push_back(pointerToNodeContext);
1168  params.push_back(sizeType);
1169  FunctionType *functionType = FunctionType::get(boolType, params, false);
1170  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1171  }
1172 
1173  vector<Value *> args;
1174  args.push_back(nodeContextValue);
1175  args.push_back(ConstantInt::get(sizeType, index));
1176  Value *eventValue = CallInst::Create(function, args, "", block);
1177 
1178  return new TruncInst(eventValue, IntegerType::get(module->getContext(), 1), "", block);
1179 }
1180 
1188 void VuoCompilerCodeGenUtilities::generateResetNodeContextEvents(Module *module, BasicBlock *block, Value *nodeContextValue)
1189 {
1190  const char *functionName = "vuoResetNodeContextEvents";
1191  Function *function = module->getFunction(functionName);
1192  if (! function)
1193  {
1194  PointerType *pointerToNodeContextType = PointerType::get(getNodeContextType(module), 0);
1195 
1196  vector<Type *> params;
1197  params.push_back(pointerToNodeContextType);
1198 
1199  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
1200  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1201  }
1202 
1203  vector<Value *> args;
1204  args.push_back(nodeContextValue);
1205  CallInst::Create(function, args, "", block);
1206 }
1207 
1216 void VuoCompilerCodeGenUtilities::generateStartedExecutingEvent(Module *module, BasicBlock *block, Value *nodeContextValue, Value *eventIdValue)
1217 {
1218  const char *functionName = "vuoStartedExecutingEvent";
1219  Function *function = module->getFunction(functionName);
1220  if (! function)
1221  {
1222  PointerType *pointerToNodeContextType = PointerType::get(getNodeContextType(module), 0);
1223  Type *eventIdType = generateNoEventIdConstant(module)->getType();
1224 
1225  vector<Type *> params;
1226  params.push_back(pointerToNodeContextType);
1227  params.push_back(eventIdType);
1228 
1229  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
1230  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1231  }
1232 
1233  vector<Value *> args;
1234  args.push_back(nodeContextValue);
1235  args.push_back(eventIdValue);
1236  CallInst::Create(function, args, "", block);
1237 }
1238 
1247 void VuoCompilerCodeGenUtilities::generateSpunOffExecutingEvent(Module *module, BasicBlock *block, Value *nodeContextValue, Value *eventIdValue)
1248 {
1249  const char *functionName = "vuoSpunOffExecutingEvent";
1250  Function *function = module->getFunction(functionName);
1251  if (! function)
1252  {
1253  PointerType *pointerToNodeContextType = PointerType::get(getNodeContextType(module), 0);
1254  Type *eventIdType = generateNoEventIdConstant(module)->getType();
1255 
1256  vector<Type *> params;
1257  params.push_back(pointerToNodeContextType);
1258  params.push_back(eventIdType);
1259 
1260  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
1261  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1262  }
1263 
1264  vector<Value *> args;
1265  args.push_back(nodeContextValue);
1266  args.push_back(eventIdValue);
1267  CallInst::Create(function, args, "", block);
1268 }
1269 
1279 Value * VuoCompilerCodeGenUtilities::generateFinishedExecutingEvent(Module *module, BasicBlock *block, Value *nodeContextValue, Value *eventIdValue)
1280 {
1281  const char *functionName = "vuoFinishedExecutingEvent";
1282  Function *function = module->getFunction(functionName);
1283  if (! function)
1284  {
1285  PointerType *pointerToNodeContextType = PointerType::get(getNodeContextType(module), 0);
1286  Type *eventIdType = generateNoEventIdConstant(module)->getType();
1287  Type *boolType = IntegerType::get(module->getContext(), 64);
1288 
1289  vector<Type *> params;
1290  params.push_back(pointerToNodeContextType);
1291  params.push_back(eventIdType);
1292 
1293  FunctionType *functionType = FunctionType::get(boolType, params, false);
1294  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1295  }
1296 
1297  vector<Value *> args;
1298  args.push_back(nodeContextValue);
1299  args.push_back(eventIdValue);
1300  return CallInst::Create(function, args, "", block);
1301 }
1302 
1311 Value * VuoCompilerCodeGenUtilities::generateGetOneExecutingEvent(Module *module, BasicBlock *block, Value *nodeContextValue)
1312 {
1313  const char *functionName = "vuoGetOneExecutingEvent";
1314  Function *function = module->getFunction(functionName);
1315  if (! function)
1316  {
1317  PointerType *pointerToNodeContextType = PointerType::get(getNodeContextType(module), 0);
1318  Type *eventIdType = generateNoEventIdConstant(module)->getType();
1319 
1320  vector<Type *> params;
1321  params.push_back(pointerToNodeContextType);
1322 
1323  FunctionType *functionType = FunctionType::get(eventIdType, params, false);
1324  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1325  }
1326 
1327  vector<Value *> args;
1328  args.push_back(nodeContextValue);
1329  return CallInst::Create(function, args, "", block);
1330 }
1331 
1335 Value * VuoCompilerCodeGenUtilities::generateCreateCompositionState(Module *module, BasicBlock *block, Value *runtimeStateValue, Value *compositionIdentifierValue)
1336 {
1337  const char *functionName = "vuoCreateCompositionState";
1338  Function *function = module->getFunction(functionName);
1339  if (! function)
1340  {
1341  PointerType *pointerToChar = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
1342  PointerType *voidPointer = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
1343  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
1344 
1345  vector<Type *> params;
1346  params.push_back(voidPointer);
1347  params.push_back(pointerToChar);
1348 
1349  FunctionType *functionType = FunctionType::get(pointerToCompositionState, params, false);
1350  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1351  }
1352 
1353  vector<Value *> args;
1354  args.push_back(runtimeStateValue);
1355  args.push_back(compositionIdentifierValue);
1356  return CallInst::Create(function, args, "", block);
1357 }
1358 
1362 Value * VuoCompilerCodeGenUtilities::generateGetCompositionStateRuntimeState(Module *module, BasicBlock *block, Value *compositionStateValue)
1363 {
1364  const char *functionName = "vuoGetCompositionStateRuntimeState";
1365  Function *function = module->getFunction(functionName);
1366  if (! function)
1367  {
1368  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
1369  PointerType *voidPointer = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
1370 
1371  vector<Type *> params;
1372  params.push_back(pointerToCompositionState);
1373 
1374  FunctionType *functionType = FunctionType::get(voidPointer, params, false);
1375  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1376  }
1377 
1378  vector<Value *> args;
1379  args.push_back(compositionStateValue);
1380  return CallInst::Create(function, args, "", block);
1381 }
1382 
1386 Value * VuoCompilerCodeGenUtilities::generateGetCompositionStateCompositionIdentifier(Module *module, BasicBlock *block, Value *compositionStateValue)
1387 {
1388  const char *functionName = "vuoGetCompositionStateCompositionIdentifier";
1389  Function *function = module->getFunction(functionName);
1390  if (! function)
1391  {
1392  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
1393  PointerType *pointerToChar = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
1394 
1395  vector<Type *> params;
1396  params.push_back(pointerToCompositionState);
1397 
1398  FunctionType *functionType = FunctionType::get(pointerToChar, params, false);
1399  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1400  }
1401 
1402  vector<Value *> args;
1403  args.push_back(compositionStateValue);
1404  return CallInst::Create(function, args, "", block);
1405 }
1406 
1410 void VuoCompilerCodeGenUtilities::generateFreeCompositionState(Module *module, BasicBlock *block, Value *compositionStateValue)
1411 {
1412  const char *functionName = "vuoFreeCompositionState";
1413  Function *function = module->getFunction(functionName);
1414  if (! function)
1415  {
1416  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
1417 
1418  vector<Type *> params;
1419  params.push_back(pointerToCompositionState);
1420 
1421  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
1422  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1423  }
1424 
1425  vector<Value *> args;
1426  args.push_back(compositionStateValue);
1427  CallInst::Create(function, args, "", block);
1428 }
1429 
1433 Value * VuoCompilerCodeGenUtilities::generateGetDataForPort(Module *module, BasicBlock *block,
1434  Value *compositionStateValue, Value *portIdentifierValue)
1435 {
1436  const char *functionName = "vuoGetDataForPort";
1437  Function *function = module->getFunction(functionName);
1438  if (! function)
1439  {
1440  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
1441  PointerType *voidPointerType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
1442 
1443  vector<Type *> params;
1444  params.push_back(compositionStateValue->getType());
1445  params.push_back(pointerToCharType);
1446 
1447  FunctionType *functionType = FunctionType::get(voidPointerType, params, false);
1448  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1449  }
1450 
1451  vector<Value *> args;
1452  args.push_back(compositionStateValue);
1453  args.push_back(portIdentifierValue);
1454  return CallInst::Create(function, args, "", block);
1455 }
1456 
1460 Value * VuoCompilerCodeGenUtilities::generateGetNodeIndexForPort(Module *module, BasicBlock *block,
1461  Value *compositionStateValue, Value *portIdentifierValue)
1462 {
1463  const char *functionName = "vuoGetNodeIndexForPort";
1464  Function *function = module->getFunction(functionName);
1465  if (! function)
1466  {
1467  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
1468  Type *unsignedLongType = IntegerType::get(module->getContext(), 64);
1469 
1470  vector<Type *> params;
1471  params.push_back(compositionStateValue->getType());
1472  params.push_back(pointerToCharType);
1473 
1474  FunctionType *functionType = FunctionType::get(unsignedLongType, params, false);
1475  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1476  }
1477 
1478  vector<Value *> args;
1479  args.push_back(compositionStateValue);
1480  args.push_back(portIdentifierValue);
1481  return CallInst::Create(function, args, "", block);
1482 }
1483 
1487 Value * VuoCompilerCodeGenUtilities::generateGetTypeIndexForPort(Module *module, BasicBlock *block,
1488  Value *compositionStateValue, Value *portIdentifierValue)
1489 {
1490  const char *functionName = "vuoGetTypeIndexForPort";
1491  Function *function = module->getFunction(functionName);
1492  if (! function)
1493  {
1494  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
1495  Type *unsignedLongType = IntegerType::get(module->getContext(), 64);
1496 
1497  vector<Type *> params;
1498  params.push_back(compositionStateValue->getType());
1499  params.push_back(pointerToCharType);
1500 
1501  FunctionType *functionType = FunctionType::get(unsignedLongType, params, false);
1502  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1503  }
1504 
1505  vector<Value *> args;
1506  args.push_back(compositionStateValue);
1507  args.push_back(portIdentifierValue);
1508  return CallInst::Create(function, args, "", block);
1509 }
1510 
1514 void VuoCompilerCodeGenUtilities::generateScheduleTriggerWorker(Module *module, BasicBlock *block,
1515  Value *queueValue, Value *contextValue, Value *workerFunctionValue,
1516  int minThreadsNeeded, int maxThreadsNeeded,
1517  Value *eventIdValue, Value *compositionStateValue,
1518  int chainCount)
1519 {
1520  Type *intType = IntegerType::get(module->getContext(), 64);
1521 
1522  const char *functionName = "vuoScheduleTriggerWorker";
1523  Function *function = module->getFunction(functionName);
1524  if (! function)
1525  {
1526  Type *dispatchQueueType = getDispatchQueueType(module);
1527  PointerType *voidPointerType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
1528  Type *workerFunctionType = workerFunctionValue->getType();
1529  Type *eventIdType = generateNoEventIdConstant(module)->getType();
1530 
1531  vector<Type *> params;
1532  params.push_back(compositionStateValue->getType());
1533  params.push_back(dispatchQueueType);
1534  params.push_back(voidPointerType);
1535  params.push_back(workerFunctionType);
1536  params.push_back(intType);
1537  params.push_back(intType);
1538  params.push_back(eventIdType);
1539  params.push_back(intType);
1540 
1541  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
1542  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1543  }
1544 
1545  Value *minThreadsNeededValue = ConstantInt::get(intType, minThreadsNeeded);
1546  Value *maxThreadsNeededValue = ConstantInt::get(intType, maxThreadsNeeded);
1547  Value *chainCountValue = ConstantInt::get(intType, chainCount);
1548 
1549  vector<Value *> args;
1550  args.push_back(compositionStateValue);
1551  args.push_back(queueValue);
1552  args.push_back(contextValue);
1553  args.push_back(workerFunctionValue);
1554  args.push_back(minThreadsNeededValue);
1555  args.push_back(maxThreadsNeededValue);
1556  args.push_back(eventIdValue);
1557  args.push_back(chainCountValue);
1558  CallInst::Create(function, args, "", block);
1559 }
1560 
1564 void VuoCompilerCodeGenUtilities::generateScheduleChainWorker(Module *module, BasicBlock *block,
1565  Value *queueValue, Value *contextValue, Value *workerFunctionValue,
1566  int minThreadsNeeded, int maxThreadsNeeded,
1567  Value *eventIdValue, Value *compositionStateValue,
1568  size_t chainIndex, vector<size_t> upstreamChainIndices)
1569 {
1570  Type *intType = IntegerType::get(module->getContext(), 64);
1571  Type *eventIdType = generateNoEventIdConstant(module)->getType();
1572 
1573  const char *functionName = "vuoScheduleChainWorker";
1574  Function *function = module->getFunction(functionName);
1575  if (! function)
1576  {
1577  Type *dispatchQueueType = getDispatchQueueType(module);
1578  PointerType *voidPointerType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
1579  Type *workerFunctionType = workerFunctionValue->getType();
1580  PointerType *unsignedLongPointerType = PointerType::get(eventIdType, 0);
1581 
1582  vector<Type *> params;
1583  params.push_back(compositionStateValue->getType());
1584  params.push_back(dispatchQueueType);
1585  params.push_back(voidPointerType);
1586  params.push_back(workerFunctionType);
1587  params.push_back(intType);
1588  params.push_back(intType);
1589  params.push_back(eventIdType);
1590  params.push_back(eventIdType);
1591  params.push_back(unsignedLongPointerType);
1592  params.push_back(intType);
1593 
1594  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
1595  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1596  }
1597 
1598  Value *minThreadsNeededValue = ConstantInt::get(intType, minThreadsNeeded);
1599  Value *maxThreadsNeededValue = ConstantInt::get(intType, maxThreadsNeeded);
1600  Value *chainIndexValue = ConstantInt::get(eventIdType, chainIndex);
1601 
1602  Value *upstreamChainIndicesCountValue = ConstantInt::get(intType, (int)upstreamChainIndices.size());
1603  Value *upstreamChainIndicesValue = generateMemoryAllocation(module, block, eventIdType, upstreamChainIndices.size());
1604  for (size_t i = 0; i < upstreamChainIndices.size(); ++i)
1605  {
1606  Value *upstreamChainIndexValue = ConstantInt::get(eventIdType, upstreamChainIndices[i]);
1607  generateSetArrayElement(module, block, upstreamChainIndicesValue, i, upstreamChainIndexValue);
1608  }
1609 
1610  vector<Value *> args;
1611  args.push_back(compositionStateValue);
1612  args.push_back(queueValue);
1613  args.push_back(contextValue);
1614  args.push_back(workerFunctionValue);
1615  args.push_back(minThreadsNeededValue);
1616  args.push_back(maxThreadsNeededValue);
1617  args.push_back(eventIdValue);
1618  args.push_back(chainIndexValue);
1619  args.push_back(upstreamChainIndicesValue);
1620  args.push_back(upstreamChainIndicesCountValue);
1621  CallInst::Create(function, args, "", block);
1622 }
1623 
1627 void VuoCompilerCodeGenUtilities::generateGrantThreadsToChain(Module *module, BasicBlock *block,
1628  int minThreadsNeeded, int maxThreadsNeeded,
1629  Value *eventIdValue, Value *compositionStateValue,
1630  size_t chainIndex)
1631 {
1632  Type *intType = IntegerType::get(module->getContext(), 64);
1633  Type *eventIdType = generateNoEventIdConstant(module)->getType();
1634 
1635  const char *functionName = "vuoGrantThreadsToChain";
1636  Function *function = module->getFunction(functionName);
1637  if (! function)
1638  {
1639  vector<Type *> params;
1640  params.push_back(compositionStateValue->getType());
1641  params.push_back(intType);
1642  params.push_back(intType);
1643  params.push_back(eventIdType);
1644  params.push_back(eventIdType);
1645 
1646  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
1647  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1648  }
1649 
1650  Value *minThreadsNeededValue = ConstantInt::get(intType, minThreadsNeeded);
1651  Value *maxThreadsNeededValue = ConstantInt::get(intType, maxThreadsNeeded);
1652  Value *chainIndexValue = ConstantInt::get(eventIdType, chainIndex);
1653 
1654  vector<Value *> args;
1655  args.push_back(compositionStateValue);
1656  args.push_back(minThreadsNeededValue);
1657  args.push_back(maxThreadsNeededValue);
1658  args.push_back(eventIdValue);
1659  args.push_back(chainIndexValue);
1660  CallInst::Create(function, args, "", block);
1661 }
1662 
1667  Value *eventIdValue, Value *compositionStateValue,
1668  Value *chainIndexValue, Value *subcompositionIdentifierValue)
1669 {
1670  const char *functionName = "vuoGrantThreadsToSubcomposition";
1671  Function *function = module->getFunction(functionName);
1672  if (! function)
1673  {
1674  Type *eventIdType = generateNoEventIdConstant(module)->getType();
1675  PointerType *charPointerType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
1676 
1677  vector<Type *> params;
1678  params.push_back(compositionStateValue->getType());
1679  params.push_back(eventIdType);
1680  params.push_back(eventIdType);
1681  params.push_back(charPointerType);
1682 
1683  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
1684  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1685  }
1686 
1687  vector<Value *> args;
1688  args.push_back(compositionStateValue);
1689  args.push_back(eventIdValue);
1690  args.push_back(chainIndexValue);
1691  args.push_back(subcompositionIdentifierValue);
1692  CallInst::Create(function, args, "", block);
1693 }
1694 
1699  Value *eventIdValue, Value *compositionStateValue)
1700 {
1701  const char *functionName = "vuoReturnThreadsForTriggerWorker";
1702  Function *function = module->getFunction(functionName);
1703  if (! function)
1704  {
1705  Type *eventIdType = generateNoEventIdConstant(module)->getType();
1706 
1707  vector<Type *> params;
1708  params.push_back(compositionStateValue->getType());
1709  params.push_back(eventIdType);
1710 
1711  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
1712  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1713  }
1714 
1715  vector<Value *> args;
1716  args.push_back(compositionStateValue);
1717  args.push_back(eventIdValue);
1718  CallInst::Create(function, args, "", block);
1719 }
1720 
1725  Value *eventIdValue, Value *compositionStateValue,
1726  Value *chainIndexValue)
1727 {
1728  const char *functionName = "vuoReturnThreadsForChainWorker";
1729  Function *function = module->getFunction(functionName);
1730  if (! function)
1731  {
1732  Type *eventIdType = generateNoEventIdConstant(module)->getType();
1733 
1734  vector<Type *> params;
1735  params.push_back(compositionStateValue->getType());
1736  params.push_back(eventIdType);
1737  params.push_back(eventIdType);
1738 
1739  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
1740  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1741  }
1742 
1743  vector<Value *> args;
1744  args.push_back(compositionStateValue);
1745  args.push_back(eventIdValue);
1746  args.push_back(chainIndexValue);
1747  CallInst::Create(function, args, "", block);
1748 }
1749 
1753 void VuoCompilerCodeGenUtilities::generateLockNodes(Module *module, BasicBlock *&block,
1754  Value *compositionStateValue, const vector<size_t> &nodeIndices, Value *eventIdValue,
1755  VuoCompilerConstantsCache *constantsCache)
1756 {
1757  string functionName = "vuoLockNodes";
1758  Function *function = module->getFunction(functionName.c_str());
1759  if (! function)
1760  {
1761  StructType *compositionStateType = getCompositionStateType(module);
1762  PointerType *pointerToCompositionState = PointerType::get(compositionStateType, 0);
1763  IntegerType *unsignedLongType = IntegerType::get(module->getContext(), 64);
1764  PointerType *pointerToUnsignedLong = PointerType::get(unsignedLongType, 0);
1765 
1766  vector<Type *> params;
1767  params.push_back(pointerToCompositionState);
1768  params.push_back(pointerToUnsignedLong);
1769  params.push_back(unsignedLongType);
1770  params.push_back(unsignedLongType);
1771  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
1772  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1773  }
1774 
1775  Constant *nodeCountValue = ConstantInt::get(module->getContext(), APInt(64, nodeIndices.size()));
1776  Constant *nodeIndicesValue = constantsCache->get(nodeIndices);
1777 
1778  vector<Value *> args;
1779  args.push_back(compositionStateValue);
1780  args.push_back(nodeIndicesValue);
1781  args.push_back(nodeCountValue);
1782  args.push_back(eventIdValue);
1783  CallInst::Create(function, args, "", block);
1784 }
1785 
1789 void VuoCompilerCodeGenUtilities::generateLockNode(Module *module, BasicBlock *&block,
1790  Value *compositionStateValue, size_t nodeIndex, Value *eventIdValue)
1791 {
1792  Constant *nodeIndexValue = ConstantInt::get(module->getContext(), APInt(64, nodeIndex));
1793  generateLockNode(module, block, compositionStateValue, nodeIndexValue, eventIdValue);
1794 }
1795 
1799 void VuoCompilerCodeGenUtilities::generateLockNode(Module *module, BasicBlock *&block,
1800  Value *compositionStateValue, Value *nodeIndexValue, Value *eventIdValue)
1801 {
1802  string functionName = "vuoLockNode";
1803  Function *function = module->getFunction(functionName.c_str());
1804  if (! function)
1805  {
1806  StructType *compositionStateType = getCompositionStateType(module);
1807  PointerType *pointerToCompositionState = PointerType::get(compositionStateType, 0);
1808  IntegerType *unsignedLongType = IntegerType::get(module->getContext(), 64);
1809 
1810  vector<Type *> params;
1811  params.push_back(pointerToCompositionState);
1812  params.push_back(unsignedLongType);
1813  params.push_back(unsignedLongType);
1814  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
1815  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1816  }
1817 
1818  vector<Value *> args;
1819  args.push_back(compositionStateValue);
1820  args.push_back(nodeIndexValue);
1821  args.push_back(eventIdValue);
1822  CallInst::Create(function, args, "", block);
1823 }
1824 
1828 void VuoCompilerCodeGenUtilities::generateUnlockNodes(Module *module, BasicBlock *block,
1829  Value *compositionStateValue, const vector<size_t> &nodeIndices,
1830  VuoCompilerConstantsCache *constantsCache)
1831 {
1832  string functionName = "vuoUnlockNodes";
1833  Function *function = module->getFunction(functionName.c_str());
1834  if (! function)
1835  {
1836  StructType *compositionStateType = getCompositionStateType(module);
1837  PointerType *pointerToCompositionState = PointerType::get(compositionStateType, 0);
1838  IntegerType *unsignedLongType = IntegerType::get(module->getContext(), 64);
1839  PointerType *pointerToUnsignedLong = PointerType::get(unsignedLongType, 0);
1840 
1841  vector<Type *> params;
1842  params.push_back(pointerToCompositionState);
1843  params.push_back(pointerToUnsignedLong);
1844  params.push_back(unsignedLongType);
1845  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
1846  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1847  }
1848 
1849  Constant *nodeCountValue = ConstantInt::get(module->getContext(), APInt(64, nodeIndices.size()));
1850  Constant *nodeIndicesValue = constantsCache->get(nodeIndices);
1851 
1852  vector<Value *> args;
1853  args.push_back(compositionStateValue);
1854  args.push_back(nodeIndicesValue);
1855  args.push_back(nodeCountValue);
1856  CallInst::Create(function, args, "", block);
1857 }
1858 
1862 void VuoCompilerCodeGenUtilities::generateUnlockNode(Module *module, BasicBlock *block,
1863  Value *compositionStateValue, size_t nodeIndex)
1864 {
1865  Constant *nodeIndexValue = ConstantInt::get(module->getContext(), APInt(64, nodeIndex));
1866  generateUnlockNode(module, block, compositionStateValue, nodeIndexValue);
1867 }
1868 
1872 void VuoCompilerCodeGenUtilities::generateUnlockNode(Module *module, BasicBlock *block,
1873  Value *compositionStateValue, Value *nodeIndexValue)
1874 {
1875  string functionName = "vuoUnlockNode";
1876  Function *function = module->getFunction(functionName.c_str());
1877  if (! function)
1878  {
1879  StructType *compositionStateType = getCompositionStateType(module);
1880  PointerType *pointerToCompositionState = PointerType::get(compositionStateType, 0);
1881  IntegerType *unsignedLongType = IntegerType::get(module->getContext(), 64);
1882 
1883  vector<Type *> params;
1884  params.push_back(pointerToCompositionState);
1885  params.push_back(unsignedLongType);
1886  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
1887  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1888  }
1889 
1890  vector<Value *> args;
1891  args.push_back(compositionStateValue);
1892  args.push_back(nodeIndexValue);
1893  CallInst::Create(function, args, "", block);
1894 }
1895 
1899 void VuoCompilerCodeGenUtilities::generateSetArrayElement(Module *module, BasicBlock *block, Value *arrayValue, size_t elementIndex, Value *value)
1900 {
1901  Value *memberPointer = generateGetArrayElementVariable(module, block, arrayValue, elementIndex);
1902  new StoreInst(value, memberPointer, false, block);
1903 }
1904 
1908 Value * VuoCompilerCodeGenUtilities::generateGetArrayElement(Module *module, BasicBlock *block, Value *arrayValue, size_t elementIndex)
1909 {
1910  Value *memberPointer = generateGetArrayElementVariable(module, block, arrayValue, elementIndex);
1911  return new LoadInst(memberPointer, "", block);
1912 }
1913 
1917 Value * VuoCompilerCodeGenUtilities::generateGetArrayElement(Module *module, BasicBlock *block, Value *arrayValue, Value *elementIndexValue)
1918 {
1919  Value *memberPointer = generateGetArrayElementVariable(module, block, arrayValue, elementIndexValue);
1920  return new LoadInst(memberPointer, "", block);
1921 }
1922 
1926 Value * VuoCompilerCodeGenUtilities::generateGetArrayElementVariable(Module *module, BasicBlock *block, Value *arrayValue, size_t elementIndex)
1927 {
1928  ConstantInt *indexValue = ConstantInt::get(module->getContext(), APInt(32, elementIndex));
1929  return generateGetArrayElementVariable(module, block, arrayValue, indexValue);
1930 }
1931 
1935 Value * VuoCompilerCodeGenUtilities::generateGetArrayElementVariable(Module *module, BasicBlock *block, Value *arrayValue, Value *elementIndexValue)
1936 {
1937  return GetElementPtrInst::Create(arrayValue, elementIndexValue, "", block);
1938 }
1939 
1943 void VuoCompilerCodeGenUtilities::generateSetStructPointerElement(Module *module, BasicBlock *block, Value *structPointer, size_t elementIndex, Value *value)
1944 {
1945  Value *memberPointer = generateGetStructPointerElementVariable(module, block, structPointer, elementIndex);
1946  new StoreInst(value, memberPointer, false, block);
1947 }
1948 
1952 Value * VuoCompilerCodeGenUtilities::generateGetStructPointerElement(Module *module, BasicBlock *block, Value *structPointer, size_t elementIndex)
1953 {
1954  Value *memberPointer = generateGetStructPointerElementVariable(module, block, structPointer, elementIndex);
1955  return new LoadInst(memberPointer, "", block);
1956 }
1957 
1961 Value * VuoCompilerCodeGenUtilities::generateGetStructPointerElementVariable(Module *module, BasicBlock *block, Value *structPointer, size_t elementIndex)
1962 {
1963  ConstantInt *zeroValue = ConstantInt::get(module->getContext(), APInt(32, 0));
1964  ConstantInt *indexValue = ConstantInt::get(module->getContext(), APInt(32, elementIndex));
1965 
1966  vector<Value *> memberIndices;
1967  memberIndices.push_back(zeroValue);
1968  memberIndices.push_back(indexValue);
1969  return GetElementPtrInst::Create(structPointer, memberIndices, "", block);
1970 }
1971 
1975 Value * VuoCompilerCodeGenUtilities::generatePointerToValue(BasicBlock *block, Value *value)
1976 {
1977  AllocaInst *variable = new AllocaInst(value->getType(), "", block);
1978  new StoreInst(value, variable, false, block);
1979  return variable;
1980 }
1981 
1990 Constant * VuoCompilerCodeGenUtilities::generatePointerToConstantString(Module *module, string stringValue, string globalVariableName)
1991 {
1992  Constant *array = ConstantDataArray::getString(module->getContext(), stringValue);
1993  ArrayType *arrayType = ArrayType::get(IntegerType::get(module->getContext(), 8), stringValue.length() + 1);
1994  GlobalVariable *global = new GlobalVariable(*module, arrayType, true, GlobalValue::InternalLinkage, 0, "");
1995  global->setInitializer(array);
1996  global->setName(globalVariableName);
1997 
1998  ConstantInt *zeroValue = ConstantInt::get(module->getContext(), APInt(32, 0));
1999  vector<Constant *> pointerIndices;
2000  pointerIndices.push_back(zeroValue);
2001  pointerIndices.push_back(zeroValue);
2002  Constant *pointer = ConstantExpr::getGetElementPtr(global, pointerIndices);
2003 
2004  return pointer;
2005 }
2006 
2015 Constant * VuoCompilerCodeGenUtilities::generatePointerToConstantArrayOfStrings(Module *module, vector<string> stringValues, string globalVariableName)
2016 {
2017  vector<Constant *> arrayElements;
2018  for (vector<string>::iterator i = stringValues.begin(); i != stringValues.end(); ++i)
2019  {
2020  Constant *stringPointer = generatePointerToConstantString(module, *i, ".str");
2021  arrayElements.push_back(stringPointer);
2022  }
2023 
2024  ArrayType *arrayType = ArrayType::get(PointerType::get(IntegerType::get(module->getContext(), 8), 0), arrayElements.size());
2025  GlobalVariable *global = new GlobalVariable(*module, arrayType, false, GlobalValue::ExternalLinkage, 0, globalVariableName);
2026  Constant *arrayConstant = ConstantArray::get(arrayType, arrayElements);
2027  global->setInitializer(arrayConstant);
2028 
2029  ConstantInt *zeroi64Constant = ConstantInt::get(module->getContext(), APInt(64, 0));
2030  vector<Constant *> pointerIndices;
2031  pointerIndices.push_back(zeroi64Constant);
2032  pointerIndices.push_back(zeroi64Constant);
2033  Constant *pointer = ConstantExpr::getGetElementPtr(global, pointerIndices);
2034 
2035  return pointer;
2036 }
2037 
2046 Constant * VuoCompilerCodeGenUtilities::generatePointerToConstantArrayOfUnsignedLongs(Module *module, const vector<unsigned long> &values, string globalVariableName)
2047 {
2048  vector<Constant *> arrayElements;
2049  for (unsigned long value : values)
2050  {
2051  Constant *valueConstant = ConstantInt::get(module->getContext(), APInt(64, value));
2052  arrayElements.push_back(valueConstant);
2053  }
2054 
2055  ArrayType *arrayType = ArrayType::get(IntegerType::get(module->getContext(), 64), arrayElements.size());
2056  GlobalVariable *global = new GlobalVariable(*module, arrayType, false, GlobalValue::ExternalLinkage, 0, globalVariableName);
2057  Constant *arrayConstant = ConstantArray::get(arrayType, arrayElements);
2058  global->setInitializer(arrayConstant);
2059 
2060  ConstantInt *zeroi64Constant = ConstantInt::get(module->getContext(), APInt(64, 0));
2061  vector<Constant *> pointerIndices;
2062  pointerIndices.push_back(zeroi64Constant);
2063  pointerIndices.push_back(zeroi64Constant);
2064  Constant *pointer = ConstantExpr::getGetElementPtr(global, pointerIndices);
2065 
2066  return pointer;
2067 }
2068 
2093 void VuoCompilerCodeGenUtilities::generateStringMatchingCode(Module *module, Function *function,
2094  BasicBlock *initialBlock, BasicBlock *finalBlock, Value *inputStringValue,
2095  map<string, pair<BasicBlock *, BasicBlock *> > blocksForString,
2096  VuoCompilerConstantsCache *constantsCache)
2097 {
2098  Function *strcmpFunction = getStrcmpFunction(module);
2099  BasicBlock *currentBlock = initialBlock;
2100 
2101  for (map<string, pair<BasicBlock *, BasicBlock *> >::iterator i = blocksForString.begin(); i != blocksForString.end(); ++i)
2102  {
2103  string currentString = i->first;
2104  BasicBlock *firstTrueBlock = i->second.first;
2105  BasicBlock *lastTrueBlock = i->second.second;
2106 
2107  Constant *currentStringValue = constantsCache->get(currentString);
2108 
2109  vector<Value *> strcmpArgs;
2110  strcmpArgs.push_back(inputStringValue);
2111  strcmpArgs.push_back(currentStringValue);
2112  CallInst *strcmpCall = CallInst::Create(strcmpFunction, strcmpArgs, "", currentBlock);
2113 
2114  ConstantInt *zeroValue = ConstantInt::get(module->getContext(), APInt(32, 0));
2115  ICmpInst *strcmpEqualsZero = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, strcmpCall, zeroValue, "");
2116  BasicBlock *falseBlock = BasicBlock::Create(module->getContext(), string("strcmp-") + currentString, function, 0);
2117  BranchInst::Create(firstTrueBlock, falseBlock, strcmpEqualsZero, currentBlock);
2118 
2119  BranchInst::Create(finalBlock, lastTrueBlock);
2120 
2121  currentBlock = falseBlock;
2122  }
2123 
2124  BranchInst::Create(finalBlock, currentBlock);
2125 }
2126 
2150 void VuoCompilerCodeGenUtilities::generateIndexMatchingCode(Module *module, Function *function,
2151  BasicBlock *initialBlock, BasicBlock *finalBlock, Value *inputIndexValue,
2152  vector< pair<BasicBlock *, BasicBlock *> > blocksForIndex)
2153 {
2154  BasicBlock *currentBlock = initialBlock;
2155 
2156  for (size_t i = 0; i < blocksForIndex.size(); ++i)
2157  {
2158  BasicBlock *firstTrueBlock = blocksForIndex[i].first;
2159  BasicBlock *lastTrueBlock = blocksForIndex[i].second;
2160 
2161  Constant *currentIndexValue = ConstantInt::get(inputIndexValue->getType(), i);
2162  ICmpInst *indexEqualsCurrent = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, inputIndexValue, currentIndexValue, "");
2163  BasicBlock *falseBlock = BasicBlock::Create(module->getContext(), "", function, 0);
2164  BranchInst::Create(firstTrueBlock, falseBlock, indexEqualsCurrent, currentBlock);
2165 
2166  BranchInst::Create(finalBlock, lastTrueBlock);
2167 
2168  currentBlock = falseBlock;
2169  }
2170 
2171  BranchInst::Create(finalBlock, currentBlock);
2172 }
2173 
2185 Value * VuoCompilerCodeGenUtilities::generateFormattedString(Module *module, BasicBlock *block, string formatString, vector<Value *> replacementValues,
2186  VuoCompilerConstantsCache *constantsCache)
2187 {
2188  Function *snprintfFunction = getSnprintfFunction(module);
2189 
2190  Type *charType = IntegerType::get(module->getContext(), 8);
2191  PointerType *pointerToCharType = PointerType::get(charType, 0);
2192  ConstantPointerNull *nullValue = ConstantPointerNull::get(pointerToCharType);
2193  ConstantInt *zeroValue64 = ConstantInt::get(module->getContext(), APInt(64, 0));
2194  ConstantInt *oneValue64 = ConstantInt::get(module->getContext(), APInt(64, 1));
2195 
2196  // int bufferLength = snprintf(NULL, 0, format, ...) + 1;
2197  Constant *formatStringValue = constantsCache->get(formatString);
2198  vector<Value *> snprintfArgs;
2199  snprintfArgs.push_back(nullValue);
2200  snprintfArgs.push_back(zeroValue64);
2201  snprintfArgs.push_back(formatStringValue);
2202  for (vector<Value *>::iterator i = replacementValues.begin(); i != replacementValues.end(); ++i)
2203  snprintfArgs.push_back(*i);
2204  Value *bufferLengthValue32 = CallInst::Create(snprintfFunction, snprintfArgs, "", block);
2205  Value *bufferLengthValue = new SExtInst(bufferLengthValue32, IntegerType::get(module->getContext(), 64), "", block);
2206  bufferLengthValue = BinaryOperator::Create(Instruction::Add, bufferLengthValue, oneValue64, "", block);
2207 
2208  // char *buffer = malloc(bufferLength);
2209  AllocaInst *bufferVariable = new AllocaInst(pointerToCharType, "buffer", block);
2210  Value *bufferValue = generateMemoryAllocation(module, block, charType, bufferLengthValue);
2211  new StoreInst(bufferValue, bufferVariable, false, block);
2212 
2213  // snprintf(buffer, bufferLength, format, ...);
2214  snprintfArgs[0] = bufferValue;
2215  snprintfArgs[1] = bufferLengthValue;
2216  CallInst::Create(snprintfFunction, snprintfArgs, "", block);
2217  return bufferValue;
2218 }
2219 
2230 Value * VuoCompilerCodeGenUtilities::generateStringConcatenation(Module *module, BasicBlock *block, vector<Value *> stringsToConcatenate,
2231  VuoCompilerConstantsCache *constantsCache)
2232 {
2233  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2234 
2235  if (stringsToConcatenate.empty())
2236  {
2237  return constantsCache->get("");
2238  }
2239  else if (stringsToConcatenate.size() == 2)
2240  {
2241  const char *functionName = "vuoConcatenateStrings2";
2242  Function *function = module->getFunction(functionName);
2243  if (! function)
2244  {
2245  vector<Type *> params;
2246  params.push_back(pointerToCharType);
2247  params.push_back(pointerToCharType);
2248 
2249  FunctionType *functionType = FunctionType::get(pointerToCharType, params, false);
2250  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
2251  }
2252 
2253  vector<Value *> args;
2254  args.push_back(stringsToConcatenate[0]);
2255  args.push_back(stringsToConcatenate[1]);
2256  return CallInst::Create(function, args, "", block);
2257  }
2258  else if (stringsToConcatenate.size() == 3)
2259  {
2260  const char *functionName = "vuoConcatenateStrings3";
2261  Function *function = module->getFunction(functionName);
2262  if (! function)
2263  {
2264  vector<Type *> params;
2265  params.push_back(pointerToCharType);
2266  params.push_back(pointerToCharType);
2267  params.push_back(pointerToCharType);
2268 
2269  FunctionType *functionType = FunctionType::get(pointerToCharType, params, false);
2270  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
2271  }
2272 
2273  vector<Value *> args;
2274  args.push_back(stringsToConcatenate[0]);
2275  args.push_back(stringsToConcatenate[1]);
2276  args.push_back(stringsToConcatenate[2]);
2277  return CallInst::Create(function, args, "", block);
2278  }
2279  else
2280  {
2281  IntegerType *sizeType = IntegerType::get(module->getContext(), 64);
2282 
2283  const char *functionName = "vuoConcatenateStrings";
2284  Function *function = module->getFunction(functionName);
2285  if (! function)
2286  {
2287  vector<Type *> params;
2288  params.push_back(PointerType::get(pointerToCharType, 0));
2289  params.push_back(sizeType);
2290 
2291  FunctionType *functionType = FunctionType::get(pointerToCharType, params, false);
2292  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
2293  }
2294 
2295  Value *stringsValue = generateMemoryAllocation(module, block, pointerToCharType, stringsToConcatenate.size());
2296  for (size_t i = 0; i < stringsToConcatenate.size(); ++i)
2297  generateSetArrayElement(module, block, stringsValue, i, stringsToConcatenate[i]);
2298 
2299  vector<Value *> args;
2300  args.push_back(stringsValue);
2301  args.push_back(ConstantInt::get(sizeType, stringsToConcatenate.size()));
2302  Value *concatenatedStringValue = CallInst::Create(function, args, "", block);
2303 
2304  generateFreeCall(module, block, stringsValue);
2305 
2306  return concatenatedStringValue;
2307  }
2308 }
2309 
2319 Value * VuoCompilerCodeGenUtilities::generateMemoryAllocation(Module *module, BasicBlock *block, Type *elementType, int elementCount)
2320 {
2321  Value *elementCountValue = ConstantInt::get(module->getContext(), APInt(64, elementCount));
2322  return generateMemoryAllocation(module, block, elementType, elementCountValue);
2323 }
2324 
2334 Value * VuoCompilerCodeGenUtilities::generateMemoryAllocation(Module *module, BasicBlock *block, Type *elementType, Value *elementCountValue)
2335 {
2336  Constant *elementBytesValue = ConstantExpr::getSizeOf(elementType);
2337  Value *elementCountValue64;
2338  if (static_cast<IntegerType *>(elementCountValue->getType())->getBitWidth() < 64)
2339  elementCountValue64 = new SExtInst(elementCountValue, IntegerType::get(module->getContext(), 64), "", block);
2340  else
2341  elementCountValue64 = elementCountValue;
2342 
2343  BinaryOperator *bytesValue = BinaryOperator::Create(Instruction::Mul, elementBytesValue, elementCountValue64, "", block);
2344 
2345  Function *mallocFunction = VuoCompilerCodeGenUtilities::getMallocFunction(module);
2346  CallInst *mallocReturnValue = CallInst::Create(mallocFunction, bytesValue, "", block);
2347 
2348  Type *elementPointerType = PointerType::get(elementType, 0);
2349  CastInst *mallocReturnValueCasted = new BitCastInst(mallocReturnValue, elementPointerType, "", block);
2350 
2351  return mallocReturnValueCasted;
2352 }
2353 
2359 Value * VuoCompilerCodeGenUtilities::generateTypeCast(Module *module, BasicBlock *block, Value *valueToCast, Type *typeToCastTo)
2360 {
2361  if (valueToCast->getType() == typeToCastTo)
2362  return valueToCast;
2363 
2364  if (valueToCast->getType()->isIntegerTy() && typeToCastTo->isIntegerTy())
2365  return CastInst::CreateIntegerCast(valueToCast, typeToCastTo, true, "", block);
2366  else if (valueToCast->getType()->isIntegerTy() && typeToCastTo->isPointerTy())
2367  return generateTypeCastFromIntegerToPointer(module, block, valueToCast, typeToCastTo);
2368  else if (valueToCast->getType()->isFloatingPointTy() && typeToCastTo->isPointerTy())
2369  return generateTypeCastFromFloatingPointToPointer(module, block, valueToCast, typeToCastTo);
2370  else if (valueToCast->getType()->isPointerTy() && typeToCastTo->isIntegerTy())
2371  return generateTypeCastFromPointerToInteger(module, block, valueToCast, typeToCastTo);
2372  else if (valueToCast->getType()->isPointerTy() && typeToCastTo->isFloatingPointTy())
2373  return generateTypeCastFromPointerToFloatingPoint(module, block, valueToCast, typeToCastTo);
2374  else if (typeToCastTo->isStructTy())
2375  return generateTypeCastFromLoweredTypeToStruct(block, valueToCast, typeToCastTo);
2376  else if (typeToCastTo->isVectorTy())
2377  return generateTypeCastFromLoweredTypeToVector(block, valueToCast, typeToCastTo);
2378  else
2379  return new BitCastInst(valueToCast, typeToCastTo, "", block);
2380 }
2381 
2393 void VuoCompilerCodeGenUtilities::generateAnnotation(Module *module, BasicBlock *block, Value *value,
2394  string annotation, string fileName, unsigned int lineNumber,
2395  VuoCompilerConstantsCache *constantsCache)
2396 {
2397  // Set variable names expected by VuoCompilerBitcodeParser::getAnnotatedArguments().
2398  string valueName = value->getName();
2399  string variableName = valueName + ".addr";
2400  string valueAsVoidPointerName = valueName + ".addr1";
2401  string annotationVariableName = valueName + "__annotation";
2402 
2403  Function *annotateFunction = getAnnotateFunction(module);
2404  vector<Value *> annotateFunctionArgs;
2405 
2406  Value *variable = generatePointerToValue(block, value);
2407  variable->setName(variableName);
2408  PointerType *voidPointerType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2409  Value *valueAsVoidPointer = generateTypeCast(module, block, variable, voidPointerType);
2410  valueAsVoidPointer->setName(valueAsVoidPointerName);
2411  annotateFunctionArgs.push_back(valueAsVoidPointer);
2412 
2413  Constant *annotationPointer = generatePointerToConstantString(module, annotation, annotationVariableName);
2414  annotateFunctionArgs.push_back(annotationPointer);
2415 
2416  Constant *fileNamePointer = constantsCache->get(fileName);
2417  annotateFunctionArgs.push_back(fileNamePointer);
2418 
2419  ConstantInt *lineNumberValue = ConstantInt::get(module->getContext(), APInt(32, lineNumber));
2420  annotateFunctionArgs.push_back(lineNumberValue);
2421 
2422  CallInst::Create(annotateFunction, annotateFunctionArgs, "", block);
2423 }
2424 
2428 void VuoCompilerCodeGenUtilities::generateModuleMetadata(Module *module, string metadata, string moduleKey)
2429 {
2430  // const char *moduleDetails = ...;
2431  Constant *moduleDetailsValue = VuoCompilerCodeGenUtilities::generatePointerToConstantString(module, metadata, ".str"); // VuoCompilerBitcodeParser::resolveGlobalToConst requires that the variable have a name
2432  Type *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2433  string variableName = "moduleDetails";
2434  if (! moduleKey.empty())
2435  variableName = VuoStringUtilities::prefixSymbolName("moduleDetails", moduleKey);
2436  GlobalVariable *moduleDetailsVariable = new GlobalVariable(*module, pointerToCharType, false, GlobalValue::ExternalLinkage, 0, variableName);
2437  moduleDetailsVariable->setInitializer(moduleDetailsValue);
2438 }
2439 
2445 Value * VuoCompilerCodeGenUtilities::generateTypeCastFromIntegerToPointer(Module *module, BasicBlock *block, Value *valueToCast, Type *typeToCastTo)
2446 {
2447  unsigned pointerBitWidth = 64;
2448  IntegerType *integerWithPointerBitWidth = IntegerType::get(module->getContext(), pointerBitWidth);
2449  CastInst *valueAsIntegerWithPointerBitWidth = CastInst::CreateIntegerCast(valueToCast, integerWithPointerBitWidth, true, "", block);
2450  return new IntToPtrInst(valueAsIntegerWithPointerBitWidth, typeToCastTo, "", block);
2451 }
2452 
2458 Value * VuoCompilerCodeGenUtilities::generateTypeCastFromFloatingPointToPointer(Module *module, BasicBlock *block, Value *valueToCast, Type *typeToCastTo)
2459 {
2460  unsigned pointerBitWidth = 64;
2461  Type *floatingPointWithPointerBitWidth = Type::getDoubleTy(module->getContext());
2462  IntegerType *integerWithPointerBitWidth = IntegerType::get(module->getContext(), pointerBitWidth);
2463  CastInst *valueAsFloatingPointWithPointerBitWidth = CastInst::CreateFPCast(valueToCast, floatingPointWithPointerBitWidth, "", block);
2464  Value *valueAsIntegerWithPointerBitWidth = new BitCastInst(valueAsFloatingPointWithPointerBitWidth, integerWithPointerBitWidth, "", block);
2465  return generateTypeCastFromIntegerToPointer(module, block, valueAsIntegerWithPointerBitWidth, typeToCastTo);
2466 }
2467 
2473 Value * VuoCompilerCodeGenUtilities::generateTypeCastFromPointerToInteger(Module *module, BasicBlock *block, Value *valueToCast, Type *typeToCastTo)
2474 {
2475  unsigned pointerBitWidth = 64;
2476  IntegerType *integerWithPointerBitWidth = IntegerType::get(module->getContext(), pointerBitWidth);
2477  CastInst *valueAsIntegerWithPointerBitWidth = new PtrToIntInst(valueToCast, integerWithPointerBitWidth, "", block);
2478  return CastInst::CreateIntegerCast(valueAsIntegerWithPointerBitWidth, typeToCastTo, true, "", block);
2479 }
2480 
2486 Value * VuoCompilerCodeGenUtilities::generateTypeCastFromPointerToFloatingPoint(Module *module, BasicBlock *block, Value *valueToCast, Type *typeToCastTo)
2487 {
2488  unsigned pointerBitWidth = 64;
2489  Type *floatingPointWithPointerBitWidth = Type::getDoubleTy(module->getContext());
2490  IntegerType *integerWithPointerBitWidth = IntegerType::get(module->getContext(), pointerBitWidth);
2491  Value *valueAsIntegerWithPointerBitWidth = generateTypeCastFromPointerToInteger(module, block, valueToCast, integerWithPointerBitWidth);
2492  CastInst *valueAsFloatingPointWithPointerBitWidth = new BitCastInst(valueAsIntegerWithPointerBitWidth, floatingPointWithPointerBitWidth, "", block);
2493  return CastInst::CreateFPCast(valueAsFloatingPointWithPointerBitWidth, typeToCastTo, "", block);
2494 }
2495 
2501 Value * VuoCompilerCodeGenUtilities::generateTypeCastFromLoweredTypeToStruct(BasicBlock *block, Value *valueToCast, Type *typeToCastTo)
2502 {
2503  Value *originalValueToCast = valueToCast;
2504 
2505  if (valueToCast->getType()->isVectorTy() || valueToCast->getType()->isDoubleTy())
2506  {
2507  // Struct was lowered to a vector or double.
2508  PointerType *pointerToLoweredType = PointerType::get(valueToCast->getType(), 0);
2509 
2510  AllocaInst *structVariable = new AllocaInst(typeToCastTo, "", block);
2511  CastInst *structVariableAsLoweredType = new BitCastInst(structVariable, pointerToLoweredType, "", block);
2512  new StoreInst(valueToCast, structVariableAsLoweredType, false, block);
2513  return new LoadInst(structVariable, "", false, block);
2514  }
2515 
2516  if (valueToCast->getType()->isPointerTy())
2517  {
2518  // Struct was passed by value.
2519  valueToCast = new LoadInst(valueToCast, "", false, block);
2520  if (valueToCast->getType() == typeToCastTo)
2521  return valueToCast;
2522  }
2523 
2524  if (valueToCast->getType()->isStructTy())
2525  {
2526  // Struct types don't match because they were loaded from different modules.
2527  StructType *structTypeOfValueToCast = static_cast<StructType *>(valueToCast->getType());
2528  PointerType *pointerToTypeToCastTo = PointerType::get(typeToCastTo, 0);
2529 
2530  AllocaInst *otherStructVariable = new AllocaInst(structTypeOfValueToCast, "", block);
2531  new StoreInst(valueToCast, otherStructVariable, false, block);
2532  CastInst *otherStructAsTypeToCastTo = new BitCastInst(otherStructVariable, pointerToTypeToCastTo, "", block);
2533  return new LoadInst(otherStructAsTypeToCastTo, "", false, block);
2534  }
2535 
2536  VUserLog("Error: Couldn't cast from lowered type to struct.");
2537  originalValueToCast->getType()->dump(); fprintf(stderr, "\n");
2538  typeToCastTo->dump(); fprintf(stderr, "\n");
2539  return originalValueToCast;
2540 }
2541 
2547 Value * VuoCompilerCodeGenUtilities::generateTypeCastFromLoweredTypeToVector(BasicBlock *block, Value *valueToCast, Type *typeToCastTo)
2548 {
2549  if (typeToCastTo->isVectorTy() && static_cast<VectorType *>(typeToCastTo)->getElementType()->isFloatTy())
2550  {
2551  uint64_t elementCount = static_cast<VectorType *>(typeToCastTo)->getNumElements();
2552  if (elementCount == 2 && valueToCast->getType()->isDoubleTy())
2553  {
2554  // VuoPoint2d — Vector of 2 floats was lowered to a double.
2555  PointerType *pointerToDoubleType = PointerType::get(valueToCast->getType(), 0);
2556 
2557  AllocaInst *vectorVariable = new AllocaInst(typeToCastTo, "", block);
2558  CastInst *dstVectorVariableAsDouble = new BitCastInst(vectorVariable, pointerToDoubleType, "", block);
2559  new StoreInst(valueToCast, dstVectorVariableAsDouble, false, block);
2560  return new LoadInst(vectorVariable, "", false, block);
2561  }
2562  else if (elementCount == 3 && valueToCast->getType()->isVectorTy() &&
2563  static_cast<VectorType *>(valueToCast->getType())->getNumElements() == 2 &&
2564  static_cast<VectorType *>(valueToCast->getType())->getElementType()->isDoubleTy())
2565  {
2566  // VuoPoint3d — Vector of 3 floats was lowered to a vector of 2 doubles.
2567  PointerType *pointerToDoubleVectorType = PointerType::get(valueToCast->getType(), 0);
2568 
2569  AllocaInst *floatVectorVariable = new AllocaInst(typeToCastTo, "", block);
2570  CastInst *floatVectorVariableAsDoubleVector = new BitCastInst(floatVectorVariable, pointerToDoubleVectorType, "", block);
2571  new StoreInst(valueToCast, floatVectorVariableAsDoubleVector, false, block);
2572  return new LoadInst(floatVectorVariable, "", false, block);
2573  }
2574  }
2575 
2576  VUserLog("Error: Couldn't cast from lowered type to vector.");
2577  valueToCast->getType()->dump(); fprintf(stderr, "\n");
2578  typeToCastTo->dump(); fprintf(stderr, "\n");
2579  return valueToCast;
2580 }
2581 
2585 void VuoCompilerCodeGenUtilities::generateRegisterCall(Module *module, BasicBlock *block, Value *argument, Function *freeFunction)
2586 {
2587  Function *function = getVuoRegisterFunction(module);
2588 
2589  Type *voidPointerType = function->getFunctionType()->getParamType(0);
2590  Type *pointerToCharType = function->getFunctionType()->getParamType(2);
2591  Type *intType = function->getFunctionType()->getParamType(3);
2592 
2593  ConstantPointerNull *nullValue = ConstantPointerNull::get( static_cast<PointerType *>(pointerToCharType) );
2594  Constant *zeroValue = ConstantInt::get(intType, 0);
2595 
2596  vector<Value *> args;
2597 
2598  BitCastInst *argumentAsVoidPointer = new BitCastInst(argument, voidPointerType, "", block);
2599  args.push_back(argumentAsVoidPointer);
2600 
2601  args.push_back(freeFunction);
2602 
2603  args.push_back(nullValue);
2604  args.push_back(zeroValue);
2605  args.push_back(nullValue);
2606  args.push_back(nullValue);
2607 
2608  CallInst::Create(function, args, "", block);
2609 }
2610 
2614 void VuoCompilerCodeGenUtilities::generateRetainCall(Module *module, BasicBlock *block, Value *argument)
2615 {
2616  generateRetainOrReleaseCall(module, block, argument, true);
2617 }
2618 
2622 void VuoCompilerCodeGenUtilities::generateReleaseCall(Module *module, BasicBlock *block, Value *argument)
2623 {
2624  generateRetainOrReleaseCall(module, block, argument, false);
2625 }
2626 
2636 void VuoCompilerCodeGenUtilities::generateRetainOrReleaseCall(Module *module, BasicBlock *block, Value *argument, bool isRetain)
2637 {
2638  if (argument->getType()->isPointerTy())
2639  {
2640  Function *function = (isRetain ? getVuoRetainFunction(module) : getVuoReleaseFunction(module));
2641  Type *voidPointerType = function->getFunctionType()->getParamType(0);
2642 
2643  vector<Value *> retainOrReleaseArgs;
2644  retainOrReleaseArgs.push_back(VuoCompilerCodeGenUtilities::generateTypeCast(module, block, argument, voidPointerType));
2645  CallInst::Create(function, retainOrReleaseArgs, "", block);
2646  }
2647  else if (argument->getType()->isStructTy())
2648  {
2649  AllocaInst *structPointer = new AllocaInst(argument->getType(), "", block);
2650  new StoreInst(argument, structPointer, false, block);
2651 
2652  int numElements = static_cast<StructType *>(argument->getType())->getNumElements();
2653  for (unsigned i = 0; i < numElements; ++i)
2654  {
2655  Value *member = generateGetStructPointerElement(module, block, structPointer, i);
2656  generateRetainOrReleaseCall(module, block, member, isRetain);
2657  }
2658  }
2659 }
2660 
2666 {
2667  return type->isPointerTy() || type->isStructTy();
2668 }
2669 
2673 void VuoCompilerCodeGenUtilities::generateFreeCall(Module *module, BasicBlock *block, Value *argument)
2674 {
2675  Function *freeFunction = getFreeFunction(module);
2676  PointerType *voidPointerType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2677  Value *argumentAsVoidPointer = new BitCastInst(argument, voidPointerType, "", block);
2678  CallInst::Create(freeFunction, argumentAsVoidPointer, "", block);
2679 }
2680 
2684 void VuoCompilerCodeGenUtilities::generateJsonObjectPut(Module *module, BasicBlock *block, Value *jsonObjectValue)
2685 {
2686  Function *function = getJsonObjectPutFunction(module);
2687  CallInst::Create(function, jsonObjectValue, "", block);
2688 }
2689 
2694 void VuoCompilerCodeGenUtilities::generateNullCheck(Module *module, Function *function, Value *valueToCheck,
2695  BasicBlock *initialBlock, BasicBlock *&nullBlock, BasicBlock *&notNullBlock)
2696 {
2697  nullBlock = BasicBlock::Create(module->getContext(), "null", function, NULL);
2698  notNullBlock = BasicBlock::Create(module->getContext(), "notNull", function, NULL);
2699 
2700  Value *nullValue = ConstantPointerNull::get( static_cast<PointerType *>(valueToCheck->getType()) );
2701  ICmpInst *isNotNull = new ICmpInst(*initialBlock, ICmpInst::ICMP_NE, valueToCheck, nullValue, "");
2702  BranchInst::Create(notNullBlock, nullBlock, isNotNull, initialBlock);
2703 }
2704 
2708 Value * VuoCompilerCodeGenUtilities::generateSerialization(Module *module, BasicBlock *block, Value *valueToSerialize,
2709  VuoCompilerConstantsCache *constantsCache)
2710 {
2711  if (valueToSerialize->getType()->isPointerTy())
2712  {
2713  vector<Value *> replacementValues;
2714  replacementValues.push_back(valueToSerialize);
2715  return generateFormattedString(module, block, "%lx", replacementValues, constantsCache);
2716  }
2717  else
2718  {
2720  VUserLog("Error: Couldn't serialize non-pointer value.");
2721  return NULL;
2722  }
2723 }
2724 
2729 void VuoCompilerCodeGenUtilities::generateUnserialization(Module *module, BasicBlock *block, Value *stringToUnserialize, Value *destinationVariable,
2730  VuoCompilerConstantsCache *constantsCache)
2731 {
2732  if (destinationVariable->getType()->isPointerTy())
2733  {
2734  // sscanf(stringToUnserialize, "%lx", destinationPointer);
2735  Value *formatString = constantsCache->get("%lx");
2736  Function *sscanfFunction = getSscanfFunction(module);
2737  vector<Value *> sscanfArgs;
2738  sscanfArgs.push_back(stringToUnserialize);
2739  sscanfArgs.push_back(formatString);
2740  sscanfArgs.push_back(destinationVariable);
2741  CallInst::Create(sscanfFunction, sscanfArgs, "", block);
2742  }
2743  else
2744  {
2746  }
2747 }
2748 
2752 ICmpInst * VuoCompilerCodeGenUtilities::generateIsPausedComparison(Module *module, BasicBlock *block, Value *compositionStateValue)
2753 {
2754  Type *boolType = IntegerType::get(module->getContext(), 64);
2755 
2756  const char *functionName = "vuoIsPaused";
2757  Function *function = module->getFunction(functionName);
2758  if (! function)
2759  {
2760  FunctionType *functionType = FunctionType::get(boolType, compositionStateValue->getType(), false);
2761  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
2762  }
2763 
2764  CallInst *isPausedValue = CallInst::Create(function, compositionStateValue, "", block);
2765  Constant *falseValue = ConstantInt::get(boolType, 0);
2766  return new ICmpInst(*block, ICmpInst::ICMP_NE, isPausedValue, falseValue, "");
2767 }
2768 
2773  Value *compositionStateValue, Value *nodeIdentifierValue)
2774 {
2775  const char *functionName = "vuoSendNodeExecutionStarted";
2776  Function *function = module->getFunction(functionName);
2777  if (! function)
2778  {
2779  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
2780  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2781 
2782  vector<Type *> functionParams;
2783  functionParams.push_back(pointerToCompositionState);
2784  functionParams.push_back(pointerToCharType);
2785  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
2786  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
2787  }
2788 
2789  vector<Value *> args;
2790  args.push_back(compositionStateValue);
2791  args.push_back(nodeIdentifierValue);
2792  CallInst::Create(function, args, "", block);
2793 }
2794 
2799  Value *compositionStateValue, Value *nodeIdentifierValue)
2800 {
2801  const char *functionName = "vuoSendNodeExecutionFinished";
2802  Function *function = module->getFunction(functionName);
2803  if (! function)
2804  {
2805  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
2806  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2807 
2808  vector<Type *> functionParams;
2809  functionParams.push_back(pointerToCompositionState);
2810  functionParams.push_back(pointerToCharType);
2811  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
2812  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
2813  }
2814 
2815  vector<Value *> args;
2816  args.push_back(compositionStateValue);
2817  args.push_back(nodeIdentifierValue);
2818  CallInst::Create(function, args, "", block);
2819 }
2820 
2824 void VuoCompilerCodeGenUtilities::generateSendInputPortsUpdated(Module *module, BasicBlock *block,
2825  Value *compositionStateValue, Value *portIdentifierValue,
2826  bool receivedEvent, bool receivedData,
2827  Value *portDataSummaryValue)
2828 {
2829  IntegerType *boolType = IntegerType::get(module->getContext(), 1);
2830  Value *receivedEventValue = ConstantInt::get(boolType, receivedEvent ? 1 : 0);
2831  Value *receivedDataValue = ConstantInt::get(boolType, receivedData ? 1 : 0);
2832  generateSendInputPortsUpdated(module, block, compositionStateValue, portIdentifierValue, receivedEventValue, receivedDataValue, portDataSummaryValue);
2833 }
2834 
2838 void VuoCompilerCodeGenUtilities::generateSendInputPortsUpdated(Module *module, BasicBlock *block,
2839  Value *compositionStateValue, Value *portIdentifierValue,
2840  Value *receivedEventValue, Value *receivedDataValue,
2841  Value *portDataSummaryValue)
2842 {
2843  const char *functionName = "vuoSendInputPortsUpdated";
2844  Function *function = module->getFunction(functionName);
2845  if (! function)
2846  {
2847  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
2848  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2849  IntegerType *boolType = IntegerType::get(module->getContext(), 1);
2850 
2851  vector<Type *> functionParams;
2852  functionParams.push_back(pointerToCompositionState);
2853  functionParams.push_back(pointerToCharType);
2854  functionParams.push_back(boolType);
2855  functionParams.push_back(boolType);
2856  functionParams.push_back(pointerToCharType);
2857  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
2858  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
2859  }
2860 
2861  vector<Value *> args;
2862  args.push_back(compositionStateValue);
2863  args.push_back(portIdentifierValue);
2864  args.push_back(receivedEventValue);
2865  args.push_back(receivedDataValue);
2866  args.push_back(portDataSummaryValue);
2867  CallInst::Create(function, args, "", block);
2868 }
2869 
2874  Value *compositionStateValue, Value *portIdentifierValue,
2875  Value *sentEventValue, Value *sentDataValue,
2876  Value *portDataSummaryValue)
2877 {
2878  const char *functionName = "vuoSendOutputPortsUpdated";
2879  Function *function = module->getFunction(functionName);
2880  if (! function)
2881  {
2882  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
2883  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2884  IntegerType *boolType = IntegerType::get(module->getContext(), 1);
2885 
2886  vector<Type *> functionParams;
2887  functionParams.push_back(pointerToCompositionState);
2888  functionParams.push_back(pointerToCharType);
2889  functionParams.push_back(boolType);
2890  functionParams.push_back(boolType);
2891  functionParams.push_back(pointerToCharType);
2892  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
2893  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
2894  }
2895 
2896  vector<Value *> args;
2897  args.push_back(compositionStateValue);
2898  args.push_back(portIdentifierValue);
2899  args.push_back(sentEventValue);
2900  args.push_back(sentDataValue);
2901  args.push_back(portDataSummaryValue);
2902  CallInst::Create(function, args, "", block);
2903 }
2904 
2909  Value *compositionStateValue, Value *portIdentifierValue,
2910  Value *sentDataValue, Value *portDataSummaryValue)
2911 {
2912  const char *functionName = "vuoSendPublishedOutputPortsUpdated";
2913  Function *function = module->getFunction(functionName);
2914  if (! function)
2915  {
2916  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
2917  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2918  IntegerType *boolType = IntegerType::get(module->getContext(), 1);
2919 
2920  vector<Type *> functionParams;
2921  functionParams.push_back(pointerToCompositionState);
2922  functionParams.push_back(pointerToCharType);
2923  functionParams.push_back(boolType);
2924  functionParams.push_back(pointerToCharType);
2925  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
2926  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
2927  }
2928 
2929  vector<Value *> args;
2930  args.push_back(compositionStateValue);
2931  args.push_back(portIdentifierValue);
2932  args.push_back(sentDataValue);
2933  args.push_back(portDataSummaryValue);
2934  CallInst::Create(function, args, "", block);
2935 }
2936 
2940 void VuoCompilerCodeGenUtilities::generateSendEventFinished(Module *module, BasicBlock *block,
2941  Value *compositionStateValue, Value *eventIdValue)
2942 {
2943  const char *functionName = "vuoSendEventFinished";
2944  Function *function = module->getFunction(functionName);
2945  if (! function)
2946  {
2947  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
2948  Type *eventIdType = generateNoEventIdConstant(module)->getType();
2949 
2950  vector<Type *> functionParams;
2951  functionParams.push_back(pointerToCompositionState);
2952  functionParams.push_back(eventIdType);
2953  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
2954  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
2955  }
2956 
2957  vector<Value *> args;
2958  args.push_back(compositionStateValue);
2959  args.push_back(eventIdValue);
2960  CallInst::Create(function, args, "", block);
2961 }
2962 
2966 void VuoCompilerCodeGenUtilities::generateSendEventDropped(Module *module, BasicBlock *block,
2967  Value *compositionStateValue, Value *portIdentifierValue)
2968 {
2969  const char *functionName = "vuoSendEventDropped";
2970  Function *function = module->getFunction(functionName);
2971  if (! function)
2972  {
2973  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
2974  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2975 
2976  vector<Type *> functionParams;
2977  functionParams.push_back(pointerToCompositionState);
2978  functionParams.push_back(pointerToCharType);
2979  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
2980  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
2981  }
2982 
2983  vector<Value *> args;
2984  args.push_back(compositionStateValue);
2985  args.push_back(portIdentifierValue);
2986  CallInst::Create(function, args, "", block);
2987 }
2988 
2992 ICmpInst * VuoCompilerCodeGenUtilities::generateShouldSendDataTelemetryComparison(Module *module, BasicBlock *block, string portIdentifier,
2993  Value *compositionStateValue,
2994  VuoCompilerConstantsCache *constantsCache)
2995 {
2996  const char *functionName = "vuoShouldSendPortDataTelemetry";
2997  Function *shouldSendTelemetryFunction = module->getFunction(functionName);
2998  if (! shouldSendTelemetryFunction)
2999  {
3000  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
3001  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3002 
3003  vector<Type *> functionParams;
3004  functionParams.push_back(pointerToCompositionState);
3005  functionParams.push_back(pointerToCharType);
3006  FunctionType *functionType = FunctionType::get(IntegerType::get(module->getContext(), 32), functionParams, false);
3007  shouldSendTelemetryFunction = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3008  }
3009 
3010  Constant *portIdentifierValue = constantsCache->get(portIdentifier);
3011 
3012  vector<Value *> args;
3013  args.push_back(compositionStateValue);
3014  args.push_back(portIdentifierValue);
3015  CallInst *retValue = CallInst::Create(shouldSendTelemetryFunction, args, "", block);
3016 
3017  Constant *zeroValue = ConstantInt::get(retValue->getType(), 0);
3018  return new ICmpInst(*block, ICmpInst::ICMP_NE, retValue, zeroValue, "");
3019 }
3020 
3025 void VuoCompilerCodeGenUtilities::generateIsNodeBeingRemovedOrReplacedCheck(Module *module, Function *function, string nodeIdentifier,
3026  Value *compositionStateValue,
3027  BasicBlock *initialBlock, BasicBlock *&trueBlock, BasicBlock *&falseBlock,
3028  VuoCompilerConstantsCache *constantsCache,
3029  Value *&replacementJsonValue)
3030 {
3031  Type *boolType = IntegerType::get(module->getContext(), 64);
3032  PointerType *pointerToJsonObjectType = PointerType::get(getJsonObjectType(module), 0);
3033 
3034  const char *functionName = "vuoIsNodeBeingRemovedOrReplaced";
3035  Function *calledFunction = module->getFunction(functionName);
3036  if (! calledFunction)
3037  {
3038  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3039  PointerType *pointerToPointerToJsonObjectType = PointerType::get(pointerToJsonObjectType, 0);
3040 
3041  vector<Type *> functionParams;
3042  functionParams.push_back(compositionStateValue->getType());
3043  functionParams.push_back(pointerToCharType);
3044  functionParams.push_back(pointerToPointerToJsonObjectType);
3045  FunctionType *functionType = FunctionType::get(boolType, functionParams, false);
3046  calledFunction = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3047  }
3048 
3049  Value *nodeIdentifierValue = constantsCache->get(nodeIdentifier);
3050 
3051  AllocaInst *replacementJsonVariable = new AllocaInst(pointerToJsonObjectType, "", initialBlock);
3052  new StoreInst(ConstantPointerNull::get(pointerToJsonObjectType), replacementJsonVariable, false, initialBlock);
3053 
3054  vector<Value *> args;
3055  args.push_back(compositionStateValue);
3056  args.push_back(nodeIdentifierValue);
3057  args.push_back(replacementJsonVariable);
3058  CallInst *retValue = CallInst::Create(calledFunction, args, "", initialBlock);
3059 
3060  replacementJsonValue = new LoadInst(replacementJsonVariable, "", false, initialBlock);
3061 
3062  trueBlock = BasicBlock::Create(module->getContext(), "removedReplaced", function, NULL);
3063  falseBlock = BasicBlock::Create(module->getContext(), "notRemovedReplaced", function, NULL);
3064  Constant *falseValue = ConstantInt::get(boolType, 0);
3065  ICmpInst *retIsTrue = new ICmpInst(*initialBlock, ICmpInst::ICMP_NE, retValue, falseValue, "");
3066  BranchInst::Create(trueBlock, falseBlock, retIsTrue, initialBlock);
3067 }
3068 
3073 ICmpInst * VuoCompilerCodeGenUtilities::generateIsNodeBeingAddedOrReplacedCheck(Module *module, Function *function, string nodeIdentifier,
3074  Value *compositionStateValue,
3075  BasicBlock *initialBlock, BasicBlock *&trueBlock, BasicBlock *&falseBlock,
3076  VuoCompilerConstantsCache *constantsCache,
3077  Value *&replacementJsonValue)
3078 {
3079  Type *boolType = IntegerType::get(module->getContext(), 64);
3080  PointerType *pointerToJsonObjectType = PointerType::get(getJsonObjectType(module), 0);
3081 
3082  const char *functionName = "vuoIsNodeBeingAddedOrReplaced";
3083  Function *calledFunction = module->getFunction(functionName);
3084  if (! calledFunction)
3085  {
3086  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3087  PointerType *pointerToPointerToJsonObjectType = PointerType::get(pointerToJsonObjectType, 0);
3088 
3089  vector<Type *> functionParams;
3090  functionParams.push_back(compositionStateValue->getType());
3091  functionParams.push_back(pointerToCharType);
3092  functionParams.push_back(pointerToPointerToJsonObjectType);
3093  FunctionType *functionType = FunctionType::get(boolType, functionParams, false);
3094  calledFunction = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3095  }
3096 
3097  Value *nodeIdentifierValue = constantsCache->get(nodeIdentifier);
3098 
3099  AllocaInst *replacementJsonVariable = new AllocaInst(pointerToJsonObjectType, "", initialBlock);
3100  new StoreInst(ConstantPointerNull::get(pointerToJsonObjectType), replacementJsonVariable, false, initialBlock);
3101 
3102  vector<Value *> args;
3103  args.push_back(compositionStateValue);
3104  args.push_back(nodeIdentifierValue);
3105  args.push_back(replacementJsonVariable);
3106  CallInst *retValue = CallInst::Create(calledFunction, args, "", initialBlock);
3107 
3108  replacementJsonValue = new LoadInst(replacementJsonVariable, "", false, initialBlock);
3109 
3110  trueBlock = BasicBlock::Create(module->getContext(), "addedReplaced", function, NULL);
3111  falseBlock = BasicBlock::Create(module->getContext(), "notAddedReplaced", function, NULL);
3112  Constant *falseValue = ConstantInt::get(boolType, 0);
3113  ICmpInst *retIsTrue = new ICmpInst(*initialBlock, ICmpInst::ICMP_NE, retValue, falseValue, "");
3114  BranchInst::Create(trueBlock, falseBlock, retIsTrue, initialBlock);
3115 
3116  return retIsTrue;
3117 }
3118 
3123 {
3124  return ConstantInt::get(module->getContext(), APInt(64, 0));
3125 }
3126 
3130 Value * VuoCompilerCodeGenUtilities::generateGetNodeContext(Module *module, BasicBlock *block,
3131  Value *compositionStateValue, size_t nodeIndex)
3132 {
3133  IntegerType *unsignedLongType = IntegerType::get(module->getContext(), 64);
3134  Value *nodeIndexValue = ConstantInt::get(unsignedLongType, nodeIndex);
3135  return generateGetNodeContext(module, block, compositionStateValue, nodeIndexValue);
3136 }
3137 
3141 Value * VuoCompilerCodeGenUtilities::generateGetNodeContext(Module *module, BasicBlock *block,
3142  Value *compositionStateValue, Value *nodeIndexValue)
3143 {
3144  const char *functionName = "vuoGetNodeContext";
3145  Function *function = module->getFunction(functionName);
3146  if (! function)
3147  {
3148  IntegerType *unsignedLongType = IntegerType::get(module->getContext(), 64);
3149  PointerType *pointerToNodeContextType = PointerType::get(getNodeContextType(module), 0);
3150 
3151  vector<Type *> functionParams;
3152  functionParams.push_back(compositionStateValue->getType());
3153  functionParams.push_back(unsignedLongType);
3154  FunctionType *functionType = FunctionType::get(pointerToNodeContextType, functionParams, false);
3155  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3156  }
3157 
3158  vector<Value *> args;
3159  args.push_back(compositionStateValue);
3160  args.push_back(nodeIndexValue);
3161  return CallInst::Create(function, args, "", block);
3162 }
3163 
3167 Value * VuoCompilerCodeGenUtilities::generateGetCompositionContext(Module *module, BasicBlock *block,
3168  Value *compositionStateValue)
3169 {
3170  const char *functionName = "vuoGetCompositionContext";
3171  Function *function = module->getFunction(functionName);
3172  if (! function)
3173  {
3174  PointerType *pointerToNodeContextType = PointerType::get(getNodeContextType(module), 0);
3175 
3176  vector<Type *> functionParams;
3177  functionParams.push_back(compositionStateValue->getType());
3178  FunctionType *functionType = FunctionType::get(pointerToNodeContextType, functionParams, false);
3179  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3180  }
3181 
3182  vector<Value *> args;
3183  args.push_back(compositionStateValue);
3184  return CallInst::Create(function, args, "", block);
3185 }
3186 
3190 void VuoCompilerCodeGenUtilities::generateAddNodeMetadata(Module *module, BasicBlock *block,
3191  Value *compositionStateValue, Value *nodeIdentifierValue,
3192  Function *compositionCreateContextForNodeFunction,
3193  Function *compositionSetPortValueFunction,
3194  Function *compositionGetPortValueFunction,
3195  Function *compositionFireTriggerPortEventFunction,
3196  Function *compositionReleasePortDataFunction)
3197 {
3198  const char *functionName = "vuoAddNodeMetadata";
3199  Function *function = module->getFunction(functionName);
3200  if (! function)
3201  {
3202  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3203  PointerType *compositionCreateContextForNodeFunctionType = PointerType::getUnqual(getCompositionCreateContextForNodeFunction(module)->getFunctionType());
3204  PointerType *compositionSetPortValueFunctionType = PointerType::getUnqual(getCompositionSetPortValueFunction(module)->getFunctionType());
3205  PointerType *compositionGetPortValueFunctionType = PointerType::getUnqual(getCompositionGetPortValueFunction(module)->getFunctionType());
3206  PointerType *compositionFireTriggerPortEventFunctionType = PointerType::getUnqual(getCompositionFireTriggerPortEventFunction(module)->getFunctionType());
3207  PointerType *compositionReleasePortDataFunctionType = PointerType::getUnqual(getCompositionReleasePortDataFunction(module)->getFunctionType());
3208 
3209  vector<Type *> functionParams;
3210  functionParams.push_back(compositionStateValue->getType());
3211  functionParams.push_back(pointerToCharType);
3212  functionParams.push_back(compositionCreateContextForNodeFunctionType);
3213  functionParams.push_back(compositionSetPortValueFunctionType);
3214  functionParams.push_back(compositionGetPortValueFunctionType);
3215  functionParams.push_back(compositionFireTriggerPortEventFunctionType);
3216  functionParams.push_back(compositionReleasePortDataFunctionType);
3217  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
3218  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3219  }
3220 
3221  vector<Value *> args;
3222  args.push_back(compositionStateValue);
3223  args.push_back(nodeIdentifierValue);
3224  args.push_back(compositionCreateContextForNodeFunction);
3225  args.push_back(compositionSetPortValueFunction);
3226  args.push_back(compositionGetPortValueFunction);
3227  args.push_back(compositionFireTriggerPortEventFunction);
3228  args.push_back(compositionReleasePortDataFunction);
3229  CallInst::Create(function, args, "", block);
3230 }
3231 
3235 void VuoCompilerCodeGenUtilities::generateAddPortMetadata(Module *module, BasicBlock *block,
3236  Value *compositionStateValue, Value *portIdentifierValue,
3237  Value *portNameValue, size_t typeIndex, Value *initialValueValue)
3238 {
3239  IntegerType *unsignedLongType = IntegerType::get(module->getContext(), 64);
3240 
3241  const char *functionName = "vuoAddPortMetadata";
3242  Function *function = module->getFunction(functionName);
3243  if (! function)
3244  {
3245  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3246 
3247  vector<Type *> functionParams;
3248  functionParams.push_back(compositionStateValue->getType());
3249  functionParams.push_back(pointerToCharType);
3250  functionParams.push_back(pointerToCharType);
3251  functionParams.push_back(unsignedLongType);
3252  functionParams.push_back(pointerToCharType);
3253  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
3254  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3255  }
3256 
3257  Value *typeIndexValue = ConstantInt::get(unsignedLongType, typeIndex);
3258 
3259  vector<Value *> args;
3260  args.push_back(compositionStateValue);
3261  args.push_back(portIdentifierValue);
3262  args.push_back(portNameValue);
3263  args.push_back(typeIndexValue);
3264  args.push_back(initialValueValue);
3265  CallInst::Create(function, args, "", block);
3266 }
3267 
3271 void VuoCompilerCodeGenUtilities::generateInitContextForTopLevelComposition(Module *module, BasicBlock *block, Value *compositionStateValue,
3272  bool isStatefulComposition, size_t publishedOutputPortCount)
3273 {
3274  IntegerType *boolType = IntegerType::get(module->getContext(), 64);
3275  IntegerType *unsignedLongType = IntegerType::get(module->getContext(), 64);
3276 
3277  const char *functionName = "vuoInitContextForTopLevelComposition";
3278  Function *function = module->getFunction(functionName);
3279  if (! function)
3280  {
3281  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
3282 
3283  vector<Type *> functionParams;
3284  functionParams.push_back(pointerToCompositionState);
3285  functionParams.push_back(boolType);
3286  functionParams.push_back(unsignedLongType);
3287  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
3288  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3289  }
3290 
3291  Value *isStatefulCompositionValue = ConstantInt::get(boolType, isStatefulComposition);
3292  Value *publishedOutputPortCountValue = ConstantInt::get(unsignedLongType, publishedOutputPortCount);
3293 
3294  vector<Value *> args;
3295  args.push_back(compositionStateValue);
3296  args.push_back(isStatefulCompositionValue);
3297  args.push_back(publishedOutputPortCountValue);
3298  CallInst::Create(function, args, "", block);
3299 }
3300 
3304 void VuoCompilerCodeGenUtilities::generateFiniContextForTopLevelComposition(Module *module, BasicBlock *block, Value *compositionStateValue)
3305 {
3306  const char *functionName = "vuoFiniContextForTopLevelComposition";
3307  Function *function = module->getFunction(functionName);
3308  if (! function)
3309  {
3310  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
3311 
3312  vector<Type *> functionParams;
3313  functionParams.push_back(pointerToCompositionState);
3314  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
3315  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3316  }
3317 
3318  vector<Value *> args;
3319  args.push_back(compositionStateValue);
3320  CallInst::Create(function, args, "", block);
3321 }
3322 
3326 Value * VuoCompilerCodeGenUtilities::getTriggerWorkersScheduledValue(Module *module, BasicBlock *block, Value *compositionStateValue)
3327 {
3328  const char *functionName = "vuoGetTriggerWorkersScheduled";
3329  Function *function = module->getFunction(functionName);
3330  if (! function)
3331  {
3332  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
3333  Type *dispatchGroupType = getDispatchGroupType(module);
3334 
3335  vector<Type *> functionParams;
3336  functionParams.push_back(pointerToCompositionState);
3337  FunctionType *functionType = FunctionType::get(dispatchGroupType, functionParams, false);
3338  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3339  }
3340 
3341  vector<Value *> args;
3342  args.push_back(compositionStateValue);
3343  return CallInst::Create(function, args, "", block);
3344 }
3345 
3349 Value * VuoCompilerCodeGenUtilities::generateGetInputPortString(Module *module, BasicBlock *block, Value *compositionStateValue,
3350  Value *portIdentifierValue, Value *interprocessSerializationValue)
3351 {
3352  const char *functionName = "vuoGetInputPortString";
3353  Function *function = module->getFunction(functionName);
3354  if (! function)
3355  {
3356  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
3357  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3358  IntegerType *boolType = IntegerType::get(module->getContext(), 32);
3359 
3360  vector<Type *> functionParams;
3361  functionParams.push_back(pointerToCompositionState);
3362  functionParams.push_back(pointerToCharType);
3363  functionParams.push_back(boolType);
3364  FunctionType *functionType = FunctionType::get(pointerToCharType, functionParams, false);
3365  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3366  }
3367 
3368  vector<Value *> args;
3369  args.push_back(compositionStateValue);
3370  args.push_back(portIdentifierValue);
3371  args.push_back(interprocessSerializationValue);
3372  return CallInst::Create(function, args, "", block);
3373 }
3374 
3378 Value * VuoCompilerCodeGenUtilities::generateGetOutputPortString(Module *module, BasicBlock *block, Value *compositionStateValue,
3379  Value *portIdentifierValue, Value *interprocessSerializationValue)
3380 {
3381  const char *functionName = "vuoGetOutputPortString";
3382  Function *function = module->getFunction(functionName);
3383  if (! function)
3384  {
3385  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
3386  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3387  IntegerType *boolType = IntegerType::get(module->getContext(), 32);
3388 
3389  vector<Type *> functionParams;
3390  functionParams.push_back(pointerToCompositionState);
3391  functionParams.push_back(pointerToCharType);
3392  functionParams.push_back(boolType);
3393  FunctionType *functionType = FunctionType::get(pointerToCharType, functionParams, false);
3394  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3395  }
3396 
3397  vector<Value *> args;
3398  args.push_back(compositionStateValue);
3399  args.push_back(portIdentifierValue);
3400  args.push_back(interprocessSerializationValue);
3401  return CallInst::Create(function, args, "", block);
3402 }
3403 
3407 Value * VuoCompilerCodeGenUtilities::generateRuntimeStateValue(Module *module, BasicBlock *block)
3408 {
3409  const char *variableName = "vuoRuntimeState";
3410  GlobalVariable *variable = module->getNamedGlobal(variableName);
3411  if (! variable)
3412  {
3413  PointerType *voidPointer = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3414  variable = new GlobalVariable(*module, voidPointer, false, GlobalValue::ExternalLinkage, 0, variableName);
3415  }
3416 
3417  return new LoadInst(variable, "", false, block);
3418 }
3419 
3423 Value * VuoCompilerCodeGenUtilities::generateGetNextEventId(Module *module, BasicBlock *block, Value *compositionStateValue)
3424 {
3425  const char *functionName = "vuoGetNextEventId";
3426  Function *function = module->getFunction(functionName);
3427  if (! function)
3428  {
3429  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
3430  Type *eventIdType = IntegerType::get(module->getContext(), 64);
3431 
3432  vector<Type *> functionParams;
3433  functionParams.push_back(pointerToCompositionState);
3434  FunctionType *functionType = FunctionType::get(eventIdType, functionParams, false);
3435  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3436  }
3437 
3438  vector<Value *> args;
3439  args.push_back(compositionStateValue);
3440  return CallInst::Create(function, args, "", block);
3441 }
3442 
3447  Value *compositionStateValue, Value *dataCopyValue,
3448  Value *eventIdCopyValue)
3449 {
3450  const char *functionName = "vuoCreateTriggerWorkerContext";
3451  Function *function = module->getFunction(functionName);
3452  if (! function)
3453  {
3454  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
3455  PointerType *voidPointerType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3456  PointerType *pointerToEventIdType = PointerType::get(generateNoEventIdConstant(module)->getType(), 0);
3457 
3458  vector<Type *> functionParams;
3459  functionParams.push_back(pointerToCompositionState);
3460  functionParams.push_back(voidPointerType);
3461  functionParams.push_back(pointerToEventIdType);
3462  FunctionType *functionType = FunctionType::get(voidPointerType, functionParams, false);
3463  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3464  }
3465 
3466  vector<Value *> args;
3467  args.push_back(compositionStateValue);
3468  args.push_back(dataCopyValue);
3469  args.push_back(eventIdCopyValue);
3470  return CallInst::Create(function, args, "", block);
3471 }
3472 
3476 void VuoCompilerCodeGenUtilities::generateFreeTriggerWorkerContext(Module *module, BasicBlock *block, Value *contextValue)
3477 {
3478  const char *functionName = "vuoFreeTriggerWorkerContext";
3479  Function *function = module->getFunction(functionName);
3480  if (! function)
3481  {
3482  PointerType *voidPointerType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3483 
3484  vector<Type *> functionParams;
3485  functionParams.push_back(voidPointerType);
3486  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
3487  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3488  }
3489 
3490  vector<Value *> args;
3491  args.push_back(contextValue);
3492  CallInst::Create(function, args, "", block);
3493 }
3494 
3499  Value *compositionStateValue, Value *inputPortIdentifierValue,
3500  Value *valueAsStringValue, Value *isCompositionRunningValue)
3501 {
3502  const char *functionName = "vuoCreatePublishedInputWorkerContext";
3503  Function *function = module->getFunction(functionName);
3504  if (! function)
3505  {
3506  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
3507  PointerType *pointerToChar = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3508  PointerType *voidPointerType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3509  Type *boolType = IntegerType::get(module->getContext(), 64);
3510 
3511  vector<Type *> functionParams;
3512  functionParams.push_back(pointerToCompositionState);
3513  functionParams.push_back(pointerToChar);
3514  functionParams.push_back(pointerToChar);
3515  functionParams.push_back(boolType);
3516  FunctionType *functionType = FunctionType::get(voidPointerType, functionParams, false);
3517  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3518  }
3519 
3520  vector<Value *> args;
3521  args.push_back(compositionStateValue);
3522  args.push_back(inputPortIdentifierValue);
3523  args.push_back(valueAsStringValue);
3524  args.push_back(isCompositionRunningValue);
3525  return CallInst::Create(function, args, "", block);
3526 }
3527 
3532  Value *compositionStateValue)
3533 {
3534  const char *functionName = "vuoAddCompositionStateToThreadLocalStorage";
3535  Function *function = module->getFunction(functionName);
3536  if (! function)
3537  {
3538  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
3539 
3540  vector<Type *> functionParams;
3541  functionParams.push_back(pointerToCompositionState);
3542  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
3543  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3544  }
3545 
3546  vector<Value *> args;
3547  args.push_back(compositionStateValue);
3548  CallInst::Create(function, args, "", block);
3549 }
3550 
3555 {
3556  const char *functionName = "vuoRemoveCompositionStateFromThreadLocalStorage";
3557  Function *function = module->getFunction(functionName);
3558  if (! function)
3559  {
3560  vector<Type *> functionParams;
3561  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
3562  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3563  }
3564 
3565  vector<Value *> args;
3566  CallInst::Create(function, args, "", block);
3567 }
3568 
3572 Value * VuoCompilerCodeGenUtilities::generateStderr(Module *module, BasicBlock *block)
3573 {
3574  PointerType *pointerToFileType = getPointerToFileType(module);
3575 
3576  string variableName = "__stderrp";
3577  GlobalVariable *stderrVariable = module->getNamedGlobal(variableName);
3578  if (! stderrVariable)
3579  stderrVariable = new GlobalVariable(*module, pointerToFileType, false, GlobalValue::ExternalLinkage, 0, variableName);
3580 
3581  return new LoadInst(stderrVariable, "", false, block);
3582 }
3583 
3587 void VuoCompilerCodeGenUtilities::generatePrint(Module *module, BasicBlock *block, string formatString, Value *value)
3588 {
3589  vector<Value *> values;
3590  if (value)
3591  values.push_back(value);
3592  generatePrint(module, block, formatString, values);
3593 }
3594 
3598 void VuoCompilerCodeGenUtilities::generatePrint(Module *module, BasicBlock *block, string formatString, const vector<Value *> &values)
3599 {
3600  Value *formatStringValue = generatePointerToConstantString(module, formatString);
3601  Value *stderrValue = generateStderr(module, block);
3602 
3603  Function *fprintfFunction = getFprintfFunction(module);
3604  vector<Value *> fprintfArgs;
3605  fprintfArgs.push_back(stderrValue);
3606  fprintfArgs.push_back(formatStringValue);
3607  for (vector<Value *>::const_iterator i = values.begin(); i != values.end(); ++i)
3608  fprintfArgs.push_back(*i);
3609  CallInst::Create(fprintfFunction, fprintfArgs, "", block);
3610 }
3611 
3613 
3617 {
3618  StructType *dispatch_semaphore_s_type = module->getTypeByName("struct.dispatch_semaphore_s");
3619  if (! dispatch_semaphore_s_type)
3620  dispatch_semaphore_s_type = StructType::create(module->getContext(), "struct.dispatch_semaphore_s");
3621 
3622  PointerType *dispatch_semaphore_t_type = PointerType::get(dispatch_semaphore_s_type, 0);
3623  return dispatch_semaphore_t_type;
3624 }
3625 
3627 {
3628  StructType *dispatch_group_s_type = module->getTypeByName("struct.dispatch_group_s");
3629  if (! dispatch_group_s_type)
3630  dispatch_group_s_type = StructType::create(module->getContext(), "struct.dispatch_group_s");
3631 
3632  PointerType *dispatch_group_t_type = PointerType::get(dispatch_group_s_type, 0);
3633  return dispatch_group_t_type;
3634 }
3635 
3636 PointerType * VuoCompilerCodeGenUtilities::getDispatchQueueType(Module *module)
3637 {
3638  StructType *dispatch_queue_s_type = module->getTypeByName("struct.dispatch_queue_s");
3639  if (! dispatch_queue_s_type)
3640  dispatch_queue_s_type = StructType::create(module->getContext(), "struct.dispatch_queue_s");
3641 
3642  PointerType *dispatch_queue_t_type = PointerType::get(dispatch_queue_s_type, 0);
3643  return dispatch_queue_t_type;
3644 }
3645 
3646 StructType * VuoCompilerCodeGenUtilities::getDispatchObjectElementType(Module *module)
3647 {
3648  StructType *dispatch_object_s_type = module->getTypeByName("struct.dispatch_object_s");
3649  if (! dispatch_object_s_type)
3650  dispatch_object_s_type = StructType::create(module->getContext(), "struct.dispatch_object_s");
3651  vector<Type *> dispatch_object_s_fields;
3652  if (dispatch_object_s_type->isOpaque())
3653  dispatch_object_s_type->setBody(dispatch_object_s_fields, false);
3654  return dispatch_object_s_type;
3655 }
3656 
3658 {
3659  StructType *dispatch_object_s_type = getDispatchObjectElementType(module);
3660  PointerType *pointerTo_dispatch_object_s_type = PointerType::get(dispatch_object_s_type, 0);
3661 
3662  StructType *dispatch_object_t_type = module->getTypeByName("union.dispatch_object_t");
3663  if (! dispatch_object_t_type)
3664  dispatch_object_t_type = StructType::create(module->getContext(), "union.dispatch_object_t");
3665  vector<Type *> dispatch_object_t_fields;
3666  dispatch_object_t_fields.push_back(pointerTo_dispatch_object_s_type);
3667  if (dispatch_object_t_type->isOpaque())
3668  dispatch_object_t_type->setBody(dispatch_object_t_fields, false);
3669  return dispatch_object_t_type;
3670 }
3671 
3673 {
3674  StructType *nodeContextType = module->getTypeByName("struct.NodeContext");
3675  if (! nodeContextType)
3676  nodeContextType = StructType::create(module->getContext(), "struct.NodeContext");
3677 
3678  if (nodeContextType->isOpaque())
3679  {
3680  PointerType *pointerToPointerToPortContextType = PointerType::get(PointerType::get(getPortContextType(module), 0), 0);
3681  PointerType *voidPointerType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3682  Type *longType = IntegerType::get(module->getContext(), 64);
3683 
3684  vector<Type *> fields;
3685  fields.push_back(pointerToPointerToPortContextType);
3686  fields.push_back(longType);
3687  fields.push_back(voidPointerType);
3688  fields.push_back(getDispatchSemaphoreType(module));
3689  fields.push_back(longType);
3690  fields.push_back(getDispatchGroupType(module));
3691  fields.push_back(longType);
3692  nodeContextType->setBody(fields, false);
3693  }
3694 
3695  return nodeContextType;
3696 }
3697 
3699 {
3700  StructType *portContextType = module->getTypeByName("struct.PortContext");
3701  if (! portContextType)
3702  portContextType = StructType::create(module->getContext(), "struct.PortContext");
3703 
3704  if (portContextType->isOpaque())
3705  {
3706  Type *boolType = IntegerType::get(module->getContext(), 64);
3707  PointerType *voidPointerType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3708 
3709  vector<Type *> fields;
3710  fields.push_back(boolType);
3711  fields.push_back(voidPointerType);
3712  fields.push_back(boolType);
3713  fields.push_back(getDispatchQueueType(module));
3714  fields.push_back(getDispatchSemaphoreType(module));
3715  fields.push_back(voidPointerType);
3716  portContextType->setBody(fields, false);
3717  }
3718 
3719  return portContextType;
3720 }
3721 
3723 {
3724  StructType *compositionStateType = module->getTypeByName("struct.VuoCompositionState");
3725  if (! compositionStateType)
3726  compositionStateType = StructType::create(module->getContext(), "struct.VuoCompositionState");
3727 
3728  if (compositionStateType->isOpaque())
3729  {
3730  PointerType *voidPointerType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3731  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3732 
3733  vector<Type *> fields;
3734  fields.push_back(voidPointerType);
3735  fields.push_back(pointerToCharType);
3736  compositionStateType->setBody(fields, false);
3737  }
3738 
3739  return compositionStateType;
3740 }
3741 
3742 StructType * VuoCompilerCodeGenUtilities::getGraphvizGraphType(Module *module)
3743 {
3744  StructType *graphType = module->getTypeByName("struct.Agraph_t");
3745  if (! graphType)
3746  graphType = StructType::create(module->getContext(), "struct.Agraph_t");
3747 
3748  return graphType;
3749 }
3750 
3752 {
3753  StructType *jsonObjectType = module->getTypeByName("struct.json_object");
3754  if (! jsonObjectType)
3755  jsonObjectType = StructType::create(module->getContext(), "struct.json_object");
3756 
3757  return jsonObjectType;
3758 }
3759 
3760 PointerType * VuoCompilerCodeGenUtilities::getPointerToFileType(Module *module)
3761 {
3762  StructType *fileType = module->getTypeByName("struct.__sFILE");
3763  if (! fileType)
3764  fileType = StructType::create(module->getContext(), "struct.__sFILE");
3765 
3766  return PointerType::get(fileType, 0);
3767 }
3768 
3769 PointerType * VuoCompilerCodeGenUtilities::getVuoShaderType(Module *module)
3770 {
3771  StructType *shaderStructType = module->getTypeByName("struct._VuoShader");
3772  if (! shaderStructType)
3773  shaderStructType = StructType::create(module->getContext(), "struct._VuoShader");
3774 
3775  return PointerType::get(shaderStructType, 0);
3776 }
3777 
3778 PointerType * VuoCompilerCodeGenUtilities::getVuoImageType(Module *module)
3779 {
3780  StructType *imageStructType = module->getTypeByName("struct._VuoImage");
3781  if (! imageStructType)
3782  imageStructType = StructType::create(module->getContext(), "struct._VuoImage");
3783 
3784  return PointerType::get(imageStructType, 0);
3785 }
3786 
3787 Type * VuoCompilerCodeGenUtilities::getVuoImageColorDepthType(Module *module)
3788 {
3789  return IntegerType::get(module->getContext(), 32);
3790 }
3791 
3793 {
3794  return PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3795 }
3797 
3798 
3800 
3804 {
3805  const char *functionName = "strcat";
3806  Function *function = module->getFunction(functionName);
3807  if (! function)
3808  {
3809  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3810 
3811  vector<Type *> functionParams;
3812  functionParams.push_back(pointerToCharType);
3813  functionParams.push_back(pointerToCharType);
3814  FunctionType *functionType = FunctionType::get(pointerToCharType, functionParams, false);
3815  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3816  }
3817  return function;
3818 }
3819 
3821 {
3822  const char *functionName = "strcmp";
3823  Function *function = module->getFunction(functionName);
3824  if (! function)
3825  {
3826  PointerType *pointerToi8Type = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3827  vector<Type *> functionParams;
3828  functionParams.push_back(pointerToi8Type);
3829  functionParams.push_back(pointerToi8Type);
3830  FunctionType *functionType = FunctionType::get(IntegerType::get(module->getContext(), 32), functionParams, false);
3831  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3832  }
3833  return function;
3834 }
3835 
3837 {
3838  const char *functionName = "strdup";
3839  Function *function = module->getFunction(functionName);
3840  if (! function)
3841  {
3842  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3843 
3844  vector<Type *> functionParams;
3845  functionParams.push_back(pointerToCharType);
3846  FunctionType *functionType = FunctionType::get(pointerToCharType, functionParams, false);
3847  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3848  }
3849  return function;
3850 }
3851 
3853 {
3854  const char *functionName = "strlen";
3855  Function *function = module->getFunction(functionName);
3856  if (! function)
3857  {
3858  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3859 
3860  vector<Type *> functionParams;
3861  functionParams.push_back(pointerToCharType);
3862  FunctionType *functionType = FunctionType::get(IntegerType::get(module->getContext(), 64), functionParams, false);
3863  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3864  }
3865  return function;
3866 }
3867 
3869 {
3870  const char *functionName = "snprintf";
3871  Function *function = module->getFunction(functionName);
3872  if (! function)
3873  {
3874  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3875 
3876  vector<Type *> functionParams;
3877  functionParams.push_back(pointerToCharType);
3878  functionParams.push_back(IntegerType::get(module->getContext(), 64));
3879  functionParams.push_back(pointerToCharType);
3880  FunctionType *functionType = FunctionType::get(IntegerType::get(module->getContext(), 32), functionParams, true);
3881  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3882  }
3883  return function;
3884 }
3885 
3887 {
3888  const char *functionName = "sscanf";
3889  Function *function = module->getFunction(functionName);
3890  if (! function)
3891  {
3892  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3893 
3894  vector<Type *> functionParams;
3895  functionParams.push_back(pointerToCharType);
3896  functionParams.push_back(pointerToCharType);
3897  FunctionType *functionType = FunctionType::get(IntegerType::get(module->getContext(), 32), functionParams, true);
3898  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3899  }
3900  return function;
3901 }
3902 
3904 {
3905  const char *functionName = "fprintf";
3906  Function *function = module->getFunction(functionName);
3907  if (! function)
3908  {
3909  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3910 
3911  vector<Type *> functionParams;
3912  functionParams.push_back( getPointerToFileType(module) );
3913  functionParams.push_back(pointerToCharType);
3914  FunctionType *functionType = FunctionType::get(IntegerType::get(module->getContext(), 32), functionParams, true);
3915  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3916  }
3917  return function;
3918 }
3919 
3921 {
3922  const char *functionName = "puts";
3923  Function *function = module->getFunction(functionName);
3924  if (! function)
3925  {
3926  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3927 
3928  vector<Type *> functionParams;
3929  functionParams.push_back(pointerToCharType);
3930  FunctionType *functionType = FunctionType::get(IntegerType::get(module->getContext(), 32), functionParams, false);
3931  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3932  }
3933  return function;
3934 }
3935 
3937 {
3938  const char *functionName = "malloc";
3939  Function *function = module->getFunction(functionName);
3940  if (! function)
3941  {
3942  PointerType *pointerToi8Type = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3943 
3944  vector<Type *> functionParams;
3945  functionParams.push_back(IntegerType::get(module->getContext(), sizeof(size_t)*CHAR_BIT));
3946  FunctionType *functionType = FunctionType::get(pointerToi8Type, functionParams, false);
3947  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3948  }
3949  return function;
3950 }
3951 
3953 {
3954  const char *functionName = "free";
3955  Function *function = module->getFunction(functionName);
3956  if (! function)
3957  {
3958  PointerType *pointerToi8Type = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3959 
3960  vector<Type *> functionParams;
3961  functionParams.push_back(pointerToi8Type);
3962  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
3963  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3964  }
3965  return function;
3966 }
3967 
3969 {
3970  const char *functionName = "llvm.var.annotation";
3971  Function *function = module->getFunction(functionName);
3972  if (! function)
3973  {
3974  PointerType *pointerToi8Type = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3975 
3976  vector<Type *> functionParams;
3977  functionParams.push_back(pointerToi8Type);
3978  functionParams.push_back(pointerToi8Type);
3979  functionParams.push_back(pointerToi8Type);
3980  functionParams.push_back(IntegerType::get(module->getContext(), 32));
3981  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
3982  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3983  }
3984  return function;
3985 }
3986 
3988 {
3989  const char *functionName = "json_object_put";
3990  Function *function = module->getFunction(functionName);
3991  if (! function)
3992  {
3993  PointerType *pointerToJsonObjectType = PointerType::get(getJsonObjectType(module), 0);
3994 
3995  vector<Type *> functionParams;
3996  functionParams.push_back(pointerToJsonObjectType);
3997  FunctionType *functionType = FunctionType::get(IntegerType::get(module->getContext(), 32), functionParams, false);
3998  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3999  }
4000  return function;
4001 }
4002 
4004 {
4005  const char *functionName = "json_object_to_json_string_ext";
4006  Function *function = module->getFunction(functionName);
4007  if (! function)
4008  {
4009  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4010  PointerType *pointerToJsonObjectType = PointerType::get(getJsonObjectType(module), 0);
4011 
4012  vector<Type *> functionParams;
4013  functionParams.push_back(pointerToJsonObjectType);
4014  functionParams.push_back(IntegerType::get(module->getContext(), 32));
4015  FunctionType *functionType = FunctionType::get(pointerToCharType, functionParams, false);
4016  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4017  }
4018  return function;
4019 }
4020 
4022 {
4023  const char *functionName = "json_tokener_parse";
4024  Function *function = module->getFunction(functionName);
4025  if (! function)
4026  {
4027  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4028  PointerType *pointerToJsonObjectType = PointerType::get(getJsonObjectType(module), 0);
4029 
4030  vector<Type *> functionParams;
4031  functionParams.push_back(pointerToCharType);
4032  FunctionType *functionType = FunctionType::get(pointerToJsonObjectType, functionParams, false);
4033  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4034  }
4035  return function;
4036 }
4037 
4039 {
4040  const char *functionName = "VuoShader_make";
4041  Function *function = module->getFunction(functionName);
4042  if (! function)
4043  {
4044  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4045  Type *shaderType = getVuoShaderType(module);
4046 
4047  vector<Type *> functionParams;
4048  functionParams.push_back(pointerToCharType);
4049  FunctionType *functionType = FunctionType::get(shaderType, functionParams, false);
4050  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4051  }
4052  return function;
4053 }
4054 
4056 {
4057  const char *functionName = "VuoShader_addSource";
4058  Function *function = module->getFunction(functionName);
4059  if (! function)
4060  {
4061  Type *shaderType = getVuoShaderType(module);
4062  Type *elementAsseblyMethodType = IntegerType::get(module->getContext(), 64);
4063  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4064 
4065  vector<Type *> functionParams;
4066  functionParams.push_back(shaderType);
4067  functionParams.push_back(elementAsseblyMethodType);
4068  functionParams.push_back(pointerToCharType);
4069  functionParams.push_back(pointerToCharType);
4070  functionParams.push_back(pointerToCharType);
4071  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
4072  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4073  }
4074  return function;
4075 }
4076 
4078 {
4079  const char *functionName = "VuoShader_setTransparent";
4080  Function *function = module->getFunction(functionName);
4081  if (! function)
4082  {
4083  Type *shaderType = getVuoShaderType(module);
4084  Type *boolType = IntegerType::get(module->getContext(), 1);
4085 
4086  vector<Type *> functionParams;
4087  functionParams.push_back(shaderType);
4088  functionParams.push_back(boolType);
4089  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
4090  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4091  }
4092  return function;
4093 }
4094 
4096 {
4097  string functionName = "VuoShader_setUniform_" + type->getBase()->getModuleKey();
4098  Function *function = module->getFunction(functionName);
4099  if (! function)
4100  {
4101  Type *shaderType = getVuoShaderType(module);
4102  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4103 
4104  Type *dataSecondParam = nullptr;
4105  Type *dataParam = type->getFunctionParameterType(&dataSecondParam);
4106 
4107  vector<Type *> functionParams;
4108  functionParams.push_back(shaderType);
4109  functionParams.push_back(pointerToCharType);
4110  functionParams.push_back(dataParam);
4111  if (dataSecondParam)
4112  functionParams.push_back(dataSecondParam);
4113  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
4114  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4115  }
4116  return function;
4117 }
4118 
4120 {
4121  string functionName = "VuoShader_samplerRectCoordinatesFromNormalizedCoordinates";
4122  Function *function = module->getFunction(functionName);
4123  if (! function)
4124  {
4125  Type *loweredPoint2dType = Type::getDoubleTy(module->getContext());
4126  Type *intType = IntegerType::get(module->getContext(), 64);
4127 
4128  vector<Type *> functionParams;
4129  functionParams.push_back(loweredPoint2dType);
4130  functionParams.push_back(intType);
4131  functionParams.push_back(intType);
4132  FunctionType *functionType = FunctionType::get(loweredPoint2dType, functionParams, false);
4133  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4134  }
4135  return function;
4136 }
4137 
4139 {
4140  const char *functionName = "VuoImage_getColorDepth";
4141  Function *function = module->getFunction(functionName);
4142  if (! function)
4143  {
4144  Type *imageType = getVuoImageType(module);
4145  Type *imageColorDepthType = getVuoImageColorDepthType(module);
4146 
4147  vector<Type *> functionParams;
4148  functionParams.push_back(imageType);
4149  FunctionType *functionType = FunctionType::get(imageColorDepthType, functionParams, false);
4150  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4151  }
4152  return function;
4153 }
4154 
4156 {
4157  const char *functionName = "VuoImageRenderer_render";
4158  Function *function = module->getFunction(functionName);
4159  if (! function)
4160  {
4161  Type *shaderType = getVuoShaderType(module);
4162  Type *intType = IntegerType::get(module->getContext(), 64);
4163  Type *imageColorDepthType = getVuoImageColorDepthType(module);
4164  Type *imageType = getVuoImageType(module);
4165 
4166  vector<Type *> functionParams;
4167  functionParams.push_back(shaderType);
4168  functionParams.push_back(intType);
4169  functionParams.push_back(intType);
4170  functionParams.push_back(imageColorDepthType);
4171  FunctionType *functionType = FunctionType::get(imageType, functionParams, false);
4172  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4173  }
4174  return function;
4175 }
4176 
4178 {
4179  string functionName = "compositionAddNodeMetadata";
4180  string moduleKey = module->getModuleIdentifier();
4181  if (! moduleKey.empty())
4182  functionName = VuoStringUtilities::prefixSymbolName(functionName, moduleKey);
4183  Function *function = module->getFunction(functionName.c_str());
4184  if (! function)
4185  {
4186  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
4187 
4188  vector<Type *> functionParams;
4189  functionParams.push_back(pointerToCompositionState);
4190  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
4191  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4192  }
4193  return function;
4194 }
4195 
4197 {
4198  string functionName = "compositionCreateContextForNode";
4199  string moduleKey = module->getModuleIdentifier();
4200  if (! moduleKey.empty())
4201  functionName = VuoStringUtilities::prefixSymbolName(functionName, moduleKey);
4202  Function *function = module->getFunction(functionName.c_str());
4203  if (! function)
4204  {
4205  IntegerType *unsignedLongType = IntegerType::get(module->getContext(), 64);
4206  PointerType *pointerToNodeContextType = PointerType::get(getNodeContextType(module), 0);
4207 
4208  vector<Type *> functionParams;
4209  functionParams.push_back(unsignedLongType);
4210  FunctionType *functionType = FunctionType::get(pointerToNodeContextType, functionParams, false);
4211  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4212  }
4213  return function;
4214 }
4215 
4217 {
4218  string functionName = "compositionPerformDataOnlyTransmissions";
4219  string moduleKey = module->getModuleIdentifier();
4220  if (! moduleKey.empty())
4221  functionName = VuoStringUtilities::prefixSymbolName(functionName, moduleKey);
4222  Function *function = module->getFunction(functionName.c_str());
4223  if (! function)
4224  {
4225  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
4226 
4227  vector<Type *> functionParams;
4228  functionParams.push_back(pointerToCompositionState);
4229  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
4230  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4231  }
4232  return function;
4233 }
4234 
4236 {
4237  string functionName = "compositionReleasePortData";
4238  string moduleKey = module->getModuleIdentifier();
4239  if (! moduleKey.empty())
4240  functionName = VuoStringUtilities::prefixSymbolName(functionName, moduleKey);
4241  Function *function = module->getFunction(functionName.c_str());
4242  if (! function)
4243  {
4244  PointerType *voidPointer = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4245  IntegerType *unsignedLongType = IntegerType::get(module->getContext(), 64);
4246 
4247  vector<Type *> functionParams;
4248  functionParams.push_back(voidPointer);
4249  functionParams.push_back(unsignedLongType);
4250  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
4251  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4252  }
4253  return function;
4254 }
4255 
4257 {
4258  const char *functionName = "vuoSetup";
4259  Function *function = module->getFunction(functionName);
4260  if (! function)
4261  {
4262  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), false);
4263  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4264  }
4265  return function;
4266 }
4267 
4269 {
4270  const char *functionName = "vuoCleanup";
4271  Function *function = module->getFunction(functionName);
4272  if (! function)
4273  {
4274  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), false);
4275  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4276  }
4277  return function;
4278 }
4279 
4281 {
4282  const char *functionName = "vuoInstanceInit";
4283  Function *function = module->getFunction(functionName);
4284  if (! function)
4285  {
4286  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), false);
4287  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4288  }
4289  return function;
4290 }
4291 
4293 {
4294  const char *functionName = "vuoInstanceFini";
4295  Function *function = module->getFunction(functionName);
4296  if (! function)
4297  {
4298  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), false);
4299  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4300  }
4301  return function;
4302 }
4303 
4305 {
4306  const char *functionName = "vuoInstanceTriggerStart";
4307  Function *function = module->getFunction(functionName);
4308  if (! function)
4309  {
4310  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), PointerType::get(getCompositionInstanceDataType(module), 0), false);
4311  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4312  }
4313  return function;
4314 }
4315 
4317 {
4318  const char *functionName = "vuoInstanceTriggerStop";
4319  Function *function = module->getFunction(functionName);
4320  if (! function)
4321  {
4322  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), PointerType::get(getCompositionInstanceDataType(module), 0), false);
4323  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4324  }
4325  return function;
4326 }
4327 
4328 Function * VuoCompilerCodeGenUtilities::getNodeInstanceInitFunction(Module *module, string moduleKey, bool isSubcomposition,
4329  Type *instanceDataType,
4330  const vector<VuoPort *> &modelInputPorts,
4331  map<VuoPort *, size_t> &indexOfParameter,
4332  VuoCompilerConstantsCache *constantsCache)
4333 {
4334  map<VuoPort *, size_t> indexOfEventParameter;
4335  return getNodeFunction(module, moduleKey, "nodeInstanceInit", isSubcomposition, false, true, false, instanceDataType, modelInputPorts, vector<VuoPort *>(),
4336  map<VuoPort *, json_object *>(), map<VuoPort *, string>(), map<VuoPort *, string>(), map<VuoPort *, VuoPortClass::EventBlocking>(),
4337  indexOfParameter, indexOfEventParameter, constantsCache);
4338 }
4339 
4340 Function * VuoCompilerCodeGenUtilities::getNodeInstanceFiniFunction(Module *module, string moduleKey,
4341  Type *instanceDataType,
4342  VuoCompilerConstantsCache *constantsCache)
4343 {
4344  map<VuoPort *, size_t> indexOfParameter;
4345  map<VuoPort *, size_t> indexOfEventParameter;
4346  return getNodeFunction(module, moduleKey, "nodeInstanceFini", true, true, false, false, instanceDataType, vector<VuoPort *>(), vector<VuoPort *>(),
4347  map<VuoPort *, json_object *>(), map<VuoPort *, string>(), map<VuoPort *, string>(), map<VuoPort *, VuoPortClass::EventBlocking>(),
4348  indexOfParameter, indexOfEventParameter, constantsCache);
4349 }
4350 
4351 Function * VuoCompilerCodeGenUtilities::getNodeInstanceTriggerStartFunction(Module *module, string moduleKey,
4352  Type *instanceDataType,
4353  const vector<VuoPort *> &modelInputPorts,
4354  map<VuoPort *, size_t> &indexOfParameter,
4355  VuoCompilerConstantsCache *constantsCache)
4356 {
4357  map<VuoPort *, size_t> indexOfEventParameter;
4358  return getNodeFunction(module, moduleKey, "nodeInstanceTriggerStart", true, true, false, false, instanceDataType, modelInputPorts, vector<VuoPort *>(),
4359  map<VuoPort *, json_object *>(), map<VuoPort *, string>(), map<VuoPort *, string>(), map<VuoPort *, VuoPortClass::EventBlocking>(),
4360  indexOfParameter, indexOfEventParameter, constantsCache);
4361 }
4362 
4363 Function * VuoCompilerCodeGenUtilities::getNodeInstanceTriggerStopFunction(Module *module, string moduleKey,
4364  Type *instanceDataType,
4365  VuoCompilerConstantsCache *constantsCache)
4366 {
4367  map<VuoPort *, size_t> indexOfParameter;
4368  map<VuoPort *, size_t> indexOfEventParameter;
4369  return getNodeFunction(module, moduleKey, "nodeInstanceTriggerStop", true, true, false, false, instanceDataType, vector<VuoPort *>(), vector<VuoPort *>(),
4370  map<VuoPort *, json_object *>(), map<VuoPort *, string>(), map<VuoPort *, string>(), map<VuoPort *, VuoPortClass::EventBlocking>(),
4371  indexOfParameter, indexOfEventParameter, constantsCache);
4372 }
4373 
4374 Function * VuoCompilerCodeGenUtilities::getNodeInstanceTriggerUpdateFunction(Module *module, string moduleKey,
4375  Type *instanceDataType,
4376  const vector<VuoPort *> &modelInputPorts,
4377  map<VuoPort *, size_t> &indexOfParameter,
4378  VuoCompilerConstantsCache *constantsCache)
4379 {
4380  map<VuoPort *, size_t> indexOfEventParameter;
4381  return getNodeFunction(module, moduleKey, "nodeInstanceTriggerUpdate", true, true, false, false, instanceDataType, modelInputPorts, vector<VuoPort *>(),
4382  map<VuoPort *, json_object *>(), map<VuoPort *, string>(), map<VuoPort *, string>(), map<VuoPort *, VuoPortClass::EventBlocking>(),
4383  indexOfParameter, indexOfEventParameter, constantsCache);
4384 }
4385 
4386 Function * VuoCompilerCodeGenUtilities::getNodeEventFunction(Module *module, string moduleKey, bool isSubcomposition, bool isStateful,
4387  Type *instanceDataType,
4388  const vector<VuoPort *> &modelInputPorts,
4389  const vector<VuoPort *> &modelOutputPorts,
4390  const map<VuoPort *, json_object *> &detailsForPorts,
4391  const map<VuoPort *, string> &displayNamesForPorts,
4392  const map<VuoPort *, string> &defaultValuesForInputPorts,
4393  const map<VuoPort *, VuoPortClass::EventBlocking> &eventBlockingForInputPorts,
4394  map<VuoPort *, size_t> &indexOfParameter,
4395  map<VuoPort *, size_t> &indexOfEventParameter,
4396  VuoCompilerConstantsCache *constantsCache)
4397 {
4398  string functionName = (isStateful ? "nodeInstanceEvent" : "nodeEvent");
4399  return getNodeFunction(module, moduleKey, functionName, isSubcomposition, isStateful, false, true, instanceDataType, modelInputPorts, modelOutputPorts,
4400  detailsForPorts, displayNamesForPorts, defaultValuesForInputPorts, eventBlockingForInputPorts,
4401  indexOfParameter, indexOfEventParameter, constantsCache);
4402 }
4403 
4404 Function * VuoCompilerCodeGenUtilities::getNodeFunction(Module *module, string moduleKey, string functionName,
4405  bool hasCompositionStateArg, bool hasInstanceDataArg,
4406  bool hasInstanceDataReturn, bool hasEventArgs,
4407  Type *instanceDataType,
4408  const vector<VuoPort *> &modelInputPorts, const vector<VuoPort *> &modelOutputPorts,
4409  const map<VuoPort *, json_object *> &detailsForPorts,
4410  const map<VuoPort *, string> &displayNamesForPorts,
4411  const map<VuoPort *, string> &defaultValuesForInputPorts,
4412  const map<VuoPort *, VuoPortClass::EventBlocking> &eventBlockingForInputPorts,
4413  map<VuoPort *, size_t> &indexOfParameter,
4414  map<VuoPort *, size_t> &indexOfEventParameter,
4415  VuoCompilerConstantsCache *constantsCache)
4416 {
4417  if (! moduleKey.empty())
4418  functionName = VuoStringUtilities::prefixSymbolName(functionName, moduleKey);
4419  Function *function = module->getFunction(functionName.c_str());
4420 
4421  if (! function)
4422  {
4423  vector<Type *> functionParams;
4424  map<int, AttributeSet> functionAttributes;
4425  map<VuoPort *, bool> hasSecondParam;
4426  Type *boolType = IntegerType::get(module->getContext(), 1);
4427  size_t indexInEventFunction = 0;
4428 
4429  if (hasCompositionStateArg)
4430  {
4431  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
4432  functionParams.push_back(pointerToCompositionState);
4433  indexInEventFunction++;
4434  }
4435 
4436  if (hasInstanceDataArg)
4437  {
4438  functionParams.push_back( PointerType::get(instanceDataType, 0) );
4439  indexInEventFunction++;
4440  }
4441 
4442  for (vector<VuoPort *>::const_iterator i = modelInputPorts.begin(); i != modelInputPorts.end(); ++i)
4443  {
4444  VuoCompilerPort *modelInputPort = static_cast<VuoCompilerPort *>( (*i)->getCompiler() );
4445  VuoType *type = modelInputPort->getDataVuoType();
4446 
4447  if (type)
4448  {
4449  Type *paramSecondType = NULL;
4450  Type *paramType = type->getCompiler()->getFunctionParameterType(&paramSecondType);
4451  AttributeSet paramAttributes = type->getCompiler()->getFunctionParameterAttributes();
4452 
4453  functionParams.push_back(paramType);
4454 
4455  // If we're generating a node function for a subcomposition, and the parameter is a struct that
4456  // would normally be passed "byval", don't actually make it "byval" in the node function.
4457  // Instead, the Vuo compiler will generate code equivalent to the "byval" semantics.
4458  //
4459  // This is a workaround for a bug where LLVM would sometimes give the node function body
4460  // an invalid value for a "byval" struct argument. https://b33p.net/kosada/node/11386
4461  if (! (hasCompositionStateArg &&
4462  type->getCompiler()->getType()->isStructTy() &&
4463  paramAttributes.hasAttrSomewhere(Attribute::ByVal)) )
4464  {
4465  functionAttributes[ functionParams.size() - 1] = paramAttributes;
4466  }
4467 
4468  indexOfParameter[modelInputPort->getBase()] = indexInEventFunction++;
4469 
4470  if (paramSecondType)
4471  {
4472  functionParams.push_back(paramSecondType);
4473  functionAttributes[ functionParams.size() - 1] = paramAttributes;
4474  hasSecondParam[*i] = true;
4475 
4476  indexInEventFunction++;
4477  }
4478 
4479  if (hasEventArgs)
4480  {
4481  functionParams.push_back(boolType);
4482 
4483  indexOfEventParameter[modelInputPort->getBase()] = indexInEventFunction++;
4484  }
4485  }
4486  else if (hasEventArgs)
4487  {
4488  functionParams.push_back(boolType);
4489 
4490  indexOfParameter[modelInputPort->getBase()] = indexInEventFunction++;
4491  }
4492  }
4493 
4494  for (vector<VuoPort *>::const_iterator i = modelOutputPorts.begin(); i != modelOutputPorts.end(); ++i)
4495  {
4496  VuoCompilerPort *modelOutputPort = static_cast<VuoCompilerPort *>( (*i)->getCompiler() );
4497  VuoType *type = modelOutputPort->getDataVuoType();
4498 
4499  if (modelOutputPort->getBase()->getClass()->getPortType() == VuoPortClass::triggerPort)
4500  {
4501  FunctionType *functionType = static_cast<VuoCompilerTriggerPortClass *>( modelOutputPort->getBase()->getClass()->getCompiler() )->getFunctionType();
4502  PointerType *triggerFunctionPointerType = PointerType::get(functionType, 0);
4503  functionParams.push_back(triggerFunctionPointerType);
4504 
4505  indexOfParameter[modelOutputPort->getBase()] = indexInEventFunction++;
4506  }
4507  else
4508  {
4509  if (type)
4510  {
4511  PointerType *paramType = PointerType::get( type->getCompiler()->getType(), 0 );
4512  functionParams.push_back(paramType);
4513 
4514  indexOfParameter[modelOutputPort->getBase()] = indexInEventFunction++;
4515 
4516  if (hasEventArgs)
4517  {
4518  PointerType *eventParamType = PointerType::get( boolType, 0 );
4519  functionParams.push_back(eventParamType);
4520 
4521  indexOfEventParameter[modelOutputPort->getBase()] = indexInEventFunction++;
4522  }
4523  }
4524  else if (hasEventArgs)
4525  {
4526  PointerType *paramType = PointerType::get( boolType, 0 );
4527  functionParams.push_back(paramType);
4528 
4529  indexOfParameter[modelOutputPort->getBase()] = indexInEventFunction++;
4530  }
4531  }
4532  }
4533 
4534  Type *returnType = (hasInstanceDataReturn ? instanceDataType : Type::getVoidTy(module->getContext()));
4535  FunctionType *functionType = FunctionType::get(returnType, functionParams, false);
4536  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4537 
4538  for (map<int, AttributeSet>::iterator i = functionAttributes.begin(); i != functionAttributes.end(); ++i)
4539  {
4540  int attributesIndex = i->first + 1;
4541  AttributeSet attributes = i->second;
4542  function->addAttributes(attributesIndex, copyAttributesToIndex(attributes, attributesIndex));
4543  }
4544 
4545  set<string> argNamesUsed;
4546 
4547  BasicBlock *block = BasicBlock::Create(module->getContext(), "", function, 0);
4548  Function::arg_iterator argIter = function->arg_begin();
4549 
4550  if (hasCompositionStateArg)
4551  {
4552  Value *arg = argIter++;
4553  string argName = "compositionState";
4554  arg->setName(argName);
4555  argNamesUsed.insert(argName);
4556  }
4557 
4558  if (hasInstanceDataArg)
4559  {
4560  Value *arg = argIter++;
4561  string argName = "instanceData";
4562  arg->setName(argName);
4563  argNamesUsed.insert(argName);
4564  generateAnnotation(module, block, arg, "vuoInstanceData", "", 0, constantsCache);
4565  }
4566 
4567  argNamesUsed.insert("refresh");
4568 
4569  map<VuoPort *, string> primaryArgNames;
4570  auto recordUniqueArgName = [&primaryArgNames, &argNamesUsed] (VuoPort *modelPort)
4571  {
4572  string argName = VuoStringUtilities::formUniqueIdentifier(argNamesUsed, modelPort->getClass()->getName());
4573  primaryArgNames[modelPort] = argName;
4574  };
4575  std::for_each(modelInputPorts.begin(), modelInputPorts.end(), recordUniqueArgName);
4576  std::for_each(modelOutputPorts.begin(), modelOutputPorts.end(), recordUniqueArgName);
4577 
4578  for (vector<VuoPort *>::const_iterator i = modelInputPorts.begin(); i != modelInputPorts.end(); ++i)
4579  {
4580  VuoPort *modelInputPort = *i;
4581  VuoType *type = static_cast<VuoCompilerPort *>( modelInputPort->getCompiler() )->getDataVuoType();
4582 
4583  if (type || hasEventArgs)
4584  {
4585  Value *arg = argIter++;
4586 
4587  string portName = modelInputPort->getClass()->getName();
4588  string argName = primaryArgNames[modelInputPort];
4589  arg->setName(argName);
4590 
4591  map<VuoPort *, VuoPortClass::EventBlocking>::const_iterator eventBlockingIter = eventBlockingForInputPorts.find(modelInputPort);
4592  bool hasNonDefaultEventBlocking = (eventBlockingIter != eventBlockingForInputPorts.end() && eventBlockingIter->second != VuoPortClass::EventBlocking_None);
4593  string eventBlockingStr = (eventBlockingIter->second == VuoPortClass::EventBlocking_Door ? "door" : "wall");
4594 
4595  json_object *details = json_object_new_object();
4596  map<VuoPort *, json_object *>::const_iterator detailsIter = detailsForPorts.find(modelInputPort);
4597  if (detailsIter != detailsForPorts.end())
4598  {
4599  json_object_object_foreach(detailsIter->second, key, val)
4600  {
4601  json_object_object_add(details, key, val);
4602  json_object_get(val);
4603  }
4604  }
4605  map<VuoPort *, string>::const_iterator displayNameIter = displayNamesForPorts.find(modelInputPort);
4606  if (displayNameIter != displayNamesForPorts.end())
4607  json_object_object_add(details, "name", json_object_new_string(displayNameIter->second.c_str()));
4608 
4609  if (type)
4610  {
4611  generateAnnotation(module, block, arg, "vuoInputData", "", 0, constantsCache);
4612  generateAnnotation(module, block, arg, "vuoType:" + type->getModuleKey(), "", 0, constantsCache);
4613 
4614  map<VuoPort *, string>::const_iterator defaultValueIter = defaultValuesForInputPorts.find(modelInputPort);
4615  if (defaultValueIter != defaultValuesForInputPorts.end())
4616  json_object_object_add(details, "default", json_tokener_parse(defaultValueIter->second.c_str()));
4617 
4618  if (hasSecondParam[modelInputPort])
4619  {
4620  Value *secondArg = argIter++;
4621  secondArg->setName(argName + ".1");
4622  }
4623 
4624  if (hasEventArgs)
4625  {
4626  Value *eventArg = argIter++;
4627 
4628  string preferredEventArgName = portName + "Event";
4629  string eventArgName = VuoStringUtilities::formUniqueIdentifier(argNamesUsed, preferredEventArgName);
4630  eventArg->setName(eventArgName);
4631 
4632  generateAnnotation(module, block, eventArg, "vuoInputEvent", "", 0, constantsCache);
4633 
4634  json_object *eventDetails = json_object_new_object();
4635  json_object_object_add(eventDetails, "data", json_object_new_string(argName.c_str()));
4636  if (hasNonDefaultEventBlocking)
4637  json_object_object_add(eventDetails, "eventBlocking", json_object_new_string(eventBlockingStr.c_str()));
4638  string eventDetailsStr = json_object_to_json_string_ext(eventDetails, JSON_C_TO_STRING_PLAIN);
4639  json_object_put(eventDetails);
4640  generateAnnotation(module, block, eventArg, "vuoDetails:" + eventDetailsStr, "", 0, constantsCache);
4641  }
4642  }
4643  else if (hasEventArgs)
4644  {
4645  generateAnnotation(module, block, arg, "vuoInputEvent", "", 0, constantsCache);
4646 
4647  if (hasNonDefaultEventBlocking)
4648  json_object_object_add(details, "eventBlocking", json_object_new_string(eventBlockingStr.c_str()));
4649  }
4650 
4651  string detailsStr = json_object_to_json_string_ext(details, JSON_C_TO_STRING_PLAIN);
4652  json_object_put(details);
4653  generateAnnotation(module, block, arg, "vuoDetails:" + detailsStr, "", 0, constantsCache);
4654  }
4655  }
4656 
4657  for (vector<VuoPort *>::const_iterator i = modelOutputPorts.begin(); i != modelOutputPorts.end(); ++i)
4658  {
4659  VuoPort *modelOutputPort = *i;
4660 
4661  Value *arg = argIter++;
4662 
4663  string portName = modelOutputPort->getClass()->getName();
4664  string argName = primaryArgNames[modelOutputPort];
4665  arg->setName(argName);
4666 
4667  json_object *details = json_object_new_object();
4668  map<VuoPort *, json_object *>::const_iterator detailsIter = detailsForPorts.find(modelOutputPort);
4669  if (detailsIter != detailsForPorts.end())
4670  {
4671  json_object_object_foreach(detailsIter->second, key, val)
4672  {
4673  json_object_object_add(details, key, val);
4674  json_object_get(val);
4675  }
4676  }
4677  map<VuoPort *, string>::const_iterator displayNameIter = displayNamesForPorts.find(modelOutputPort);
4678  if (displayNameIter != displayNamesForPorts.end())
4679  json_object_object_add(details, "name", json_object_new_string(displayNameIter->second.c_str()));
4680  string detailsStr = json_object_to_json_string_ext(details, JSON_C_TO_STRING_PLAIN);
4681  json_object_put(details);
4682  generateAnnotation(module, block, arg, "vuoDetails:" + detailsStr, "", 0, constantsCache);
4683 
4684  VuoType *type = static_cast<VuoCompilerPort *>( modelOutputPort->getCompiler() )->getDataVuoType();
4685  if (modelOutputPort->getClass()->getPortType() == VuoPortClass::triggerPort)
4686  {
4687  generateAnnotation(module, block, arg, "vuoOutputTrigger:" + argName, "", 0, constantsCache);
4688  generateAnnotation(module, block, arg, "vuoType:" + (type ? type->getModuleKey() : "void"), "", 0, constantsCache);
4689  }
4690  else
4691  {
4692  if (type)
4693  {
4694  generateAnnotation(module, block, arg, "vuoOutputData", "", 0, constantsCache);
4695  generateAnnotation(module, block, arg, "vuoType:" + type->getModuleKey(), "", 0, constantsCache);
4696 
4697  if (hasEventArgs)
4698  {
4699  Value *eventArg = argIter++;
4700 
4701  string preferredEventArgName = portName + "Event";
4702  string eventArgName = VuoStringUtilities::formUniqueIdentifier(argNamesUsed, preferredEventArgName);
4703  eventArg->setName(eventArgName);
4704 
4705  generateAnnotation(module, block, eventArg, "vuoOutputEvent", "", 0, constantsCache);
4706 
4707  json_object *eventDetails = json_object_new_object();
4708  json_object_object_add(eventDetails, "data", json_object_new_string(argName.c_str()));
4709  string eventDetailsStr = json_object_to_json_string_ext(eventDetails, JSON_C_TO_STRING_PLAIN);
4710  json_object_put(eventDetails);
4711  generateAnnotation(module, block, eventArg, "vuoDetails:" + eventDetailsStr, "", 0, constantsCache);
4712  }
4713  }
4714  else if (hasEventArgs)
4715  {
4716  generateAnnotation(module, block, arg, "vuoOutputEvent", "", 0, constantsCache);
4717  }
4718  }
4719  }
4720  }
4721 
4722  return function;
4723 }
4724 
4725 Function * VuoCompilerCodeGenUtilities::getVuoRegisterFunction(Module *module)
4726 {
4727  const char *functionName = "VuoRegisterF";
4728  Function *function = module->getFunction(functionName);
4729  if (! function)
4730  {
4731  PointerType *voidPointerType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4732  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4733  IntegerType *intType = IntegerType::get(module->getContext(), 32);
4734 
4735  FunctionType *deallocateFunctionType = FunctionType::get(Type::getVoidTy(module->getContext()), voidPointerType, false);
4736  PointerType *deallocateFunctionPointerType = PointerType::get(deallocateFunctionType, 0);
4737 
4738  vector<Type *> functionParams;
4739  functionParams.push_back(voidPointerType);
4740  functionParams.push_back(deallocateFunctionPointerType);
4741  functionParams.push_back(pointerToCharType);
4742  functionParams.push_back(intType);
4743  functionParams.push_back(pointerToCharType);
4744  functionParams.push_back(pointerToCharType);
4745  FunctionType *functionType = FunctionType::get(intType, functionParams, false);
4746  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4747  }
4748  return function;
4749 }
4750 
4751 Function * VuoCompilerCodeGenUtilities::getVuoRetainFunction(Module *module)
4752 {
4753  const char *functionName = "VuoRetain";
4754  Function *function = module->getFunction(functionName);
4755  if (! function)
4756  {
4757  PointerType *voidPointerType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4758  IntegerType *intType = IntegerType::get(module->getContext(), 32);
4759 
4760  vector<Type *> functionParams;
4761  functionParams.push_back(voidPointerType); // pointer
4762  FunctionType *functionType = FunctionType::get(intType, functionParams, false);
4763  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4764  }
4765  return function;
4766 }
4767 
4768 Function * VuoCompilerCodeGenUtilities::getVuoReleaseFunction(Module *module)
4769 {
4770  const char *functionName = "VuoRelease";
4771  Function *function = module->getFunction(functionName);
4772  if (! function)
4773  {
4774  PointerType *voidPointerType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4775  IntegerType *intType = IntegerType::get(module->getContext(), 32);
4776 
4777  vector<Type *> functionParams;
4778  functionParams.push_back(voidPointerType); // pointer
4779  FunctionType *functionType = FunctionType::get(intType, functionParams, false);
4780  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4781  }
4782  return function;
4783 }
4784 
4786 {
4787  string functionName = "compositionGetPortValue";
4788  string moduleKey = module->getModuleIdentifier();
4789  if (! moduleKey.empty())
4790  functionName = VuoStringUtilities::prefixSymbolName(functionName, moduleKey);
4791  Function *function = module->getFunction(functionName.c_str());
4792  if (! function)
4793  {
4794  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
4795  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4796  IntegerType *intType = IntegerType::get(module->getContext(), 32);
4797 
4798  vector<Type *> functionParams;
4799  functionParams.push_back(pointerToCompositionState);
4800  functionParams.push_back(pointerToCharType);
4801  functionParams.push_back(intType);
4802  functionParams.push_back(intType);
4803  FunctionType *functionType = FunctionType::get(pointerToCharType, functionParams, false);
4804  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4805  }
4806  return function;
4807 }
4808 
4810 {
4811  string functionName = "compositionSetPortValue";
4812  string moduleKey = module->getModuleIdentifier();
4813  if (! moduleKey.empty())
4814  functionName = VuoStringUtilities::prefixSymbolName(functionName, moduleKey);
4815  Function *function = module->getFunction(functionName.c_str());
4816  if (! function)
4817  {
4818  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
4819  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4820  Type *boolType = IntegerType::get(module->getContext(), 32);
4821 
4822  vector<Type *> functionParams;
4823  functionParams.push_back(pointerToCompositionState);
4824  functionParams.push_back(pointerToCharType);
4825  functionParams.push_back(pointerToCharType);
4826  functionParams.push_back(boolType);
4827  functionParams.push_back(boolType);
4828  functionParams.push_back(boolType);
4829  functionParams.push_back(boolType);
4830  functionParams.push_back(boolType);
4831  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
4832  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4833  }
4834  return function;
4835 }
4836 
4838 {
4839  string functionName = "compositionFireTriggerPortEvent";
4840  string moduleKey = module->getModuleIdentifier();
4841  if (! moduleKey.empty())
4842  functionName = VuoStringUtilities::prefixSymbolName(functionName, moduleKey);
4843  Function *function = module->getFunction(functionName.c_str());
4844  if (! function)
4845  {
4846  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
4847  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4848 
4849  vector<Type *> functionParams;
4850  functionParams.push_back(pointerToCompositionState);
4851  functionParams.push_back(pointerToCharType);
4852  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
4853  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4854  }
4855  return function;
4856 }
4857 
4859 {
4860  const char *functionName = "vuoSetInputPortValue";
4861  Function *function = module->getFunction(functionName);
4862  if (! function)
4863  {
4864  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4865 
4866  vector<Type *> functionParams;
4867  functionParams.push_back(pointerToCharType);
4868  functionParams.push_back(pointerToCharType);
4869  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
4870  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4871  }
4872  return function;
4873 }
4874 
4876 {
4877  const char *functionName = "getPublishedInputPortValue";
4878  Function *function = module->getFunction(functionName);
4879  if (! function)
4880  {
4881  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4882  IntegerType *intType = IntegerType::get(module->getContext(), 32);
4883 
4884  vector<Type *> functionParams;
4885  functionParams.push_back(pointerToCharType);
4886  functionParams.push_back(intType);
4887  FunctionType *functionType = FunctionType::get(pointerToCharType, functionParams, false);
4888  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4889  }
4890  return function;
4891 }
4892 
4894 {
4895  const char *functionName = "getPublishedOutputPortValue";
4896  Function *function = module->getFunction(functionName);
4897  if (! function)
4898  {
4899  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4900  IntegerType *intType = IntegerType::get(module->getContext(), 32);
4901 
4902  vector<Type *> functionParams;
4903  functionParams.push_back(pointerToCharType);
4904  functionParams.push_back(intType);
4905  FunctionType *functionType = FunctionType::get(pointerToCharType, functionParams, false);
4906  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4907  }
4908  return function;
4909 }
4910 
4912 {
4913  string functionName = "compositionSetPublishedInputPortValue";
4914  string moduleKey = module->getModuleIdentifier();
4915  if (! moduleKey.empty())
4916  functionName = VuoStringUtilities::prefixSymbolName(functionName, moduleKey);
4917  Function *function = module->getFunction(functionName.c_str());
4918  if (! function)
4919  {
4920  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
4921  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4922  Type *boolType = IntegerType::get(module->getContext(), 64);
4923 
4924  vector<Type *> functionParams;
4925  functionParams.push_back(pointerToCompositionState);
4926  functionParams.push_back(pointerToCharType);
4927  functionParams.push_back(pointerToCharType);
4928  functionParams.push_back(boolType);
4929  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
4930  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4931  }
4932  return function;
4933 }
4934 
4936 {
4937  const char *functionName = "setPublishedInputPortValue";
4938  Function *function = module->getFunction(functionName);
4939  if (! function)
4940  {
4941  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4942 
4943  vector<Type *> functionParams;
4944  functionParams.push_back(pointerToCharType);
4945  functionParams.push_back(pointerToCharType);
4946  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
4947  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4948  }
4949  return function;
4950 }
4952 
4958 Type * VuoCompilerCodeGenUtilities::getParameterTypeBeforeLowering(Function *function, Module *module, string typeName)
4959 {
4960  if (typeName == "VuoPoint2d")
4961  return VectorType::get(Type::getFloatTy(module->getContext()), 2);
4962  if (typeName == "VuoPoint3d")
4963  return VectorType::get(Type::getFloatTy(module->getContext()), 3);
4964  if (typeName == "VuoPoint4d")
4965  return VectorType::get(Type::getFloatTy(module->getContext()), 4);
4966 
4967  Type *type = function->getFunctionType()->getParamType(0);
4968  bool hasSecondType = (function->getFunctionType()->getNumParams() == 2);
4969 
4970  // Parameter was originally a struct, but was lowered to a "byval" pointer-to-struct, a vector, or two parameters.
4971  if (isParameterPassedByValue(function, 0) || type->isVectorTy() || hasSecondType)
4972  type = module->getTypeByName("struct." + typeName);
4973 
4974  if (! type)
4975  {
4976  VUserLog("Couldn't guess the original type for %s", typeName.c_str());
4977  function->getFunctionType()->dump(); fprintf(stderr, "\n");
4978  }
4979 
4980  return type;
4981 }
4982 
4993 Value * VuoCompilerCodeGenUtilities::unlowerArgument(VuoCompilerType *unloweredVuoType, Function *function, int parameterIndex,
4994  Module *module, BasicBlock *block)
4995 {
4996  Type *unloweredType = unloweredVuoType->getType();
4997 
4998  Type *secondLoweredType = NULL;
4999  unloweredVuoType->getFunctionParameterType(&secondLoweredType);
5000  bool hasSecondArgument = (secondLoweredType != NULL);
5001 
5002  Function::arg_iterator argIter = function->arg_begin();
5003  for (int i = 0; i < parameterIndex; ++i)
5004  ++argIter;
5005  Value *argument = argIter;
5006  Value *secondArgument = (hasSecondArgument ? ++argIter : NULL);
5007 
5008  if (unloweredType->isVectorTy())
5009  {
5010  if (static_cast<VectorType *>(unloweredType)->getElementType()->isFloatTy())
5011  {
5012  uint64_t elementCount = static_cast<VectorType *>(unloweredType)->getNumElements();
5013  if (elementCount == 2 && argument->getType()->isDoubleTy())
5014  {
5015  // VuoPoint2d — Argument is a vector of 2 floats lowered to a double.
5016  PointerType *pointerToVectorType = PointerType::get(unloweredType, 0);
5017 
5018  Value *vectorVariableAsDouble = generatePointerToValue(block, argument);
5019  Value *vectorVariable = new BitCastInst(vectorVariableAsDouble, pointerToVectorType, "", block);
5020  return new LoadInst(vectorVariable, "", false, block);
5021  }
5022  else if (elementCount == 3 && argument->getType()->isVectorTy() &&
5023  static_cast<VectorType *>(argument->getType())->getNumElements() == 2 &&
5024  static_cast<VectorType *>(argument->getType())->getElementType()->isDoubleTy())
5025  {
5026  // VuoPoint3d — Argument is a vector of 3 floats lowered to a vector of 2 doubles.
5027  PointerType *pointerToFloatVectorType = PointerType::get(unloweredType, 0);
5028 
5029  Value *floatVectorValueAsDoubleVector = generatePointerToValue(block, argument);
5030  Value *floatVectorVariable = new BitCastInst(floatVectorValueAsDoubleVector, pointerToFloatVectorType, "", block);
5031  return new LoadInst(floatVectorVariable, "", false, block);
5032  }
5033  }
5034  }
5035  else if (unloweredType->isStructTy())
5036  {
5037  if (! hasSecondArgument)
5038  {
5039  if (argument->getType()->isVectorTy())
5040  {
5041  // Argument is a struct lowered to a vector.
5042  PointerType *pointerToStructType = PointerType::get(unloweredType, 0);
5043 
5044  Value *structVariableAsVector = generatePointerToValue(block, argument);
5045  Value *structVariable = new BitCastInst(structVariableAsVector, pointerToStructType, "", block);
5046  return new LoadInst(structVariable, "", false, block);
5047  }
5048  }
5049  else
5050  {
5051  // Argument is a struct lowered to two parameters (e.g. two vectors).
5052  PointerType *pointerToStructType = PointerType::get(unloweredType, 0);
5053 
5054  vector<Type *> bothLoweredMembers;
5055  bothLoweredMembers.push_back(argument->getType());
5056  bothLoweredMembers.push_back(secondLoweredType);
5057  StructType *bothLoweredTypes = StructType::create(bothLoweredMembers);
5058 
5059  Value *structVariableAsBothLoweredTypes = new AllocaInst(bothLoweredTypes, "", block);
5060 
5061  ConstantInt *zeroValue = ConstantInt::get(module->getContext(), APInt(32, 0));
5062  ConstantInt *oneValue = ConstantInt::get(module->getContext(), APInt(32, 1));
5063 
5064  vector<Value *> firstMemberIndices;
5065  firstMemberIndices.push_back(zeroValue);
5066  firstMemberIndices.push_back(zeroValue);
5067  Value *firstMemberPointer = GetElementPtrInst::Create(structVariableAsBothLoweredTypes, firstMemberIndices, "", block);
5068  new StoreInst(argument, firstMemberPointer, block);
5069 
5070  vector<Value *> secondMemberIndices;
5071  secondMemberIndices.push_back(zeroValue);
5072  secondMemberIndices.push_back(oneValue);
5073  Value *secondMemberPointer = GetElementPtrInst::Create(structVariableAsBothLoweredTypes, secondMemberIndices, "", block);
5074  new StoreInst(secondArgument, secondMemberPointer, block);
5075 
5076  Value *structVariable = new BitCastInst(structVariableAsBothLoweredTypes, pointerToStructType, "", block);
5077  return new LoadInst(structVariable, "", false, block);
5078  }
5079 
5080  if (isParameterPassedByValue(function, parameterIndex))
5081  {
5082  // Argument is a struct passed by value.
5083  argument = new LoadInst(argument, "", false, block);
5084  }
5085  }
5086 
5087  if (argument->getType() != unloweredType)
5088  {
5089  // Argument type doesn't match parameter type because they're structs loaded from different modules.
5090  if (argument->getType()->isStructTy() && unloweredType->isStructTy())
5091  {
5092  Value *argumentVariable = generatePointerToValue(block, argument);
5093  Type *pointerToUnloweredType = PointerType::get(unloweredType, 0);
5094  Value *argumentVariableAsUnloweredType = new BitCastInst(argumentVariable, pointerToUnloweredType, "", block);
5095  return new LoadInst(argumentVariableAsUnloweredType, "", false, block);
5096  }
5097  else
5098  {
5099  Type *sourceType = argument->getType();
5100  Type *destinationType = unloweredType;
5101  while (sourceType->isPointerTy() && destinationType->isPointerTy())
5102  {
5103  Type *sourceElementType = static_cast<PointerType *>(sourceType)->getElementType();
5104  Type *destinationElementType = static_cast<PointerType *>(destinationType)->getElementType();
5105  if (sourceElementType->isStructTy() && destinationElementType->isStructTy())
5106  return new BitCastInst(argument, unloweredType, "", block);
5107  sourceType = sourceElementType;
5108  destinationType = destinationElementType;
5109  }
5110  }
5111  }
5112 
5113  if (argument->getType() != unloweredType)
5114  {
5115  VUserLog("Couldn't convert argument %d of %s to the type of %s", parameterIndex, function->getName().str().c_str(), unloweredVuoType->getBase()->getModuleKey().c_str());
5116  function->arg_begin()->getType()->dump(); fprintf(stderr, "\n");
5117  argument->getType()->dump(); fprintf(stderr, "\n");
5118  unloweredType->dump(); fprintf(stderr, "\n");
5119  return NULL;
5120  }
5121 
5122  return argument;
5123 }
5124 
5137 Value * VuoCompilerCodeGenUtilities::convertArgumentToParameterType(Value *argument, Function *function, int parameterIndex,
5138  Value **secondArgument, Module *module, BasicBlock *block)
5139 {
5140  return convertArgumentToParameterType(argument, function->getFunctionType(), parameterIndex, isParameterPassedByValue(function, parameterIndex),
5141  secondArgument, module, block);
5142 }
5143 
5157 Value * VuoCompilerCodeGenUtilities::convertArgumentToParameterType(Value *argument, FunctionType *functionType, int parameterIndex, bool isPassedByValue,
5158  Value **secondArgument, Module *module, BasicBlock *block)
5159 {
5160  if (secondArgument)
5161  *secondArgument = NULL;
5162 
5163  Type *parameterType = functionType->getParamType(parameterIndex);
5164 
5165  if (argument->getType()->isVectorTy())
5166  {
5167  if (static_cast<VectorType *>(argument->getType())->getElementType()->isFloatTy())
5168  {
5169  uint64_t elementCount = static_cast<VectorType *>(argument->getType())->getNumElements();
5170  if (elementCount == 2 && parameterType->isDoubleTy())
5171  {
5172  // VuoPoint2d — Argument is a vector of 2 floats lowered to a double.
5173  PointerType *pointerToDoubleType = PointerType::get(parameterType, 0);
5174 
5175  Value *vectorVariable = generatePointerToValue(block, argument);
5176  CastInst *vectorVariableAsDouble = new BitCastInst(vectorVariable, pointerToDoubleType, "", block);
5177  return new LoadInst(vectorVariableAsDouble, "", false, block);
5178  }
5179  else if (elementCount == 3 && parameterType->isVectorTy() &&
5180  static_cast<VectorType *>(parameterType)->getNumElements() == 2 &&
5181  static_cast<VectorType *>(parameterType)->getElementType()->isDoubleTy())
5182  {
5183  // VuoPoint3d — Argument is a vector of 3 floats lowered to a vector of 2 doubles.
5184  PointerType *pointerToDoubleVectorType = PointerType::get(parameterType, 0);
5185 
5186  Value *floatVectorVariable = generatePointerToValue(block, argument);
5187  CastInst *floatVectorVariableAsDoubleVector = new BitCastInst(floatVectorVariable, pointerToDoubleVectorType, "", block);
5188  return new LoadInst(floatVectorVariableAsDoubleVector, "", false, block);
5189  }
5190  else if (elementCount == 2 && parameterType->isPointerTy() && static_cast<PointerType *>(parameterType)->getElementType() == argument->getType())
5191  {
5192  // Workaround for vuo.image.make.checkerboard2 center (https://b33p.net/kosada/node/15936)
5193  // VuoPoint2d — Argument is a vector of 2 floats lowered to a pointer to a vector of 2 floats.
5194  return generatePointerToValue(block, argument);
5195  }
5196  }
5197  }
5198  else if (argument->getType()->isStructTy())
5199  {
5200  if (! secondArgument)
5201  {
5202  if (parameterType->isVectorTy())
5203  {
5204  // Argument is a struct lowered to a vector.
5205  PointerType *pointerToVectorType = PointerType::get(parameterType, 0);
5206 
5207  Value *structVariable = generatePointerToValue(block, argument);
5208  CastInst *structVariableAsVector = new BitCastInst(structVariable, pointerToVectorType, "", block);
5209  return new LoadInst(structVariableAsVector, "", false, block);
5210  }
5211  }
5212  else
5213  {
5214  // Argument is a struct lowered to two parameters (e.g. two vectors).
5215  Type *secondParameterType = functionType->getParamType(parameterIndex + 1);
5216  vector<Type *> bothParameterMembers;
5217  bothParameterMembers.push_back(parameterType);
5218  bothParameterMembers.push_back(secondParameterType);
5219  StructType *bothParameterTypes = StructType::create(bothParameterMembers);
5220  PointerType *pointerToBothParameterTypes = PointerType::get(bothParameterTypes, 0);
5221 
5222  Value *structVariable = generatePointerToValue(block, argument);
5223  CastInst *structVariableAsBothParameterTypes = new BitCastInst(structVariable, pointerToBothParameterTypes, "", block);
5224 
5225  ConstantInt *zeroValue = ConstantInt::get(module->getContext(), APInt(32, 0));
5226  ConstantInt *oneValue = ConstantInt::get(module->getContext(), APInt(32, 1));
5227 
5228  vector<Value *> firstMemberIndices;
5229  firstMemberIndices.push_back(zeroValue);
5230  firstMemberIndices.push_back(zeroValue);
5231  Value *firstMemberPointer = GetElementPtrInst::Create(structVariableAsBothParameterTypes, firstMemberIndices, "", block);
5232  Value *firstMember = new LoadInst(firstMemberPointer, "", false, block);
5233 
5234  vector<Value *> secondMemberIndices;
5235  secondMemberIndices.push_back(zeroValue);
5236  secondMemberIndices.push_back(oneValue);
5237  Value *secondMemberPointer = GetElementPtrInst::Create(structVariableAsBothParameterTypes, secondMemberIndices, "", block);
5238  Value *secondMember = new LoadInst(secondMemberPointer, "", false, block);
5239 
5240  *secondArgument = secondMember;
5241  return firstMember;
5242  }
5243 
5244  if (isPassedByValue)
5245  {
5246  // Argument is a struct passed by value.
5247  argument = generatePointerToValue(block, argument);
5248  }
5249  }
5250 
5251  if (argument->getType() != parameterType)
5252  {
5253  // Argument type doesn't match parameter type because they're structs loaded from different modules.
5254  if (argument->getType()->isStructTy() && parameterType->isStructTy())
5255  {
5256  Value *argumentVariable = generatePointerToValue(block, argument);
5257  Type *pointerToParameterType = PointerType::get(parameterType, 0);
5258  Value *argumentVariableAsParameterType = new BitCastInst(argumentVariable, pointerToParameterType, "", block);
5259  return new LoadInst(argumentVariableAsParameterType, "", false, block);
5260  }
5261  else
5262  {
5263  Type *sourceType = argument->getType();
5264  Type *destinationType = parameterType;
5265  while (sourceType->isPointerTy() && destinationType->isPointerTy())
5266  {
5267  Type *sourceElementType = static_cast<PointerType *>(sourceType)->getElementType();
5268  Type *destinationElementType = static_cast<PointerType *>(destinationType)->getElementType();
5269  if (! sourceElementType->isPointerTy() && ! destinationElementType->isPointerTy())
5270  return new BitCastInst(argument, parameterType, "", block);
5271  sourceType = sourceElementType;
5272  destinationType = destinationElementType;
5273  }
5274  }
5275  }
5276 
5277  if (argument->getType() != parameterType)
5278  {
5279  string s;
5280  raw_string_ostream oss(s);
5281  oss << "Couldn't convert argument type `";
5282  argument->getType()->print(oss);
5283  oss << "` to parameter type `";
5284  parameterType->print(oss);
5285  oss << "` for function: \n\n ";
5286  functionType->print(oss);
5287  VuoCompilerIssue issue(VuoCompilerIssue::Error, "compiling composition", "", "Unsupported composition layout", oss.str());
5288  throw VuoCompilerException(issue);
5289  }
5290 
5291  return argument;
5292 }
5293 
5299 bool VuoCompilerCodeGenUtilities::isParameterPassedByValue(Function *function, int parameterIndex)
5300 {
5301  AttributeSet functionAttrs = function->getAttributes();
5302  AttributeSet paramAttrs = functionAttrs.getParamAttributes(parameterIndex + 1);
5303  return paramAttrs.hasAttrSomewhere(Attribute::ByVal);
5304 }
5305 
5309 Value * VuoCompilerCodeGenUtilities::callFunctionWithStructReturn(Function *function, vector<Value *> args, BasicBlock *block)
5310 {
5311  PointerType *pointerToReturnType = static_cast<PointerType *>(function->getFunctionType()->getParamType(0));
5312  Type *returnType = pointerToReturnType->getElementType();
5313  Value *returnVariable = new AllocaInst(returnType, "", block);
5314  args.insert(args.begin(), returnVariable);
5315  CallInst::Create(function, args, "", block);
5316  return returnVariable;
5317 }
5318 
5324 {
5325  AttributeSet functionAttrs = function->getAttributes();
5326  AttributeSet paramAttrs = functionAttrs.getParamAttributes(1);
5327  return paramAttrs.hasAttrSomewhere(Attribute::StructRet);
5328 }
5329 
5334 FunctionType * VuoCompilerCodeGenUtilities::getFunctionType(Module *module, VuoType *vuoType)
5335 {
5336  vector<Type *> params;
5337 
5338  if (vuoType)
5339  {
5340  Type *secondParamType = NULL;
5341  Type *firstParamType = vuoType->getCompiler()->getFunctionParameterType(&secondParamType);
5342  params.push_back(firstParamType);
5343  if (secondParamType)
5344  params.push_back(secondParamType);
5345  }
5346 
5347  return FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
5348 }
5349 
5353 Value * VuoCompilerCodeGenUtilities::getArgumentAtIndex(Function *function, size_t index)
5354 {
5355  Value *argValue = NULL;
5356 
5357  Function::arg_iterator args = function->arg_begin();
5358  for (size_t i = 0; i <= index && i < function->arg_size(); ++i)
5359  argValue = args++;
5360 
5361  return argValue;
5362 }
5363 
5369 AttributeSet VuoCompilerCodeGenUtilities::copyAttributesToIndex(AttributeSet attributesToCopy, int destinationIndex)
5370 {
5371  if (attributesToCopy.getNumSlots() > 1)
5372  VUserLog("Warning: I was expecting an AttributeSet with 0 or 1 slots, but got %d.", attributesToCopy.getNumSlots());
5373 
5374  int inputIndex = AttributeSet::ReturnIndex + 1;
5375 
5376  string attributeString = attributesToCopy.getAsString(inputIndex);
5377  if (!attributeString.empty()
5378  && attributeString != "byval align 8"
5379  && attributeString != "byval align 16")
5380  VUserLog("Warning: I don't know how to handle all the attributes in '%s'.", attributeString.c_str());
5381 
5382  AttrBuilder builder;
5383 
5384  if (attributesToCopy.hasAttribute(inputIndex, Attribute::ByVal))
5385  builder.addAttribute(Attribute::ByVal);
5386 
5387  if (attributesToCopy.hasAttribute(inputIndex, Attribute::Alignment))
5388  builder.addAlignmentAttr(attributesToCopy.getParamAlignment(inputIndex));
5389 
5390  return AttributeSet::get(getGlobalContext(), destinationIndex, builder);
5391 }