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