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)
407 Module module(
"", getGlobalContext());
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())
423 PointerType *pointerToFunctionType = PointerType::get(functionType, 0);
427 modelOutputPorts[i] = modelTriggerPort->
getBase();
435 void VuoCompilerBitcodeGenerator::makeDependencies(
void)
441 makeDependencies_Pro();
445 compiler->getDependenciesForComposition(composition);
457 bool isStatefulComposition =
false;
462 isStatefulComposition =
true;
467 module =
new Module(moduleKey, getGlobalContext());
473 generateCompositionMetadata();
475 generateTriggerFunctions();
477 if (! isTopLevelComposition)
478 generateNodeEventFunction(isStatefulComposition);
480 if (isStatefulComposition)
482 generateNodeInstanceInitFunction();
483 generateNodeInstanceFiniFunction();
484 generateNodeInstanceTriggerStartFunction();
485 if (! isTopLevelComposition)
486 generateNodeInstanceTriggerUpdateFunction();
489 generateNodeInstanceTriggerStopFunction();
491 generateCompositionReleasePortDataFunction();
493 generateCompositionGetPortValueFunction();
494 generateCompositionSetPortValueFunction();
495 generateCompositionFireTriggerPortEventFunction();
497 generateCompositionSetPublishedInputPortValueFunction();
499 generateCompositionCreateContextForNodeFunction();
500 generateCompositionAddNodeMetadataFunction();
501 generateCompositionPerformDataOnlyTransmissionsFunction();
503 if (isTopLevelComposition)
507 generateAllocation();
508 generateSetupFunction(isStatefulComposition);
509 generateCleanupFunction();
511 generateInstanceInitFunction(isStatefulComposition);
512 generateInstanceFiniFunction(isStatefulComposition);
513 generateInstanceTriggerStartFunction(isStatefulComposition);
514 generateInstanceTriggerStopFunction(isStatefulComposition);
516 generateSetInputPortValueFunction();
518 generateGetPublishedPortCountFunction(
true);
519 generateGetPublishedPortCountFunction(
false);
520 generateGetPublishedPortNamesFunction(
true);
521 generateGetPublishedPortNamesFunction(
false);
522 generateGetPublishedPortTypesFunction(
true);
523 generateGetPublishedPortTypesFunction(
false);
524 generateGetPublishedPortDetailsFunction(
true);
525 generateGetPublishedPortDetailsFunction(
false);
526 generateGetPublishedPortValueFunction(
true);
527 generateGetPublishedPortValueFunction(
false);
528 generateSetPublishedInputPortValueFunction();
529 generateFirePublishedInputPortEventFunction();
534 delete constantsCache;
535 constantsCache =
nullptr;
543 void VuoCompilerBitcodeGenerator::generateCompositionMetadata(
void)
545 json_object *metadataJson = json_object_new_object();
546 json_object *nodeMetadataJson = json_object_new_object();
554 json_object_object_add(metadataJson,
"title", json_object_new_string(title.c_str()));
557 json_object_object_add(metadataJson,
"description", json_object_new_string(description.c_str()));
559 json_object *keywordsJson = json_object_new_array();
561 json_object_array_add(keywordsJson, json_object_new_string(keyword.c_str()));
562 json_object_object_add(metadataJson,
"keywords", keywordsJson);
565 if (! version.empty())
566 json_object_object_add(metadataJson,
"version", json_object_new_string(version.c_str()));
568 json_object *dependenciesJson = json_object_new_array();
569 for (
const string &dependency : dependencies)
570 json_object_array_add(dependenciesJson, json_object_new_string(dependency.c_str()));
571 json_object_object_add(metadataJson,
"dependencies", dependenciesJson);
573 if (! isTopLevelComposition)
576 generateCompositionMetadata_Pro(nodeMetadataJson);
579 json_object *triggersJson = json_object_new_array();
584 json_object_array_add(triggersJson, t);
592 json_object *t = triggerInSubcomposition->getJsonWithinSubcomposition(node);
593 json_object_array_add(triggersJson, t);
596 json_object_object_add(nodeMetadataJson,
"triggers", triggersJson);
602 json_object_object_add(nodesJson, node->
getIdentifier().c_str(), nodeClassNameJson);
604 json_object_object_add(nodeMetadataJson,
"nodes", nodesJson);
607 json_object_object_add(metadataJson,
"node", nodeMetadataJson);
609 string metadata = json_object_to_json_string_ext(metadataJson, JSON_C_TO_STRING_PLAIN);
610 json_object_put(metadataJson);
620 void VuoCompilerBitcodeGenerator::generateShouldShowSplashWindowFunction(
bool shouldShow)
622 IntegerType *returnType = IntegerType::get(module->getContext(), 8);
623 FunctionType *functionType = FunctionType::get(returnType,
false);
624 Function *
function = Function::Create(functionType, GlobalValue::ExternalLinkage,
"vuoShouldShowSplashWindow", module);
625 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
626 Value *boolValue = ConstantInt::get(returnType, shouldShow);
627 ReturnInst::Create(module->getContext(), boolValue, block);
636 void VuoCompilerBitcodeGenerator::generateCompositionAddNodeMetadataFunction(
void)
639 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
641 Function::arg_iterator args =
function->arg_begin();
642 Value *compositionStateValue = args++;
643 compositionStateValue->setName(
"compositionState");
651 for (vector<VuoCompilerNode *>::iterator i = orderedNodes.begin(); i != orderedNodes.end(); ++i)
655 node->
generateAddMetadata(module, block, compositionStateValue, orderedTypes, compositionCreateContextForNodeFunction,
656 compositionSetPortValueFunction, compositionGetPortValueFunction, compositionFireTriggerPortEventFunction,
657 releasePortDataFunction);
660 ReturnInst::Create(module->getContext(), block);
669 void VuoCompilerBitcodeGenerator::generateCompositionCreateContextForNodeFunction(
void)
672 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, NULL);
673 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, NULL);
675 Function::arg_iterator args =
function->arg_begin();
676 Value *nodeIndexValue = args++;
677 nodeIndexValue->setName(
"nodeIndex");
680 AllocaInst *nodeContextVariable =
new AllocaInst(pointerToNodeContext,
"nodeContext", initialBlock);
682 vector< pair<BasicBlock *, BasicBlock *> > blocksForIndex;
684 for (
size_t i = 0; i < orderedNodes.size(); ++i)
688 BasicBlock *block = BasicBlock::Create(module->getContext(), node->
getIdentifier(),
function, NULL);
690 new StoreInst(nodeContextValue, nodeContextVariable, block);
692 blocksForIndex.push_back(make_pair(block, block));
697 Value *nodeContextValue =
new LoadInst(nodeContextVariable,
"",
false, finalBlock);
698 ReturnInst::Create(module->getContext(), nodeContextValue, finalBlock);
709 void VuoCompilerBitcodeGenerator::generateCompositionPerformDataOnlyTransmissionsFunction(
void)
712 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
714 Function::arg_iterator args =
function->arg_begin();
715 Value *compositionStateValue = args++;
716 compositionStateValue->setName(
"compositionState");
721 generateDataOnlyTransmissionFromNode(
function, block, compositionStateValue, node,
false,
false,
false);
728 if (subcompositionFunctionSrc)
740 Value *falseValue = ConstantInt::get(setPublishedInputPortValueFunctionDst->getFunctionType()->getParamType(3), 0);
748 Value *inputPortNameValue = constantsCache->
get(inputPort->getClass()->getName());
751 vector<Value *> args;
752 args.push_back(subcompositionStateValueDst);
753 args.push_back(inputPortNameValue);
754 args.push_back(dataValue);
755 args.push_back(falseValue);
756 CallInst::Create(setPublishedInputPortValueFunctionDst, args,
"", block);
763 CallInst::Create(subcompositionFunctionDst, subcompositionStateValueDst,
"", block);
770 ReturnInst::Create(module->getContext(), block);
778 void VuoCompilerBitcodeGenerator::generateCompositionReleasePortDataFunction(
void)
781 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, NULL);
782 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, NULL);
784 Function::arg_iterator args =
function->arg_begin();
785 Value *portAddressAsVoidPointer = args++;
786 portAddressAsVoidPointer->setName(
"portData");
787 Value *typeIndexValue = args++;
788 typeIndexValue->setName(
"typeIndex");
790 vector< pair<BasicBlock *, BasicBlock *> > blocksForIndex;
792 for (vector<VuoCompilerType *>::iterator i = orderedTypes.begin(); i != orderedTypes.end(); ++i)
796 BasicBlock *block = BasicBlock::Create(module->getContext(), type->
getBase()->
getModuleKey(),
function, NULL);
797 Value *portAddress =
new BitCastInst(portAddressAsVoidPointer, PointerType::get(type->
getType(), 0),
"", block);
798 Value *portValue =
new LoadInst(portAddress,
"",
false, block);
801 blocksForIndex.push_back(make_pair(block, block));
806 ReturnInst::Create(module->getContext(), finalBlock);
812 void VuoCompilerBitcodeGenerator::generateSetInputDataFromNodeFunctionArguments(Function *
function, BasicBlock *&block, Value *compositionStateValue,
813 map<VuoPort *, size_t> indexOfParameter,
814 map<VuoPort *, size_t> indexOfEventParameter,
815 bool shouldWaitForDataOnlyDownstreamNodes,
816 bool shouldUpdateTriggers,
bool shouldSendTelemetry)
819 if (! publishedInputNode)
822 Value *publishedNodeContextValue = publishedInputNode->
generateGetContext(module, block, compositionStateValue);
825 vector<VuoCompilerInputEventPort *> inputEventPorts;
829 for (
size_t i = 0; i < publishedInputPorts.size(); ++i)
835 inputEventPorts.push_back(inputEventPort);
839 size_t dataArgIndex = indexOfParameter[ modelInputPorts[i] ];
849 if (type->
getType()->isStructTy() &&
853 Value *argAsPointer =
new BitCastInst(argAsPointerToOtherType, type->
getType()->getPointerTo(),
"", block);
854 dataArg =
new LoadInst(argAsPointer,
"", block);
868 generateDataOnlyTransmissionFromNode(
function, block, compositionStateValue, publishedInputNode,
869 shouldWaitForDataOnlyDownstreamNodes, shouldUpdateTriggers, shouldSendTelemetry);
873 for (
size_t i = 0; i < publishedInputPorts.size(); ++i)
878 &indexOfEventParameter :
881 auto foundIndex = indexMap->find( modelInputPorts[i] );
882 if (foundIndex != indexMap->end())
884 size_t eventArgIndex = foundIndex->second;
887 inputEventPort->
generateStoreEvent(module, block, publishedNodeContextValue, eventArg);
900 void VuoCompilerBitcodeGenerator::generateNodeEventFunction(
bool isStatefulComposition)
902 vector<VuoPort *> modelPorts;
903 modelPorts.insert(modelPorts.end(), modelInputPorts.begin(), modelInputPorts.end());
904 modelPorts.insert(modelPorts.end(), modelOutputPorts.begin(), modelOutputPorts.end());
908 vector<VuoPublishedPort *> publishedPorts;
909 publishedPorts.insert(publishedPorts.end(), publishedInputPorts.begin(), publishedInputPorts.end());
910 publishedPorts.insert(publishedPorts.end(), publishedOutputPorts.begin(), publishedOutputPorts.end());
912 map<VuoPort *, string> displayNamesForPorts;
913 map<VuoPort *, json_object *> detailsForPorts;
914 for (
size_t i = 0; i < modelPorts.size(); ++i)
916 VuoPort *modelPort = modelPorts[i];
920 bool isAllCaps =
true;
921 for (
size_t j = 0; j < portName.length(); ++j)
922 if (! isupper(portName[j]))
928 displayNamesForPorts[modelPort] = portName;
933 map<VuoPort *, string> defaultValuesForInputPorts;
934 map<VuoPort *, VuoPortClass::EventBlocking> eventBlockingForInputPorts;
935 for (
size_t i = 0; i < publishedInputPorts.size(); ++i)
940 if (! defaultValue.empty())
941 defaultValuesForInputPorts[publishedInputPort] = defaultValue;
946 map<VuoPort *, size_t> indexOfParameter;
947 map<VuoPort *, size_t> indexOfEventParameter;
950 modelInputPorts, modelOutputPorts,
951 detailsForPorts, displayNamesForPorts,
952 defaultValuesForInputPorts, eventBlockingForInputPorts,
953 indexOfParameter, indexOfEventParameter, constantsCache);
954 BasicBlock *block = &(
function->getEntryBlock());
959 ReturnInst::Create(module->getContext(), block);
965 Value *compositionStateValue =
function->arg_begin();
974 vector<VuoCompilerNode *> triggerWaitNodes = getNodesToWaitOnBeforeTransmission(trigger);
975 generateLockNodes(module, block, compositionStateValue, triggerWaitNodes, eventIdValue);
979 bool hasClaimedNodesDownstreamOfPublishedInputNode = (triggerWaitNodes.size() > 2);
980 generateSetInputDataFromNodeFunctionArguments(
function, block, compositionStateValue, indexOfParameter, indexOfEventParameter,
981 ! hasClaimedNodesDownstreamOfPublishedInputNode,
true,
true);
990 Value *triggerNodeContextValue = triggerNode->
generateGetContext(module, block, compositionStateValue);
991 Value *triggerFunctionValue = trigger->
generateLoadFunction(module, block, triggerNodeContextValue);
992 CallInst::Create(triggerFunctionValue,
"", block);
1001 Value *publishedOutputNodeContext = publishedOutputNode->
generateGetContext(module, block, compositionStateValue);
1002 for (
size_t i = 0; i < modelOutputPorts.size(); ++i)
1004 VuoPort *modelOutputPort = modelOutputPorts[i];
1010 bool hasEventParameter =
false;
1011 size_t eventIndex = 0;
1015 size_t index = indexOfParameter[ modelOutputPort ];
1019 new StoreInst(value, outputArg, block);
1021 map<VuoPort *, size_t>::iterator iter = indexOfEventParameter.find(modelOutputPort);
1022 if (iter != indexOfEventParameter.end())
1024 hasEventParameter =
true;
1025 eventIndex = iter->second;
1030 hasEventParameter =
true;
1031 eventIndex = indexOfParameter[ modelOutputPort ];
1034 if (hasEventParameter)
1039 new StoreInst(eventValue, outputArg, block);
1046 generateUnlockNodes(module, block, compositionStateValue, vector<VuoCompilerNode *>(1, publishedOutputNode));
1048 ReturnInst::Create(module->getContext(), block);
1056 void VuoCompilerBitcodeGenerator::generateNodeInstanceInitFunction(
void)
1058 vector<VuoPort *> inputPorts;
1059 if (! isTopLevelComposition)
1060 inputPorts = modelInputPorts;
1062 map<VuoPort *, size_t> indexOfParameter;
1065 inputPorts, indexOfParameter, constantsCache);
1066 BasicBlock *block = &(
function->getEntryBlock());
1068 Value *compositionStateValue =
function->arg_begin();
1070 if (! isTopLevelComposition)
1071 generateSetInputDataFromNodeFunctionArguments(
function, block, compositionStateValue, indexOfParameter, map<VuoPort *, size_t>(),
1072 false,
false,
false);
1078 BasicBlock *initBlock = NULL;
1079 BasicBlock *nextBlock = NULL;
1080 Value *replacementJsonValue = NULL;
1082 compositionStateValue, block, initBlock, nextBlock,
1083 constantsCache, replacementJsonValue);
1089 BranchInst::Create(nextBlock, initBlock);
1094 PointerType *instanceDataType =
static_cast<PointerType *
>(
function->getReturnType() );
1095 ConstantPointerNull *nullInstanceDataValue = ConstantPointerNull::get(instanceDataType);
1096 ReturnInst::Create(module->getContext(), nullInstanceDataValue, block);
1105 void VuoCompilerBitcodeGenerator::generateNodeInstanceFiniFunction(
void)
1110 BasicBlock *block = &(
function->getEntryBlock());
1112 Value *compositionStateValue =
function->arg_begin();
1118 BasicBlock *finiBlock = NULL;
1119 BasicBlock *nextBlock = NULL;
1120 Value *replacementJsonValue = NULL;
1122 compositionStateValue, block, finiBlock, nextBlock,
1123 constantsCache, replacementJsonValue);
1129 BranchInst::Create(nextBlock, finiBlock);
1134 ReturnInst::Create(module->getContext(), block);
1144 void VuoCompilerBitcodeGenerator::generateNodeInstanceTriggerStartFunction(
void)
1146 vector<VuoPort *> inputPorts;
1147 if (! isTopLevelComposition)
1148 inputPorts = modelInputPorts;
1150 map<VuoPort *, size_t> indexOfParameter;
1153 inputPorts, indexOfParameter, constantsCache);
1154 BasicBlock *block = &(
function->getEntryBlock());
1156 Value *compositionStateValue =
function->arg_begin();
1158 if (! isTopLevelComposition)
1159 generateSetInputDataFromNodeFunctionArguments(
function, block, compositionStateValue, indexOfParameter, map<VuoPort *, size_t>(),
1160 false,
false,
false);
1164 generateLockNodes(module, block, compositionStateValue, orderedNodes);
1175 generateUnlockNodes(module, block, compositionStateValue, orderedNodes);
1177 ReturnInst::Create(module->getContext(), block);
1185 void VuoCompilerBitcodeGenerator::generateNodeInstanceTriggerStopFunction(
void)
1190 BasicBlock *block = &(
function->getEntryBlock());
1192 Value *compositionStateValue =
function->arg_begin();
1195 generateLockNodes(module, block, compositionStateValue, orderedNodes);
1201 generateUnlockNodes(module, block, compositionStateValue, orderedNodes);
1203 if (isTopLevelComposition)
1210 generateLockNodes(module, block, compositionStateValue, orderedNodes);
1211 generateUnlockNodes(module, block, compositionStateValue, orderedNodes);
1214 ReturnInst::Create(module->getContext(), block);
1222 void VuoCompilerBitcodeGenerator::generateNodeInstanceTriggerUpdateFunction(
void)
1224 map<VuoPort *, size_t> indexOfParameter;
1227 modelInputPorts, indexOfParameter, constantsCache);
1228 BasicBlock *block = &(
function->getEntryBlock());
1230 Value *compositionStateValue =
function->arg_begin();
1235 ReturnInst::Create(module->getContext(), block);
1239 vector<VuoCompilerNode *> triggerWaitNodes = getNodesToWaitOnBeforeTransmission(trigger);
1240 generateLockNodes(module, block, compositionStateValue, triggerWaitNodes);
1242 bool hasClaimedNodesDownstreamOfPublishedInputNode = (triggerWaitNodes.size() > 2);
1243 generateSetInputDataFromNodeFunctionArguments(
function, block, compositionStateValue, indexOfParameter, map<VuoPort *, size_t>(),
1244 ! hasClaimedNodesDownstreamOfPublishedInputNode,
true,
true);
1246 generateUnlockNodes(module, block, compositionStateValue, triggerWaitNodes);
1248 ReturnInst::Create(module->getContext(), block);
1254 void VuoCompilerBitcodeGenerator::generateLockNodes(Module *module, BasicBlock *block,
1255 Value *compositionStateValue, vector<VuoCompilerNode *> nodes,
1256 Value *eventIdValue)
1264 if (nodes.size() == 1)
1266 size_t nodeIndex = nodes[0]->getIndexInOrderedNodes();
1273 vector<size_t> nodeIndices;
1274 std::transform(nodes.begin(), nodes.end(), std::back_inserter(nodeIndices), [](
VuoCompilerNode *n) { return n->getIndexInOrderedNodes(); });
1283 void VuoCompilerBitcodeGenerator::generateUnlockNodes(Module *module, BasicBlock *block, Value *compositionStateValue,
1284 vector<VuoCompilerNode *> nodes)
1289 if (nodes.size() == 1)
1291 size_t nodeIndex = nodes[0]->getIndexInOrderedNodes();
1296 vector<size_t> nodeIndices;
1297 std::transform(nodes.begin(), nodes.end(), std::back_inserter(nodeIndices), [](
VuoCompilerNode *n) { return n->getIndexInOrderedNodes(); });
1367 void VuoCompilerBitcodeGenerator::generateCompositionGetPortValueFunction(
void)
1371 Function::arg_iterator args =
function->arg_begin();
1372 Value *compositionStateValue = args++;
1373 compositionStateValue->setName(
"compositionState");
1374 Value *portIdentifierValue = args++;
1375 portIdentifierValue->setName(
"portIdentifier");
1376 Value *serializationTypeValue = args++;
1377 serializationTypeValue->setName(
"serializationType");
1378 Value *isThreadSafeValue = args++;
1379 isThreadSafeValue->setName(
"isThreadSafe");
1384 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, 0);
1385 PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
1387 AllocaInst *retVariable =
new AllocaInst(pointerToCharType,
"ret", initialBlock);
1388 ConstantPointerNull *nullPointerToChar = ConstantPointerNull::get(pointerToCharType);
1389 new StoreInst(nullPointerToChar, retVariable,
false, initialBlock);
1397 BasicBlock *checkWaitBlock = BasicBlock::Create(module->getContext(),
"checkWait",
function, 0);
1398 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, 0);
1400 ConstantPointerNull *nullPortAddress = ConstantPointerNull::get(
static_cast<PointerType *
>(portAddressAsVoidPointer->getType()));
1401 ICmpInst *portAddressNotEqualsNull =
new ICmpInst(*initialBlock, ICmpInst::ICMP_NE, portAddressAsVoidPointer, nullPortAddress,
"");
1402 BranchInst::Create(checkWaitBlock, finalBlock, portAddressNotEqualsNull, initialBlock);
1416 BasicBlock *waitBlock = BasicBlock::Create(module->getContext(),
"wait",
function, 0);
1417 BasicBlock *checkTypeIndexBlock = BasicBlock::Create(module->getContext(),
"checkTypeIndex",
function, 0);
1418 ConstantInt *falseValue = ConstantInt::get(
static_cast<IntegerType *
>(isThreadSafeValue->getType()), 0);
1419 ICmpInst *isThreadSafeEqualsTrue =
new ICmpInst(*checkWaitBlock, ICmpInst::ICMP_NE, isThreadSafeValue, falseValue,
"");
1420 BranchInst::Create(waitBlock, checkTypeIndexBlock, isThreadSafeEqualsTrue, checkWaitBlock);
1424 BranchInst::Create(checkTypeIndexBlock, waitBlock);
1447 vector< pair<BasicBlock *, BasicBlock *> > blocksForIndex;
1448 for (
size_t i = 0; i < orderedTypes.size(); ++i)
1455 BasicBlock *checkSummaryBlock = BasicBlock::Create(module->getContext(), typeName +
"_checkSummary",
function, 0);
1456 BasicBlock *summaryBlock = BasicBlock::Create(module->getContext(), typeName +
"_summary",
function, 0);
1457 BasicBlock *checkStringBlock = NULL;
1458 BasicBlock *stringBlock = BasicBlock::Create(module->getContext(), typeName +
"_string",
function, 0);
1459 BasicBlock *interprocessBlock = NULL;
1460 BasicBlock *typeFinalBlock = BasicBlock::Create(module->getContext(), typeName +
"_final",
function, 0);
1462 BasicBlock *firstStringBlock = NULL;
1463 if (hasInterprocess)
1465 checkStringBlock = BasicBlock::Create(module->getContext(), typeName +
"_checkString",
function, 0);
1466 interprocessBlock = BasicBlock::Create(module->getContext(), typeName +
"_interprocess",
function, 0);
1467 firstStringBlock = checkStringBlock;
1471 firstStringBlock = stringBlock;
1474 PointerType *pointerToType = PointerType::get(type->
getType(), 0);
1475 Value *portAddress =
new BitCastInst(portAddressAsVoidPointer, pointerToType,
"", checkSummaryBlock);
1476 Value *portValue =
new LoadInst(portAddress,
"",
false, checkSummaryBlock);
1478 ConstantInt *zeroValue = ConstantInt::get(
static_cast<IntegerType *
>(serializationTypeValue->getType()), 0);
1479 ICmpInst *serializationTypeEqualsZero =
new ICmpInst(*checkSummaryBlock, ICmpInst::ICMP_EQ, serializationTypeValue, zeroValue,
"");
1480 BranchInst::Create(summaryBlock, firstStringBlock, serializationTypeEqualsZero, checkSummaryBlock);
1483 new StoreInst(summaryValue, retVariable, summaryBlock);
1484 BranchInst::Create(typeFinalBlock, summaryBlock);
1486 if (hasInterprocess)
1488 ConstantInt *oneValue = ConstantInt::get(
static_cast<IntegerType *
>(serializationTypeValue->getType()), 1);
1489 ICmpInst *serializationTypeEqualsOne =
new ICmpInst(*checkStringBlock, ICmpInst::ICMP_EQ, serializationTypeValue, oneValue,
"");
1490 BranchInst::Create(stringBlock, interprocessBlock, serializationTypeEqualsOne, checkStringBlock);
1494 new StoreInst(stringValue, retVariable, stringBlock);
1495 BranchInst::Create(typeFinalBlock, stringBlock);
1497 if (hasInterprocess)
1500 new StoreInst(interprocessValue, retVariable, interprocessBlock);
1501 BranchInst::Create(typeFinalBlock, interprocessBlock);
1504 blocksForIndex.push_back( make_pair(checkSummaryBlock, typeFinalBlock) );
1507 BasicBlock *checkSignalBlock = BasicBlock::Create(module->getContext(),
"checkSignal",
function, 0);
1514 BasicBlock *signalBlock = BasicBlock::Create(module->getContext(),
"signal",
function, 0);
1515 BranchInst::Create(signalBlock, finalBlock, isThreadSafeEqualsTrue, checkSignalBlock);
1518 BranchInst::Create(finalBlock, signalBlock);
1523 LoadInst *retValue =
new LoadInst(retVariable,
"",
false, finalBlock);
1524 ReturnInst::Create(module->getContext(), retValue, finalBlock);
1605 void VuoCompilerBitcodeGenerator::generateCompositionSetPortValueFunction(
void)
1609 Function::arg_iterator args =
function->arg_begin();
1610 Value *compositionStateValue = args++;
1611 compositionStateValue->setName(
"compositionState");
1612 Value *portIdentifierValue = args++;
1613 portIdentifierValue->setName(
"portIdentifier");
1614 Value *valueAsStringValue = args++;
1615 valueAsStringValue->setName(
"valueAsString");
1616 Value *isThreadSafeValue = args++;
1617 isThreadSafeValue->setName(
"isThreadSafe");
1618 Value *shouldUpdateTriggersValue = args++;
1619 shouldUpdateTriggersValue->setName(
"shouldUpdateTriggers");
1620 Value *shouldSendTelemetryValue = args++;
1621 shouldSendTelemetryValue->setName(
"shouldSendTelemetry");
1622 Value *hasOldValue = args++;
1623 hasOldValue->setName(
"hasOldValue");
1624 Value *hasNewValue = args++;
1625 hasNewValue->setName(
"hasNewValue");
1630 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, 0);
1635 BasicBlock *checkWaitBlock = BasicBlock::Create(module->getContext(),
"checkWait",
function, 0);
1636 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, 0);
1638 ConstantPointerNull *nullPortAddress = ConstantPointerNull::get(
static_cast<PointerType *
>(portAddressAsVoidPointer->getType()));
1639 ICmpInst *portAddressNotEqualsNull =
new ICmpInst(*initialBlock, ICmpInst::ICMP_NE, portAddressAsVoidPointer, nullPortAddress,
"");
1640 BranchInst::Create(checkWaitBlock, finalBlock, portAddressNotEqualsNull, initialBlock);
1650 PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
1651 AllocaInst *summaryVariable =
new AllocaInst(pointerToCharType,
"summary", checkWaitBlock);
1652 ConstantPointerNull *nullSummary = ConstantPointerNull::get(pointerToCharType);
1653 new StoreInst(nullSummary, summaryVariable,
false, checkWaitBlock);
1661 BasicBlock *waitBlock = BasicBlock::Create(module->getContext(),
"wait",
function, 0);
1662 BasicBlock *checkTypeIndexBlock = BasicBlock::Create(module->getContext(),
"checkTypeIndex",
function, 0);
1663 ConstantInt *falseArgValue = ConstantInt::get(
static_cast<IntegerType *
>(isThreadSafeValue->getType()), 0);
1664 ICmpInst *isThreadSafeEqualsTrue =
new ICmpInst(*checkWaitBlock, ICmpInst::ICMP_NE, isThreadSafeValue, falseArgValue,
"");
1665 BranchInst::Create(waitBlock, checkTypeIndexBlock, isThreadSafeEqualsTrue, checkWaitBlock);
1669 BranchInst::Create(checkTypeIndexBlock, waitBlock);
1700 ICmpInst *hasOldValueIsTrue =
new ICmpInst(*checkTypeIndexBlock, ICmpInst::ICMP_NE, hasOldValue, falseArgValue,
"");
1701 ICmpInst *hasNewValueIsTrue =
new ICmpInst(*checkTypeIndexBlock, ICmpInst::ICMP_NE, hasNewValue, falseArgValue,
"");
1702 ICmpInst *shouldSendTelemetryIsTrue =
new ICmpInst(*checkTypeIndexBlock, ICmpInst::ICMP_NE, shouldSendTelemetryValue, falseArgValue,
"");
1704 vector< pair<BasicBlock *, BasicBlock *> > blocksForTypeIndex;
1705 for (
size_t i = 0; i < orderedTypes.size(); ++i)
1709 BasicBlock *typeInitialBlock = BasicBlock::Create(module->getContext(), type->
getBase()->
getModuleKey() +
"_initial",
function, 0);
1710 Value *portAddress =
new BitCastInst(portAddressAsVoidPointer, PointerType::get(type->
getType(), 0),
"", typeInitialBlock);
1712 BasicBlock *typeFinalBlock = BasicBlock::Create(module->getContext(), type->
getBase()->
getModuleKey() +
"_final",
function, 0);
1714 BasicBlock *setNewValueBlock = BasicBlock::Create(module->getContext(),
"setNewValue",
function, 0);
1716 new StoreInst(portValue, portAddress,
false, setNewValueBlock);
1719 BasicBlock *summaryBlock = BasicBlock::Create(module->getContext(),
"summary",
function, 0);
1721 new StoreInst(summaryValue, summaryVariable,
false, summaryBlock);
1725 BasicBlock *saveOldValueBlock = BasicBlock::Create(module->getContext(),
"saveOldValue",
function, 0);
1726 BasicBlock *checkNewValueBlock = BasicBlock::Create(module->getContext(),
"checkNewValue",
function, 0);
1727 BasicBlock *checkOldValueBlock = BasicBlock::Create(module->getContext(),
"checkOldValue",
function, 0);
1728 BasicBlock *releaseOldValueBlock = BasicBlock::Create(module->getContext(),
"releaseOldValue",
function, 0);
1730 AllocaInst *oldPortValueVariable =
new AllocaInst(type->
getType(),
"oldPortValue", typeInitialBlock);
1731 BranchInst::Create(saveOldValueBlock, checkNewValueBlock, hasOldValueIsTrue, typeInitialBlock);
1733 Value *oldPortValue =
new LoadInst(portAddress,
"",
false, saveOldValueBlock);
1734 new StoreInst(oldPortValue, oldPortValueVariable,
false, saveOldValueBlock);
1735 BranchInst::Create(checkNewValueBlock, saveOldValueBlock);
1737 BranchInst::Create(setNewValueBlock, checkOldValueBlock, hasNewValueIsTrue, checkNewValueBlock);
1739 BranchInst::Create(summaryBlock, checkOldValueBlock, shouldSendTelemetryIsTrue, setNewValueBlock);
1741 BranchInst::Create(checkOldValueBlock, summaryBlock);
1743 BranchInst::Create(releaseOldValueBlock, typeFinalBlock, hasOldValueIsTrue, checkOldValueBlock);
1745 oldPortValue =
new LoadInst(oldPortValueVariable,
"",
false, releaseOldValueBlock);
1747 BranchInst::Create(typeFinalBlock, releaseOldValueBlock);
1751 BranchInst::Create(setNewValueBlock, typeFinalBlock, hasNewValueIsTrue, typeInitialBlock);
1753 BranchInst::Create(summaryBlock, typeFinalBlock, shouldSendTelemetryIsTrue, setNewValueBlock);
1755 BranchInst::Create(typeFinalBlock, summaryBlock);
1758 blocksForTypeIndex.push_back( make_pair(typeInitialBlock, typeFinalBlock) );
1761 BasicBlock *checkUpdateBlock = BasicBlock::Create(module->getContext(),
"checkUpdate",
function, 0);
1774 Constant *zeroValue = ConstantInt::get(shouldUpdateTriggersValue->getType(), 0);
1775 ICmpInst *shouldUpdateTriggersIsTrue =
new ICmpInst(*checkUpdateBlock, ICmpInst::ICMP_NE, shouldUpdateTriggersValue, zeroValue,
"");
1776 BasicBlock *updateTriggersBlock = BasicBlock::Create(module->getContext(),
"updateTriggers",
function, 0);
1777 BasicBlock *checkSendBlock = BasicBlock::Create(module->getContext(),
"checkSend",
function, 0);
1778 BranchInst::Create(updateTriggersBlock, checkSendBlock, shouldUpdateTriggersIsTrue, checkUpdateBlock);
1780 vector< pair<BasicBlock *, BasicBlock *> > blocksForNodeIndex;
1781 for (
size_t i = 0; i < orderedNodes.size(); ++i)
1784 BasicBlock *currentBlock = BasicBlock::Create(module->getContext(), node->
getIdentifier(),
function, 0);
1785 BasicBlock *origCurrentBlock = currentBlock;
1789 generateDataOnlyTransmissionFromNode(
function, currentBlock, compositionStateValue, node,
true,
true,
true);
1791 blocksForNodeIndex.push_back( make_pair(origCurrentBlock, currentBlock) );
1794 BasicBlock *checkSignalBlock = BasicBlock::Create(module->getContext(),
"checkSignal",
function, 0);
1801 BasicBlock *signalBlock = BasicBlock::Create(module->getContext(),
"signal",
function, 0);
1802 BranchInst::Create(signalBlock, checkSendBlock, isThreadSafeEqualsTrue, checkSignalBlock);
1805 BranchInst::Create(checkSendBlock, signalBlock);
1814 BasicBlock *sendBlock = BasicBlock::Create(module->getContext(),
"send",
function, 0);
1815 BranchInst::Create(sendBlock, finalBlock, shouldSendTelemetryIsTrue, checkSendBlock);
1817 Value *summaryValue =
new LoadInst(summaryVariable,
"",
false, sendBlock);
1820 false,
true, summaryValue);
1823 BranchInst::Create(finalBlock, sendBlock);
1825 ReturnInst::Create(module->getContext(), finalBlock);
1833 void VuoCompilerBitcodeGenerator::generateSetInputPortValueFunction(
void)
1836 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
1838 Function::arg_iterator args =
function->arg_begin();
1839 Value *portIdentifierValue = args++;
1840 portIdentifierValue->setName(
"portIdentifier");
1841 Value *valueAsStringValue = args++;
1842 valueAsStringValue->setName(
"valueAsString");
1850 Value *trueValue = ConstantInt::get(compositionSetPortValueFunction->getFunctionType()->getParamType(3), 1);
1852 vector<Value *> compositionArgs;
1853 compositionArgs.push_back(compositionStateValue);
1854 compositionArgs.push_back(portIdentifierValue);
1855 compositionArgs.push_back(valueAsStringValue);
1856 compositionArgs.push_back(trueValue);
1857 compositionArgs.push_back(trueValue);
1858 compositionArgs.push_back(trueValue);
1859 compositionArgs.push_back(trueValue);
1860 compositionArgs.push_back(trueValue);
1861 CallInst::Create(compositionSetPortValueFunction, compositionArgs,
"", block);
1865 ReturnInst::Create(module->getContext(), block);
1887 void VuoCompilerBitcodeGenerator::generateCompositionFireTriggerPortEventFunction(
void)
1891 Function::arg_iterator args =
function->arg_begin();
1892 Value *compositionStateValue = args++;
1893 compositionStateValue->setName(
"compositionState");
1894 Value *portIdentifierValue = args++;
1895 portIdentifierValue->setName(
"portIdentifier");
1897 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, 0);
1899 map<string, pair<BasicBlock *, BasicBlock *> > blocksForString;
1906 BasicBlock *currentBlock = BasicBlock::Create(module->getContext(), currentPortIdentifier,
function, 0);
1907 BasicBlock *origCurrentBlock = currentBlock;
1909 Value *nodeContextValue = triggerNode->
generateGetContext(module, currentBlock, compositionStateValue);
1910 Value *triggerFunctionValue = trigger->
generateLoadFunction(module, currentBlock, nodeContextValue);
1912 vector<Value *> triggerArgs;
1913 AttributeSet triggerParamAttributes;
1917 generateLockNodes(module, currentBlock, compositionStateValue, vector<VuoCompilerNode *>(1, triggerNode));
1923 Type *secondParam = NULL;
1927 bool isByVal = triggerParamAttributes.hasAttrSomewhere(Attribute::ByVal);
1929 Value *secondArg = NULL;
1930 Value **secondArgIfNeeded = (secondParam ? &secondArg : NULL);
1933 triggerArgs.push_back(arg);
1935 triggerArgs.push_back(secondArg);
1938 CallInst *call = CallInst::Create(triggerFunctionValue, triggerArgs,
"", currentBlock);
1943 generateUnlockNodes(module, currentBlock, compositionStateValue, vector<VuoCompilerNode *>(1, triggerNode));
1945 blocksForString[currentPortIdentifier] = make_pair(origCurrentBlock, currentBlock);
1948 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, 0);
1950 ReturnInst::Create(module->getContext(), finalBlock);
1970 void VuoCompilerBitcodeGenerator::generateGetPublishedPortCountFunction(
bool input)
1973 string functionName;
1977 functionName =
"getPublishedInputPortCount";
1982 functionName =
"getPublishedOutputPortCount";
1985 Function *
function = module->getFunction(functionName);
1988 vector<Type *> functionParams;
1989 FunctionType *functionType = FunctionType::get(IntegerType::get(module->getContext(), 32), functionParams,
false);
1990 function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
1993 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, 0);
1994 ConstantInt *countConstant = ConstantInt::get(module->getContext(), APInt(32, count));
1995 ReturnInst::Create(module->getContext(), countConstant, block);
2013 void VuoCompilerBitcodeGenerator::generateGetPublishedPortNamesFunction(
bool input)
2015 string functionName;
2016 vector<VuoPublishedPort *> publishedPorts;
2019 functionName =
"getPublishedInputPortNames";
2024 functionName =
"getPublishedOutputPortNames";
2028 vector<string> names;
2029 for (vector<VuoPublishedPort *>::iterator i = publishedPorts.begin(); i != publishedPorts.end(); ++i)
2031 names.push_back( (*i)->getClass()->getName() );
2034 generateFunctionReturningStringArray(functionName, names);
2052 void VuoCompilerBitcodeGenerator::generateGetPublishedPortTypesFunction(
bool input)
2054 string functionName;
2055 vector<VuoPublishedPort *> publishedPorts;
2058 functionName =
"getPublishedInputPortTypes";
2063 functionName =
"getPublishedOutputPortTypes";
2067 vector<string> types;
2068 for (vector<VuoPublishedPort *>::iterator i = publishedPorts.begin(); i != publishedPorts.end(); ++i)
2074 types.push_back(typeName);
2077 generateFunctionReturningStringArray(functionName, types);
2095 void VuoCompilerBitcodeGenerator::generateGetPublishedPortDetailsFunction(
bool input)
2097 string functionName;
2098 vector<VuoPublishedPort *> publishedPorts;
2101 functionName =
"getPublishedInputPortDetails";
2106 functionName =
"getPublishedOutputPortDetails";
2110 vector<string> details;
2111 for (vector<VuoPublishedPort *>::iterator i = publishedPorts.begin(); i != publishedPorts.end(); ++i)
2116 string detailsSerialized = json_object_to_json_string_ext(detailsObj, JSON_C_TO_STRING_PLAIN);
2117 details.push_back(detailsSerialized);
2119 json_object_put(detailsObj);
2122 generateFunctionReturningStringArray(functionName, details);
2131 void VuoCompilerBitcodeGenerator::generateFunctionReturningStringArray(
string functionName, vector<string> stringValues)
2133 Function *
function = module->getFunction(functionName);
2136 PointerType *pointerToChar = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2137 PointerType *pointerToPointerToChar = PointerType::get(pointerToChar, 0);
2138 vector<Type *> functionParams;
2139 FunctionType *functionType = FunctionType::get(pointerToPointerToChar, functionParams,
false);
2140 function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
2143 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, 0);
2146 ReturnInst::Create(module->getContext(), stringArrayGlobalPointer, block);
2158 void VuoCompilerBitcodeGenerator::generateFirePublishedInputPortEventFunction(
void)
2160 string functionName =
"firePublishedInputPortEvent";
2161 Function *
function = module->getFunction(functionName);
2164 PointerType *pointerToChar = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2165 PointerType *pointerToPointerToChar = PointerType::get(pointerToChar, 0);
2166 Type *countType = IntegerType::get(module->getContext(), 32);
2168 vector<Type *> functionParams;
2169 functionParams.push_back(pointerToPointerToChar);
2170 functionParams.push_back(countType);
2171 FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams,
false);
2172 function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
2175 Function::arg_iterator args =
function->arg_begin();
2176 Value *namesValue = args++;
2177 namesValue->setName(
"names");
2178 Value *countValue = args++;
2179 countValue->setName(
"count");
2181 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, 0);
2186 ReturnInst::Create(module->getContext(), initialBlock);
2195 compositionIdentifierValue);
2204 vector<VuoCompilerNode *> triggerWaitNodes = getNodesToWaitOnBeforeTransmission(trigger);
2207 if (find(triggerWaitNodes.begin(), triggerWaitNodes.end(), publishedOutputNode) == triggerWaitNodes.end())
2208 triggerWaitNodes.push_back(publishedOutputNode);
2210 generateLockNodes(module, initialBlock, compositionStateValue, triggerWaitNodes, eventIdValue);
2235 Value *publishedInputNodeContextValue = publishedInputNode->
generateGetContext(module, initialBlock, compositionStateValue);
2237 Value *zeroValue = ConstantInt::get(
static_cast<IntegerType *
>(countValue->getType()), 0);
2238 AllocaInst *iterVariable =
new AllocaInst(countValue->getType(),
"i", initialBlock);
2239 new StoreInst(zeroValue, iterVariable,
false, initialBlock);
2241 BasicBlock *loopConditionBlock = BasicBlock::Create(module->getContext(),
"loopCondition",
function, 0);
2242 BasicBlock *loopBeginBlock = BasicBlock::Create(module->getContext(),
"loopBegin",
function, 0);
2243 BasicBlock *loopEndBlock = BasicBlock::Create(module->getContext(),
"loopEnd",
function, 0);
2244 BasicBlock *fireBlock = BasicBlock::Create(module->getContext(),
"fire",
function, 0);
2246 BranchInst::Create(loopConditionBlock, initialBlock);
2248 Value *iterValue =
new LoadInst(iterVariable,
"",
false, loopConditionBlock);
2249 ICmpInst *iterLessThanCount =
new ICmpInst(*loopConditionBlock, ICmpInst::ICMP_ULT, iterValue, countValue,
"");
2250 BranchInst::Create(loopBeginBlock, fireBlock, iterLessThanCount, loopConditionBlock);
2254 map<string, pair<BasicBlock *, BasicBlock *> > blocksForString;
2257 for (
size_t i = 0; i < publishedInputPorts.size(); ++i)
2259 string currentName = publishedInputPorts[i]->getClass()->getName();
2260 BasicBlock *currentBlock = BasicBlock::Create(module->getContext(), currentName,
function, 0);
2264 inputEventPort->
generateStoreEvent(module, currentBlock, publishedInputNodeContextValue,
true);
2266 blocksForString[currentName] = make_pair(currentBlock, currentBlock);
2271 Value *oneValue = ConstantInt::get(
static_cast<IntegerType *
>(countValue->getType()), 1);
2272 Value *iterPlusOneValue = BinaryOperator::Create(Instruction::Add, iterValue, oneValue,
"", loopEndBlock);
2273 new StoreInst(iterPlusOneValue, iterVariable,
false, loopEndBlock);
2275 BranchInst::Create(loopConditionBlock, loopEndBlock);
2279 Value *triggerNodeContextValue = triggerNode->
generateGetContext(module, fireBlock, compositionStateValue);
2280 Value *triggerFunctionValue = trigger->
generateLoadFunction(module, fireBlock, triggerNodeContextValue);
2281 CallInst::Create(triggerFunctionValue,
"", fireBlock);
2283 ReturnInst::Create(module->getContext(), fireBlock);
2325 void VuoCompilerBitcodeGenerator::generateGetPublishedPortValueFunction(
bool input)
2327 Function *
function = (input ?
2331 Function::arg_iterator args =
function->arg_begin();
2332 Value *portIdentifierValue = args++;
2333 portIdentifierValue->setName(
"portIdentifier");
2334 Value *shouldUseInterprocessSerializationValue = args++;
2335 shouldUseInterprocessSerializationValue->setName(
"shouldUseInterprocessSerialization");
2337 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, 0);
2338 PointerType *pointerToChar = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2339 AllocaInst *retVariable =
new AllocaInst(pointerToChar,
"ret", initialBlock);
2340 ConstantPointerNull *nullValue = ConstantPointerNull::get(pointerToChar);
2341 new StoreInst(nullValue, retVariable,
false, initialBlock);
2346 compositionIdentifierValue);
2348 vector<VuoPort *> inputPortsOnPublishedNode;
2352 for (
size_t i = 0; i < publishedPorts.size(); ++i)
2355 inputPortsOnPublishedNode.push_back(port);
2361 for (
size_t i = 0; i < publishedPorts.size(); ++i)
2364 inputPortsOnPublishedNode.push_back(port);
2368 map<string, pair<BasicBlock *, BasicBlock *> > blocksForString;
2369 for (
VuoPort *port : inputPortsOnPublishedNode)
2372 BasicBlock *currentBlock = BasicBlock::Create(module->getContext(), currentName,
function, 0);
2375 Constant *currentIdentifierValue = constantsCache->
get(currentIdentifier);
2378 currentIdentifierValue, shouldUseInterprocessSerializationValue);
2379 new StoreInst(retValue, retVariable, currentBlock);
2381 blocksForString[currentName] = make_pair(currentBlock, currentBlock);
2384 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, 0);
2388 LoadInst *retValue =
new LoadInst(retVariable,
"",
false, finalBlock);
2389 ReturnInst::Create(module->getContext(), retValue, finalBlock);
2405 void VuoCompilerBitcodeGenerator::generateCompositionSetPublishedInputPortValueFunction(
void)
2409 Function::arg_iterator args =
function->arg_begin();
2410 Value *compositionStateValue = args++;
2411 compositionStateValue->setName(
"compositionState");
2412 Value *publishedInputPortNameValue = args++;
2413 publishedInputPortNameValue->setName(
"publishedInputPortName");
2414 Value *valueAsStringValue = args++;
2415 valueAsStringValue->setName(
"valueAsString");
2416 Value *isCompositionRunningValue = args++;
2417 isCompositionRunningValue->setName(
"isCompositionRunning");
2419 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, 0);
2424 ReturnInst::Create(module->getContext(), initialBlock);
2430 PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2431 AllocaInst *inputPortIdentifierVariable =
new AllocaInst(pointerToCharType,
"inputPortIdentifier", initialBlock);
2432 ConstantPointerNull *nullInputPortIdentifier = ConstantPointerNull::get(pointerToCharType);
2433 new StoreInst(nullInputPortIdentifier, inputPortIdentifierVariable,
false, initialBlock);
2441 map<string, pair<BasicBlock *, BasicBlock *> > blocksForString;
2443 for (
size_t i = 0; i < publishedInputPorts.size(); ++i)
2445 string currPublishedInputPortName = publishedInputPorts[i]->getClass()->getName();
2446 BasicBlock *currBlock = BasicBlock::Create(module->getContext(), currPublishedInputPortName,
function, 0);
2450 Value *inputPortIdentifierValue = constantsCache->
get(inputPortIdentifier);
2452 new StoreInst(inputPortIdentifierValue, inputPortIdentifierVariable,
false, currBlock);
2454 blocksForString[currPublishedInputPortName] = make_pair(currBlock, currBlock);
2457 BasicBlock *checkBlock = BasicBlock::Create(module->getContext(),
"check",
function, 0);
2458 BasicBlock *scheduleBlock = BasicBlock::Create(module->getContext(),
"schedule",
function, 0);
2459 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, 0);
2466 Value *inputPortIdentifierValue =
new LoadInst(inputPortIdentifierVariable,
"",
false, checkBlock);
2467 ICmpInst *portIdentifierNotEqualsNull =
new ICmpInst(*checkBlock, ICmpInst::ICMP_NE, inputPortIdentifierValue, nullInputPortIdentifier,
"");
2468 BranchInst::Create(scheduleBlock, finalBlock, portIdentifierNotEqualsNull, checkBlock);
2477 inputPortIdentifierValue, valueAsStringValue,
2478 isCompositionRunningValue);
2484 Value *nodeContextValue = triggerNode->
generateGetContext(module, scheduleBlock, compositionStateValue);
2488 workerFunctionName, contextValue);
2490 BranchInst::Create(finalBlock, scheduleBlock);
2491 ReturnInst::Create(module->getContext(), finalBlock);
2498 Function::arg_iterator workerArgs = workerFunction->arg_begin();
2499 Value *contextValueInWorker = workerArgs++;
2500 contextValueInWorker->setName(
"context");
2502 BasicBlock *workerBlock = BasicBlock::Create(module->getContext(),
"", workerFunction, 0);
2509 Type *voidPointerType = contextValueInWorker->getType();
2510 Type *voidPointerPointerType = PointerType::get(voidPointerType, 0);
2512 Type *boolType = compositionSetPortValueFunction->getFunctionType()->getParamType(3);
2514 Value *contextValueAsVoidPointerArray =
new BitCastInst(contextValueInWorker, voidPointerPointerType,
"", workerBlock);
2516 Value *compositionStateValueInWorker =
new BitCastInst(compositionStateAsVoidPointer, compositionStatePointerType,
"", workerBlock);
2519 Value *inputPortIdentifierValueInWorker =
new BitCastInst(inputPortIdentifierAsVoidPointer, pointerToCharType,
"", workerBlock);
2522 Value *valueAsStringValueInWorker =
new BitCastInst(valueAsStringValueAsVoidPointer, pointerToCharType,
"", workerBlock);
2525 Value *isCompositionRunningValueInWorker =
new PtrToIntInst(isCompositionRunningValueAsVoidPointer, boolType,
"", workerBlock);
2534 Value *trueValue = ConstantInt::get(boolType, 1);
2536 vector<Value *> setValueArgs;
2537 setValueArgs.push_back(compositionStateValueInWorker);
2538 setValueArgs.push_back(inputPortIdentifierValueInWorker);
2539 setValueArgs.push_back(valueAsStringValueInWorker);
2540 setValueArgs.push_back(isCompositionRunningValueInWorker);
2541 setValueArgs.push_back(isCompositionRunningValueInWorker);
2542 setValueArgs.push_back(isCompositionRunningValueInWorker);
2543 setValueArgs.push_back(trueValue);
2544 setValueArgs.push_back(trueValue);
2545 CallInst::Create(compositionSetPortValueFunction, setValueArgs,
"", workerBlock);
2547 ReturnInst::Create(module->getContext(), workerBlock);
2557 void VuoCompilerBitcodeGenerator::generateSetPublishedInputPortValueFunction(
void)
2561 Function::arg_iterator args =
function->arg_begin();
2562 Value *publishedInputPortNameValue = args++;
2563 publishedInputPortNameValue->setName(
"publishedInputPortName");
2564 Value *valueAsStringValue = args++;
2565 valueAsStringValue->setName(
"valueAsString");
2567 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
2574 Value *trueValue = ConstantInt::get(compositionFunction->getFunctionType()->getParamType(3), 1);
2576 vector<Value *> compositionArgs;
2577 compositionArgs.push_back(compositionStateValue);
2578 compositionArgs.push_back(publishedInputPortNameValue);
2579 compositionArgs.push_back(valueAsStringValue);
2580 compositionArgs.push_back(trueValue);
2581 CallInst::Create(compositionFunction, compositionArgs,
"", block);
2585 ReturnInst::Create(module->getContext(), block);
2592 void VuoCompilerBitcodeGenerator::generateTransmissionFromOutputPort(Function *
function, BasicBlock *¤tBlock,
2593 Value *compositionStateValue,
2595 Value *eventValue, Value *dataValue,
2596 bool requiresEvent,
bool shouldSendTelemetry)
2598 IntegerType *boolType = IntegerType::get(module->getContext(), 1);
2599 PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2603 Constant *trueValue = ConstantInt::get(boolType, 1);
2604 Constant *falseValue = ConstantInt::get(boolType, 0);
2605 Constant *transmittedEventValue = (requiresEvent ? trueValue : falseValue);
2608 AllocaInst *dataSummaryVariable =
new AllocaInst(pointerToCharType,
"dataSummary", currentBlock);
2609 new StoreInst(ConstantPointerNull::get(pointerToCharType), dataSummaryVariable, currentBlock);
2611 map<VuoCompilerPort *, ICmpInst *> shouldSummarizeInput;
2612 if (shouldSendTelemetry)
2615 AllocaInst *sentDataVariable =
new AllocaInst(boolType,
"sentData", currentBlock);
2616 new StoreInst(falseValue, sentDataVariable, currentBlock);
2618 for (set<VuoCompilerCable *>::iterator i = outgoingCables.begin(); i != outgoingCables.end(); ++i)
2625 compositionStateValue,
2627 shouldSummarizeInput[inputPort] = shouldSendDataForInput;
2634 compositionStateValue,
2637 for (set<VuoCompilerCable *>::iterator i = outgoingCables.begin(); i != outgoingCables.end(); ++i)
2644 shouldSummarizeOutput = BinaryOperator::Create(Instruction::Or, shouldSummarizeOutput, shouldSummarizeInput[inputPort],
"", currentBlock);
2648 BasicBlock *summaryBlock = BasicBlock::Create(module->getContext(),
"outputSummary",
function, NULL);
2649 BasicBlock *sendOutputBlock = BasicBlock::Create(module->getContext(),
"sendOutput",
function, NULL);
2650 BranchInst::Create(summaryBlock, sendOutputBlock, shouldSummarizeOutput, currentBlock);
2653 new StoreInst(trueValue, sentDataVariable, summaryBlock);
2658 new StoreInst(dataSummaryValue, dataSummaryVariable, summaryBlock);
2660 BranchInst::Create(sendOutputBlock, summaryBlock);
2661 currentBlock = sendOutputBlock;
2666 Value *sentDataValue =
new LoadInst(sentDataVariable,
"",
false, currentBlock);
2667 Value *dataSummaryValue =
new LoadInst(dataSummaryVariable,
"",
false, currentBlock);
2669 Constant *outputPortIdentifierValue = constantsCache->
get(outputPort->
getIdentifier());
2672 transmittedEventValue, sentDataValue, dataSummaryValue);
2678 BasicBlock *transmissionBlock = NULL;
2679 BasicBlock *noTransmissionBlock = NULL;
2680 if (alwaysTransmitsEvent)
2682 transmissionBlock = currentBlock;
2686 transmissionBlock = BasicBlock::Create(module->getContext(),
"transmission",
function, NULL);
2687 noTransmissionBlock = BasicBlock::Create(module->getContext(),
"noTransmission",
function, NULL);
2689 ConstantInt *zeroValue = ConstantInt::get(
static_cast<IntegerType *
>(eventValue->getType()), 0);
2690 ICmpInst *eventValueIsTrue =
new ICmpInst(*currentBlock, ICmpInst::ICMP_NE, eventValue, zeroValue,
"");
2691 BranchInst::Create(transmissionBlock, noTransmissionBlock, eventValueIsTrue, currentBlock);
2695 for (set<VuoCompilerCable *>::iterator i = outgoingCables.begin(); i != outgoingCables.end(); ++i)
2700 Value *inputNodeContextValue = inputNode->
generateGetContext(module, transmissionBlock, compositionStateValue);
2702 Value *inputPortContextValue = inputPort->
generateGetPortContext(module, transmissionBlock, inputNodeContextValue);
2704 Value *transmittedDataValue = (cable->
carriesData() ? dataValue : NULL);
2706 cable->
generateTransmission(module, transmissionBlock, inputNodeContextValue, inputPortContextValue, transmittedDataValue, requiresEvent);
2711 AllocaInst *inputDataSummaryVariable =
new AllocaInst(pointerToCharType,
"inputDataSummary", transmissionBlock);
2712 new StoreInst(ConstantPointerNull::get(pointerToCharType), inputDataSummaryVariable, transmissionBlock);
2715 AllocaInst *receivedDataVariable =
new AllocaInst(boolType,
"receivedData", transmissionBlock);
2716 new StoreInst(falseValue, receivedDataVariable, transmissionBlock);
2721 BasicBlock *summaryBlock = BasicBlock::Create(module->getContext(),
"inputSummary",
function, NULL);
2722 BasicBlock *sendInputBlock = BasicBlock::Create(module->getContext(),
"sendInput",
function, NULL);
2723 BranchInst::Create(summaryBlock, sendInputBlock, shouldSummarizeInput[inputPort], transmissionBlock);
2725 Value *inputDataSummaryValue;
2726 if (transmittedDataValue)
2729 new StoreInst(trueValue, receivedDataVariable, summaryBlock);
2732 inputDataSummaryValue =
new LoadInst(dataSummaryVariable,
"",
false, summaryBlock);
2737 Value *inputDataValue = inputPort->
generateLoadData(module, summaryBlock, inputNodeContextValue, inputPortContextValue);
2740 new StoreInst(inputDataSummaryValue, inputDataSummaryVariable, summaryBlock);
2742 BranchInst::Create(sendInputBlock, summaryBlock);
2743 transmissionBlock = sendInputBlock;
2746 Value *receivedDataValue =
new LoadInst(receivedDataVariable,
"",
false, transmissionBlock);
2747 Value *inputDataSummaryValue =
new LoadInst(inputDataSummaryVariable,
"",
false, transmissionBlock);
2749 Constant *inputPortIdentifierValue = constantsCache->
get(inputPort->
getIdentifier());
2752 transmittedEventValue, receivedDataValue, inputDataSummaryValue);
2754 if (inputDataType && ! transmittedDataValue)
2762 if (alwaysTransmitsEvent)
2764 currentBlock = transmissionBlock;
2768 BranchInst::Create(noTransmissionBlock, transmissionBlock);
2769 currentBlock = noTransmissionBlock;
2772 if (shouldSendTelemetry && dataValue)
2776 LoadInst *dataSummaryValue =
new LoadInst(dataSummaryVariable,
"",
false, currentBlock);
2777 CallInst::Create(freeFunction, dataSummaryValue,
"", currentBlock);
2785 void VuoCompilerBitcodeGenerator::generateTransmissionFromNode(Function *
function, BasicBlock *¤tBlock,
2786 Value *compositionStateValue, Value *nodeContextValue,
2790 for (vector<VuoPort *>::iterator i = outputPorts.begin(); i != outputPorts.end(); ++i)
2794 if (! outputEventPort)
2797 Value *portContextValue = outputEventPort->
generateGetPortContext(module, currentBlock, nodeContextValue);
2798 Value *outputEventValue = outputEventPort->
generateLoadEvent(module, currentBlock, nodeContextValue, portContextValue);
2800 BasicBlock *telemetryBlock = NULL;
2801 BasicBlock *noTelemetryBlock = NULL;
2804 telemetryBlock = BasicBlock::Create(module->getContext(),
"",
function, NULL);
2805 noTelemetryBlock = BasicBlock::Create(module->getContext(),
"",
function, NULL);
2808 ConstantInt *zeroValue = ConstantInt::get(
static_cast<IntegerType *
>(outputEventValue->getType()), 0);
2809 ICmpInst *eventValueIsTrue =
new ICmpInst(*currentBlock, ICmpInst::ICMP_NE, outputEventValue, zeroValue,
"");
2810 BranchInst::Create(telemetryBlock, noTelemetryBlock, eventValueIsTrue, currentBlock);
2814 telemetryBlock = currentBlock;
2819 Value *outputDataValue = (outputData ?
2820 outputEventPort->
generateLoadData(module, telemetryBlock, nodeContextValue, portContextValue) :
2822 generateTransmissionFromOutputPort(
function, telemetryBlock, compositionStateValue,
2823 node, outputEventPort, outputEventValue, outputDataValue, requiresEvent, shouldSendTelemetry);
2827 BranchInst::Create(noTelemetryBlock, telemetryBlock);
2828 currentBlock = noTelemetryBlock;
2832 currentBlock = telemetryBlock;
2841 void VuoCompilerBitcodeGenerator::generateTelemetryFromPublishedOutputNode(Function *
function, BasicBlock *¤tBlock, Value *compositionStateValue,
2844 IntegerType *boolType = IntegerType::get(module->getContext(), 1);
2845 PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2855 BasicBlock *telemetryBlock = BasicBlock::Create(module->getContext(),
"",
function, NULL);
2856 BasicBlock *noTelemetryBlock = BasicBlock::Create(module->getContext(),
"",
function, NULL);
2859 Value *eventValue = inputEventPort->
generateLoadEvent(module, currentBlock, nodeContextValue);
2860 ConstantInt *zeroValue = ConstantInt::get(
static_cast<IntegerType *
>(eventValue->getType()), 0);
2861 ICmpInst *eventValueIsTrue =
new ICmpInst(*currentBlock, ICmpInst::ICMP_NE, eventValue, zeroValue,
"");
2862 BranchInst::Create(telemetryBlock, noTelemetryBlock, eventValueIsTrue, currentBlock);
2865 Value *dataValue = data ? inputEventPort->
generateLoadData(module, telemetryBlock, nodeContextValue) : NULL;
2866 Constant *trueValue = ConstantInt::get(boolType, 1);
2867 Constant *falseValue = ConstantInt::get(boolType, 0);
2869 Value *sentDataValue = NULL;
2870 Value *dataSummaryValue = NULL;
2874 sentDataValue = trueValue;
2883 sentDataValue = falseValue;
2886 dataSummaryValue = ConstantPointerNull::get(pointerToCharType);
2891 sentDataValue, dataSummaryValue);
2893 BranchInst::Create(noTelemetryBlock, telemetryBlock);
2894 currentBlock = noTelemetryBlock;
2904 void VuoCompilerBitcodeGenerator::generateDataOnlyTransmissionFromNode(Function *
function, BasicBlock *¤tBlock, Value *compositionStateValue,
2906 bool shouldUpdateTriggers,
bool shouldSendTelemetry)
2909 if (downstreamNodes.empty())
2912 if (shouldWaitForDownstreamNodes)
2915 generateLockNodes(module, currentBlock, compositionStateValue, downstreamNodes,
nullptr);
2919 vector<VuoCompilerNode *> nodesToVisit = downstreamNodes;
2920 nodesToVisit.insert(nodesToVisit.begin(), node);
2925 Value *nodeContextValue = visitedNode->generateGetContext(module, currentBlock, compositionStateValue);
2928 vector<VuoPort *> inputPorts = visitedNode->getBase()->getInputPorts();
2936 generateNodeExecution(
function, currentBlock, compositionStateValue, visitedNode,
false);
2939 generateTransmissionFromNode(
function, currentBlock, compositionStateValue, nodeContextValue, visitedNode,
false, shouldSendTelemetry);
2945 if (visitedNode != node)
2947 if (shouldUpdateTriggers)
2950 visitedNode->generateCallbackUpdateFunctionCall(module, currentBlock, compositionStateValue);
2953 if (shouldWaitForDownstreamNodes)
2956 generateUnlockNodes(module, currentBlock, compositionStateValue, vector<VuoCompilerNode *>(1, visitedNode));
2965 void VuoCompilerBitcodeGenerator::generateNodeExecution(Function *
function, BasicBlock *¤tBlock,
2967 bool shouldSendTelemetry)
2971 if (shouldSendTelemetry)
2982 if (shouldSendTelemetry)
2992 void VuoCompilerBitcodeGenerator::generateAllocation(
void)
2995 generateAllocation_Pro();
3000 new GlobalVariable(*module, value->getType(),
true, GlobalValue::ExternalLinkage, value,
"vuoTopLevelCompositionIdentifier");
3011 void VuoCompilerBitcodeGenerator::generateSetupFunction(
bool isStatefulComposition)
3014 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
3023 CallInst::Create(compositionCreateAndRegisterMetadataFunction, topLevelCompositionStateValue,
"", block);
3029 isStatefulComposition, publishedOutputPortCount);
3034 Value *falseValue = ConstantInt::get(compositionSetPublishedInputPortValueFunction->getFunctionType()->getParamType(3), 0);
3041 vector<Value *> args;
3042 args.push_back(topLevelCompositionStateValue);
3043 args.push_back( constantsCache->
get(name) );
3044 args.push_back( constantsCache->
get(initialValue) );
3045 args.push_back(falseValue);
3046 CallInst::Create(compositionSetPublishedInputPortValueFunction, args,
"", block);
3052 CallInst::Create(compositionPerformDataOnlyTransmissionsFunction, topLevelCompositionStateValue,
"", block);
3056 for (map<VuoCompilerTriggerPort *, Function *>::iterator i = topLevelTriggerFunctions.begin(); i != topLevelTriggerFunctions.end(); ++i)
3059 Function *
function = i->second;
3062 Value *nodeContextValue = node->
generateGetContext(module, block, topLevelCompositionStateValue);
3068 for (map<
string, map<
size_t, map<VuoCompilerTriggerDescription *, Function *> > >::iterator i = subcompositionTriggerFunctions.begin(); i != subcompositionTriggerFunctions.end(); ++i)
3070 string compositionIdentifier = i->first;
3072 for (map<
size_t, map<VuoCompilerTriggerDescription *, Function *> >::iterator j = i->second.begin(); j != i->second.end(); ++j)
3074 size_t nodeIndex = j->first;
3076 for (map<VuoCompilerTriggerDescription *, Function *>::iterator k = j->second.begin(); k != j->second.end(); ++k)
3079 Function *
function = k->second;
3081 Value *compositionIdentifierValue = constantsCache->
get(compositionIdentifier);
3096 ReturnInst::Create(module->getContext(), block);
3105 void VuoCompilerBitcodeGenerator::generateCleanupFunction(
void)
3108 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
3118 ReturnInst::Create(module->getContext(), block);
3126 void VuoCompilerBitcodeGenerator::generateInstanceInitFunction(
bool isStatefulComposition)
3129 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
3131 if (isStatefulComposition)
3133 map<VuoPort *, size_t> indexOfParameter;
3136 vector<VuoPort *>(),
3137 indexOfParameter, constantsCache);
3143 CallInst::Create(nodeInstanceInitFunction, topLevelCompositionStateValue,
"", block);
3148 ReturnInst::Create(module->getContext(), block);
3156 void VuoCompilerBitcodeGenerator::generateInstanceFiniFunction(
bool isStatefulComposition)
3159 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
3161 if (isStatefulComposition)
3171 PointerType *instanceDataType =
static_cast<PointerType *
>( nodeInstanceFiniFunction->getFunctionType()->getParamType(1) );
3172 ConstantPointerNull *nullInstanceDataValue = ConstantPointerNull::get(instanceDataType);
3174 vector<Value *> args;
3175 args.push_back(topLevelCompositionStateValue);
3176 args.push_back(nullInstanceDataValue);
3177 CallInst::Create(nodeInstanceFiniFunction, args,
"", block);
3182 ReturnInst::Create(module->getContext(), block);
3190 void VuoCompilerBitcodeGenerator::generateInstanceTriggerStartFunction(
bool isStatefulComposition)
3193 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
3195 if (isStatefulComposition)
3197 map<VuoPort *, size_t> indexOfParameter;
3200 vector<VuoPort *>(),
3208 PointerType *instanceDataType =
static_cast<PointerType *
>( nodeInstanceTriggerStartFunction->getFunctionType()->getParamType(1) );
3209 ConstantPointerNull *nullInstanceDataValue = ConstantPointerNull::get(instanceDataType);
3211 vector<Value *> args;
3212 args.push_back(topLevelCompositionStateValue);
3213 args.push_back(nullInstanceDataValue);
3214 CallInst::Create(nodeInstanceTriggerStartFunction, args,
"", block);
3219 ReturnInst::Create(module->getContext(), block);
3227 void VuoCompilerBitcodeGenerator::generateInstanceTriggerStopFunction(
bool isStatefulComposition)
3230 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
3241 PointerType *instanceDataType =
static_cast<PointerType *
>( nodeInstanceTriggerStopFunction->getFunctionType()->getParamType(1) );
3242 ConstantPointerNull *nullInstanceDataValue = ConstantPointerNull::get(instanceDataType);
3244 vector<Value *> args;
3245 args.push_back(topLevelCompositionStateValue);
3246 args.push_back(nullInstanceDataValue);
3247 CallInst::Create(nodeInstanceTriggerStopFunction, args,
"", block);
3252 ReturnInst::Create(module->getContext(), block);
3260 void VuoCompilerBitcodeGenerator::generateTriggerFunctions(
void)
3262 auto isSpinOffTrigger = [] (
const string &nodeClassName)
3269 map<VuoCompilerTriggerPort *, Function *> workerFunctionForTrigger;
3272 Function *workerFunction = generateTriggerWorkerFunction(trigger);
3273 workerFunctionForTrigger[trigger] = workerFunction;
3276 if (isTopLevelComposition)
3278 for (map<VuoCompilerTriggerPort *, Function *>::iterator i = workerFunctionForTrigger.begin(); i != workerFunctionForTrigger.end(); ++i)
3281 Function *workerFunction = i->second;
3298 int minThreadsNeeded, maxThreadsNeeded;
3301 int chainCount = (int)graph->
getChains()[trigger].size();
3304 portIdentifier, portContextIndex, canDropEvents, isPublishedTrigger, isSpinOff,
3305 minThreadsNeeded, maxThreadsNeeded, chainCount, workerFunction);
3306 topLevelTriggerFunctions[trigger] =
function;
3317 for (vector<VuoCompilerTriggerDescription *>::iterator j = triggers.begin(); j != triggers.end(); ++j)
3332 string fullSubcompositionNodeIdentifier = (subcompositionNodeIdentifier.empty() ?
3339 int minThreadsNeeded, maxThreadsNeeded;
3340 if (isPublishedTrigger)
3341 minThreadsNeeded = maxThreadsNeeded = -1;
3350 Function *
function = generateTriggerSchedulerFunction(dataType, fullSubcompositionNodeIdentifier, triggerNodeIndex,
3351 portIdentifier, portContextIndex, canDropEvents, isPublishedTrigger, isSpinOff,
3352 minThreadsNeeded, maxThreadsNeeded, chainCount, workerFunction);
3354 subcompositionTriggerFunctions[fullSubcompositionNodeIdentifier][triggerNodeIndex][trigger] =
function;
3403 Function * VuoCompilerBitcodeGenerator::generateTriggerSchedulerFunction(
VuoType *dataType,
3404 string compositionIdentifier,
size_t nodeIndex,
3405 string portIdentifier,
int portContextIndex,
3406 bool canDropEvents,
bool isPublishedInputTrigger,
bool isSpinOff,
3407 int minThreadsNeeded,
int maxThreadsNeeded,
int chainCount,
3408 Function *workerFunction)
3413 Function *
function = Function::Create(functionType, GlobalValue::InternalLinkage, functionName, module);
3418 function->setAttributes(paramAttributes);
3421 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, NULL);
3422 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, NULL);
3423 BasicBlock *scheduleBlock = BasicBlock::Create(module->getContext(),
"schedule",
function, NULL);
3426 Value *compositionIdentifierValue = constantsCache->
get(compositionIdentifier);
3437 BasicBlock *checkEventDropBlock = BasicBlock::Create(module->getContext(),
"checkEventDrop",
function, NULL);
3438 BranchInst::Create(checkEventDropBlock, initialBlock);
3442 Constant *zeroValue = ConstantInt::get(retValue->getType(), 0);
3443 ICmpInst *isTriggerAvailableValue =
new ICmpInst(*checkEventDropBlock, ICmpInst::ICMP_EQ, retValue, zeroValue,
"");
3444 BasicBlock *dropEventBlock = BasicBlock::Create(module->getContext(),
"dropEvent",
function, NULL);
3445 BranchInst::Create(scheduleBlock, dropEventBlock, isTriggerAvailableValue, checkEventDropBlock);
3452 Constant *portIdentifierValue = constantsCache->
get(portIdentifier);
3457 BranchInst::Create(finalBlock, dropEventBlock);
3461 BranchInst::Create(scheduleBlock, initialBlock);
3468 Value *eventIdValue;
3469 if (! isPublishedInputTrigger)
3491 compositionStateValue, eventIdValue, portContextValue, dataType,
3492 minThreadsNeeded, maxThreadsNeeded, chainCount, workerFunction);
3493 BranchInst::Create(finalBlock, scheduleBlock);
3495 ReturnInst::Create(module->getContext(), finalBlock);
3649 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, NULL);
3650 BasicBlock *triggerBlock = BasicBlock::Create(module->getContext(),
"trigger",
function, NULL);
3651 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, NULL);
3658 Value *triggerNodeContextValue = triggerNode->
generateGetContext(module, initialBlock, compositionStateValue);
3663 bool isNodeEventForSubcomposition = (! isTopLevelComposition && isPublishedInputTrigger);
3665 if (! isNodeEventForSubcomposition)
3668 BasicBlock *isPausedBlock = BasicBlock::Create(module->getContext(),
"isPaused",
function, NULL);
3670 BranchInst::Create(isPausedBlock, triggerBlock, isPausedValueIsTrue, initialBlock);
3677 vector<VuoCompilerNode *> publishedOutputNodeVector(1, publishedOutputNode);
3678 if (publishedOutputNode && ! isPublishedInputTrigger)
3679 generateLockNodes(module, isPausedBlock, compositionStateValue, publishedOutputNodeVector);
3684 if (isPublishedInputTrigger)
3687 vector<VuoCompilerNode *> triggerWaitNodes = getNodesToWaitOnBeforeTransmission(trigger);
3688 generateUnlockNodes(module, isPausedBlock, compositionStateValue, triggerWaitNodes);
3692 if (publishedOutputNode)
3693 generateUnlockNodes(module, isPausedBlock, compositionStateValue, publishedOutputNodeVector);
3705 BranchInst::Create(finalBlock, isPausedBlock);
3710 BranchInst::Create(triggerBlock, initialBlock);
3713 if (isPublishedInputTrigger)
3715 if (! isNodeEventForSubcomposition)
3718 vector<VuoCompilerNode *> triggerWaitNodes = getNodesToWaitOnBeforeTransmission(trigger);
3720 if (find(triggerWaitNodes.begin(), triggerWaitNodes.end(), publishedOutputNode) == triggerWaitNodes.end())
3722 vector<VuoCompilerNode *> publishedOutputNodeVector(1, publishedOutputNode);
3723 generateUnlockNodes(module, triggerBlock, compositionStateValue, publishedOutputNodeVector);
3730 vector<VuoCompilerNode *> triggerWaitNodes = getNodesToWaitOnBeforeTransmission(trigger);
3731 generateLockNodes(module, triggerBlock, compositionStateValue, triggerWaitNodes, eventIdValue);
3734 Value *triggerDataValue = trigger->
generateDataValueUpdate(module, triggerBlock,
function, triggerNodeContextValue);
3737 generateTransmissionFromOutputPort(
function, triggerBlock, compositionStateValue, triggerNode, trigger, NULL, triggerDataValue);
3742 if (find(downstreamNodes.begin(), downstreamNodes.end(), triggerNode) == downstreamNodes.end())
3743 generateUnlockNodes(module, triggerBlock, compositionStateValue, vector<VuoCompilerNode *>(1, triggerNode));
3755 map<VuoCompilerChain *, vector<VuoCompilerChain *> > chainsImmediatelyDownstream;
3756 map<VuoCompilerChain *, vector<VuoCompilerChain *> > chainsImmediatelyUpstream;
3757 set<VuoCompilerChain *> chainsScheduled;
3759 vector<VuoCompilerChain *> allChains = chainsForTrigger[trigger];
3761 if (! allChains.empty())
3764 for (vector<VuoCompilerChain *>::iterator i = allChains.begin(); i != allChains.end(); ++i)
3769 for (vector<VuoCompilerChain *>::iterator j = allChains.begin(); j != allChains.end(); ++j)
3773 if (chain == otherChain)
3778 if (graph->
mayTransmit(lastNodeInOtherChain, firstNodeInThisChain, trigger))
3780 chainsImmediatelyUpstream[chain].push_back(otherChain);
3781 chainsImmediatelyDownstream[otherChain].push_back(chain);
3790 vector<VuoCompilerChain *> firstChains;
3791 for (vector<VuoCompilerChain *>::iterator i = allChains.begin(); i != allChains.end(); ++i)
3794 map<VuoCompilerChain *, vector<VuoCompilerChain *> >::iterator upstreamIter = chainsImmediatelyUpstream.find(chain);
3795 if (upstreamIter == chainsImmediatelyUpstream.end())
3796 firstChains.push_back(chain);
3801 firstChains.pop_back();
3802 chainsScheduled.insert(chainToExecute);
3803 size_t chainIndex = find(allChains.begin(), allChains.end(), chainToExecute) - allChains.begin();
3807 int minThreadsNeeded, maxThreadsNeeded;
3810 eventIdValue, compositionStateValue, chainIndex);
3813 generateAndScheduleChainWorkerFunctions(triggerBlock, compositionStateValue, contextValue, firstChains, trigger,
3814 allChains, chainsImmediatelyDownstream, chainsImmediatelyUpstream, chainsScheduled);
3817 generateChainExecution(
function, triggerBlock, compositionStateValue, contextValue, eventIdValue, chainToExecute, trigger,
3818 allChains, chainsImmediatelyDownstream, chainsImmediatelyUpstream, chainsScheduled);
3826 if (isNodeEventForSubcomposition)
3834 BranchInst::Create(finalBlock, triggerBlock);
3840 ReturnInst::Create(module->getContext(), finalBlock);
3848 void VuoCompilerBitcodeGenerator::generateAndScheduleChainWorkerFunctions(BasicBlock *schedulerBlock,
3849 Value *compositionStateValueInScheduler, Value *contextValueInScheduler,
3851 const vector<VuoCompilerChain *> &allChains,
3852 const map<
VuoCompilerChain *, vector<VuoCompilerChain *> > &chainsImmediatelyDownstream,
3853 const map<
VuoCompilerChain *, vector<VuoCompilerChain *> > &chainsImmediatelyUpstream,
3854 set<VuoCompilerChain *> &chainsScheduled)
3857 vector<VuoCompilerChain *> uniqueChainsToSchedule;
3858 for (vector<VuoCompilerChain *>::const_iterator i = chainsToSchedule.begin(); i != chainsToSchedule.end(); ++i)
3861 if (chainsScheduled.find(chain) == chainsScheduled.end())
3863 uniqueChainsToSchedule.push_back(chain);
3864 chainsScheduled.insert(chain);
3869 for (vector<VuoCompilerChain *>::const_iterator i = uniqueChainsToSchedule.begin(); i != uniqueChainsToSchedule.end(); ++i)
3873 for (vector<VuoCompilerChain *>::const_iterator i = uniqueChainsToSchedule.begin(); i != uniqueChainsToSchedule.end(); ++i)
3876 generateAndScheduleChainWorkerFunction(schedulerBlock, compositionStateValueInScheduler, contextValueInScheduler,
3877 chain, trigger, allChains, chainsImmediatelyDownstream, chainsImmediatelyUpstream,
3885 void VuoCompilerBitcodeGenerator::generateAndScheduleChainWorkerFunction(BasicBlock *schedulerBlock,
3886 Value *compositionStateValueInScheduler, Value *contextValueInScheduler,
3888 const vector<VuoCompilerChain *> &allChains,
3889 const map<
VuoCompilerChain *, vector<VuoCompilerChain *> > &chainsImmediatelyDownstream,
3890 const map<
VuoCompilerChain *, vector<VuoCompilerChain *> > &chainsImmediatelyUpstream,
3891 set<VuoCompilerChain *> &chainsScheduled)
3893 int minThreadsNeeded, maxThreadsNeeded;
3896 size_t chainIndex = find(allChains.begin(), allChains.end(), chain) - allChains.begin();
3898 vector<VuoCompilerChain *> upstreamChains;
3899 map<VuoCompilerChain *, vector<VuoCompilerChain *> >::const_iterator upstreamChainsIter = chainsImmediatelyUpstream.find(chain);
3900 if (upstreamChainsIter != chainsImmediatelyUpstream.end())
3901 upstreamChains = upstreamChainsIter->second;
3903 vector<size_t> upstreamChainIndices;
3904 for (vector<VuoCompilerChain *>::iterator i = upstreamChains.begin(); i != upstreamChains.end(); ++i)
3905 upstreamChainIndices.push_back( find(allChains.begin(), allChains.end(), *i) - allChains.begin() );
3908 Function *chainWorker = chain->
generateScheduleWorker(module, schedulerBlock, compositionStateValueInScheduler, contextValueInScheduler,
3909 trigger->
getIdentifier(), minThreadsNeeded, maxThreadsNeeded, chainIndex,
3910 upstreamChainIndices);
3912 BasicBlock *chainBlock = BasicBlock::Create(module->getContext(),
"", chainWorker, 0);
3913 Value *contextValueInChainWorker = chainWorker->arg_begin();
3915 Value *eventIdValue = chain->
generateEventIdValue(module, chainBlock, contextValueInChainWorker);
3918 generateChainExecution(chainWorker, chainBlock, compositionStateValueInChainWorker, contextValueInChainWorker, eventIdValue, chain, trigger,
3919 allChains, chainsImmediatelyDownstream, chainsImmediatelyUpstream, chainsScheduled);
3924 ReturnInst::Create(module->getContext(), chainBlock);
3930 void VuoCompilerBitcodeGenerator::generateChainExecution(Function *
function, BasicBlock *&block,
3931 Value *compositionStateValue, Value *contextValue,
3933 const vector<VuoCompilerChain *> &allChains,
3934 const map<
VuoCompilerChain *, vector<VuoCompilerChain *> > &chainsImmediatelyDownstream,
3935 const map<
VuoCompilerChain *, vector<VuoCompilerChain *> > &chainsImmediatelyUpstream,
3936 set<VuoCompilerChain *> &chainsScheduled)
3938 size_t chainIndex = find(allChains.begin(), allChains.end(), chain) - allChains.begin();
3939 Value *chainIndexValue = ConstantInt::get(eventIdValue->getType(), chainIndex);
3942 vector<VuoCompilerNode *> chainNodes = chain->
getNodes();
3943 for (vector<VuoCompilerNode *>::iterator i = chainNodes.begin(); i != chainNodes.end(); ++i)
3947 Function *nodeExecutionFunction = executionFunctionForNode[node];
3948 if (! nodeExecutionFunction)
3950 nodeExecutionFunction = generateNodeExecutionFunction(module, node);
3951 executionFunctionForNode[node] = nodeExecutionFunction;
3954 Function *nodeTransmissionFunction = transmissionFunctionForNode[node];
3955 if (! nodeTransmissionFunction)
3957 nodeTransmissionFunction = generateNodeTransmissionFunction(module, node);
3958 transmissionFunctionForNode[node] = nodeTransmissionFunction;
3962 vector<Value *> nodeExecutionArgs;
3963 nodeExecutionArgs.push_back(compositionStateValue);
3964 nodeExecutionArgs.push_back(eventIdValue);
3965 nodeExecutionArgs.push_back(chainIndexValue);
3966 CallInst *isHitValue = CallInst::Create(nodeExecutionFunction, nodeExecutionArgs,
"", block);
3971 vector<VuoCompilerNode *> outputNodes = getNodesToWaitOnBeforeTransmission(trigger, node);
3972 generateLockNodes(module, block, compositionStateValue, outputNodes, eventIdValue);
3976 vector<Value *> nodeTransmissionArgs;
3977 nodeTransmissionArgs.push_back(compositionStateValue);
3978 nodeTransmissionArgs.push_back(isHitValue);
3979 CallInst::Create(nodeTransmissionFunction, nodeTransmissionArgs,
"", block);
3988 generateUnlockNodes(module, block, compositionStateValue, vector<VuoCompilerNode *>(1, node));
3993 vector<VuoCompilerChain *> downstreamChains;
3994 map<VuoCompilerChain *, vector<VuoCompilerChain *> >::const_iterator downstreamChainsIter = chainsImmediatelyDownstream.find(chain);
3995 if (downstreamChainsIter != chainsImmediatelyDownstream.end())
3996 downstreamChains = downstreamChainsIter->second;
3997 if (! downstreamChains.empty())
3999 vector<size_t> downstreamChainIndices;
4000 for (vector<VuoCompilerChain *>::iterator i = downstreamChains.begin(); i != downstreamChains.end(); ++i)
4001 downstreamChainIndices.push_back( find(allChains.begin(), allChains.end(), *i) - allChains.begin() );
4003 vector<VuoCompilerChain *> nextChains;
4004 for (vector<VuoCompilerChain *>::iterator i = downstreamChains.begin(); i != downstreamChains.end(); ++i)
4007 nextChains.push_back(downstreamChain);
4010 generateAndScheduleChainWorkerFunctions(block, compositionStateValue, contextValue, nextChains, trigger, allChains,
4011 chainsImmediatelyDownstream, chainsImmediatelyUpstream, chainsScheduled);
4063 Function * VuoCompilerBitcodeGenerator::generateNodeExecutionFunction(Module *module,
VuoCompilerNode *node)
4067 Type *boolType = IntegerType::get(module->getContext(), 1);
4069 vector<Type *> params;
4070 params.push_back(pointerToCompositionStateType);
4071 params.push_back(eventIdType);
4072 params.push_back(eventIdType);
4073 FunctionType *functionType = FunctionType::get(boolType, params,
false);
4074 Function *
function = Function::Create(functionType, GlobalValue::InternalLinkage, functionName, module);
4076 Function::arg_iterator args =
function->arg_begin();
4077 Value *compositionStateValue = args++;
4078 compositionStateValue->setName(
"compositionState");
4079 Value *eventIdValue = args++;
4080 eventIdValue->setName(
"eventId");
4081 Value *chainIndexValue = args++;
4082 chainIndexValue->setName(
"chainIndex");
4084 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, NULL);
4085 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, NULL);
4087 Value *nodeContextValue = node->
generateGetContext(module, initialBlock, compositionStateValue);
4092 if (isTopLevelComposition)
4096 BranchInst::Create(finalBlock, initialBlock);
4102 BasicBlock *currBlock = initialBlock;
4111 for (
size_t publishedPortIndex = 0; publishedPortIndex < publishedOutputPorts.size(); ++publishedPortIndex)
4117 if (publishedOutputTriggerNames.find( port->
getClass()->
getName() ) != publishedOutputTriggerNames.end())
4119 BasicBlock *triggerBlock = BasicBlock::Create(module->getContext(),
"trigger",
function, NULL);
4120 BasicBlock *nextBlock = BasicBlock::Create(module->getContext(),
"next",
function, NULL);
4121 BranchInst::Create(triggerBlock, nextBlock, isPortHitValue, currBlock);
4129 vector<Value *> args;
4132 Value *dataValue = eventPort->
generateLoadData(module, triggerBlock, nodeContextValue);
4135 Value *secondArg = NULL;
4136 Value **secondArgIfNeeded = (isLoweredToTwoParameters ? &secondArg : NULL);
4138 secondArgIfNeeded, module, triggerBlock);
4139 args.push_back(arg);
4141 args.push_back(secondArg);
4150 CallInst::Create(triggerFunction, args,
"", triggerBlock);
4151 BranchInst::Create(nextBlock, triggerBlock);
4153 currBlock = nextBlock;
4165 ConstantInt *falseValue = ConstantInt::get(
static_cast<IntegerType *
>(subcompositionFinishedValue->getType()), 0);
4166 ICmpInst *subcompositionFinishedIsTrue =
new ICmpInst(*currBlock, ICmpInst::ICMP_NE, subcompositionFinishedValue, falseValue,
"");
4167 BasicBlock *leaveBlock = BasicBlock::Create(module->getContext(),
"leave",
function, NULL);
4168 BasicBlock *signalBlock = BasicBlock::Create(module->getContext(),
"signal",
function, NULL);
4169 BranchInst::Create(leaveBlock, signalBlock, subcompositionFinishedIsTrue, currBlock);
4175 BranchInst::Create(finalBlock, leaveBlock);
4180 generateUnlockNodes(module, signalBlock, compositionStateValue, vector<VuoCompilerNode *>(1, node));
4181 BranchInst::Create(finalBlock, signalBlock);
4187 BasicBlock *executeBlock = BasicBlock::Create(module->getContext(),
"execute",
function, NULL);
4188 BranchInst::Create(executeBlock, finalBlock, isHitValue, initialBlock);
4199 eventIdValue, compositionStateValue, chainIndexValue,
4200 subcompositionIdentifierValue);
4206 generateNodeExecution(
function, executeBlock, compositionStateValue, node, shouldSendTelemetry);
4207 BranchInst::Create(finalBlock, executeBlock);
4210 ReturnInst::Create(module->getContext(), isHitValue, finalBlock);
4239 Function * VuoCompilerBitcodeGenerator::generateNodeTransmissionFunction(Module *module,
VuoCompilerNode *node)
4243 Type *boolType = IntegerType::get(module->getContext(), 1);
4244 vector<Type *> params;
4245 params.push_back(pointerToCompositionStateType);
4246 params.push_back(boolType);
4247 FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params,
false);
4248 Function *
function = Function::Create(functionType, GlobalValue::InternalLinkage, functionName, module);
4250 Function::arg_iterator args =
function->arg_begin();
4251 Value *compositionStateValue = args++;
4252 compositionStateValue->setName(
"compositionState");
4253 Value *isHitValue = args++;
4254 isHitValue->setName(
"isHit");
4256 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, NULL);
4257 BasicBlock *transmitBlock = BasicBlock::Create(module->getContext(),
"transmit",
function, NULL);
4258 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, NULL);
4261 BranchInst::Create(transmitBlock, finalBlock, isHitValue, initialBlock);
4263 Value *nodeContextValue = node->
generateGetContext(module, transmitBlock, compositionStateValue);
4267 if (isTopLevelComposition)
4268 generateTelemetryFromPublishedOutputNode(
function, transmitBlock, compositionStateValue, nodeContextValue, node);
4273 generateTransmissionFromNode(
function, transmitBlock, compositionStateValue, nodeContextValue, node);
4279 BranchInst::Create(finalBlock, transmitBlock);
4280 ReturnInst::Create(module->getContext(), finalBlock);
4290 this->debugMode = debugMode;