Vuo  2.0.0
VuoCompilerNode.cc
Go to the documentation of this file.
1 
10 #include <sstream>
11 
17 #include "VuoCompilerNode.hh"
18 #include "VuoCompilerNodeClass.hh"
21 #include "VuoCompilerType.hh"
22 #include "VuoNode.hh"
23 #include "VuoNodeClass.hh"
24 #include "VuoPort.hh"
25 #include "VuoStringUtilities.hh"
26 #include "VuoType.hh"
27 
28 
33  : VuoBaseDetail<VuoNode>("VuoNode", baseNode)
34 {
35  getBase()->setCompiler(this);
36 
37  instanceData = NULL;
39  if (instanceDataClass)
40  instanceData = new VuoCompilerInstanceData(instanceDataClass);
41 
42  graphvizIdentifier = getGraphvizIdentifierPrefix();
43 
44  constantStrings = NULL;
45  indexInOrderedNodes = ULONG_MAX - 1;
46 }
47 
51 void VuoCompilerNode::setIndexInOrderedNodes(size_t indexInOrderedNodes)
52 {
53  this->indexInOrderedNodes = indexInOrderedNodes;
54 }
55 
60 {
61  return indexInOrderedNodes;
62 }
63 
68 {
69  this->constantStrings = constantStrings;
70 
71  vector<VuoPort *> inputPorts = getBase()->getInputPorts();
72  vector<VuoPort *> outputPorts = getBase()->getOutputPorts();
73  vector<VuoPort *> ports;
74  ports.insert(ports.end(), inputPorts.begin(), inputPorts.end());
75  ports.insert(ports.end(), outputPorts.begin(), outputPorts.end());
76  for (vector<VuoPort *>::iterator i = ports.begin(); i != ports.end(); ++i)
77  {
78  VuoCompilerPort *port = static_cast<VuoCompilerPort *>( (*i)->getCompiler() );
79  port->setConstantStringCache(constantStrings);
80  }
81 }
82 
87 {
88  return constantStrings->get(module, getIdentifier());
89 }
90 
97 Value * VuoCompilerNode::generateSubcompositionIdentifierValue(Module *module, BasicBlock *block, Value *compositionIdentifierValue)
98 {
99  vector<Value *> identifierParts;
100  identifierParts.push_back(compositionIdentifierValue);
101  identifierParts.push_back(constantStrings->get(module, "/" + getIdentifier()));
102  return VuoCompilerCodeGenUtilities::generateStringConcatenation(module, block, identifierParts, *constantStrings);
103 }
104 
108 Value * VuoCompilerNode::generateGetContext(Module *module, BasicBlock *block, Value *compositionStateValue)
109 {
110  return VuoCompilerCodeGenUtilities::generateGetNodeContext(module, block, compositionStateValue, indexInOrderedNodes);
111 }
112 
117 void VuoCompilerNode::generateAddMetadata(Module *module, BasicBlock *block, Value *compositionStateValue,
118  const vector<VuoCompilerType *> &orderedTypes,
119  Function *compositionCreateContextForNode,
120  Function *compositionSetPortValueFunction, Function *compositionGetPortValueFunction,
121  Function *compositionFireTriggerPortEventFunction, Function *compositionReleasePortDataFunction)
122 {
123  Function *subcompositionFunctionSrc = getBase()->getNodeClass()->getCompiler()->getCompositionAddNodeMetadataFunction();
124 
125  Value *nodeIdentifierValue = generateIdentifierValue(module);
126  VuoCompilerCodeGenUtilities::generateAddNodeMetadata(module, block, compositionStateValue, nodeIdentifierValue,
127  compositionCreateContextForNode, compositionSetPortValueFunction,
128  compositionGetPortValueFunction, compositionFireTriggerPortEventFunction,
129  compositionReleasePortDataFunction);
130 
131  vector<VuoPort *> inputPorts = getBase()->getInputPorts();
132  vector<VuoPort *> outputPorts = getBase()->getOutputPorts();
133  vector<VuoPort *> ports;
134  ports.insert(ports.end(), inputPorts.begin(), inputPorts.end());
135  ports.insert(ports.end(), outputPorts.begin(), outputPorts.end());
136  for (vector<VuoPort *>::iterator i = ports.begin(); i != ports.end(); ++i)
137  {
138  VuoCompilerPort *port = static_cast<VuoCompilerPort *>( (*i)->getCompiler() );
139 
140  Value *portIdentifierValue = constantStrings->get(module, port->getIdentifier());
141  Value *portNameValue = constantStrings->get(module, port->getBase()->getClass()->getName());
142 
143  size_t typeIndex;
144  string initialValue;
145 
146  VuoType *dataType = port->getDataVuoType();
147  if (dataType)
148  {
149  vector<VuoCompilerType *>::const_iterator typeIter = find(orderedTypes.begin(), orderedTypes.end(), dataType->getCompiler());
150  typeIndex = typeIter - orderedTypes.begin();
151 
152  VuoCompilerInputEventPort *inputEventPort = dynamic_cast<VuoCompilerInputEventPort *>(port);
153  initialValue = (inputEventPort ? inputEventPort->getData()->getInitialValue() : "");
154  }
155  else
156  {
157  typeIndex = orderedTypes.size();
158  }
159 
160  Value *initialValueValue = constantStrings->get(module, initialValue);
161 
162  VuoCompilerCodeGenUtilities::generateAddPortMetadata(module, block, compositionStateValue, portIdentifierValue,
163  portNameValue, typeIndex, initialValueValue);
164  }
165 
166  if (subcompositionFunctionSrc)
167  {
168  Value *runtimeStateValue = VuoCompilerCodeGenUtilities::generateGetCompositionStateRuntimeState(module, block, compositionStateValue);
169  Value *compositionIdentifierValue = VuoCompilerCodeGenUtilities::generateGetCompositionStateCompositionIdentifier(module, block, compositionStateValue);
170  Value *subcompositionIdentifierValue = generateSubcompositionIdentifierValue(module, block, compositionIdentifierValue);
171  Value *subcompositionStateValue = VuoCompilerCodeGenUtilities::generateCreateCompositionState(module, block, runtimeStateValue, subcompositionIdentifierValue);
172 
173  Function *subcompositionFunctionDst = VuoCompilerModule::declareFunctionInModule(module, subcompositionFunctionSrc);
174  Value *arg = VuoCompilerCodeGenUtilities::convertArgumentToParameterType(subcompositionStateValue, subcompositionFunctionDst, 0, NULL, module, block);
175  CallInst::Create(subcompositionFunctionDst, arg, "", block);
176 
177  VuoCompilerCodeGenUtilities::generateFreeCompositionState(module, block, subcompositionStateValue);
178  VuoCompilerCodeGenUtilities::generateFreeCall(module, block, subcompositionIdentifierValue);
179  }
180 }
181 
185 Value * VuoCompilerNode::generateCreateContext(Module *module, BasicBlock *block)
186 {
187  // Create the node context.
188 
189  bool isSubcomposition = getBase()->getNodeClass()->getCompiler()->isSubcomposition();
190  unsigned long publishedOutputPortCount = (isSubcomposition ?
192 
193  Value * nodeContextValue = VuoCompilerCodeGenUtilities::generateCreateNodeContext(module, block, instanceData, isSubcomposition, publishedOutputPortCount);
194 
195  // Create each port's context.
196 
197  vector<VuoPort *> inputPorts = getBase()->getInputPorts();
198  vector<VuoPort *> outputPorts = getBase()->getOutputPorts();
199  vector<VuoPort *> ports;
200  ports.insert(ports.end(), inputPorts.begin(), inputPorts.end());
201  ports.insert(ports.end(), outputPorts.begin(), outputPorts.end());
202  vector<Value *> portContextValues;
203  for (vector<VuoPort *>::iterator i = ports.begin(); i != ports.end(); ++i)
204  {
205  VuoCompilerPort *port = static_cast<VuoCompilerPort *>( (*i)->getCompiler() );
206 
207  Value *portContextValue = port->generateCreatePortContext(module, block);
208  portContextValues.push_back(portContextValue);
209  }
210 
211  VuoCompilerCodeGenUtilities::generateSetNodeContextPortContexts(module, block, nodeContextValue, portContextValues);
212 
213  return nodeContextValue;
214 }
215 
227 void VuoCompilerNode::generateEventFunctionCall(Module *module, Function *function, BasicBlock *&currentBlock,
228  Value *compositionStateValue)
229 {
230  Function *functionSrc = getBase()->getNodeClass()->getCompiler()->getEventFunction();
231 
232  Value *nodeContextValue = generateGetContext(module, currentBlock, compositionStateValue);
233 
234  map<VuoCompilerEventPort *, Value *> portContextForEventPort;
235  vector<VuoPort *> inputPorts = getBase()->getInputPorts();
236  vector<VuoPort *> outputPorts = getBase()->getOutputPorts();
237  vector<VuoPort *> ports;
238  ports.insert(ports.end(), inputPorts.begin(), inputPorts.end());
239  ports.insert(ports.end(), outputPorts.begin(), outputPorts.end());
240  for (vector<VuoPort *>::iterator i = ports.begin(); i != ports.end(); ++i)
241  {
242  VuoCompilerEventPort *eventPort = dynamic_cast<VuoCompilerEventPort *>((*i)->getCompiler());
243  if (eventPort)
244  portContextForEventPort[eventPort] = eventPort->generateGetPortContext(module, currentBlock, nodeContextValue);
245  }
246 
247  generateFunctionCall(functionSrc, module, currentBlock, compositionStateValue, nodeContextValue, portContextForEventPort);
248 
249  // The output port should transmit an event if any non-blocking input port received the event.
250  // The output port should not transmit an event if no non-blocking or door input ports received the event.
251  // Otherwise, the output port's event transmission is handled by the node class implementation.
252 
253  vector<VuoPort *> nonBlockingInputPorts;
254  vector<VuoPort *> doorInputPorts;
255  for (vector<VuoPort *>::iterator i = inputPorts.begin(); i != inputPorts.end(); ++i)
256  {
257  VuoPortClass::EventBlocking eventBlocking = (*i)->getClass()->getEventBlocking();
258  if (eventBlocking == VuoPortClass::EventBlocking_None)
259  nonBlockingInputPorts.push_back(*i);
260  else if (eventBlocking == VuoPortClass::EventBlocking_Door)
261  doorInputPorts.push_back(*i);
262  }
263 
264  Value *eventHitNonBlockingInputPort = generateReceivedEventCondition(module, currentBlock, nodeContextValue, nonBlockingInputPorts,
265  portContextForEventPort);
266  Value *transmitForAllOutputPorts = eventHitNonBlockingInputPort;
267 
268  BasicBlock *handleTransmissionBlock = NULL;
269  BasicBlock *nextBlock = NULL;
270  if (! doorInputPorts.empty())
271  {
272  handleTransmissionBlock = BasicBlock::Create(module->getContext(), "handleTransmission", function, 0);
273  nextBlock = BasicBlock::Create(module->getContext(), "next", function, 0);
274 
275  Value *eventHitDoorInputPort = generateReceivedEventCondition(module, currentBlock, nodeContextValue, doorInputPorts,
276  portContextForEventPort);
277 
278  Value *blockForAllOutputPorts = BinaryOperator::Create(Instruction::And,
279  BinaryOperator::CreateNot(eventHitNonBlockingInputPort, "", currentBlock),
280  BinaryOperator::CreateNot(eventHitDoorInputPort, "", currentBlock),
281  "", currentBlock);
282  Value *handleTransmission = BinaryOperator::Create(Instruction::Or, transmitForAllOutputPorts, blockForAllOutputPorts, "", currentBlock);
283 
284  Constant *zeroValue = ConstantInt::get(transmitForAllOutputPorts->getType(), 0);
285  ICmpInst *handleTransmissionComparison = new ICmpInst(*currentBlock, ICmpInst::ICMP_NE, handleTransmission, zeroValue, "");
286  BranchInst::Create(handleTransmissionBlock, nextBlock, handleTransmissionComparison, currentBlock);
287  }
288  else
289  {
290  handleTransmissionBlock = currentBlock;
291  }
292 
293  for (vector<VuoPort *>::iterator i = outputPorts.begin(); i != outputPorts.end(); ++i)
294  {
295  VuoCompilerOutputEventPort *eventPort = dynamic_cast<VuoCompilerOutputEventPort *>((*i)->getCompiler());
296  if (eventPort)
297  {
298  Value *portContextValue = portContextForEventPort[eventPort];
299  eventPort->generateStoreEvent(module, handleTransmissionBlock, nodeContextValue, transmitForAllOutputPorts, portContextValue);
300  }
301  }
302 
303  if (! doorInputPorts.empty())
304  {
305  BranchInst::Create(nextBlock, handleTransmissionBlock);
306  currentBlock = nextBlock;
307  }
308 }
309 
320 void VuoCompilerNode::generateInitFunctionCall(Module *module, BasicBlock *block, Value *compositionStateValue)
321 {
322  Function *functionSrc = getBase()->getNodeClass()->getCompiler()->getInitFunction();
323 
324  Value *nodeContextValue = generateGetContext(module, block, compositionStateValue);
325  CallInst *call = generateFunctionCall(functionSrc, module, block, compositionStateValue, nodeContextValue);
326 
327  Type *instanceDataType = instanceData->getBase()->getClass()->getCompiler()->getType();
328  Value *callCasted = VuoCompilerCodeGenUtilities::generateTypeCast(module, block, call, instanceDataType);
329  instanceData->generateStore(module, block, nodeContextValue, callCasted);
330 
331  // Retain the instance data.
332  Value *instanceDataValue = instanceData->generateLoad(module, block, nodeContextValue);
333  VuoCompilerCodeGenUtilities::generateRetainCall(module, block, instanceDataValue);
334 }
335 
345 void VuoCompilerNode::generateFiniFunctionCall(Module *module, BasicBlock *block, Value *compositionStateValue)
346 {
347  Function *functionSrc = getBase()->getNodeClass()->getCompiler()->getFiniFunction();
348 
349  Value *nodeContextValue = generateGetContext(module, block, compositionStateValue);
350  if (functionSrc)
351  generateFunctionCall(functionSrc, module, block, compositionStateValue, nodeContextValue);
352 
353  // Release the instance data.
354  Value *instanceDataValue = instanceData->generateLoad(module, block, nodeContextValue);
355  VuoCompilerCodeGenUtilities::generateReleaseCall(module, block, instanceDataValue);
356 }
357 
365 void VuoCompilerNode::generateCallbackStartFunctionCall(Module *module, BasicBlock *block, Value *compositionStateValue)
366 {
367  Function *functionSrc = getBase()->getNodeClass()->getCompiler()->getCallbackStartFunction();
368  if (! functionSrc)
369  return;
370 
371  Value *nodeContextValue = generateGetContext(module, block, compositionStateValue);
372  generateFunctionCall(functionSrc, module, block, compositionStateValue, nodeContextValue);
373 }
374 
382 void VuoCompilerNode::generateCallbackUpdateFunctionCall(Module *module, BasicBlock *block, Value *compositionStateValue)
383 {
384  Function *functionSrc = getBase()->getNodeClass()->getCompiler()->getCallbackUpdateFunction();
385  if (! functionSrc)
386  return;
387 
388  Value *nodeContextValue = generateGetContext(module, block, compositionStateValue);
389  generateFunctionCall(functionSrc, module, block, compositionStateValue, nodeContextValue);
390 }
391 
399 void VuoCompilerNode::generateCallbackStopFunctionCall(Module *module, BasicBlock *block, Value *compositionStateValue)
400 {
401  Function *functionSrc = getBase()->getNodeClass()->getCompiler()->getCallbackStopFunction();
402  if (! functionSrc)
403  return;
404 
405  Value *nodeContextValue = generateGetContext(module, block, compositionStateValue);
406  generateFunctionCall(functionSrc, module, block, compositionStateValue, nodeContextValue);
407 }
408 
418 CallInst * VuoCompilerNode::generateFunctionCall(Function *functionSrc, Module *module, BasicBlock *block,
419  Value *compositionStateValue, Value *nodeContextValue,
420  const map<VuoCompilerEventPort *, Value *> &portContextForEventPort)
421 {
422  Function *functionDst = VuoCompilerModule::declareFunctionInModule(module, functionSrc);
423 
424  vector<Value *> args(functionDst->getFunctionType()->getNumParams());
425 
426  // Set up the argument for the composition state (if a subcomposition).
427  Value *subcompositionIdentifierValue = NULL;
428  Value *subcompositionStateValue = NULL;
429  if (getBase()->getNodeClass()->getCompiler()->isSubcomposition())
430  {
431  Value *runtimeStateValue = VuoCompilerCodeGenUtilities::generateGetCompositionStateRuntimeState(module, block, compositionStateValue);
432  Value *compositionIdentifierValue = VuoCompilerCodeGenUtilities::generateGetCompositionStateCompositionIdentifier(module, block, compositionStateValue);
433  subcompositionIdentifierValue = generateSubcompositionIdentifierValue(module, block, compositionIdentifierValue);
434  subcompositionStateValue = VuoCompilerCodeGenUtilities::generateCreateCompositionState(module, block, runtimeStateValue, subcompositionIdentifierValue);
435  args[0] = VuoCompilerCodeGenUtilities::convertArgumentToParameterType(subcompositionStateValue, functionDst, 0, NULL, module, block);
436  }
437 
438  // Set up the arguments for input ports.
439  vector<VuoPort *> inputPorts = getBase()->getInputPorts();
440  for (vector<VuoPort *>::iterator i = inputPorts.begin(); i != inputPorts.end(); ++i)
441  {
442  VuoCompilerInputEventPort *eventPort = dynamic_cast<VuoCompilerInputEventPort *>((*i)->getCompiler());
443 
444  VuoCompilerInputData *data = eventPort->getData();
445  bool isEventArgumentInFunction = isArgumentInFunction(eventPort, functionSrc);
446  bool isDataArgumentInFunction = data && isArgumentInFunction(data, functionSrc);
447 
448  if (isEventArgumentInFunction || isDataArgumentInFunction)
449  {
450  map<VuoCompilerEventPort *, Value *>::const_iterator iter = portContextForEventPort.find(eventPort);
451  Value *portContextValue = (iter != portContextForEventPort.end() ?
452  iter->second :
453  eventPort->generateGetPortContext(module, block, nodeContextValue));
454 
455  if (isEventArgumentInFunction)
456  {
457  size_t index = getArgumentIndexInFunction(eventPort, functionSrc);
458  args[index] = eventPort->generateLoadEvent(module, block, nodeContextValue, portContextValue);
459  }
460 
461  if (isDataArgumentInFunction)
462  {
463  size_t index = getArgumentIndexInFunction(data, functionSrc);
464  Value *arg = eventPort->generateLoadData(module, block, nodeContextValue, portContextValue);
465  Value *secondArg = NULL;
466 
467  // If we're calling a node function for a subcomposition, and the parameter is a struct that
468  // would normally be passed "byval", instead generate code equivalent to the "byval" semantics:
469  // Allocate a stack variable, copy the struct into it, and pass the variable's address as
470  // the argument to the node function.
471  //
472  // This is a workaround for a bug where LLVM would sometimes give the node function body
473  // an invalid value for a "byval" struct argument. https://b33p.net/kosada/node/11386
474  if (getBase()->getNodeClass()->getCompiler()->isSubcomposition() &&
475  arg->getType()->isStructTy() &&
476  eventPort->getDataVuoType()->getCompiler()->getFunctionParameterAttributes().hasAttrSomewhere(Attribute::ByVal))
477  {
478  Value *argAsPointer = VuoCompilerCodeGenUtilities::generatePointerToValue(block, arg);
479  arg = new BitCastInst(argAsPointer, functionSrc->getFunctionType()->getParamType(index), "", block);
480  }
481  else
482  {
483  bool isLoweredToTwoParameters = static_cast<VuoCompilerInputDataClass *>(data->getBase()->getClass()->getCompiler())->isLoweredToTwoParameters();
484  Value **secondArgIfNeeded = (isLoweredToTwoParameters ? &secondArg : NULL);
485  arg = VuoCompilerCodeGenUtilities::convertArgumentToParameterType(arg, functionDst, index, secondArgIfNeeded, module, block);
486  if (!arg)
487  {
488  VUserLog("Warning: Couldn't convert argument for input port '%s' of function %s; not generating call.",
489  (*i)->getClass()->getName().c_str(),
490  functionDst->getName().str().c_str());
491  return nullptr;
492  }
493  }
494 
495  args[index] = arg;
496  if (secondArg)
497  args[index + 1] = secondArg;
498  }
499  }
500  }
501 
502  // Set up the arguments for output ports.
503  vector<VuoPort *> outputPorts = getBase()->getOutputPorts();
504  map<VuoCompilerOutputEventPort *, Value *> outputPortDataVariables;
505  map<VuoCompilerOutputEventPort *, AllocaInst *> outputPortEventVariables;
506  for (vector<VuoPort *>::iterator i = outputPorts.begin(); i != outputPorts.end(); ++i)
507  {
508  VuoCompilerOutputEventPort *eventPort = dynamic_cast<VuoCompilerOutputEventPort *>((*i)->getCompiler());
509  if (eventPort)
510  {
511  VuoCompilerOutputData *data = eventPort->getData();
512  bool isEventArgumentInFunction = isArgumentInFunction(eventPort, functionSrc);
513  bool isDataArgumentInFunction = data && isArgumentInFunction(data, functionSrc);
514 
515  if (isEventArgumentInFunction)
516  {
517  size_t index = getArgumentIndexInFunction(eventPort, functionSrc);
518  PointerType *eventPointerType = static_cast<PointerType *>( functionDst->getFunctionType()->getParamType(index) );
519  AllocaInst *arg = new AllocaInst(eventPointerType->getElementType(), "", block);
520  new StoreInst(ConstantInt::get(eventPointerType->getElementType(), 0), arg, block);
521  outputPortEventVariables[eventPort] = arg;
522  args[index] = arg;
523  }
524 
525  if (isDataArgumentInFunction)
526  {
527  map<VuoCompilerEventPort *, Value *>::const_iterator iter = portContextForEventPort.find(eventPort);
528  Value *portContextValue = (iter != portContextForEventPort.end() ?
529  iter->second :
530  eventPort->generateGetPortContext(module, block, nodeContextValue));
531 
532  size_t index = getArgumentIndexInFunction(data, functionSrc);
533  Type *type = eventPort->getDataVuoType()->getCompiler()->getType();
534  Value *dataVariable = VuoCompilerCodeGenUtilities::generateGetPortContextDataVariable(module, block, portContextValue, type);
535  outputPortDataVariables[eventPort] = dataVariable;
536 
537  Value *arg = VuoCompilerCodeGenUtilities::convertArgumentToParameterType(dataVariable, functionDst, index, NULL, module, block);
538  if (!arg)
539  {
540  VUserLog("Warning: Couldn't convert argument for output port '%s' of function %s; not generating call.",
541  (*i)->getClass()->getName().c_str(),
542  functionDst->getName().str().c_str());
543  return nullptr;
544  }
545  args[index] = arg;
546  }
547  }
548  else
549  {
550  VuoCompilerTriggerPort *triggerPort = (VuoCompilerTriggerPort *)((*i)->getCompiler());
551  if (isArgumentInFunction(triggerPort, functionSrc))
552  {
553  size_t index = getArgumentIndexInFunction(triggerPort, functionSrc);
554  args[index] = triggerPort->generateLoadFunction(module, block, nodeContextValue);
555  }
556  }
557  }
558 
559  // Set up the argument for the instance data (if it exists).
560  Value *instanceDataVariable = NULL;
561  if (instanceData && isArgumentInFunction(instanceData, functionSrc))
562  {
563  Type *type = instanceData->getBase()->getClass()->getCompiler()->getType();
564  instanceDataVariable = VuoCompilerCodeGenUtilities::generateGetNodeContextInstanceDataVariable(module, block, nodeContextValue, type);
565 
566  size_t index = getArgumentIndexInFunction(instanceData, functionSrc);
567  Value *arg = instanceDataVariable;
568  args[index] = VuoCompilerCodeGenUtilities::convertArgumentToParameterType(arg, functionDst, index, NULL, module, block);
569  if (!args[index])
570  {
571  VUserLog("Warning: Couldn't convert argument for instance data of function %s; not generating call.", functionDst->getName().str().c_str());
572  return nullptr;
573  }
574  }
575 
576  // Save the old output port values so they can be released later.
577  map<VuoCompilerOutputEventPort *, Value *> oldOutputDataValues;
578  for (map<VuoCompilerOutputEventPort *, Value *>::iterator i = outputPortDataVariables.begin(); i != outputPortDataVariables.end(); ++i)
579  {
580  VuoCompilerOutputEventPort *eventPort = i->first;
581  Value *dataVariable = i->second;
582 
583  oldOutputDataValues[eventPort] = new LoadInst(dataVariable, "", false, block);
584  }
585 
586  // Save the old instance data value so it can be released later.
587  Value *oldInstanceDataValue = NULL;
588  if (instanceDataVariable)
589  {
590  oldInstanceDataValue = new LoadInst(instanceDataVariable, "", false, block);
591  }
592 
594 
595  // Call the node class's function.
596  CallInst *call = CallInst::Create(functionDst, args, "", block);
597 
599 
600  // Save the output events from temporary variables to the ports.
601  // (The temporary variables are needed to avoid mismatched types between the parameters and the arguments, e.g. i8* vs. i64*.)
602  for (map<VuoCompilerOutputEventPort *, AllocaInst *>::iterator i = outputPortEventVariables.begin(); i != outputPortEventVariables.end(); ++i)
603  {
604  VuoCompilerOutputEventPort *eventPort = i->first;
605  AllocaInst *eventVariable = i->second;
606  Value *eventValue = new LoadInst(eventVariable, "", false, block);
607  eventPort->generateStoreEvent(module, block, nodeContextValue, eventValue);
608  }
609 
610  // Retain the new output port values.
611  for (map<VuoCompilerOutputEventPort *, Value *>::iterator i = outputPortDataVariables.begin(); i != outputPortDataVariables.end(); ++i)
612  {
613  VuoCompilerOutputEventPort *eventPort = i->first;
614  Value *dataVariable = i->second;
615 
616  Value *outputDataValue = new LoadInst(dataVariable, "", false, block);
617  VuoCompilerType *type = eventPort->getDataVuoType()->getCompiler();
618  type->generateRetainCall(module, block, outputDataValue);
619  }
620 
621  // Release the old output port values.
622  for (map<VuoCompilerOutputEventPort *, Value *>::iterator i = oldOutputDataValues.begin(); i != oldOutputDataValues.end(); ++i)
623  {
624  VuoCompilerOutputEventPort *eventPort = i->first;
625  Value *oldOutputDataValue = i->second;
626 
627  VuoCompilerType *type = eventPort->getDataVuoType()->getCompiler();
628  type->generateReleaseCall(module, block, oldOutputDataValue);
629  }
630 
631  if (instanceDataVariable)
632  {
633  // Retain the new instance data value.
634  Value *instanceDataValue = new LoadInst(instanceDataVariable, "", false, block);
635  VuoCompilerCodeGenUtilities::generateRetainCall(module, block, instanceDataValue);
636 
637  // Release the old instance data value.
638  VuoCompilerCodeGenUtilities::generateReleaseCall(module, block, oldInstanceDataValue);
639  }
640 
641  if (getBase()->getNodeClass()->getCompiler()->isSubcomposition())
642  {
643  VuoCompilerCodeGenUtilities::generateFreeCompositionState(module, block, subcompositionStateValue);
644  VuoCompilerCodeGenUtilities::generateFreeCall(module, block, subcompositionIdentifierValue);
645  }
646 
647  return call;
648 }
649 
656 bool VuoCompilerNode::isArgumentInFunction(VuoCompilerNodeArgument *argument, Function *function)
657 {
658  VuoCompilerNodeArgumentClass *argumentClass = argument->getBase()->getClass()->getCompiler();
659  if (function == getBase()->getNodeClass()->getCompiler()->getEventFunction())
660  return argumentClass->isInEventFunction();
661  else if (function == getBase()->getNodeClass()->getCompiler()->getInitFunction())
662  return argumentClass->isInInitFunction();
663  else if (function == getBase()->getNodeClass()->getCompiler()->getCallbackStartFunction())
664  return argumentClass->isInCallbackStartFunction();
665  else if (function == getBase()->getNodeClass()->getCompiler()->getCallbackUpdateFunction())
666  return argumentClass->isInCallbackUpdateFunction();
667  else if (function == getBase()->getNodeClass()->getCompiler()->getCallbackStopFunction())
668  return argumentClass->isInCallbackStopFunction();
669  else if (instanceData == argument &&
670  (function == getBase()->getNodeClass()->getCompiler()->getFiniFunction()))
671  return true;
672  return false;
673 }
674 
681 size_t VuoCompilerNode::getArgumentIndexInFunction(VuoCompilerNodeArgument *argument, Function *function)
682 {
683  VuoCompilerNodeArgumentClass *argumentClass = argument->getBase()->getClass()->getCompiler();
684  if (function == getBase()->getNodeClass()->getCompiler()->getEventFunction())
685  return argumentClass->getIndexInEventFunction();
686  else if (function == getBase()->getNodeClass()->getCompiler()->getInitFunction())
687  return argumentClass->getIndexInInitFunction();
688  else if (function == getBase()->getNodeClass()->getCompiler()->getFiniFunction())
689  return (getBase()->getNodeClass()->getCompiler()->isSubcomposition() ? 1 : 0);
690  else if (function == getBase()->getNodeClass()->getCompiler()->getCallbackStartFunction())
691  return argumentClass->getIndexInCallbackStartFunction();
692  else if (function == getBase()->getNodeClass()->getCompiler()->getCallbackUpdateFunction())
693  return argumentClass->getIndexInCallbackUpdateFunction();
694  else if (function == getBase()->getNodeClass()->getCompiler()->getCallbackStopFunction())
695  return argumentClass->getIndexInCallbackStopFunction();
696  return 0;
697 }
698 
702 Value * VuoCompilerNode::generateReceivedEventCondition(Module *module, BasicBlock *block, Value *nodeContextValue)
703 {
704  return generateReceivedEventCondition(module, block, nodeContextValue, getBase()->getInputPorts());
705 }
706 
710 Value * VuoCompilerNode::generateReceivedEventCondition(Module *module, BasicBlock *block, Value *nodeContextValue,
711  vector<VuoPort *> selectedInputPorts,
712  const map<VuoCompilerEventPort *, Value *> &portContextForEventPort)
713 {
714  Value *conditionValue = ConstantInt::getFalse(block->getContext());
715  for (vector<VuoPort *>::iterator i = selectedInputPorts.begin(); i != selectedInputPorts.end(); ++i)
716  {
717  VuoCompilerInputEventPort *eventPort = dynamic_cast<VuoCompilerInputEventPort *>((*i)->getCompiler());
718  if (eventPort)
719  {
720  map<VuoCompilerEventPort *, Value *>::const_iterator iter = portContextForEventPort.find(eventPort);
721  Value *portContextValue = (iter != portContextForEventPort.end() ?
722  iter->second :
723  eventPort->generateGetPortContext(module, block, nodeContextValue));
724 
725  Value *pushValue = eventPort->generateLoadEvent(module, block, nodeContextValue, portContextValue);
726  conditionValue = BinaryOperator::Create(Instruction::Or, conditionValue, pushValue, "", block);
727  }
728  }
729  return conditionValue;
730 }
731 
736 {
737  return instanceData;
738 }
739 
747 {
748  return getGraphvizIdentifier();
749 }
750 
760 {
761  string titleWithoutSpaces = VuoStringUtilities::convertToCamelCase(getBase()->getTitle(), true, false, false);
762 
763  if (titleWithoutSpaces.empty())
764  return "Node";
765  else
766  return titleWithoutSpaces;
767 }
768 
772 void VuoCompilerNode::setGraphvizIdentifier(string graphvizIdentifier)
773 {
774  this->graphvizIdentifier = graphvizIdentifier;
775 }
776 
781 {
782  return graphvizIdentifier;
783 }
784 
789 string VuoCompilerNode::getGraphvizDeclaration(bool shouldPrintPosition, double xPositionOffset, double yPositionOffset,
790  VuoPort *manuallyFirableInputPort)
791 {
792  ostringstream declaration;
793 
794  vector<VuoPort *> inputPorts = getBase()->getInputPorts();
795  vector<VuoPort *> outputPorts = getBase()->getOutputPorts();
796 
797  // name
798  declaration << getGraphvizIdentifier();
799 
800  // type
801  declaration << " [type=\"" << getBase()->getNodeClass()->getClassName() << "\"";
802 
803  // version
804  declaration << " version=\"" << getBase()->getNodeClass()->getVersion() << "\"";
805 
806  // label
807  declaration << " label=\"" << VuoStringUtilities::transcodeToGraphvizIdentifier(getBase()->getTitle());
808  for (vector<VuoPort *>::iterator i = inputPorts.begin(); i != inputPorts.end(); ++i)
809  {
810  string portName = VuoStringUtilities::transcodeToGraphvizIdentifier((*i)->getClass()->getName());
811  declaration << "|<" << portName << ">" << portName << "\\l";
812  }
813  for (vector<VuoPort *>::iterator i = outputPorts.begin(); i != outputPorts.end(); ++i)
814  {
815  string portName = VuoStringUtilities::transcodeToGraphvizIdentifier((*i)->getClass()->getName());
816  declaration << "|<" << portName << ">" << portName << "\\r";
817  }
818  declaration << "\"";
819 
820  // position
821  if (shouldPrintPosition)
822  declaration << " pos=\"" << getBase()->getX()+xPositionOffset << "," << getBase()->getY()+yPositionOffset << "\"";
823 
824  // collapsed
825  if (getBase()->isCollapsed())
826  declaration << " collapsed";
827 
828  // tint color
829  if (getBase()->getTintColor() != VuoNode::TintNone)
830  declaration << " fillcolor=\"" << getBase()->getTintColorGraphvizName() << "\"";
831 
832  // constant values
833  for (vector<VuoPort *>::iterator i = inputPorts.begin(); i != inputPorts.end(); ++i)
834  {
835  VuoPort *port = *i;
836  VuoCompilerInputEventPort *eventPort = static_cast<VuoCompilerInputEventPort *>(port->getCompiler());
837  VuoCompilerInputData *data = eventPort->getData();
838  if (data && (! eventPort->hasConnectedDataCable() && ! data->getInitialValue().empty()))
839  {
840  string portConstant = data->getInitialValue();
841  string escapedPortConstant = VuoStringUtilities::transcodeToGraphvizIdentifier(portConstant);
842  declaration << " _" << port->getClass()->getName() << "=\"" << escapedPortConstant << "\"";
843  }
844  }
845 
846  // event throttling
847  for (vector<VuoPort *>::iterator i = outputPorts.begin(); i != outputPorts.end(); ++i)
848  {
849  VuoPort *port = *i;
851  {
852  string eventThrottling = (port->getEventThrottling() == VuoPortClass::EventThrottling_Enqueue ? "enqueue" : "drop");
853  declaration << " _" << port->getClass()->getName() << "_eventThrottling=\"" << eventThrottling << "\"";
854  }
855  }
856 
857  // manually firable input port
858  if (manuallyFirableInputPort)
859  declaration << " _" << manuallyFirableInputPort->getClass()->getName() << "_manuallyFirable";
860 
861  declaration << "];";
862 
863  return declaration.str();
864 }