43 bool isTopLevelComposition,
54 bool isTopLevelComposition,
58 VuoCompilerBitcodeGenerator_Pro();
61 constantsCache =
nullptr;
64 this->composition = composition;
65 this->isTopLevelComposition = isTopLevelComposition;
66 this->moduleKey = moduleKey;
67 this->compiler = compiler;
74 makePortContextInfo();
75 makeSubcompositionModelPorts();
84 for (vector<VuoPort *>::iterator i = modelOutputPorts.begin(); i != modelOutputPorts.end(); ++i)
107 bool operator() (
const vector<VuoCompilerNode *> &chainNodes1,
const vector<VuoCompilerNode *> &chainNodes2)
114 bool isNode2DownstreamOfNode1 = find(downstreamOfChain1.begin(), downstreamOfChain1.end(), chainNodes2.front()) != downstreamOfChain1.end();
115 bool isNode1DownstreamOfNode2 = find(downstreamOfChain2.begin(), downstreamOfChain2.end(), chainNodes1.front()) != downstreamOfChain2.end();
117 if (isNode2DownstreamOfNode1 && isNode1DownstreamOfNode2)
119 else if (isNode2DownstreamOfNode1)
121 else if (isNode1DownstreamOfNode2)
127 size_t maxNumDownstreamOfTrigger[2] = { 0, 0 };
128 vector<VuoCompilerNode *> chainNodes[2] = { chainNodes1, chainNodes2 };
129 for (
int i = 0; i < 2; ++i)
131 for (vector<VuoCompilerNode *>::const_iterator j = chainNodes[i].begin(); j != chainNodes[i].end(); ++j)
135 for (vector<VuoPort *>::iterator k = outputPorts.begin(); k != outputPorts.end(); ++k)
142 maxNumDownstreamOfTrigger[i] = max(maxNumDownstreamOfTrigger[i], numDownstreamOfTrigger);
148 if (maxNumDownstreamOfTrigger[0] != maxNumDownstreamOfTrigger[1])
149 return maxNumDownstreamOfTrigger[0] > maxNumDownstreamOfTrigger[1];
153 return chainNodes1.front()->getIdentifier() < chainNodes2.front()->getIdentifier();
160 void VuoCompilerBitcodeGenerator::makeOrderedNodes(
void)
166 vector<VuoCompilerChain *> chains;
167 map<VuoCompilerTriggerPort *, vector<VuoCompilerChain *> >::iterator chainsIter = chainsForTrigger.find(trigger);
168 if (chainsIter != chainsForTrigger.end())
169 chains = chainsIter->second;
171 vector< vector<VuoCompilerNode *> > chainNodeLists;
172 set<VuoCompilerNode *> lastNodeInLoop;
175 if (chain->isLastNodeInLoop())
176 lastNodeInLoop.insert( chain->getNodes().front() );
178 chainNodeLists.push_back( chain->getNodes() );
185 sort(chainNodeLists.begin(), chainNodeLists.end(), c);
187 vector<VuoCompilerNode *> orderedNodeList;
190 orderedNodeList.push_back(triggerNode);
192 for (vector<VuoCompilerNode *> chainNodeList : chainNodeLists)
194 auto triggerNodeIter = std::find(chainNodeList.begin(), chainNodeList.end(), triggerNode);
195 if (triggerNodeIter != chainNodeList.end())
196 chainNodeList.erase(triggerNodeIter);
198 orderedNodeList.insert( orderedNodeList.end(), chainNodeList.begin(), chainNodeList.end() );
201 downstreamNodesForTrigger[trigger] = orderedNodeList;
204 vector< vector<VuoCompilerNode *> > orderedNodesPerTrigger;
205 for (
const map<
VuoCompilerTriggerPort *, vector<VuoCompilerNode *> >::value_type &i : downstreamNodesForTrigger)
206 orderedNodesPerTrigger.push_back(i.second);
214 vector<VuoCompilerNode *> nodesInProgress;
215 nodesInProgress.push_back(node);
216 nodesInProgress.insert(nodesInProgress.end(), downstreamNodes.begin(), downstreamNodes.end());
217 orderedNodesPerTrigger.push_back(nodesInProgress);
222 std::sort(orderedNodesPerTrigger.begin(), orderedNodesPerTrigger.end(),
223 [](
const vector<VuoCompilerNode *> &nodes1,
const vector<VuoCompilerNode *> &nodes2) {
224 if (nodes1.size() != nodes2.size())
225 return nodes1.size() < nodes2.size();
230 for (VuoCompilerNode *n : nodes1)
231 oss1 << n->getIdentifier() <<
" ";
232 for (VuoCompilerNode *n : nodes2)
233 oss2 << n->getIdentifier() <<
" ";
234 return oss1.str() < oss2.str();
240 int previousTriggerNodeIndex = -1;
241 for (vector< vector<VuoCompilerNode *> >::reverse_iterator i = orderedNodesPerTrigger.rbegin(); i != orderedNodesPerTrigger.rend(); ++i)
244 int previousNodeIndex = previousTriggerNodeIndex;
245 bool isFirstNode =
true;
248 vector<VuoCompilerNode *>::iterator nodeIter = find(orderedNodes.begin(), orderedNodes.end(), node);
249 if (nodeIter == orderedNodes.end())
250 nodeIter = orderedNodes.insert(orderedNodes.begin() + previousNodeIndex + 1, node);
252 previousNodeIndex = max(previousNodeIndex, (
int)(nodeIter - orderedNodes.begin()));
255 previousTriggerNodeIndex = previousNodeIndex;
263 if (find(orderedNodes.begin(), orderedNodes.end(), node) == orderedNodes.end())
264 orderedNodes.push_back(node);
266 for (
size_t i = 0; i < orderedNodes.size(); ++i)
267 orderedNodes[i]->setIndexInOrderedNodes(i);
273 void VuoCompilerBitcodeGenerator::sortNodes(vector<VuoCompilerNode *> &nodes)
275 vector<VuoCompilerNode *> sortedNodes;
276 for (vector<VuoCompilerNode *>::iterator i = orderedNodes.begin(); i != orderedNodes.end(); ++i)
279 if (find(nodes.begin(), nodes.end(), node) != nodes.end())
280 sortedNodes.push_back(node);
288 vector<VuoCompilerNode *> VuoCompilerBitcodeGenerator::getNodesToWaitOnBeforeTransmission(
VuoCompilerTriggerPort *trigger)
311 vector<VuoCompilerNode *> sortedDownstreamNodes = downstreamNodesForTrigger[trigger];
312 sortNodes(sortedDownstreamNodes);
313 bool hasOutOfOrderDownstreamNodes = (downstreamNodesForTrigger[trigger] != sortedDownstreamNodes);
316 vector<VuoCompilerNode *> nodesToWaitOn;
317 if (hasScatterOverlappedByAnotherTrigger || hasOverlapWithSpinOff || hasOutOfOrderDownstreamNodes)
318 nodesToWaitOn = downstreamNodesForTrigger[trigger];
322 VuoCompilerNode *triggerNode = downstreamNodesForTrigger[trigger].front();
323 if (find(nodesToWaitOn.begin(), nodesToWaitOn.end(), triggerNode) == nodesToWaitOn.end())
324 nodesToWaitOn.push_back(triggerNode);
327 return nodesToWaitOn;
345 vector<VuoCompilerNode *> nodesToWaitOn =
346 (hasGatherOverlappedByAnotherTrigger ?
350 return nodesToWaitOn;
356 void VuoCompilerBitcodeGenerator::makeOrderedTypes(
void)
362 vector<VuoPort *> ports;
363 ports.insert(ports.end(), inputPorts.begin(), inputPorts.end());
364 ports.insert(ports.end(), outputPorts.begin(), outputPorts.end());
372 vector<VuoCompilerType *>::iterator typeIter = find(orderedTypes.begin(), orderedTypes.end(), dataType->
getCompiler());
373 if (typeIter == orderedTypes.end())
383 void VuoCompilerBitcodeGenerator::makePortContextInfo(
void)
389 vector<VuoPort *> ports;
390 ports.insert(ports.end(), inputPorts.begin(), inputPorts.end());
391 ports.insert(ports.end(), outputPorts.begin(), outputPorts.end());
392 for (
size_t i = 0; i < ports.size(); ++i)
405 void VuoCompilerBitcodeGenerator::makeSubcompositionModelPorts(
void)
411 modelInputPorts.insert( modelInputPorts.end(), publishedInputPorts.begin(), publishedInputPorts.end() );
412 modelOutputPorts.insert( modelOutputPorts.end(), publishedOutputPorts.begin(), publishedOutputPorts.end() );
416 for (
size_t i = 0; i < modelOutputPorts.size(); ++i)
418 string portName = modelOutputPorts[i]->getClass()->getName();
419 if (publishedOutputTriggerNames.find(portName) != publishedOutputTriggerNames.end())
425 modelOutputPorts[i] = modelTriggerPort->
getBase();
433 void VuoCompilerBitcodeGenerator::makeDependencies(
void)
439 makeDependencies_Pro();
443 compiler->getDependenciesForComposition(composition);
455 bool isStatefulComposition =
false;
460 isStatefulComposition =
true;
471 generateCompositionMetadata();
473 generateTriggerFunctions();
475 if (! isTopLevelComposition)
476 generateNodeEventFunction(isStatefulComposition);
478 if (isStatefulComposition)
480 generateNodeInstanceInitFunction();
481 generateNodeInstanceFiniFunction();
482 generateNodeInstanceTriggerStartFunction();
483 if (! isTopLevelComposition)
484 generateNodeInstanceTriggerUpdateFunction();
487 generateNodeInstanceTriggerStopFunction();
489 generateCompositionReleasePortDataFunction();
491 generateCompositionGetPortValueFunction();
492 generateCompositionSetPortValueFunction();
493 generateCompositionFireTriggerPortEventFunction();
495 generateCompositionSetPublishedInputPortValueFunction();
497 generateCompositionCreateContextForNodeFunction();
498 generateCompositionAddNodeMetadataFunction();
499 generateCompositionPerformDataOnlyTransmissionsFunction();
501 if (isTopLevelComposition)
505 generateAllocation();
506 generateSetupFunction(isStatefulComposition);
507 generateCleanupFunction();
509 generateInstanceInitFunction(isStatefulComposition);
510 generateInstanceFiniFunction(isStatefulComposition);
511 generateInstanceTriggerStartFunction(isStatefulComposition);
512 generateInstanceTriggerStopFunction(isStatefulComposition);
514 generateSetInputPortValueFunction();
516 generateGetPublishedPortCountFunction(
true);
517 generateGetPublishedPortCountFunction(
false);
518 generateGetPublishedPortNamesFunction(
true);
519 generateGetPublishedPortNamesFunction(
false);
520 generateGetPublishedPortTypesFunction(
true);
521 generateGetPublishedPortTypesFunction(
false);
522 generateGetPublishedPortDetailsFunction(
true);
523 generateGetPublishedPortDetailsFunction(
false);
524 generateGetPublishedPortValueFunction(
true);
525 generateGetPublishedPortValueFunction(
false);
526 generateSetPublishedInputPortValueFunction();
527 generateFirePublishedInputPortEventFunction();
532 delete constantsCache;
533 constantsCache =
nullptr;
541 void VuoCompilerBitcodeGenerator::generateCompositionMetadata(
void)
543 json_object *metadataJson = json_object_new_object();
544 json_object *nodeMetadataJson = json_object_new_object();
552 json_object_object_add(metadataJson,
"title", json_object_new_string(title.c_str()));
555 json_object_object_add(metadataJson,
"description", json_object_new_string(description.c_str()));
557 json_object *keywordsJson = json_object_new_array();
559 json_object_array_add(keywordsJson, json_object_new_string(keyword.c_str()));
560 json_object_object_add(metadataJson,
"keywords", keywordsJson);
563 if (! version.empty())
564 json_object_object_add(metadataJson,
"version", json_object_new_string(version.c_str()));
566 json_object *dependenciesJson = json_object_new_array();
567 for (
const string &dependency : dependencies)
568 json_object_array_add(dependenciesJson, json_object_new_string(dependency.c_str()));
569 json_object_object_add(metadataJson,
"dependencies", dependenciesJson);
572 json_object_object_add(metadataJson,
"compatibility", compatibilityJson);
574 if (! isTopLevelComposition)
577 generateCompositionMetadata_Pro(nodeMetadataJson);
580 json_object *triggersJson = json_object_new_array();
585 json_object_array_add(triggersJson, t);
593 json_object *t = triggerInSubcomposition->getJsonWithinSubcomposition(node);
594 json_object_array_add(triggersJson, t);
597 json_object_object_add(nodeMetadataJson,
"triggers", triggersJson);
603 json_object_object_add(nodesJson, node->
getIdentifier().c_str(), nodeClassNameJson);
605 json_object_object_add(nodeMetadataJson,
"nodes", nodesJson);
608 json_object_object_add(metadataJson,
"node", nodeMetadataJson);
610 string metadata = json_object_to_json_string_ext(metadataJson, JSON_C_TO_STRING_PLAIN);
611 json_object_put(metadataJson);
621 void VuoCompilerBitcodeGenerator::generateShouldShowSplashWindowFunction(
bool shouldShow)
623 IntegerType *returnType = IntegerType::get(module->getContext(), 8);
624 FunctionType *functionType = FunctionType::get(returnType,
false);
625 Function *
function = Function::Create(functionType, GlobalValue::ExternalLinkage,
"vuoShouldShowSplashWindow", module);
626 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
627 Value *boolValue = ConstantInt::get(returnType, shouldShow);
628 ReturnInst::Create(module->getContext(), boolValue, block);
637 void VuoCompilerBitcodeGenerator::generateCompositionAddNodeMetadataFunction(
void)
640 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
642 Function::arg_iterator args =
function->arg_begin();
643 Value *compositionStateValue = args++;
644 compositionStateValue->setName(
"compositionState");
652 for (vector<VuoCompilerNode *>::iterator i = orderedNodes.begin(); i != orderedNodes.end(); ++i)
656 node->
generateAddMetadata(module, block, compositionStateValue, orderedTypes, compositionCreateContextForNodeFunction,
657 compositionSetPortValueFunction, compositionGetPortValueFunction, compositionFireTriggerPortEventFunction,
658 releasePortDataFunction);
661 ReturnInst::Create(module->getContext(), block);
670 void VuoCompilerBitcodeGenerator::generateCompositionCreateContextForNodeFunction(
void)
673 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, NULL);
674 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, NULL);
676 Function::arg_iterator args =
function->arg_begin();
677 Value *nodeIndexValue = args++;
678 nodeIndexValue->setName(
"nodeIndex");
681 AllocaInst *nodeContextVariable =
new AllocaInst(pointerToNodeContext, 0,
"nodeContext", initialBlock);
683 vector< pair<BasicBlock *, BasicBlock *> > blocksForIndex;
685 for (
size_t i = 0; i < orderedNodes.size(); ++i)
689 BasicBlock *block = BasicBlock::Create(module->getContext(), node->
getIdentifier(),
function, NULL);
691 new StoreInst(nodeContextValue, nodeContextVariable, block);
693 blocksForIndex.push_back(make_pair(block, block));
698 Value *nodeContextValue =
new LoadInst(nodeContextVariable,
"",
false, finalBlock);
699 ReturnInst::Create(module->getContext(), nodeContextValue, finalBlock);
710 void VuoCompilerBitcodeGenerator::generateCompositionPerformDataOnlyTransmissionsFunction(
void)
713 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
715 Function::arg_iterator args =
function->arg_begin();
716 Value *compositionStateValue = args++;
717 compositionStateValue->setName(
"compositionState");
722 generateDataOnlyTransmissionFromNode(
function, block, compositionStateValue, node,
false,
false,
false);
729 if (subcompositionFunctionSrc)
735 Value *subcompositionStateValueDst =
new BitCastInst(subcompositionStateValue, subcompositionFunctionSrc->getFunctionType()->getParamType(0),
"", block);
741 Value *falseValue = ConstantInt::get(setPublishedInputPortValueFunctionDst->getFunctionType()->getParamType(3), 0);
749 Value *inputPortNameValue = constantsCache->
get(inputPort->getClass()->getName());
752 vector<Value *> args;
753 args.push_back(subcompositionStateValueDst);
754 args.push_back(inputPortNameValue);
755 args.push_back(dataValue);
756 args.push_back(falseValue);
757 CallInst::Create(setPublishedInputPortValueFunctionDst, args,
"", block);
764 CallInst::Create(subcompositionFunctionDst, subcompositionStateValueDst,
"", block);
771 ReturnInst::Create(module->getContext(), block);
781 void VuoCompilerBitcodeGenerator::generateCompositionReleasePortDataFunction(
void)
784 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, NULL);
785 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, NULL);
787 Function::arg_iterator args =
function->arg_begin();
788 Value *portAddressAsVoidPointer = args++;
789 portAddressAsVoidPointer->setName(
"portData");
790 Value *typeIndexValue = args++;
791 typeIndexValue->setName(
"typeIndex");
793 vector< pair<BasicBlock *, BasicBlock *> > blocksForIndex;
795 for (vector<VuoCompilerType *>::iterator i = orderedTypes.begin(); i != orderedTypes.end(); ++i)
799 BasicBlock *block = BasicBlock::Create(module->getContext(), type->
getBase()->
getModuleKey(),
function, NULL);
802 blocksForIndex.push_back(make_pair(block, block));
807 ReturnInst::Create(module->getContext(), finalBlock);
813 void VuoCompilerBitcodeGenerator::generateSetInputDataFromNodeFunctionArguments(Function *
function, BasicBlock *&block, Value *compositionStateValue,
814 map<VuoPort *, size_t> indexOfParameter,
815 map<VuoPort *, size_t> indexOfEventParameter,
816 bool shouldWaitForDataOnlyDownstreamNodes,
817 bool shouldUpdateTriggers,
bool shouldSendTelemetry)
820 if (! publishedInputNode)
823 Value *publishedNodeContextValue = publishedInputNode->
generateGetContext(module, block, compositionStateValue);
826 vector<VuoCompilerInputEventPort *> inputEventPorts;
830 for (
size_t i = 0; i < publishedInputPorts.size(); ++i)
836 inputEventPorts.push_back(inputEventPort);
840 size_t dataArgIndex = indexOfParameter[ modelInputPorts[i] ];
843 inputEventPort->
generateReplaceData(module, block, publishedNodeContextValue, dataPointer);
850 generateDataOnlyTransmissionFromNode(
function, block, compositionStateValue, publishedInputNode,
851 shouldWaitForDataOnlyDownstreamNodes, shouldUpdateTriggers, shouldSendTelemetry);
855 for (
size_t i = 0; i < publishedInputPorts.size(); ++i)
860 &indexOfEventParameter :
863 auto foundIndex = indexMap->find( modelInputPorts[i] );
864 if (foundIndex != indexMap->end())
866 size_t eventArgIndex = foundIndex->second;
869 inputEventPort->
generateStoreEvent(module, block, publishedNodeContextValue, eventArg);
882 void VuoCompilerBitcodeGenerator::generateNodeEventFunction(
bool isStatefulComposition)
884 vector<VuoPort *> modelPorts;
885 modelPorts.insert(modelPorts.end(), modelInputPorts.begin(), modelInputPorts.end());
886 modelPorts.insert(modelPorts.end(), modelOutputPorts.begin(), modelOutputPorts.end());
890 vector<VuoPublishedPort *> publishedPorts;
891 publishedPorts.insert(publishedPorts.end(), publishedInputPorts.begin(), publishedInputPorts.end());
892 publishedPorts.insert(publishedPorts.end(), publishedOutputPorts.begin(), publishedOutputPorts.end());
894 map<VuoPort *, string> displayNamesForPorts;
895 map<VuoPort *, json_object *> detailsForPorts;
896 for (
size_t i = 0; i < modelPorts.size(); ++i)
898 VuoPort *modelPort = modelPorts[i];
902 bool isAllCaps =
true;
903 for (
size_t j = 0; j < portName.length(); ++j)
904 if (! isupper(portName[j]))
910 displayNamesForPorts[modelPort] = portName;
915 map<VuoPort *, string> defaultValuesForInputPorts;
916 map<VuoPort *, VuoPortClass::EventBlocking> eventBlockingForInputPorts;
917 for (
size_t i = 0; i < publishedInputPorts.size(); ++i)
922 if (! defaultValue.empty())
923 defaultValuesForInputPorts[publishedInputPort] = defaultValue;
928 map<VuoPort *, size_t> indexOfParameter;
929 map<VuoPort *, size_t> indexOfEventParameter;
932 modelInputPorts, modelOutputPorts,
933 detailsForPorts, displayNamesForPorts,
934 defaultValuesForInputPorts, eventBlockingForInputPorts,
935 indexOfParameter, indexOfEventParameter, constantsCache);
936 BasicBlock *block = &(
function->getEntryBlock());
941 ReturnInst::Create(module->getContext(), block);
947 Value *compositionStateValue =
function->arg_begin();
956 vector<VuoCompilerNode *> triggerWaitNodes = getNodesToWaitOnBeforeTransmission(trigger);
957 generateLockNodes(module, block, compositionStateValue, triggerWaitNodes, eventIdValue);
961 bool hasClaimedNodesDownstreamOfPublishedInputNode = (triggerWaitNodes.size() > 2);
962 generateSetInputDataFromNodeFunctionArguments(
function, block, compositionStateValue, indexOfParameter, indexOfEventParameter,
963 ! hasClaimedNodesDownstreamOfPublishedInputNode,
true,
true);
972 Value *triggerNodeContextValue = triggerNode->
generateGetContext(module, block, compositionStateValue);
973 Value *triggerFunctionValue = trigger->
generateLoadFunction(module, block, triggerNodeContextValue);
974 CallInst::Create(triggerFunctionValue,
"", block);
983 Value *publishedOutputNodeContext = publishedOutputNode->
generateGetContext(module, block, compositionStateValue);
984 for (
size_t i = 0; i < modelOutputPorts.size(); ++i)
986 VuoPort *modelOutputPort = modelOutputPorts[i];
992 bool hasEventParameter =
false;
993 size_t eventIndex = 0;
997 size_t index = indexOfParameter[ modelOutputPort ];
1000 Value *inputDataPointer = inputPort->
generateRetrieveData(module, block, publishedOutputNodeContext);
1005 map<VuoPort *, size_t>::iterator iter = indexOfEventParameter.find(modelOutputPort);
1006 if (iter != indexOfEventParameter.end())
1008 hasEventParameter =
true;
1009 eventIndex = iter->second;
1014 hasEventParameter =
true;
1015 eventIndex = indexOfParameter[ modelOutputPort ];
1018 if (hasEventParameter)
1023 new StoreInst(eventValue, outputArg, block);
1030 generateUnlockNodes(module, block, compositionStateValue, vector<VuoCompilerNode *>(1, publishedOutputNode));
1032 ReturnInst::Create(module->getContext(), block);
1040 void VuoCompilerBitcodeGenerator::generateNodeInstanceInitFunction(
void)
1042 vector<VuoPort *> inputPorts;
1043 if (! isTopLevelComposition)
1044 inputPorts = modelInputPorts;
1046 map<VuoPort *, size_t> indexOfParameter;
1049 inputPorts, indexOfParameter, constantsCache);
1050 BasicBlock *block = &(
function->getEntryBlock());
1052 Value *compositionStateValue =
function->arg_begin();
1054 if (! isTopLevelComposition)
1055 generateSetInputDataFromNodeFunctionArguments(
function, block, compositionStateValue, indexOfParameter, map<VuoPort *, size_t>(),
1056 false,
false,
false);
1062 BasicBlock *initBlock = NULL;
1063 BasicBlock *nextBlock = NULL;
1064 Value *replacementJsonValue = NULL;
1066 compositionStateValue, block, initBlock, nextBlock,
1067 constantsCache, replacementJsonValue);
1073 BranchInst::Create(nextBlock, initBlock);
1078 PointerType *instanceDataType =
static_cast<PointerType *
>(
function->getReturnType() );
1079 ConstantPointerNull *nullInstanceDataValue = ConstantPointerNull::get(instanceDataType);
1080 ReturnInst::Create(module->getContext(), nullInstanceDataValue, block);
1089 void VuoCompilerBitcodeGenerator::generateNodeInstanceFiniFunction(
void)
1094 BasicBlock *block = &(
function->getEntryBlock());
1096 Value *compositionStateValue =
function->arg_begin();
1102 BasicBlock *finiBlock = NULL;
1103 BasicBlock *nextBlock = NULL;
1104 Value *replacementJsonValue = NULL;
1106 compositionStateValue, block, finiBlock, nextBlock,
1107 constantsCache, replacementJsonValue);
1113 BranchInst::Create(nextBlock, finiBlock);
1118 ReturnInst::Create(module->getContext(), block);
1128 void VuoCompilerBitcodeGenerator::generateNodeInstanceTriggerStartFunction(
void)
1130 vector<VuoPort *> inputPorts;
1131 if (! isTopLevelComposition)
1132 inputPorts = modelInputPorts;
1134 map<VuoPort *, size_t> indexOfParameter;
1137 inputPorts, indexOfParameter, constantsCache);
1138 BasicBlock *block = &(
function->getEntryBlock());
1140 Value *compositionStateValue =
function->arg_begin();
1142 if (! isTopLevelComposition)
1143 generateSetInputDataFromNodeFunctionArguments(
function, block, compositionStateValue, indexOfParameter, map<VuoPort *, size_t>(),
1144 false,
false,
false);
1148 generateLockNodes(module, block, compositionStateValue, orderedNodes);
1159 generateUnlockNodes(module, block, compositionStateValue, orderedNodes);
1161 ReturnInst::Create(module->getContext(), block);
1169 void VuoCompilerBitcodeGenerator::generateNodeInstanceTriggerStopFunction(
void)
1174 BasicBlock *block = &(
function->getEntryBlock());
1176 Value *compositionStateValue =
function->arg_begin();
1179 generateLockNodes(module, block, compositionStateValue, orderedNodes);
1185 generateUnlockNodes(module, block, compositionStateValue, orderedNodes);
1187 if (isTopLevelComposition)
1194 generateLockNodes(module, block, compositionStateValue, orderedNodes);
1195 generateUnlockNodes(module, block, compositionStateValue, orderedNodes);
1198 ReturnInst::Create(module->getContext(), block);
1206 void VuoCompilerBitcodeGenerator::generateNodeInstanceTriggerUpdateFunction(
void)
1208 map<VuoPort *, size_t> indexOfParameter;
1211 modelInputPorts, indexOfParameter, constantsCache);
1212 BasicBlock *block = &(
function->getEntryBlock());
1214 Value *compositionStateValue =
function->arg_begin();
1219 ReturnInst::Create(module->getContext(), block);
1223 vector<VuoCompilerNode *> triggerWaitNodes = getNodesToWaitOnBeforeTransmission(trigger);
1224 generateLockNodes(module, block, compositionStateValue, triggerWaitNodes);
1226 bool hasClaimedNodesDownstreamOfPublishedInputNode = (triggerWaitNodes.size() > 2);
1227 generateSetInputDataFromNodeFunctionArguments(
function, block, compositionStateValue, indexOfParameter, map<VuoPort *, size_t>(),
1228 ! hasClaimedNodesDownstreamOfPublishedInputNode,
true,
true);
1230 generateUnlockNodes(module, block, compositionStateValue, triggerWaitNodes);
1232 ReturnInst::Create(module->getContext(), block);
1238 void VuoCompilerBitcodeGenerator::generateLockNodes(Module *module, BasicBlock *block,
1239 Value *compositionStateValue, vector<VuoCompilerNode *> nodes,
1240 Value *eventIdValue)
1248 if (nodes.size() == 1)
1250 size_t nodeIndex = nodes[0]->getIndexInOrderedNodes();
1257 vector<size_t> nodeIndices;
1258 std::transform(nodes.begin(), nodes.end(), std::back_inserter(nodeIndices), [](
VuoCompilerNode *n) { return n->getIndexInOrderedNodes(); });
1267 void VuoCompilerBitcodeGenerator::generateUnlockNodes(Module *module, BasicBlock *block, Value *compositionStateValue,
1268 vector<VuoCompilerNode *> nodes)
1273 if (nodes.size() == 1)
1275 size_t nodeIndex = nodes[0]->getIndexInOrderedNodes();
1280 vector<size_t> nodeIndices;
1281 std::transform(nodes.begin(), nodes.end(), std::back_inserter(nodeIndices), [](
VuoCompilerNode *n) { return n->getIndexInOrderedNodes(); });
1351 void VuoCompilerBitcodeGenerator::generateCompositionGetPortValueFunction(
void)
1355 Function::arg_iterator args =
function->arg_begin();
1356 Value *compositionStateValue = args++;
1357 compositionStateValue->setName(
"compositionState");
1358 Value *portIdentifierValue = args++;
1359 portIdentifierValue->setName(
"portIdentifier");
1360 Value *serializationTypeValue = args++;
1361 serializationTypeValue->setName(
"serializationType");
1362 Value *isThreadSafeValue = args++;
1363 isThreadSafeValue->setName(
"isThreadSafe");
1368 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, 0);
1369 PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
1371 AllocaInst *retVariable =
new AllocaInst(pointerToCharType, 0,
"ret", initialBlock);
1372 ConstantPointerNull *nullPointerToChar = ConstantPointerNull::get(pointerToCharType);
1373 new StoreInst(nullPointerToChar, retVariable,
false, initialBlock);
1381 BasicBlock *checkWaitBlock = BasicBlock::Create(module->getContext(),
"checkWait",
function, 0);
1382 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, 0);
1384 ConstantPointerNull *nullPortAddress = ConstantPointerNull::get(
static_cast<PointerType *
>(portAddressAsVoidPointer->getType()));
1385 ICmpInst *portAddressNotEqualsNull =
new ICmpInst(*initialBlock, ICmpInst::ICMP_NE, portAddressAsVoidPointer, nullPortAddress,
"");
1386 BranchInst::Create(checkWaitBlock, finalBlock, portAddressNotEqualsNull, initialBlock);
1400 BasicBlock *waitBlock = BasicBlock::Create(module->getContext(),
"wait",
function, 0);
1401 BasicBlock *checkTypeIndexBlock = BasicBlock::Create(module->getContext(),
"checkTypeIndex",
function, 0);
1402 ConstantInt *falseValue = ConstantInt::get(
static_cast<IntegerType *
>(isThreadSafeValue->getType()), 0);
1403 ICmpInst *isThreadSafeEqualsTrue =
new ICmpInst(*checkWaitBlock, ICmpInst::ICMP_NE, isThreadSafeValue, falseValue,
"");
1404 BranchInst::Create(waitBlock, checkTypeIndexBlock, isThreadSafeEqualsTrue, checkWaitBlock);
1408 BranchInst::Create(checkTypeIndexBlock, waitBlock);
1431 vector< pair<BasicBlock *, BasicBlock *> > blocksForIndex;
1432 for (
size_t i = 0; i < orderedTypes.size(); ++i)
1439 BasicBlock *checkSummaryBlock = BasicBlock::Create(module->getContext(), typeName +
"_checkSummary",
function, 0);
1440 BasicBlock *summaryBlock = BasicBlock::Create(module->getContext(), typeName +
"_summary",
function, 0);
1441 BasicBlock *checkStringBlock = NULL;
1442 BasicBlock *stringBlock = BasicBlock::Create(module->getContext(), typeName +
"_string",
function, 0);
1443 BasicBlock *interprocessBlock = NULL;
1444 BasicBlock *typeFinalBlock = BasicBlock::Create(module->getContext(), typeName +
"_final",
function, 0);
1446 BasicBlock *firstStringBlock = NULL;
1447 if (hasInterprocess)
1449 checkStringBlock = BasicBlock::Create(module->getContext(), typeName +
"_checkString",
function, 0);
1450 interprocessBlock = BasicBlock::Create(module->getContext(), typeName +
"_interprocess",
function, 0);
1451 firstStringBlock = checkStringBlock;
1455 firstStringBlock = stringBlock;
1458 ConstantInt *zeroValue = ConstantInt::get(
static_cast<IntegerType *
>(serializationTypeValue->getType()), 0);
1459 ICmpInst *serializationTypeEqualsZero =
new ICmpInst(*checkSummaryBlock, ICmpInst::ICMP_EQ, serializationTypeValue, zeroValue,
"");
1460 BranchInst::Create(summaryBlock, firstStringBlock, serializationTypeEqualsZero, checkSummaryBlock);
1463 new StoreInst(summaryValue, retVariable, summaryBlock);
1464 BranchInst::Create(typeFinalBlock, summaryBlock);
1466 if (hasInterprocess)
1468 ConstantInt *oneValue = ConstantInt::get(
static_cast<IntegerType *
>(serializationTypeValue->getType()), 1);
1469 ICmpInst *serializationTypeEqualsOne =
new ICmpInst(*checkStringBlock, ICmpInst::ICMP_EQ, serializationTypeValue, oneValue,
"");
1470 BranchInst::Create(stringBlock, interprocessBlock, serializationTypeEqualsOne, checkStringBlock);
1474 new StoreInst(stringValue, retVariable, stringBlock);
1475 BranchInst::Create(typeFinalBlock, stringBlock);
1477 if (hasInterprocess)
1480 new StoreInst(interprocessValue, retVariable, interprocessBlock);
1481 BranchInst::Create(typeFinalBlock, interprocessBlock);
1484 blocksForIndex.push_back( make_pair(checkSummaryBlock, typeFinalBlock) );
1487 BasicBlock *checkSignalBlock = BasicBlock::Create(module->getContext(),
"checkSignal",
function, 0);
1494 BasicBlock *signalBlock = BasicBlock::Create(module->getContext(),
"signal",
function, 0);
1495 BranchInst::Create(signalBlock, finalBlock, isThreadSafeEqualsTrue, checkSignalBlock);
1498 BranchInst::Create(finalBlock, signalBlock);
1503 LoadInst *retValue =
new LoadInst(retVariable,
"",
false, finalBlock);
1504 ReturnInst::Create(module->getContext(), retValue, finalBlock);
1585 void VuoCompilerBitcodeGenerator::generateCompositionSetPortValueFunction(
void)
1589 Function::arg_iterator args =
function->arg_begin();
1590 Value *compositionStateValue = args++;
1591 compositionStateValue->setName(
"compositionState");
1592 Value *portIdentifierValue = args++;
1593 portIdentifierValue->setName(
"portIdentifier");
1594 Value *valueAsStringValue = args++;
1595 valueAsStringValue->setName(
"valueAsString");
1596 Value *isThreadSafeValue = args++;
1597 isThreadSafeValue->setName(
"isThreadSafe");
1598 Value *shouldUpdateTriggersValue = args++;
1599 shouldUpdateTriggersValue->setName(
"shouldUpdateTriggers");
1600 Value *shouldSendTelemetryValue = args++;
1601 shouldSendTelemetryValue->setName(
"shouldSendTelemetry");
1602 Value *hasOldValue = args++;
1603 hasOldValue->setName(
"hasOldValue");
1604 Value *hasNewValue = args++;
1605 hasNewValue->setName(
"hasNewValue");
1610 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, 0);
1615 BasicBlock *checkWaitBlock = BasicBlock::Create(module->getContext(),
"checkWait",
function, 0);
1616 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, 0);
1618 ConstantPointerNull *nullPortAddress = ConstantPointerNull::get(
static_cast<PointerType *
>(portAddressAsVoidPointer->getType()));
1619 ICmpInst *portAddressNotEqualsNull =
new ICmpInst(*initialBlock, ICmpInst::ICMP_NE, portAddressAsVoidPointer, nullPortAddress,
"");
1620 BranchInst::Create(checkWaitBlock, finalBlock, portAddressNotEqualsNull, initialBlock);
1630 PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
1631 AllocaInst *summaryVariable =
new AllocaInst(pointerToCharType, 0,
"summary", checkWaitBlock);
1632 ConstantPointerNull *nullSummary = ConstantPointerNull::get(pointerToCharType);
1633 new StoreInst(nullSummary, summaryVariable,
false, checkWaitBlock);
1641 BasicBlock *waitBlock = BasicBlock::Create(module->getContext(),
"wait",
function, 0);
1642 BasicBlock *checkTypeIndexBlock = BasicBlock::Create(module->getContext(),
"checkTypeIndex",
function, 0);
1643 ConstantInt *falseArgValue = ConstantInt::get(
static_cast<IntegerType *
>(isThreadSafeValue->getType()), 0);
1644 ICmpInst *isThreadSafeEqualsTrue =
new ICmpInst(*checkWaitBlock, ICmpInst::ICMP_NE, isThreadSafeValue, falseArgValue,
"");
1645 BranchInst::Create(waitBlock, checkTypeIndexBlock, isThreadSafeEqualsTrue, checkWaitBlock);
1649 BranchInst::Create(checkTypeIndexBlock, waitBlock);
1681 ICmpInst *hasOldValueIsTrue =
new ICmpInst(*checkTypeIndexBlock, ICmpInst::ICMP_NE, hasOldValue, falseArgValue,
"");
1682 ICmpInst *hasNewValueIsTrue =
new ICmpInst(*checkTypeIndexBlock, ICmpInst::ICMP_NE, hasNewValue, falseArgValue,
"");
1683 ICmpInst *shouldSendTelemetryIsTrue =
new ICmpInst(*checkTypeIndexBlock, ICmpInst::ICMP_NE, shouldSendTelemetryValue, falseArgValue,
"");
1685 vector< pair<BasicBlock *, BasicBlock *> > blocksForTypeIndex;
1686 for (
size_t i = 0; i < orderedTypes.size(); ++i)
1690 BasicBlock *typeInitialBlock = BasicBlock::Create(module->getContext(), type->
getBase()->
getModuleKey() +
"_initial",
function, 0);
1691 BasicBlock *makeNewValueBlock = BasicBlock::Create(module->getContext(),
"makeNewValue",
function, 0);
1692 BasicBlock *checkOldValueBlock = BasicBlock::Create(module->getContext(),
"checkOldValue",
function, 0);
1693 BasicBlock *releaseOldValueBlock = BasicBlock::Create(module->getContext(),
"releaseOldValue",
function, 0);
1694 BasicBlock *checkNewValueBlock = BasicBlock::Create(module->getContext(),
"checkNewValue",
function, 0);
1695 BasicBlock *setNewValueBlock = BasicBlock::Create(module->getContext(),
"setNewValue",
function, 0);
1696 BasicBlock *summaryBlock = BasicBlock::Create(module->getContext(),
"summary",
function, 0);
1697 BasicBlock *typeFinalBlock = BasicBlock::Create(module->getContext(), type->
getBase()->
getModuleKey() +
"_final",
function, 0);
1699 Value *portAddress = type->
convertToPortData(typeInitialBlock, portAddressAsVoidPointer);
1700 AllocaInst *newPortValueAddress =
new AllocaInst(cast<PointerType>(portAddress->getType())->getElementType(), 0,
"newPortValueAddress", typeInitialBlock);
1702 BranchInst::Create(makeNewValueBlock, checkOldValueBlock, hasNewValueIsTrue, typeInitialBlock);
1707 BranchInst::Create(checkOldValueBlock, makeNewValueBlock);
1709 BranchInst::Create(releaseOldValueBlock, checkNewValueBlock, hasOldValueIsTrue, checkOldValueBlock);
1712 BranchInst::Create(checkNewValueBlock, releaseOldValueBlock);
1714 BranchInst::Create(setNewValueBlock, typeFinalBlock, hasNewValueIsTrue, checkNewValueBlock);
1717 BranchInst::Create(summaryBlock, typeFinalBlock, shouldSendTelemetryIsTrue, setNewValueBlock);
1720 new StoreInst(summaryValue, summaryVariable,
false, summaryBlock);
1721 BranchInst::Create(typeFinalBlock, summaryBlock);
1723 blocksForTypeIndex.push_back( make_pair(typeInitialBlock, typeFinalBlock) );
1726 BasicBlock *checkUpdateBlock = BasicBlock::Create(module->getContext(),
"checkUpdate",
function, 0);
1739 Constant *zeroValue = ConstantInt::get(shouldUpdateTriggersValue->getType(), 0);
1740 ICmpInst *shouldUpdateTriggersIsTrue =
new ICmpInst(*checkUpdateBlock, ICmpInst::ICMP_NE, shouldUpdateTriggersValue, zeroValue,
"");
1741 BasicBlock *updateTriggersBlock = BasicBlock::Create(module->getContext(),
"updateTriggers",
function, 0);
1742 BasicBlock *checkSendBlock = BasicBlock::Create(module->getContext(),
"checkSend",
function, 0);
1743 BranchInst::Create(updateTriggersBlock, checkSendBlock, shouldUpdateTriggersIsTrue, checkUpdateBlock);
1745 vector< pair<BasicBlock *, BasicBlock *> > blocksForNodeIndex;
1746 for (
size_t i = 0; i < orderedNodes.size(); ++i)
1749 BasicBlock *currentBlock = BasicBlock::Create(module->getContext(), node->
getIdentifier(),
function, 0);
1750 BasicBlock *origCurrentBlock = currentBlock;
1754 generateDataOnlyTransmissionFromNode(
function, currentBlock, compositionStateValue, node,
true,
true,
true);
1756 blocksForNodeIndex.push_back( make_pair(origCurrentBlock, currentBlock) );
1759 BasicBlock *checkSignalBlock = BasicBlock::Create(module->getContext(),
"checkSignal",
function, 0);
1766 BasicBlock *signalBlock = BasicBlock::Create(module->getContext(),
"signal",
function, 0);
1767 BranchInst::Create(signalBlock, checkSendBlock, isThreadSafeEqualsTrue, checkSignalBlock);
1770 BranchInst::Create(checkSendBlock, signalBlock);
1779 BasicBlock *sendBlock = BasicBlock::Create(module->getContext(),
"send",
function, 0);
1780 BranchInst::Create(sendBlock, finalBlock, shouldSendTelemetryIsTrue, checkSendBlock);
1782 Value *summaryValue =
new LoadInst(summaryVariable,
"",
false, sendBlock);
1785 false,
true, summaryValue);
1788 BranchInst::Create(finalBlock, sendBlock);
1790 ReturnInst::Create(module->getContext(), finalBlock);
1798 void VuoCompilerBitcodeGenerator::generateSetInputPortValueFunction(
void)
1801 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
1803 Function::arg_iterator args =
function->arg_begin();
1804 Value *portIdentifierValue = args++;
1805 portIdentifierValue->setName(
"portIdentifier");
1806 Value *valueAsStringValue = args++;
1807 valueAsStringValue->setName(
"valueAsString");
1815 Value *trueValue = ConstantInt::get(compositionSetPortValueFunction->getFunctionType()->getParamType(3), 1);
1817 vector<Value *> compositionArgs;
1818 compositionArgs.push_back(compositionStateValue);
1819 compositionArgs.push_back(portIdentifierValue);
1820 compositionArgs.push_back(valueAsStringValue);
1821 compositionArgs.push_back(trueValue);
1822 compositionArgs.push_back(trueValue);
1823 compositionArgs.push_back(trueValue);
1824 compositionArgs.push_back(trueValue);
1825 compositionArgs.push_back(trueValue);
1826 CallInst::Create(compositionSetPortValueFunction, compositionArgs,
"", block);
1830 ReturnInst::Create(module->getContext(), block);
1852 void VuoCompilerBitcodeGenerator::generateCompositionFireTriggerPortEventFunction(
void)
1856 Function::arg_iterator args =
function->arg_begin();
1857 Value *compositionStateValue = args++;
1858 compositionStateValue->setName(
"compositionState");
1859 Value *portIdentifierValue = args++;
1860 portIdentifierValue->setName(
"portIdentifier");
1862 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, 0);
1864 map<string, pair<BasicBlock *, BasicBlock *> > blocksForString;
1871 BasicBlock *currentBlock = BasicBlock::Create(module->getContext(), currentPortIdentifier,
function, 0);
1872 BasicBlock *origCurrentBlock = currentBlock;
1874 Value *nodeContextValue = triggerNode->
generateGetContext(module, currentBlock, compositionStateValue);
1875 Value *triggerFunctionValue = trigger->
generateLoadFunction(module, currentBlock, nodeContextValue);
1877 vector<Value *> triggerArgs;
1881 generateLockNodes(module, currentBlock, compositionStateValue, vector<VuoCompilerNode *>(1, triggerNode));
1889 CallInst *call = CallInst::Create(triggerFunctionValue, triggerArgs,
"", currentBlock);
1895 generateUnlockNodes(module, currentBlock, compositionStateValue, vector<VuoCompilerNode *>(1, triggerNode));
1898 blocksForString[currentPortIdentifier] = make_pair(origCurrentBlock, currentBlock);
1901 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, 0);
1903 ReturnInst::Create(module->getContext(), finalBlock);
1923 void VuoCompilerBitcodeGenerator::generateGetPublishedPortCountFunction(
bool input)
1926 string functionName;
1930 functionName =
"getPublishedInputPortCount";
1935 functionName =
"getPublishedOutputPortCount";
1938 Function *
function = module->getFunction(functionName);
1941 vector<Type *> functionParams;
1942 FunctionType *functionType = FunctionType::get(IntegerType::get(module->getContext(), 32), functionParams,
false);
1943 function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1946 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, 0);
1947 ConstantInt *countConstant = ConstantInt::get(module->getContext(), APInt(32, count));
1948 ReturnInst::Create(module->getContext(), countConstant, block);
1966 void VuoCompilerBitcodeGenerator::generateGetPublishedPortNamesFunction(
bool input)
1968 string functionName;
1969 vector<VuoPublishedPort *> publishedPorts;
1972 functionName =
"getPublishedInputPortNames";
1977 functionName =
"getPublishedOutputPortNames";
1981 vector<string> names;
1982 for (vector<VuoPublishedPort *>::iterator i = publishedPorts.begin(); i != publishedPorts.end(); ++i)
1984 names.push_back( (*i)->getClass()->getName() );
1987 generateFunctionReturningStringArray(functionName, names);
2005 void VuoCompilerBitcodeGenerator::generateGetPublishedPortTypesFunction(
bool input)
2007 string functionName;
2008 vector<VuoPublishedPort *> publishedPorts;
2011 functionName =
"getPublishedInputPortTypes";
2016 functionName =
"getPublishedOutputPortTypes";
2020 vector<string> types;
2021 for (vector<VuoPublishedPort *>::iterator i = publishedPorts.begin(); i != publishedPorts.end(); ++i)
2027 types.push_back(typeName);
2030 generateFunctionReturningStringArray(functionName, types);
2048 void VuoCompilerBitcodeGenerator::generateGetPublishedPortDetailsFunction(
bool input)
2050 string functionName;
2051 vector<VuoPublishedPort *> publishedPorts;
2054 functionName =
"getPublishedInputPortDetails";
2059 functionName =
"getPublishedOutputPortDetails";
2063 vector<string> details;
2064 for (vector<VuoPublishedPort *>::iterator i = publishedPorts.begin(); i != publishedPorts.end(); ++i)
2069 string detailsSerialized = json_object_to_json_string_ext(detailsObj, JSON_C_TO_STRING_PLAIN);
2070 details.push_back(detailsSerialized);
2072 json_object_put(detailsObj);
2075 generateFunctionReturningStringArray(functionName, details);
2084 void VuoCompilerBitcodeGenerator::generateFunctionReturningStringArray(
string functionName, vector<string> stringValues)
2086 Function *
function = module->getFunction(functionName);
2089 PointerType *pointerToChar = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2090 PointerType *pointerToPointerToChar = PointerType::get(pointerToChar, 0);
2091 vector<Type *> functionParams;
2092 FunctionType *functionType = FunctionType::get(pointerToPointerToChar, functionParams,
false);
2093 function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
2096 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, 0);
2099 ReturnInst::Create(module->getContext(), stringArrayGlobalPointer, block);
2111 void VuoCompilerBitcodeGenerator::generateFirePublishedInputPortEventFunction(
void)
2113 string functionName =
"firePublishedInputPortEvent";
2114 Function *
function = module->getFunction(functionName);
2115 PointerType *pointerToChar = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2118 PointerType *pointerToPointerToChar = PointerType::get(pointerToChar, 0);
2119 Type *countType = IntegerType::get(module->getContext(), 32);
2121 vector<Type *> functionParams;
2122 functionParams.push_back(pointerToPointerToChar);
2123 functionParams.push_back(countType);
2124 FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams,
false);
2125 function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
2128 Function::arg_iterator args =
function->arg_begin();
2129 Value *namesValue = args++;
2130 namesValue->setName(
"names");
2131 Value *countValue = args++;
2132 countValue->setName(
"count");
2134 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, 0);
2139 ReturnInst::Create(module->getContext(), initialBlock);
2148 compositionIdentifierValue);
2157 vector<VuoCompilerNode *> triggerWaitNodes = getNodesToWaitOnBeforeTransmission(trigger);
2160 if (find(triggerWaitNodes.begin(), triggerWaitNodes.end(), publishedOutputNode) == triggerWaitNodes.end())
2161 triggerWaitNodes.push_back(publishedOutputNode);
2163 generateLockNodes(module, initialBlock, compositionStateValue, triggerWaitNodes, eventIdValue);
2188 Value *publishedInputNodeContextValue = publishedInputNode->
generateGetContext(module, initialBlock, compositionStateValue);
2190 Value *zeroValue = ConstantInt::get(
static_cast<IntegerType *
>(countValue->getType()), 0);
2191 AllocaInst *iterVariable =
new AllocaInst(countValue->getType(), 0,
"i", initialBlock);
2192 new StoreInst(zeroValue, iterVariable,
false, initialBlock);
2194 BasicBlock *loopConditionBlock = BasicBlock::Create(module->getContext(),
"loopCondition",
function, 0);
2195 BasicBlock *loopBeginBlock = BasicBlock::Create(module->getContext(),
"loopBegin",
function, 0);
2196 BasicBlock *loopEndBlock = BasicBlock::Create(module->getContext(),
"loopEnd",
function, 0);
2197 BasicBlock *fireBlock = BasicBlock::Create(module->getContext(),
"fire",
function, 0);
2199 BranchInst::Create(loopConditionBlock, initialBlock);
2201 Value *iterValue =
new LoadInst(iterVariable,
"",
false, loopConditionBlock);
2202 ICmpInst *iterLessThanCount =
new ICmpInst(*loopConditionBlock, ICmpInst::ICMP_ULT, iterValue, countValue,
"");
2203 BranchInst::Create(loopBeginBlock, fireBlock, iterLessThanCount, loopConditionBlock);
2207 map<string, pair<BasicBlock *, BasicBlock *> > blocksForString;
2210 for (
size_t i = 0; i < publishedInputPorts.size(); ++i)
2212 string currentName = publishedInputPorts[i]->getClass()->getName();
2213 BasicBlock *currentBlock = BasicBlock::Create(module->getContext(), currentName,
function, 0);
2217 inputEventPort->
generateStoreEvent(module, currentBlock, publishedInputNodeContextValue,
true);
2219 blocksForString[currentName] = make_pair(currentBlock, currentBlock);
2224 Value *oneValue = ConstantInt::get(
static_cast<IntegerType *
>(countValue->getType()), 1);
2225 Value *iterPlusOneValue = BinaryOperator::Create(Instruction::Add, iterValue, oneValue,
"", loopEndBlock);
2226 new StoreInst(iterPlusOneValue, iterVariable,
false, loopEndBlock);
2228 BranchInst::Create(loopConditionBlock, loopEndBlock);
2232 Value *triggerNodeContextValue = triggerNode->
generateGetContext(module, fireBlock, compositionStateValue);
2233 Value *triggerFunctionValue = trigger->
generateLoadFunction(module, fireBlock, triggerNodeContextValue);
2234 CallInst::Create(triggerFunctionValue,
"", fireBlock);
2238 ReturnInst::Create(module->getContext(), fireBlock);
2280 void VuoCompilerBitcodeGenerator::generateGetPublishedPortValueFunction(
bool input)
2282 Function *
function = (input ?
2286 Function::arg_iterator args =
function->arg_begin();
2287 Value *portIdentifierValue = args++;
2288 portIdentifierValue->setName(
"portIdentifier");
2289 Value *shouldUseInterprocessSerializationValue = args++;
2290 shouldUseInterprocessSerializationValue->setName(
"shouldUseInterprocessSerialization");
2292 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, 0);
2293 PointerType *pointerToChar = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2294 AllocaInst *retVariable =
new AllocaInst(pointerToChar, 0,
"ret", initialBlock);
2295 ConstantPointerNull *nullValue = ConstantPointerNull::get(pointerToChar);
2296 new StoreInst(nullValue, retVariable,
false, initialBlock);
2301 compositionIdentifierValue);
2303 vector<VuoPort *> inputPortsOnPublishedNode;
2307 for (
size_t i = 0; i < publishedPorts.size(); ++i)
2310 inputPortsOnPublishedNode.push_back(port);
2316 for (
size_t i = 0; i < publishedPorts.size(); ++i)
2319 inputPortsOnPublishedNode.push_back(port);
2323 map<string, pair<BasicBlock *, BasicBlock *> > blocksForString;
2324 for (
VuoPort *port : inputPortsOnPublishedNode)
2327 BasicBlock *currentBlock = BasicBlock::Create(module->getContext(), currentName,
function, 0);
2330 Constant *currentIdentifierValue = constantsCache->
get(currentIdentifier);
2333 currentIdentifierValue, shouldUseInterprocessSerializationValue);
2334 new StoreInst(retValue, retVariable, currentBlock);
2336 blocksForString[currentName] = make_pair(currentBlock, currentBlock);
2339 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, 0);
2343 LoadInst *retValue =
new LoadInst(retVariable,
"",
false, finalBlock);
2344 ReturnInst::Create(module->getContext(), retValue, finalBlock);
2360 void VuoCompilerBitcodeGenerator::generateCompositionSetPublishedInputPortValueFunction(
void)
2364 Function::arg_iterator args =
function->arg_begin();
2365 Value *compositionStateValue = args++;
2366 compositionStateValue->setName(
"compositionState");
2367 Value *publishedInputPortNameValue = args++;
2368 publishedInputPortNameValue->setName(
"publishedInputPortName");
2369 Value *valueAsStringValue = args++;
2370 valueAsStringValue->setName(
"valueAsString");
2371 Value *isCompositionRunningValue = args++;
2372 isCompositionRunningValue->setName(
"isCompositionRunning");
2374 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, 0);
2379 ReturnInst::Create(module->getContext(), initialBlock);
2385 PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2386 AllocaInst *inputPortIdentifierVariable =
new AllocaInst(pointerToCharType, 0,
"inputPortIdentifier", initialBlock);
2387 ConstantPointerNull *nullInputPortIdentifier = ConstantPointerNull::get(pointerToCharType);
2388 new StoreInst(nullInputPortIdentifier, inputPortIdentifierVariable,
false, initialBlock);
2396 map<string, pair<BasicBlock *, BasicBlock *> > blocksForString;
2398 for (
size_t i = 0; i < publishedInputPorts.size(); ++i)
2400 string currPublishedInputPortName = publishedInputPorts[i]->getClass()->getName();
2401 BasicBlock *currBlock = BasicBlock::Create(module->getContext(), currPublishedInputPortName,
function, 0);
2405 Value *inputPortIdentifierValue = constantsCache->
get(inputPortIdentifier);
2407 new StoreInst(inputPortIdentifierValue, inputPortIdentifierVariable,
false, currBlock);
2409 blocksForString[currPublishedInputPortName] = make_pair(currBlock, currBlock);
2412 BasicBlock *checkBlock = BasicBlock::Create(module->getContext(),
"check",
function, 0);
2413 BasicBlock *scheduleBlock = BasicBlock::Create(module->getContext(),
"schedule",
function, 0);
2414 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, 0);
2421 Value *inputPortIdentifierValue =
new LoadInst(inputPortIdentifierVariable,
"",
false, checkBlock);
2422 ICmpInst *portIdentifierNotEqualsNull =
new ICmpInst(*checkBlock, ICmpInst::ICMP_NE, inputPortIdentifierValue, nullInputPortIdentifier,
"");
2423 BranchInst::Create(scheduleBlock, finalBlock, portIdentifierNotEqualsNull, checkBlock);
2432 inputPortIdentifierValue, valueAsStringValue,
2433 isCompositionRunningValue);
2439 Value *nodeContextValue = triggerNode->
generateGetContext(module, scheduleBlock, compositionStateValue);
2443 workerFunctionName, contextValue);
2445 BranchInst::Create(finalBlock, scheduleBlock);
2446 ReturnInst::Create(module->getContext(), finalBlock);
2453 Function::arg_iterator workerArgs = workerFunction->arg_begin();
2454 Value *contextValueInWorker = workerArgs++;
2455 contextValueInWorker->setName(
"context");
2457 BasicBlock *workerBlock = BasicBlock::Create(module->getContext(),
"", workerFunction, 0);
2464 Type *voidPointerType = contextValueInWorker->getType();
2465 Type *voidPointerPointerType = PointerType::get(voidPointerType, 0);
2467 Type *boolType = compositionSetPortValueFunction->getFunctionType()->getParamType(3);
2469 Value *contextValueAsVoidPointerArray =
new BitCastInst(contextValueInWorker, voidPointerPointerType,
"", workerBlock);
2471 Value *compositionStateValueInWorker =
new BitCastInst(compositionStateAsVoidPointer, compositionStatePointerType,
"", workerBlock);
2474 Value *inputPortIdentifierValueInWorker =
new BitCastInst(inputPortIdentifierAsVoidPointer, pointerToCharType,
"", workerBlock);
2477 Value *valueAsStringValueInWorker =
new BitCastInst(valueAsStringValueAsVoidPointer, pointerToCharType,
"", workerBlock);
2480 Value *isCompositionRunningValueInWorker =
new PtrToIntInst(isCompositionRunningValueAsVoidPointer, boolType,
"", workerBlock);
2489 Value *trueValue = ConstantInt::get(boolType, 1);
2491 vector<Value *> setValueArgs;
2492 setValueArgs.push_back(compositionStateValueInWorker);
2493 setValueArgs.push_back(inputPortIdentifierValueInWorker);
2494 setValueArgs.push_back(valueAsStringValueInWorker);
2495 setValueArgs.push_back(isCompositionRunningValueInWorker);
2496 setValueArgs.push_back(isCompositionRunningValueInWorker);
2497 setValueArgs.push_back(isCompositionRunningValueInWorker);
2498 setValueArgs.push_back(trueValue);
2499 setValueArgs.push_back(trueValue);
2500 CallInst::Create(compositionSetPortValueFunction, setValueArgs,
"", workerBlock);
2502 ReturnInst::Create(module->getContext(), workerBlock);
2512 void VuoCompilerBitcodeGenerator::generateSetPublishedInputPortValueFunction(
void)
2516 Function::arg_iterator args =
function->arg_begin();
2517 Value *publishedInputPortNameValue = args++;
2518 publishedInputPortNameValue->setName(
"publishedInputPortName");
2519 Value *valueAsStringValue = args++;
2520 valueAsStringValue->setName(
"valueAsString");
2522 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
2529 Value *trueValue = ConstantInt::get(compositionFunction->getFunctionType()->getParamType(3), 1);
2531 vector<Value *> compositionArgs;
2532 compositionArgs.push_back(compositionStateValue);
2533 compositionArgs.push_back(publishedInputPortNameValue);
2534 compositionArgs.push_back(valueAsStringValue);
2535 compositionArgs.push_back(trueValue);
2536 CallInst::Create(compositionFunction, compositionArgs,
"", block);
2540 ReturnInst::Create(module->getContext(), block);
2547 void VuoCompilerBitcodeGenerator::generateTransmissionFromOutputPort(Function *
function, BasicBlock *¤tBlock,
2548 Value *compositionStateValue,
2550 Value *eventValue, Value *dataPointer,
2551 bool requiresEvent,
bool shouldSendTelemetry)
2553 IntegerType *boolType = IntegerType::get(module->getContext(), 1);
2554 PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2558 Constant *trueValue = ConstantInt::get(boolType, 1);
2559 Constant *falseValue = ConstantInt::get(boolType, 0);
2560 Constant *transmittedEventValue = (requiresEvent ? trueValue : falseValue);
2563 AllocaInst *dataSummaryVariable =
new AllocaInst(pointerToCharType, 0,
"dataSummary", currentBlock);
2564 new StoreInst(ConstantPointerNull::get(pointerToCharType), dataSummaryVariable, currentBlock);
2566 map<VuoCompilerPort *, ICmpInst *> shouldSummarizeInput;
2567 if (shouldSendTelemetry)
2570 AllocaInst *sentDataVariable =
new AllocaInst(boolType, 0,
"sentData", currentBlock);
2571 new StoreInst(falseValue, sentDataVariable, currentBlock);
2573 for (set<VuoCompilerCable *>::iterator i = outgoingCables.begin(); i != outgoingCables.end(); ++i)
2580 compositionStateValue,
2582 shouldSummarizeInput[inputPort] = shouldSendDataForInput;
2589 compositionStateValue,
2592 for (set<VuoCompilerCable *>::iterator i = outgoingCables.begin(); i != outgoingCables.end(); ++i)
2599 shouldSummarizeOutput = BinaryOperator::Create(Instruction::Or, shouldSummarizeOutput, shouldSummarizeInput[inputPort],
"", currentBlock);
2603 BasicBlock *summaryBlock = BasicBlock::Create(module->getContext(),
"outputSummary",
function, NULL);
2604 BasicBlock *sendOutputBlock = BasicBlock::Create(module->getContext(),
"sendOutput",
function, NULL);
2605 BranchInst::Create(summaryBlock, sendOutputBlock, shouldSummarizeOutput, currentBlock);
2608 new StoreInst(trueValue, sentDataVariable, summaryBlock);
2613 new StoreInst(dataSummaryValue, dataSummaryVariable, summaryBlock);
2615 BranchInst::Create(sendOutputBlock, summaryBlock);
2616 currentBlock = sendOutputBlock;
2621 Value *sentDataValue =
new LoadInst(sentDataVariable,
"",
false, currentBlock);
2622 Value *dataSummaryValue =
new LoadInst(dataSummaryVariable,
"",
false, currentBlock);
2624 Constant *outputPortIdentifierValue = constantsCache->
get(outputPort->
getIdentifier());
2627 transmittedEventValue, sentDataValue, dataSummaryValue);
2633 BasicBlock *transmissionBlock = NULL;
2634 BasicBlock *noTransmissionBlock = NULL;
2635 if (alwaysTransmitsEvent)
2637 transmissionBlock = currentBlock;
2641 transmissionBlock = BasicBlock::Create(module->getContext(),
"transmission",
function, NULL);
2642 noTransmissionBlock = BasicBlock::Create(module->getContext(),
"noTransmission",
function, NULL);
2644 ConstantInt *zeroValue = ConstantInt::get(
static_cast<IntegerType *
>(eventValue->getType()), 0);
2645 ICmpInst *eventValueIsTrue =
new ICmpInst(*currentBlock, ICmpInst::ICMP_NE, eventValue, zeroValue,
"");
2646 BranchInst::Create(transmissionBlock, noTransmissionBlock, eventValueIsTrue, currentBlock);
2650 for (set<VuoCompilerCable *>::iterator i = outgoingCables.begin(); i != outgoingCables.end(); ++i)
2655 Value *inputNodeContextValue = inputNode->
generateGetContext(module, transmissionBlock, compositionStateValue);
2657 Value *inputPortContextValue = inputPort->
generateGetPortContext(module, transmissionBlock, inputNodeContextValue);
2659 Value *transmittedDataPointer = (cable->
carriesData() ? dataPointer : NULL);
2661 cable->
generateTransmission(module, transmissionBlock, inputNodeContextValue, inputPortContextValue, transmittedDataPointer, requiresEvent);
2666 AllocaInst *inputDataSummaryVariable =
new AllocaInst(pointerToCharType, 0,
"inputDataSummary", transmissionBlock);
2667 new StoreInst(ConstantPointerNull::get(pointerToCharType), inputDataSummaryVariable, transmissionBlock);
2670 AllocaInst *receivedDataVariable =
new AllocaInst(boolType, 0,
"receivedData", transmissionBlock);
2671 new StoreInst(falseValue, receivedDataVariable, transmissionBlock);
2676 BasicBlock *summaryBlock = BasicBlock::Create(module->getContext(),
"inputSummary",
function, NULL);
2677 BasicBlock *sendInputBlock = BasicBlock::Create(module->getContext(),
"sendInput",
function, NULL);
2678 BranchInst::Create(summaryBlock, sendInputBlock, shouldSummarizeInput[inputPort], transmissionBlock);
2680 Value *inputDataSummaryValue;
2681 if (transmittedDataPointer)
2684 new StoreInst(trueValue, receivedDataVariable, summaryBlock);
2687 inputDataSummaryValue =
new LoadInst(dataSummaryVariable,
"",
false, summaryBlock);
2695 new StoreInst(inputDataSummaryValue, inputDataSummaryVariable, summaryBlock);
2697 BranchInst::Create(sendInputBlock, summaryBlock);
2698 transmissionBlock = sendInputBlock;
2701 Value *receivedDataValue =
new LoadInst(receivedDataVariable,
"",
false, transmissionBlock);
2702 Value *inputDataSummaryValue =
new LoadInst(inputDataSummaryVariable,
"",
false, transmissionBlock);
2704 Constant *inputPortIdentifierValue = constantsCache->
get(inputPort->
getIdentifier());
2707 transmittedEventValue, receivedDataValue, inputDataSummaryValue);
2709 if (inputDataType && ! transmittedDataPointer)
2717 if (alwaysTransmitsEvent)
2719 currentBlock = transmissionBlock;
2723 BranchInst::Create(noTransmissionBlock, transmissionBlock);
2724 currentBlock = noTransmissionBlock;
2727 if (shouldSendTelemetry && dataPointer)
2731 LoadInst *dataSummaryValue =
new LoadInst(dataSummaryVariable,
"",
false, currentBlock);
2732 CallInst::Create(freeFunction, dataSummaryValue,
"", currentBlock);
2740 void VuoCompilerBitcodeGenerator::generateTransmissionFromNode(Function *
function, BasicBlock *¤tBlock,
2741 Value *compositionStateValue, Value *nodeContextValue,
2745 for (vector<VuoPort *>::iterator i = outputPorts.begin(); i != outputPorts.end(); ++i)
2749 if (! outputEventPort)
2752 Value *portContextValue = outputEventPort->
generateGetPortContext(module, currentBlock, nodeContextValue);
2753 Value *outputEventValue = outputEventPort->
generateLoadEvent(module, currentBlock, nodeContextValue, portContextValue);
2755 BasicBlock *telemetryBlock = NULL;
2756 BasicBlock *noTelemetryBlock = NULL;
2759 telemetryBlock = BasicBlock::Create(module->getContext(),
"",
function, NULL);
2760 noTelemetryBlock = BasicBlock::Create(module->getContext(),
"",
function, NULL);
2763 ConstantInt *zeroValue = ConstantInt::get(
static_cast<IntegerType *
>(outputEventValue->getType()), 0);
2764 ICmpInst *eventValueIsTrue =
new ICmpInst(*currentBlock, ICmpInst::ICMP_NE, outputEventValue, zeroValue,
"");
2765 BranchInst::Create(telemetryBlock, noTelemetryBlock, eventValueIsTrue, currentBlock);
2769 telemetryBlock = currentBlock;
2774 Value *outputDataPointer = (outputData ?
2775 outputEventPort->
generateRetrieveData(module, telemetryBlock, nodeContextValue, portContextValue) :
2777 generateTransmissionFromOutputPort(
function, telemetryBlock, compositionStateValue,
2778 node, outputEventPort, outputEventValue, outputDataPointer, requiresEvent, shouldSendTelemetry);
2782 BranchInst::Create(noTelemetryBlock, telemetryBlock);
2783 currentBlock = noTelemetryBlock;
2787 currentBlock = telemetryBlock;
2796 void VuoCompilerBitcodeGenerator::generateTelemetryFromPublishedOutputNode(Function *
function, BasicBlock *¤tBlock, Value *compositionStateValue,
2799 IntegerType *boolType = IntegerType::get(module->getContext(), 1);
2800 PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2810 BasicBlock *telemetryBlock = BasicBlock::Create(module->getContext(),
"",
function, NULL);
2811 BasicBlock *noTelemetryBlock = BasicBlock::Create(module->getContext(),
"",
function, NULL);
2814 Value *eventValue = inputEventPort->
generateLoadEvent(module, currentBlock, nodeContextValue);
2815 ConstantInt *zeroValue = ConstantInt::get(
static_cast<IntegerType *
>(eventValue->getType()), 0);
2816 ICmpInst *eventValueIsTrue =
new ICmpInst(*currentBlock, ICmpInst::ICMP_NE, eventValue, zeroValue,
"");
2817 BranchInst::Create(telemetryBlock, noTelemetryBlock, eventValueIsTrue, currentBlock);
2820 Value *dataPointer = data ? inputEventPort->
generateRetrieveData(module, telemetryBlock, nodeContextValue) : NULL;
2821 Constant *trueValue = ConstantInt::get(boolType, 1);
2822 Constant *falseValue = ConstantInt::get(boolType, 0);
2824 Value *sentDataValue = NULL;
2825 Value *dataSummaryValue = NULL;
2829 sentDataValue = trueValue;
2838 sentDataValue = falseValue;
2841 dataSummaryValue = ConstantPointerNull::get(pointerToCharType);
2846 sentDataValue, dataSummaryValue);
2850 BranchInst::Create(noTelemetryBlock, telemetryBlock);
2851 currentBlock = noTelemetryBlock;
2861 void VuoCompilerBitcodeGenerator::generateDataOnlyTransmissionFromNode(Function *
function, BasicBlock *¤tBlock, Value *compositionStateValue,
2863 bool shouldUpdateTriggers,
bool shouldSendTelemetry)
2866 if (downstreamNodes.empty())
2869 if (shouldWaitForDownstreamNodes)
2872 generateLockNodes(module, currentBlock, compositionStateValue, downstreamNodes,
nullptr);
2876 vector<VuoCompilerNode *> nodesToVisit = downstreamNodes;
2877 nodesToVisit.insert(nodesToVisit.begin(), node);
2882 Value *nodeContextValue = visitedNode->generateGetContext(module, currentBlock, compositionStateValue);
2885 vector<VuoPort *> inputPorts = visitedNode->getBase()->getInputPorts();
2893 generateNodeExecution(
function, currentBlock, compositionStateValue, visitedNode,
false);
2896 generateTransmissionFromNode(
function, currentBlock, compositionStateValue, nodeContextValue, visitedNode,
false, shouldSendTelemetry);
2902 if (visitedNode != node)
2904 if (shouldUpdateTriggers)
2907 visitedNode->generateCallbackUpdateFunctionCall(module, currentBlock, compositionStateValue);
2910 if (shouldWaitForDownstreamNodes)
2913 generateUnlockNodes(module, currentBlock, compositionStateValue, vector<VuoCompilerNode *>(1, visitedNode));
2922 void VuoCompilerBitcodeGenerator::generateNodeExecution(Function *
function, BasicBlock *¤tBlock,
2924 bool shouldSendTelemetry)
2928 if (shouldSendTelemetry)
2939 if (shouldSendTelemetry)
2949 void VuoCompilerBitcodeGenerator::generateAllocation(
void)
2952 generateAllocation_Pro();
2957 new GlobalVariable(*module, value->getType(),
true, GlobalValue::ExternalLinkage, value,
"vuoTopLevelCompositionIdentifier");
2968 void VuoCompilerBitcodeGenerator::generateSetupFunction(
bool isStatefulComposition)
2971 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
2980 CallInst::Create(compositionCreateAndRegisterMetadataFunction, topLevelCompositionStateValue,
"", block);
2986 isStatefulComposition, publishedOutputPortCount);
2991 Value *falseValue = ConstantInt::get(compositionSetPublishedInputPortValueFunction->getFunctionType()->getParamType(3), 0);
2998 vector<Value *> args;
2999 args.push_back(topLevelCompositionStateValue);
3000 args.push_back( constantsCache->
get(name) );
3001 args.push_back( constantsCache->
get(initialValue) );
3002 args.push_back(falseValue);
3003 CallInst::Create(compositionSetPublishedInputPortValueFunction, args,
"", block);
3009 CallInst::Create(compositionPerformDataOnlyTransmissionsFunction, topLevelCompositionStateValue,
"", block);
3013 for (map<VuoCompilerTriggerPort *, Function *>::iterator i = topLevelTriggerFunctions.begin(); i != topLevelTriggerFunctions.end(); ++i)
3016 Function *
function = i->second;
3019 Value *nodeContextValue = node->
generateGetContext(module, block, topLevelCompositionStateValue);
3025 for (map<
string, map<
size_t, map<VuoCompilerTriggerDescription *, Function *> > >::iterator i = subcompositionTriggerFunctions.begin(); i != subcompositionTriggerFunctions.end(); ++i)
3027 string compositionIdentifier = i->first;
3029 for (map<
size_t, map<VuoCompilerTriggerDescription *, Function *> >::iterator j = i->second.begin(); j != i->second.end(); ++j)
3031 size_t nodeIndex = j->first;
3033 for (map<VuoCompilerTriggerDescription *, Function *>::iterator k = j->second.begin(); k != j->second.end(); ++k)
3036 Function *
function = k->second;
3038 Value *compositionIdentifierValue = constantsCache->
get(compositionIdentifier);
3053 ReturnInst::Create(module->getContext(), block);
3062 void VuoCompilerBitcodeGenerator::generateCleanupFunction(
void)
3065 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
3075 ReturnInst::Create(module->getContext(), block);
3083 void VuoCompilerBitcodeGenerator::generateInstanceInitFunction(
bool isStatefulComposition)
3086 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
3088 if (isStatefulComposition)
3090 map<VuoPort *, size_t> indexOfParameter;
3093 vector<VuoPort *>(),
3094 indexOfParameter, constantsCache);
3100 CallInst::Create(nodeInstanceInitFunction, topLevelCompositionStateValue,
"", block);
3105 ReturnInst::Create(module->getContext(), block);
3113 void VuoCompilerBitcodeGenerator::generateInstanceFiniFunction(
bool isStatefulComposition)
3116 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
3118 if (isStatefulComposition)
3128 PointerType *instanceDataType =
static_cast<PointerType *
>( nodeInstanceFiniFunction->getFunctionType()->getParamType(1) );
3129 ConstantPointerNull *nullInstanceDataValue = ConstantPointerNull::get(instanceDataType);
3131 vector<Value *> args;
3132 args.push_back(topLevelCompositionStateValue);
3133 args.push_back(nullInstanceDataValue);
3134 CallInst::Create(nodeInstanceFiniFunction, args,
"", block);
3139 ReturnInst::Create(module->getContext(), block);
3147 void VuoCompilerBitcodeGenerator::generateInstanceTriggerStartFunction(
bool isStatefulComposition)
3150 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
3152 if (isStatefulComposition)
3154 map<VuoPort *, size_t> indexOfParameter;
3157 vector<VuoPort *>(),
3165 PointerType *instanceDataType =
static_cast<PointerType *
>( nodeInstanceTriggerStartFunction->getFunctionType()->getParamType(1) );
3166 ConstantPointerNull *nullInstanceDataValue = ConstantPointerNull::get(instanceDataType);
3168 vector<Value *> args;
3169 args.push_back(topLevelCompositionStateValue);
3170 args.push_back(nullInstanceDataValue);
3171 CallInst::Create(nodeInstanceTriggerStartFunction, args,
"", block);
3176 ReturnInst::Create(module->getContext(), block);
3184 void VuoCompilerBitcodeGenerator::generateInstanceTriggerStopFunction(
bool isStatefulComposition)
3187 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
3198 PointerType *instanceDataType =
static_cast<PointerType *
>( nodeInstanceTriggerStopFunction->getFunctionType()->getParamType(1) );
3199 ConstantPointerNull *nullInstanceDataValue = ConstantPointerNull::get(instanceDataType);
3201 vector<Value *> args;
3202 args.push_back(topLevelCompositionStateValue);
3203 args.push_back(nullInstanceDataValue);
3204 CallInst::Create(nodeInstanceTriggerStopFunction, args,
"", block);
3209 ReturnInst::Create(module->getContext(), block);
3217 void VuoCompilerBitcodeGenerator::generateTriggerFunctions(
void)
3219 auto isSpinOffTrigger = [] (
const string &nodeClassName)
3226 map<VuoCompilerTriggerPort *, Function *> workerFunctionForTrigger;
3229 Function *workerFunction = generateTriggerWorkerFunction(trigger);
3230 workerFunctionForTrigger[trigger] = workerFunction;
3233 if (isTopLevelComposition)
3235 for (map<VuoCompilerTriggerPort *, Function *>::iterator i = workerFunctionForTrigger.begin(); i != workerFunctionForTrigger.end(); ++i)
3238 Function *workerFunction = i->second;
3255 int minThreadsNeeded, maxThreadsNeeded;
3258 int chainCount = (int)graph->
getChains()[trigger].size();
3261 portIdentifier, portContextIndex, canDropEvents, isPublishedTrigger, isSpinOff,
3262 minThreadsNeeded, maxThreadsNeeded, chainCount, workerFunction);
3263 topLevelTriggerFunctions[trigger] =
function;
3274 for (vector<VuoCompilerTriggerDescription *>::iterator j = triggers.begin(); j != triggers.end(); ++j)
3289 string fullSubcompositionNodeIdentifier = (subcompositionNodeIdentifier.empty() ?
3296 int minThreadsNeeded, maxThreadsNeeded;
3297 if (isPublishedTrigger)
3298 minThreadsNeeded = maxThreadsNeeded = -1;
3307 Function *
function = generateTriggerSchedulerFunction(dataType, fullSubcompositionNodeIdentifier, triggerNodeIndex,
3308 portIdentifier, portContextIndex, canDropEvents, isPublishedTrigger, isSpinOff,
3309 minThreadsNeeded, maxThreadsNeeded, chainCount, workerFunction);
3311 subcompositionTriggerFunctions[fullSubcompositionNodeIdentifier][triggerNodeIndex][trigger] =
function;
3360 Function * VuoCompilerBitcodeGenerator::generateTriggerSchedulerFunction(
VuoType *dataType,
3361 string compositionIdentifier,
size_t nodeIndex,
3362 string portIdentifier,
int portContextIndex,
3363 bool canDropEvents,
bool isPublishedInputTrigger,
bool isSpinOff,
3364 int minThreadsNeeded,
int maxThreadsNeeded,
int chainCount,
3365 Function *workerFunction)
3370 Function *
function = Function::Create(functionType, GlobalValue::InternalLinkage, functionName, module);
3375 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, NULL);
3376 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, NULL);
3377 BasicBlock *scheduleBlock = BasicBlock::Create(module->getContext(),
"schedule",
function, NULL);
3380 Value *compositionIdentifierValue = constantsCache->
get(compositionIdentifier);
3391 BasicBlock *checkEventDropBlock = BasicBlock::Create(module->getContext(),
"checkEventDrop",
function, NULL);
3392 BranchInst::Create(checkEventDropBlock, initialBlock);
3396 Constant *zeroValue = ConstantInt::get(retValue->getType(), 0);
3397 ICmpInst *isTriggerAvailableValue =
new ICmpInst(*checkEventDropBlock, ICmpInst::ICMP_EQ, retValue, zeroValue,
"");
3398 BasicBlock *dropEventBlock = BasicBlock::Create(module->getContext(),
"dropEvent",
function, NULL);
3399 BranchInst::Create(scheduleBlock, dropEventBlock, isTriggerAvailableValue, checkEventDropBlock);
3406 Constant *portIdentifierValue = constantsCache->
get(portIdentifier);
3411 BranchInst::Create(finalBlock, dropEventBlock);
3415 BranchInst::Create(scheduleBlock, initialBlock);
3422 Value *eventIdValue;
3423 if (! isPublishedInputTrigger)
3445 compositionStateValue, eventIdValue, portContextValue, dataType,
3446 minThreadsNeeded, maxThreadsNeeded, chainCount, workerFunction);
3447 BranchInst::Create(finalBlock, scheduleBlock);
3449 ReturnInst::Create(module->getContext(), finalBlock);
3603 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, NULL);
3604 BasicBlock *triggerBlock = BasicBlock::Create(module->getContext(),
"trigger",
function, NULL);
3605 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, NULL);
3612 Value *triggerNodeContextValue = triggerNode->
generateGetContext(module, initialBlock, compositionStateValue);
3617 bool isNodeEventForSubcomposition = (! isTopLevelComposition && isPublishedInputTrigger);
3619 if (! isNodeEventForSubcomposition)
3622 BasicBlock *isPausedBlock = BasicBlock::Create(module->getContext(),
"isPaused",
function, NULL);
3624 BranchInst::Create(isPausedBlock, triggerBlock, isPausedValueIsTrue, initialBlock);
3631 vector<VuoCompilerNode *> publishedOutputNodeVector(1, publishedOutputNode);
3632 if (publishedOutputNode && ! isPublishedInputTrigger)
3633 generateLockNodes(module, isPausedBlock, compositionStateValue, publishedOutputNodeVector);
3638 if (isPublishedInputTrigger)
3641 vector<VuoCompilerNode *> triggerWaitNodes = getNodesToWaitOnBeforeTransmission(trigger);
3642 generateUnlockNodes(module, isPausedBlock, compositionStateValue, triggerWaitNodes);
3646 if (publishedOutputNode)
3647 generateUnlockNodes(module, isPausedBlock, compositionStateValue, publishedOutputNodeVector);
3659 BranchInst::Create(finalBlock, isPausedBlock);
3664 BranchInst::Create(triggerBlock, initialBlock);
3667 if (isPublishedInputTrigger)
3669 if (! isNodeEventForSubcomposition)
3672 vector<VuoCompilerNode *> triggerWaitNodes = getNodesToWaitOnBeforeTransmission(trigger);
3674 if (find(triggerWaitNodes.begin(), triggerWaitNodes.end(), publishedOutputNode) == triggerWaitNodes.end())
3676 vector<VuoCompilerNode *> publishedOutputNodeVector(1, publishedOutputNode);
3677 generateUnlockNodes(module, triggerBlock, compositionStateValue, publishedOutputNodeVector);
3684 vector<VuoCompilerNode *> triggerWaitNodes = getNodesToWaitOnBeforeTransmission(trigger);
3685 generateLockNodes(module, triggerBlock, compositionStateValue, triggerWaitNodes, eventIdValue);
3688 Value *triggerDataValue = trigger->
generateDataValueUpdate(module, triggerBlock,
function, triggerNodeContextValue);
3692 generateTransmissionFromOutputPort(
function, triggerBlock, compositionStateValue, triggerNode, trigger, NULL, triggerDataPointer);
3697 if (find(downstreamNodes.begin(), downstreamNodes.end(), triggerNode) == downstreamNodes.end())
3698 generateUnlockNodes(module, triggerBlock, compositionStateValue, vector<VuoCompilerNode *>(1, triggerNode));
3710 map<VuoCompilerChain *, vector<VuoCompilerChain *> > chainsImmediatelyDownstream;
3711 map<VuoCompilerChain *, vector<VuoCompilerChain *> > chainsImmediatelyUpstream;
3712 set<VuoCompilerChain *> chainsScheduled;
3714 vector<VuoCompilerChain *> allChains = chainsForTrigger[trigger];
3716 if (! allChains.empty())
3719 for (vector<VuoCompilerChain *>::iterator i = allChains.begin(); i != allChains.end(); ++i)
3724 for (vector<VuoCompilerChain *>::iterator j = allChains.begin(); j != allChains.end(); ++j)
3728 if (chain == otherChain)
3733 if (graph->
mayTransmit(lastNodeInOtherChain, firstNodeInThisChain, trigger))
3735 chainsImmediatelyUpstream[chain].push_back(otherChain);
3736 chainsImmediatelyDownstream[otherChain].push_back(chain);
3745 vector<VuoCompilerChain *> firstChains;
3746 for (vector<VuoCompilerChain *>::iterator i = allChains.begin(); i != allChains.end(); ++i)
3749 map<VuoCompilerChain *, vector<VuoCompilerChain *> >::iterator upstreamIter = chainsImmediatelyUpstream.find(chain);
3750 if (upstreamIter == chainsImmediatelyUpstream.end())
3751 firstChains.push_back(chain);
3756 firstChains.pop_back();
3757 chainsScheduled.insert(chainToExecute);
3758 size_t chainIndex = find(allChains.begin(), allChains.end(), chainToExecute) - allChains.begin();
3762 int minThreadsNeeded, maxThreadsNeeded;
3765 eventIdValue, compositionStateValue, chainIndex);
3768 generateAndScheduleChainWorkerFunctions(triggerBlock, compositionStateValue, contextValue, firstChains, trigger,
3769 allChains, chainsImmediatelyDownstream, chainsImmediatelyUpstream, chainsScheduled);
3772 generateChainExecution(
function, triggerBlock, compositionStateValue, contextValue, eventIdValue, chainToExecute, trigger,
3773 allChains, chainsImmediatelyDownstream, chainsImmediatelyUpstream, chainsScheduled);
3781 if (isNodeEventForSubcomposition)
3789 BranchInst::Create(finalBlock, triggerBlock);
3795 ReturnInst::Create(module->getContext(), finalBlock);
3803 void VuoCompilerBitcodeGenerator::generateAndScheduleChainWorkerFunctions(BasicBlock *schedulerBlock,
3804 Value *compositionStateValueInScheduler, Value *contextValueInScheduler,
3806 const vector<VuoCompilerChain *> &allChains,
3807 const map<
VuoCompilerChain *, vector<VuoCompilerChain *> > &chainsImmediatelyDownstream,
3808 const map<
VuoCompilerChain *, vector<VuoCompilerChain *> > &chainsImmediatelyUpstream,
3809 set<VuoCompilerChain *> &chainsScheduled)
3812 vector<VuoCompilerChain *> uniqueChainsToSchedule;
3813 for (vector<VuoCompilerChain *>::const_iterator i = chainsToSchedule.begin(); i != chainsToSchedule.end(); ++i)
3816 if (chainsScheduled.find(chain) == chainsScheduled.end())
3818 uniqueChainsToSchedule.push_back(chain);
3819 chainsScheduled.insert(chain);
3824 for (vector<VuoCompilerChain *>::const_iterator i = uniqueChainsToSchedule.begin(); i != uniqueChainsToSchedule.end(); ++i)
3828 for (vector<VuoCompilerChain *>::const_iterator i = uniqueChainsToSchedule.begin(); i != uniqueChainsToSchedule.end(); ++i)
3831 generateAndScheduleChainWorkerFunction(schedulerBlock, compositionStateValueInScheduler, contextValueInScheduler,
3832 chain, trigger, allChains, chainsImmediatelyDownstream, chainsImmediatelyUpstream,
3840 void VuoCompilerBitcodeGenerator::generateAndScheduleChainWorkerFunction(BasicBlock *schedulerBlock,
3841 Value *compositionStateValueInScheduler, Value *contextValueInScheduler,
3843 const vector<VuoCompilerChain *> &allChains,
3844 const map<
VuoCompilerChain *, vector<VuoCompilerChain *> > &chainsImmediatelyDownstream,
3845 const map<
VuoCompilerChain *, vector<VuoCompilerChain *> > &chainsImmediatelyUpstream,
3846 set<VuoCompilerChain *> &chainsScheduled)
3848 int minThreadsNeeded, maxThreadsNeeded;
3851 size_t chainIndex = find(allChains.begin(), allChains.end(), chain) - allChains.begin();
3853 vector<VuoCompilerChain *> upstreamChains;
3854 map<VuoCompilerChain *, vector<VuoCompilerChain *> >::const_iterator upstreamChainsIter = chainsImmediatelyUpstream.find(chain);
3855 if (upstreamChainsIter != chainsImmediatelyUpstream.end())
3856 upstreamChains = upstreamChainsIter->second;
3858 vector<size_t> upstreamChainIndices;
3859 for (vector<VuoCompilerChain *>::iterator i = upstreamChains.begin(); i != upstreamChains.end(); ++i)
3860 upstreamChainIndices.push_back( find(allChains.begin(), allChains.end(), *i) - allChains.begin() );
3863 Function *chainWorker = chain->
generateScheduleWorker(module, schedulerBlock, compositionStateValueInScheduler, contextValueInScheduler,
3864 trigger->
getIdentifier(), minThreadsNeeded, maxThreadsNeeded, chainIndex,
3865 upstreamChainIndices);
3867 BasicBlock *chainBlock = BasicBlock::Create(module->getContext(),
"", chainWorker, 0);
3868 Value *contextValueInChainWorker = chainWorker->arg_begin();
3870 Value *eventIdValue = chain->
generateEventIdValue(module, chainBlock, contextValueInChainWorker);
3873 generateChainExecution(chainWorker, chainBlock, compositionStateValueInChainWorker, contextValueInChainWorker, eventIdValue, chain, trigger,
3874 allChains, chainsImmediatelyDownstream, chainsImmediatelyUpstream, chainsScheduled);
3879 ReturnInst::Create(module->getContext(), chainBlock);
3885 void VuoCompilerBitcodeGenerator::generateChainExecution(Function *
function, BasicBlock *&block,
3886 Value *compositionStateValue, Value *contextValue,
3888 const vector<VuoCompilerChain *> &allChains,
3889 const map<
VuoCompilerChain *, vector<VuoCompilerChain *> > &chainsImmediatelyDownstream,
3890 const map<
VuoCompilerChain *, vector<VuoCompilerChain *> > &chainsImmediatelyUpstream,
3891 set<VuoCompilerChain *> &chainsScheduled)
3893 size_t chainIndex = find(allChains.begin(), allChains.end(), chain) - allChains.begin();
3894 Value *chainIndexValue = ConstantInt::get(eventIdValue->getType(), chainIndex);
3897 vector<VuoCompilerNode *> chainNodes = chain->
getNodes();
3898 for (vector<VuoCompilerNode *>::iterator i = chainNodes.begin(); i != chainNodes.end(); ++i)
3902 Function *nodeExecutionFunction = executionFunctionForNode[node];
3903 if (! nodeExecutionFunction)
3905 nodeExecutionFunction = generateNodeExecutionFunction(module, node);
3906 executionFunctionForNode[node] = nodeExecutionFunction;
3909 Function *nodeTransmissionFunction = transmissionFunctionForNode[node];
3910 if (! nodeTransmissionFunction)
3912 nodeTransmissionFunction = generateNodeTransmissionFunction(module, node);
3913 transmissionFunctionForNode[node] = nodeTransmissionFunction;
3917 vector<Value *> nodeExecutionArgs;
3918 nodeExecutionArgs.push_back(compositionStateValue);
3919 nodeExecutionArgs.push_back(eventIdValue);
3920 nodeExecutionArgs.push_back(chainIndexValue);
3921 CallInst *isHitValue = CallInst::Create(nodeExecutionFunction, nodeExecutionArgs,
"", block);
3926 vector<VuoCompilerNode *> outputNodes = getNodesToWaitOnBeforeTransmission(trigger, node);
3927 generateLockNodes(module, block, compositionStateValue, outputNodes, eventIdValue);
3931 vector<Value *> nodeTransmissionArgs;
3932 nodeTransmissionArgs.push_back(compositionStateValue);
3933 nodeTransmissionArgs.push_back(isHitValue);
3934 CallInst::Create(nodeTransmissionFunction, nodeTransmissionArgs,
"", block);
3943 generateUnlockNodes(module, block, compositionStateValue, vector<VuoCompilerNode *>(1, node));
3948 vector<VuoCompilerChain *> downstreamChains;
3949 map<VuoCompilerChain *, vector<VuoCompilerChain *> >::const_iterator downstreamChainsIter = chainsImmediatelyDownstream.find(chain);
3950 if (downstreamChainsIter != chainsImmediatelyDownstream.end())
3951 downstreamChains = downstreamChainsIter->second;
3952 if (! downstreamChains.empty())
3954 vector<size_t> downstreamChainIndices;
3955 for (vector<VuoCompilerChain *>::iterator i = downstreamChains.begin(); i != downstreamChains.end(); ++i)
3956 downstreamChainIndices.push_back( find(allChains.begin(), allChains.end(), *i) - allChains.begin() );
3958 vector<VuoCompilerChain *> nextChains;
3959 for (vector<VuoCompilerChain *>::iterator i = downstreamChains.begin(); i != downstreamChains.end(); ++i)
3962 nextChains.push_back(downstreamChain);
3965 generateAndScheduleChainWorkerFunctions(block, compositionStateValue, contextValue, nextChains, trigger, allChains,
3966 chainsImmediatelyDownstream, chainsImmediatelyUpstream, chainsScheduled);
4018 Function * VuoCompilerBitcodeGenerator::generateNodeExecutionFunction(Module *module,
VuoCompilerNode *node)
4022 Type *boolType = IntegerType::get(module->getContext(), 1);
4024 vector<Type *> params;
4025 params.push_back(pointerToCompositionStateType);
4026 params.push_back(eventIdType);
4027 params.push_back(eventIdType);
4028 FunctionType *functionType = FunctionType::get(boolType, params,
false);
4029 Function *
function = Function::Create(functionType, GlobalValue::InternalLinkage, functionName, module);
4031 Function::arg_iterator args =
function->arg_begin();
4032 Value *compositionStateValue = args++;
4033 compositionStateValue->setName(
"compositionState");
4034 Value *eventIdValue = args++;
4035 eventIdValue->setName(
"eventId");
4036 Value *chainIndexValue = args++;
4037 chainIndexValue->setName(
"chainIndex");
4039 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, NULL);
4040 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, NULL);
4042 Value *nodeContextValue = node->
generateGetContext(module, initialBlock, compositionStateValue);
4047 if (isTopLevelComposition)
4051 BranchInst::Create(finalBlock, initialBlock);
4057 BasicBlock *currBlock = initialBlock;
4066 for (
size_t publishedPortIndex = 0; publishedPortIndex < publishedOutputPorts.size(); ++publishedPortIndex)
4072 if (publishedOutputTriggerNames.find( port->
getClass()->
getName() ) != publishedOutputTriggerNames.end())
4074 BasicBlock *triggerBlock = BasicBlock::Create(module->getContext(),
"trigger",
function, NULL);
4075 BasicBlock *nextBlock = BasicBlock::Create(module->getContext(),
"next",
function, NULL);
4076 BranchInst::Create(triggerBlock, nextBlock, isPortHitValue, currBlock);
4083 vector<Value *> args;
4096 CallInst *triggerFunctionCall = CallInst::Create(triggerFunction, args,
"", triggerBlock);
4100 BranchInst::Create(nextBlock, triggerBlock);
4102 currBlock = nextBlock;
4114 ConstantInt *falseValue = ConstantInt::get(
static_cast<IntegerType *
>(subcompositionFinishedValue->getType()), 0);
4115 ICmpInst *subcompositionFinishedIsTrue =
new ICmpInst(*currBlock, ICmpInst::ICMP_NE, subcompositionFinishedValue, falseValue,
"");
4116 BasicBlock *leaveBlock = BasicBlock::Create(module->getContext(),
"leave",
function, NULL);
4117 BasicBlock *signalBlock = BasicBlock::Create(module->getContext(),
"signal",
function, NULL);
4118 BranchInst::Create(leaveBlock, signalBlock, subcompositionFinishedIsTrue, currBlock);
4124 BranchInst::Create(finalBlock, leaveBlock);
4129 generateUnlockNodes(module, signalBlock, compositionStateValue, vector<VuoCompilerNode *>(1, node));
4130 BranchInst::Create(finalBlock, signalBlock);
4136 BasicBlock *executeBlock = BasicBlock::Create(module->getContext(),
"execute",
function, NULL);
4137 BranchInst::Create(executeBlock, finalBlock, isHitValue, initialBlock);
4148 eventIdValue, compositionStateValue, chainIndexValue,
4149 subcompositionIdentifierValue);
4155 generateNodeExecution(
function, executeBlock, compositionStateValue, node, shouldSendTelemetry);
4156 BranchInst::Create(finalBlock, executeBlock);
4159 ReturnInst::Create(module->getContext(), isHitValue, finalBlock);
4188 Function * VuoCompilerBitcodeGenerator::generateNodeTransmissionFunction(Module *module,
VuoCompilerNode *node)
4192 Type *boolType = IntegerType::get(module->getContext(), 1);
4193 vector<Type *> params;
4194 params.push_back(pointerToCompositionStateType);
4195 params.push_back(boolType);
4196 FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params,
false);
4197 Function *
function = Function::Create(functionType, GlobalValue::InternalLinkage, functionName, module);
4199 Function::arg_iterator args =
function->arg_begin();
4200 Value *compositionStateValue = args++;
4201 compositionStateValue->setName(
"compositionState");
4202 Value *isHitValue = args++;
4203 isHitValue->setName(
"isHit");
4205 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, NULL);
4206 BasicBlock *transmitBlock = BasicBlock::Create(module->getContext(),
"transmit",
function, NULL);
4207 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, NULL);
4210 BranchInst::Create(transmitBlock, finalBlock, isHitValue, initialBlock);
4212 Value *nodeContextValue = node->
generateGetContext(module, transmitBlock, compositionStateValue);
4216 if (isTopLevelComposition)
4217 generateTelemetryFromPublishedOutputNode(
function, transmitBlock, compositionStateValue, nodeContextValue, node);
4222 generateTransmissionFromNode(
function, transmitBlock, compositionStateValue, nodeContextValue, node);
4228 BranchInst::Create(finalBlock, transmitBlock);
4229 ReturnInst::Create(module->getContext(), finalBlock);
4239 this->debugMode = debugMode;