Vuo  2.3.2
VuoCompilerCodeGenUtilities.cc
Go to the documentation of this file.
1 
11 #include "VuoCompiler.hh"
13 #include "VuoCompilerException.hh"
14 #include "VuoCompilerIssue.hh"
15 #include "VuoCompilerPort.hh"
17 #include "VuoCompilerType.hh"
18 #include "VuoPort.hh"
19 #include "VuoStringUtilities.hh"
20 #include "VuoType.hh"
21 
30 Value * VuoCompilerCodeGenUtilities::generateCreateDispatchSemaphore(Module *module, BasicBlock *block, int initialValue)
31 {
32  PointerType *dispatch_semaphore_t_type = getDispatchSemaphoreType(module);
33 
34  Function *dispatch_semaphore_create_function = module->getFunction("dispatch_semaphore_create");
35  if (! dispatch_semaphore_create_function)
36  {
37  vector<Type *> dispatch_semaphore_create_functionParams;
38  dispatch_semaphore_create_functionParams.push_back(IntegerType::get(module->getContext(), 64));
39  FunctionType *dispatch_semaphore_create_functionType = FunctionType::get(dispatch_semaphore_t_type,
40  dispatch_semaphore_create_functionParams,
41  false);
42  dispatch_semaphore_create_function = Function::Create(dispatch_semaphore_create_functionType,
43  GlobalValue::ExternalLinkage,
44  "dispatch_semaphore_create",
45  module);
46  }
47 
48  ConstantInt *initialValueConst = ConstantInt::get(module->getContext(), APInt(64, initialValue));
49  return CallInst::Create(dispatch_semaphore_create_function, initialValueConst, "", block);
50 }
51 
60 Value * VuoCompilerCodeGenUtilities::generateWaitForSemaphore(Module *module, BasicBlock *block, AllocaInst *semaphoreVariable)
61 {
62  LoadInst *semaphoreValue = new LoadInst(semaphoreVariable, "", false, block);
63  return generateWaitForSemaphore(module, block, semaphoreValue);
64 }
65 
75 Value * VuoCompilerCodeGenUtilities::generateWaitForSemaphore(Module *module, BasicBlock *block, AllocaInst *semaphoreVariable, Value *timeoutValue)
76 {
77  LoadInst *semaphoreValue = new LoadInst(semaphoreVariable, "", false, block);
78  return generateWaitForSemaphore(module, block, semaphoreValue, timeoutValue);
79 }
80 
84 Value * VuoCompilerCodeGenUtilities::generateWaitForSemaphore(Module *module, BasicBlock *block, Value *semaphoreValue)
85 {
86  IntegerType *dispatch_time_t_type = IntegerType::get(module->getContext(), 64);
87  Value *timeoutValue = ConstantInt::get(dispatch_time_t_type, DISPATCH_TIME_FOREVER);
88  return generateWaitForSemaphore(module, block, semaphoreValue, timeoutValue);
89 }
90 
94 Value * VuoCompilerCodeGenUtilities::generateWaitForSemaphore(Module *module, BasicBlock *block, Value *semaphoreValue, Value *timeoutValue)
95 {
96  PointerType *dispatch_semaphore_t_type = getDispatchSemaphoreType(module);
97  IntegerType *dispatch_time_t_type = IntegerType::get(module->getContext(), 64);
98 
99  vector<Type *> dispatch_semaphore_wait_functionParams;
100  dispatch_semaphore_wait_functionParams.push_back(dispatch_semaphore_t_type);
101  dispatch_semaphore_wait_functionParams.push_back(dispatch_time_t_type);
102  FunctionType *dispatch_semaphore_wait_functionType = FunctionType::get(IntegerType::get(module->getContext(), 64),
103  dispatch_semaphore_wait_functionParams,
104  false);
105 
106  Function *dispatch_semaphore_wait_function = module->getFunction("dispatch_semaphore_wait");
107  if (! dispatch_semaphore_wait_function) {
108  dispatch_semaphore_wait_function = Function::Create(dispatch_semaphore_wait_functionType,
109  GlobalValue::ExternalLinkage,
110  "dispatch_semaphore_wait",
111  module);
112  }
113 
114  vector<Value *> args;
115  args.push_back(semaphoreValue);
116  args.push_back(timeoutValue);
117  return CallInst::Create(dispatch_semaphore_wait_function, args, "", block);
118 }
119 
123 void VuoCompilerCodeGenUtilities::generateSignalForSemaphore(Module *module, BasicBlock *block, AllocaInst *semaphoreVariable)
124 {
125  LoadInst *semaphoreValue = new LoadInst(semaphoreVariable, "", false, block);
126  return generateSignalForSemaphore(module, block, semaphoreValue);
127 }
128 
132 void VuoCompilerCodeGenUtilities::generateSignalForSemaphore(Module *module, BasicBlock *block, Value *semaphoreValue)
133 {
134  PointerType *dispatch_semaphore_t_type = getDispatchSemaphoreType(module);
135 
136  vector<Type *> dispatch_semaphore_signal_functionParams;
137  dispatch_semaphore_signal_functionParams.push_back(dispatch_semaphore_t_type);
138  FunctionType *dispatch_semaphore_signal_functionType = FunctionType::get(IntegerType::get(module->getContext(), 64),
139  dispatch_semaphore_signal_functionParams,
140  false);
141 
142  Function *dispatch_semaphore_signal_function = module->getFunction("dispatch_semaphore_signal");
143  if (! dispatch_semaphore_signal_function) {
144  dispatch_semaphore_signal_function = Function::Create(dispatch_semaphore_signal_functionType,
145  GlobalValue::ExternalLinkage,
146  "dispatch_semaphore_signal",
147  module);
148  }
149 
150  CallInst::Create(dispatch_semaphore_signal_function, semaphoreValue, "", block);
151 }
152 
160 Value * VuoCompilerCodeGenUtilities::generateCreateDispatchGroup(Module *module, BasicBlock *block)
161 {
162  Function *dispatch_group_create_function = module->getFunction("dispatch_group_create");
163  if (! dispatch_group_create_function)
164  {
165  vector<Type *> dispatch_group_create_functionParams;
166  FunctionType *dispatch_group_create_functionType = FunctionType::get(getDispatchGroupType(module),
167  dispatch_group_create_functionParams,
168  false);
169  dispatch_group_create_function = Function::Create(dispatch_group_create_functionType,
170  GlobalValue::ExternalLinkage,
171  "dispatch_group_create", module);
172  }
173 
174  return CallInst::Create(dispatch_group_create_function, "", block);
175 }
176 
180 void VuoCompilerCodeGenUtilities::generateEnterDispatchGroup(Module *module, BasicBlock *block, Value *dispatchGroupValue)
181 {
182  Function *dispatch_group_enter_function = module->getFunction("dispatch_group_enter");
183  if (! dispatch_group_enter_function)
184  {
185  PointerType *dispatch_group_t_type = getDispatchGroupType(module);
186  FunctionType *dispatch_group_enter_functionType = FunctionType::get(Type::getVoidTy(module->getContext()),
187  dispatch_group_t_type,
188  false);
189  dispatch_group_enter_function = Function::Create(dispatch_group_enter_functionType,
190  GlobalValue::ExternalLinkage,
191  "dispatch_group_enter",
192  module);
193  }
194 
195  CallInst::Create(dispatch_group_enter_function, dispatchGroupValue, "", block);
196 }
197 
201 void VuoCompilerCodeGenUtilities::generateLeaveDispatchGroup(Module *module, BasicBlock *block, Value *dispatchGroupValue)
202 {
203  Function *dispatch_group_leave_function = module->getFunction("dispatch_group_leave");
204  if (! dispatch_group_leave_function)
205  {
206  PointerType *dispatch_group_t_type = getDispatchGroupType(module);
207  FunctionType *dispatch_group_leave_functionType = FunctionType::get(Type::getVoidTy(module->getContext()),
208  dispatch_group_t_type,
209  false);
210  dispatch_group_leave_function = Function::Create(dispatch_group_leave_functionType,
211  GlobalValue::ExternalLinkage,
212  "dispatch_group_leave",
213  module);
214  }
215 
216  CallInst::Create(dispatch_group_leave_function, dispatchGroupValue, "", block);
217 }
218 
222 void VuoCompilerCodeGenUtilities::generateWaitForDispatchGroup(Module *module, BasicBlock *block, Value *dispatchGroupValue,
223  dispatch_time_t timeout)
224 {
225  Function *dispatch_group_wait_function = module->getFunction("dispatch_group_wait");
226  if (! dispatch_group_wait_function)
227  {
228  PointerType *dispatch_group_t_type = getDispatchGroupType(module);
229 
230  vector<Type *> dispatch_group_wait_functionParams;
231  dispatch_group_wait_functionParams.push_back(dispatch_group_t_type);
232  dispatch_group_wait_functionParams.push_back(IntegerType::get(module->getContext(), 64));
233  FunctionType *dispatch_group_wait_functionType = FunctionType::get(IntegerType::get(module->getContext(), 64),
234  dispatch_group_wait_functionParams,
235  false);
236 
237  dispatch_group_wait_function = Function::Create(dispatch_group_wait_functionType,
238  GlobalValue::ExternalLinkage,
239  "dispatch_group_wait",
240  module);
241  }
242 
243  ConstantInt *timeout_value = ConstantInt::get(module->getContext(), APInt(64, timeout, true));
244 
245  vector<Value *> args;
246  args.push_back(dispatchGroupValue);
247  args.push_back(timeout_value);
248  CallInst::Create(dispatch_group_wait_function, args, "", block);
249 }
250 
254 Value * VuoCompilerCodeGenUtilities::generateGetGlobalDispatchQueue(Module *module, BasicBlock *block)
255 {
256  PointerType *dispatch_queue_t_type = getDispatchQueueType(module);
257 
258  vector<Type *> dispatch_get_global_queue_functionParams;
259  dispatch_get_global_queue_functionParams.push_back(IntegerType::get(module->getContext(), 64));
260  dispatch_get_global_queue_functionParams.push_back(IntegerType::get(module->getContext(), 64));
261  FunctionType *dispatch_get_global_queue_functionType = FunctionType::get(dispatch_queue_t_type,
262  dispatch_get_global_queue_functionParams,
263  false);
264 
265  Function *dispatch_get_global_queue_function = module->getFunction("dispatch_get_global_queue");
266  if (! dispatch_get_global_queue_function) {
267  dispatch_get_global_queue_function = Function::Create(dispatch_get_global_queue_functionType,
268  GlobalValue::ExternalLinkage,
269  "dispatch_get_global_queue",
270  module);
271  }
272 
273  Constant *zeroValue = ConstantInt::get(dispatch_get_global_queue_functionType->getParamType(0), 0);
274 
275  vector<Value *> args;
276  args.push_back(zeroValue);
277  args.push_back(zeroValue);
278  return CallInst::Create(dispatch_get_global_queue_function, args, "", block);
279 }
280 
289 Value * VuoCompilerCodeGenUtilities::generateCreateDispatchQueue(Module *module, BasicBlock *block, string dispatchQueueName)
290 {
291  PointerType *dispatch_queue_t_type = getDispatchQueueType(module);
292  PointerType *pointerToi8 = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
293 
294  StructType *dispatch_queue_attr_s_type = module->getTypeByName("struct.dispatch_queue_attr_s");
295  if (! dispatch_queue_attr_s_type)
296  dispatch_queue_attr_s_type = StructType::create(module->getContext(), "struct.dispatch_queue_attr_s");
297  PointerType *dispatch_queue_attr_t_type = PointerType::get(dispatch_queue_attr_s_type, 0);
298 
299  vector<Type *> dispatch_queue_create_functionParams;
300  dispatch_queue_create_functionParams.push_back(pointerToi8);
301  dispatch_queue_create_functionParams.push_back(dispatch_queue_attr_t_type);
302  FunctionType *dispatch_queue_create_functionType = FunctionType::get(dispatch_queue_t_type,
303  dispatch_queue_create_functionParams,
304  false);
305 
306  Function *dispatch_queue_create_function = module->getFunction("dispatch_queue_create");
307  if (! dispatch_queue_create_function)
308  {
309  dispatch_queue_create_function = Function::Create(dispatch_queue_create_functionType,
310  GlobalValue::ExternalLinkage,
311  "dispatch_queue_create",
312  module);
313  }
314 
315  ArrayType *dispatchQueueNameType = ArrayType::get(IntegerType::get(module->getContext(), 8), dispatchQueueName.length() + 1);
316  GlobalVariable *dispatchQueueNameVariable = new GlobalVariable(*module,
317  dispatchQueueNameType,
318  true,
319  GlobalValue::InternalLinkage,
320  0,
321  ".str");
322  Constant *dispatchQueueNameValue = ConstantDataArray::getString(module->getContext(), dispatchQueueName, true);
323  dispatchQueueNameVariable->setInitializer(dispatchQueueNameValue);
324 
325  ConstantInt *zeroi64Value = ConstantInt::get(module->getContext(), APInt(64, 0));
326  ConstantPointerNull *nullValue = ConstantPointerNull::get(dispatch_queue_attr_t_type);
327 
328  std::vector<Constant*> dispatchQueueLabel_indices;
329  dispatchQueueLabel_indices.push_back(zeroi64Value);
330  dispatchQueueLabel_indices.push_back(zeroi64Value);
331  Constant *dispatchQueueLabel = ConstantExpr::getGetElementPtr(dispatchQueueNameType, dispatchQueueNameVariable, dispatchQueueLabel_indices);
332 
333  vector<Value *> args;
334  args.push_back(dispatchQueueLabel);
335  args.push_back(nullValue);
336  return CallInst::Create(dispatch_queue_create_function, args, "", block);
337 }
338 
342 void VuoCompilerCodeGenUtilities::generateAsynchronousSubmissionToDispatchQueue(Module *module, BasicBlock *block, Value *dispatchQueueValue,
343  Function *workerFunction, Value *contextValue)
344 {
345  generateSubmissionToDispatchQueue(module, block, dispatchQueueValue, workerFunction, contextValue, false);
346 }
347 
351 void VuoCompilerCodeGenUtilities::generateSynchronousSubmissionToDispatchQueue(Module *module, BasicBlock *block, Value *dispatchQueueValue,
352  Function *workerFunction, Value *contextValue)
353 {
354  generateSubmissionToDispatchQueue(module, block, dispatchQueueValue, workerFunction, contextValue, true);
355 }
356 
360 void VuoCompilerCodeGenUtilities::generateSubmissionToDispatchQueue(Module *module, BasicBlock *block, Value *dispatchQueueValue,
361  Function *workerFunction, Value *contextValue, bool isSynchronous)
362 {
363  PointerType *dispatch_queue_t_type = getDispatchQueueType(module);
364  PointerType *pointerToi8 = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
365 
366  vector<Type *> dispatchSubmitFunctionParams;
367  dispatchSubmitFunctionParams.push_back(dispatch_queue_t_type);
368  dispatchSubmitFunctionParams.push_back(pointerToi8);
369  dispatchSubmitFunctionParams.push_back(workerFunction->getType());
370  FunctionType *dispatchSubmitFunctionType = FunctionType::get(Type::getVoidTy(module->getContext()),
371  dispatchSubmitFunctionParams,
372  false);
373 
374  const char *dispatchSubmitFunctionName = (isSynchronous ? "dispatch_sync_f" : "dispatch_async_f");
375  Function *dispatchSubmitFunction = module->getFunction(dispatchSubmitFunctionName);
376  if (! dispatchSubmitFunction) {
377  dispatchSubmitFunction = Function::Create(dispatchSubmitFunctionType,
378  GlobalValue::ExternalLinkage,
379  dispatchSubmitFunctionName,
380  module);
381  }
382 
383  vector<Value *> args;
384  args.push_back(dispatchQueueValue);
385  args.push_back(contextValue);
386  args.push_back(workerFunction);
387  CallInst::Create(dispatchSubmitFunction, args, "", block);
388 }
389 
393 Value * VuoCompilerCodeGenUtilities::generateConversionToDispatchObject(Module *module, BasicBlock *block, Value *dispatchObjectVariable)
394 {
395  PointerType *pointerToi8Type = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
396  PointerType *dispatchObjectOriginalType = cast<PointerType>(dispatchObjectVariable->getType());
397  StructType *dispatch_object_t_type = getDispatchObjectType(module);
398 
399  vector<Type *> llvm_memcpy_p0i8_p0i8_i64_functionParams;
400  llvm_memcpy_p0i8_p0i8_i64_functionParams.push_back(pointerToi8Type);
401  llvm_memcpy_p0i8_p0i8_i64_functionParams.push_back(pointerToi8Type);
402  llvm_memcpy_p0i8_p0i8_i64_functionParams.push_back(IntegerType::get(module->getContext(), 64));
403  llvm_memcpy_p0i8_p0i8_i64_functionParams.push_back(IntegerType::get(module->getContext(), 32));
404  llvm_memcpy_p0i8_p0i8_i64_functionParams.push_back(IntegerType::get(module->getContext(), 1));
405  FunctionType *llvm_memcpy_p0i8_p0i8_i64_functionType = FunctionType::get(Type::getVoidTy(module->getContext()), llvm_memcpy_p0i8_p0i8_i64_functionParams, false);
406  Function *llvm_memcpy_p0i8_p0i8_i64_function = module->getFunction("llvm.memcpy.p0i8.p0i8.i64");
407  if (! llvm_memcpy_p0i8_p0i8_i64_function)
408  llvm_memcpy_p0i8_p0i8_i64_function = Function::Create(llvm_memcpy_p0i8_p0i8_i64_functionType, GlobalValue::ExternalLinkage, "llvm.memcpy.p0i8.p0i8.i64", module);
409 
410  ConstantInt *zeroValue32 = ConstantInt::get(module->getContext(), APInt(32, 0));
411  ConstantInt *zeroValue1 = ConstantInt::get(module->getContext(), APInt(1, 0));
412  ConstantInt *eightValue64 = ConstantInt::get(module->getContext(), APInt(64, 8));
413  ConstantInt *eightValue32 = ConstantInt::get(module->getContext(), APInt(32, 8));
414 
415  AllocaInst *dispatchObjectUnion = new AllocaInst(dispatch_object_t_type, 0, "", block);
416  AllocaInst *compoundLiteral = new AllocaInst(dispatch_object_t_type, 0, "", block);
417 
418  CastInst *compoundLiteralAsDispatchObjectOriginalType = new BitCastInst(compoundLiteral, dispatchObjectOriginalType, "", block);
419  LoadInst *dispatchObjectValue = new LoadInst(dispatchObjectVariable, "", false, block);
420  new StoreInst(dispatchObjectValue, compoundLiteralAsDispatchObjectOriginalType, false, block);
421 
422  CastInst *dispatchObjectUnionAsPointerToi8 = new BitCastInst(dispatchObjectUnion, pointerToi8Type, "", block);
423  CastInst *compoundLiteralAsPointerToi8 = new BitCastInst(compoundLiteral, pointerToi8Type, "", block);
424 
425  std::vector<Value *> llvm_memcpy_p0i8_p0i8_i64_functionArgs;
426  llvm_memcpy_p0i8_p0i8_i64_functionArgs.push_back(dispatchObjectUnionAsPointerToi8);
427  llvm_memcpy_p0i8_p0i8_i64_functionArgs.push_back(compoundLiteralAsPointerToi8);
428  llvm_memcpy_p0i8_p0i8_i64_functionArgs.push_back(eightValue64);
429  llvm_memcpy_p0i8_p0i8_i64_functionArgs.push_back(eightValue32);
430  llvm_memcpy_p0i8_p0i8_i64_functionArgs.push_back(zeroValue1);
431  CallInst::Create(llvm_memcpy_p0i8_p0i8_i64_function, llvm_memcpy_p0i8_p0i8_i64_functionArgs, "", block);
432 
433  vector<Value *> gepIndices;
434  gepIndices.push_back(zeroValue32);
435  gepIndices.push_back(zeroValue32);
436  Instruction *dispatchObjectUnionMember = GetElementPtrInst::Create(dispatch_object_t_type, dispatchObjectUnion, gepIndices, "", block);
437  return new LoadInst(dispatchObjectUnionMember, "", false, block);
438 }
439 
447 void VuoCompilerCodeGenUtilities::generateRetainForDispatchObject(Module *module, BasicBlock *block, Value *dispatchObjectVariable)
448 {
449  Value *dispatchObjectValueAsDispatchObject = generateConversionToDispatchObject(module, block, dispatchObjectVariable);
450 
451  StructType *dispatch_object_s_type = getDispatchObjectElementType(module);
452  PointerType *pointerTo_dispatch_object_s_type = PointerType::get(dispatch_object_s_type, 0);
453 
454  vector<Type*> dispatchRetainFunctionParams;
455  dispatchRetainFunctionParams.push_back(pointerTo_dispatch_object_s_type);
456  FunctionType *dispatchRetainFunctionType = FunctionType::get(Type::getVoidTy(module->getContext()), dispatchRetainFunctionParams, false);
457  Function *dispatchRetainFunction = module->getFunction("dispatch_retain");
458  if (! dispatchRetainFunction)
459  dispatchRetainFunction = Function::Create(dispatchRetainFunctionType, GlobalValue::ExternalLinkage, "dispatch_retain", module);
460 
461  CallInst::Create(dispatchRetainFunction, dispatchObjectValueAsDispatchObject, "", block);
462 }
463 
471 void VuoCompilerCodeGenUtilities::generateFinalizationForDispatchObject(Module *module, BasicBlock *block, Value *dispatchObjectVariable)
472 {
473  Value *dispatchObjectValueAsDispatchObject = generateConversionToDispatchObject(module, block, dispatchObjectVariable);
474 
475  StructType *dispatch_object_s_type = getDispatchObjectElementType(module);
476  PointerType *pointerTo_dispatch_object_s_type = PointerType::get(dispatch_object_s_type, 0);
477 
478  vector<Type*> dispatchReleaseFunctionParams;
479  dispatchReleaseFunctionParams.push_back(pointerTo_dispatch_object_s_type);
480  FunctionType *dispatchReleaseFunctionType = FunctionType::get(Type::getVoidTy(module->getContext()), dispatchReleaseFunctionParams, false);
481  Function *dispatchReleaseFunction = module->getFunction("dispatch_release");
482  if (! dispatchReleaseFunction)
483  dispatchReleaseFunction = Function::Create(dispatchReleaseFunctionType, GlobalValue::ExternalLinkage, "dispatch_release", module);
484 
485  CallInst::Create(dispatchReleaseFunction, dispatchObjectValueAsDispatchObject, "", block);
486 }
487 
496 Value * VuoCompilerCodeGenUtilities::generateCreateDispatchTime(Module *module, BasicBlock *block, Value *deltaValue)
497 {
498  Type *dispatch_time_t_type = IntegerType::get(module->getContext(), 64);
499 
500  vector<Type *> dispatch_time_functionParams;
501  dispatch_time_functionParams.push_back(dispatch_time_t_type);
502  dispatch_time_functionParams.push_back(IntegerType::get(module->getContext(), 64));
503  FunctionType *dispatch_time_functionType = FunctionType::get(dispatch_time_t_type,
504  dispatch_time_functionParams,
505  false);
506 
507  Function *dispatch_time_function = module->getFunction("dispatch_time");
508  if (! dispatch_time_function) {
509  dispatch_time_function = Function::Create(dispatch_time_functionType,
510  GlobalValue::ExternalLinkage,
511  "dispatch_time",
512  module);
513  }
514 
515  ConstantInt *whenValue = ConstantInt::get(module->getContext(), APInt(64, DISPATCH_TIME_NOW));
516 
517  vector<Value *> args;
518  args.push_back(whenValue);
519  args.push_back(deltaValue);
520  return CallInst::Create(dispatch_time_function, args, "", block);
521 }
522 
533 Value * VuoCompilerCodeGenUtilities::generateCreatePortContext(Module *module, BasicBlock *block, VuoCompilerType *dataType,
534  bool isTrigger, string triggerQueueName)
535 {
536  IntegerType *boolType = IntegerType::get(module->getContext(), 64);
537  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
538  PointerType *voidPointerType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
539 
540  const char *functionName = "vuoCreatePortContext";
541  Function *function = module->getFunction(functionName);
542  if (! function)
543  {
544  PointerType *pointerToPortContext = PointerType::get(getPortContextType(module), 0);
545 
546  vector<Type *> params;
547  params.push_back(voidPointerType);
548  params.push_back(boolType);
549  params.push_back(pointerToCharType);
550 
551  FunctionType *functionType = FunctionType::get(pointerToPortContext, params, false);
552  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
553  }
554 
555  Value *pointerToDataAsVoidPointer;
556  if (dataType)
557  {
558  Value *pointerToData = VuoCompilerCodeGenUtilities::generateMemoryAllocation(module, block, dataType->getSize(module));
559  pointerToDataAsVoidPointer = new BitCastInst(pointerToData, voidPointerType, "", block);
560  }
561  else
562  pointerToDataAsVoidPointer = ConstantPointerNull::get(voidPointerType);
563 
564  vector<Value *> args;
565  args.push_back(pointerToDataAsVoidPointer);
566  args.push_back(ConstantInt::get(boolType, isTrigger));
567  args.push_back(generatePointerToConstantString(module, triggerQueueName));
568  return CallInst::Create(function, args, "", block);
569 }
570 
579 void VuoCompilerCodeGenUtilities::generateSetPortContextEvent(Module *module, BasicBlock *block, Value *portContextValue, Value *eventValue)
580 {
581  const char *functionName = "vuoSetPortContextEvent";
582  Function *function = module->getFunction(functionName);
583  if (! function)
584  {
585  StructType *portContextType = getPortContextType(module);
586  PointerType *pointerToPortContext = PointerType::get(portContextType, 0);
587  Type *boolType = portContextType->getElementType(0);
588 
589  vector<Type *> params;
590  params.push_back(pointerToPortContext);
591  params.push_back(boolType);
592  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
593  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
594  }
595 
596  vector<Value *> args;
597  args.push_back(portContextValue);
598  args.push_back(eventValue);
599  CallInst::Create(function, args, "", block);
600 }
601 
611 void VuoCompilerCodeGenUtilities::generateSetPortContextData(Module *module, BasicBlock *block, Value *portContextValue, Value *dataValue, VuoCompilerType *dataType)
612 {
613  Value *pointerToData = generateGetPortContextDataVariable(module, block, portContextValue, dataType);
614  new StoreInst(dataValue, pointerToData, false, block);
615 }
616 
625 void VuoCompilerCodeGenUtilities::generateSetPortContextTriggerFunction(Module *module, BasicBlock *block, Value *portContextValue, Value *triggerFunctionValue)
626 {
627  const char *functionName = "vuoSetPortContextTriggerFunction";
628  Function *function = module->getFunction(functionName);
629  if (! function)
630  {
631  StructType *portContextType = getPortContextType(module);
632  PointerType *pointerToPortContext = PointerType::get(portContextType, 0);
633  Type *triggerFunctionType = portContextType->getElementType(5);
634 
635  vector<Type *> params;
636  params.push_back(pointerToPortContext);
637  params.push_back(triggerFunctionType);
638  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
639  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
640  }
641 
642  PointerType *voidPointerType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
643  Value *triggerFunctionAsVoidPointer = new BitCastInst(triggerFunctionValue, voidPointerType, "", block);
644 
645  vector<Value *> args;
646  args.push_back(portContextValue);
647  args.push_back(triggerFunctionAsVoidPointer);
648  CallInst::Create(function, args, "", block);
649 }
650 
659 Value * VuoCompilerCodeGenUtilities::generateGetPortContextEvent(Module *module, BasicBlock *block, Value *portContextValue)
660 {
661  const char *functionName = "vuoGetPortContextEvent";
662  Function *function = module->getFunction(functionName);
663  if (! function)
664  {
665  StructType *portContextType = getPortContextType(module);
666  PointerType *pointerToPortContext = PointerType::get(portContextType, 0);
667  Type *boolType = portContextType->getElementType(0);
668 
669  FunctionType *functionType = FunctionType::get(boolType, pointerToPortContext, false);
670  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
671  }
672 
673  return CallInst::Create(function, portContextValue, "", block);
674 }
675 
685 Value * VuoCompilerCodeGenUtilities::generateGetPortContextDataVariable(Module *module, BasicBlock *block, Value *portContextValue, VuoCompilerType *dataType)
686 {
687  Value *pointerToDataAsVoidPointer = generateGetPortContextDataVariableAsVoidPointer(module, block, portContextValue);
688  return dataType->convertToPortData(block, pointerToDataAsVoidPointer);
689 }
690 
699 Value * VuoCompilerCodeGenUtilities::generateGetPortContextDataVariableAsVoidPointer(Module *module, BasicBlock *block, Value *portContextValue)
700 {
701  const char *functionName = "vuoGetPortContextData";
702  Function *function = module->getFunction(functionName);
703  if (! function)
704  {
705  StructType *portContextType = getPortContextType(module);
706  PointerType *pointerToPortContext = PointerType::get(portContextType, 0);
707  Type *voidPointerType = portContextType->getElementType(1);
708 
709  FunctionType *functionType = FunctionType::get(voidPointerType, pointerToPortContext, false);
710  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
711  }
712 
713  return CallInst::Create(function, portContextValue, "", block);
714 }
715 
724 Value * VuoCompilerCodeGenUtilities::generateGetPortContextTriggerQueue(Module *module, BasicBlock *block, Value *portContextValue)
725 {
726  const char *functionName = "vuoGetPortContextTriggerQueue";
727  Function *function = module->getFunction(functionName);
728  if (! function)
729  {
730  StructType *portContextType = getPortContextType(module);
731  PointerType *pointerToPortContext = PointerType::get(portContextType, 0);
732  Type *dispatchQueueType = portContextType->getElementType(3);
733 
734  FunctionType *functionType = FunctionType::get(dispatchQueueType, pointerToPortContext, false);
735  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
736  }
737 
738  return CallInst::Create(function, portContextValue, "", block);
739 }
740 
749 Value * VuoCompilerCodeGenUtilities::generateGetPortContextTriggerSemaphore(Module *module, BasicBlock *block, Value *portContextValue)
750 {
751  const char *functionName = "vuoGetPortContextTriggerSemaphore";
752  Function *function = module->getFunction(functionName);
753  if (! function)
754  {
755  StructType *portContextType = getPortContextType(module);
756  PointerType *pointerToPortContext = PointerType::get(portContextType, 0);
757  Type *dispatchSemaphoreType = portContextType->getElementType(4);
758 
759  FunctionType *functionType = FunctionType::get(dispatchSemaphoreType, pointerToPortContext, false);
760  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
761  }
762 
763  return CallInst::Create(function, portContextValue, "", block);
764 }
765 
775 Value * VuoCompilerCodeGenUtilities::generateGetPortContextTriggerFunction(Module *module, BasicBlock *block, Value *portContextValue, FunctionType *functionType)
776 {
777  const char *functionName = "vuoGetPortContextTriggerFunction";
778  Function *function = module->getFunction(functionName);
779  if (! function)
780  {
781  StructType *portContextType = getPortContextType(module);
782  PointerType *pointerToPortContext = PointerType::get(portContextType, 0);
783  Type *triggerFunctionType = portContextType->getElementType(5);
784 
785  FunctionType *functionType = FunctionType::get(triggerFunctionType, pointerToPortContext, false);
786  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
787  }
788 
789  Value *triggerFunctionAsVoidPointer = CallInst::Create(function, portContextValue, "", block);
790  PointerType *pointerToTriggerFunctionType = PointerType::get(functionType, 0);
791  return new BitCastInst(triggerFunctionAsVoidPointer, pointerToTriggerFunctionType, "", block);
792 }
793 
801 void VuoCompilerCodeGenUtilities::generateRetainPortContextData(Module *module, BasicBlock *block, Value *portContextValue)
802 {
803  const char *functionName = "vuoRetainPortContextData";
804  Function *function = module->getFunction(functionName);
805  if (! function)
806  {
807  StructType *portContextType = getPortContextType(module);
808  PointerType *pointerToPortContext = PointerType::get(portContextType, 0);
809 
810  vector<Type *> params;
811  params.push_back(pointerToPortContext);
812  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
813  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
814  }
815 
816  vector<Value *> args;
817  args.push_back(portContextValue);
818  CallInst::Create(function, args, "", block);
819 }
820 
831 Value * VuoCompilerCodeGenUtilities::generateCreateNodeContext(Module *module, BasicBlock *block, bool hasInstanceData,
832  bool isComposition, size_t outputEventCount)
833 {
834  IntegerType *boolType = IntegerType::get(module->getContext(), 64);
835  IntegerType *sizeType = IntegerType::get(module->getContext(), 64);
836 
837  const char *functionName = "vuoCreateNodeContext";
838  Function *function = module->getFunction(functionName);
839  if (! function)
840  {
841  PointerType *pointerToNodeContext = PointerType::get(getNodeContextType(module), 0);
842 
843  vector<Type *> params;
844  params.push_back(boolType);
845  params.push_back(boolType);
846  params.push_back(sizeType);
847 
848  FunctionType *functionType = FunctionType::get(pointerToNodeContext, params, false);
849  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
850  }
851 
852  vector<Value *> args;
853  args.push_back(ConstantInt::get(boolType, hasInstanceData));
854  args.push_back(ConstantInt::get(boolType, isComposition));
855  args.push_back(ConstantInt::get(sizeType, outputEventCount));
856  return CallInst::Create(function, args, "", block);
857 }
858 
867 void VuoCompilerCodeGenUtilities::generateSetNodeContextPortContexts(Module *module, BasicBlock *block, Value *nodeContextValue, vector<Value *> portContextValues)
868 {
869  PointerType *pointerToPortContext = PointerType::get(getPortContextType(module), 0);
870  PointerType *pointerToPointerToPortContext = PointerType::get(pointerToPortContext, 0);
871  IntegerType *sizeType = IntegerType::get(module->getContext(), 64);
872 
873  Value *portContextsArrayValue = generateMemoryAllocation(module, block, pointerToPortContext, portContextValues.size());
874  for (size_t i = 0; i < portContextValues.size(); ++i)
875  generateSetArrayElement(module, block, portContextsArrayValue, i, portContextValues[i]);
876 
877  const char *functionName = "vuoSetNodeContextPortContexts";
878  Function *function = module->getFunction(functionName);
879  if (! function)
880  {
881  StructType *nodeContextType = getNodeContextType(module);
882  PointerType *pointerToNodeContext = PointerType::get(nodeContextType, 0);
883 
884  vector<Type *> params;
885  params.push_back(pointerToNodeContext);
886  params.push_back(pointerToPointerToPortContext);
887  params.push_back(sizeType);
888  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
889  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
890  }
891 
892  vector<Value *> args;
893  args.push_back(nodeContextValue);
894  args.push_back(portContextsArrayValue);
895  args.push_back(ConstantInt::get(sizeType, portContextValues.size()));
896  CallInst::Create(function, args, "", block);
897 }
898 
907 void VuoCompilerCodeGenUtilities::generateSetNodeContextInstanceData(Module *module, BasicBlock *block, Value *nodeContextValue, Value *instanceDataValue)
908 {
909  StructType *nodeContextType = getNodeContextType(module);
910  Type *voidPointerType = nodeContextType->getElementType(2);
911 
912  const char *functionName = "vuoSetNodeContextInstanceData";
913  Function *function = module->getFunction(functionName);
914  if (! function)
915  {
916  PointerType *pointerToNodeContext = PointerType::get(nodeContextType, 0);
917 
918  vector<Type *> params;
919  params.push_back(pointerToNodeContext);
920  params.push_back(voidPointerType);
921  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
922  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
923  }
924 
925  Value *pointerToInstanceData = VuoCompilerCodeGenUtilities::generateMemoryAllocation(module, block, instanceDataValue->getType(), 1);
926  new StoreInst(instanceDataValue, pointerToInstanceData, false, block);
927  Value *pointerToInstanceDataAsVoidPointer = new BitCastInst(pointerToInstanceData, voidPointerType, "", block);
928 
929  vector<Value *> args;
930  args.push_back(nodeContextValue);
931  args.push_back(pointerToInstanceDataAsVoidPointer);
932  CallInst::Create(function, args, "", block);
933 }
934 
943 void VuoCompilerCodeGenUtilities::generateSetNodeContextClaimingEventId(Module *module, BasicBlock *block, Value *nodeContextValue, Value *claimingEventIdValue)
944 {
945  const char *functionName = "vuoSetNodeContextClaimingEventId";
946  Function *function = module->getFunction(functionName);
947  if (! function)
948  {
949  StructType *nodeContextType = getNodeContextType(module);
950  PointerType *pointerToNodeContext = PointerType::get(nodeContextType, 0);
951  Type *eventIdType = nodeContextType->getElementType(4);
952 
953  vector<Type *> params;
954  params.push_back(pointerToNodeContext);
955  params.push_back(eventIdType);
956  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
957  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
958  }
959 
960  vector<Value *> args;
961  args.push_back(nodeContextValue);
962  args.push_back(claimingEventIdValue);
963  CallInst::Create(function, args, "", block);
964 }
965 
975 void VuoCompilerCodeGenUtilities::generateSetNodeContextOutputEvent(Module *module, BasicBlock *block, Value *nodeContextValue, size_t index, Value *eventValue)
976 {
977  Type *sizeType = IntegerType::get(module->getContext(), 64);
978 
979  const char *functionName = "vuoSetNodeContextOutputEvent";
980  Function *function = module->getFunction(functionName);
981  if (! function)
982  {
983  StructType *nodeContextType = getNodeContextType(module);
984  PointerType *pointerToNodeContext = PointerType::get(nodeContextType, 0);
985  Type *boolType = IntegerType::get(module->getContext(), 64);
986 
987  vector<Type *> params;
988  params.push_back(pointerToNodeContext);
989  params.push_back(sizeType);
990  params.push_back(boolType);
991  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
992  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
993  }
994 
995  eventValue = new ZExtInst(eventValue, sizeType, "", block);
996 
997  vector<Value *> args;
998  args.push_back(nodeContextValue);
999  args.push_back(ConstantInt::get(sizeType, index));
1000  args.push_back(eventValue);
1001  CallInst::Create(function, args, "", block);
1002 }
1003 
1013 Value * VuoCompilerCodeGenUtilities::generateGetNodeContextPortContext(Module *module, BasicBlock *block, Value *nodeContextValue, int index)
1014 {
1015  Type *indexType = IntegerType::get(module->getContext(), 64);
1016 
1017  const char *functionName = "vuoGetNodeContextPortContext";
1018  Function *function = module->getFunction(functionName);
1019  if (! function)
1020  {
1021  StructType *nodeContextType = getNodeContextType(module);
1022  PointerType *pointerToNodeContext = PointerType::get(nodeContextType, 0);
1023  StructType *portContextType = getPortContextType(module);
1024  PointerType *pointerToPortContext = PointerType::get(portContextType, 0);
1025 
1026  vector<Type *> params;
1027  params.push_back(pointerToNodeContext);
1028  params.push_back(indexType);
1029 
1030  FunctionType *functionType = FunctionType::get(pointerToPortContext, params, false);
1031  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1032  }
1033 
1034  vector<Value *> args;
1035  args.push_back(nodeContextValue);
1036  args.push_back(ConstantInt::get(indexType, index));
1037  return CallInst::Create(function, args, "", block);
1038 }
1039 
1049 Value * VuoCompilerCodeGenUtilities::generateGetNodeContextInstanceData(Module *module, BasicBlock *block, Value *nodeContextValue, Type *instanceDataType)
1050 {
1051  Value *pointerToInstanceData = generateGetNodeContextInstanceDataVariable(module, block, nodeContextValue, instanceDataType);
1052  return new LoadInst(pointerToInstanceData, "", false, block);
1053 }
1054 
1064 Value * VuoCompilerCodeGenUtilities::generateGetNodeContextInstanceDataVariable(Module *module, BasicBlock *block, Value *nodeContextValue, Type *instanceDataType)
1065 {
1066  const char *functionName = "vuoGetNodeContextInstanceData";
1067  Function *function = module->getFunction(functionName);
1068  if (! function)
1069  {
1070  StructType *nodeContextType = getNodeContextType(module);
1071  PointerType *pointerToNodeContext = PointerType::get(nodeContextType, 0);
1072  Type *voidPointerType = nodeContextType->getElementType(2);
1073 
1074  FunctionType *functionType = FunctionType::get(voidPointerType, pointerToNodeContext, false);
1075  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1076  }
1077 
1078  Value *pointerToInstanceDataAsVoidPointer = CallInst::Create(function, nodeContextValue, "", block);
1079  return new BitCastInst(pointerToInstanceDataAsVoidPointer, PointerType::get(instanceDataType, 0), "", block);
1080 }
1081 
1090 Value * VuoCompilerCodeGenUtilities::generateGetNodeContextClaimingEventId(Module *module, BasicBlock *block, Value *nodeContextValue)
1091 {
1092  const char *functionName = "vuoGetNodeContextClaimingEventId";
1093  Function *function = module->getFunction(functionName);
1094  if (! function)
1095  {
1096  StructType *nodeContextType = getNodeContextType(module);
1097  PointerType *pointerToNodeContext = PointerType::get(nodeContextType, 0);
1098  Type *eventIdType = nodeContextType->getElementType(4);
1099 
1100  FunctionType *functionType = FunctionType::get(eventIdType, pointerToNodeContext, false);
1101  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1102  }
1103 
1104  return CallInst::Create(function, nodeContextValue, "", block);
1105 }
1106 
1115 Value * VuoCompilerCodeGenUtilities::generateGetNodeContextExecutingGroup(Module *module, BasicBlock *block, Value *nodeContextValue)
1116 {
1117  const char *functionName = "vuoGetNodeContextExecutingGroup";
1118  Function *function = module->getFunction(functionName);
1119  if (! function)
1120  {
1121  StructType *nodeContextType = getNodeContextType(module);
1122  PointerType *pointerToNodeContext = PointerType::get(nodeContextType, 0);
1123  Type *dispatchGroupType = nodeContextType->getElementType(5);
1124 
1125  FunctionType *functionType = FunctionType::get(dispatchGroupType, pointerToNodeContext, false);
1126  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1127  }
1128 
1129  return CallInst::Create(function, nodeContextValue, "", block);
1130 }
1131 
1141 Value * VuoCompilerCodeGenUtilities::generateGetNodeContextOutputEvent(Module *module, BasicBlock *block, Value *nodeContextValue, size_t index)
1142 {
1143  Type *sizeType = IntegerType::get(module->getContext(), 64);
1144 
1145  const char *functionName = "vuoGetNodeContextOutputEvent";
1146  Function *function = module->getFunction(functionName);
1147  if (! function)
1148  {
1149  StructType *nodeContextType = getNodeContextType(module);
1150  PointerType *pointerToNodeContext = PointerType::get(nodeContextType, 0);
1151  Type *boolType = IntegerType::get(module->getContext(), 64);
1152 
1153  vector<Type *> params;
1154  params.push_back(pointerToNodeContext);
1155  params.push_back(sizeType);
1156  FunctionType *functionType = FunctionType::get(boolType, params, false);
1157  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1158  }
1159 
1160  vector<Value *> args;
1161  args.push_back(nodeContextValue);
1162  args.push_back(ConstantInt::get(sizeType, index));
1163  Value *eventValue = CallInst::Create(function, args, "", block);
1164 
1165  return new TruncInst(eventValue, IntegerType::get(module->getContext(), 1), "", block);
1166 }
1167 
1175 void VuoCompilerCodeGenUtilities::generateResetNodeContextEvents(Module *module, BasicBlock *block, Value *nodeContextValue)
1176 {
1177  const char *functionName = "vuoResetNodeContextEvents";
1178  Function *function = module->getFunction(functionName);
1179  if (! function)
1180  {
1181  PointerType *pointerToNodeContextType = PointerType::get(getNodeContextType(module), 0);
1182 
1183  vector<Type *> params;
1184  params.push_back(pointerToNodeContextType);
1185 
1186  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
1187  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1188  }
1189 
1190  vector<Value *> args;
1191  args.push_back(nodeContextValue);
1192  CallInst::Create(function, args, "", block);
1193 }
1194 
1203 void VuoCompilerCodeGenUtilities::generateStartedExecutingEvent(Module *module, BasicBlock *block, Value *nodeContextValue, Value *eventIdValue)
1204 {
1205  const char *functionName = "vuoStartedExecutingEvent";
1206  Function *function = module->getFunction(functionName);
1207  if (! function)
1208  {
1209  PointerType *pointerToNodeContextType = PointerType::get(getNodeContextType(module), 0);
1210  Type *eventIdType = generateNoEventIdConstant(module)->getType();
1211 
1212  vector<Type *> params;
1213  params.push_back(pointerToNodeContextType);
1214  params.push_back(eventIdType);
1215 
1216  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
1217  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1218  }
1219 
1220  vector<Value *> args;
1221  args.push_back(nodeContextValue);
1222  args.push_back(eventIdValue);
1223  CallInst::Create(function, args, "", block);
1224 }
1225 
1234 void VuoCompilerCodeGenUtilities::generateSpunOffExecutingEvent(Module *module, BasicBlock *block, Value *nodeContextValue, Value *eventIdValue)
1235 {
1236  const char *functionName = "vuoSpunOffExecutingEvent";
1237  Function *function = module->getFunction(functionName);
1238  if (! function)
1239  {
1240  PointerType *pointerToNodeContextType = PointerType::get(getNodeContextType(module), 0);
1241  Type *eventIdType = generateNoEventIdConstant(module)->getType();
1242 
1243  vector<Type *> params;
1244  params.push_back(pointerToNodeContextType);
1245  params.push_back(eventIdType);
1246 
1247  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
1248  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1249  }
1250 
1251  vector<Value *> args;
1252  args.push_back(nodeContextValue);
1253  args.push_back(eventIdValue);
1254  CallInst::Create(function, args, "", block);
1255 }
1256 
1266 Value * VuoCompilerCodeGenUtilities::generateFinishedExecutingEvent(Module *module, BasicBlock *block, Value *nodeContextValue, Value *eventIdValue)
1267 {
1268  const char *functionName = "vuoFinishedExecutingEvent";
1269  Function *function = module->getFunction(functionName);
1270  if (! function)
1271  {
1272  PointerType *pointerToNodeContextType = PointerType::get(getNodeContextType(module), 0);
1273  Type *eventIdType = generateNoEventIdConstant(module)->getType();
1274  Type *boolType = IntegerType::get(module->getContext(), 64);
1275 
1276  vector<Type *> params;
1277  params.push_back(pointerToNodeContextType);
1278  params.push_back(eventIdType);
1279 
1280  FunctionType *functionType = FunctionType::get(boolType, params, false);
1281  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1282  }
1283 
1284  vector<Value *> args;
1285  args.push_back(nodeContextValue);
1286  args.push_back(eventIdValue);
1287  return CallInst::Create(function, args, "", block);
1288 }
1289 
1298 Value * VuoCompilerCodeGenUtilities::generateGetOneExecutingEvent(Module *module, BasicBlock *block, Value *nodeContextValue)
1299 {
1300  const char *functionName = "vuoGetOneExecutingEvent";
1301  Function *function = module->getFunction(functionName);
1302  if (! function)
1303  {
1304  PointerType *pointerToNodeContextType = PointerType::get(getNodeContextType(module), 0);
1305  Type *eventIdType = generateNoEventIdConstant(module)->getType();
1306 
1307  vector<Type *> params;
1308  params.push_back(pointerToNodeContextType);
1309 
1310  FunctionType *functionType = FunctionType::get(eventIdType, params, false);
1311  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1312  }
1313 
1314  vector<Value *> args;
1315  args.push_back(nodeContextValue);
1316  return CallInst::Create(function, args, "", block);
1317 }
1318 
1322 Value * VuoCompilerCodeGenUtilities::generateCreateCompositionState(Module *module, BasicBlock *block, Value *runtimeStateValue, Value *compositionIdentifierValue)
1323 {
1324  const char *functionName = "vuoCreateCompositionState";
1325  Function *function = module->getFunction(functionName);
1326  if (! function)
1327  {
1328  PointerType *pointerToChar = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
1329  PointerType *voidPointer = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
1330  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
1331 
1332  vector<Type *> params;
1333  params.push_back(voidPointer);
1334  params.push_back(pointerToChar);
1335 
1336  FunctionType *functionType = FunctionType::get(pointerToCompositionState, params, false);
1337  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1338  }
1339 
1340  vector<Value *> args;
1341  args.push_back(runtimeStateValue);
1342  args.push_back(compositionIdentifierValue);
1343  return CallInst::Create(function, args, "", block);
1344 }
1345 
1349 Value * VuoCompilerCodeGenUtilities::generateGetCompositionStateRuntimeState(Module *module, BasicBlock *block, Value *compositionStateValue)
1350 {
1351  const char *functionName = "vuoGetCompositionStateRuntimeState";
1352  Function *function = module->getFunction(functionName);
1353  if (! function)
1354  {
1355  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
1356  PointerType *voidPointer = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
1357 
1358  vector<Type *> params;
1359  params.push_back(pointerToCompositionState);
1360 
1361  FunctionType *functionType = FunctionType::get(voidPointer, params, false);
1362  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1363  }
1364 
1365  vector<Value *> args;
1366  args.push_back(compositionStateValue);
1367  return CallInst::Create(function, args, "", block);
1368 }
1369 
1373 Value * VuoCompilerCodeGenUtilities::generateGetCompositionStateCompositionIdentifier(Module *module, BasicBlock *block, Value *compositionStateValue)
1374 {
1375  const char *functionName = "vuoGetCompositionStateCompositionIdentifier";
1376  Function *function = module->getFunction(functionName);
1377  if (! function)
1378  {
1379  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
1380  PointerType *pointerToChar = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
1381 
1382  vector<Type *> params;
1383  params.push_back(pointerToCompositionState);
1384 
1385  FunctionType *functionType = FunctionType::get(pointerToChar, params, false);
1386  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1387  }
1388 
1389  vector<Value *> args;
1390  args.push_back(compositionStateValue);
1391  return CallInst::Create(function, args, "", block);
1392 }
1393 
1397 void VuoCompilerCodeGenUtilities::generateFreeCompositionState(Module *module, BasicBlock *block, Value *compositionStateValue)
1398 {
1399  const char *functionName = "vuoFreeCompositionState";
1400  Function *function = module->getFunction(functionName);
1401  if (! function)
1402  {
1403  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
1404 
1405  vector<Type *> params;
1406  params.push_back(pointerToCompositionState);
1407 
1408  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
1409  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1410  }
1411 
1412  vector<Value *> args;
1413  args.push_back(compositionStateValue);
1414  CallInst::Create(function, args, "", block);
1415 }
1416 
1420 Value * VuoCompilerCodeGenUtilities::generateGetDataForPort(Module *module, BasicBlock *block,
1421  Value *compositionStateValue, Value *portIdentifierValue)
1422 {
1423  const char *functionName = "vuoGetDataForPort";
1424  Function *function = module->getFunction(functionName);
1425  if (! function)
1426  {
1427  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
1428  PointerType *voidPointerType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
1429 
1430  vector<Type *> params;
1431  params.push_back(compositionStateValue->getType());
1432  params.push_back(pointerToCharType);
1433 
1434  FunctionType *functionType = FunctionType::get(voidPointerType, params, false);
1435  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1436  }
1437 
1438  vector<Value *> args;
1439  args.push_back(compositionStateValue);
1440  args.push_back(portIdentifierValue);
1441  return CallInst::Create(function, args, "", block);
1442 }
1443 
1447 Value * VuoCompilerCodeGenUtilities::generateGetNodeIndexForPort(Module *module, BasicBlock *block,
1448  Value *compositionStateValue, Value *portIdentifierValue)
1449 {
1450  const char *functionName = "vuoGetNodeIndexForPort";
1451  Function *function = module->getFunction(functionName);
1452  if (! function)
1453  {
1454  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
1455  Type *unsignedLongType = IntegerType::get(module->getContext(), 64);
1456 
1457  vector<Type *> params;
1458  params.push_back(compositionStateValue->getType());
1459  params.push_back(pointerToCharType);
1460 
1461  FunctionType *functionType = FunctionType::get(unsignedLongType, params, false);
1462  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1463  }
1464 
1465  vector<Value *> args;
1466  args.push_back(compositionStateValue);
1467  args.push_back(portIdentifierValue);
1468  return CallInst::Create(function, args, "", block);
1469 }
1470 
1474 Value * VuoCompilerCodeGenUtilities::generateGetTypeIndexForPort(Module *module, BasicBlock *block,
1475  Value *compositionStateValue, Value *portIdentifierValue)
1476 {
1477  const char *functionName = "vuoGetTypeIndexForPort";
1478  Function *function = module->getFunction(functionName);
1479  if (! function)
1480  {
1481  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
1482  Type *unsignedLongType = IntegerType::get(module->getContext(), 64);
1483 
1484  vector<Type *> params;
1485  params.push_back(compositionStateValue->getType());
1486  params.push_back(pointerToCharType);
1487 
1488  FunctionType *functionType = FunctionType::get(unsignedLongType, params, false);
1489  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1490  }
1491 
1492  vector<Value *> args;
1493  args.push_back(compositionStateValue);
1494  args.push_back(portIdentifierValue);
1495  return CallInst::Create(function, args, "", block);
1496 }
1497 
1501 void VuoCompilerCodeGenUtilities::generateScheduleTriggerWorker(Module *module, BasicBlock *block,
1502  Value *queueValue, Value *contextValue, Value *workerFunctionValue,
1503  int minThreadsNeeded, int maxThreadsNeeded,
1504  Value *eventIdValue, Value *compositionStateValue,
1505  int chainCount)
1506 {
1507  Type *intType = IntegerType::get(module->getContext(), 64);
1508 
1509  const char *functionName = "vuoScheduleTriggerWorker";
1510  Function *function = module->getFunction(functionName);
1511  if (! function)
1512  {
1513  Type *dispatchQueueType = getDispatchQueueType(module);
1514  PointerType *voidPointerType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
1515  Type *workerFunctionType = workerFunctionValue->getType();
1516  Type *eventIdType = generateNoEventIdConstant(module)->getType();
1517 
1518  vector<Type *> params;
1519  params.push_back(compositionStateValue->getType());
1520  params.push_back(dispatchQueueType);
1521  params.push_back(voidPointerType);
1522  params.push_back(workerFunctionType);
1523  params.push_back(intType);
1524  params.push_back(intType);
1525  params.push_back(eventIdType);
1526  params.push_back(intType);
1527 
1528  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
1529  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1530  }
1531 
1532  Value *minThreadsNeededValue = ConstantInt::get(intType, minThreadsNeeded);
1533  Value *maxThreadsNeededValue = ConstantInt::get(intType, maxThreadsNeeded);
1534  Value *chainCountValue = ConstantInt::get(intType, chainCount);
1535 
1536  vector<Value *> args;
1537  args.push_back(compositionStateValue);
1538  args.push_back(queueValue);
1539  args.push_back(contextValue);
1540  args.push_back(workerFunctionValue);
1541  args.push_back(minThreadsNeededValue);
1542  args.push_back(maxThreadsNeededValue);
1543  args.push_back(eventIdValue);
1544  args.push_back(chainCountValue);
1545  CallInst::Create(function, args, "", block);
1546 }
1547 
1551 void VuoCompilerCodeGenUtilities::generateScheduleChainWorker(Module *module, BasicBlock *block,
1552  Value *queueValue, Value *contextValue, Value *workerFunctionValue,
1553  int minThreadsNeeded, int maxThreadsNeeded,
1554  Value *eventIdValue, Value *compositionStateValue,
1555  size_t chainIndex, vector<size_t> upstreamChainIndices)
1556 {
1557  Type *intType = IntegerType::get(module->getContext(), 64);
1558  Type *eventIdType = generateNoEventIdConstant(module)->getType();
1559 
1560  const char *functionName = "vuoScheduleChainWorker";
1561  Function *function = module->getFunction(functionName);
1562  if (! function)
1563  {
1564  Type *dispatchQueueType = getDispatchQueueType(module);
1565  PointerType *voidPointerType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
1566  Type *workerFunctionType = workerFunctionValue->getType();
1567  PointerType *unsignedLongPointerType = PointerType::get(eventIdType, 0);
1568 
1569  vector<Type *> params;
1570  params.push_back(compositionStateValue->getType());
1571  params.push_back(dispatchQueueType);
1572  params.push_back(voidPointerType);
1573  params.push_back(workerFunctionType);
1574  params.push_back(intType);
1575  params.push_back(intType);
1576  params.push_back(eventIdType);
1577  params.push_back(eventIdType);
1578  params.push_back(unsignedLongPointerType);
1579  params.push_back(intType);
1580 
1581  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
1582  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1583  }
1584 
1585  Value *minThreadsNeededValue = ConstantInt::get(intType, minThreadsNeeded);
1586  Value *maxThreadsNeededValue = ConstantInt::get(intType, maxThreadsNeeded);
1587  Value *chainIndexValue = ConstantInt::get(eventIdType, chainIndex);
1588 
1589  Value *upstreamChainIndicesCountValue = ConstantInt::get(intType, (int)upstreamChainIndices.size());
1590  Value *upstreamChainIndicesValue = generateMemoryAllocation(module, block, eventIdType, upstreamChainIndices.size());
1591  for (size_t i = 0; i < upstreamChainIndices.size(); ++i)
1592  {
1593  Value *upstreamChainIndexValue = ConstantInt::get(eventIdType, upstreamChainIndices[i]);
1594  generateSetArrayElement(module, block, upstreamChainIndicesValue, i, upstreamChainIndexValue);
1595  }
1596 
1597  vector<Value *> args;
1598  args.push_back(compositionStateValue);
1599  args.push_back(queueValue);
1600  args.push_back(contextValue);
1601  args.push_back(workerFunctionValue);
1602  args.push_back(minThreadsNeededValue);
1603  args.push_back(maxThreadsNeededValue);
1604  args.push_back(eventIdValue);
1605  args.push_back(chainIndexValue);
1606  args.push_back(upstreamChainIndicesValue);
1607  args.push_back(upstreamChainIndicesCountValue);
1608  CallInst::Create(function, args, "", block);
1609 }
1610 
1614 void VuoCompilerCodeGenUtilities::generateGrantThreadsToChain(Module *module, BasicBlock *block,
1615  int minThreadsNeeded, int maxThreadsNeeded,
1616  Value *eventIdValue, Value *compositionStateValue,
1617  size_t chainIndex)
1618 {
1619  Type *intType = IntegerType::get(module->getContext(), 64);
1620  Type *eventIdType = generateNoEventIdConstant(module)->getType();
1621 
1622  const char *functionName = "vuoGrantThreadsToChain";
1623  Function *function = module->getFunction(functionName);
1624  if (! function)
1625  {
1626  vector<Type *> params;
1627  params.push_back(compositionStateValue->getType());
1628  params.push_back(intType);
1629  params.push_back(intType);
1630  params.push_back(eventIdType);
1631  params.push_back(eventIdType);
1632 
1633  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
1634  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1635  }
1636 
1637  Value *minThreadsNeededValue = ConstantInt::get(intType, minThreadsNeeded);
1638  Value *maxThreadsNeededValue = ConstantInt::get(intType, maxThreadsNeeded);
1639  Value *chainIndexValue = ConstantInt::get(eventIdType, chainIndex);
1640 
1641  vector<Value *> args;
1642  args.push_back(compositionStateValue);
1643  args.push_back(minThreadsNeededValue);
1644  args.push_back(maxThreadsNeededValue);
1645  args.push_back(eventIdValue);
1646  args.push_back(chainIndexValue);
1647  CallInst::Create(function, args, "", block);
1648 }
1649 
1654  Value *eventIdValue, Value *compositionStateValue,
1655  Value *chainIndexValue, Value *subcompositionIdentifierValue)
1656 {
1657  const char *functionName = "vuoGrantThreadsToSubcomposition";
1658  Function *function = module->getFunction(functionName);
1659  if (! function)
1660  {
1661  Type *eventIdType = generateNoEventIdConstant(module)->getType();
1662  PointerType *charPointerType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
1663 
1664  vector<Type *> params;
1665  params.push_back(compositionStateValue->getType());
1666  params.push_back(eventIdType);
1667  params.push_back(eventIdType);
1668  params.push_back(charPointerType);
1669 
1670  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
1671  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1672  }
1673 
1674  vector<Value *> args;
1675  args.push_back(compositionStateValue);
1676  args.push_back(eventIdValue);
1677  args.push_back(chainIndexValue);
1678  args.push_back(subcompositionIdentifierValue);
1679  CallInst::Create(function, args, "", block);
1680 }
1681 
1686  Value *eventIdValue, Value *compositionStateValue)
1687 {
1688  const char *functionName = "vuoReturnThreadsForTriggerWorker";
1689  Function *function = module->getFunction(functionName);
1690  if (! function)
1691  {
1692  Type *eventIdType = generateNoEventIdConstant(module)->getType();
1693 
1694  vector<Type *> params;
1695  params.push_back(compositionStateValue->getType());
1696  params.push_back(eventIdType);
1697 
1698  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
1699  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1700  }
1701 
1702  vector<Value *> args;
1703  args.push_back(compositionStateValue);
1704  args.push_back(eventIdValue);
1705  CallInst::Create(function, args, "", block);
1706 }
1707 
1712  Value *eventIdValue, Value *compositionStateValue,
1713  Value *chainIndexValue)
1714 {
1715  const char *functionName = "vuoReturnThreadsForChainWorker";
1716  Function *function = module->getFunction(functionName);
1717  if (! function)
1718  {
1719  Type *eventIdType = generateNoEventIdConstant(module)->getType();
1720 
1721  vector<Type *> params;
1722  params.push_back(compositionStateValue->getType());
1723  params.push_back(eventIdType);
1724  params.push_back(eventIdType);
1725 
1726  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
1727  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1728  }
1729 
1730  vector<Value *> args;
1731  args.push_back(compositionStateValue);
1732  args.push_back(eventIdValue);
1733  args.push_back(chainIndexValue);
1734  CallInst::Create(function, args, "", block);
1735 }
1736 
1740 void VuoCompilerCodeGenUtilities::generateLockNodes(Module *module, BasicBlock *&block,
1741  Value *compositionStateValue, const vector<size_t> &nodeIndices, Value *eventIdValue,
1742  VuoCompilerConstantsCache *constantsCache)
1743 {
1744  string functionName = "vuoLockNodes";
1745  Function *function = module->getFunction(functionName.c_str());
1746  if (! function)
1747  {
1748  StructType *compositionStateType = getCompositionStateType(module);
1749  PointerType *pointerToCompositionState = PointerType::get(compositionStateType, 0);
1750  IntegerType *unsignedLongType = IntegerType::get(module->getContext(), 64);
1751  PointerType *pointerToUnsignedLong = PointerType::get(unsignedLongType, 0);
1752 
1753  vector<Type *> params;
1754  params.push_back(pointerToCompositionState);
1755  params.push_back(pointerToUnsignedLong);
1756  params.push_back(unsignedLongType);
1757  params.push_back(unsignedLongType);
1758  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
1759  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1760  }
1761 
1762  Constant *nodeCountValue = ConstantInt::get(module->getContext(), APInt(64, nodeIndices.size()));
1763  Constant *nodeIndicesValue = constantsCache->get(nodeIndices);
1764 
1765  vector<Value *> args;
1766  args.push_back(compositionStateValue);
1767  args.push_back(nodeIndicesValue);
1768  args.push_back(nodeCountValue);
1769  args.push_back(eventIdValue);
1770  CallInst::Create(function, args, "", block);
1771 }
1772 
1776 void VuoCompilerCodeGenUtilities::generateLockNode(Module *module, BasicBlock *&block,
1777  Value *compositionStateValue, size_t nodeIndex, Value *eventIdValue)
1778 {
1779  Constant *nodeIndexValue = ConstantInt::get(module->getContext(), APInt(64, nodeIndex));
1780  generateLockNode(module, block, compositionStateValue, nodeIndexValue, eventIdValue);
1781 }
1782 
1786 void VuoCompilerCodeGenUtilities::generateLockNode(Module *module, BasicBlock *&block,
1787  Value *compositionStateValue, Value *nodeIndexValue, Value *eventIdValue)
1788 {
1789  string functionName = "vuoLockNode";
1790  Function *function = module->getFunction(functionName.c_str());
1791  if (! function)
1792  {
1793  StructType *compositionStateType = getCompositionStateType(module);
1794  PointerType *pointerToCompositionState = PointerType::get(compositionStateType, 0);
1795  IntegerType *unsignedLongType = IntegerType::get(module->getContext(), 64);
1796 
1797  vector<Type *> params;
1798  params.push_back(pointerToCompositionState);
1799  params.push_back(unsignedLongType);
1800  params.push_back(unsignedLongType);
1801  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
1802  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1803  }
1804 
1805  vector<Value *> args;
1806  args.push_back(compositionStateValue);
1807  args.push_back(nodeIndexValue);
1808  args.push_back(eventIdValue);
1809  CallInst::Create(function, args, "", block);
1810 }
1811 
1815 void VuoCompilerCodeGenUtilities::generateUnlockNodes(Module *module, BasicBlock *block,
1816  Value *compositionStateValue, const vector<size_t> &nodeIndices,
1817  VuoCompilerConstantsCache *constantsCache)
1818 {
1819  string functionName = "vuoUnlockNodes";
1820  Function *function = module->getFunction(functionName.c_str());
1821  if (! function)
1822  {
1823  StructType *compositionStateType = getCompositionStateType(module);
1824  PointerType *pointerToCompositionState = PointerType::get(compositionStateType, 0);
1825  IntegerType *unsignedLongType = IntegerType::get(module->getContext(), 64);
1826  PointerType *pointerToUnsignedLong = PointerType::get(unsignedLongType, 0);
1827 
1828  vector<Type *> params;
1829  params.push_back(pointerToCompositionState);
1830  params.push_back(pointerToUnsignedLong);
1831  params.push_back(unsignedLongType);
1832  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
1833  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1834  }
1835 
1836  Constant *nodeCountValue = ConstantInt::get(module->getContext(), APInt(64, nodeIndices.size()));
1837  Constant *nodeIndicesValue = constantsCache->get(nodeIndices);
1838 
1839  vector<Value *> args;
1840  args.push_back(compositionStateValue);
1841  args.push_back(nodeIndicesValue);
1842  args.push_back(nodeCountValue);
1843  CallInst::Create(function, args, "", block);
1844 }
1845 
1849 void VuoCompilerCodeGenUtilities::generateUnlockNode(Module *module, BasicBlock *block,
1850  Value *compositionStateValue, size_t nodeIndex)
1851 {
1852  Constant *nodeIndexValue = ConstantInt::get(module->getContext(), APInt(64, nodeIndex));
1853  generateUnlockNode(module, block, compositionStateValue, nodeIndexValue);
1854 }
1855 
1859 void VuoCompilerCodeGenUtilities::generateUnlockNode(Module *module, BasicBlock *block,
1860  Value *compositionStateValue, Value *nodeIndexValue)
1861 {
1862  string functionName = "vuoUnlockNode";
1863  Function *function = module->getFunction(functionName.c_str());
1864  if (! function)
1865  {
1866  StructType *compositionStateType = getCompositionStateType(module);
1867  PointerType *pointerToCompositionState = PointerType::get(compositionStateType, 0);
1868  IntegerType *unsignedLongType = IntegerType::get(module->getContext(), 64);
1869 
1870  vector<Type *> params;
1871  params.push_back(pointerToCompositionState);
1872  params.push_back(unsignedLongType);
1873  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
1874  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1875  }
1876 
1877  vector<Value *> args;
1878  args.push_back(compositionStateValue);
1879  args.push_back(nodeIndexValue);
1880  CallInst::Create(function, args, "", block);
1881 }
1882 
1886 void VuoCompilerCodeGenUtilities::generateSetArrayElement(Module *module, BasicBlock *block, Value *arrayValue, size_t elementIndex, Value *value)
1887 {
1888  Value *memberPointer = generateGetArrayElementVariable(module, block, arrayValue, elementIndex);
1889  new StoreInst(value, memberPointer, false, block);
1890 }
1891 
1895 Value * VuoCompilerCodeGenUtilities::generateGetArrayElement(Module *module, BasicBlock *block, Value *arrayValue, size_t elementIndex)
1896 {
1897  Value *memberPointer = generateGetArrayElementVariable(module, block, arrayValue, elementIndex);
1898  return new LoadInst(memberPointer, "", block);
1899 }
1900 
1904 Value * VuoCompilerCodeGenUtilities::generateGetArrayElement(Module *module, BasicBlock *block, Value *arrayValue, Value *elementIndexValue)
1905 {
1906  Value *memberPointer = generateGetArrayElementVariable(module, block, arrayValue, elementIndexValue);
1907  return new LoadInst(memberPointer, "", block);
1908 }
1909 
1913 Value * VuoCompilerCodeGenUtilities::generateGetArrayElementVariable(Module *module, BasicBlock *block, Value *arrayValue, size_t elementIndex)
1914 {
1915  ConstantInt *indexValue = ConstantInt::get(module->getContext(), APInt(32, elementIndex));
1916  return generateGetArrayElementVariable(module, block, arrayValue, indexValue);
1917 }
1918 
1922 Value * VuoCompilerCodeGenUtilities::generateGetArrayElementVariable(Module *module, BasicBlock *block, Value *arrayValue, Value *elementIndexValue)
1923 {
1924  return GetElementPtrInst::Create(nullptr, arrayValue, elementIndexValue, "", block);
1925 }
1926 
1930 void VuoCompilerCodeGenUtilities::generateSetStructPointerElement(Module *module, BasicBlock *block, Value *structPointer, size_t elementIndex, Value *value)
1931 {
1932  Value *memberPointer = generateGetStructPointerElementVariable(module, block, structPointer, elementIndex);
1933  new StoreInst(value, memberPointer, false, block);
1934 }
1935 
1939 Value * VuoCompilerCodeGenUtilities::generateGetStructPointerElement(Module *module, BasicBlock *block, Value *structPointer, size_t elementIndex)
1940 {
1941  Value *memberPointer = generateGetStructPointerElementVariable(module, block, structPointer, elementIndex);
1942  return new LoadInst(memberPointer, "", block);
1943 }
1944 
1948 Value * VuoCompilerCodeGenUtilities::generateGetStructPointerElementVariable(Module *module, BasicBlock *block, Value *structPointer, size_t elementIndex)
1949 {
1950  ConstantInt *zeroValue = ConstantInt::get(module->getContext(), APInt(32, 0));
1951  ConstantInt *indexValue = ConstantInt::get(module->getContext(), APInt(32, elementIndex));
1952 
1953  vector<Value *> memberIndices;
1954  memberIndices.push_back(zeroValue);
1955  memberIndices.push_back(indexValue);
1956  return GetElementPtrInst::Create(nullptr, structPointer, memberIndices, "", block);
1957 }
1958 
1962 Value * VuoCompilerCodeGenUtilities::generatePointerToValue(BasicBlock *block, Value *value)
1963 {
1964  AllocaInst *variable = new AllocaInst(value->getType(), 0, "", block);
1965  new StoreInst(value, variable, false, block);
1966  return variable;
1967 }
1968 
1977 Constant * VuoCompilerCodeGenUtilities::generatePointerToConstantString(Module *module, string stringValue, string globalVariableName)
1978 {
1979  Constant *array = ConstantDataArray::getString(module->getContext(), stringValue);
1980  ArrayType *arrayType = ArrayType::get(IntegerType::get(module->getContext(), 8), stringValue.length() + 1);
1981  GlobalVariable *global = new GlobalVariable(*module, arrayType, true, GlobalValue::InternalLinkage, 0, "");
1982  global->setInitializer(array);
1983  global->setName(globalVariableName);
1984 
1985  ConstantInt *zeroValue = ConstantInt::get(module->getContext(), APInt(32, 0));
1986  vector<Constant *> pointerIndices;
1987  pointerIndices.push_back(zeroValue);
1988  pointerIndices.push_back(zeroValue);
1989  Constant *pointer = ConstantExpr::getGetElementPtr(arrayType, global, pointerIndices);
1990 
1991  return pointer;
1992 }
1993 
2002 Constant * VuoCompilerCodeGenUtilities::generatePointerToConstantArrayOfStrings(Module *module, vector<string> stringValues, string globalVariableName)
2003 {
2004  vector<Constant *> arrayElements;
2005  for (vector<string>::iterator i = stringValues.begin(); i != stringValues.end(); ++i)
2006  {
2007  Constant *stringPointer = generatePointerToConstantString(module, *i, ".str");
2008  arrayElements.push_back(stringPointer);
2009  }
2010 
2011  ArrayType *arrayType = ArrayType::get(PointerType::get(IntegerType::get(module->getContext(), 8), 0), arrayElements.size());
2012  GlobalVariable *global = new GlobalVariable(*module, arrayType, false, GlobalValue::ExternalLinkage, 0, globalVariableName);
2013  Constant *arrayConstant = ConstantArray::get(arrayType, arrayElements);
2014  global->setInitializer(arrayConstant);
2015 
2016  ConstantInt *zeroi64Constant = ConstantInt::get(module->getContext(), APInt(64, 0));
2017  vector<Constant *> pointerIndices;
2018  pointerIndices.push_back(zeroi64Constant);
2019  pointerIndices.push_back(zeroi64Constant);
2020  Constant *pointer = ConstantExpr::getGetElementPtr(arrayType, global, pointerIndices);
2021 
2022  return pointer;
2023 }
2024 
2033 Constant * VuoCompilerCodeGenUtilities::generatePointerToConstantArrayOfUnsignedLongs(Module *module, const vector<unsigned long> &values, string globalVariableName)
2034 {
2035  vector<Constant *> arrayElements;
2036  for (unsigned long value : values)
2037  {
2038  Constant *valueConstant = ConstantInt::get(module->getContext(), APInt(64, value));
2039  arrayElements.push_back(valueConstant);
2040  }
2041 
2042  ArrayType *arrayType = ArrayType::get(IntegerType::get(module->getContext(), 64), arrayElements.size());
2043  GlobalVariable *global = new GlobalVariable(*module, arrayType, false, GlobalValue::ExternalLinkage, 0, globalVariableName);
2044  Constant *arrayConstant = ConstantArray::get(arrayType, arrayElements);
2045  global->setInitializer(arrayConstant);
2046 
2047  ConstantInt *zeroi64Constant = ConstantInt::get(module->getContext(), APInt(64, 0));
2048  vector<Constant *> pointerIndices;
2049  pointerIndices.push_back(zeroi64Constant);
2050  pointerIndices.push_back(zeroi64Constant);
2051  Constant *pointer = ConstantExpr::getGetElementPtr(arrayType, global, pointerIndices);
2052 
2053  return pointer;
2054 }
2055 
2080 void VuoCompilerCodeGenUtilities::generateStringMatchingCode(Module *module, Function *function,
2081  BasicBlock *initialBlock, BasicBlock *finalBlock, Value *inputStringValue,
2082  map<string, pair<BasicBlock *, BasicBlock *> > blocksForString,
2083  VuoCompilerConstantsCache *constantsCache)
2084 {
2085  Function *strcmpFunction = getStrcmpFunction(module);
2086  BasicBlock *currentBlock = initialBlock;
2087 
2088  for (map<string, pair<BasicBlock *, BasicBlock *> >::iterator i = blocksForString.begin(); i != blocksForString.end(); ++i)
2089  {
2090  string currentString = i->first;
2091  BasicBlock *firstTrueBlock = i->second.first;
2092  BasicBlock *lastTrueBlock = i->second.second;
2093 
2094  Constant *currentStringValue = constantsCache->get(currentString);
2095 
2096  vector<Value *> strcmpArgs;
2097  strcmpArgs.push_back(inputStringValue);
2098  strcmpArgs.push_back(currentStringValue);
2099  CallInst *strcmpCall = CallInst::Create(strcmpFunction, strcmpArgs, "", currentBlock);
2100 
2101  ConstantInt *zeroValue = ConstantInt::get(module->getContext(), APInt(32, 0));
2102  ICmpInst *strcmpEqualsZero = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, strcmpCall, zeroValue, "");
2103  BasicBlock *falseBlock = BasicBlock::Create(module->getContext(), string("strcmp-") + currentString, function, 0);
2104  BranchInst::Create(firstTrueBlock, falseBlock, strcmpEqualsZero, currentBlock);
2105 
2106  BranchInst::Create(finalBlock, lastTrueBlock);
2107 
2108  currentBlock = falseBlock;
2109  }
2110 
2111  BranchInst::Create(finalBlock, currentBlock);
2112 }
2113 
2137 void VuoCompilerCodeGenUtilities::generateIndexMatchingCode(Module *module, Function *function,
2138  BasicBlock *initialBlock, BasicBlock *finalBlock, Value *inputIndexValue,
2139  vector< pair<BasicBlock *, BasicBlock *> > blocksForIndex)
2140 {
2141  BasicBlock *currentBlock = initialBlock;
2142 
2143  for (size_t i = 0; i < blocksForIndex.size(); ++i)
2144  {
2145  BasicBlock *firstTrueBlock = blocksForIndex[i].first;
2146  BasicBlock *lastTrueBlock = blocksForIndex[i].second;
2147 
2148  Constant *currentIndexValue = ConstantInt::get(inputIndexValue->getType(), i);
2149  ICmpInst *indexEqualsCurrent = new ICmpInst(*currentBlock, ICmpInst::ICMP_EQ, inputIndexValue, currentIndexValue, "");
2150  BasicBlock *falseBlock = BasicBlock::Create(module->getContext(), "", function, 0);
2151  BranchInst::Create(firstTrueBlock, falseBlock, indexEqualsCurrent, currentBlock);
2152 
2153  BranchInst::Create(finalBlock, lastTrueBlock);
2154 
2155  currentBlock = falseBlock;
2156  }
2157 
2158  BranchInst::Create(finalBlock, currentBlock);
2159 }
2160 
2172 Value * VuoCompilerCodeGenUtilities::generateFormattedString(Module *module, BasicBlock *block, string formatString, vector<Value *> replacementValues,
2173  VuoCompilerConstantsCache *constantsCache)
2174 {
2175  Function *snprintfFunction = getSnprintfFunction(module);
2176 
2177  Type *charType = IntegerType::get(module->getContext(), 8);
2178  PointerType *pointerToCharType = PointerType::get(charType, 0);
2179  ConstantPointerNull *nullValue = ConstantPointerNull::get(pointerToCharType);
2180  ConstantInt *zeroValue64 = ConstantInt::get(module->getContext(), APInt(64, 0));
2181  ConstantInt *oneValue64 = ConstantInt::get(module->getContext(), APInt(64, 1));
2182 
2183  // int bufferLength = snprintf(NULL, 0, format, ...) + 1;
2184  Constant *formatStringValue = constantsCache->get(formatString);
2185  vector<Value *> snprintfArgs;
2186  snprintfArgs.push_back(nullValue);
2187  snprintfArgs.push_back(zeroValue64);
2188  snprintfArgs.push_back(formatStringValue);
2189  for (vector<Value *>::iterator i = replacementValues.begin(); i != replacementValues.end(); ++i)
2190  snprintfArgs.push_back(*i);
2191  Value *bufferLengthValue32 = CallInst::Create(snprintfFunction, snprintfArgs, "", block);
2192  Value *bufferLengthValue = new SExtInst(bufferLengthValue32, IntegerType::get(module->getContext(), 64), "", block);
2193  bufferLengthValue = BinaryOperator::Create(Instruction::Add, bufferLengthValue, oneValue64, "", block);
2194 
2195  // char *buffer = malloc(bufferLength);
2196  AllocaInst *bufferVariable = new AllocaInst(pointerToCharType, 0, "buffer", block);
2197  Value *bufferValue = generateMemoryAllocation(module, block, charType, bufferLengthValue);
2198  new StoreInst(bufferValue, bufferVariable, false, block);
2199 
2200  // snprintf(buffer, bufferLength, format, ...);
2201  snprintfArgs[0] = bufferValue;
2202  snprintfArgs[1] = bufferLengthValue;
2203  CallInst::Create(snprintfFunction, snprintfArgs, "", block);
2204  return bufferValue;
2205 }
2206 
2217 Value * VuoCompilerCodeGenUtilities::generateStringConcatenation(Module *module, BasicBlock *block, vector<Value *> stringsToConcatenate,
2218  VuoCompilerConstantsCache *constantsCache)
2219 {
2220  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2221 
2222  if (stringsToConcatenate.empty())
2223  {
2224  return constantsCache->get("");
2225  }
2226  else if (stringsToConcatenate.size() == 2)
2227  {
2228  const char *functionName = "vuoConcatenateStrings2";
2229  Function *function = module->getFunction(functionName);
2230  if (! function)
2231  {
2232  vector<Type *> params;
2233  params.push_back(pointerToCharType);
2234  params.push_back(pointerToCharType);
2235 
2236  FunctionType *functionType = FunctionType::get(pointerToCharType, params, false);
2237  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
2238  }
2239 
2240  vector<Value *> args;
2241  args.push_back(stringsToConcatenate[0]);
2242  args.push_back(stringsToConcatenate[1]);
2243  return CallInst::Create(function, args, "", block);
2244  }
2245  else if (stringsToConcatenate.size() == 3)
2246  {
2247  const char *functionName = "vuoConcatenateStrings3";
2248  Function *function = module->getFunction(functionName);
2249  if (! function)
2250  {
2251  vector<Type *> params;
2252  params.push_back(pointerToCharType);
2253  params.push_back(pointerToCharType);
2254  params.push_back(pointerToCharType);
2255 
2256  FunctionType *functionType = FunctionType::get(pointerToCharType, params, false);
2257  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
2258  }
2259 
2260  vector<Value *> args;
2261  args.push_back(stringsToConcatenate[0]);
2262  args.push_back(stringsToConcatenate[1]);
2263  args.push_back(stringsToConcatenate[2]);
2264  return CallInst::Create(function, args, "", block);
2265  }
2266  else
2267  {
2268  IntegerType *sizeType = IntegerType::get(module->getContext(), 64);
2269 
2270  const char *functionName = "vuoConcatenateStrings";
2271  Function *function = module->getFunction(functionName);
2272  if (! function)
2273  {
2274  vector<Type *> params;
2275  params.push_back(PointerType::get(pointerToCharType, 0));
2276  params.push_back(sizeType);
2277 
2278  FunctionType *functionType = FunctionType::get(pointerToCharType, params, false);
2279  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
2280  }
2281 
2282  Value *stringsValue = generateMemoryAllocation(module, block, pointerToCharType, stringsToConcatenate.size());
2283  for (size_t i = 0; i < stringsToConcatenate.size(); ++i)
2284  generateSetArrayElement(module, block, stringsValue, i, stringsToConcatenate[i]);
2285 
2286  vector<Value *> args;
2287  args.push_back(stringsValue);
2288  args.push_back(ConstantInt::get(sizeType, stringsToConcatenate.size()));
2289  Value *concatenatedStringValue = CallInst::Create(function, args, "", block);
2290 
2291  generateFreeCall(module, block, stringsValue);
2292 
2293  return concatenatedStringValue;
2294  }
2295 }
2296 
2306 Value * VuoCompilerCodeGenUtilities::generateMemoryAllocation(Module *module, BasicBlock *block, Type *elementType, int elementCount)
2307 {
2308  Value *elementCountValue = ConstantInt::get(module->getContext(), APInt(64, elementCount));
2309  return generateMemoryAllocation(module, block, elementType, elementCountValue);
2310 }
2311 
2321 Value * VuoCompilerCodeGenUtilities::generateMemoryAllocation(Module *module, BasicBlock *block, Type *elementType, Value *elementCountValue)
2322 {
2323  Constant *elementBytesValue = ConstantExpr::getSizeOf(elementType);
2324  Value *elementCountValue64;
2325  if (static_cast<IntegerType *>(elementCountValue->getType())->getBitWidth() < 64)
2326  elementCountValue64 = new SExtInst(elementCountValue, IntegerType::get(module->getContext(), 64), "", block);
2327  else
2328  elementCountValue64 = elementCountValue;
2329 
2330  BinaryOperator *bytesValue = BinaryOperator::Create(Instruction::Mul, elementBytesValue, elementCountValue64, "", block);
2331 
2332  Function *mallocFunction = VuoCompilerCodeGenUtilities::getMallocFunction(module);
2333  CallInst *mallocReturnValue = CallInst::Create(mallocFunction, bytesValue, "", block);
2334 
2335  Type *elementPointerType = PointerType::get(elementType, 0);
2336  CastInst *mallocReturnValueCasted = new BitCastInst(mallocReturnValue, elementPointerType, "", block);
2337 
2338  return mallocReturnValueCasted;
2339 }
2340 
2349 Value *VuoCompilerCodeGenUtilities::generateMemoryAllocation(Module *module, BasicBlock *block, size_t bytes)
2350 {
2351  Value *bytesValue = ConstantInt::get(module->getContext(), APInt(sizeof(size_t) * 8, bytes));
2352  Function *mallocFunction = VuoCompilerCodeGenUtilities::getMallocFunction(module);
2353  return CallInst::Create(mallocFunction, bytesValue, "", block);
2354 }
2355 
2369 void VuoCompilerCodeGenUtilities::generateMemoryCopy(Module *module, BasicBlock *block, Value *sourceAddress, Value *destAddress, size_t bytes)
2370 {
2371  vector<Value *> args;
2372 
2373  PointerType *voidPointerType = PointerType::getUnqual(IntegerType::get(module->getContext(), 8));
2374  destAddress = new BitCastInst(destAddress, voidPointerType, "", block);
2375  args.push_back(destAddress);
2376 
2377  sourceAddress = new BitCastInst(sourceAddress, voidPointerType, "", block);
2378  args.push_back(sourceAddress);
2379 
2380  args.push_back(ConstantInt::get(module->getContext(), APInt(sizeof(size_t) * 8, bytes)));
2381 
2382  Function *memcpyFunction = VuoCompilerCodeGenUtilities::getMemcpyFunction(module);
2383  CallInst::Create(memcpyFunction, args, "", block);
2384 }
2385 
2391 Value * VuoCompilerCodeGenUtilities::generateTypeCast(Module *module, BasicBlock *block, Value *valueToCast, Type *typeToCastTo)
2392 {
2393  if (valueToCast->getType() == typeToCastTo)
2394  return valueToCast;
2395 
2396  if (valueToCast->getType()->isIntegerTy() && typeToCastTo->isIntegerTy())
2397  return CastInst::CreateIntegerCast(valueToCast, typeToCastTo, true, "", block);
2398  else if (valueToCast->getType()->isIntegerTy() && typeToCastTo->isPointerTy())
2399  return generateTypeCastFromIntegerToPointer(module, block, valueToCast, typeToCastTo);
2400  else if (valueToCast->getType()->isFloatingPointTy() && typeToCastTo->isPointerTy())
2401  return generateTypeCastFromFloatingPointToPointer(module, block, valueToCast, typeToCastTo);
2402  else if (valueToCast->getType()->isPointerTy() && typeToCastTo->isIntegerTy())
2403  return generateTypeCastFromPointerToInteger(module, block, valueToCast, typeToCastTo);
2404  else if (valueToCast->getType()->isPointerTy() && typeToCastTo->isFloatingPointTy())
2405  return generateTypeCastFromPointerToFloatingPoint(module, block, valueToCast, typeToCastTo);
2406  else if (typeToCastTo->isStructTy())
2407  return generateTypeCastFromLoweredTypeToStruct(block, valueToCast, typeToCastTo);
2408  else if (typeToCastTo->isVectorTy())
2409  return generateTypeCastFromLoweredTypeToVector(block, valueToCast, typeToCastTo);
2410  else if (typeToCastTo->isArrayTy())
2411  return generateTypeCastFromLoweredTypeToArray(module, block, valueToCast, typeToCastTo);
2412  else
2413  return new BitCastInst(valueToCast, typeToCastTo, "", block);
2414 }
2415 
2427 void VuoCompilerCodeGenUtilities::generateAnnotation(Module *module, BasicBlock *block, Value *value,
2428  string annotation, string fileName, unsigned int lineNumber,
2429  VuoCompilerConstantsCache *constantsCache)
2430 {
2431  // Set variable names expected by VuoCompilerBitcodeParser::getAnnotatedArguments().
2432  string valueName = value->getName();
2433  string variableName = valueName + ".addr";
2434  string valueAsVoidPointerName = valueName + ".addr1";
2435  string annotationVariableName = valueName + "__annotation";
2436 
2437  Function *annotateFunction = getAnnotateFunction(module);
2438  vector<Value *> annotateFunctionArgs;
2439 
2440  Value *variable = generatePointerToValue(block, value);
2441  variable->setName(variableName);
2442  PointerType *voidPointerType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2443  Value *valueAsVoidPointer = generateTypeCast(module, block, variable, voidPointerType);
2444  valueAsVoidPointer->setName(valueAsVoidPointerName);
2445  annotateFunctionArgs.push_back(valueAsVoidPointer);
2446 
2447  Constant *annotationPointer = generatePointerToConstantString(module, annotation, annotationVariableName);
2448  annotateFunctionArgs.push_back(annotationPointer);
2449 
2450  Constant *fileNamePointer = constantsCache->get(fileName);
2451  annotateFunctionArgs.push_back(fileNamePointer);
2452 
2453  ConstantInt *lineNumberValue = ConstantInt::get(module->getContext(), APInt(32, lineNumber));
2454  annotateFunctionArgs.push_back(lineNumberValue);
2455 
2456  CallInst::Create(annotateFunction, annotateFunctionArgs, "", block);
2457 }
2458 
2462 void VuoCompilerCodeGenUtilities::generateModuleMetadata(Module *module, string metadata, string moduleKey)
2463 {
2464  // const char *moduleDetails = ...;
2465  Constant *moduleDetailsValue = VuoCompilerCodeGenUtilities::generatePointerToConstantString(module, metadata, ".str"); // VuoCompilerBitcodeParser::resolveGlobalToConst requires that the variable have a name
2466  Type *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2467  string variableName = "moduleDetails";
2468  if (! moduleKey.empty())
2469  variableName = VuoStringUtilities::prefixSymbolName("moduleDetails", moduleKey);
2470  GlobalVariable *moduleDetailsVariable = new GlobalVariable(*module, pointerToCharType, false, GlobalValue::ExternalLinkage, 0, variableName);
2471  moduleDetailsVariable->setInitializer(moduleDetailsValue);
2472 }
2473 
2479 Value * VuoCompilerCodeGenUtilities::generateTypeCastFromIntegerToPointer(Module *module, BasicBlock *block, Value *valueToCast, Type *typeToCastTo)
2480 {
2481  unsigned pointerBitWidth = 64;
2482  IntegerType *integerWithPointerBitWidth = IntegerType::get(module->getContext(), pointerBitWidth);
2483  CastInst *valueAsIntegerWithPointerBitWidth = CastInst::CreateIntegerCast(valueToCast, integerWithPointerBitWidth, true, "", block);
2484  return new IntToPtrInst(valueAsIntegerWithPointerBitWidth, typeToCastTo, "", block);
2485 }
2486 
2492 Value * VuoCompilerCodeGenUtilities::generateTypeCastFromFloatingPointToPointer(Module *module, BasicBlock *block, Value *valueToCast, Type *typeToCastTo)
2493 {
2494  unsigned pointerBitWidth = 64;
2495  Type *floatingPointWithPointerBitWidth = Type::getDoubleTy(module->getContext());
2496  IntegerType *integerWithPointerBitWidth = IntegerType::get(module->getContext(), pointerBitWidth);
2497  CastInst *valueAsFloatingPointWithPointerBitWidth = CastInst::CreateFPCast(valueToCast, floatingPointWithPointerBitWidth, "", block);
2498  Value *valueAsIntegerWithPointerBitWidth = new BitCastInst(valueAsFloatingPointWithPointerBitWidth, integerWithPointerBitWidth, "", block);
2499  return generateTypeCastFromIntegerToPointer(module, block, valueAsIntegerWithPointerBitWidth, typeToCastTo);
2500 }
2501 
2507 Value * VuoCompilerCodeGenUtilities::generateTypeCastFromPointerToInteger(Module *module, BasicBlock *block, Value *valueToCast, Type *typeToCastTo)
2508 {
2509  unsigned pointerBitWidth = 64;
2510  IntegerType *integerWithPointerBitWidth = IntegerType::get(module->getContext(), pointerBitWidth);
2511  CastInst *valueAsIntegerWithPointerBitWidth = new PtrToIntInst(valueToCast, integerWithPointerBitWidth, "", block);
2512  return CastInst::CreateIntegerCast(valueAsIntegerWithPointerBitWidth, typeToCastTo, true, "", block);
2513 }
2514 
2520 Value * VuoCompilerCodeGenUtilities::generateTypeCastFromPointerToFloatingPoint(Module *module, BasicBlock *block, Value *valueToCast, Type *typeToCastTo)
2521 {
2522  unsigned pointerBitWidth = 64;
2523  Type *floatingPointWithPointerBitWidth = Type::getDoubleTy(module->getContext());
2524  IntegerType *integerWithPointerBitWidth = IntegerType::get(module->getContext(), pointerBitWidth);
2525  Value *valueAsIntegerWithPointerBitWidth = generateTypeCastFromPointerToInteger(module, block, valueToCast, integerWithPointerBitWidth);
2526  CastInst *valueAsFloatingPointWithPointerBitWidth = new BitCastInst(valueAsIntegerWithPointerBitWidth, floatingPointWithPointerBitWidth, "", block);
2527  return CastInst::CreateFPCast(valueAsFloatingPointWithPointerBitWidth, typeToCastTo, "", block);
2528 }
2529 
2535 Value * VuoCompilerCodeGenUtilities::generateTypeCastFromLoweredTypeToStruct(BasicBlock *block, Value *valueToCast, Type *typeToCastTo)
2536 {
2537  Value *originalValueToCast = valueToCast;
2538 
2539  if (valueToCast->getType()->isVectorTy() || valueToCast->getType()->isDoubleTy())
2540  {
2541  // Struct was lowered to a vector or double.
2542  PointerType *pointerToLoweredType = PointerType::get(valueToCast->getType(), 0);
2543 
2544  AllocaInst *structVariable = new AllocaInst(typeToCastTo, 0, "", block);
2545  CastInst *structVariableAsLoweredType = new BitCastInst(structVariable, pointerToLoweredType, "", block);
2546  new StoreInst(valueToCast, structVariableAsLoweredType, false, block);
2547  return new LoadInst(structVariable, "", false, block);
2548  }
2549 
2550  if (valueToCast->getType()->isPointerTy())
2551  {
2552  // Struct was passed by value.
2553  valueToCast = new LoadInst(valueToCast, "", false, block);
2554  if (valueToCast->getType() == typeToCastTo)
2555  return valueToCast;
2556  }
2557 
2558  if (valueToCast->getType()->isStructTy())
2559  {
2560  // Struct types don't match because they were loaded from different modules.
2561  StructType *structTypeOfValueToCast = static_cast<StructType *>(valueToCast->getType());
2562  PointerType *pointerToTypeToCastTo = PointerType::get(typeToCastTo, 0);
2563 
2564  AllocaInst *otherStructVariable = new AllocaInst(structTypeOfValueToCast, 0, "", block);
2565  new StoreInst(valueToCast, otherStructVariable, false, block);
2566  CastInst *otherStructAsTypeToCastTo = new BitCastInst(otherStructVariable, pointerToTypeToCastTo, "", block);
2567  return new LoadInst(otherStructAsTypeToCastTo, "", false, block);
2568  }
2569 
2570  VUserLog("Error: Couldn't cast from lowered type to struct.");
2571  originalValueToCast->getType()->dump(); fprintf(stderr, "\n");
2572  typeToCastTo->dump(); fprintf(stderr, "\n");
2573  return originalValueToCast;
2574 }
2575 
2581 Value * VuoCompilerCodeGenUtilities::generateTypeCastFromLoweredTypeToVector(BasicBlock *block, Value *valueToCast, Type *typeToCastTo)
2582 {
2583  if (typeToCastTo->isVectorTy() && static_cast<VectorType *>(typeToCastTo)->getElementType()->isFloatTy())
2584  {
2585  uint64_t elementCount = static_cast<VectorType *>(typeToCastTo)->getNumElements();
2586  if (elementCount == 2 && valueToCast->getType()->isDoubleTy())
2587  {
2588  // VuoPoint2d — Vector of 2 floats was lowered to a double (x86_64).
2589  PointerType *pointerToDoubleType = PointerType::get(valueToCast->getType(), 0);
2590 
2591  AllocaInst *vectorVariable = new AllocaInst(typeToCastTo, 0, "", block);
2592  CastInst *dstVectorVariableAsDouble = new BitCastInst(vectorVariable, pointerToDoubleType, "", block);
2593  new StoreInst(valueToCast, dstVectorVariableAsDouble, false, block);
2594  return new LoadInst(vectorVariable, "", false, block);
2595  }
2596  else if (elementCount == 3 && valueToCast->getType()->isVectorTy() &&
2597  static_cast<VectorType *>(valueToCast->getType())->getNumElements() == 2 &&
2598  static_cast<VectorType *>(valueToCast->getType())->getElementType()->isDoubleTy())
2599  {
2600  // VuoPoint3d — Vector of 3 floats was lowered to a vector of 2 doubles (x86_64).
2601  PointerType *pointerToDoubleVectorType = PointerType::get(valueToCast->getType(), 0);
2602 
2603  AllocaInst *floatVectorVariable = new AllocaInst(typeToCastTo, 0, "", block);
2604  CastInst *floatVectorVariableAsDoubleVector = new BitCastInst(floatVectorVariable, pointerToDoubleVectorType, "", block);
2605  new StoreInst(valueToCast, floatVectorVariableAsDoubleVector, false, block);
2606  return new LoadInst(floatVectorVariable, "", false, block);
2607  }
2608  else if (elementCount == 3 && valueToCast->getType()->isVectorTy() &&
2609  static_cast<VectorType *>(valueToCast->getType())->getNumElements() == 4 &&
2610  static_cast<VectorType *>(valueToCast->getType())->getElementType()->isIntegerTy(32))
2611  {
2612  // VuoPoint3d — Vector of 3 floats was lowered to a vector of 4 i32s (arm64).
2613  PointerType *pointerToIntVectorType = PointerType::get(valueToCast->getType(), 0);
2614  AllocaInst *floatVectorVariable = new AllocaInst(typeToCastTo, 0, "", block);
2615  CastInst *floatVectorVariableAsIntVector = new BitCastInst(floatVectorVariable, pointerToIntVectorType, "", block);
2616  new StoreInst(valueToCast, floatVectorVariableAsIntVector, false, block);
2617  return new LoadInst(floatVectorVariable, "", false, block);
2618  }
2619  }
2620 
2621  VUserLog("Error: Couldn't cast from lowered type to vector.");
2622  valueToCast->getType()->dump(); fprintf(stderr, "\n");
2623  typeToCastTo->dump(); fprintf(stderr, "\n");
2624  return valueToCast;
2625 }
2626 
2632 Value *VuoCompilerCodeGenUtilities::generateTypeCastFromLoweredTypeToArray(Module *module, BasicBlock *block, Value *valueToCast, Type *typeToCastTo)
2633 {
2634  if (valueToCast->getType()->isStructTy())
2635  {
2636  StructType *valueType = static_cast<StructType *>(valueToCast->getType());
2637  ArrayType *arrayTypeToCastTo = static_cast<ArrayType *>(typeToCastTo);
2638  if (valueType->getElementType(0)->isFloatTy() && arrayTypeToCastTo->getElementType()->isFloatTy())
2639  {
2640  AllocaInst *arrayVariable = new AllocaInst(typeToCastTo, 0, "", block);
2641  PointerType *pointerToLoweredType = PointerType::get(valueToCast->getType(), 0);
2642  CastInst *arrayVariableAsLoweredType = new BitCastInst(arrayVariable, pointerToLoweredType, "", block);
2643  new StoreInst(valueToCast, arrayVariableAsLoweredType, false, block);
2644  return new LoadInst(arrayVariable, "", false, block);
2645  }
2646  }
2647 
2648  VUserLog("Error: Couldn't cast from lowered type to array.");
2649  valueToCast->getType()->dump(); fprintf(stderr, "\n");
2650  typeToCastTo->dump(); fprintf(stderr, "\n");
2651  return valueToCast;
2652 }
2653 
2657 void VuoCompilerCodeGenUtilities::generateRegisterCall(Module *module, BasicBlock *block, Value *argument, Function *freeFunction)
2658 {
2659  Function *function = getVuoRegisterFunction(module);
2660 
2661  Type *voidPointerType = function->getFunctionType()->getParamType(0);
2662  Type *pointerToCharType = function->getFunctionType()->getParamType(2);
2663  Type *intType = function->getFunctionType()->getParamType(3);
2664 
2665  ConstantPointerNull *nullValue = ConstantPointerNull::get( static_cast<PointerType *>(pointerToCharType) );
2666  Constant *zeroValue = ConstantInt::get(intType, 0);
2667 
2668  vector<Value *> args;
2669 
2670  BitCastInst *argumentAsVoidPointer = new BitCastInst(argument, voidPointerType, "", block);
2671  args.push_back(argumentAsVoidPointer);
2672 
2673  args.push_back(freeFunction);
2674 
2675  args.push_back(nullValue);
2676  args.push_back(zeroValue);
2677  args.push_back(nullValue);
2678  args.push_back(nullValue);
2679 
2680  CallInst::Create(function, args, "", block);
2681 }
2682 
2686 void VuoCompilerCodeGenUtilities::generateRetainCall(Module *module, BasicBlock *block, Value *argument)
2687 {
2688  generateRetainOrReleaseCall(module, block, argument, true);
2689 }
2690 
2694 void VuoCompilerCodeGenUtilities::generateReleaseCall(Module *module, BasicBlock *block, Value *argument)
2695 {
2696  generateRetainOrReleaseCall(module, block, argument, false);
2697 }
2698 
2708 void VuoCompilerCodeGenUtilities::generateRetainOrReleaseCall(Module *module, BasicBlock *block, Value *argument, bool isRetain)
2709 {
2710  if (argument->getType()->isPointerTy())
2711  {
2712  Function *function = (isRetain ? getVuoRetainFunction(module) : getVuoReleaseFunction(module));
2713  Type *voidPointerType = function->getFunctionType()->getParamType(0);
2714 
2715  vector<Value *> retainOrReleaseArgs;
2716  retainOrReleaseArgs.push_back(VuoCompilerCodeGenUtilities::generateTypeCast(module, block, argument, voidPointerType));
2717  CallInst::Create(function, retainOrReleaseArgs, "", block);
2718  }
2719  else if (argument->getType()->isStructTy())
2720  {
2721  AllocaInst *structPointer = new AllocaInst(argument->getType(), 0, "", block);
2722  new StoreInst(argument, structPointer, false, block);
2723 
2724  int numElements = static_cast<StructType *>(argument->getType())->getNumElements();
2725  for (unsigned i = 0; i < numElements; ++i)
2726  {
2727  Value *member = generateGetStructPointerElement(module, block, structPointer, i);
2728  generateRetainOrReleaseCall(module, block, member, isRetain);
2729  }
2730  }
2731 }
2732 
2738 {
2739  return type->isPointerTy() || type->isStructTy();
2740 }
2741 
2745 void VuoCompilerCodeGenUtilities::generateFreeCall(Module *module, BasicBlock *block, Value *argument)
2746 {
2747  Function *freeFunction = getFreeFunction(module);
2748  PointerType *voidPointerType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2749  Value *argumentAsVoidPointer = new BitCastInst(argument, voidPointerType, "", block);
2750  CallInst::Create(freeFunction, argumentAsVoidPointer, "", block);
2751 }
2752 
2756 void VuoCompilerCodeGenUtilities::generateJsonObjectPut(Module *module, BasicBlock *block, Value *jsonObjectValue)
2757 {
2758  Function *function = getJsonObjectPutFunction(module);
2759  CallInst::Create(function, jsonObjectValue, "", block);
2760 }
2761 
2766 void VuoCompilerCodeGenUtilities::generateNullCheck(Module *module, Function *function, Value *valueToCheck,
2767  BasicBlock *initialBlock, BasicBlock *&nullBlock, BasicBlock *&notNullBlock)
2768 {
2769  nullBlock = BasicBlock::Create(module->getContext(), "null", function, NULL);
2770  notNullBlock = BasicBlock::Create(module->getContext(), "notNull", function, NULL);
2771 
2772  Value *nullValue = ConstantPointerNull::get( static_cast<PointerType *>(valueToCheck->getType()) );
2773  ICmpInst *isNotNull = new ICmpInst(*initialBlock, ICmpInst::ICMP_NE, valueToCheck, nullValue, "");
2774  BranchInst::Create(notNullBlock, nullBlock, isNotNull, initialBlock);
2775 }
2776 
2780 Value * VuoCompilerCodeGenUtilities::generateSerialization(Module *module, BasicBlock *block, Value *valueToSerialize,
2781  VuoCompilerConstantsCache *constantsCache)
2782 {
2783  if (valueToSerialize->getType()->isPointerTy())
2784  {
2785  vector<Value *> replacementValues;
2786  replacementValues.push_back(valueToSerialize);
2787  return generateFormattedString(module, block, "%lx", replacementValues, constantsCache);
2788  }
2789  else
2790  {
2792  VUserLog("Error: Couldn't serialize non-pointer value.");
2793  return NULL;
2794  }
2795 }
2796 
2801 void VuoCompilerCodeGenUtilities::generateUnserialization(Module *module, BasicBlock *block, Value *stringToUnserialize, Value *destinationVariable,
2802  VuoCompilerConstantsCache *constantsCache)
2803 {
2804  if (destinationVariable->getType()->isPointerTy())
2805  {
2806  // sscanf(stringToUnserialize, "%lx", destinationPointer);
2807  Value *formatString = constantsCache->get("%lx");
2808  Function *sscanfFunction = getSscanfFunction(module);
2809  vector<Value *> sscanfArgs;
2810  sscanfArgs.push_back(stringToUnserialize);
2811  sscanfArgs.push_back(formatString);
2812  sscanfArgs.push_back(destinationVariable);
2813  CallInst::Create(sscanfFunction, sscanfArgs, "", block);
2814  }
2815  else
2816  {
2818  }
2819 }
2820 
2824 ICmpInst * VuoCompilerCodeGenUtilities::generateIsPausedComparison(Module *module, BasicBlock *block, Value *compositionStateValue)
2825 {
2826  Type *boolType = IntegerType::get(module->getContext(), 64);
2827 
2828  const char *functionName = "vuoIsPaused";
2829  Function *function = module->getFunction(functionName);
2830  if (! function)
2831  {
2832  FunctionType *functionType = FunctionType::get(boolType, compositionStateValue->getType(), false);
2833  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
2834  }
2835 
2836  CallInst *isPausedValue = CallInst::Create(function, compositionStateValue, "", block);
2837  Constant *falseValue = ConstantInt::get(boolType, 0);
2838  return new ICmpInst(*block, ICmpInst::ICMP_NE, isPausedValue, falseValue, "");
2839 }
2840 
2845  Value *compositionStateValue, Value *nodeIdentifierValue)
2846 {
2847  const char *functionName = "vuoSendNodeExecutionStarted";
2848  Function *function = module->getFunction(functionName);
2849  if (! function)
2850  {
2851  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
2852  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2853 
2854  vector<Type *> functionParams;
2855  functionParams.push_back(pointerToCompositionState);
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(nodeIdentifierValue);
2864  CallInst::Create(function, args, "", block);
2865 }
2866 
2871  Value *compositionStateValue, Value *nodeIdentifierValue)
2872 {
2873  const char *functionName = "vuoSendNodeExecutionFinished";
2874  Function *function = module->getFunction(functionName);
2875  if (! function)
2876  {
2877  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
2878  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2879 
2880  vector<Type *> functionParams;
2881  functionParams.push_back(pointerToCompositionState);
2882  functionParams.push_back(pointerToCharType);
2883  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
2884  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
2885  }
2886 
2887  vector<Value *> args;
2888  args.push_back(compositionStateValue);
2889  args.push_back(nodeIdentifierValue);
2890  CallInst::Create(function, args, "", block);
2891 }
2892 
2896 void VuoCompilerCodeGenUtilities::generateSendInputPortsUpdated(Module *module, BasicBlock *block,
2897  Value *compositionStateValue, Value *portIdentifierValue,
2898  bool receivedEvent, bool receivedData,
2899  Value *portDataSummaryValue)
2900 {
2901  IntegerType *boolType = IntegerType::get(module->getContext(), 1);
2902  Value *receivedEventValue = ConstantInt::get(boolType, receivedEvent ? 1 : 0);
2903  Value *receivedDataValue = ConstantInt::get(boolType, receivedData ? 1 : 0);
2904  generateSendInputPortsUpdated(module, block, compositionStateValue, portIdentifierValue, receivedEventValue, receivedDataValue, portDataSummaryValue);
2905 }
2906 
2910 void VuoCompilerCodeGenUtilities::generateSendInputPortsUpdated(Module *module, BasicBlock *block,
2911  Value *compositionStateValue, Value *portIdentifierValue,
2912  Value *receivedEventValue, Value *receivedDataValue,
2913  Value *portDataSummaryValue)
2914 {
2915  const char *functionName = "vuoSendInputPortsUpdated";
2916  Function *function = module->getFunction(functionName);
2917  if (! function)
2918  {
2919  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
2920  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2921  IntegerType *boolType = IntegerType::get(module->getContext(), 1);
2922 
2923  vector<Type *> functionParams;
2924  functionParams.push_back(pointerToCompositionState);
2925  functionParams.push_back(pointerToCharType);
2926  functionParams.push_back(boolType);
2927  functionParams.push_back(boolType);
2928  functionParams.push_back(pointerToCharType);
2929  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
2930  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
2931  }
2932 
2933  vector<Value *> args;
2934  args.push_back(compositionStateValue);
2935  args.push_back(portIdentifierValue);
2936  args.push_back(receivedEventValue);
2937  args.push_back(receivedDataValue);
2938  args.push_back(portDataSummaryValue);
2939  CallInst::Create(function, args, "", block);
2940 }
2941 
2946  Value *compositionStateValue, Value *portIdentifierValue,
2947  Value *sentEventValue, Value *sentDataValue,
2948  Value *portDataSummaryValue)
2949 {
2950  const char *functionName = "vuoSendOutputPortsUpdated";
2951  Function *function = module->getFunction(functionName);
2952  if (! function)
2953  {
2954  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
2955  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2956  IntegerType *boolType = IntegerType::get(module->getContext(), 1);
2957 
2958  vector<Type *> functionParams;
2959  functionParams.push_back(pointerToCompositionState);
2960  functionParams.push_back(pointerToCharType);
2961  functionParams.push_back(boolType);
2962  functionParams.push_back(boolType);
2963  functionParams.push_back(pointerToCharType);
2964  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
2965  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
2966  }
2967 
2968  vector<Value *> args;
2969  args.push_back(compositionStateValue);
2970  args.push_back(portIdentifierValue);
2971  args.push_back(sentEventValue);
2972  args.push_back(sentDataValue);
2973  args.push_back(portDataSummaryValue);
2974  CallInst::Create(function, args, "", block);
2975 }
2976 
2981  Value *compositionStateValue, Value *portIdentifierValue,
2982  Value *sentDataValue, Value *portDataSummaryValue)
2983 {
2984  const char *functionName = "vuoSendPublishedOutputPortsUpdated";
2985  Function *function = module->getFunction(functionName);
2986  if (! function)
2987  {
2988  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
2989  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2990  IntegerType *boolType = IntegerType::get(module->getContext(), 1);
2991 
2992  vector<Type *> functionParams;
2993  functionParams.push_back(pointerToCompositionState);
2994  functionParams.push_back(pointerToCharType);
2995  functionParams.push_back(boolType);
2996  functionParams.push_back(pointerToCharType);
2997  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
2998  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
2999  }
3000 
3001  vector<Value *> args;
3002  args.push_back(compositionStateValue);
3003  args.push_back(portIdentifierValue);
3004  args.push_back(sentDataValue);
3005  args.push_back(portDataSummaryValue);
3006  CallInst::Create(function, args, "", block);
3007 }
3008 
3012 void VuoCompilerCodeGenUtilities::generateSendEventFinished(Module *module, BasicBlock *block,
3013  Value *compositionStateValue, Value *eventIdValue)
3014 {
3015  const char *functionName = "vuoSendEventFinished";
3016  Function *function = module->getFunction(functionName);
3017  if (! function)
3018  {
3019  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
3020  Type *eventIdType = generateNoEventIdConstant(module)->getType();
3021 
3022  vector<Type *> functionParams;
3023  functionParams.push_back(pointerToCompositionState);
3024  functionParams.push_back(eventIdType);
3025  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
3026  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3027  }
3028 
3029  vector<Value *> args;
3030  args.push_back(compositionStateValue);
3031  args.push_back(eventIdValue);
3032  CallInst::Create(function, args, "", block);
3033 }
3034 
3038 void VuoCompilerCodeGenUtilities::generateSendEventDropped(Module *module, BasicBlock *block,
3039  Value *compositionStateValue, Value *portIdentifierValue)
3040 {
3041  const char *functionName = "vuoSendEventDropped";
3042  Function *function = module->getFunction(functionName);
3043  if (! function)
3044  {
3045  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
3046  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3047 
3048  vector<Type *> functionParams;
3049  functionParams.push_back(pointerToCompositionState);
3050  functionParams.push_back(pointerToCharType);
3051  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
3052  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3053  }
3054 
3055  vector<Value *> args;
3056  args.push_back(compositionStateValue);
3057  args.push_back(portIdentifierValue);
3058  CallInst::Create(function, args, "", block);
3059 }
3060 
3064 ICmpInst * VuoCompilerCodeGenUtilities::generateShouldSendDataTelemetryComparison(Module *module, BasicBlock *block, string portIdentifier,
3065  Value *compositionStateValue,
3066  VuoCompilerConstantsCache *constantsCache)
3067 {
3068  const char *functionName = "vuoShouldSendPortDataTelemetry";
3069  Function *shouldSendTelemetryFunction = module->getFunction(functionName);
3070  if (! shouldSendTelemetryFunction)
3071  {
3072  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
3073  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3074 
3075  vector<Type *> functionParams;
3076  functionParams.push_back(pointerToCompositionState);
3077  functionParams.push_back(pointerToCharType);
3078  FunctionType *functionType = FunctionType::get(IntegerType::get(module->getContext(), 32), functionParams, false);
3079  shouldSendTelemetryFunction = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3080  }
3081 
3082  Constant *portIdentifierValue = constantsCache->get(portIdentifier);
3083 
3084  vector<Value *> args;
3085  args.push_back(compositionStateValue);
3086  args.push_back(portIdentifierValue);
3087  CallInst *retValue = CallInst::Create(shouldSendTelemetryFunction, args, "", block);
3088 
3089  Constant *zeroValue = ConstantInt::get(retValue->getType(), 0);
3090  return new ICmpInst(*block, ICmpInst::ICMP_NE, retValue, zeroValue, "");
3091 }
3092 
3097 void VuoCompilerCodeGenUtilities::generateIsNodeBeingRemovedOrReplacedCheck(Module *module, Function *function, string nodeIdentifier,
3098  Value *compositionStateValue,
3099  BasicBlock *initialBlock, BasicBlock *&trueBlock, BasicBlock *&falseBlock,
3100  VuoCompilerConstantsCache *constantsCache,
3101  Value *&replacementJsonValue)
3102 {
3103  Type *boolType = IntegerType::get(module->getContext(), 64);
3104  PointerType *pointerToJsonObjectType = PointerType::get(getJsonObjectType(module), 0);
3105 
3106  const char *functionName = "vuoIsNodeBeingRemovedOrReplaced";
3107  Function *calledFunction = module->getFunction(functionName);
3108  if (! calledFunction)
3109  {
3110  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3111  PointerType *pointerToPointerToJsonObjectType = PointerType::get(pointerToJsonObjectType, 0);
3112 
3113  vector<Type *> functionParams;
3114  functionParams.push_back(compositionStateValue->getType());
3115  functionParams.push_back(pointerToCharType);
3116  functionParams.push_back(pointerToPointerToJsonObjectType);
3117  FunctionType *functionType = FunctionType::get(boolType, functionParams, false);
3118  calledFunction = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3119  }
3120 
3121  Value *nodeIdentifierValue = constantsCache->get(nodeIdentifier);
3122 
3123  AllocaInst *replacementJsonVariable = new AllocaInst(pointerToJsonObjectType, 0, "", initialBlock);
3124  new StoreInst(ConstantPointerNull::get(pointerToJsonObjectType), replacementJsonVariable, false, initialBlock);
3125 
3126  vector<Value *> args;
3127  args.push_back(compositionStateValue);
3128  args.push_back(nodeIdentifierValue);
3129  args.push_back(replacementJsonVariable);
3130  CallInst *retValue = CallInst::Create(calledFunction, args, "", initialBlock);
3131 
3132  replacementJsonValue = new LoadInst(replacementJsonVariable, "", false, initialBlock);
3133 
3134  trueBlock = BasicBlock::Create(module->getContext(), "removedReplaced", function, NULL);
3135  falseBlock = BasicBlock::Create(module->getContext(), "notRemovedReplaced", function, NULL);
3136  Constant *falseValue = ConstantInt::get(boolType, 0);
3137  ICmpInst *retIsTrue = new ICmpInst(*initialBlock, ICmpInst::ICMP_NE, retValue, falseValue, "");
3138  BranchInst::Create(trueBlock, falseBlock, retIsTrue, initialBlock);
3139 }
3140 
3145 ICmpInst * VuoCompilerCodeGenUtilities::generateIsNodeBeingAddedOrReplacedCheck(Module *module, Function *function, string nodeIdentifier,
3146  Value *compositionStateValue,
3147  BasicBlock *initialBlock, BasicBlock *&trueBlock, BasicBlock *&falseBlock,
3148  VuoCompilerConstantsCache *constantsCache,
3149  Value *&replacementJsonValue)
3150 {
3151  Type *boolType = IntegerType::get(module->getContext(), 64);
3152  PointerType *pointerToJsonObjectType = PointerType::get(getJsonObjectType(module), 0);
3153 
3154  const char *functionName = "vuoIsNodeBeingAddedOrReplaced";
3155  Function *calledFunction = module->getFunction(functionName);
3156  if (! calledFunction)
3157  {
3158  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3159  PointerType *pointerToPointerToJsonObjectType = PointerType::get(pointerToJsonObjectType, 0);
3160 
3161  vector<Type *> functionParams;
3162  functionParams.push_back(compositionStateValue->getType());
3163  functionParams.push_back(pointerToCharType);
3164  functionParams.push_back(pointerToPointerToJsonObjectType);
3165  FunctionType *functionType = FunctionType::get(boolType, functionParams, false);
3166  calledFunction = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3167  }
3168 
3169  Value *nodeIdentifierValue = constantsCache->get(nodeIdentifier);
3170 
3171  AllocaInst *replacementJsonVariable = new AllocaInst(pointerToJsonObjectType, 0, "", initialBlock);
3172  new StoreInst(ConstantPointerNull::get(pointerToJsonObjectType), replacementJsonVariable, false, initialBlock);
3173 
3174  vector<Value *> args;
3175  args.push_back(compositionStateValue);
3176  args.push_back(nodeIdentifierValue);
3177  args.push_back(replacementJsonVariable);
3178  CallInst *retValue = CallInst::Create(calledFunction, args, "", initialBlock);
3179 
3180  replacementJsonValue = new LoadInst(replacementJsonVariable, "", false, initialBlock);
3181 
3182  trueBlock = BasicBlock::Create(module->getContext(), "addedReplaced", function, NULL);
3183  falseBlock = BasicBlock::Create(module->getContext(), "notAddedReplaced", function, NULL);
3184  Constant *falseValue = ConstantInt::get(boolType, 0);
3185  ICmpInst *retIsTrue = new ICmpInst(*initialBlock, ICmpInst::ICMP_NE, retValue, falseValue, "");
3186  BranchInst::Create(trueBlock, falseBlock, retIsTrue, initialBlock);
3187 
3188  return retIsTrue;
3189 }
3190 
3195 {
3196  return ConstantInt::get(module->getContext(), APInt(64, 0));
3197 }
3198 
3202 Value * VuoCompilerCodeGenUtilities::generateGetNodeContext(Module *module, BasicBlock *block,
3203  Value *compositionStateValue, size_t nodeIndex)
3204 {
3205  IntegerType *unsignedLongType = IntegerType::get(module->getContext(), 64);
3206  Value *nodeIndexValue = ConstantInt::get(unsignedLongType, nodeIndex);
3207  return generateGetNodeContext(module, block, compositionStateValue, nodeIndexValue);
3208 }
3209 
3213 Value * VuoCompilerCodeGenUtilities::generateGetNodeContext(Module *module, BasicBlock *block,
3214  Value *compositionStateValue, Value *nodeIndexValue)
3215 {
3216  const char *functionName = "vuoGetNodeContext";
3217  Function *function = module->getFunction(functionName);
3218  if (! function)
3219  {
3220  IntegerType *unsignedLongType = IntegerType::get(module->getContext(), 64);
3221  PointerType *pointerToNodeContextType = PointerType::get(getNodeContextType(module), 0);
3222 
3223  vector<Type *> functionParams;
3224  functionParams.push_back(compositionStateValue->getType());
3225  functionParams.push_back(unsignedLongType);
3226  FunctionType *functionType = FunctionType::get(pointerToNodeContextType, functionParams, false);
3227  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3228  }
3229 
3230  vector<Value *> args;
3231  args.push_back(compositionStateValue);
3232  args.push_back(nodeIndexValue);
3233  return CallInst::Create(function, args, "", block);
3234 }
3235 
3239 Value * VuoCompilerCodeGenUtilities::generateGetCompositionContext(Module *module, BasicBlock *block,
3240  Value *compositionStateValue)
3241 {
3242  const char *functionName = "vuoGetCompositionContext";
3243  Function *function = module->getFunction(functionName);
3244  if (! function)
3245  {
3246  PointerType *pointerToNodeContextType = PointerType::get(getNodeContextType(module), 0);
3247 
3248  vector<Type *> functionParams;
3249  functionParams.push_back(compositionStateValue->getType());
3250  FunctionType *functionType = FunctionType::get(pointerToNodeContextType, functionParams, false);
3251  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3252  }
3253 
3254  vector<Value *> args;
3255  args.push_back(compositionStateValue);
3256  return CallInst::Create(function, args, "", block);
3257 }
3258 
3262 void VuoCompilerCodeGenUtilities::generateAddNodeMetadata(Module *module, BasicBlock *block,
3263  Value *compositionStateValue, Value *nodeIdentifierValue,
3264  Function *compositionCreateContextForNodeFunction,
3265  Function *compositionSetPortValueFunction,
3266  Function *compositionGetPortValueFunction,
3267  Function *compositionFireTriggerPortEventFunction,
3268  Function *compositionReleasePortDataFunction)
3269 {
3270  const char *functionName = "vuoAddNodeMetadata";
3271  Function *function = module->getFunction(functionName);
3272  if (! function)
3273  {
3274  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3275  PointerType *compositionCreateContextForNodeFunctionType = PointerType::getUnqual(getCompositionCreateContextForNodeFunction(module)->getFunctionType());
3276  PointerType *compositionSetPortValueFunctionType = PointerType::getUnqual(getCompositionSetPortValueFunction(module)->getFunctionType());
3277  PointerType *compositionGetPortValueFunctionType = PointerType::getUnqual(getCompositionGetPortValueFunction(module)->getFunctionType());
3278  PointerType *compositionFireTriggerPortEventFunctionType = PointerType::getUnqual(getCompositionFireTriggerPortEventFunction(module)->getFunctionType());
3279  PointerType *compositionReleasePortDataFunctionType = PointerType::getUnqual(getCompositionReleasePortDataFunction(module)->getFunctionType());
3280 
3281  vector<Type *> functionParams;
3282  functionParams.push_back(compositionStateValue->getType());
3283  functionParams.push_back(pointerToCharType);
3284  functionParams.push_back(compositionCreateContextForNodeFunctionType);
3285  functionParams.push_back(compositionSetPortValueFunctionType);
3286  functionParams.push_back(compositionGetPortValueFunctionType);
3287  functionParams.push_back(compositionFireTriggerPortEventFunctionType);
3288  functionParams.push_back(compositionReleasePortDataFunctionType);
3289  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
3290  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3291  }
3292 
3293  vector<Value *> args;
3294  args.push_back(compositionStateValue);
3295  args.push_back(nodeIdentifierValue);
3296  args.push_back(compositionCreateContextForNodeFunction);
3297  args.push_back(compositionSetPortValueFunction);
3298  args.push_back(compositionGetPortValueFunction);
3299  args.push_back(compositionFireTriggerPortEventFunction);
3300  args.push_back(compositionReleasePortDataFunction);
3301  CallInst::Create(function, args, "", block);
3302 }
3303 
3307 void VuoCompilerCodeGenUtilities::generateAddPortMetadata(Module *module, BasicBlock *block,
3308  Value *compositionStateValue, Value *portIdentifierValue,
3309  Value *portNameValue, size_t typeIndex, Value *initialValueValue)
3310 {
3311  IntegerType *unsignedLongType = IntegerType::get(module->getContext(), 64);
3312 
3313  const char *functionName = "vuoAddPortMetadata";
3314  Function *function = module->getFunction(functionName);
3315  if (! function)
3316  {
3317  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3318 
3319  vector<Type *> functionParams;
3320  functionParams.push_back(compositionStateValue->getType());
3321  functionParams.push_back(pointerToCharType);
3322  functionParams.push_back(pointerToCharType);
3323  functionParams.push_back(unsignedLongType);
3324  functionParams.push_back(pointerToCharType);
3325  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
3326  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3327  }
3328 
3329  Value *typeIndexValue = ConstantInt::get(unsignedLongType, typeIndex);
3330 
3331  vector<Value *> args;
3332  args.push_back(compositionStateValue);
3333  args.push_back(portIdentifierValue);
3334  args.push_back(portNameValue);
3335  args.push_back(typeIndexValue);
3336  args.push_back(initialValueValue);
3337  CallInst::Create(function, args, "", block);
3338 }
3339 
3343 void VuoCompilerCodeGenUtilities::generateInitContextForTopLevelComposition(Module *module, BasicBlock *block, Value *compositionStateValue,
3344  bool isStatefulComposition, size_t publishedOutputPortCount)
3345 {
3346  IntegerType *boolType = IntegerType::get(module->getContext(), 64);
3347  IntegerType *unsignedLongType = IntegerType::get(module->getContext(), 64);
3348 
3349  const char *functionName = "vuoInitContextForTopLevelComposition";
3350  Function *function = module->getFunction(functionName);
3351  if (! function)
3352  {
3353  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
3354 
3355  vector<Type *> functionParams;
3356  functionParams.push_back(pointerToCompositionState);
3357  functionParams.push_back(boolType);
3358  functionParams.push_back(unsignedLongType);
3359  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
3360  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3361  }
3362 
3363  Value *isStatefulCompositionValue = ConstantInt::get(boolType, isStatefulComposition);
3364  Value *publishedOutputPortCountValue = ConstantInt::get(unsignedLongType, publishedOutputPortCount);
3365 
3366  vector<Value *> args;
3367  args.push_back(compositionStateValue);
3368  args.push_back(isStatefulCompositionValue);
3369  args.push_back(publishedOutputPortCountValue);
3370  CallInst::Create(function, args, "", block);
3371 }
3372 
3376 void VuoCompilerCodeGenUtilities::generateFiniContextForTopLevelComposition(Module *module, BasicBlock *block, Value *compositionStateValue)
3377 {
3378  const char *functionName = "vuoFiniContextForTopLevelComposition";
3379  Function *function = module->getFunction(functionName);
3380  if (! function)
3381  {
3382  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
3383 
3384  vector<Type *> functionParams;
3385  functionParams.push_back(pointerToCompositionState);
3386  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
3387  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3388  }
3389 
3390  vector<Value *> args;
3391  args.push_back(compositionStateValue);
3392  CallInst::Create(function, args, "", block);
3393 }
3394 
3398 Value * VuoCompilerCodeGenUtilities::getTriggerWorkersScheduledValue(Module *module, BasicBlock *block, Value *compositionStateValue)
3399 {
3400  const char *functionName = "vuoGetTriggerWorkersScheduled";
3401  Function *function = module->getFunction(functionName);
3402  if (! function)
3403  {
3404  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
3405  Type *dispatchGroupType = getDispatchGroupType(module);
3406 
3407  vector<Type *> functionParams;
3408  functionParams.push_back(pointerToCompositionState);
3409  FunctionType *functionType = FunctionType::get(dispatchGroupType, functionParams, false);
3410  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3411  }
3412 
3413  vector<Value *> args;
3414  args.push_back(compositionStateValue);
3415  return CallInst::Create(function, args, "", block);
3416 }
3417 
3421 Value * VuoCompilerCodeGenUtilities::generateGetInputPortString(Module *module, BasicBlock *block, Value *compositionStateValue,
3422  Value *portIdentifierValue, Value *interprocessSerializationValue)
3423 {
3424  const char *functionName = "vuoGetInputPortString";
3425  Function *function = module->getFunction(functionName);
3426  if (! function)
3427  {
3428  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
3429  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3430  IntegerType *boolType = IntegerType::get(module->getContext(), 32);
3431 
3432  vector<Type *> functionParams;
3433  functionParams.push_back(pointerToCompositionState);
3434  functionParams.push_back(pointerToCharType);
3435  functionParams.push_back(boolType);
3436  FunctionType *functionType = FunctionType::get(pointerToCharType, functionParams, false);
3437  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3438  }
3439 
3440  vector<Value *> args;
3441  args.push_back(compositionStateValue);
3442  args.push_back(portIdentifierValue);
3443  args.push_back(interprocessSerializationValue);
3444  return CallInst::Create(function, args, "", block);
3445 }
3446 
3450 Value * VuoCompilerCodeGenUtilities::generateGetOutputPortString(Module *module, BasicBlock *block, Value *compositionStateValue,
3451  Value *portIdentifierValue, Value *interprocessSerializationValue)
3452 {
3453  const char *functionName = "vuoGetOutputPortString";
3454  Function *function = module->getFunction(functionName);
3455  if (! function)
3456  {
3457  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
3458  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3459  IntegerType *boolType = IntegerType::get(module->getContext(), 32);
3460 
3461  vector<Type *> functionParams;
3462  functionParams.push_back(pointerToCompositionState);
3463  functionParams.push_back(pointerToCharType);
3464  functionParams.push_back(boolType);
3465  FunctionType *functionType = FunctionType::get(pointerToCharType, functionParams, false);
3466  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3467  }
3468 
3469  vector<Value *> args;
3470  args.push_back(compositionStateValue);
3471  args.push_back(portIdentifierValue);
3472  args.push_back(interprocessSerializationValue);
3473  return CallInst::Create(function, args, "", block);
3474 }
3475 
3479 Value * VuoCompilerCodeGenUtilities::generateRuntimeStateValue(Module *module, BasicBlock *block)
3480 {
3481  const char *variableName = "vuoRuntimeState";
3482  GlobalVariable *variable = module->getNamedGlobal(variableName);
3483  if (! variable)
3484  {
3485  PointerType *voidPointer = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3486  variable = new GlobalVariable(*module, voidPointer, false, GlobalValue::ExternalLinkage, 0, variableName);
3487  }
3488 
3489  return new LoadInst(variable, "", false, block);
3490 }
3491 
3495 Value * VuoCompilerCodeGenUtilities::generateGetNextEventId(Module *module, BasicBlock *block, Value *compositionStateValue)
3496 {
3497  const char *functionName = "vuoGetNextEventId";
3498  Function *function = module->getFunction(functionName);
3499  if (! function)
3500  {
3501  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
3502  Type *eventIdType = IntegerType::get(module->getContext(), 64);
3503 
3504  vector<Type *> functionParams;
3505  functionParams.push_back(pointerToCompositionState);
3506  FunctionType *functionType = FunctionType::get(eventIdType, functionParams, false);
3507  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3508  }
3509 
3510  vector<Value *> args;
3511  args.push_back(compositionStateValue);
3512  return CallInst::Create(function, args, "", block);
3513 }
3514 
3519  Value *compositionStateValue, Value *dataCopyValue,
3520  Value *eventIdCopyValue)
3521 {
3522  const char *functionName = "vuoCreateTriggerWorkerContext";
3523  Function *function = module->getFunction(functionName);
3524  if (! function)
3525  {
3526  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
3527  PointerType *voidPointerType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3528  PointerType *pointerToEventIdType = PointerType::get(generateNoEventIdConstant(module)->getType(), 0);
3529 
3530  vector<Type *> functionParams;
3531  functionParams.push_back(pointerToCompositionState);
3532  functionParams.push_back(voidPointerType);
3533  functionParams.push_back(pointerToEventIdType);
3534  FunctionType *functionType = FunctionType::get(voidPointerType, functionParams, false);
3535  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3536  }
3537 
3538  vector<Value *> args;
3539  args.push_back(compositionStateValue);
3540  args.push_back(dataCopyValue);
3541  args.push_back(eventIdCopyValue);
3542  return CallInst::Create(function, args, "", block);
3543 }
3544 
3548 void VuoCompilerCodeGenUtilities::generateFreeTriggerWorkerContext(Module *module, BasicBlock *block, Value *contextValue)
3549 {
3550  const char *functionName = "vuoFreeTriggerWorkerContext";
3551  Function *function = module->getFunction(functionName);
3552  if (! function)
3553  {
3554  PointerType *voidPointerType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3555 
3556  vector<Type *> functionParams;
3557  functionParams.push_back(voidPointerType);
3558  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
3559  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3560  }
3561 
3562  vector<Value *> args;
3563  args.push_back(contextValue);
3564  CallInst::Create(function, args, "", block);
3565 }
3566 
3571  Value *compositionStateValue, Value *inputPortIdentifierValue,
3572  Value *valueAsStringValue, Value *isCompositionRunningValue)
3573 {
3574  const char *functionName = "vuoCreatePublishedInputWorkerContext";
3575  Function *function = module->getFunction(functionName);
3576  if (! function)
3577  {
3578  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
3579  PointerType *pointerToChar = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3580  PointerType *voidPointerType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3581  Type *boolType = IntegerType::get(module->getContext(), 64);
3582 
3583  vector<Type *> functionParams;
3584  functionParams.push_back(pointerToCompositionState);
3585  functionParams.push_back(pointerToChar);
3586  functionParams.push_back(pointerToChar);
3587  functionParams.push_back(boolType);
3588  FunctionType *functionType = FunctionType::get(voidPointerType, functionParams, false);
3589  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3590  }
3591 
3592  vector<Value *> args;
3593  args.push_back(compositionStateValue);
3594  args.push_back(inputPortIdentifierValue);
3595  args.push_back(valueAsStringValue);
3596  args.push_back(isCompositionRunningValue);
3597  return CallInst::Create(function, args, "", block);
3598 }
3599 
3604  Value *compositionStateValue)
3605 {
3606  const char *functionName = "vuoAddCompositionStateToThreadLocalStorage";
3607  Function *function = module->getFunction(functionName);
3608  if (! function)
3609  {
3610  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
3611 
3612  vector<Type *> functionParams;
3613  functionParams.push_back(pointerToCompositionState);
3614  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
3615  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3616  }
3617 
3618  vector<Value *> args;
3619  args.push_back(compositionStateValue);
3620  CallInst::Create(function, args, "", block);
3621 }
3622 
3627 {
3628  const char *functionName = "vuoRemoveCompositionStateFromThreadLocalStorage";
3629  Function *function = module->getFunction(functionName);
3630  if (! function)
3631  {
3632  vector<Type *> functionParams;
3633  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
3634  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3635  }
3636 
3637  vector<Value *> args;
3638  CallInst::Create(function, args, "", block);
3639 }
3640 
3644 Value * VuoCompilerCodeGenUtilities::generateStderr(Module *module, BasicBlock *block)
3645 {
3646  PointerType *pointerToFileType = getPointerToFileType(module);
3647 
3648  string variableName = "__stderrp";
3649  GlobalVariable *stderrVariable = module->getNamedGlobal(variableName);
3650  if (! stderrVariable)
3651  stderrVariable = new GlobalVariable(*module, pointerToFileType, false, GlobalValue::ExternalLinkage, 0, variableName);
3652 
3653  return new LoadInst(stderrVariable, "", false, block);
3654 }
3655 
3659 void VuoCompilerCodeGenUtilities::generatePrint(Module *module, BasicBlock *block, string formatString, Value *value)
3660 {
3661  vector<Value *> values;
3662  if (value)
3663  values.push_back(value);
3664  generatePrint(module, block, formatString, values);
3665 }
3666 
3670 void VuoCompilerCodeGenUtilities::generatePrint(Module *module, BasicBlock *block, string formatString, const vector<Value *> &values)
3671 {
3672  Value *formatStringValue = generatePointerToConstantString(module, formatString);
3673  Value *stderrValue = generateStderr(module, block);
3674 
3675  Function *fprintfFunction = getFprintfFunction(module);
3676  vector<Value *> fprintfArgs;
3677  fprintfArgs.push_back(stderrValue);
3678  fprintfArgs.push_back(formatStringValue);
3679  for (vector<Value *>::const_iterator i = values.begin(); i != values.end(); ++i)
3680  fprintfArgs.push_back(*i);
3681  CallInst::Create(fprintfFunction, fprintfArgs, "", block);
3682 }
3683 
3685 
3689 {
3690  StructType *dispatch_semaphore_s_type = module->getTypeByName("struct.dispatch_semaphore_s");
3691  if (! dispatch_semaphore_s_type)
3692  dispatch_semaphore_s_type = StructType::create(module->getContext(), "struct.dispatch_semaphore_s");
3693 
3694  PointerType *dispatch_semaphore_t_type = PointerType::get(dispatch_semaphore_s_type, 0);
3695  return dispatch_semaphore_t_type;
3696 }
3697 
3699 {
3700  StructType *dispatch_group_s_type = module->getTypeByName("struct.dispatch_group_s");
3701  if (! dispatch_group_s_type)
3702  dispatch_group_s_type = StructType::create(module->getContext(), "struct.dispatch_group_s");
3703 
3704  PointerType *dispatch_group_t_type = PointerType::get(dispatch_group_s_type, 0);
3705  return dispatch_group_t_type;
3706 }
3707 
3708 PointerType * VuoCompilerCodeGenUtilities::getDispatchQueueType(Module *module)
3709 {
3710  StructType *dispatch_queue_s_type = module->getTypeByName("struct.dispatch_queue_s");
3711  if (! dispatch_queue_s_type)
3712  dispatch_queue_s_type = StructType::create(module->getContext(), "struct.dispatch_queue_s");
3713 
3714  PointerType *dispatch_queue_t_type = PointerType::get(dispatch_queue_s_type, 0);
3715  return dispatch_queue_t_type;
3716 }
3717 
3718 StructType * VuoCompilerCodeGenUtilities::getDispatchObjectElementType(Module *module)
3719 {
3720  StructType *dispatch_object_s_type = module->getTypeByName("struct.dispatch_object_s");
3721  if (! dispatch_object_s_type)
3722  dispatch_object_s_type = StructType::create(module->getContext(), "struct.dispatch_object_s");
3723  vector<Type *> dispatch_object_s_fields;
3724  if (dispatch_object_s_type->isOpaque())
3725  dispatch_object_s_type->setBody(dispatch_object_s_fields, false);
3726  return dispatch_object_s_type;
3727 }
3728 
3730 {
3731  StructType *dispatch_object_s_type = getDispatchObjectElementType(module);
3732  PointerType *pointerTo_dispatch_object_s_type = PointerType::get(dispatch_object_s_type, 0);
3733 
3734  StructType *dispatch_object_t_type = module->getTypeByName("union.dispatch_object_t");
3735  if (! dispatch_object_t_type)
3736  dispatch_object_t_type = StructType::create(module->getContext(), "union.dispatch_object_t");
3737  vector<Type *> dispatch_object_t_fields;
3738  dispatch_object_t_fields.push_back(pointerTo_dispatch_object_s_type);
3739  if (dispatch_object_t_type->isOpaque())
3740  dispatch_object_t_type->setBody(dispatch_object_t_fields, false);
3741  return dispatch_object_t_type;
3742 }
3743 
3745 {
3746  StructType *nodeContextType = module->getTypeByName("struct.NodeContext");
3747  if (! nodeContextType)
3748  nodeContextType = StructType::create(module->getContext(), "struct.NodeContext");
3749 
3750  if (nodeContextType->isOpaque())
3751  {
3752  PointerType *pointerToPointerToPortContextType = PointerType::get(PointerType::get(getPortContextType(module), 0), 0);
3753  PointerType *voidPointerType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3754  Type *longType = IntegerType::get(module->getContext(), 64);
3755 
3756  vector<Type *> fields;
3757  fields.push_back(pointerToPointerToPortContextType);
3758  fields.push_back(longType);
3759  fields.push_back(voidPointerType);
3760  fields.push_back(getDispatchSemaphoreType(module));
3761  fields.push_back(longType);
3762  fields.push_back(getDispatchGroupType(module));
3763  fields.push_back(longType);
3764  nodeContextType->setBody(fields, false);
3765  }
3766 
3767  return nodeContextType;
3768 }
3769 
3771 {
3772  StructType *portContextType = module->getTypeByName("struct.PortContext");
3773  if (! portContextType)
3774  portContextType = StructType::create(module->getContext(), "struct.PortContext");
3775 
3776  if (portContextType->isOpaque())
3777  {
3778  Type *boolType = IntegerType::get(module->getContext(), 64);
3779  PointerType *voidPointerType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3780 
3781  vector<Type *> fields;
3782  fields.push_back(boolType);
3783  fields.push_back(voidPointerType);
3784  fields.push_back(boolType);
3785  fields.push_back(getDispatchQueueType(module));
3786  fields.push_back(getDispatchSemaphoreType(module));
3787  fields.push_back(voidPointerType);
3788  portContextType->setBody(fields, false);
3789  }
3790 
3791  return portContextType;
3792 }
3793 
3795 {
3796  StructType *compositionStateType = module->getTypeByName("struct.VuoCompositionState");
3797  if (! compositionStateType)
3798  compositionStateType = StructType::create(module->getContext(), "struct.VuoCompositionState");
3799 
3800  if (compositionStateType->isOpaque())
3801  {
3802  PointerType *voidPointerType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3803  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3804 
3805  vector<Type *> fields;
3806  fields.push_back(voidPointerType);
3807  fields.push_back(pointerToCharType);
3808  compositionStateType->setBody(fields, false);
3809  }
3810 
3811  return compositionStateType;
3812 }
3813 
3814 StructType * VuoCompilerCodeGenUtilities::getGraphvizGraphType(Module *module)
3815 {
3816  StructType *graphType = module->getTypeByName("struct.Agraph_t");
3817  if (! graphType)
3818  graphType = StructType::create(module->getContext(), "struct.Agraph_t");
3819 
3820  return graphType;
3821 }
3822 
3824 {
3825  StructType *jsonObjectType = module->getTypeByName("struct.json_object");
3826  if (! jsonObjectType)
3827  jsonObjectType = StructType::create(module->getContext(), "struct.json_object");
3828 
3829  return jsonObjectType;
3830 }
3831 
3832 PointerType * VuoCompilerCodeGenUtilities::getPointerToFileType(Module *module)
3833 {
3834  StructType *fileType = module->getTypeByName("struct.__sFILE");
3835  if (! fileType)
3836  fileType = StructType::create(module->getContext(), "struct.__sFILE");
3837 
3838  return PointerType::get(fileType, 0);
3839 }
3840 
3841 PointerType * VuoCompilerCodeGenUtilities::getVuoShaderType(Module *module)
3842 {
3843  StructType *shaderStructType = module->getTypeByName("struct._VuoShader");
3844  if (! shaderStructType)
3845  shaderStructType = StructType::create(module->getContext(), "struct._VuoShader");
3846 
3847  return PointerType::get(shaderStructType, 0);
3848 }
3849 
3850 PointerType * VuoCompilerCodeGenUtilities::getVuoImageType(Module *module)
3851 {
3852  StructType *imageStructType = module->getTypeByName("struct._VuoImage");
3853  if (! imageStructType)
3854  imageStructType = StructType::create(module->getContext(), "struct._VuoImage");
3855 
3856  return PointerType::get(imageStructType, 0);
3857 }
3858 
3859 Type * VuoCompilerCodeGenUtilities::getVuoImageColorDepthType(Module *module)
3860 {
3861  return IntegerType::get(module->getContext(), 32);
3862 }
3863 
3865 {
3866  return PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3867 }
3869 
3870 
3872 
3876 {
3877  const char *functionName = "strcat";
3878  Function *function = module->getFunction(functionName);
3879  if (! function)
3880  {
3881  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3882 
3883  vector<Type *> functionParams;
3884  functionParams.push_back(pointerToCharType);
3885  functionParams.push_back(pointerToCharType);
3886  FunctionType *functionType = FunctionType::get(pointerToCharType, functionParams, false);
3887  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3888  }
3889  return function;
3890 }
3891 
3893 {
3894  const char *functionName = "strcmp";
3895  Function *function = module->getFunction(functionName);
3896  if (! function)
3897  {
3898  PointerType *pointerToi8Type = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3899  vector<Type *> functionParams;
3900  functionParams.push_back(pointerToi8Type);
3901  functionParams.push_back(pointerToi8Type);
3902  FunctionType *functionType = FunctionType::get(IntegerType::get(module->getContext(), 32), functionParams, false);
3903  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3904  }
3905  return function;
3906 }
3907 
3909 {
3910  const char *functionName = "strdup";
3911  Function *function = module->getFunction(functionName);
3912  if (! function)
3913  {
3914  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3915 
3916  vector<Type *> functionParams;
3917  functionParams.push_back(pointerToCharType);
3918  FunctionType *functionType = FunctionType::get(pointerToCharType, functionParams, false);
3919  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3920  }
3921  return function;
3922 }
3923 
3925 {
3926  const char *functionName = "strlen";
3927  Function *function = module->getFunction(functionName);
3928  if (! function)
3929  {
3930  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3931 
3932  vector<Type *> functionParams;
3933  functionParams.push_back(pointerToCharType);
3934  FunctionType *functionType = FunctionType::get(IntegerType::get(module->getContext(), 64), functionParams, false);
3935  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3936  }
3937  return function;
3938 }
3939 
3941 {
3942  const char *functionName = "snprintf";
3943  Function *function = module->getFunction(functionName);
3944  if (! function)
3945  {
3946  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3947 
3948  vector<Type *> functionParams;
3949  functionParams.push_back(pointerToCharType);
3950  functionParams.push_back(IntegerType::get(module->getContext(), 64));
3951  functionParams.push_back(pointerToCharType);
3952  FunctionType *functionType = FunctionType::get(IntegerType::get(module->getContext(), 32), functionParams, true);
3953  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3954  }
3955  return function;
3956 }
3957 
3959 {
3960  const char *functionName = "sscanf";
3961  Function *function = module->getFunction(functionName);
3962  if (! function)
3963  {
3964  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3965 
3966  vector<Type *> functionParams;
3967  functionParams.push_back(pointerToCharType);
3968  functionParams.push_back(pointerToCharType);
3969  FunctionType *functionType = FunctionType::get(IntegerType::get(module->getContext(), 32), functionParams, true);
3970  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3971  }
3972  return function;
3973 }
3974 
3976 {
3977  const char *functionName = "fprintf";
3978  Function *function = module->getFunction(functionName);
3979  if (! function)
3980  {
3981  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3982 
3983  vector<Type *> functionParams;
3984  functionParams.push_back( getPointerToFileType(module) );
3985  functionParams.push_back(pointerToCharType);
3986  FunctionType *functionType = FunctionType::get(IntegerType::get(module->getContext(), 32), functionParams, true);
3987  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
3988  }
3989  return function;
3990 }
3991 
3993 {
3994  const char *functionName = "puts";
3995  Function *function = module->getFunction(functionName);
3996  if (! function)
3997  {
3998  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3999 
4000  vector<Type *> functionParams;
4001  functionParams.push_back(pointerToCharType);
4002  FunctionType *functionType = FunctionType::get(IntegerType::get(module->getContext(), 32), functionParams, false);
4003  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4004  }
4005  return function;
4006 }
4007 
4009 {
4010  const char *functionName = "malloc";
4011  Function *function = module->getFunction(functionName);
4012  if (! function)
4013  {
4014  PointerType *pointerToi8Type = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4015 
4016  vector<Type *> functionParams;
4017  functionParams.push_back(IntegerType::get(module->getContext(), sizeof(size_t)*CHAR_BIT));
4018  FunctionType *functionType = FunctionType::get(pointerToi8Type, functionParams, false);
4019  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4020  }
4021  return function;
4022 }
4023 
4025 {
4026  const char *functionName = "memcpy";
4027  Function *function = module->getFunction(functionName);
4028  if (! function)
4029  {
4030  PointerType *pointerToi8Type = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4031 
4032  vector<Type *> functionParams;
4033  functionParams.push_back(pointerToi8Type);
4034  functionParams.push_back(pointerToi8Type);
4035  functionParams.push_back(IntegerType::get(module->getContext(), sizeof(size_t)*CHAR_BIT));
4036  FunctionType *functionType = FunctionType::get(pointerToi8Type, functionParams, false);
4037  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4038  }
4039  return function;
4040 }
4041 
4043 {
4044  const char *functionName = "free";
4045  Function *function = module->getFunction(functionName);
4046  if (! function)
4047  {
4048  PointerType *pointerToi8Type = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4049 
4050  vector<Type *> functionParams;
4051  functionParams.push_back(pointerToi8Type);
4052  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
4053  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4054  }
4055  return function;
4056 }
4057 
4059 {
4060  const char *functionName = "llvm.var.annotation";
4061  Function *function = module->getFunction(functionName);
4062  if (! function)
4063  {
4064  PointerType *pointerToi8Type = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4065 
4066  vector<Type *> functionParams;
4067  functionParams.push_back(pointerToi8Type);
4068  functionParams.push_back(pointerToi8Type);
4069  functionParams.push_back(pointerToi8Type);
4070  functionParams.push_back(IntegerType::get(module->getContext(), 32));
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 = "json_object_put";
4080  Function *function = module->getFunction(functionName);
4081  if (! function)
4082  {
4083  PointerType *pointerToJsonObjectType = PointerType::get(getJsonObjectType(module), 0);
4084 
4085  vector<Type *> functionParams;
4086  functionParams.push_back(pointerToJsonObjectType);
4087  FunctionType *functionType = FunctionType::get(IntegerType::get(module->getContext(), 32), functionParams, false);
4088  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4089  }
4090  return function;
4091 }
4092 
4094 {
4095  const char *functionName = "json_object_to_json_string_ext";
4096  Function *function = module->getFunction(functionName);
4097  if (! function)
4098  {
4099  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4100  PointerType *pointerToJsonObjectType = PointerType::get(getJsonObjectType(module), 0);
4101 
4102  vector<Type *> functionParams;
4103  functionParams.push_back(pointerToJsonObjectType);
4104  functionParams.push_back(IntegerType::get(module->getContext(), 32));
4105  FunctionType *functionType = FunctionType::get(pointerToCharType, functionParams, false);
4106  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4107  }
4108  return function;
4109 }
4110 
4112 {
4113  const char *functionName = "json_tokener_parse";
4114  Function *function = module->getFunction(functionName);
4115  if (! function)
4116  {
4117  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4118  PointerType *pointerToJsonObjectType = PointerType::get(getJsonObjectType(module), 0);
4119 
4120  vector<Type *> functionParams;
4121  functionParams.push_back(pointerToCharType);
4122  FunctionType *functionType = FunctionType::get(pointerToJsonObjectType, functionParams, false);
4123  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4124  }
4125  return function;
4126 }
4127 
4129 {
4130  const char *functionName = "VuoShader_make";
4131  Function *function = module->getFunction(functionName);
4132  if (! function)
4133  {
4134  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4135  Type *shaderType = getVuoShaderType(module);
4136 
4137  vector<Type *> functionParams;
4138  functionParams.push_back(pointerToCharType);
4139  FunctionType *functionType = FunctionType::get(shaderType, functionParams, false);
4140  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4141  }
4142  return function;
4143 }
4144 
4146 {
4147  const char *functionName = "VuoShader_addSource";
4148  Function *function = module->getFunction(functionName);
4149  if (! function)
4150  {
4151  Type *shaderType = getVuoShaderType(module);
4152  Type *elementAsseblyMethodType = IntegerType::get(module->getContext(), 64);
4153  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4154 
4155  vector<Type *> functionParams;
4156  functionParams.push_back(shaderType);
4157  functionParams.push_back(elementAsseblyMethodType);
4158  functionParams.push_back(pointerToCharType);
4159  functionParams.push_back(pointerToCharType);
4160  functionParams.push_back(pointerToCharType);
4161  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
4162  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4163  }
4164  return function;
4165 }
4166 
4168 {
4169  const char *functionName = "VuoShader_setTransparent";
4170  Function *function = module->getFunction(functionName);
4171  if (! function)
4172  {
4173  Type *shaderType = getVuoShaderType(module);
4174  Type *boolType = IntegerType::get(module->getContext(), 1);
4175 
4176  vector<Type *> functionParams;
4177  functionParams.push_back(shaderType);
4178  functionParams.push_back(boolType);
4179  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
4180  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4181  }
4182  return function;
4183 }
4184 
4186 {
4187  string functionName = "VuoShader_setUniform_" + type->getBase()->getModuleKey();
4188  Function *function = module->getFunction(functionName);
4189  if (! function)
4190  {
4191  Type *shaderType = getVuoShaderType(module);
4192  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4193 
4194  vector<Type *> dataParams = type->getFunctionParameterTypes();
4195 
4196  vector<Type *> functionParams;
4197  functionParams.push_back(shaderType);
4198  functionParams.push_back(pointerToCharType);
4199  functionParams.insert(functionParams.end(), dataParams.begin(), dataParams.end());
4200  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
4201  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4202  }
4203  return function;
4204 }
4205 
4207 {
4208  string functionName = "VuoShader_samplerRectCoordinatesFromNormalizedCoordinates";
4209  Function *function = module->getFunction(functionName);
4210  if (! function)
4211  {
4212  Type *loweredPoint2dType = Type::getDoubleTy(module->getContext());
4213  Type *intType = IntegerType::get(module->getContext(), 64);
4214 
4215  vector<Type *> functionParams;
4216  functionParams.push_back(loweredPoint2dType);
4217  functionParams.push_back(intType);
4218  functionParams.push_back(intType);
4219  FunctionType *functionType = FunctionType::get(loweredPoint2dType, functionParams, false);
4220  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4221  }
4222  return function;
4223 }
4224 
4226 {
4227  const char *functionName = "VuoImage_getColorDepth";
4228  Function *function = module->getFunction(functionName);
4229  if (! function)
4230  {
4231  Type *imageType = getVuoImageType(module);
4232  Type *imageColorDepthType = getVuoImageColorDepthType(module);
4233 
4234  vector<Type *> functionParams;
4235  functionParams.push_back(imageType);
4236  FunctionType *functionType = FunctionType::get(imageColorDepthType, functionParams, false);
4237  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4238  }
4239  return function;
4240 }
4241 
4243 {
4244  const char *functionName = "VuoImageRenderer_render";
4245  Function *function = module->getFunction(functionName);
4246  if (! function)
4247  {
4248  Type *shaderType = getVuoShaderType(module);
4249  Type *intType = IntegerType::get(module->getContext(), 64);
4250  Type *imageColorDepthType = getVuoImageColorDepthType(module);
4251  Type *imageType = getVuoImageType(module);
4252 
4253  vector<Type *> functionParams;
4254  functionParams.push_back(shaderType);
4255  functionParams.push_back(intType);
4256  functionParams.push_back(intType);
4257  functionParams.push_back(imageColorDepthType);
4258  FunctionType *functionType = FunctionType::get(imageType, functionParams, false);
4259  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4260  }
4261  return function;
4262 }
4263 
4265 {
4266  string functionName = "compositionAddNodeMetadata";
4267  string moduleKey = module->getModuleIdentifier();
4268  if (! moduleKey.empty())
4269  functionName = VuoStringUtilities::prefixSymbolName(functionName, moduleKey);
4270  Function *function = module->getFunction(functionName.c_str());
4271  if (! function)
4272  {
4273  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
4274 
4275  vector<Type *> functionParams;
4276  functionParams.push_back(pointerToCompositionState);
4277  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
4278  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4279  }
4280  return function;
4281 }
4282 
4284 {
4285  string functionName = "compositionCreateContextForNode";
4286  string moduleKey = module->getModuleIdentifier();
4287  if (! moduleKey.empty())
4288  functionName = VuoStringUtilities::prefixSymbolName(functionName, moduleKey);
4289  Function *function = module->getFunction(functionName.c_str());
4290  if (! function)
4291  {
4292  IntegerType *unsignedLongType = IntegerType::get(module->getContext(), 64);
4293  PointerType *pointerToNodeContextType = PointerType::get(getNodeContextType(module), 0);
4294 
4295  vector<Type *> functionParams;
4296  functionParams.push_back(unsignedLongType);
4297  FunctionType *functionType = FunctionType::get(pointerToNodeContextType, functionParams, false);
4298  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4299  }
4300  return function;
4301 }
4302 
4304 {
4305  string functionName = "compositionPerformDataOnlyTransmissions";
4306  string moduleKey = module->getModuleIdentifier();
4307  if (! moduleKey.empty())
4308  functionName = VuoStringUtilities::prefixSymbolName(functionName, moduleKey);
4309  Function *function = module->getFunction(functionName.c_str());
4310  if (! function)
4311  {
4312  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
4313 
4314  vector<Type *> functionParams;
4315  functionParams.push_back(pointerToCompositionState);
4316  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
4317  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4318  }
4319  return function;
4320 }
4321 
4323 {
4324  string functionName = "compositionReleasePortData";
4325  string moduleKey = module->getModuleIdentifier();
4326  if (! moduleKey.empty())
4327  functionName = VuoStringUtilities::prefixSymbolName(functionName, moduleKey);
4328  Function *function = module->getFunction(functionName.c_str());
4329  if (! function)
4330  {
4331  PointerType *voidPointer = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4332  IntegerType *unsignedLongType = IntegerType::get(module->getContext(), 64);
4333 
4334  vector<Type *> functionParams;
4335  functionParams.push_back(voidPointer);
4336  functionParams.push_back(unsignedLongType);
4337  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
4338  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4339  }
4340  return function;
4341 }
4342 
4344 {
4345  const char *functionName = "vuoSetup";
4346  Function *function = module->getFunction(functionName);
4347  if (! function)
4348  {
4349  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), false);
4350  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4351  }
4352  return function;
4353 }
4354 
4356 {
4357  const char *functionName = "vuoCleanup";
4358  Function *function = module->getFunction(functionName);
4359  if (! function)
4360  {
4361  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), false);
4362  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4363  }
4364  return function;
4365 }
4366 
4368 {
4369  const char *functionName = "vuoInstanceInit";
4370  Function *function = module->getFunction(functionName);
4371  if (! function)
4372  {
4373  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), false);
4374  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4375  }
4376  return function;
4377 }
4378 
4380 {
4381  const char *functionName = "vuoInstanceFini";
4382  Function *function = module->getFunction(functionName);
4383  if (! function)
4384  {
4385  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), false);
4386  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4387  }
4388  return function;
4389 }
4390 
4392 {
4393  const char *functionName = "vuoInstanceTriggerStart";
4394  Function *function = module->getFunction(functionName);
4395  if (! function)
4396  {
4397  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), PointerType::get(getCompositionInstanceDataType(module), 0), false);
4398  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4399  }
4400  return function;
4401 }
4402 
4404 {
4405  const char *functionName = "vuoInstanceTriggerStop";
4406  Function *function = module->getFunction(functionName);
4407  if (! function)
4408  {
4409  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), PointerType::get(getCompositionInstanceDataType(module), 0), false);
4410  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4411  }
4412  return function;
4413 }
4414 
4415 Function * VuoCompilerCodeGenUtilities::getNodeInstanceInitFunction(Module *module, string moduleKey, bool isSubcomposition,
4416  Type *instanceDataType,
4417  const vector<VuoPort *> &modelInputPorts,
4418  map<VuoPort *, size_t> &indexOfParameter,
4419  VuoCompilerConstantsCache *constantsCache)
4420 {
4421  map<VuoPort *, size_t> indexOfEventParameter;
4422  return getNodeFunction(module, moduleKey, "nodeInstanceInit", isSubcomposition, false, true, false, instanceDataType, modelInputPorts, vector<VuoPort *>(),
4423  map<VuoPort *, json_object *>(), map<VuoPort *, string>(), map<VuoPort *, string>(), map<VuoPort *, VuoPortClass::EventBlocking>(),
4424  indexOfParameter, indexOfEventParameter, constantsCache);
4425 }
4426 
4427 Function * VuoCompilerCodeGenUtilities::getNodeInstanceFiniFunction(Module *module, string moduleKey,
4428  Type *instanceDataType,
4429  VuoCompilerConstantsCache *constantsCache)
4430 {
4431  map<VuoPort *, size_t> indexOfParameter;
4432  map<VuoPort *, size_t> indexOfEventParameter;
4433  return getNodeFunction(module, moduleKey, "nodeInstanceFini", true, true, false, false, instanceDataType, vector<VuoPort *>(), vector<VuoPort *>(),
4434  map<VuoPort *, json_object *>(), map<VuoPort *, string>(), map<VuoPort *, string>(), map<VuoPort *, VuoPortClass::EventBlocking>(),
4435  indexOfParameter, indexOfEventParameter, constantsCache);
4436 }
4437 
4438 Function * VuoCompilerCodeGenUtilities::getNodeInstanceTriggerStartFunction(Module *module, string moduleKey,
4439  Type *instanceDataType,
4440  const vector<VuoPort *> &modelInputPorts,
4441  map<VuoPort *, size_t> &indexOfParameter,
4442  VuoCompilerConstantsCache *constantsCache)
4443 {
4444  map<VuoPort *, size_t> indexOfEventParameter;
4445  return getNodeFunction(module, moduleKey, "nodeInstanceTriggerStart", true, true, false, false, instanceDataType, modelInputPorts, vector<VuoPort *>(),
4446  map<VuoPort *, json_object *>(), map<VuoPort *, string>(), map<VuoPort *, string>(), map<VuoPort *, VuoPortClass::EventBlocking>(),
4447  indexOfParameter, indexOfEventParameter, constantsCache);
4448 }
4449 
4450 Function * VuoCompilerCodeGenUtilities::getNodeInstanceTriggerStopFunction(Module *module, string moduleKey,
4451  Type *instanceDataType,
4452  VuoCompilerConstantsCache *constantsCache)
4453 {
4454  map<VuoPort *, size_t> indexOfParameter;
4455  map<VuoPort *, size_t> indexOfEventParameter;
4456  return getNodeFunction(module, moduleKey, "nodeInstanceTriggerStop", true, true, false, false, instanceDataType, vector<VuoPort *>(), vector<VuoPort *>(),
4457  map<VuoPort *, json_object *>(), map<VuoPort *, string>(), map<VuoPort *, string>(), map<VuoPort *, VuoPortClass::EventBlocking>(),
4458  indexOfParameter, indexOfEventParameter, constantsCache);
4459 }
4460 
4461 Function * VuoCompilerCodeGenUtilities::getNodeInstanceTriggerUpdateFunction(Module *module, string moduleKey,
4462  Type *instanceDataType,
4463  const vector<VuoPort *> &modelInputPorts,
4464  map<VuoPort *, size_t> &indexOfParameter,
4465  VuoCompilerConstantsCache *constantsCache)
4466 {
4467  map<VuoPort *, size_t> indexOfEventParameter;
4468  return getNodeFunction(module, moduleKey, "nodeInstanceTriggerUpdate", true, true, false, false, instanceDataType, modelInputPorts, vector<VuoPort *>(),
4469  map<VuoPort *, json_object *>(), map<VuoPort *, string>(), map<VuoPort *, string>(), map<VuoPort *, VuoPortClass::EventBlocking>(),
4470  indexOfParameter, indexOfEventParameter, constantsCache);
4471 }
4472 
4473 Function * VuoCompilerCodeGenUtilities::getNodeEventFunction(Module *module, string moduleKey, bool isSubcomposition, bool isStateful,
4474  Type *instanceDataType,
4475  const vector<VuoPort *> &modelInputPorts,
4476  const vector<VuoPort *> &modelOutputPorts,
4477  const map<VuoPort *, json_object *> &detailsForPorts,
4478  const map<VuoPort *, string> &displayNamesForPorts,
4479  const map<VuoPort *, string> &defaultValuesForInputPorts,
4480  const map<VuoPort *, VuoPortClass::EventBlocking> &eventBlockingForInputPorts,
4481  map<VuoPort *, size_t> &indexOfParameter,
4482  map<VuoPort *, size_t> &indexOfEventParameter,
4483  VuoCompilerConstantsCache *constantsCache)
4484 {
4485  string functionName = (isStateful ? "nodeInstanceEvent" : "nodeEvent");
4486  return getNodeFunction(module, moduleKey, functionName, isSubcomposition, isStateful, false, true, instanceDataType, modelInputPorts, modelOutputPorts,
4487  detailsForPorts, displayNamesForPorts, defaultValuesForInputPorts, eventBlockingForInputPorts,
4488  indexOfParameter, indexOfEventParameter, constantsCache);
4489 }
4490 
4491 Function * VuoCompilerCodeGenUtilities::getNodeFunction(Module *module, string moduleKey, string functionName,
4492  bool hasCompositionStateArg, bool hasInstanceDataArg,
4493  bool hasInstanceDataReturn, bool hasEventArgs,
4494  Type *instanceDataType,
4495  const vector<VuoPort *> &modelInputPorts, const vector<VuoPort *> &modelOutputPorts,
4496  const map<VuoPort *, json_object *> &detailsForPorts,
4497  const map<VuoPort *, string> &displayNamesForPorts,
4498  const map<VuoPort *, string> &defaultValuesForInputPorts,
4499  const map<VuoPort *, VuoPortClass::EventBlocking> &eventBlockingForInputPorts,
4500  map<VuoPort *, size_t> &indexOfParameter,
4501  map<VuoPort *, size_t> &indexOfEventParameter,
4502  VuoCompilerConstantsCache *constantsCache)
4503 {
4504  if (! moduleKey.empty())
4505  functionName = VuoStringUtilities::prefixSymbolName(functionName, moduleKey);
4506  Function *function = module->getFunction(functionName.c_str());
4507 
4508  if (! function)
4509  {
4510  vector<Type *> functionParams;
4511  AttributeList functionAttributes;
4512  map<VuoPort *, bool> hasSecondParam;
4513  Type *boolType = IntegerType::get(module->getContext(), 1);
4514  size_t indexInEventFunction = 0;
4515 
4516  if (hasCompositionStateArg)
4517  {
4518  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
4519  functionParams.push_back(pointerToCompositionState);
4520  indexInEventFunction++;
4521  }
4522 
4523  if (hasInstanceDataArg)
4524  {
4525  functionParams.push_back( PointerType::get(instanceDataType, 0) );
4526  indexInEventFunction++;
4527  }
4528 
4529  for (vector<VuoPort *>::const_iterator i = modelInputPorts.begin(); i != modelInputPorts.end(); ++i)
4530  {
4531  VuoCompilerPort *modelInputPort = static_cast<VuoCompilerPort *>( (*i)->getCompiler() );
4532  VuoType *type = modelInputPort->getDataVuoType();
4533 
4534  if (type)
4535  {
4536  vector<Type *> paramTypes = type->getCompiler()->getFunctionParameterTypes();
4537  AttributeList typeFunctionAttributes = type->getCompiler()->getFunctionAttributes();
4538 
4539  functionParams.insert(functionParams.end(), paramTypes.begin(), paramTypes.end());
4540 
4541  for (size_t j = 0; j < paramTypes.size(); ++j)
4542  functionAttributes = functionAttributes.addParamAttributes(module->getContext(), functionParams.size() - 1, typeFunctionAttributes.getParamAttributes(j));
4543 
4544  indexOfParameter[modelInputPort->getBase()] = indexInEventFunction;
4545  indexInEventFunction += paramTypes.size();
4546 
4547  hasSecondParam[*i] = paramTypes.size() > 1;
4548 
4549  if (hasEventArgs)
4550  {
4551  functionParams.push_back(boolType);
4552 
4553  indexOfEventParameter[modelInputPort->getBase()] = indexInEventFunction++;
4554  }
4555  }
4556  else if (hasEventArgs)
4557  {
4558  functionParams.push_back(boolType);
4559 
4560  indexOfParameter[modelInputPort->getBase()] = indexInEventFunction++;
4561  }
4562  }
4563 
4564  for (vector<VuoPort *>::const_iterator i = modelOutputPorts.begin(); i != modelOutputPorts.end(); ++i)
4565  {
4566  VuoCompilerPort *modelOutputPort = static_cast<VuoCompilerPort *>( (*i)->getCompiler() );
4567  VuoType *type = modelOutputPort->getDataVuoType();
4568 
4569  if (modelOutputPort->getBase()->getClass()->getPortType() == VuoPortClass::triggerPort)
4570  {
4571  FunctionType *functionType = static_cast<VuoCompilerTriggerPortClass *>( modelOutputPort->getBase()->getClass()->getCompiler() )->getFunctionType(module);
4572  PointerType *triggerFunctionPointerType = PointerType::get(functionType, 0);
4573  functionParams.push_back(triggerFunctionPointerType);
4574 
4575  indexOfParameter[modelOutputPort->getBase()] = indexInEventFunction++;
4576  }
4577  else
4578  {
4579  if (type)
4580  {
4581  PointerType *paramType = type->getCompiler()->getFunctionParameterPointerType();
4582  functionParams.push_back(paramType);
4583 
4584  indexOfParameter[modelOutputPort->getBase()] = indexInEventFunction++;
4585 
4586  if (hasEventArgs)
4587  {
4588  PointerType *eventParamType = PointerType::get( boolType, 0 );
4589  functionParams.push_back(eventParamType);
4590 
4591  indexOfEventParameter[modelOutputPort->getBase()] = indexInEventFunction++;
4592  }
4593  }
4594  else if (hasEventArgs)
4595  {
4596  PointerType *paramType = PointerType::get( boolType, 0 );
4597  functionParams.push_back(paramType);
4598 
4599  indexOfParameter[modelOutputPort->getBase()] = indexInEventFunction++;
4600  }
4601  }
4602  }
4603 
4604  Type *returnType = (hasInstanceDataReturn ? instanceDataType : Type::getVoidTy(module->getContext()));
4605  FunctionType *functionType = FunctionType::get(returnType, functionParams, false);
4606  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4607  function->setAttributes(functionAttributes);
4608 
4609  set<string> argNamesUsed;
4610 
4611  BasicBlock *block = BasicBlock::Create(module->getContext(), "", function, 0);
4612  Function::arg_iterator argIter = function->arg_begin();
4613 
4614  if (hasCompositionStateArg)
4615  {
4616  Value *arg = argIter++;
4617  string argName = "compositionState";
4618  arg->setName(argName);
4619  argNamesUsed.insert(argName);
4620  }
4621 
4622  if (hasInstanceDataArg)
4623  {
4624  Value *arg = argIter++;
4625  string argName = "instanceData";
4626  arg->setName(argName);
4627  argNamesUsed.insert(argName);
4628  generateAnnotation(module, block, arg, "vuoInstanceData", "", 0, constantsCache);
4629  }
4630 
4631  argNamesUsed.insert("refresh");
4632 
4633  map<VuoPort *, string> primaryArgNames;
4634  auto recordUniqueArgName = [&primaryArgNames, &argNamesUsed] (VuoPort *modelPort)
4635  {
4636  string argName = VuoStringUtilities::formUniqueIdentifier(argNamesUsed, modelPort->getClass()->getName());
4637  primaryArgNames[modelPort] = argName;
4638  };
4639  std::for_each(modelInputPorts.begin(), modelInputPorts.end(), recordUniqueArgName);
4640  std::for_each(modelOutputPorts.begin(), modelOutputPorts.end(), recordUniqueArgName);
4641 
4642  for (vector<VuoPort *>::const_iterator i = modelInputPorts.begin(); i != modelInputPorts.end(); ++i)
4643  {
4644  VuoPort *modelInputPort = *i;
4645  VuoType *type = static_cast<VuoCompilerPort *>( modelInputPort->getCompiler() )->getDataVuoType();
4646 
4647  if (type || hasEventArgs)
4648  {
4649  Value *arg = argIter++;
4650 
4651  string portName = modelInputPort->getClass()->getName();
4652  string argName = primaryArgNames[modelInputPort];
4653  arg->setName(argName);
4654 
4655  map<VuoPort *, VuoPortClass::EventBlocking>::const_iterator eventBlockingIter = eventBlockingForInputPorts.find(modelInputPort);
4656  bool hasNonDefaultEventBlocking = (eventBlockingIter != eventBlockingForInputPorts.end() && eventBlockingIter->second != VuoPortClass::EventBlocking_None);
4657  string eventBlockingStr = (eventBlockingIter->second == VuoPortClass::EventBlocking_Door ? "door" : "wall");
4658 
4659  json_object *details = json_object_new_object();
4660  map<VuoPort *, json_object *>::const_iterator detailsIter = detailsForPorts.find(modelInputPort);
4661  if (detailsIter != detailsForPorts.end())
4662  {
4663  json_object_object_foreach(detailsIter->second, key, val)
4664  {
4665  json_object_object_add(details, key, val);
4666  json_object_get(val);
4667  }
4668  }
4669  map<VuoPort *, string>::const_iterator displayNameIter = displayNamesForPorts.find(modelInputPort);
4670  if (displayNameIter != displayNamesForPorts.end())
4671  json_object_object_add(details, "name", json_object_new_string(displayNameIter->second.c_str()));
4672 
4673  if (type)
4674  {
4675  generateAnnotation(module, block, arg, "vuoInputData", "", 0, constantsCache);
4676  generateAnnotation(module, block, arg, "vuoType:" + type->getModuleKey(), "", 0, constantsCache);
4677 
4678  map<VuoPort *, string>::const_iterator defaultValueIter = defaultValuesForInputPorts.find(modelInputPort);
4679  if (defaultValueIter != defaultValuesForInputPorts.end())
4680  json_object_object_add(details, "default", json_tokener_parse(defaultValueIter->second.c_str()));
4681 
4682  if (hasSecondParam[modelInputPort])
4683  {
4684  Value *secondArg = argIter++;
4685  secondArg->setName(argName + ".1");
4686  }
4687 
4688  if (hasEventArgs)
4689  {
4690  Value *eventArg = argIter++;
4691 
4692  string preferredEventArgName = portName + "Event";
4693  string eventArgName = VuoStringUtilities::formUniqueIdentifier(argNamesUsed, preferredEventArgName);
4694  eventArg->setName(eventArgName);
4695 
4696  generateAnnotation(module, block, eventArg, "vuoInputEvent", "", 0, constantsCache);
4697 
4698  json_object *eventDetails = json_object_new_object();
4699  json_object_object_add(eventDetails, "data", json_object_new_string(argName.c_str()));
4700  if (hasNonDefaultEventBlocking)
4701  json_object_object_add(eventDetails, "eventBlocking", json_object_new_string(eventBlockingStr.c_str()));
4702  string eventDetailsStr = json_object_to_json_string_ext(eventDetails, JSON_C_TO_STRING_PLAIN);
4703  json_object_put(eventDetails);
4704  generateAnnotation(module, block, eventArg, "vuoDetails:" + eventDetailsStr, "", 0, constantsCache);
4705  }
4706  }
4707  else if (hasEventArgs)
4708  {
4709  generateAnnotation(module, block, arg, "vuoInputEvent", "", 0, constantsCache);
4710 
4711  if (hasNonDefaultEventBlocking)
4712  json_object_object_add(details, "eventBlocking", json_object_new_string(eventBlockingStr.c_str()));
4713  }
4714 
4715  string detailsStr = json_object_to_json_string_ext(details, JSON_C_TO_STRING_PLAIN);
4716  json_object_put(details);
4717  generateAnnotation(module, block, arg, "vuoDetails:" + detailsStr, "", 0, constantsCache);
4718  }
4719  }
4720 
4721  for (vector<VuoPort *>::const_iterator i = modelOutputPorts.begin(); i != modelOutputPorts.end(); ++i)
4722  {
4723  VuoPort *modelOutputPort = *i;
4724 
4725  Value *arg = argIter++;
4726 
4727  string portName = modelOutputPort->getClass()->getName();
4728  string argName = primaryArgNames[modelOutputPort];
4729  arg->setName(argName);
4730 
4731  json_object *details = json_object_new_object();
4732  map<VuoPort *, json_object *>::const_iterator detailsIter = detailsForPorts.find(modelOutputPort);
4733  if (detailsIter != detailsForPorts.end())
4734  {
4735  json_object_object_foreach(detailsIter->second, key, val)
4736  {
4737  json_object_object_add(details, key, val);
4738  json_object_get(val);
4739  }
4740  }
4741  map<VuoPort *, string>::const_iterator displayNameIter = displayNamesForPorts.find(modelOutputPort);
4742  if (displayNameIter != displayNamesForPorts.end())
4743  json_object_object_add(details, "name", json_object_new_string(displayNameIter->second.c_str()));
4744  string detailsStr = json_object_to_json_string_ext(details, JSON_C_TO_STRING_PLAIN);
4745  json_object_put(details);
4746  generateAnnotation(module, block, arg, "vuoDetails:" + detailsStr, "", 0, constantsCache);
4747 
4748  VuoType *type = static_cast<VuoCompilerPort *>( modelOutputPort->getCompiler() )->getDataVuoType();
4749  if (modelOutputPort->getClass()->getPortType() == VuoPortClass::triggerPort)
4750  {
4751  generateAnnotation(module, block, arg, "vuoOutputTrigger:" + argName, "", 0, constantsCache);
4752  generateAnnotation(module, block, arg, "vuoType:" + (type ? type->getModuleKey() : "void"), "", 0, constantsCache);
4753  }
4754  else
4755  {
4756  if (type)
4757  {
4758  generateAnnotation(module, block, arg, "vuoOutputData", "", 0, constantsCache);
4759  generateAnnotation(module, block, arg, "vuoType:" + type->getModuleKey(), "", 0, constantsCache);
4760 
4761  if (hasEventArgs)
4762  {
4763  Value *eventArg = argIter++;
4764 
4765  string preferredEventArgName = portName + "Event";
4766  string eventArgName = VuoStringUtilities::formUniqueIdentifier(argNamesUsed, preferredEventArgName);
4767  eventArg->setName(eventArgName);
4768 
4769  generateAnnotation(module, block, eventArg, "vuoOutputEvent", "", 0, constantsCache);
4770 
4771  json_object *eventDetails = json_object_new_object();
4772  json_object_object_add(eventDetails, "data", json_object_new_string(argName.c_str()));
4773  string eventDetailsStr = json_object_to_json_string_ext(eventDetails, JSON_C_TO_STRING_PLAIN);
4774  json_object_put(eventDetails);
4775  generateAnnotation(module, block, eventArg, "vuoDetails:" + eventDetailsStr, "", 0, constantsCache);
4776  }
4777  }
4778  else if (hasEventArgs)
4779  {
4780  generateAnnotation(module, block, arg, "vuoOutputEvent", "", 0, constantsCache);
4781  }
4782  }
4783  }
4784  }
4785 
4786  return function;
4787 }
4788 
4789 Function * VuoCompilerCodeGenUtilities::getVuoRegisterFunction(Module *module)
4790 {
4791  const char *functionName = "VuoRegisterF";
4792  Function *function = module->getFunction(functionName);
4793  if (! function)
4794  {
4795  PointerType *voidPointerType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4796  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4797  IntegerType *intType = IntegerType::get(module->getContext(), 32);
4798 
4799  FunctionType *deallocateFunctionType = FunctionType::get(Type::getVoidTy(module->getContext()), voidPointerType, false);
4800  PointerType *deallocateFunctionPointerType = PointerType::get(deallocateFunctionType, 0);
4801 
4802  vector<Type *> functionParams;
4803  functionParams.push_back(voidPointerType);
4804  functionParams.push_back(deallocateFunctionPointerType);
4805  functionParams.push_back(pointerToCharType);
4806  functionParams.push_back(intType);
4807  functionParams.push_back(pointerToCharType);
4808  functionParams.push_back(pointerToCharType);
4809  FunctionType *functionType = FunctionType::get(intType, functionParams, false);
4810  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4811  }
4812  return function;
4813 }
4814 
4815 Function * VuoCompilerCodeGenUtilities::getVuoRetainFunction(Module *module)
4816 {
4817  const char *functionName = "VuoRetain";
4818  Function *function = module->getFunction(functionName);
4819  if (! function)
4820  {
4821  PointerType *voidPointerType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4822  IntegerType *intType = IntegerType::get(module->getContext(), 32);
4823 
4824  vector<Type *> functionParams;
4825  functionParams.push_back(voidPointerType); // pointer
4826  FunctionType *functionType = FunctionType::get(intType, functionParams, false);
4827  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4828  }
4829  return function;
4830 }
4831 
4832 Function * VuoCompilerCodeGenUtilities::getVuoReleaseFunction(Module *module)
4833 {
4834  const char *functionName = "VuoRelease";
4835  Function *function = module->getFunction(functionName);
4836  if (! function)
4837  {
4838  PointerType *voidPointerType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4839  IntegerType *intType = IntegerType::get(module->getContext(), 32);
4840 
4841  vector<Type *> functionParams;
4842  functionParams.push_back(voidPointerType); // pointer
4843  FunctionType *functionType = FunctionType::get(intType, functionParams, false);
4844  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4845  }
4846  return function;
4847 }
4848 
4850 {
4851  string functionName = "compositionGetPortValue";
4852  string moduleKey = module->getModuleIdentifier();
4853  if (! moduleKey.empty())
4854  functionName = VuoStringUtilities::prefixSymbolName(functionName, moduleKey);
4855  Function *function = module->getFunction(functionName.c_str());
4856  if (! function)
4857  {
4858  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
4859  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4860  IntegerType *intType = IntegerType::get(module->getContext(), 32);
4861 
4862  vector<Type *> functionParams;
4863  functionParams.push_back(pointerToCompositionState);
4864  functionParams.push_back(pointerToCharType);
4865  functionParams.push_back(intType);
4866  functionParams.push_back(intType);
4867  FunctionType *functionType = FunctionType::get(pointerToCharType, functionParams, false);
4868  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4869  }
4870  return function;
4871 }
4872 
4874 {
4875  string functionName = "compositionSetPortValue";
4876  string moduleKey = module->getModuleIdentifier();
4877  if (! moduleKey.empty())
4878  functionName = VuoStringUtilities::prefixSymbolName(functionName, moduleKey);
4879  Function *function = module->getFunction(functionName.c_str());
4880  if (! function)
4881  {
4882  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
4883  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4884  Type *boolType = IntegerType::get(module->getContext(), 32);
4885 
4886  vector<Type *> functionParams;
4887  functionParams.push_back(pointerToCompositionState);
4888  functionParams.push_back(pointerToCharType);
4889  functionParams.push_back(pointerToCharType);
4890  functionParams.push_back(boolType);
4891  functionParams.push_back(boolType);
4892  functionParams.push_back(boolType);
4893  functionParams.push_back(boolType);
4894  functionParams.push_back(boolType);
4895  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
4896  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4897  }
4898  return function;
4899 }
4900 
4902 {
4903  string functionName = "compositionFireTriggerPortEvent";
4904  string moduleKey = module->getModuleIdentifier();
4905  if (! moduleKey.empty())
4906  functionName = VuoStringUtilities::prefixSymbolName(functionName, moduleKey);
4907  Function *function = module->getFunction(functionName.c_str());
4908  if (! function)
4909  {
4910  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
4911  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4912 
4913  vector<Type *> functionParams;
4914  functionParams.push_back(pointerToCompositionState);
4915  functionParams.push_back(pointerToCharType);
4916  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
4917  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4918  }
4919  return function;
4920 }
4921 
4923 {
4924  const char *functionName = "vuoSetInputPortValue";
4925  Function *function = module->getFunction(functionName);
4926  if (! function)
4927  {
4928  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4929 
4930  vector<Type *> functionParams;
4931  functionParams.push_back(pointerToCharType);
4932  functionParams.push_back(pointerToCharType);
4933  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
4934  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4935  }
4936  return function;
4937 }
4938 
4940 {
4941  const char *functionName = "getPublishedInputPortValue";
4942  Function *function = module->getFunction(functionName);
4943  if (! function)
4944  {
4945  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4946  IntegerType *intType = IntegerType::get(module->getContext(), 32);
4947 
4948  vector<Type *> functionParams;
4949  functionParams.push_back(pointerToCharType);
4950  functionParams.push_back(intType);
4951  FunctionType *functionType = FunctionType::get(pointerToCharType, functionParams, false);
4952  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4953  }
4954  return function;
4955 }
4956 
4958 {
4959  const char *functionName = "getPublishedOutputPortValue";
4960  Function *function = module->getFunction(functionName);
4961  if (! function)
4962  {
4963  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4964  IntegerType *intType = IntegerType::get(module->getContext(), 32);
4965 
4966  vector<Type *> functionParams;
4967  functionParams.push_back(pointerToCharType);
4968  functionParams.push_back(intType);
4969  FunctionType *functionType = FunctionType::get(pointerToCharType, functionParams, false);
4970  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4971  }
4972  return function;
4973 }
4974 
4976 {
4977  string functionName = "compositionSetPublishedInputPortValue";
4978  string moduleKey = module->getModuleIdentifier();
4979  if (! moduleKey.empty())
4980  functionName = VuoStringUtilities::prefixSymbolName(functionName, moduleKey);
4981  Function *function = module->getFunction(functionName.c_str());
4982  if (! function)
4983  {
4984  PointerType *pointerToCompositionState = PointerType::get(getCompositionStateType(module), 0);
4985  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
4986  Type *boolType = IntegerType::get(module->getContext(), 64);
4987 
4988  vector<Type *> functionParams;
4989  functionParams.push_back(pointerToCompositionState);
4990  functionParams.push_back(pointerToCharType);
4991  functionParams.push_back(pointerToCharType);
4992  functionParams.push_back(boolType);
4993  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
4994  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
4995  }
4996  return function;
4997 }
4998 
5000 {
5001  const char *functionName = "setPublishedInputPortValue";
5002  Function *function = module->getFunction(functionName);
5003  if (! function)
5004  {
5005  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
5006 
5007  vector<Type *> functionParams;
5008  functionParams.push_back(pointerToCharType);
5009  functionParams.push_back(pointerToCharType);
5010  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
5011  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
5012  }
5013  return function;
5014 }
5016 
5020 bool VuoCompilerCodeGenUtilities::isPointerToStruct(Type *type, StructType **structType)
5021 {
5022  if (type->isPointerTy())
5023  {
5024  Type *elementType = cast<PointerType>(type)->getElementType();
5025  if (elementType->isStructTy())
5026  {
5027  if (structType)
5028  *structType = cast<StructType>(elementType);
5029 
5030  return true;
5031  }
5032  }
5033 
5034  return false;
5035 }
5036 
5040 Value * VuoCompilerCodeGenUtilities::callFunctionWithStructReturn(Function *function, vector<Value *> args, BasicBlock *block)
5041 {
5042  PointerType *pointerToReturnType = static_cast<PointerType *>(function->getFunctionType()->getParamType(0));
5043  Type *returnType = pointerToReturnType->getElementType();
5044  Value *returnVariable = new AllocaInst(returnType, 0, "", block);
5045  args.insert(args.begin(), returnVariable);
5046  CallInst::Create(function, args, "", block);
5047  return returnVariable;
5048 }
5049 
5055 {
5056  AttributeList functionAttrs = function->getAttributes();
5057  AttributeSet paramAttrs = functionAttrs.getParamAttributes(0);
5058  return paramAttrs.hasAttribute(Attribute::StructRet);
5059 }
5060 
5064 void VuoCompilerCodeGenUtilities::copyParameterAttributes(Function *srcFunction, Function *dstFunction)
5065 {
5066  AttributeList srcAttributes = srcFunction->getAttributes();
5067  for (int i = 0; i < srcFunction->getFunctionType()->getNumParams(); ++i)
5068  dstFunction->addParamAttrs(i, srcAttributes.getParamAttributes(i));
5069 }
5070 
5074 void VuoCompilerCodeGenUtilities::copyParameterAttributes(Module *module, Function *srcFunction, CallInst *dstCall)
5075 {
5076  copyParameterAttributes(module, srcFunction->getAttributes(), 0, srcFunction->getFunctionType()->getNumParams(), dstCall, 0);
5077 }
5078 
5083  const AttributeList &srcAttributes, size_t srcStartParam, size_t srcNumParams,
5084  Function *dstFunction, size_t dstStartParam)
5085 {
5086  AttributeList dstAttributes = dstFunction->getAttributes();
5087  for (size_t i = 0; i < srcNumParams; ++i)
5088  {
5089  size_t srcIndex = srcStartParam + i;
5090  size_t dstIndex = dstStartParam + i;
5091  dstAttributes = dstAttributes.addParamAttributes(module->getContext(), dstIndex, srcAttributes.getParamAttributes(srcIndex));
5092  }
5093  dstFunction->setAttributes(dstAttributes);
5094 }
5095 
5100  const AttributeList &srcAttributes, size_t srcStartParam, size_t srcNumParams,
5101  CallInst *dstCall, size_t dstStartParam)
5102 {
5103  AttributeList dstAttributes = dstCall->getAttributes();
5104  for (size_t i = 0; i < srcNumParams; ++i)
5105  {
5106  size_t srcIndex = srcStartParam + i;
5107  size_t dstIndex = dstStartParam + i;
5108  dstAttributes = dstAttributes.addParamAttributes(module->getContext(), dstIndex, srcAttributes.getParamAttributes(srcIndex));
5109  }
5110  dstCall->setAttributes(dstAttributes);
5111 }
5112 
5117 FunctionType * VuoCompilerCodeGenUtilities::getFunctionType(Module *module, VuoType *vuoType)
5118 {
5119  vector<Type *> params;
5120 
5121  if (vuoType)
5122  params = vuoType->getCompiler()->getFunctionParameterTypes();
5123 
5124  return FunctionType::get(Type::getVoidTy(module->getContext()), params, false);
5125 }
5126 
5130 Value * VuoCompilerCodeGenUtilities::getArgumentAtIndex(Function *function, size_t index)
5131 {
5132  Value *argValue = NULL;
5133 
5134  Function::arg_iterator args = function->arg_begin();
5135  for (size_t i = 0; i <= index && i < function->arg_size(); ++i)
5136  argValue = args++;
5137 
5138  return argValue;
5139 }