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,
false);
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,
2827 Value *eventValue, Value *dataValue,
2828 bool requiresEvent,
bool shouldSendTelemetry)
2830 IntegerType *boolType = IntegerType::get(module->getContext(), 1);
2831 PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
2835 Constant *trueValue = ConstantInt::get(boolType, 1);
2836 Constant *falseValue = ConstantInt::get(boolType, 0);
2837 Constant *transmittedEventValue = (requiresEvent ? trueValue : falseValue);
2840 AllocaInst *dataSummaryVariable =
new AllocaInst(pointerToCharType,
"dataSummary", currentBlock);
2841 new StoreInst(ConstantPointerNull::get(pointerToCharType), dataSummaryVariable, currentBlock);
2843 map<VuoCompilerPort *, ICmpInst *> shouldSummarizeInput;
2844 if (shouldSendTelemetry)
2847 AllocaInst *sentDataVariable =
new AllocaInst(boolType,
"sentData", currentBlock);
2848 new StoreInst(falseValue, sentDataVariable, currentBlock);
2850 for (set<VuoCompilerCable *>::iterator i = outgoingCables.begin(); i != outgoingCables.end(); ++i)
2857 compositionStateValue,
2859 shouldSummarizeInput[inputPort] = shouldSendDataForInput;
2866 compositionStateValue,
2869 for (set<VuoCompilerCable *>::iterator i = outgoingCables.begin(); i != outgoingCables.end(); ++i)
2876 shouldSummarizeOutput = BinaryOperator::Create(Instruction::Or, shouldSummarizeOutput, shouldSummarizeInput[inputPort],
"", currentBlock);
2880 BasicBlock *summaryBlock = BasicBlock::Create(module->getContext(),
"outputSummary",
function, NULL);
2881 BasicBlock *sendOutputBlock = BasicBlock::Create(module->getContext(),
"sendOutput",
function, NULL);
2882 BranchInst::Create(summaryBlock, sendOutputBlock, shouldSummarizeOutput, currentBlock);
2885 new StoreInst(trueValue, sentDataVariable, summaryBlock);
2890 new StoreInst(dataSummaryValue, dataSummaryVariable, summaryBlock);
2892 BranchInst::Create(sendOutputBlock, summaryBlock);
2893 currentBlock = sendOutputBlock;
2896 Value *sentDataValue =
new LoadInst(sentDataVariable,
"",
false, currentBlock);
2897 Value *dataSummaryValue =
new LoadInst(dataSummaryVariable,
"",
false, currentBlock);
2899 Constant *outputPortIdentifierValue = constantStrings.
get(module, outputPort->
getIdentifier());
2902 transmittedEventValue, sentDataValue, dataSummaryValue);
2907 BasicBlock *transmissionBlock = NULL;
2908 BasicBlock *noTransmissionBlock = NULL;
2909 if (alwaysTransmitsEvent)
2911 transmissionBlock = currentBlock;
2915 transmissionBlock = BasicBlock::Create(module->getContext(),
"transmission",
function, NULL);
2916 noTransmissionBlock = BasicBlock::Create(module->getContext(),
"noTransmission",
function, NULL);
2918 ConstantInt *zeroValue = ConstantInt::get(
static_cast<IntegerType *
>(eventValue->getType()), 0);
2919 ICmpInst *eventValueIsTrue =
new ICmpInst(*currentBlock, ICmpInst::ICMP_NE, eventValue, zeroValue,
"");
2920 BranchInst::Create(transmissionBlock, noTransmissionBlock, eventValueIsTrue, currentBlock);
2924 for (set<VuoCompilerCable *>::iterator i = outgoingCables.begin(); i != outgoingCables.end(); ++i)
2929 Value *inputNodeContextValue = inputNode->
generateGetContext(module, transmissionBlock, compositionStateValue);
2931 Value *inputPortContextValue = inputPort->
generateGetPortContext(module, transmissionBlock, inputNodeContextValue);
2933 Value *transmittedDataValue = (cable->
carriesData() ? dataValue : NULL);
2935 cable->
generateTransmission(module, transmissionBlock, inputNodeContextValue, inputPortContextValue, transmittedDataValue, requiresEvent);
2937 if (shouldSendTelemetry)
2940 AllocaInst *inputDataSummaryVariable =
new AllocaInst(pointerToCharType,
"inputDataSummary", transmissionBlock);
2941 new StoreInst(ConstantPointerNull::get(pointerToCharType), inputDataSummaryVariable, transmissionBlock);
2944 AllocaInst *receivedDataVariable =
new AllocaInst(boolType,
"receivedData", transmissionBlock);
2945 new StoreInst(falseValue, receivedDataVariable, transmissionBlock);
2950 BasicBlock *summaryBlock = BasicBlock::Create(module->getContext(),
"inputSummary",
function, NULL);
2951 BasicBlock *sendInputBlock = BasicBlock::Create(module->getContext(),
"sendInput",
function, NULL);
2952 BranchInst::Create(summaryBlock, sendInputBlock, shouldSummarizeInput[inputPort], transmissionBlock);
2954 Value *inputDataSummaryValue;
2955 if (transmittedDataValue)
2958 new StoreInst(trueValue, receivedDataVariable, summaryBlock);
2961 inputDataSummaryValue =
new LoadInst(dataSummaryVariable,
"",
false, summaryBlock);
2966 Value *inputDataValue = inputPort->
generateLoadData(module, summaryBlock, inputNodeContextValue, inputPortContextValue);
2969 new StoreInst(inputDataSummaryValue, inputDataSummaryVariable, summaryBlock);
2971 BranchInst::Create(sendInputBlock, summaryBlock);
2972 transmissionBlock = sendInputBlock;
2975 Value *receivedDataValue =
new LoadInst(receivedDataVariable,
"",
false, transmissionBlock);
2976 Value *inputDataSummaryValue =
new LoadInst(inputDataSummaryVariable,
"",
false, transmissionBlock);
2978 Constant *inputPortIdentifierValue = constantStrings.
get(module, inputPort->
getIdentifier());
2981 transmittedEventValue, receivedDataValue, inputDataSummaryValue);
2983 if (inputDataType && ! transmittedDataValue)
2991 if (alwaysTransmitsEvent)
2993 currentBlock = transmissionBlock;
2997 BranchInst::Create(noTransmissionBlock, transmissionBlock);
2998 currentBlock = noTransmissionBlock;
3001 if (shouldSendTelemetry && dataValue)
3005 LoadInst *dataSummaryValue =
new LoadInst(dataSummaryVariable,
"",
false, currentBlock);
3006 CallInst::Create(freeFunction, dataSummaryValue,
"", currentBlock);
3014 void VuoCompilerBitcodeGenerator::generateTransmissionFromNode(Function *
function, BasicBlock *¤tBlock,
3015 Value *compositionStateValue, Value *nodeContextValue,
3019 for (vector<VuoPort *>::iterator i = outputPorts.begin(); i != outputPorts.end(); ++i)
3023 if (! outputEventPort)
3026 Value *portContextValue = outputEventPort->
generateGetPortContext(module, currentBlock, nodeContextValue);
3027 Value *outputEventValue = outputEventPort->
generateLoadEvent(module, currentBlock, nodeContextValue, portContextValue);
3029 BasicBlock *telemetryBlock = NULL;
3030 BasicBlock *noTelemetryBlock = NULL;
3033 telemetryBlock = BasicBlock::Create(module->getContext(),
"",
function, NULL);
3034 noTelemetryBlock = BasicBlock::Create(module->getContext(),
"",
function, NULL);
3037 ConstantInt *zeroValue = ConstantInt::get(
static_cast<IntegerType *
>(outputEventValue->getType()), 0);
3038 ICmpInst *eventValueIsTrue =
new ICmpInst(*currentBlock, ICmpInst::ICMP_NE, outputEventValue, zeroValue,
"");
3039 BranchInst::Create(telemetryBlock, noTelemetryBlock, eventValueIsTrue, currentBlock);
3043 telemetryBlock = currentBlock;
3048 Value *outputDataValue = (outputData ?
3049 outputEventPort->
generateLoadData(module, telemetryBlock, nodeContextValue, portContextValue) :
3051 generateTransmissionFromOutputPort(
function, telemetryBlock, compositionStateValue,
3052 outputEventPort, outputEventValue, outputDataValue, requiresEvent, shouldSendTelemetry);
3056 BranchInst::Create(noTelemetryBlock, telemetryBlock);
3057 currentBlock = noTelemetryBlock;
3061 currentBlock = telemetryBlock;
3070 void VuoCompilerBitcodeGenerator::generateTelemetryFromPublishedOutputNode(Function *
function, BasicBlock *¤tBlock, Value *compositionStateValue,
3073 IntegerType *boolType = IntegerType::get(module->getContext(), 1);
3074 PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
3077 for (vector<VuoPort *>::iterator i = inputPorts.begin(); i != inputPorts.end(); ++i)
3081 BasicBlock *telemetryBlock = BasicBlock::Create(module->getContext(),
"",
function, NULL);
3082 BasicBlock *noTelemetryBlock = BasicBlock::Create(module->getContext(),
"",
function, NULL);
3085 Value *eventValue = inputEventPort->
generateLoadEvent(module, currentBlock, nodeContextValue);
3086 ConstantInt *zeroValue = ConstantInt::get(
static_cast<IntegerType *
>(eventValue->getType()), 0);
3087 ICmpInst *eventValueIsTrue =
new ICmpInst(*currentBlock, ICmpInst::ICMP_NE, eventValue, zeroValue,
"");
3088 BranchInst::Create(telemetryBlock, noTelemetryBlock, eventValueIsTrue, currentBlock);
3091 Value *dataValue = data ? inputEventPort->
generateLoadData(module, telemetryBlock, nodeContextValue) : NULL;
3092 Constant *trueValue = ConstantInt::get(boolType, 1);
3093 Constant *falseValue = ConstantInt::get(boolType, 0);
3095 Value *sentDataValue = NULL;
3096 Value *dataSummaryValue = NULL;
3100 sentDataValue = trueValue;
3109 sentDataValue = falseValue;
3112 dataSummaryValue = ConstantPointerNull::get(pointerToCharType);
3117 sentDataValue, dataSummaryValue);
3119 BranchInst::Create(noTelemetryBlock, telemetryBlock);
3120 currentBlock = noTelemetryBlock;
3130 void VuoCompilerBitcodeGenerator::generateDataOnlyTransmissionFromNode(Function *
function, BasicBlock *¤tBlock, Value *compositionStateValue,
3132 bool shouldUpdateTriggers,
bool shouldSendTelemetry)
3135 if (downstreamNodes.empty())
3138 if (shouldWaitForDownstreamNodes)
3141 generateWaitForNodes(module,
function, currentBlock, compositionStateValue, downstreamNodes, NULL,
true);
3145 vector<VuoCompilerNode *> nodesToVisit = downstreamNodes;
3146 nodesToVisit.insert(nodesToVisit.begin(), node);
3151 Value *nodeContextValue = visitedNode->generateGetContext(module, currentBlock, compositionStateValue);
3154 vector<VuoPort *> inputPorts = visitedNode->getBase()->getInputPorts();
3162 generateNodeExecution(
function, currentBlock, compositionStateValue, visitedNode,
false);
3165 bool shouldSendTelemetryForNode = (shouldSendTelemetry && visitedNode != graph->
getPublishedInputNode());
3166 generateTransmissionFromNode(
function, currentBlock, compositionStateValue, nodeContextValue, visitedNode,
false, shouldSendTelemetryForNode);
3172 if (visitedNode != node)
3174 if (shouldUpdateTriggers)
3177 visitedNode->generateCallbackUpdateFunctionCall(module, currentBlock, compositionStateValue);
3180 if (shouldWaitForDownstreamNodes)
3183 generateSignalForNodes(module, currentBlock, compositionStateValue, vector<VuoCompilerNode *>(1, visitedNode));
3192 void VuoCompilerBitcodeGenerator::generateNodeExecution(Function *
function, BasicBlock *¤tBlock,
3194 bool shouldSendTelemetry)
3196 Value *nodeIdentifierValue = constantStrings.
get(module, node->
getIdentifier());
3198 if (shouldSendTelemetry)
3209 if (shouldSendTelemetry)
3219 void VuoCompilerBitcodeGenerator::generateAllocation(
void)
3222 generateAllocation_Pro();
3227 new GlobalVariable(*module, value->getType(),
true, GlobalValue::ExternalLinkage, value,
"vuoTopLevelCompositionIdentifier");
3238 void VuoCompilerBitcodeGenerator::generateSetupFunction(
bool isStatefulComposition)
3241 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
3250 CallInst::Create(compositionCreateAndRegisterMetadataFunction, topLevelCompositionStateValue,
"", block);
3256 isStatefulComposition, publishedOutputPortCount);
3261 Value *falseValue = ConstantInt::get(compositionSetPublishedInputPortValueFunction->getFunctionType()->getParamType(3), 0);
3268 vector<Value *> args;
3269 args.push_back(topLevelCompositionStateValue);
3270 args.push_back( constantStrings.
get(module, name) );
3271 args.push_back( constantStrings.
get(module, initialValue) );
3272 args.push_back(falseValue);
3273 CallInst::Create(compositionSetPublishedInputPortValueFunction, args,
"", block);
3279 CallInst::Create(compositionPerformDataOnlyTransmissionsFunction, topLevelCompositionStateValue,
"", block);
3283 for (map<VuoCompilerTriggerPort *, Function *>::iterator i = topLevelTriggerFunctions.begin(); i != topLevelTriggerFunctions.end(); ++i)
3286 Function *
function = i->second;
3289 Value *nodeContextValue = node->
generateGetContext(module, block, topLevelCompositionStateValue);
3295 for (map<
string, map<
size_t, map<VuoCompilerTriggerDescription *, Function *> > >::iterator i = subcompositionTriggerFunctions.begin(); i != subcompositionTriggerFunctions.end(); ++i)
3297 string compositionIdentifier = i->first;
3299 for (map<
size_t, map<VuoCompilerTriggerDescription *, Function *> >::iterator j = i->second.begin(); j != i->second.end(); ++j)
3301 size_t nodeIndex = j->first;
3303 for (map<VuoCompilerTriggerDescription *, Function *>::iterator k = j->second.begin(); k != j->second.end(); ++k)
3306 Function *
function = k->second;
3308 Value *compositionIdentifierValue = constantStrings.
get(module, compositionIdentifier);
3323 ReturnInst::Create(module->getContext(), block);
3332 void VuoCompilerBitcodeGenerator::generateCleanupFunction(
void)
3335 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
3345 ReturnInst::Create(module->getContext(), block);
3353 void VuoCompilerBitcodeGenerator::generateInstanceInitFunction(
bool isStatefulComposition)
3356 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
3358 if (isStatefulComposition)
3360 map<VuoPort *, size_t> indexOfParameter;
3363 vector<VuoPort *>(),
3364 indexOfParameter, constantStrings);
3370 CallInst::Create(nodeInstanceInitFunction, topLevelCompositionStateValue,
"", block);
3375 ReturnInst::Create(module->getContext(), block);
3383 void VuoCompilerBitcodeGenerator::generateInstanceFiniFunction(
bool isStatefulComposition)
3386 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
3388 if (isStatefulComposition)
3398 PointerType *instanceDataType =
static_cast<PointerType *
>( nodeInstanceFiniFunction->getFunctionType()->getParamType(1) );
3399 ConstantPointerNull *nullInstanceDataValue = ConstantPointerNull::get(instanceDataType);
3401 vector<Value *> args;
3402 args.push_back(topLevelCompositionStateValue);
3403 args.push_back(nullInstanceDataValue);
3404 CallInst::Create(nodeInstanceFiniFunction, args,
"", block);
3409 ReturnInst::Create(module->getContext(), block);
3417 void VuoCompilerBitcodeGenerator::generateInstanceTriggerStartFunction(
bool isStatefulComposition)
3420 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
3422 if (isStatefulComposition)
3424 map<VuoPort *, size_t> indexOfParameter;
3427 vector<VuoPort *>(),
3435 PointerType *instanceDataType =
static_cast<PointerType *
>( nodeInstanceTriggerStartFunction->getFunctionType()->getParamType(1) );
3436 ConstantPointerNull *nullInstanceDataValue = ConstantPointerNull::get(instanceDataType);
3438 vector<Value *> args;
3439 args.push_back(topLevelCompositionStateValue);
3440 args.push_back(nullInstanceDataValue);
3441 CallInst::Create(nodeInstanceTriggerStartFunction, args,
"", block);
3446 ReturnInst::Create(module->getContext(), block);
3454 void VuoCompilerBitcodeGenerator::generateInstanceTriggerStopFunction(
bool isStatefulComposition)
3457 BasicBlock *block = BasicBlock::Create(module->getContext(),
"",
function, NULL);
3468 PointerType *instanceDataType =
static_cast<PointerType *
>( nodeInstanceTriggerStopFunction->getFunctionType()->getParamType(1) );
3469 ConstantPointerNull *nullInstanceDataValue = ConstantPointerNull::get(instanceDataType);
3471 vector<Value *> args;
3472 args.push_back(topLevelCompositionStateValue);
3473 args.push_back(nullInstanceDataValue);
3474 CallInst::Create(nodeInstanceTriggerStopFunction, args,
"", block);
3479 ReturnInst::Create(module->getContext(), block);
3487 void VuoCompilerBitcodeGenerator::generateTriggerFunctions(
void)
3489 auto isSpinOffTrigger = [] (
const string &nodeClassName)
3496 map<VuoCompilerTriggerPort *, Function *> workerFunctionForTrigger;
3499 Function *workerFunction = generateTriggerWorkerFunction(trigger);
3500 workerFunctionForTrigger[trigger] = workerFunction;
3503 if (isTopLevelComposition)
3505 for (map<VuoCompilerTriggerPort *, Function *>::iterator i = workerFunctionForTrigger.begin(); i != workerFunctionForTrigger.end(); ++i)
3508 Function *workerFunction = i->second;
3525 int minThreadsNeeded, maxThreadsNeeded;
3528 int chainCount = (int)graph->
getChains()[trigger].size();
3531 portIdentifier, portContextIndex, canDropEvents, isPublishedTrigger, isSpinOff,
3532 minThreadsNeeded, maxThreadsNeeded, chainCount, workerFunction);
3533 topLevelTriggerFunctions[trigger] =
function;
3544 for (vector<VuoCompilerTriggerDescription *>::iterator j = triggers.begin(); j != triggers.end(); ++j)
3559 string fullSubcompositionNodeIdentifier = (subcompositionNodeIdentifier.empty() ?
3566 int minThreadsNeeded, maxThreadsNeeded;
3567 if (isPublishedTrigger)
3568 minThreadsNeeded = maxThreadsNeeded = -1;
3577 Function *
function = generateTriggerSchedulerFunction(dataType, fullSubcompositionNodeIdentifier, triggerNodeIndex,
3578 portIdentifier, portContextIndex, canDropEvents, isPublishedTrigger, isSpinOff,
3579 minThreadsNeeded, maxThreadsNeeded, chainCount, workerFunction);
3581 subcompositionTriggerFunctions[fullSubcompositionNodeIdentifier][triggerNodeIndex][trigger] =
function;
3630 Function * VuoCompilerBitcodeGenerator::generateTriggerSchedulerFunction(
VuoType *dataType,
3631 string compositionIdentifier,
size_t nodeIndex,
3632 string portIdentifier,
int portContextIndex,
3633 bool canDropEvents,
bool isPublishedInputTrigger,
bool isSpinOff,
3634 int minThreadsNeeded,
int maxThreadsNeeded,
int chainCount,
3635 Function *workerFunction)
3640 Function *
function = Function::Create(functionType, GlobalValue::InternalLinkage, functionName, module);
3645 function->setAttributes(paramAttributes);
3648 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, NULL);
3649 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, NULL);
3650 BasicBlock *scheduleBlock = BasicBlock::Create(module->getContext(),
"schedule",
function, NULL);
3653 Value *compositionIdentifierValue = constantStrings.
get(module, compositionIdentifier);
3664 BasicBlock *checkEventDropBlock = BasicBlock::Create(module->getContext(),
"checkEventDrop",
function, NULL);
3665 BranchInst::Create(checkEventDropBlock, initialBlock);
3669 Constant *zeroValue = ConstantInt::get(retValue->getType(), 0);
3670 ICmpInst *isTriggerAvailableValue =
new ICmpInst(*checkEventDropBlock, ICmpInst::ICMP_EQ, retValue, zeroValue,
"");
3671 BasicBlock *dropEventBlock = BasicBlock::Create(module->getContext(),
"dropEvent",
function, NULL);
3672 BranchInst::Create(scheduleBlock, dropEventBlock, isTriggerAvailableValue, checkEventDropBlock);
3679 Constant *portIdentifierValue = constantStrings.
get(module, portIdentifier);
3684 BranchInst::Create(finalBlock, dropEventBlock);
3688 BranchInst::Create(scheduleBlock, initialBlock);
3695 Value *eventIdValue;
3696 if (! isPublishedInputTrigger)
3718 compositionStateValue, eventIdValue, portContextValue, dataType,
3719 minThreadsNeeded, maxThreadsNeeded, chainCount, workerFunction);
3720 BranchInst::Create(finalBlock, scheduleBlock);
3722 ReturnInst::Create(module->getContext(), finalBlock);
3876 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, NULL);
3877 BasicBlock *triggerBlock = BasicBlock::Create(module->getContext(),
"trigger",
function, NULL);
3878 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, NULL);
3885 Value *triggerNodeContextValue = triggerNode->
generateGetContext(module, initialBlock, compositionStateValue);
3890 bool isNodeEventForSubcomposition = (! isTopLevelComposition && isPublishedInputTrigger);
3892 if (! isNodeEventForSubcomposition)
3895 BasicBlock *isPausedBlock = BasicBlock::Create(module->getContext(),
"isPaused",
function, NULL);
3897 BranchInst::Create(isPausedBlock, triggerBlock, isPausedValueIsTrue, initialBlock);
3904 vector<VuoCompilerNode *> publishedOutputNodeVector(1, publishedOutputNode);
3905 if (publishedOutputNode && ! isPublishedInputTrigger)
3906 generateWaitForNodes(module,
function, isPausedBlock, compositionStateValue, publishedOutputNodeVector);
3911 if (isPublishedInputTrigger)
3914 vector<VuoCompilerNode *> triggerWaitNodes = getNodesToWaitOnBeforeTransmission(trigger);
3915 generateSignalForNodes(module, isPausedBlock, compositionStateValue, triggerWaitNodes);
3919 if (publishedOutputNode)
3920 generateSignalForNodes(module, isPausedBlock, compositionStateValue, publishedOutputNodeVector);
3932 BranchInst::Create(finalBlock, isPausedBlock);
3937 BranchInst::Create(triggerBlock, initialBlock);
3940 if (isPublishedInputTrigger)
3942 if (! isNodeEventForSubcomposition)
3945 vector<VuoCompilerNode *> triggerWaitNodes = getNodesToWaitOnBeforeTransmission(trigger);
3947 if (find(triggerWaitNodes.begin(), triggerWaitNodes.end(), publishedOutputNode) == triggerWaitNodes.end())
3949 vector<VuoCompilerNode *> publishedOutputNodeVector(1, publishedOutputNode);
3950 generateSignalForNodes(module, triggerBlock, compositionStateValue, publishedOutputNodeVector);
3957 vector<VuoCompilerNode *> triggerWaitNodes = getNodesToWaitOnBeforeTransmission(trigger);
3958 generateWaitForNodes(module,
function, triggerBlock, compositionStateValue, triggerWaitNodes, eventIdValue);
3961 Value *triggerDataValue = trigger->
generateDataValueUpdate(module, triggerBlock,
function, triggerNodeContextValue);
3964 generateTransmissionFromOutputPort(
function, triggerBlock, compositionStateValue, trigger, NULL, triggerDataValue);
3969 if (find(downstreamNodes.begin(), downstreamNodes.end(), triggerNode) == downstreamNodes.end())
3970 generateSignalForNodes(module, triggerBlock, compositionStateValue, vector<VuoCompilerNode *>(1, triggerNode));
3982 map<VuoCompilerChain *, vector<VuoCompilerChain *> > chainsImmediatelyDownstream;
3983 map<VuoCompilerChain *, vector<VuoCompilerChain *> > chainsImmediatelyUpstream;
3984 set<VuoCompilerChain *> chainsScheduled;
3986 vector<VuoCompilerChain *> allChains = chainsForTrigger[trigger];
3988 if (! allChains.empty())
3991 for (vector<VuoCompilerChain *>::iterator i = allChains.begin(); i != allChains.end(); ++i)
3996 for (vector<VuoCompilerChain *>::iterator j = allChains.begin(); j != allChains.end(); ++j)
4000 if (chain == otherChain)
4005 if (graph->
mayTransmit(lastNodeInOtherChain, firstNodeInThisChain, trigger))
4007 chainsImmediatelyUpstream[chain].push_back(otherChain);
4008 chainsImmediatelyDownstream[otherChain].push_back(chain);
4017 vector<VuoCompilerChain *> firstChains;
4018 for (vector<VuoCompilerChain *>::iterator i = allChains.begin(); i != allChains.end(); ++i)
4021 map<VuoCompilerChain *, vector<VuoCompilerChain *> >::iterator upstreamIter = chainsImmediatelyUpstream.find(chain);
4022 if (upstreamIter == chainsImmediatelyUpstream.end())
4023 firstChains.push_back(chain);
4028 firstChains.pop_back();
4029 chainsScheduled.insert(chainToExecute);
4030 size_t chainIndex = find(allChains.begin(), allChains.end(), chainToExecute) - allChains.begin();
4034 int minThreadsNeeded, maxThreadsNeeded;
4037 eventIdValue, compositionStateValue, chainIndex);
4040 generateAndScheduleChainWorkerFunctions(triggerBlock, compositionStateValue, contextValue, firstChains, trigger,
4041 allChains, chainsImmediatelyDownstream, chainsImmediatelyUpstream, chainsScheduled);
4044 generateChainExecution(
function, triggerBlock, compositionStateValue, contextValue, eventIdValue, chainToExecute, trigger,
4045 allChains, chainsImmediatelyDownstream, chainsImmediatelyUpstream, chainsScheduled);
4053 if (isNodeEventForSubcomposition)
4061 BranchInst::Create(finalBlock, triggerBlock);
4067 ReturnInst::Create(module->getContext(), finalBlock);
4075 void VuoCompilerBitcodeGenerator::generateAndScheduleChainWorkerFunctions(BasicBlock *schedulerBlock,
4076 Value *compositionStateValueInScheduler, Value *contextValueInScheduler,
4078 const vector<VuoCompilerChain *> &allChains,
4079 const map<
VuoCompilerChain *, vector<VuoCompilerChain *> > &chainsImmediatelyDownstream,
4080 const map<
VuoCompilerChain *, vector<VuoCompilerChain *> > &chainsImmediatelyUpstream,
4081 set<VuoCompilerChain *> &chainsScheduled)
4084 vector<VuoCompilerChain *> uniqueChainsToSchedule;
4085 for (vector<VuoCompilerChain *>::const_iterator i = chainsToSchedule.begin(); i != chainsToSchedule.end(); ++i)
4088 if (chainsScheduled.find(chain) == chainsScheduled.end())
4090 uniqueChainsToSchedule.push_back(chain);
4091 chainsScheduled.insert(chain);
4096 for (vector<VuoCompilerChain *>::const_iterator i = uniqueChainsToSchedule.begin(); i != uniqueChainsToSchedule.end(); ++i)
4100 for (vector<VuoCompilerChain *>::const_iterator i = uniqueChainsToSchedule.begin(); i != uniqueChainsToSchedule.end(); ++i)
4103 generateAndScheduleChainWorkerFunction(schedulerBlock, compositionStateValueInScheduler, contextValueInScheduler,
4104 chain, trigger, allChains, chainsImmediatelyDownstream, chainsImmediatelyUpstream,
4112 void VuoCompilerBitcodeGenerator::generateAndScheduleChainWorkerFunction(BasicBlock *schedulerBlock,
4113 Value *compositionStateValueInScheduler, Value *contextValueInScheduler,
4115 const vector<VuoCompilerChain *> &allChains,
4116 const map<
VuoCompilerChain *, vector<VuoCompilerChain *> > &chainsImmediatelyDownstream,
4117 const map<
VuoCompilerChain *, vector<VuoCompilerChain *> > &chainsImmediatelyUpstream,
4118 set<VuoCompilerChain *> &chainsScheduled)
4120 int minThreadsNeeded, maxThreadsNeeded;
4123 size_t chainIndex = find(allChains.begin(), allChains.end(), chain) - allChains.begin();
4125 vector<VuoCompilerChain *> upstreamChains;
4126 map<VuoCompilerChain *, vector<VuoCompilerChain *> >::const_iterator upstreamChainsIter = chainsImmediatelyUpstream.find(chain);
4127 if (upstreamChainsIter != chainsImmediatelyUpstream.end())
4128 upstreamChains = upstreamChainsIter->second;
4130 vector<size_t> upstreamChainIndices;
4131 for (vector<VuoCompilerChain *>::iterator i = upstreamChains.begin(); i != upstreamChains.end(); ++i)
4132 upstreamChainIndices.push_back( find(allChains.begin(), allChains.end(), *i) - allChains.begin() );
4135 Function *chainWorker = chain->
generateScheduleWorker(module, schedulerBlock, compositionStateValueInScheduler, contextValueInScheduler,
4136 trigger->
getIdentifier(), minThreadsNeeded, maxThreadsNeeded, chainIndex,
4137 upstreamChainIndices);
4139 BasicBlock *chainBlock = BasicBlock::Create(module->getContext(),
"", chainWorker, 0);
4140 Value *contextValueInChainWorker = chainWorker->arg_begin();
4142 Value *eventIdValue = chain->
generateEventIdValue(module, chainBlock, contextValueInChainWorker);
4145 generateChainExecution(chainWorker, chainBlock, compositionStateValueInChainWorker, contextValueInChainWorker, eventIdValue, chain, trigger,
4146 allChains, chainsImmediatelyDownstream, chainsImmediatelyUpstream, chainsScheduled);
4151 ReturnInst::Create(module->getContext(), chainBlock);
4157 void VuoCompilerBitcodeGenerator::generateChainExecution(Function *
function, BasicBlock *&block,
4158 Value *compositionStateValue, Value *contextValue,
4160 const vector<VuoCompilerChain *> &allChains,
4161 const map<
VuoCompilerChain *, vector<VuoCompilerChain *> > &chainsImmediatelyDownstream,
4162 const map<
VuoCompilerChain *, vector<VuoCompilerChain *> > &chainsImmediatelyUpstream,
4163 set<VuoCompilerChain *> &chainsScheduled)
4165 size_t chainIndex = find(allChains.begin(), allChains.end(), chain) - allChains.begin();
4166 Value *chainIndexValue = ConstantInt::get(eventIdValue->getType(), chainIndex);
4169 vector<VuoCompilerNode *> chainNodes = chain->
getNodes();
4170 for (vector<VuoCompilerNode *>::iterator i = chainNodes.begin(); i != chainNodes.end(); ++i)
4174 Function *nodeExecutionFunction = executionFunctionForNode[node];
4175 if (! nodeExecutionFunction)
4177 nodeExecutionFunction = generateNodeExecutionFunction(module, node);
4178 executionFunctionForNode[node] = nodeExecutionFunction;
4181 Function *nodeTransmissionFunction = transmissionFunctionForNode[node];
4182 if (! nodeTransmissionFunction)
4184 nodeTransmissionFunction = generateNodeTransmissionFunction(module, node);
4185 transmissionFunctionForNode[node] = nodeTransmissionFunction;
4189 vector<Value *> nodeExecutionArgs;
4190 nodeExecutionArgs.push_back(compositionStateValue);
4191 nodeExecutionArgs.push_back(eventIdValue);
4192 nodeExecutionArgs.push_back(chainIndexValue);
4193 CallInst *isHitValue = CallInst::Create(nodeExecutionFunction, nodeExecutionArgs,
"", block);
4198 vector<VuoCompilerNode *> outputNodes = getNodesToWaitOnBeforeTransmission(trigger, node);
4199 generateWaitForNodes(module,
function, block, compositionStateValue, outputNodes, eventIdValue);
4203 vector<Value *> nodeTransmissionArgs;
4204 nodeTransmissionArgs.push_back(compositionStateValue);
4205 nodeTransmissionArgs.push_back(isHitValue);
4206 CallInst::Create(nodeTransmissionFunction, nodeTransmissionArgs,
"", block);
4215 generateSignalForNodes(module, block, compositionStateValue, vector<VuoCompilerNode *>(1, node));
4220 vector<VuoCompilerChain *> downstreamChains;
4221 map<VuoCompilerChain *, vector<VuoCompilerChain *> >::const_iterator downstreamChainsIter = chainsImmediatelyDownstream.find(chain);
4222 if (downstreamChainsIter != chainsImmediatelyDownstream.end())
4223 downstreamChains = downstreamChainsIter->second;
4224 if (! downstreamChains.empty())
4226 vector<size_t> downstreamChainIndices;
4227 for (vector<VuoCompilerChain *>::iterator i = downstreamChains.begin(); i != downstreamChains.end(); ++i)
4228 downstreamChainIndices.push_back( find(allChains.begin(), allChains.end(), *i) - allChains.begin() );
4230 vector<VuoCompilerChain *> nextChains;
4231 for (vector<VuoCompilerChain *>::iterator i = downstreamChains.begin(); i != downstreamChains.end(); ++i)
4234 nextChains.push_back(downstreamChain);
4237 generateAndScheduleChainWorkerFunctions(block, compositionStateValue, contextValue, nextChains, trigger, allChains,
4238 chainsImmediatelyDownstream, chainsImmediatelyUpstream, chainsScheduled);
4290 Function * VuoCompilerBitcodeGenerator::generateNodeExecutionFunction(Module *module,
VuoCompilerNode *node)
4294 Type *boolType = IntegerType::get(module->getContext(), 1);
4296 vector<Type *> params;
4297 params.push_back(pointerToCompositionStateType);
4298 params.push_back(eventIdType);
4299 params.push_back(eventIdType);
4300 FunctionType *functionType = FunctionType::get(boolType, params,
false);
4301 Function *
function = Function::Create(functionType, GlobalValue::InternalLinkage, functionName, module);
4303 Function::arg_iterator args =
function->arg_begin();
4304 Value *compositionStateValue = args++;
4305 compositionStateValue->setName(
"compositionState");
4306 Value *eventIdValue = args++;
4307 eventIdValue->setName(
"eventId");
4308 Value *chainIndexValue = args++;
4309 chainIndexValue->setName(
"chainIndex");
4311 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, NULL);
4312 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, NULL);
4314 Value *nodeContextValue = node->
generateGetContext(module, initialBlock, compositionStateValue);
4319 if (isTopLevelComposition)
4323 BranchInst::Create(finalBlock, initialBlock);
4329 BasicBlock *currBlock = initialBlock;
4338 for (
size_t publishedPortIndex = 0; publishedPortIndex < publishedOutputPorts.size(); ++publishedPortIndex)
4344 if (publishedOutputTriggerNames.find( port->
getClass()->
getName() ) != publishedOutputTriggerNames.end())
4346 BasicBlock *triggerBlock = BasicBlock::Create(module->getContext(),
"trigger",
function, NULL);
4347 BasicBlock *nextBlock = BasicBlock::Create(module->getContext(),
"next",
function, NULL);
4348 BranchInst::Create(triggerBlock, nextBlock, isPortHitValue, currBlock);
4356 vector<Value *> args;
4359 Value *dataValue = eventPort->
generateLoadData(module, triggerBlock, nodeContextValue);
4362 Value *secondArg = NULL;
4363 Value **secondArgIfNeeded = (isLoweredToTwoParameters ? &secondArg : NULL);
4365 secondArgIfNeeded, module, triggerBlock);
4366 args.push_back(arg);
4368 args.push_back(secondArg);
4377 CallInst::Create(triggerFunction, args,
"", triggerBlock);
4378 BranchInst::Create(nextBlock, triggerBlock);
4380 currBlock = nextBlock;
4392 ConstantInt *falseValue = ConstantInt::get(
static_cast<IntegerType *
>(subcompositionFinishedValue->getType()), 0);
4393 ICmpInst *subcompositionFinishedIsTrue =
new ICmpInst(*currBlock, ICmpInst::ICMP_NE, subcompositionFinishedValue, falseValue,
"");
4394 BasicBlock *leaveBlock = BasicBlock::Create(module->getContext(),
"leave",
function, NULL);
4395 BasicBlock *signalBlock = BasicBlock::Create(module->getContext(),
"signal",
function, NULL);
4396 BranchInst::Create(leaveBlock, signalBlock, subcompositionFinishedIsTrue, currBlock);
4402 BranchInst::Create(finalBlock, leaveBlock);
4407 generateSignalForNodes(module, signalBlock, compositionStateValue, vector<VuoCompilerNode *>(1, node));
4408 BranchInst::Create(finalBlock, signalBlock);
4414 BasicBlock *executeBlock = BasicBlock::Create(module->getContext(),
"execute",
function, NULL);
4415 BranchInst::Create(executeBlock, finalBlock, isHitValue, initialBlock);
4426 eventIdValue, compositionStateValue, chainIndexValue,
4427 subcompositionIdentifierValue);
4433 generateNodeExecution(
function, executeBlock, compositionStateValue, node, shouldSendTelemetry);
4434 BranchInst::Create(finalBlock, executeBlock);
4437 ReturnInst::Create(module->getContext(), isHitValue, finalBlock);
4466 Function * VuoCompilerBitcodeGenerator::generateNodeTransmissionFunction(Module *module,
VuoCompilerNode *node)
4470 Type *boolType = IntegerType::get(module->getContext(), 1);
4471 vector<Type *> params;
4472 params.push_back(pointerToCompositionStateType);
4473 params.push_back(boolType);
4474 FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), params,
false);
4475 Function *
function = Function::Create(functionType, GlobalValue::InternalLinkage, functionName, module);
4477 Function::arg_iterator args =
function->arg_begin();
4478 Value *compositionStateValue = args++;
4479 compositionStateValue->setName(
"compositionState");
4480 Value *isHitValue = args++;
4481 isHitValue->setName(
"isHit");
4483 BasicBlock *initialBlock = BasicBlock::Create(module->getContext(),
"initial",
function, NULL);
4484 BasicBlock *transmitBlock = BasicBlock::Create(module->getContext(),
"transmit",
function, NULL);
4485 BasicBlock *finalBlock = BasicBlock::Create(module->getContext(),
"final",
function, NULL);
4488 BranchInst::Create(transmitBlock, finalBlock, isHitValue, initialBlock);
4490 Value *nodeContextValue = node->
generateGetContext(module, transmitBlock, compositionStateValue);
4494 if (isTopLevelComposition)
4495 generateTelemetryFromPublishedOutputNode(
function, transmitBlock, compositionStateValue, nodeContextValue, node);
4500 generateTransmissionFromNode(
function, transmitBlock, compositionStateValue, nodeContextValue, node);
4506 BranchInst::Create(finalBlock, transmitBlock);
4507 ReturnInst::Create(module->getContext(), finalBlock);
4517 this->debugMode = debugMode;