42 bool isTopLevelComposition,
53 bool isTopLevelComposition,
57 VuoCompilerBitcodeGenerator_Pro();
62 this->composition = composition;
63 this->isTopLevelComposition = isTopLevelComposition;
64 this->moduleKey = moduleKey;
65 this->compiler = compiler;
72 makePortContextInfo();
73 makeSubcompositionModelPorts();
82 for (vector<VuoPort *>::iterator i = modelOutputPorts.begin(); i != modelOutputPorts.end(); ++i)
105 bool operator() (
const vector<VuoCompilerNode *> &chainNodes1,
const vector<VuoCompilerNode *> &chainNodes2)
112 bool isNode2DownstreamOfNode1 = find(downstreamOfChain1.begin(), downstreamOfChain1.end(), chainNodes2.front()) != downstreamOfChain1.end();
113 bool isNode1DownstreamOfNode2 = find(downstreamOfChain2.begin(), downstreamOfChain2.end(), chainNodes1.front()) != downstreamOfChain2.end();
115 if (isNode2DownstreamOfNode1 && isNode1DownstreamOfNode2)
117 else if (isNode2DownstreamOfNode1)
119 else if (isNode1DownstreamOfNode2)
125 size_t maxNumDownstreamOfTrigger[2] = { 0, 0 };
126 vector<VuoCompilerNode *> chainNodes[2] = { chainNodes1, chainNodes2 };
127 for (
int i = 0; i < 2; ++i)
129 for (vector<VuoCompilerNode *>::const_iterator j = chainNodes[i].begin(); j != chainNodes[i].end(); ++j)
133 for (vector<VuoPort *>::iterator k = outputPorts.begin(); k != outputPorts.end(); ++k)
140 maxNumDownstreamOfTrigger[i] = max(maxNumDownstreamOfTrigger[i], numDownstreamOfTrigger);
146 if (maxNumDownstreamOfTrigger[0] != maxNumDownstreamOfTrigger[1])
147 return maxNumDownstreamOfTrigger[0] > maxNumDownstreamOfTrigger[1];
151 return chainNodes1.front()->getIdentifier() < chainNodes2.front()->getIdentifier();
158 void VuoCompilerBitcodeGenerator::makeOrderedNodes(
void)
164 vector<VuoCompilerChain *> chains;
165 map<VuoCompilerTriggerPort *, vector<VuoCompilerChain *> >::iterator chainsIter = chainsForTrigger.find(trigger);
166 if (chainsIter != chainsForTrigger.end())
167 chains = chainsIter->second;
169 vector< vector<VuoCompilerNode *> > chainNodeLists;
170 set<VuoCompilerNode *> lastNodeInLoop;
173 if (chain->isLastNodeInLoop())
174 lastNodeInLoop.insert( chain->getNodes().front() );
176 chainNodeLists.push_back( chain->getNodes() );
183 sort(chainNodeLists.begin(), chainNodeLists.end(), c);
185 vector<VuoCompilerNode *> orderedNodeList;
188 orderedNodeList.push_back(triggerNode);
190 for (vector<VuoCompilerNode *> chainNodeList : chainNodeLists)
192 auto triggerNodeIter = std::find(chainNodeList.begin(), chainNodeList.end(), triggerNode);
193 if (triggerNodeIter != chainNodeList.end())
194 chainNodeList.erase(triggerNodeIter);
196 orderedNodeList.insert( orderedNodeList.end(), chainNodeList.begin(), chainNodeList.end() );
199 downstreamNodesForTrigger[trigger] = orderedNodeList;
202 vector< vector<VuoCompilerNode *> > orderedNodesPerTrigger;
203 for (
const map<
VuoCompilerTriggerPort *, vector<VuoCompilerNode *> >::value_type &i : downstreamNodesForTrigger)
204 orderedNodesPerTrigger.push_back(i.second);
212 vector<VuoCompilerNode *> nodesInProgress;
213 nodesInProgress.push_back(node);
214 nodesInProgress.insert(nodesInProgress.end(), downstreamNodes.begin(), downstreamNodes.end());
215 orderedNodesPerTrigger.push_back(nodesInProgress);
220 std::sort(orderedNodesPerTrigger.begin(), orderedNodesPerTrigger.end(),
221 [](
const vector<VuoCompilerNode *> &nodes1,
const vector<VuoCompilerNode *> &nodes2) {
222 if (nodes1.size() != nodes2.size())
223 return nodes1.size() < nodes2.size();
228 for (VuoCompilerNode *n : nodes1)
229 oss1 << n->getIdentifier() <<
" ";
230 for (VuoCompilerNode *n : nodes2)
231 oss2 << n->getIdentifier() <<
" ";
232 return oss1.str() < oss2.str();
238 int previousTriggerNodeIndex = -1;
239 for (vector< vector<VuoCompilerNode *> >::reverse_iterator i = orderedNodesPerTrigger.rbegin(); i != orderedNodesPerTrigger.rend(); ++i)
242 int previousNodeIndex = previousTriggerNodeIndex;
243 bool isFirstNode =
true;
246 vector<VuoCompilerNode *>::iterator nodeIter = find(orderedNodes.begin(), orderedNodes.end(), node);
247 if (nodeIter == orderedNodes.end())
248 nodeIter = orderedNodes.insert(orderedNodes.begin() + previousNodeIndex + 1, node);
250 previousNodeIndex = max(previousNodeIndex, (
int)(nodeIter - orderedNodes.begin()));
253 previousTriggerNodeIndex = previousNodeIndex;
261 if (find(orderedNodes.begin(), orderedNodes.end(), node) == orderedNodes.end())
262 orderedNodes.push_back(node);
264 for (
size_t i = 0; i < orderedNodes.size(); ++i)
265 orderedNodes[i]->setIndexInOrderedNodes(i);
271 void VuoCompilerBitcodeGenerator::sortNodes(vector<VuoCompilerNode *> &nodes)
273 vector<VuoCompilerNode *> sortedNodes;
274 for (vector<VuoCompilerNode *>::iterator i = orderedNodes.begin(); i != orderedNodes.end(); ++i)
277 if (find(nodes.begin(), nodes.end(), node) != nodes.end())
278 sortedNodes.push_back(node);
286 vector<VuoCompilerNode *> VuoCompilerBitcodeGenerator::getNodesToWaitOnBeforeTransmission(
VuoCompilerTriggerPort *trigger)
309 vector<VuoCompilerNode *> sortedDownstreamNodes = downstreamNodesForTrigger[trigger];
310 sortNodes(sortedDownstreamNodes);
311 bool hasOutOfOrderDownstreamNodes = (downstreamNodesForTrigger[trigger] != sortedDownstreamNodes);
314 vector<VuoCompilerNode *> nodesToWaitOn;
315 if (hasScatterOverlappedByAnotherTrigger || hasOverlapWithSpinOff || hasOutOfOrderDownstreamNodes)
316 nodesToWaitOn = downstreamNodesForTrigger[trigger];
320 VuoCompilerNode *triggerNode = downstreamNodesForTrigger[trigger].front();
321 if (find(nodesToWaitOn.begin(), nodesToWaitOn.end(), triggerNode) == nodesToWaitOn.end())
322 nodesToWaitOn.push_back(triggerNode);
325 return nodesToWaitOn;
343 vector<VuoCompilerNode *> nodesToWaitOn =
344 (hasGatherOverlappedByAnotherTrigger ?
348 return nodesToWaitOn;
354 void VuoCompilerBitcodeGenerator::makeOrderedTypes(
void)
360 vector<VuoPort *> ports;
361 ports.insert(ports.end(), inputPorts.begin(), inputPorts.end());
362 ports.insert(ports.end(), outputPorts.begin(), outputPorts.end());
370 vector<VuoCompilerType *>::iterator typeIter = find(orderedTypes.begin(), orderedTypes.end(), dataType->
getCompiler());
371 if (typeIter == orderedTypes.end())
381 void VuoCompilerBitcodeGenerator::makePortContextInfo(
void)
387 vector<VuoPort *> ports;
388 ports.insert(ports.end(), inputPorts.begin(), inputPorts.end());
389 ports.insert(ports.end(), outputPorts.begin(), outputPorts.end());
390 for (
size_t i = 0; i < ports.size(); ++i)
403 void VuoCompilerBitcodeGenerator::makeSubcompositionModelPorts(
void)
405 Module module(
"", getGlobalContext());
409 modelInputPorts.insert( modelInputPorts.end(), publishedInputPorts.begin(), publishedInputPorts.end() );
410 modelOutputPorts.insert( modelOutputPorts.end(), publishedOutputPorts.begin(), publishedOutputPorts.end() );
414 for (
size_t i = 0; i < modelOutputPorts.size(); ++i)
416 string portName = modelOutputPorts[i]->getClass()->getName();
417 if (publishedOutputTriggerNames.find(portName) != publishedOutputTriggerNames.end())
421 PointerType *pointerToFunctionType = PointerType::get(functionType, 0);
425 modelOutputPorts[i] = modelTriggerPort->
getBase();
433 void VuoCompilerBitcodeGenerator::makeDependencies(
void)
439 makeDependencies_Pro();
443 compiler->getDependenciesForComposition(composition);
455 bool isStatefulComposition =
false;
460 isStatefulComposition =
true;
465 constantStrings.
clear();
469 module =
new Module(moduleKey, getGlobalContext());
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 generateCompositionWaitForNodeFunction();
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();
540 void VuoCompilerBitcodeGenerator::generateCompositionMetadata(
void)
542 json_object *metadataJson = json_object_new_object();
543 json_object *nodeMetadataJson = json_object_new_object();
551 json_object_object_add(metadataJson,
"title", json_object_new_string(title.c_str()));
554 json_object_object_add(metadataJson,
"description", json_object_new_string(description.c_str()));
556 json_object *keywordsJson = json_object_new_array();
558 json_object_array_add(keywordsJson, json_object_new_string(keyword.c_str()));
559 json_object_object_add(metadataJson,
"keywords", keywordsJson);
562 if (! version.empty())
563 json_object_object_add(metadataJson,
"version", json_object_new_string(version.c_str()));
565 json_object *dependenciesJson = json_object_new_array();
566 for (
const string &dependency : dependencies)
567 json_object_array_add(dependenciesJson, json_object_new_string(dependency.c_str()));
568 json_object_object_add(metadataJson,
"dependencies", dependenciesJson);
570 if (! isTopLevelComposition)
573 generateCompositionMetadata_Pro(nodeMetadataJson);
576 json_object *triggersJson = json_object_new_array();
581 json_object_array_add(triggersJson, t);
589 json_object *t = triggerInSubcomposition->getJsonWithinSubcomposition(node);
590 json_object_array_add(triggersJson, t);
593 json_object_object_add(nodeMetadataJson,
"triggers", triggersJson);
599 json_object_object_add(nodesJson, node->
getIdentifier().c_str(), nodeClassNameJson);
601 json_object_object_add(nodeMetadataJson,
"nodes", nodesJson);
604 json_object_object_add(metadataJson,
"node", nodeMetadataJson);
606 string metadata = json_object_to_json_string_ext(metadataJson, JSON_C_TO_STRING_PLAIN);
607 json_object_put(metadataJson);
617 void VuoCompilerBitcodeGenerator::generateShouldShowSplashWindowFunction(
bool shouldShow)
619 IntegerType *returnType = IntegerType::get(module->getContext(), 8);
620 FunctionType *functionType = FunctionType::get(returnType,
false);
621 Function *
function = Function::Create(functionType, GlobalValue::ExternalLinkage,
"vuoShouldShowSplashWindow", module);
622 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
623 Value *boolValue = ConstantInt::get(returnType, shouldShow);
624 ReturnInst::Create(module->getContext(), boolValue, block);
633 void VuoCompilerBitcodeGenerator::generateCompositionAddNodeMetadataFunction(
void)
636 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
638 Function::arg_iterator args =
function->arg_begin();
639 Value *compositionStateValue = args++;
640 compositionStateValue->setName(
"compositionState");
648 for (vector<VuoCompilerNode *>::iterator i = orderedNodes.begin(); i != orderedNodes.end(); ++i)
652 node->
generateAddMetadata(module, block, compositionStateValue, orderedTypes, compositionCreateContextForNodeFunction,
653 compositionSetPortValueFunction, compositionGetPortValueFunction, compositionFireTriggerPortEventFunction,
654 releasePortDataFunction);
657 ReturnInst::Create(module->getContext(), block);
666 void VuoCompilerBitcodeGenerator::generateCompositionCreateContextForNodeFunction(
void)
669 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, NULL);
670 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, NULL);
672 Function::arg_iterator args =
function->arg_begin();
673 Value *nodeIndexValue = args++;
674 nodeIndexValue->setName(
"nodeIndex");
677 AllocaInst *nodeContextVariable =
new AllocaInst(pointerToNodeContext,
"nodeContext", initialBlock);
679 vector< pair<BasicBlock *, BasicBlock *> > blocksForIndex;
681 for (
size_t i = 0; i < orderedNodes.size(); ++i)
685 BasicBlock *block = BasicBlock::Create(module->getContext(), node->
getIdentifier(),
function, NULL);
687 new StoreInst(nodeContextValue, nodeContextVariable, block);
689 blocksForIndex.push_back(make_pair(block, block));
694 Value *nodeContextValue =
new LoadInst(nodeContextVariable,
"",
false, finalBlock);
695 ReturnInst::Create(module->getContext(), nodeContextValue, finalBlock);
706 void VuoCompilerBitcodeGenerator::generateCompositionPerformDataOnlyTransmissionsFunction(
void)
709 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
711 Function::arg_iterator args =
function->arg_begin();
712 Value *compositionStateValue = args++;
713 compositionStateValue->setName(
"compositionState");
718 generateDataOnlyTransmissionFromNode(
function, block, compositionStateValue, node,
false,
false,
false);
725 if (subcompositionFunctionSrc)
737 Value *falseValue = ConstantInt::get(setPublishedInputPortValueFunctionDst->getFunctionType()->getParamType(3), 0);
745 Value *inputPortNameValue = constantStrings.
get(module, inputPort->getClass()->getName());
748 vector<Value *> args;
749 args.push_back(subcompositionStateValueDst);
750 args.push_back(inputPortNameValue);
751 args.push_back(dataValue);
752 args.push_back(falseValue);
753 CallInst::Create(setPublishedInputPortValueFunctionDst, args,
"", block);
760 CallInst::Create(subcompositionFunctionDst, subcompositionStateValueDst,
"", block);
767 ReturnInst::Create(module->getContext(), block);
775 void VuoCompilerBitcodeGenerator::generateCompositionReleasePortDataFunction(
void)
778 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, NULL);
779 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, NULL);
781 Function::arg_iterator args =
function->arg_begin();
782 Value *portAddressAsVoidPointer = args++;
783 portAddressAsVoidPointer->setName(
"portData");
784 Value *typeIndexValue = args++;
785 typeIndexValue->setName(
"typeIndex");
787 vector< pair<BasicBlock *, BasicBlock *> > blocksForIndex;
789 for (vector<VuoCompilerType *>::iterator i = orderedTypes.begin(); i != orderedTypes.end(); ++i)
793 BasicBlock *block = BasicBlock::Create(module->getContext(), type->
getBase()->
getModuleKey(),
function, NULL);
794 Value *portAddress =
new BitCastInst(portAddressAsVoidPointer, PointerType::get(type->
getType(), 0),
"", block);
795 Value *portValue =
new LoadInst(portAddress,
"",
false, block);
798 blocksForIndex.push_back(make_pair(block, block));
803 ReturnInst::Create(module->getContext(), finalBlock);
809 void VuoCompilerBitcodeGenerator::generateSetInputDataFromNodeFunctionArguments(Function *
function, BasicBlock *&block, Value *compositionStateValue,
810 map<VuoPort *, size_t> indexOfParameter,
811 map<VuoPort *, size_t> indexOfEventParameter,
812 bool shouldWaitForDataOnlyDownstreamNodes,
813 bool shouldUpdateTriggers,
bool shouldSendTelemetry)
816 if (! publishedInputNode)
819 Value *publishedNodeContextValue = publishedInputNode->
generateGetContext(module, block, compositionStateValue);
822 vector<VuoCompilerInputEventPort *> inputEventPorts;
826 for (
size_t i = 0; i < publishedInputPorts.size(); ++i)
832 inputEventPorts.push_back(inputEventPort);
836 size_t dataArgIndex = indexOfParameter[ modelInputPorts[i] ];
846 if (type->
getType()->isStructTy() &&
850 Value *argAsPointer =
new BitCastInst(argAsPointerToOtherType, type->
getType()->getPointerTo(),
"", block);
851 dataArg =
new LoadInst(argAsPointer,
"", block);
865 generateDataOnlyTransmissionFromNode(
function, block, compositionStateValue, publishedInputNode,
866 shouldWaitForDataOnlyDownstreamNodes, shouldUpdateTriggers, shouldSendTelemetry);
870 for (
size_t i = 0; i < publishedInputPorts.size(); ++i)
875 &indexOfEventParameter :
878 auto foundIndex = indexMap->find( modelInputPorts[i] );
879 if (foundIndex != indexMap->end())
881 size_t eventArgIndex = foundIndex->second;
884 inputEventPort->
generateStoreEvent(module, block, publishedNodeContextValue, eventArg);
897 void VuoCompilerBitcodeGenerator::generateNodeEventFunction(
bool isStatefulComposition)
899 vector<VuoPort *> modelPorts;
900 modelPorts.insert(modelPorts.end(), modelInputPorts.begin(), modelInputPorts.end());
901 modelPorts.insert(modelPorts.end(), modelOutputPorts.begin(), modelOutputPorts.end());
905 vector<VuoPublishedPort *> publishedPorts;
906 publishedPorts.insert(publishedPorts.end(), publishedInputPorts.begin(), publishedInputPorts.end());
907 publishedPorts.insert(publishedPorts.end(), publishedOutputPorts.begin(), publishedOutputPorts.end());
909 map<VuoPort *, string> displayNamesForPorts;
910 map<VuoPort *, json_object *> detailsForPorts;
911 for (
size_t i = 0; i < modelPorts.size(); ++i)
913 VuoPort *modelPort = modelPorts[i];
917 bool isAllCaps =
true;
918 for (
size_t j = 0; j < portName.length(); ++j)
919 if (! isupper(portName[j]))
925 displayNamesForPorts[modelPort] = portName;
930 map<VuoPort *, string> defaultValuesForInputPorts;
931 map<VuoPort *, VuoPortClass::EventBlocking> eventBlockingForInputPorts;
932 for (
size_t i = 0; i < publishedInputPorts.size(); ++i)
937 if (! defaultValue.empty())
938 defaultValuesForInputPorts[publishedInputPort] = defaultValue;
943 map<VuoPort *, size_t> indexOfParameter;
944 map<VuoPort *, size_t> indexOfEventParameter;
947 modelInputPorts, modelOutputPorts,
948 detailsForPorts, displayNamesForPorts,
949 defaultValuesForInputPorts, eventBlockingForInputPorts,
950 indexOfParameter, indexOfEventParameter, constantStrings);
951 BasicBlock *block = &(
function->getEntryBlock());
956 ReturnInst::Create(module->getContext(), block);
962 Value *compositionStateValue =
function->arg_begin();
971 vector<VuoCompilerNode *> triggerWaitNodes = getNodesToWaitOnBeforeTransmission(trigger);
972 generateWaitForNodes(module,
function, block, compositionStateValue, triggerWaitNodes, eventIdValue);
976 bool hasClaimedNodesDownstreamOfPublishedInputNode = (triggerWaitNodes.size() > 2);
977 generateSetInputDataFromNodeFunctionArguments(
function, block, compositionStateValue, indexOfParameter, indexOfEventParameter,
978 ! hasClaimedNodesDownstreamOfPublishedInputNode,
true,
true);
987 Value *triggerNodeContextValue = triggerNode->
generateGetContext(module, block, compositionStateValue);
988 Value *triggerFunctionValue = trigger->
generateLoadFunction(module, block, triggerNodeContextValue);
989 CallInst::Create(triggerFunctionValue,
"", block);
998 Value *publishedOutputNodeContext = publishedOutputNode->
generateGetContext(module, block, compositionStateValue);
999 for (
size_t i = 0; i < modelOutputPorts.size(); ++i)
1001 VuoPort *modelOutputPort = modelOutputPorts[i];
1007 bool hasEventParameter =
false;
1008 size_t eventIndex = 0;
1012 size_t index = indexOfParameter[ modelOutputPort ];
1016 new StoreInst(value, outputArg, block);
1018 map<VuoPort *, size_t>::iterator iter = indexOfEventParameter.find(modelOutputPort);
1019 if (iter != indexOfEventParameter.end())
1021 hasEventParameter =
true;
1022 eventIndex = iter->second;
1027 hasEventParameter =
true;
1028 eventIndex = indexOfParameter[ modelOutputPort ];
1031 if (hasEventParameter)
1036 new StoreInst(eventValue, outputArg, block);
1043 generateSignalForNodes(module, block, compositionStateValue, vector<VuoCompilerNode *>(1, publishedOutputNode));
1045 ReturnInst::Create(module->getContext(), block);
1053 void VuoCompilerBitcodeGenerator::generateNodeInstanceInitFunction(
void)
1055 vector<VuoPort *> inputPorts;
1056 if (! isTopLevelComposition)
1057 inputPorts = modelInputPorts;
1059 map<VuoPort *, size_t> indexOfParameter;
1062 inputPorts, indexOfParameter, constantStrings);
1063 BasicBlock *block = &(
function->getEntryBlock());
1065 Value *compositionStateValue =
function->arg_begin();
1067 if (! isTopLevelComposition)
1068 generateSetInputDataFromNodeFunctionArguments(
function, block, compositionStateValue, indexOfParameter, map<VuoPort *, size_t>(),
1069 false,
false,
false);
1075 BasicBlock *initBlock = NULL;
1076 BasicBlock *nextBlock = NULL;
1077 Value *replacementJsonValue = NULL;
1079 compositionStateValue, block, initBlock, nextBlock,
1080 constantStrings, replacementJsonValue);
1086 BranchInst::Create(nextBlock, initBlock);
1091 PointerType *instanceDataType =
static_cast<PointerType *
>(
function->getReturnType() );
1092 ConstantPointerNull *nullInstanceDataValue = ConstantPointerNull::get(instanceDataType);
1093 ReturnInst::Create(module->getContext(), nullInstanceDataValue, block);
1102 void VuoCompilerBitcodeGenerator::generateNodeInstanceFiniFunction(
void)
1107 BasicBlock *block = &(
function->getEntryBlock());
1109 Value *compositionStateValue =
function->arg_begin();
1115 BasicBlock *finiBlock = NULL;
1116 BasicBlock *nextBlock = NULL;
1117 Value *replacementJsonValue = NULL;
1119 compositionStateValue, block, finiBlock, nextBlock,
1120 constantStrings, replacementJsonValue);
1126 BranchInst::Create(nextBlock, finiBlock);
1131 ReturnInst::Create(module->getContext(), block);
1141 void VuoCompilerBitcodeGenerator::generateNodeInstanceTriggerStartFunction(
void)
1143 vector<VuoPort *> inputPorts;
1144 if (! isTopLevelComposition)
1145 inputPorts = modelInputPorts;
1147 map<VuoPort *, size_t> indexOfParameter;
1150 inputPorts, indexOfParameter, constantStrings);
1151 BasicBlock *block = &(
function->getEntryBlock());
1153 Value *compositionStateValue =
function->arg_begin();
1155 if (! isTopLevelComposition)
1156 generateSetInputDataFromNodeFunctionArguments(
function, block, compositionStateValue, indexOfParameter, map<VuoPort *, size_t>(),
1157 false,
false,
false);
1161 generateWaitForNodes(module,
function, block, compositionStateValue, orderedNodes);
1172 generateSignalForNodes(module, block, compositionStateValue, orderedNodes);
1174 ReturnInst::Create(module->getContext(), block);
1182 void VuoCompilerBitcodeGenerator::generateNodeInstanceTriggerStopFunction(
void)
1187 BasicBlock *block = &(
function->getEntryBlock());
1189 Value *compositionStateValue =
function->arg_begin();
1192 generateWaitForNodes(module,
function, block, compositionStateValue, orderedNodes);
1198 generateSignalForNodes(module, block, compositionStateValue, orderedNodes);
1200 if (isTopLevelComposition)
1207 generateWaitForNodes(module,
function, block, compositionStateValue, orderedNodes);
1208 generateSignalForNodes(module, block, compositionStateValue, orderedNodes);
1211 ReturnInst::Create(module->getContext(), block);
1219 void VuoCompilerBitcodeGenerator::generateNodeInstanceTriggerUpdateFunction(
void)
1221 map<VuoPort *, size_t> indexOfParameter;
1224 modelInputPorts, indexOfParameter, constantStrings);
1225 BasicBlock *block = &(
function->getEntryBlock());
1227 Value *compositionStateValue =
function->arg_begin();
1232 ReturnInst::Create(module->getContext(), block);
1236 vector<VuoCompilerNode *> triggerWaitNodes = getNodesToWaitOnBeforeTransmission(trigger);
1237 generateWaitForNodes(module,
function, block, compositionStateValue, triggerWaitNodes);
1239 bool hasClaimedNodesDownstreamOfPublishedInputNode = (triggerWaitNodes.size() > 2);
1240 generateSetInputDataFromNodeFunctionArguments(
function, block, compositionStateValue, indexOfParameter, map<VuoPort *, size_t>(),
1241 ! hasClaimedNodesDownstreamOfPublishedInputNode,
true,
true);
1243 generateSignalForNodes(module, block, compositionStateValue, triggerWaitNodes);
1245 ReturnInst::Create(module->getContext(), block);
1292 Value * VuoCompilerBitcodeGenerator::generateWaitForNodes(Module *module, Function *
function, BasicBlock *&block,
1293 Value *compositionStateValue, vector<VuoCompilerNode *> nodes,
1294 Value *eventIdValue,
bool shouldBlock)
1302 Type *unsignedLongType = waitForNodeFunction->getFunctionType()->getParamType(1);
1303 Type *boolType = waitForNodeFunction->getFunctionType()->getParamType(3);
1304 Constant *falseValue = ConstantInt::get(boolType, 0);
1305 Constant *trueValue = ConstantInt::get(boolType, 1);
1309 vector<VuoCompilerNode *>::iterator prevNodeIter = orderedNodes.begin();
1311 for (vector<VuoCompilerNode *>::iterator i = nodes.begin(); i != nodes.end(); ++i)
1315 vector<VuoCompilerNode *>::iterator orderedNodeIter = find(prevNodeIter, orderedNodes.end(), node);
1316 prevNodeIter = orderedNodeIter;
1317 size_t orderedNodeIndex = orderedNodeIter - orderedNodes.begin();
1318 Constant *orderedNodeIndexValue = ConstantInt::get(unsignedLongType, orderedNodeIndex);
1320 vector<Value *> args;
1321 args.push_back(compositionStateValue);
1322 args.push_back(orderedNodeIndexValue);
1323 args.push_back(eventIdValue);
1324 args.push_back(trueValue);
1325 CallInst::Create(waitForNodeFunction, args,
"", block);
1332 AllocaInst *keepTryingVariable =
new AllocaInst(IntegerType::get(module->getContext(), 1),
"keepTrying", block);
1333 new StoreInst(trueValue, keepTryingVariable, block);
1335 vector<VuoCompilerNode *>::iterator prevNodeIter = orderedNodes.begin();
1337 vector<BasicBlock *> signalBlocks;
1338 for (vector<VuoCompilerNode *>::iterator i = nodes.begin(); i != nodes.end(); ++i)
1342 BasicBlock *waitBlock = block;
1344 vector<VuoCompilerNode *>::iterator orderedNodeIter = find(prevNodeIter, orderedNodes.end(), node);
1345 prevNodeIter = orderedNodeIter;
1346 size_t orderedNodeIndex = orderedNodeIter - orderedNodes.begin();
1347 Value *orderedNodeIndexValue = ConstantInt::get(unsignedLongType, orderedNodeIndex);
1349 vector<Value *> args;
1350 args.push_back(compositionStateValue);
1351 args.push_back(orderedNodeIndexValue);
1352 args.push_back(eventIdValue);
1353 args.push_back(falseValue);
1354 CallInst *keepTryingValue = CallInst::Create(waitForNodeFunction, args,
"", waitBlock);
1355 new StoreInst(keepTryingValue, keepTryingVariable, waitBlock);
1357 ICmpInst *keepTryingIsFalse =
new ICmpInst(*waitBlock, ICmpInst::ICMP_EQ, keepTryingValue, falseValue);
1358 BasicBlock *signalBlock = BasicBlock::Create(module->getContext(),
"signal",
function);
1359 BasicBlock *nextNodeBlock = BasicBlock::Create(module->getContext(),
"wait",
function);
1360 BranchInst::Create(signalBlock, nextNodeBlock, keepTryingIsFalse, waitBlock);
1362 signalBlocks.push_back(signalBlock);
1363 block = nextNodeBlock;
1366 if (! signalBlocks.empty())
1368 BranchInst::Create(signalBlocks[0], block);
1369 block = signalBlocks[0];
1372 for (
size_t i = 1; i < signalBlocks.size(); ++i)
1374 BasicBlock *signalBlock = signalBlocks[i];
1377 generateSignalForNodes(module, signalBlock, compositionStateValue, vector<VuoCompilerNode *>(1, nodeToSignal));
1379 BranchInst::Create(signalBlocks[i-1], signalBlock);
1382 Value *keepTryingValue =
new LoadInst(keepTryingVariable,
"",
false, block);
1384 return keepTryingValue;
1421 void VuoCompilerBitcodeGenerator::generateCompositionWaitForNodeFunction(
void)
1424 Function::arg_iterator args =
function->arg_begin();
1425 Value *compositionStateValue = args++;
1426 compositionStateValue->setName(
"compositionState");
1427 Value *indexInOrderedNodesValue = args++;
1428 indexInOrderedNodesValue->setName(
"indexInOrderedNodes");
1429 Value *eventIdValue = args++;
1430 eventIdValue->setName(
"eventId");
1431 Value *shouldBlockValue = args++;
1432 shouldBlockValue->setName(
"shouldBlock");
1437 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, 0);
1439 AllocaInst *keepTryingVariable =
new AllocaInst(IntegerType::get(module->getContext(), 1),
"keepTrying", initialBlock);
1440 ConstantInt *trueValue = ConstantInt::get(module->getContext(), APInt(1, 1));
1441 new StoreInst(trueValue, keepTryingVariable, initialBlock);
1447 Type *timeoutDeltaType = IntegerType::get(module->getContext(), 64);
1448 AllocaInst *timeoutDeltaVariable =
new AllocaInst(timeoutDeltaType,
"timeoutDelta", initialBlock);
1449 ICmpInst *shouldBlockIsTrue =
new ICmpInst(*initialBlock, ICmpInst::ICMP_EQ, shouldBlockValue, trueValue);
1450 BasicBlock *nonZeroTimeoutBlock = BasicBlock::Create(module->getContext(),
"nonZeroTimeout",
function);
1451 BasicBlock *zeroTimeoutBlock = BasicBlock::Create(module->getContext(),
"zeroTimeout",
function);
1452 BranchInst::Create(nonZeroTimeoutBlock, zeroTimeoutBlock, shouldBlockIsTrue, initialBlock);
1454 BasicBlock *checkEventIdBlock = BasicBlock::Create(module->getContext(),
"checkEventId",
function);
1456 ConstantInt *nonZeroTimeoutValue = ConstantInt::get(module->getContext(), APInt(64, NSEC_PER_SEC / 1000));
1457 new StoreInst(nonZeroTimeoutValue, timeoutDeltaVariable,
false, nonZeroTimeoutBlock);
1458 BranchInst::Create(checkEventIdBlock, nonZeroTimeoutBlock);
1460 ConstantInt *zeroTimeoutValue = ConstantInt::get(module->getContext(), APInt(64, 0));
1461 new StoreInst(zeroTimeoutValue, timeoutDeltaVariable,
false, zeroTimeoutBlock);
1462 BranchInst::Create(checkEventIdBlock, zeroTimeoutBlock);
1464 Value *timeoutDeltaValue =
new LoadInst(timeoutDeltaVariable,
"",
false, checkEventIdBlock);
1471 compositionStateValue, indexInOrderedNodesValue);
1484 ICmpInst *claimingEventIdNotEqualsEventId =
new ICmpInst(*checkEventIdBlock, ICmpInst::ICMP_NE, claimingEventIdValue, eventIdValue,
"");
1485 BasicBlock *checkKeepTryingBlock = BasicBlock::Create(module->getContext(),
"checkKeepTrying",
function);
1486 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"doneWaitingNodeSemaphore",
function);
1487 BranchInst::Create(checkKeepTryingBlock, finalBlock, claimingEventIdNotEqualsEventId, checkEventIdBlock);
1489 Value *keepTryingValue =
new LoadInst(keepTryingVariable,
"",
false, checkKeepTryingBlock);
1490 ICmpInst *keepTryingIsTrue =
new ICmpInst(*checkKeepTryingBlock, ICmpInst::ICMP_EQ, keepTryingValue, trueValue);
1491 BasicBlock *waitBlock = BasicBlock::Create(module->getContext(),
"waitNodeSemaphore",
function);
1492 BranchInst::Create(waitBlock, finalBlock, keepTryingIsTrue, checkKeepTryingBlock);
1497 Value *zeroValue = ConstantInt::get(retValue->getType(), 0);
1498 ICmpInst *retEqualsZero =
new ICmpInst(*waitBlock, ICmpInst::ICMP_EQ, retValue, zeroValue,
"");
1499 BasicBlock *setEventIdBlock = BasicBlock::Create(module->getContext(),
"setEventId",
function);
1500 BasicBlock *checkShouldBlockBlock = BasicBlock::Create(module->getContext(),
"checkShouldBlock",
function);
1501 BasicBlock *endWhileBlock = BasicBlock::Create(module->getContext(),
"endWhile",
function);
1502 BranchInst::Create(setEventIdBlock, checkShouldBlockBlock, retEqualsZero, waitBlock);
1505 BranchInst::Create(endWhileBlock, setEventIdBlock);
1507 BasicBlock *setKeepTryingBlock = BasicBlock::Create(module->getContext(),
"setKeepTrying",
function);
1508 BranchInst::Create(endWhileBlock, setKeepTryingBlock, shouldBlockIsTrue, checkShouldBlockBlock);
1510 Value *falseValue = ConstantInt::get(keepTryingValue->getType(), 0);
1511 new StoreInst(falseValue, keepTryingVariable, setKeepTryingBlock);
1512 BranchInst::Create(endWhileBlock, setKeepTryingBlock);
1514 BranchInst::Create(checkEventIdBlock, endWhileBlock);
1519 keepTryingValue =
new LoadInst(keepTryingVariable,
"",
false, finalBlock);
1520 ReturnInst::Create(module->getContext(), keepTryingValue, finalBlock);
1532 void VuoCompilerBitcodeGenerator::generateSignalForNodes(Module *module, BasicBlock *block, Value *compositionStateValue,
1533 vector<VuoCompilerNode *> nodes)
1535 for (vector<VuoCompilerNode *>::iterator i = nodes.begin(); i != nodes.end(); ++i)
1539 Value *nodeContextValue = node->
generateGetContext(module, block, compositionStateValue);
1610 void VuoCompilerBitcodeGenerator::generateCompositionGetPortValueFunction(
void)
1614 Function::arg_iterator args =
function->arg_begin();
1615 Value *compositionStateValue = args++;
1616 compositionStateValue->setName(
"compositionState");
1617 Value *portIdentifierValue = args++;
1618 portIdentifierValue->setName(
"portIdentifier");
1619 Value *serializationTypeValue = args++;
1620 serializationTypeValue->setName(
"serializationType");
1621 Value *isThreadSafeValue = args++;
1622 isThreadSafeValue->setName(
"isThreadSafe");
1627 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, 0);
1628 PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
1630 AllocaInst *retVariable =
new AllocaInst(pointerToCharType,
"ret", initialBlock);
1631 ConstantPointerNull *nullPointerToChar = ConstantPointerNull::get(pointerToCharType);
1632 new StoreInst(nullPointerToChar, retVariable,
false, initialBlock);
1640 BasicBlock *checkWaitBlock = BasicBlock::Create(module->getContext(),
"checkWait",
function, 0);
1641 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, 0);
1643 ConstantPointerNull *nullPortAddress = ConstantPointerNull::get(
static_cast<PointerType *
>(portAddressAsVoidPointer->getType()));
1644 ICmpInst *portAddressNotEqualsNull =
new ICmpInst(*initialBlock, ICmpInst::ICMP_NE, portAddressAsVoidPointer, nullPortAddress,
"");
1645 BranchInst::Create(checkWaitBlock, finalBlock, portAddressNotEqualsNull, initialBlock);
1656 BasicBlock *waitBlock = BasicBlock::Create(module->getContext(),
"wait",
function, 0);
1657 BasicBlock *checkTypeIndexBlock = BasicBlock::Create(module->getContext(),
"checkTypeIndex",
function, 0);
1658 ConstantInt *falseValue = ConstantInt::get(
static_cast<IntegerType *
>(isThreadSafeValue->getType()), 0);
1659 ICmpInst *isThreadSafeEqualsTrue =
new ICmpInst(*checkWaitBlock, ICmpInst::ICMP_NE, isThreadSafeValue, falseValue,
"");
1660 BranchInst::Create(waitBlock, checkTypeIndexBlock, isThreadSafeEqualsTrue, checkWaitBlock);
1663 BranchInst::Create(checkTypeIndexBlock, waitBlock);
1686 vector< pair<BasicBlock *, BasicBlock *> > blocksForIndex;
1687 for (
size_t i = 0; i < orderedTypes.size(); ++i)
1694 BasicBlock *checkSummaryBlock = BasicBlock::Create(module->getContext(), typeName +
"_checkSummary",
function, 0);
1695 BasicBlock *summaryBlock = BasicBlock::Create(module->getContext(), typeName +
"_summary",
function, 0);
1696 BasicBlock *checkStringBlock = NULL;
1697 BasicBlock *stringBlock = BasicBlock::Create(module->getContext(), typeName +
"_string",
function, 0);
1698 BasicBlock *interprocessBlock = NULL;
1699 BasicBlock *typeFinalBlock = BasicBlock::Create(module->getContext(), typeName +
"_final",
function, 0);
1701 BasicBlock *firstStringBlock = NULL;
1702 if (hasInterprocess)
1704 checkStringBlock = BasicBlock::Create(module->getContext(), typeName +
"_checkString",
function, 0);
1705 interprocessBlock = BasicBlock::Create(module->getContext(), typeName +
"_interprocess",
function, 0);
1706 firstStringBlock = checkStringBlock;
1710 firstStringBlock = stringBlock;
1713 PointerType *pointerToType = PointerType::get(type->
getType(), 0);
1714 Value *portAddress =
new BitCastInst(portAddressAsVoidPointer, pointerToType,
"", checkSummaryBlock);
1715 Value *portValue =
new LoadInst(portAddress,
"",
false, checkSummaryBlock);
1717 ConstantInt *zeroValue = ConstantInt::get(
static_cast<IntegerType *
>(serializationTypeValue->getType()), 0);
1718 ICmpInst *serializationTypeEqualsZero =
new ICmpInst(*checkSummaryBlock, ICmpInst::ICMP_EQ, serializationTypeValue, zeroValue,
"");
1719 BranchInst::Create(summaryBlock, firstStringBlock, serializationTypeEqualsZero, checkSummaryBlock);
1722 new StoreInst(summaryValue, retVariable, summaryBlock);
1723 BranchInst::Create(typeFinalBlock, summaryBlock);
1725 if (hasInterprocess)
1727 ConstantInt *oneValue = ConstantInt::get(
static_cast<IntegerType *
>(serializationTypeValue->getType()), 1);
1728 ICmpInst *serializationTypeEqualsOne =
new ICmpInst(*checkStringBlock, ICmpInst::ICMP_EQ, serializationTypeValue, oneValue,
"");
1729 BranchInst::Create(stringBlock, interprocessBlock, serializationTypeEqualsOne, checkStringBlock);
1733 new StoreInst(stringValue, retVariable, stringBlock);
1734 BranchInst::Create(typeFinalBlock, stringBlock);
1736 if (hasInterprocess)
1739 new StoreInst(interprocessValue, retVariable, interprocessBlock);
1740 BranchInst::Create(typeFinalBlock, interprocessBlock);
1743 blocksForIndex.push_back( make_pair(checkSummaryBlock, typeFinalBlock) );
1746 BasicBlock *checkSignalBlock = BasicBlock::Create(module->getContext(),
"checkSignal",
function, 0);
1753 BasicBlock *signalBlock = BasicBlock::Create(module->getContext(),
"signal",
function, 0);
1754 BranchInst::Create(signalBlock, finalBlock, isThreadSafeEqualsTrue, checkSignalBlock);
1757 BranchInst::Create(finalBlock, signalBlock);
1762 LoadInst *retValue =
new LoadInst(retVariable,
"",
false, finalBlock);
1763 ReturnInst::Create(module->getContext(), retValue, finalBlock);
1841 void VuoCompilerBitcodeGenerator::generateCompositionSetPortValueFunction(
void)
1845 Function::arg_iterator args =
function->arg_begin();
1846 Value *compositionStateValue = args++;
1847 compositionStateValue->setName(
"compositionState");
1848 Value *portIdentifierValue = args++;
1849 portIdentifierValue->setName(
"portIdentifier");
1850 Value *valueAsStringValue = args++;
1851 valueAsStringValue->setName(
"valueAsString");
1852 Value *isThreadSafeValue = args++;
1853 isThreadSafeValue->setName(
"isThreadSafe");
1854 Value *shouldUpdateTriggersValue = args++;
1855 shouldUpdateTriggersValue->setName(
"shouldUpdateTriggers");
1856 Value *shouldSendTelemetryValue = args++;
1857 shouldSendTelemetryValue->setName(
"shouldSendTelemetry");
1858 Value *hasOldValue = args++;
1859 hasOldValue->setName(
"hasOldValue");
1860 Value *hasNewValue = args++;
1861 hasNewValue->setName(
"hasNewValue");
1866 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, 0);
1871 BasicBlock *checkWaitBlock = BasicBlock::Create(module->getContext(),
"checkWait",
function, 0);
1872 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, 0);
1874 ConstantPointerNull *nullPortAddress = ConstantPointerNull::get(
static_cast<PointerType *
>(portAddressAsVoidPointer->getType()));
1875 ICmpInst *portAddressNotEqualsNull =
new ICmpInst(*initialBlock, ICmpInst::ICMP_NE, portAddressAsVoidPointer, nullPortAddress,
"");
1876 BranchInst::Create(checkWaitBlock, finalBlock, portAddressNotEqualsNull, initialBlock);
1887 PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
1888 AllocaInst *summaryVariable =
new AllocaInst(pointerToCharType,
"summary", checkWaitBlock);
1889 ConstantPointerNull *nullSummary = ConstantPointerNull::get(pointerToCharType);
1890 new StoreInst(nullSummary, summaryVariable,
false, checkWaitBlock);
1895 BasicBlock *waitBlock = BasicBlock::Create(module->getContext(),
"wait",
function, 0);
1896 BasicBlock *checkTypeIndexBlock = BasicBlock::Create(module->getContext(),
"checkTypeIndex",
function, 0);
1897 ConstantInt *falseArgValue = ConstantInt::get(
static_cast<IntegerType *
>(isThreadSafeValue->getType()), 0);
1898 ICmpInst *isThreadSafeEqualsTrue =
new ICmpInst(*checkWaitBlock, ICmpInst::ICMP_NE, isThreadSafeValue, falseArgValue,
"");
1899 BranchInst::Create(waitBlock, checkTypeIndexBlock, isThreadSafeEqualsTrue, checkWaitBlock);
1902 BranchInst::Create(checkTypeIndexBlock, waitBlock);
1933 ICmpInst *hasOldValueIsTrue =
new ICmpInst(*checkTypeIndexBlock, ICmpInst::ICMP_NE, hasOldValue, falseArgValue,
"");
1934 ICmpInst *hasNewValueIsTrue =
new ICmpInst(*checkTypeIndexBlock, ICmpInst::ICMP_NE, hasNewValue, falseArgValue,
"");
1935 ICmpInst *shouldSendTelemetryIsTrue =
new ICmpInst(*checkTypeIndexBlock, ICmpInst::ICMP_NE, shouldSendTelemetryValue, falseArgValue,
"");
1937 vector< pair<BasicBlock *, BasicBlock *> > blocksForTypeIndex;
1938 for (
size_t i = 0; i < orderedTypes.size(); ++i)
1942 BasicBlock *typeInitialBlock = BasicBlock::Create(module->getContext(), type->
getBase()->
getModuleKey() +
"_initial",
function, 0);
1943 Value *portAddress =
new BitCastInst(portAddressAsVoidPointer, PointerType::get(type->
getType(), 0),
"", typeInitialBlock);
1945 BasicBlock *typeFinalBlock = BasicBlock::Create(module->getContext(), type->
getBase()->
getModuleKey() +
"_final",
function, 0);
1947 BasicBlock *setNewValueBlock = BasicBlock::Create(module->getContext(),
"setNewValue",
function, 0);
1949 new StoreInst(portValue, portAddress,
false, setNewValueBlock);
1952 BasicBlock *summaryBlock = BasicBlock::Create(module->getContext(),
"summary",
function, 0);
1954 new StoreInst(summaryValue, summaryVariable,
false, summaryBlock);
1958 BasicBlock *saveOldValueBlock = BasicBlock::Create(module->getContext(),
"saveOldValue",
function, 0);
1959 BasicBlock *checkNewValueBlock = BasicBlock::Create(module->getContext(),
"checkNewValue",
function, 0);
1960 BasicBlock *checkOldValueBlock = BasicBlock::Create(module->getContext(),
"checkOldValue",
function, 0);
1961 BasicBlock *releaseOldValueBlock = BasicBlock::Create(module->getContext(),
"releaseOldValue",
function, 0);
1963 AllocaInst *oldPortValueVariable =
new AllocaInst(type->
getType(),
"oldPortValue", typeInitialBlock);
1964 BranchInst::Create(saveOldValueBlock, checkNewValueBlock, hasOldValueIsTrue, typeInitialBlock);
1966 Value *oldPortValue =
new LoadInst(portAddress,
"",
false, saveOldValueBlock);
1967 new StoreInst(oldPortValue, oldPortValueVariable,
false, saveOldValueBlock);
1968 BranchInst::Create(checkNewValueBlock, saveOldValueBlock);
1970 BranchInst::Create(setNewValueBlock, checkOldValueBlock, hasNewValueIsTrue, checkNewValueBlock);
1972 BranchInst::Create(summaryBlock, checkOldValueBlock, shouldSendTelemetryIsTrue, setNewValueBlock);
1974 BranchInst::Create(checkOldValueBlock, summaryBlock);
1976 BranchInst::Create(releaseOldValueBlock, typeFinalBlock, hasOldValueIsTrue, checkOldValueBlock);
1978 oldPortValue =
new LoadInst(oldPortValueVariable,
"",
false, releaseOldValueBlock);
1980 BranchInst::Create(typeFinalBlock, releaseOldValueBlock);
1984 BranchInst::Create(setNewValueBlock, typeFinalBlock, hasNewValueIsTrue, typeInitialBlock);
1986 BranchInst::Create(summaryBlock, typeFinalBlock, shouldSendTelemetryIsTrue, setNewValueBlock);
1988 BranchInst::Create(typeFinalBlock, summaryBlock);
1991 blocksForTypeIndex.push_back( make_pair(typeInitialBlock, typeFinalBlock) );
1994 BasicBlock *checkUpdateBlock = BasicBlock::Create(module->getContext(),
"checkUpdate",
function, 0);
2007 Constant *zeroValue = ConstantInt::get(shouldUpdateTriggersValue->getType(), 0);
2008 ICmpInst *shouldUpdateTriggersIsTrue =
new ICmpInst(*checkUpdateBlock, ICmpInst::ICMP_NE, shouldUpdateTriggersValue, zeroValue,
"");
2009 BasicBlock *updateTriggersBlock = BasicBlock::Create(module->getContext(),
"updateTriggers",
function, 0);
2010 BasicBlock *checkSendBlock = BasicBlock::Create(module->getContext(),
"checkSend",
function, 0);
2011 BranchInst::Create(updateTriggersBlock, checkSendBlock, shouldUpdateTriggersIsTrue, checkUpdateBlock);
2013 vector< pair<BasicBlock *, BasicBlock *> > blocksForNodeIndex;
2014 for (
size_t i = 0; i < orderedNodes.size(); ++i)
2017 BasicBlock *currentBlock = BasicBlock::Create(module->getContext(), node->
getIdentifier(),
function, 0);
2018 BasicBlock *origCurrentBlock = currentBlock;
2022 generateDataOnlyTransmissionFromNode(
function, currentBlock, compositionStateValue, node,
true,
true,
true);
2024 blocksForNodeIndex.push_back( make_pair(origCurrentBlock, currentBlock) );
2027 BasicBlock *checkSignalBlock = BasicBlock::Create(module->getContext(),
"checkSignal",
function, 0);
2034 BasicBlock *signalBlock = BasicBlock::Create(module->getContext(),
"signal",
function, 0);
2035 BranchInst::Create(signalBlock, checkSendBlock, isThreadSafeEqualsTrue, checkSignalBlock);
2038 BranchInst::Create(checkSendBlock, signalBlock);
2047 BasicBlock *sendBlock = BasicBlock::Create(module->getContext(),
"send",
function, 0);
2048 BranchInst::Create(sendBlock, finalBlock, shouldSendTelemetryIsTrue, checkSendBlock);
2050 Value *summaryValue =
new LoadInst(summaryVariable,
"",
false, sendBlock);
2053 false,
true, summaryValue);
2056 BranchInst::Create(finalBlock, sendBlock);
2058 ReturnInst::Create(module->getContext(), finalBlock);
2066 void VuoCompilerBitcodeGenerator::generateSetInputPortValueFunction(
void)
2069 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
2071 Function::arg_iterator args =
function->arg_begin();
2072 Value *portIdentifierValue = args++;
2073 portIdentifierValue->setName(
"portIdentifier");
2074 Value *valueAsStringValue = args++;
2075 valueAsStringValue->setName(
"valueAsString");
2083 Value *trueValue = ConstantInt::get(compositionSetPortValueFunction->getFunctionType()->getParamType(3), 1);
2085 vector<Value *> compositionArgs;
2086 compositionArgs.push_back(compositionStateValue);
2087 compositionArgs.push_back(portIdentifierValue);
2088 compositionArgs.push_back(valueAsStringValue);
2089 compositionArgs.push_back(trueValue);
2090 compositionArgs.push_back(trueValue);
2091 compositionArgs.push_back(trueValue);
2092 compositionArgs.push_back(trueValue);
2093 compositionArgs.push_back(trueValue);
2094 CallInst::Create(compositionSetPortValueFunction, compositionArgs,
"", block);
2098 ReturnInst::Create(module->getContext(), block);
2120 void VuoCompilerBitcodeGenerator::generateCompositionFireTriggerPortEventFunction(
void)
2124 Function::arg_iterator args =
function->arg_begin();
2125 Value *compositionStateValue = args++;
2126 compositionStateValue->setName(
"compositionState");
2127 Value *portIdentifierValue = args++;
2128 portIdentifierValue->setName(
"portIdentifier");
2130 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, 0);
2132 map<string, pair<BasicBlock *, BasicBlock *> > blocksForString;
2139 BasicBlock *currentBlock = BasicBlock::Create(module->getContext(), currentPortIdentifier,
function, 0);
2140 BasicBlock *origCurrentBlock = currentBlock;
2142 Value *nodeContextValue = triggerNode->
generateGetContext(module, currentBlock, compositionStateValue);
2143 Value *triggerFunctionValue = trigger->
generateLoadFunction(module, currentBlock, nodeContextValue);
2145 vector<Value *> triggerArgs;
2146 AttributeSet triggerParamAttributes;
2150 generateWaitForNodes(module,
function, currentBlock, compositionStateValue, vector<VuoCompilerNode *>(1, triggerNode));
2156 Type *secondParam = NULL;
2160 bool isByVal = triggerParamAttributes.hasAttrSomewhere(Attribute::ByVal);
2162 Value *secondArg = NULL;
2163 Value **secondArgIfNeeded = (secondParam ? &secondArg : NULL);
2166 triggerArgs.push_back(arg);
2168 triggerArgs.push_back(secondArg);
2171 CallInst *call = CallInst::Create(triggerFunctionValue, triggerArgs,
"", currentBlock);
2176 generateSignalForNodes(module, currentBlock, compositionStateValue, vector<VuoCompilerNode *>(1, triggerNode));
2178 blocksForString[currentPortIdentifier] = make_pair(origCurrentBlock, currentBlock);
2181 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, 0);
2183 ReturnInst::Create(module->getContext(), finalBlock);
2203 void VuoCompilerBitcodeGenerator::generateGetPublishedPortCountFunction(
bool input)
2206 string functionName;
2210 functionName =
"getPublishedInputPortCount";
2215 functionName =
"getPublishedOutputPortCount";
2218 Function *
function = module->getFunction(functionName);
2221 vector<Type *> functionParams;
2222 FunctionType *functionType = FunctionType::get(IntegerType::get(module->getContext(), 32), functionParams,
false);
2223 function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
2226 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, 0);
2227 ConstantInt *countConstant = ConstantInt::get(module->getContext(), APInt(32, count));
2228 ReturnInst::Create(module->getContext(), countConstant, block);
2246 void VuoCompilerBitcodeGenerator::generateGetPublishedPortNamesFunction(
bool input)
2248 string functionName;
2249 vector<VuoPublishedPort *> publishedPorts;
2252 functionName =
"getPublishedInputPortNames";
2257 functionName =
"getPublishedOutputPortNames";
2261 vector<string> names;
2262 for (vector<VuoPublishedPort *>::iterator i = publishedPorts.begin(); i != publishedPorts.end(); ++i)
2264 names.push_back( (*i)->getClass()->getName() );
2267 generateFunctionReturningStringArray(functionName, names);
2285 void VuoCompilerBitcodeGenerator::generateGetPublishedPortTypesFunction(
bool input)
2287 string functionName;
2288 vector<VuoPublishedPort *> publishedPorts;
2291 functionName =
"getPublishedInputPortTypes";
2296 functionName =
"getPublishedOutputPortTypes";
2300 vector<string> types;
2301 for (vector<VuoPublishedPort *>::iterator i = publishedPorts.begin(); i != publishedPorts.end(); ++i)
2307 types.push_back(typeName);
2310 generateFunctionReturningStringArray(functionName, types);
2328 void VuoCompilerBitcodeGenerator::generateGetPublishedPortDetailsFunction(
bool input)
2330 string functionName;
2331 vector<VuoPublishedPort *> publishedPorts;
2334 functionName =
"getPublishedInputPortDetails";
2339 functionName =
"getPublishedOutputPortDetails";
2343 vector<string> details;
2344 for (vector<VuoPublishedPort *>::iterator i = publishedPorts.begin(); i != publishedPorts.end(); ++i)
2349 string detailsSerialized = json_object_to_json_string_ext(detailsObj, JSON_C_TO_STRING_PLAIN);
2350 details.push_back(detailsSerialized);
2352 json_object_put(detailsObj);
2355 generateFunctionReturningStringArray(functionName, details);
2364 void VuoCompilerBitcodeGenerator::generateFunctionReturningStringArray(
string functionName, vector<string> stringValues)
2366 Function *
function = module->getFunction(functionName);
2369 PointerType *pointerToChar = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2370 PointerType *pointerToPointerToChar = PointerType::get(pointerToChar, 0);
2371 vector<Type *> functionParams;
2372 FunctionType *functionType = FunctionType::get(pointerToPointerToChar, functionParams,
false);
2373 function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
2376 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, 0);
2379 ReturnInst::Create(module->getContext(), stringArrayGlobalPointer, block);
2391 void VuoCompilerBitcodeGenerator::generateFirePublishedInputPortEventFunction(
void)
2393 string functionName =
"firePublishedInputPortEvent";
2394 Function *
function = module->getFunction(functionName);
2397 PointerType *pointerToChar = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2398 PointerType *pointerToPointerToChar = PointerType::get(pointerToChar, 0);
2399 Type *countType = IntegerType::get(module->getContext(), 32);
2401 vector<Type *> functionParams;
2402 functionParams.push_back(pointerToPointerToChar);
2403 functionParams.push_back(countType);
2404 FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams,
false);
2405 function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
2408 Function::arg_iterator args =
function->arg_begin();
2409 Value *namesValue = args++;
2410 namesValue->setName(
"names");
2411 Value *countValue = args++;
2412 countValue->setName(
"count");
2414 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, 0);
2419 ReturnInst::Create(module->getContext(), initialBlock);
2428 compositionIdentifierValue);
2437 vector<VuoCompilerNode *> triggerWaitNodes = getNodesToWaitOnBeforeTransmission(trigger);
2440 if (find(triggerWaitNodes.begin(), triggerWaitNodes.end(), publishedOutputNode) == triggerWaitNodes.end())
2441 triggerWaitNodes.push_back(publishedOutputNode);
2443 generateWaitForNodes(module,
function, initialBlock, compositionStateValue, triggerWaitNodes, eventIdValue);
2468 Value *publishedInputNodeContextValue = publishedInputNode->
generateGetContext(module, initialBlock, compositionStateValue);
2470 Value *zeroValue = ConstantInt::get(
static_cast<IntegerType *
>(countValue->getType()), 0);
2471 AllocaInst *iterVariable =
new AllocaInst(countValue->getType(),
"i", initialBlock);
2472 new StoreInst(zeroValue, iterVariable,
false, initialBlock);
2474 BasicBlock *loopConditionBlock = BasicBlock::Create(module->getContext(),
"loopCondition",
function, 0);
2475 BasicBlock *loopBeginBlock = BasicBlock::Create(module->getContext(),
"loopBegin",
function, 0);
2476 BasicBlock *loopEndBlock = BasicBlock::Create(module->getContext(),
"loopEnd",
function, 0);
2477 BasicBlock *fireBlock = BasicBlock::Create(module->getContext(),
"fire",
function, 0);
2479 BranchInst::Create(loopConditionBlock, initialBlock);
2481 Value *iterValue =
new LoadInst(iterVariable,
"",
false, loopConditionBlock);
2482 ICmpInst *iterLessThanCount =
new ICmpInst(*loopConditionBlock, ICmpInst::ICMP_ULT, iterValue, countValue,
"");
2483 BranchInst::Create(loopBeginBlock, fireBlock, iterLessThanCount, loopConditionBlock);
2487 map<string, pair<BasicBlock *, BasicBlock *> > blocksForString;
2490 for (
size_t i = 0; i < publishedInputPorts.size(); ++i)
2492 string currentName = publishedInputPorts[i]->getClass()->getName();
2493 BasicBlock *currentBlock = BasicBlock::Create(module->getContext(), currentName,
function, 0);
2497 inputEventPort->
generateStoreEvent(module, currentBlock, publishedInputNodeContextValue,
true);
2499 blocksForString[currentName] = make_pair(currentBlock, currentBlock);
2504 Value *oneValue = ConstantInt::get(
static_cast<IntegerType *
>(countValue->getType()), 1);
2505 Value *iterPlusOneValue = BinaryOperator::Create(Instruction::Add, iterValue, oneValue,
"", loopEndBlock);
2506 new StoreInst(iterPlusOneValue, iterVariable,
false, loopEndBlock);
2508 BranchInst::Create(loopConditionBlock, loopEndBlock);
2512 Value *triggerNodeContextValue = triggerNode->
generateGetContext(module, fireBlock, compositionStateValue);
2513 Value *triggerFunctionValue = trigger->
generateLoadFunction(module, fireBlock, triggerNodeContextValue);
2514 CallInst::Create(triggerFunctionValue,
"", fireBlock);
2516 ReturnInst::Create(module->getContext(), fireBlock);
2558 void VuoCompilerBitcodeGenerator::generateGetPublishedPortValueFunction(
bool input)
2560 Function *
function = (input ?
2564 Function::arg_iterator args =
function->arg_begin();
2565 Value *portIdentifierValue = args++;
2566 portIdentifierValue->setName(
"portIdentifier");
2567 Value *shouldUseInterprocessSerializationValue = args++;
2568 shouldUseInterprocessSerializationValue->setName(
"shouldUseInterprocessSerialization");
2570 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, 0);
2571 PointerType *pointerToChar = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2572 AllocaInst *retVariable =
new AllocaInst(pointerToChar,
"ret", initialBlock);
2573 ConstantPointerNull *nullValue = ConstantPointerNull::get(pointerToChar);
2574 new StoreInst(nullValue, retVariable,
false, initialBlock);
2579 compositionIdentifierValue);
2581 vector<VuoPort *> inputPortsOnPublishedNode;
2585 for (
size_t i = 0; i < publishedPorts.size(); ++i)
2588 inputPortsOnPublishedNode.push_back(port);
2594 for (
size_t i = 0; i < publishedPorts.size(); ++i)
2597 inputPortsOnPublishedNode.push_back(port);
2601 map<string, pair<BasicBlock *, BasicBlock *> > blocksForString;
2602 for (
VuoPort *port : inputPortsOnPublishedNode)
2605 BasicBlock *currentBlock = BasicBlock::Create(module->getContext(), currentName,
function, 0);
2608 Constant *currentIdentifierValue = constantStrings.
get(module, currentIdentifier);
2611 currentIdentifierValue, shouldUseInterprocessSerializationValue);
2612 new StoreInst(retValue, retVariable, currentBlock);
2614 blocksForString[currentName] = make_pair(currentBlock, currentBlock);
2617 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, 0);
2621 LoadInst *retValue =
new LoadInst(retVariable,
"",
false, finalBlock);
2622 ReturnInst::Create(module->getContext(), retValue, finalBlock);
2638 void VuoCompilerBitcodeGenerator::generateCompositionSetPublishedInputPortValueFunction(
void)
2642 Function::arg_iterator args =
function->arg_begin();
2643 Value *compositionStateValue = args++;
2644 compositionStateValue->setName(
"compositionState");
2645 Value *publishedInputPortNameValue = args++;
2646 publishedInputPortNameValue->setName(
"publishedInputPortName");
2647 Value *valueAsStringValue = args++;
2648 valueAsStringValue->setName(
"valueAsString");
2649 Value *isCompositionRunningValue = args++;
2650 isCompositionRunningValue->setName(
"isCompositionRunning");
2652 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, 0);
2657 ReturnInst::Create(module->getContext(), initialBlock);
2663 PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2664 AllocaInst *inputPortIdentifierVariable =
new AllocaInst(pointerToCharType,
"inputPortIdentifier", initialBlock);
2665 ConstantPointerNull *nullInputPortIdentifier = ConstantPointerNull::get(pointerToCharType);
2666 new StoreInst(nullInputPortIdentifier, inputPortIdentifierVariable,
false, initialBlock);
2674 map<string, pair<BasicBlock *, BasicBlock *> > blocksForString;
2676 for (
size_t i = 0; i < publishedInputPorts.size(); ++i)
2678 string currPublishedInputPortName = publishedInputPorts[i]->getClass()->getName();
2679 BasicBlock *currBlock = BasicBlock::Create(module->getContext(), currPublishedInputPortName,
function, 0);
2683 Value *inputPortIdentifierValue = constantStrings.
get(module, inputPortIdentifier);
2685 new StoreInst(inputPortIdentifierValue, inputPortIdentifierVariable,
false, currBlock);
2687 blocksForString[currPublishedInputPortName] = make_pair(currBlock, currBlock);
2690 BasicBlock *checkBlock = BasicBlock::Create(module->getContext(),
"check",
function, 0);
2691 BasicBlock *scheduleBlock = BasicBlock::Create(module->getContext(),
"schedule",
function, 0);
2692 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, 0);
2699 Value *inputPortIdentifierValue =
new LoadInst(inputPortIdentifierVariable,
"",
false, checkBlock);
2700 ICmpInst *portIdentifierNotEqualsNull =
new ICmpInst(*checkBlock, ICmpInst::ICMP_NE, inputPortIdentifierValue, nullInputPortIdentifier,
"");
2701 BranchInst::Create(scheduleBlock, finalBlock, portIdentifierNotEqualsNull, checkBlock);
2710 inputPortIdentifierValue, valueAsStringValue,
2711 isCompositionRunningValue);
2717 Value *nodeContextValue = triggerNode->
generateGetContext(module, scheduleBlock, compositionStateValue);
2721 workerFunctionName, contextValue);
2723 BranchInst::Create(finalBlock, scheduleBlock);
2724 ReturnInst::Create(module->getContext(), finalBlock);
2731 Function::arg_iterator workerArgs = workerFunction->arg_begin();
2732 Value *contextValueInWorker = workerArgs++;
2733 contextValueInWorker->setName(
"context");
2735 BasicBlock *workerBlock = BasicBlock::Create(module->getContext(),
"", workerFunction, 0);
2742 Type *voidPointerType = contextValueInWorker->getType();
2743 Type *voidPointerPointerType = PointerType::get(voidPointerType, 0);
2745 Type *boolType = compositionSetPortValueFunction->getFunctionType()->getParamType(3);
2747 Value *contextValueAsVoidPointerArray =
new BitCastInst(contextValueInWorker, voidPointerPointerType,
"", workerBlock);
2749 Value *compositionStateValueInWorker =
new BitCastInst(compositionStateAsVoidPointer, compositionStatePointerType,
"", workerBlock);
2752 Value *inputPortIdentifierValueInWorker =
new BitCastInst(inputPortIdentifierAsVoidPointer, pointerToCharType,
"", workerBlock);
2755 Value *valueAsStringValueInWorker =
new BitCastInst(valueAsStringValueAsVoidPointer, pointerToCharType,
"", workerBlock);
2758 Value *isCompositionRunningValueInWorker =
new PtrToIntInst(isCompositionRunningValueAsVoidPointer, boolType,
"", workerBlock);
2767 Value *trueValue = ConstantInt::get(boolType, 1);
2769 vector<Value *> setValueArgs;
2770 setValueArgs.push_back(compositionStateValueInWorker);
2771 setValueArgs.push_back(inputPortIdentifierValueInWorker);
2772 setValueArgs.push_back(valueAsStringValueInWorker);
2773 setValueArgs.push_back(isCompositionRunningValueInWorker);
2774 setValueArgs.push_back(isCompositionRunningValueInWorker);
2775 setValueArgs.push_back(isCompositionRunningValueInWorker);
2776 setValueArgs.push_back(trueValue);
2777 setValueArgs.push_back(trueValue);
2778 CallInst::Create(compositionSetPortValueFunction, setValueArgs,
"", workerBlock);
2780 ReturnInst::Create(module->getContext(), workerBlock);
2790 void VuoCompilerBitcodeGenerator::generateSetPublishedInputPortValueFunction(
void)
2794 Function::arg_iterator args =
function->arg_begin();
2795 Value *publishedInputPortNameValue = args++;
2796 publishedInputPortNameValue->setName(
"publishedInputPortName");
2797 Value *valueAsStringValue = args++;
2798 valueAsStringValue->setName(
"valueAsString");
2800 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
2807 Value *trueValue = ConstantInt::get(compositionFunction->getFunctionType()->getParamType(3), 1);
2809 vector<Value *> compositionArgs;
2810 compositionArgs.push_back(compositionStateValue);
2811 compositionArgs.push_back(publishedInputPortNameValue);
2812 compositionArgs.push_back(valueAsStringValue);
2813 compositionArgs.push_back(trueValue);
2814 CallInst::Create(compositionFunction, compositionArgs,
"", block);
2818 ReturnInst::Create(module->getContext(), block);
2825 void VuoCompilerBitcodeGenerator::generateTransmissionFromOutputPort(Function *
function, BasicBlock *¤tBlock,
2826 Value *compositionStateValue,
2828 Value *eventValue, Value *dataValue,
2829 bool requiresEvent,
bool shouldSendTelemetry)
2831 IntegerType *boolType = IntegerType::get(module->getContext(), 1);
2832 PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2836 Constant *trueValue = ConstantInt::get(boolType, 1);
2837 Constant *falseValue = ConstantInt::get(boolType, 0);
2838 Constant *transmittedEventValue = (requiresEvent ? trueValue : falseValue);
2841 AllocaInst *dataSummaryVariable =
new AllocaInst(pointerToCharType,
"dataSummary", currentBlock);
2842 new StoreInst(ConstantPointerNull::get(pointerToCharType), dataSummaryVariable, currentBlock);
2844 map<VuoCompilerPort *, ICmpInst *> shouldSummarizeInput;
2845 if (shouldSendTelemetry)
2848 AllocaInst *sentDataVariable =
new AllocaInst(boolType,
"sentData", currentBlock);
2849 new StoreInst(falseValue, sentDataVariable, currentBlock);
2851 for (set<VuoCompilerCable *>::iterator i = outgoingCables.begin(); i != outgoingCables.end(); ++i)
2858 compositionStateValue,
2860 shouldSummarizeInput[inputPort] = shouldSendDataForInput;
2867 compositionStateValue,
2870 for (set<VuoCompilerCable *>::iterator i = outgoingCables.begin(); i != outgoingCables.end(); ++i)
2877 shouldSummarizeOutput = BinaryOperator::Create(Instruction::Or, shouldSummarizeOutput, shouldSummarizeInput[inputPort],
"", currentBlock);
2881 BasicBlock *summaryBlock = BasicBlock::Create(module->getContext(),
"outputSummary",
function, NULL);
2882 BasicBlock *sendOutputBlock = BasicBlock::Create(module->getContext(),
"sendOutput",
function, NULL);
2883 BranchInst::Create(summaryBlock, sendOutputBlock, shouldSummarizeOutput, currentBlock);
2886 new StoreInst(trueValue, sentDataVariable, summaryBlock);
2891 new StoreInst(dataSummaryValue, dataSummaryVariable, summaryBlock);
2893 BranchInst::Create(sendOutputBlock, summaryBlock);
2894 currentBlock = sendOutputBlock;
2899 Value *sentDataValue =
new LoadInst(sentDataVariable,
"",
false, currentBlock);
2900 Value *dataSummaryValue =
new LoadInst(dataSummaryVariable,
"",
false, currentBlock);
2902 Constant *outputPortIdentifierValue = constantStrings.
get(module, outputPort->
getIdentifier());
2905 transmittedEventValue, sentDataValue, dataSummaryValue);
2911 BasicBlock *transmissionBlock = NULL;
2912 BasicBlock *noTransmissionBlock = NULL;
2913 if (alwaysTransmitsEvent)
2915 transmissionBlock = currentBlock;
2919 transmissionBlock = BasicBlock::Create(module->getContext(),
"transmission",
function, NULL);
2920 noTransmissionBlock = BasicBlock::Create(module->getContext(),
"noTransmission",
function, NULL);
2922 ConstantInt *zeroValue = ConstantInt::get(
static_cast<IntegerType *
>(eventValue->getType()), 0);
2923 ICmpInst *eventValueIsTrue =
new ICmpInst(*currentBlock, ICmpInst::ICMP_NE, eventValue, zeroValue,
"");
2924 BranchInst::Create(transmissionBlock, noTransmissionBlock, eventValueIsTrue, currentBlock);
2928 for (set<VuoCompilerCable *>::iterator i = outgoingCables.begin(); i != outgoingCables.end(); ++i)
2933 Value *inputNodeContextValue = inputNode->
generateGetContext(module, transmissionBlock, compositionStateValue);
2935 Value *inputPortContextValue = inputPort->
generateGetPortContext(module, transmissionBlock, inputNodeContextValue);
2937 Value *transmittedDataValue = (cable->
carriesData() ? dataValue : NULL);
2939 cable->
generateTransmission(module, transmissionBlock, inputNodeContextValue, inputPortContextValue, transmittedDataValue, requiresEvent);
2944 AllocaInst *inputDataSummaryVariable =
new AllocaInst(pointerToCharType,
"inputDataSummary", transmissionBlock);
2945 new StoreInst(ConstantPointerNull::get(pointerToCharType), inputDataSummaryVariable, transmissionBlock);
2948 AllocaInst *receivedDataVariable =
new AllocaInst(boolType,
"receivedData", transmissionBlock);
2949 new StoreInst(falseValue, receivedDataVariable, transmissionBlock);
2954 BasicBlock *summaryBlock = BasicBlock::Create(module->getContext(),
"inputSummary",
function, NULL);
2955 BasicBlock *sendInputBlock = BasicBlock::Create(module->getContext(),
"sendInput",
function, NULL);
2956 BranchInst::Create(summaryBlock, sendInputBlock, shouldSummarizeInput[inputPort], transmissionBlock);
2958 Value *inputDataSummaryValue;
2959 if (transmittedDataValue)
2962 new StoreInst(trueValue, receivedDataVariable, summaryBlock);
2965 inputDataSummaryValue =
new LoadInst(dataSummaryVariable,
"",
false, summaryBlock);
2970 Value *inputDataValue = inputPort->
generateLoadData(module, summaryBlock, inputNodeContextValue, inputPortContextValue);
2973 new StoreInst(inputDataSummaryValue, inputDataSummaryVariable, summaryBlock);
2975 BranchInst::Create(sendInputBlock, summaryBlock);
2976 transmissionBlock = sendInputBlock;
2979 Value *receivedDataValue =
new LoadInst(receivedDataVariable,
"",
false, transmissionBlock);
2980 Value *inputDataSummaryValue =
new LoadInst(inputDataSummaryVariable,
"",
false, transmissionBlock);
2982 Constant *inputPortIdentifierValue = constantStrings.
get(module, inputPort->
getIdentifier());
2985 transmittedEventValue, receivedDataValue, inputDataSummaryValue);
2987 if (inputDataType && ! transmittedDataValue)
2995 if (alwaysTransmitsEvent)
2997 currentBlock = transmissionBlock;
3001 BranchInst::Create(noTransmissionBlock, transmissionBlock);
3002 currentBlock = noTransmissionBlock;
3005 if (shouldSendTelemetry && dataValue)
3009 LoadInst *dataSummaryValue =
new LoadInst(dataSummaryVariable,
"",
false, currentBlock);
3010 CallInst::Create(freeFunction, dataSummaryValue,
"", currentBlock);
3018 void VuoCompilerBitcodeGenerator::generateTransmissionFromNode(Function *
function, BasicBlock *¤tBlock,
3019 Value *compositionStateValue, Value *nodeContextValue,
3023 for (vector<VuoPort *>::iterator i = outputPorts.begin(); i != outputPorts.end(); ++i)
3027 if (! outputEventPort)
3030 Value *portContextValue = outputEventPort->
generateGetPortContext(module, currentBlock, nodeContextValue);
3031 Value *outputEventValue = outputEventPort->
generateLoadEvent(module, currentBlock, nodeContextValue, portContextValue);
3033 BasicBlock *telemetryBlock = NULL;
3034 BasicBlock *noTelemetryBlock = NULL;
3037 telemetryBlock = BasicBlock::Create(module->getContext(),
"",
function, NULL);
3038 noTelemetryBlock = BasicBlock::Create(module->getContext(),
"",
function, NULL);
3041 ConstantInt *zeroValue = ConstantInt::get(
static_cast<IntegerType *
>(outputEventValue->getType()), 0);
3042 ICmpInst *eventValueIsTrue =
new ICmpInst(*currentBlock, ICmpInst::ICMP_NE, outputEventValue, zeroValue,
"");
3043 BranchInst::Create(telemetryBlock, noTelemetryBlock, eventValueIsTrue, currentBlock);
3047 telemetryBlock = currentBlock;
3052 Value *outputDataValue = (outputData ?
3053 outputEventPort->
generateLoadData(module, telemetryBlock, nodeContextValue, portContextValue) :
3055 generateTransmissionFromOutputPort(
function, telemetryBlock, compositionStateValue,
3056 node, outputEventPort, outputEventValue, outputDataValue, requiresEvent, shouldSendTelemetry);
3060 BranchInst::Create(noTelemetryBlock, telemetryBlock);
3061 currentBlock = noTelemetryBlock;
3065 currentBlock = telemetryBlock;
3074 void VuoCompilerBitcodeGenerator::generateTelemetryFromPublishedOutputNode(Function *
function, BasicBlock *¤tBlock, Value *compositionStateValue,
3077 IntegerType *boolType = IntegerType::get(module->getContext(), 1);
3078 PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3088 BasicBlock *telemetryBlock = BasicBlock::Create(module->getContext(),
"",
function, NULL);
3089 BasicBlock *noTelemetryBlock = BasicBlock::Create(module->getContext(),
"",
function, NULL);
3092 Value *eventValue = inputEventPort->
generateLoadEvent(module, currentBlock, nodeContextValue);
3093 ConstantInt *zeroValue = ConstantInt::get(
static_cast<IntegerType *
>(eventValue->getType()), 0);
3094 ICmpInst *eventValueIsTrue =
new ICmpInst(*currentBlock, ICmpInst::ICMP_NE, eventValue, zeroValue,
"");
3095 BranchInst::Create(telemetryBlock, noTelemetryBlock, eventValueIsTrue, currentBlock);
3098 Value *dataValue = data ? inputEventPort->
generateLoadData(module, telemetryBlock, nodeContextValue) : NULL;
3099 Constant *trueValue = ConstantInt::get(boolType, 1);
3100 Constant *falseValue = ConstantInt::get(boolType, 0);
3102 Value *sentDataValue = NULL;
3103 Value *dataSummaryValue = NULL;
3107 sentDataValue = trueValue;
3116 sentDataValue = falseValue;
3119 dataSummaryValue = ConstantPointerNull::get(pointerToCharType);
3124 sentDataValue, dataSummaryValue);
3126 BranchInst::Create(noTelemetryBlock, telemetryBlock);
3127 currentBlock = noTelemetryBlock;
3137 void VuoCompilerBitcodeGenerator::generateDataOnlyTransmissionFromNode(Function *
function, BasicBlock *¤tBlock, Value *compositionStateValue,
3139 bool shouldUpdateTriggers,
bool shouldSendTelemetry)
3142 if (downstreamNodes.empty())
3145 if (shouldWaitForDownstreamNodes)
3148 generateWaitForNodes(module,
function, currentBlock, compositionStateValue, downstreamNodes, NULL,
true);
3152 vector<VuoCompilerNode *> nodesToVisit = downstreamNodes;
3153 nodesToVisit.insert(nodesToVisit.begin(), node);
3158 Value *nodeContextValue = visitedNode->generateGetContext(module, currentBlock, compositionStateValue);
3161 vector<VuoPort *> inputPorts = visitedNode->getBase()->getInputPorts();
3169 generateNodeExecution(
function, currentBlock, compositionStateValue, visitedNode,
false);
3172 generateTransmissionFromNode(
function, currentBlock, compositionStateValue, nodeContextValue, visitedNode,
false, shouldSendTelemetry);
3178 if (visitedNode != node)
3180 if (shouldUpdateTriggers)
3183 visitedNode->generateCallbackUpdateFunctionCall(module, currentBlock, compositionStateValue);
3186 if (shouldWaitForDownstreamNodes)
3189 generateSignalForNodes(module, currentBlock, compositionStateValue, vector<VuoCompilerNode *>(1, visitedNode));
3198 void VuoCompilerBitcodeGenerator::generateNodeExecution(Function *
function, BasicBlock *¤tBlock,
3200 bool shouldSendTelemetry)
3202 Value *nodeIdentifierValue = constantStrings.
get(module, node->
getIdentifier());
3204 if (shouldSendTelemetry)
3215 if (shouldSendTelemetry)
3225 void VuoCompilerBitcodeGenerator::generateAllocation(
void)
3228 generateAllocation_Pro();
3233 new GlobalVariable(*module, value->getType(),
true, GlobalValue::ExternalLinkage, value,
"vuoTopLevelCompositionIdentifier");
3244 void VuoCompilerBitcodeGenerator::generateSetupFunction(
bool isStatefulComposition)
3247 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
3256 CallInst::Create(compositionCreateAndRegisterMetadataFunction, topLevelCompositionStateValue,
"", block);
3262 isStatefulComposition, publishedOutputPortCount);
3267 Value *falseValue = ConstantInt::get(compositionSetPublishedInputPortValueFunction->getFunctionType()->getParamType(3), 0);
3274 vector<Value *> args;
3275 args.push_back(topLevelCompositionStateValue);
3276 args.push_back( constantStrings.
get(module, name) );
3277 args.push_back( constantStrings.
get(module, initialValue) );
3278 args.push_back(falseValue);
3279 CallInst::Create(compositionSetPublishedInputPortValueFunction, args,
"", block);
3285 CallInst::Create(compositionPerformDataOnlyTransmissionsFunction, topLevelCompositionStateValue,
"", block);
3289 for (map<VuoCompilerTriggerPort *, Function *>::iterator i = topLevelTriggerFunctions.begin(); i != topLevelTriggerFunctions.end(); ++i)
3292 Function *
function = i->second;
3295 Value *nodeContextValue = node->
generateGetContext(module, block, topLevelCompositionStateValue);
3301 for (map<
string, map<
size_t, map<VuoCompilerTriggerDescription *, Function *> > >::iterator i = subcompositionTriggerFunctions.begin(); i != subcompositionTriggerFunctions.end(); ++i)
3303 string compositionIdentifier = i->first;
3305 for (map<
size_t, map<VuoCompilerTriggerDescription *, Function *> >::iterator j = i->second.begin(); j != i->second.end(); ++j)
3307 size_t nodeIndex = j->first;
3309 for (map<VuoCompilerTriggerDescription *, Function *>::iterator k = j->second.begin(); k != j->second.end(); ++k)
3312 Function *
function = k->second;
3314 Value *compositionIdentifierValue = constantStrings.
get(module, compositionIdentifier);
3329 ReturnInst::Create(module->getContext(), block);
3338 void VuoCompilerBitcodeGenerator::generateCleanupFunction(
void)
3341 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
3351 ReturnInst::Create(module->getContext(), block);
3359 void VuoCompilerBitcodeGenerator::generateInstanceInitFunction(
bool isStatefulComposition)
3362 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
3364 if (isStatefulComposition)
3366 map<VuoPort *, size_t> indexOfParameter;
3369 vector<VuoPort *>(),
3370 indexOfParameter, constantStrings);
3376 CallInst::Create(nodeInstanceInitFunction, topLevelCompositionStateValue,
"", block);
3381 ReturnInst::Create(module->getContext(), block);
3389 void VuoCompilerBitcodeGenerator::generateInstanceFiniFunction(
bool isStatefulComposition)
3392 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
3394 if (isStatefulComposition)
3404 PointerType *instanceDataType =
static_cast<PointerType *
>( nodeInstanceFiniFunction->getFunctionType()->getParamType(1) );
3405 ConstantPointerNull *nullInstanceDataValue = ConstantPointerNull::get(instanceDataType);
3407 vector<Value *> args;
3408 args.push_back(topLevelCompositionStateValue);
3409 args.push_back(nullInstanceDataValue);
3410 CallInst::Create(nodeInstanceFiniFunction, args,
"", block);
3415 ReturnInst::Create(module->getContext(), block);
3423 void VuoCompilerBitcodeGenerator::generateInstanceTriggerStartFunction(
bool isStatefulComposition)
3426 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
3428 if (isStatefulComposition)
3430 map<VuoPort *, size_t> indexOfParameter;
3433 vector<VuoPort *>(),
3441 PointerType *instanceDataType =
static_cast<PointerType *
>( nodeInstanceTriggerStartFunction->getFunctionType()->getParamType(1) );
3442 ConstantPointerNull *nullInstanceDataValue = ConstantPointerNull::get(instanceDataType);
3444 vector<Value *> args;
3445 args.push_back(topLevelCompositionStateValue);
3446 args.push_back(nullInstanceDataValue);
3447 CallInst::Create(nodeInstanceTriggerStartFunction, args,
"", block);
3452 ReturnInst::Create(module->getContext(), block);
3460 void VuoCompilerBitcodeGenerator::generateInstanceTriggerStopFunction(
bool isStatefulComposition)
3463 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
3474 PointerType *instanceDataType =
static_cast<PointerType *
>( nodeInstanceTriggerStopFunction->getFunctionType()->getParamType(1) );
3475 ConstantPointerNull *nullInstanceDataValue = ConstantPointerNull::get(instanceDataType);
3477 vector<Value *> args;
3478 args.push_back(topLevelCompositionStateValue);
3479 args.push_back(nullInstanceDataValue);
3480 CallInst::Create(nodeInstanceTriggerStopFunction, args,
"", block);
3485 ReturnInst::Create(module->getContext(), block);
3493 void VuoCompilerBitcodeGenerator::generateTriggerFunctions(
void)
3495 auto isSpinOffTrigger = [] (
const string &nodeClassName)
3502 map<VuoCompilerTriggerPort *, Function *> workerFunctionForTrigger;
3505 Function *workerFunction = generateTriggerWorkerFunction(trigger);
3506 workerFunctionForTrigger[trigger] = workerFunction;
3509 if (isTopLevelComposition)
3511 for (map<VuoCompilerTriggerPort *, Function *>::iterator i = workerFunctionForTrigger.begin(); i != workerFunctionForTrigger.end(); ++i)
3514 Function *workerFunction = i->second;
3531 int minThreadsNeeded, maxThreadsNeeded;
3534 int chainCount = (int)graph->
getChains()[trigger].size();
3537 portIdentifier, portContextIndex, canDropEvents, isPublishedTrigger, isSpinOff,
3538 minThreadsNeeded, maxThreadsNeeded, chainCount, workerFunction);
3539 topLevelTriggerFunctions[trigger] =
function;
3550 for (vector<VuoCompilerTriggerDescription *>::iterator j = triggers.begin(); j != triggers.end(); ++j)
3565 string fullSubcompositionNodeIdentifier = (subcompositionNodeIdentifier.empty() ?
3572 int minThreadsNeeded, maxThreadsNeeded;
3573 if (isPublishedTrigger)
3574 minThreadsNeeded = maxThreadsNeeded = -1;
3583 Function *
function = generateTriggerSchedulerFunction(dataType, fullSubcompositionNodeIdentifier, triggerNodeIndex,
3584 portIdentifier, portContextIndex, canDropEvents, isPublishedTrigger, isSpinOff,
3585 minThreadsNeeded, maxThreadsNeeded, chainCount, workerFunction);
3587 subcompositionTriggerFunctions[fullSubcompositionNodeIdentifier][triggerNodeIndex][trigger] =
function;
3636 Function * VuoCompilerBitcodeGenerator::generateTriggerSchedulerFunction(
VuoType *dataType,
3637 string compositionIdentifier,
size_t nodeIndex,
3638 string portIdentifier,
int portContextIndex,
3639 bool canDropEvents,
bool isPublishedInputTrigger,
bool isSpinOff,
3640 int minThreadsNeeded,
int maxThreadsNeeded,
int chainCount,
3641 Function *workerFunction)
3646 Function *
function = Function::Create(functionType, GlobalValue::InternalLinkage, functionName, module);
3651 function->setAttributes(paramAttributes);
3654 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, NULL);
3655 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, NULL);
3656 BasicBlock *scheduleBlock = BasicBlock::Create(module->getContext(),
"schedule",
function, NULL);
3659 Value *compositionIdentifierValue = constantStrings.
get(module, compositionIdentifier);
3670 BasicBlock *checkEventDropBlock = BasicBlock::Create(module->getContext(),
"checkEventDrop",
function, NULL);
3671 BranchInst::Create(checkEventDropBlock, initialBlock);
3675 Constant *zeroValue = ConstantInt::get(retValue->getType(), 0);
3676 ICmpInst *isTriggerAvailableValue =
new ICmpInst(*checkEventDropBlock, ICmpInst::ICMP_EQ, retValue, zeroValue,
"");
3677 BasicBlock *dropEventBlock = BasicBlock::Create(module->getContext(),
"dropEvent",
function, NULL);
3678 BranchInst::Create(scheduleBlock, dropEventBlock, isTriggerAvailableValue, checkEventDropBlock);
3685 Constant *portIdentifierValue = constantStrings.
get(module, portIdentifier);
3690 BranchInst::Create(finalBlock, dropEventBlock);
3694 BranchInst::Create(scheduleBlock, initialBlock);
3701 Value *eventIdValue;
3702 if (! isPublishedInputTrigger)
3724 compositionStateValue, eventIdValue, portContextValue, dataType,
3725 minThreadsNeeded, maxThreadsNeeded, chainCount, workerFunction);
3726 BranchInst::Create(finalBlock, scheduleBlock);
3728 ReturnInst::Create(module->getContext(), finalBlock);
3882 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, NULL);
3883 BasicBlock *triggerBlock = BasicBlock::Create(module->getContext(),
"trigger",
function, NULL);
3884 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, NULL);
3891 Value *triggerNodeContextValue = triggerNode->
generateGetContext(module, initialBlock, compositionStateValue);
3896 bool isNodeEventForSubcomposition = (! isTopLevelComposition && isPublishedInputTrigger);
3898 if (! isNodeEventForSubcomposition)
3901 BasicBlock *isPausedBlock = BasicBlock::Create(module->getContext(),
"isPaused",
function, NULL);
3903 BranchInst::Create(isPausedBlock, triggerBlock, isPausedValueIsTrue, initialBlock);
3910 vector<VuoCompilerNode *> publishedOutputNodeVector(1, publishedOutputNode);
3911 if (publishedOutputNode && ! isPublishedInputTrigger)
3912 generateWaitForNodes(module,
function, isPausedBlock, compositionStateValue, publishedOutputNodeVector);
3917 if (isPublishedInputTrigger)
3920 vector<VuoCompilerNode *> triggerWaitNodes = getNodesToWaitOnBeforeTransmission(trigger);
3921 generateSignalForNodes(module, isPausedBlock, compositionStateValue, triggerWaitNodes);
3925 if (publishedOutputNode)
3926 generateSignalForNodes(module, isPausedBlock, compositionStateValue, publishedOutputNodeVector);
3938 BranchInst::Create(finalBlock, isPausedBlock);
3943 BranchInst::Create(triggerBlock, initialBlock);
3946 if (isPublishedInputTrigger)
3948 if (! isNodeEventForSubcomposition)
3951 vector<VuoCompilerNode *> triggerWaitNodes = getNodesToWaitOnBeforeTransmission(trigger);
3953 if (find(triggerWaitNodes.begin(), triggerWaitNodes.end(), publishedOutputNode) == triggerWaitNodes.end())
3955 vector<VuoCompilerNode *> publishedOutputNodeVector(1, publishedOutputNode);
3956 generateSignalForNodes(module, triggerBlock, compositionStateValue, publishedOutputNodeVector);
3963 vector<VuoCompilerNode *> triggerWaitNodes = getNodesToWaitOnBeforeTransmission(trigger);
3964 generateWaitForNodes(module,
function, triggerBlock, compositionStateValue, triggerWaitNodes, eventIdValue);
3967 Value *triggerDataValue = trigger->
generateDataValueUpdate(module, triggerBlock,
function, triggerNodeContextValue);
3970 generateTransmissionFromOutputPort(
function, triggerBlock, compositionStateValue, triggerNode, trigger, NULL, triggerDataValue);
3975 if (find(downstreamNodes.begin(), downstreamNodes.end(), triggerNode) == downstreamNodes.end())
3976 generateSignalForNodes(module, triggerBlock, compositionStateValue, vector<VuoCompilerNode *>(1, triggerNode));
3988 map<VuoCompilerChain *, vector<VuoCompilerChain *> > chainsImmediatelyDownstream;
3989 map<VuoCompilerChain *, vector<VuoCompilerChain *> > chainsImmediatelyUpstream;
3990 set<VuoCompilerChain *> chainsScheduled;
3992 vector<VuoCompilerChain *> allChains = chainsForTrigger[trigger];
3994 if (! allChains.empty())
3997 for (vector<VuoCompilerChain *>::iterator i = allChains.begin(); i != allChains.end(); ++i)
4002 for (vector<VuoCompilerChain *>::iterator j = allChains.begin(); j != allChains.end(); ++j)
4006 if (chain == otherChain)
4011 if (graph->
mayTransmit(lastNodeInOtherChain, firstNodeInThisChain, trigger))
4013 chainsImmediatelyUpstream[chain].push_back(otherChain);
4014 chainsImmediatelyDownstream[otherChain].push_back(chain);
4023 vector<VuoCompilerChain *> firstChains;
4024 for (vector<VuoCompilerChain *>::iterator i = allChains.begin(); i != allChains.end(); ++i)
4027 map<VuoCompilerChain *, vector<VuoCompilerChain *> >::iterator upstreamIter = chainsImmediatelyUpstream.find(chain);
4028 if (upstreamIter == chainsImmediatelyUpstream.end())
4029 firstChains.push_back(chain);
4034 firstChains.pop_back();
4035 chainsScheduled.insert(chainToExecute);
4036 size_t chainIndex = find(allChains.begin(), allChains.end(), chainToExecute) - allChains.begin();
4040 int minThreadsNeeded, maxThreadsNeeded;
4043 eventIdValue, compositionStateValue, chainIndex);
4046 generateAndScheduleChainWorkerFunctions(triggerBlock, compositionStateValue, contextValue, firstChains, trigger,
4047 allChains, chainsImmediatelyDownstream, chainsImmediatelyUpstream, chainsScheduled);
4050 generateChainExecution(
function, triggerBlock, compositionStateValue, contextValue, eventIdValue, chainToExecute, trigger,
4051 allChains, chainsImmediatelyDownstream, chainsImmediatelyUpstream, chainsScheduled);
4059 if (isNodeEventForSubcomposition)
4067 BranchInst::Create(finalBlock, triggerBlock);
4073 ReturnInst::Create(module->getContext(), finalBlock);
4081 void VuoCompilerBitcodeGenerator::generateAndScheduleChainWorkerFunctions(BasicBlock *schedulerBlock,
4082 Value *compositionStateValueInScheduler, Value *contextValueInScheduler,
4084 const vector<VuoCompilerChain *> &allChains,
4085 const map<
VuoCompilerChain *, vector<VuoCompilerChain *> > &chainsImmediatelyDownstream,
4086 const map<
VuoCompilerChain *, vector<VuoCompilerChain *> > &chainsImmediatelyUpstream,
4087 set<VuoCompilerChain *> &chainsScheduled)
4090 vector<VuoCompilerChain *> uniqueChainsToSchedule;
4091 for (vector<VuoCompilerChain *>::const_iterator i = chainsToSchedule.begin(); i != chainsToSchedule.end(); ++i)
4094 if (chainsScheduled.find(chain) == chainsScheduled.end())
4096 uniqueChainsToSchedule.push_back(chain);
4097 chainsScheduled.insert(chain);
4102 for (vector<VuoCompilerChain *>::const_iterator i = uniqueChainsToSchedule.begin(); i != uniqueChainsToSchedule.end(); ++i)
4106 for (vector<VuoCompilerChain *>::const_iterator i = uniqueChainsToSchedule.begin(); i != uniqueChainsToSchedule.end(); ++i)
4109 generateAndScheduleChainWorkerFunction(schedulerBlock, compositionStateValueInScheduler, contextValueInScheduler,
4110 chain, trigger, allChains, chainsImmediatelyDownstream, chainsImmediatelyUpstream,
4118 void VuoCompilerBitcodeGenerator::generateAndScheduleChainWorkerFunction(BasicBlock *schedulerBlock,
4119 Value *compositionStateValueInScheduler, Value *contextValueInScheduler,
4121 const vector<VuoCompilerChain *> &allChains,
4122 const map<
VuoCompilerChain *, vector<VuoCompilerChain *> > &chainsImmediatelyDownstream,
4123 const map<
VuoCompilerChain *, vector<VuoCompilerChain *> > &chainsImmediatelyUpstream,
4124 set<VuoCompilerChain *> &chainsScheduled)
4126 int minThreadsNeeded, maxThreadsNeeded;
4129 size_t chainIndex = find(allChains.begin(), allChains.end(), chain) - allChains.begin();
4131 vector<VuoCompilerChain *> upstreamChains;
4132 map<VuoCompilerChain *, vector<VuoCompilerChain *> >::const_iterator upstreamChainsIter = chainsImmediatelyUpstream.find(chain);
4133 if (upstreamChainsIter != chainsImmediatelyUpstream.end())
4134 upstreamChains = upstreamChainsIter->second;
4136 vector<size_t> upstreamChainIndices;
4137 for (vector<VuoCompilerChain *>::iterator i = upstreamChains.begin(); i != upstreamChains.end(); ++i)
4138 upstreamChainIndices.push_back( find(allChains.begin(), allChains.end(), *i) - allChains.begin() );
4141 Function *chainWorker = chain->
generateScheduleWorker(module, schedulerBlock, compositionStateValueInScheduler, contextValueInScheduler,
4142 trigger->
getIdentifier(), minThreadsNeeded, maxThreadsNeeded, chainIndex,
4143 upstreamChainIndices);
4145 BasicBlock *chainBlock = BasicBlock::Create(module->getContext(),
"", chainWorker, 0);
4146 Value *contextValueInChainWorker = chainWorker->arg_begin();
4148 Value *eventIdValue = chain->
generateEventIdValue(module, chainBlock, contextValueInChainWorker);
4151 generateChainExecution(chainWorker, chainBlock, compositionStateValueInChainWorker, contextValueInChainWorker, eventIdValue, chain, trigger,
4152 allChains, chainsImmediatelyDownstream, chainsImmediatelyUpstream, chainsScheduled);
4157 ReturnInst::Create(module->getContext(), chainBlock);
4163 void VuoCompilerBitcodeGenerator::generateChainExecution(Function *
function, BasicBlock *&block,
4164 Value *compositionStateValue, Value *contextValue,
4166 const vector<VuoCompilerChain *> &allChains,
4167 const map<
VuoCompilerChain *, vector<VuoCompilerChain *> > &chainsImmediatelyDownstream,
4168 const map<
VuoCompilerChain *, vector<VuoCompilerChain *> > &chainsImmediatelyUpstream,
4169 set<VuoCompilerChain *> &chainsScheduled)
4171 size_t chainIndex = find(allChains.begin(), allChains.end(), chain) - allChains.begin();
4172 Value *chainIndexValue = ConstantInt::get(eventIdValue->getType(), chainIndex);
4175 vector<VuoCompilerNode *> chainNodes = chain->
getNodes();
4176 for (vector<VuoCompilerNode *>::iterator i = chainNodes.begin(); i != chainNodes.end(); ++i)
4180 Function *nodeExecutionFunction = executionFunctionForNode[node];
4181 if (! nodeExecutionFunction)
4183 nodeExecutionFunction = generateNodeExecutionFunction(module, node);
4184 executionFunctionForNode[node] = nodeExecutionFunction;
4187 Function *nodeTransmissionFunction = transmissionFunctionForNode[node];
4188 if (! nodeTransmissionFunction)
4190 nodeTransmissionFunction = generateNodeTransmissionFunction(module, node);
4191 transmissionFunctionForNode[node] = nodeTransmissionFunction;
4195 vector<Value *> nodeExecutionArgs;
4196 nodeExecutionArgs.push_back(compositionStateValue);
4197 nodeExecutionArgs.push_back(eventIdValue);
4198 nodeExecutionArgs.push_back(chainIndexValue);
4199 CallInst *isHitValue = CallInst::Create(nodeExecutionFunction, nodeExecutionArgs,
"", block);
4204 vector<VuoCompilerNode *> outputNodes = getNodesToWaitOnBeforeTransmission(trigger, node);
4205 generateWaitForNodes(module,
function, block, compositionStateValue, outputNodes, eventIdValue);
4209 vector<Value *> nodeTransmissionArgs;
4210 nodeTransmissionArgs.push_back(compositionStateValue);
4211 nodeTransmissionArgs.push_back(isHitValue);
4212 CallInst::Create(nodeTransmissionFunction, nodeTransmissionArgs,
"", block);
4221 generateSignalForNodes(module, block, compositionStateValue, vector<VuoCompilerNode *>(1, node));
4226 vector<VuoCompilerChain *> downstreamChains;
4227 map<VuoCompilerChain *, vector<VuoCompilerChain *> >::const_iterator downstreamChainsIter = chainsImmediatelyDownstream.find(chain);
4228 if (downstreamChainsIter != chainsImmediatelyDownstream.end())
4229 downstreamChains = downstreamChainsIter->second;
4230 if (! downstreamChains.empty())
4232 vector<size_t> downstreamChainIndices;
4233 for (vector<VuoCompilerChain *>::iterator i = downstreamChains.begin(); i != downstreamChains.end(); ++i)
4234 downstreamChainIndices.push_back( find(allChains.begin(), allChains.end(), *i) - allChains.begin() );
4236 vector<VuoCompilerChain *> nextChains;
4237 for (vector<VuoCompilerChain *>::iterator i = downstreamChains.begin(); i != downstreamChains.end(); ++i)
4240 nextChains.push_back(downstreamChain);
4243 generateAndScheduleChainWorkerFunctions(block, compositionStateValue, contextValue, nextChains, trigger, allChains,
4244 chainsImmediatelyDownstream, chainsImmediatelyUpstream, chainsScheduled);
4296 Function * VuoCompilerBitcodeGenerator::generateNodeExecutionFunction(Module *module,
VuoCompilerNode *node)
4300 Type *boolType = IntegerType::get(module->getContext(), 1);
4302 vector<Type *> params;
4303 params.push_back(pointerToCompositionStateType);
4304 params.push_back(eventIdType);
4305 params.push_back(eventIdType);
4306 FunctionType *functionType = FunctionType::get(boolType, params,
false);
4307 Function *
function = Function::Create(functionType, GlobalValue::InternalLinkage, functionName, module);
4309 Function::arg_iterator args =
function->arg_begin();
4310 Value *compositionStateValue = args++;
4311 compositionStateValue->setName(
"compositionState");
4312 Value *eventIdValue = args++;
4313 eventIdValue->setName(
"eventId");
4314 Value *chainIndexValue = args++;
4315 chainIndexValue->setName(
"chainIndex");
4317 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, NULL);
4318 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, NULL);
4320 Value *nodeContextValue = node->
generateGetContext(module, initialBlock, compositionStateValue);
4325 if (isTopLevelComposition)
4329 BranchInst::Create(finalBlock, initialBlock);
4335 BasicBlock *currBlock = initialBlock;
4344 for (
size_t publishedPortIndex = 0; publishedPortIndex < publishedOutputPorts.size(); ++publishedPortIndex)
4350 if (publishedOutputTriggerNames.find( port->
getClass()->
getName() ) != publishedOutputTriggerNames.end())
4352 BasicBlock *triggerBlock = BasicBlock::Create(module->getContext(),
"trigger",
function, NULL);
4353 BasicBlock *nextBlock = BasicBlock::Create(module->getContext(),
"next",
function, NULL);
4354 BranchInst::Create(triggerBlock, nextBlock, isPortHitValue, currBlock);
4362 vector<Value *> args;
4365 Value *dataValue = eventPort->
generateLoadData(module, triggerBlock, nodeContextValue);
4368 Value *secondArg = NULL;
4369 Value **secondArgIfNeeded = (isLoweredToTwoParameters ? &secondArg : NULL);
4371 secondArgIfNeeded, module, triggerBlock);
4372 args.push_back(arg);
4374 args.push_back(secondArg);
4383 CallInst::Create(triggerFunction, args,
"", triggerBlock);
4384 BranchInst::Create(nextBlock, triggerBlock);
4386 currBlock = nextBlock;
4398 ConstantInt *falseValue = ConstantInt::get(
static_cast<IntegerType *
>(subcompositionFinishedValue->getType()), 0);
4399 ICmpInst *subcompositionFinishedIsTrue =
new ICmpInst(*currBlock, ICmpInst::ICMP_NE, subcompositionFinishedValue, falseValue,
"");
4400 BasicBlock *leaveBlock = BasicBlock::Create(module->getContext(),
"leave",
function, NULL);
4401 BasicBlock *signalBlock = BasicBlock::Create(module->getContext(),
"signal",
function, NULL);
4402 BranchInst::Create(leaveBlock, signalBlock, subcompositionFinishedIsTrue, currBlock);
4408 BranchInst::Create(finalBlock, leaveBlock);
4413 generateSignalForNodes(module, signalBlock, compositionStateValue, vector<VuoCompilerNode *>(1, node));
4414 BranchInst::Create(finalBlock, signalBlock);
4420 BasicBlock *executeBlock = BasicBlock::Create(module->getContext(),
"execute",
function, NULL);
4421 BranchInst::Create(executeBlock, finalBlock, isHitValue, initialBlock);
4432 eventIdValue, compositionStateValue, chainIndexValue,
4433 subcompositionIdentifierValue);
4439 generateNodeExecution(
function, executeBlock, compositionStateValue, node, shouldSendTelemetry);
4440 BranchInst::Create(finalBlock, executeBlock);
4443 ReturnInst::Create(module->getContext(), isHitValue, finalBlock);
4472 Function * VuoCompilerBitcodeGenerator::generateNodeTransmissionFunction(Module *module,
VuoCompilerNode *node)
4476 Type *boolType = IntegerType::get(module->getContext(), 1);
4477 vector<Type *> params;
4478 params.push_back(pointerToCompositionStateType);
4479 params.push_back(boolType);
4480 FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params,
false);
4481 Function *
function = Function::Create(functionType, GlobalValue::InternalLinkage, functionName, module);
4483 Function::arg_iterator args =
function->arg_begin();
4484 Value *compositionStateValue = args++;
4485 compositionStateValue->setName(
"compositionState");
4486 Value *isHitValue = args++;
4487 isHitValue->setName(
"isHit");
4489 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, NULL);
4490 BasicBlock *transmitBlock = BasicBlock::Create(module->getContext(),
"transmit",
function, NULL);
4491 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, NULL);
4494 BranchInst::Create(transmitBlock, finalBlock, isHitValue, initialBlock);
4496 Value *nodeContextValue = node->
generateGetContext(module, transmitBlock, compositionStateValue);
4500 if (isTopLevelComposition)
4501 generateTelemetryFromPublishedOutputNode(
function, transmitBlock, compositionStateValue, nodeContextValue, node);
4506 generateTransmissionFromNode(
function, transmitBlock, compositionStateValue, nodeContextValue, node);
4512 BranchInst::Create(finalBlock, transmitBlock);
4513 ReturnInst::Create(module->getContext(), finalBlock);
4523 this->debugMode = debugMode;