Vuo  2.3.1
VuoCompilerTriggerPort.cc
Go to the documentation of this file.
1 
13 #include "VuoCompilerType.hh"
14 #include "VuoPort.hh"
15 #include "VuoType.hh"
16 
21  : VuoCompilerPort(basePort)
22 {
23 }
24 
30 Value * VuoCompilerTriggerPort::generateCreatePortContext(Module *module, BasicBlock *block)
31 {
32  VuoType *dataType = getClass()->getDataVuoType();
33 
35  dataType ? dataType->getCompiler() : nullptr,
36  true, "org.vuo.composition." + getIdentifier());
37 }
38 
46 void VuoCompilerTriggerPort::generateScheduleWorker(Module *module, Function *function, BasicBlock *block,
47  Value *compositionStateValue, Value *eventIdValue,
48  Value *portContextValue, VuoType *dataType,
49  int minThreadsNeeded, int maxThreadsNeeded, int chainCount,
50  Function *workerFunction)
51 {
52  PointerType *voidPointer = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
53 
54  Value *dataCopyAsVoidPointer;
55  if (dataType)
56  {
57  // Create a copy of the data on the heap.
58  Value *dataPointer = dataType->getCompiler()->convertArgsToPortData(module, block, function, 0);
59  size_t byteCount = dataType->getCompiler()->getSize(module);
60  dataCopyAsVoidPointer = VuoCompilerCodeGenUtilities::generateMemoryAllocation(module, block, byteCount);
61  VuoCompilerCodeGenUtilities::generateMemoryCopy(module, block, dataPointer, dataCopyAsVoidPointer, byteCount);
62 
63  dataType->getCompiler()->generateRetainCall(module, block, dataCopyAsVoidPointer);
64  }
65  else
66  dataCopyAsVoidPointer = ConstantPointerNull::get(voidPointer);
67 
68  // Create a copy of the event ID on the heap.
69  Type *eventIdType = VuoCompilerCodeGenUtilities::generateNoEventIdConstant(module)->getType();
70  Value *eventIdCopyAddress = VuoCompilerCodeGenUtilities::generateMemoryAllocation(module, block, eventIdType, 1);
71  new StoreInst(eventIdValue, eventIdCopyAddress, false, block);
72 
73  Value *contextValue = VuoCompilerCodeGenUtilities::generateCreateTriggerWorkerContext(module, block, compositionStateValue,
74  dataCopyAsVoidPointer, eventIdCopyAddress);
75 
76  Value *dispatchQueueValue = VuoCompilerCodeGenUtilities::generateGetPortContextTriggerQueue(module, block, portContextValue);
77 
78  VuoCompilerCodeGenUtilities::generateScheduleTriggerWorker(module, block, dispatchQueueValue, contextValue, workerFunction,
79  minThreadsNeeded, maxThreadsNeeded,
80  eventIdValue, compositionStateValue, chainCount);
81 }
82 
87 Function * VuoCompilerTriggerPort::generateSynchronousSubmissionToDispatchQueue(Module *module, BasicBlock *block, Value *nodeContextValue,
88  string workerFunctionName, Value *workerFunctionArg)
89 {
90  Function *workerFunction = getWorkerFunction(module, workerFunctionName);
91 
92  PointerType *voidPointer = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
93  Value *argAsVoidPointer;
94  if (workerFunctionArg)
95  argAsVoidPointer = new BitCastInst(workerFunctionArg, voidPointer, "", block);
96  else
97  argAsVoidPointer = ConstantPointerNull::get(voidPointer);
98 
99  Value *portContextValue = generateGetPortContext(module, block, nodeContextValue);
100  Value *dispatchQueueValue = VuoCompilerCodeGenUtilities::generateGetPortContextTriggerQueue(module, block, portContextValue);
101  VuoCompilerCodeGenUtilities::generateSynchronousSubmissionToDispatchQueue(module, block, dispatchQueueValue, workerFunction, argAsVoidPointer);
102 
103  return workerFunction;
104 }
105 
109 Function * VuoCompilerTriggerPort::getWorkerFunction(Module *module, string functionName, bool isExternal)
110 {
111  PointerType *voidPointer = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
112 
113  vector<Type *> workerFunctionParams;
114  workerFunctionParams.push_back(voidPointer);
115  FunctionType *workerFunctionType = FunctionType::get(Type::getVoidTy(module->getContext()),
116  workerFunctionParams,
117  false);
118 
119  Function *workerFunction = module->getFunction(functionName);
120  if (! workerFunction) {
121  workerFunction = Function::Create(workerFunctionType,
122  isExternal ? GlobalValue::ExternalLinkage : GlobalValue::InternalLinkage,
123  functionName,
124  module);
125  }
126 
127  return workerFunction;
128 }
129 
134 Value * VuoCompilerTriggerPort::generateNonBlockingWaitForSemaphore(Module *module, BasicBlock *block, Value *portContextValue)
135 {
136  ConstantInt *timeoutDeltaValue = ConstantInt::get(module->getContext(), APInt(64, 0));
137  Value *timeoutValue = VuoCompilerCodeGenUtilities::generateCreateDispatchTime(module, block, timeoutDeltaValue);
138  Value *dispatchSemaphoreValue = VuoCompilerCodeGenUtilities::generateGetPortContextTriggerSemaphore(module, block, portContextValue);
139  return VuoCompilerCodeGenUtilities::generateWaitForSemaphore(module, block, dispatchSemaphoreValue, timeoutValue);
140 }
141 
145 void VuoCompilerTriggerPort::generateSignalForSemaphore(Module *module, BasicBlock *block, Value *nodeContextValue)
146 {
147  Value *portContextValue = generateGetPortContext(module, block, nodeContextValue);
148  Value *dispatchSemaphoreValue = VuoCompilerCodeGenUtilities::generateGetPortContextTriggerSemaphore(module, block, portContextValue);
149  VuoCompilerCodeGenUtilities::generateSignalForSemaphore(module, block, dispatchSemaphoreValue);
150 }
151 
155 Value * VuoCompilerTriggerPort::generateLoadFunction(Module *module, BasicBlock *block, Value *nodeContextValue)
156 {
157  Value *portContextValue = generateGetPortContext(module, block, nodeContextValue);
158  return VuoCompilerCodeGenUtilities::generateGetPortContextTriggerFunction(module, block, portContextValue, getClass()->getFunctionType(module));
159 }
160 
164 void VuoCompilerTriggerPort::generateStoreFunction(Module *module, BasicBlock *block, Value *nodeContextValue, Value *functionValue)
165 {
166  Value *portContextValue = generateGetPortContext(module, block, nodeContextValue);
167  VuoCompilerCodeGenUtilities::generateSetPortContextTriggerFunction(module, block, portContextValue, functionValue);
168 }
169 
173 Value * VuoCompilerTriggerPort::generateRetrievePreviousData(Module *module, BasicBlock *block, Value *nodeContextValue)
174 {
175  Value *portContextValue = generateGetPortContext(module, block, nodeContextValue);
176  return VuoCompilerCodeGenUtilities::generateGetPortContextDataVariable(module, block, portContextValue, getClass()->getDataVuoType()->getCompiler());
177 }
178 
183 void VuoCompilerTriggerPort::generateFreeContext(Module *module, BasicBlock *block, Function *workerFunction)
184 {
185  Value *contextValue = workerFunction->arg_begin();
187 }
188 
193 Value * VuoCompilerTriggerPort::generateCompositionStateValue(Module *module, BasicBlock *block, Function *workerFunction)
194 {
195  // VuoCompositionState *compositionState = (VuoCompositionState *)((void **)context)[0];
196 
197  Value *contextValue = workerFunction->arg_begin();
198  Type *voidPointerType = contextValue->getType();
199  Type *voidPointerPointerType = PointerType::get(voidPointerType, 0);
200  Type *compositionStatePointerType = PointerType::get(VuoCompilerCodeGenUtilities::getCompositionStateType(module), 0);
201 
202  Value *contextValueAsVoidPointerArray = new BitCastInst(contextValue, voidPointerPointerType, "", block);
203  Value *compositionStateAsVoidPointer = VuoCompilerCodeGenUtilities::generateGetArrayElement(module, block, contextValueAsVoidPointerArray, (size_t)0);
204  return new BitCastInst(compositionStateAsVoidPointer, compositionStatePointerType, "", block);
205 }
206 
211 Value * VuoCompilerTriggerPort::generateDataValue(Module *module, BasicBlock *block, Function *workerFunction)
212 {
213  // PortDataType *dataCopy = (PortDataType *)((void **)context)[1]);
214  // PortDataType data = *dataCopy;
215 
216  Value *contextValue = workerFunction->arg_begin();
217  Type *voidPointerType = contextValue->getType();
218  Type *voidPointerPointerType = PointerType::get(voidPointerType, 0);
219 
220  Value *contextValueAsVoidPointerArray = new BitCastInst(contextValue, voidPointerPointerType, "", block);
221  return VuoCompilerCodeGenUtilities::generateGetArrayElement(module, block, contextValueAsVoidPointerArray, 1);
222 }
223 
228 Value * VuoCompilerTriggerPort::generateEventIdValue(Module *module, BasicBlock *block, Function *workerFunction)
229 {
230  // unsigned long *eventIdCopy = (unsigned long *)((void **)context)[2];
231  // unsigned long eventId = *eventIdCopy;
232 
233  Value *contextValue = workerFunction->arg_begin();
234  Type *voidPointerType = contextValue->getType();
235  Type *voidPointerPointerType = PointerType::get(voidPointerType, 0);
236  Type *eventIdType = VuoCompilerCodeGenUtilities::generateNoEventIdConstant(module)->getType();
237 
238  Value *contextValueAsVoidPointerArray = new BitCastInst(contextValue, voidPointerPointerType, "", block);
239  Value *eventIdCopyAsVoidPointer = VuoCompilerCodeGenUtilities::generateGetArrayElement(module, block, contextValueAsVoidPointerArray, 2);
240  PointerType *pointerToEventIdType = PointerType::get(eventIdType, 0);
241  Value *eventIdCopyValue = new BitCastInst(eventIdCopyAsVoidPointer, pointerToEventIdType, "", block);
242  return new LoadInst(eventIdCopyValue, "", block);
243 }
244 
250 Value * VuoCompilerTriggerPort::generateDataValueUpdate(Module *module, BasicBlock *block, Function *workerFunction, Value *nodeContextValue)
251 {
252  Value *currentDataValue = NULL;
253  VuoType *dataType = getClass()->getDataVuoType();
254 
255  if (dataType)
256  {
257  // Load the previous data.
258  Value *previousDataPointer = generateRetrievePreviousData(module, block, nodeContextValue);
259 
260  // Load the current data.
261  Value *currentDataVoidPointer = generateDataValue(module, block, workerFunction);
262  Value *currentDataPointer = dataType->getCompiler()->convertToPortData(block, currentDataVoidPointer);
263  currentDataValue = new LoadInst(currentDataPointer, "", block);
264 
265  // The current data becomes the previous data.
266  dataType->getCompiler()->generateReleaseCall(module, block, previousDataPointer);
267  Value *portContextValue = generateGetPortContext(module, block, nodeContextValue);
268  VuoCompilerCodeGenUtilities::generateSetPortContextData(module, block, portContextValue, currentDataValue, dataType->getCompiler());
269  }
270 
271  return currentDataValue;
272 }
273 
277 void VuoCompilerTriggerPort::generateDataValueDiscardFromScheduler(Module *module, Function *function, BasicBlock *block,
278  VuoType *dataType)
279 {
280  Value *dataPointer = dataType->getCompiler()->convertArgsToPortData(module, block, function, 0);
281  dataType->getCompiler()->generateRetainCall(module, block, dataPointer);
282  dataType->getCompiler()->generateReleaseCall(module, block, dataPointer);
283 }
284 
288 void VuoCompilerTriggerPort::generateDataValueDiscardFromWorker(Module *module, BasicBlock *block, Function *workerFunction)
289 {
290  VuoType *dataType = getClass()->getDataVuoType();
291 
292  if (dataType)
293  {
294  Value *dataValue = generateDataValue(module, block, workerFunction);
295  dataValue = dataType->getCompiler()->convertToPortData(block, dataValue);
296  dataType->getCompiler()->generateReleaseCall(module, block, dataValue);
297  }
298 }
299 
304 {
306 }