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