Vuo  2.0.0
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()->getType() : NULL,
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  // PortDataType_retain(data);
58  // PortDataType *dataCopy = (void *)malloc(sizeof(VuoImage));
59  // *dataCopy = data;
60  Value *dataValue = VuoCompilerCodeGenUtilities::unlowerArgument(dataType->getCompiler(), function, 0, module, block);
61  dataType->getCompiler()->generateRetainCall(module, block, dataValue);
62  ConstantInt *oneValue = ConstantInt::get(module->getContext(), APInt(64, 1));
63  Value *dataCopyAddress = VuoCompilerCodeGenUtilities::generateMemoryAllocation(module, block, dataType->getCompiler()->getType(), oneValue);
64  new StoreInst(dataValue, dataCopyAddress, false, block);
65  dataCopyAsVoidPointer = new BitCastInst(dataCopyAddress, voidPointer, "", block);
66  }
67  else
68  {
69  dataCopyAsVoidPointer = ConstantPointerNull::get(voidPointer);
70  }
71 
72  // unsigned long *eventIdCopy = (unsigned long *)malloc(sizeof(unsigned long));
73  // *eventIdCopy = eventId;
74  Type *eventIdType = VuoCompilerCodeGenUtilities::generateNoEventIdConstant(module)->getType();
75  Value *eventIdCopyAddress = VuoCompilerCodeGenUtilities::generateMemoryAllocation(module, block, eventIdType, 1);
76  new StoreInst(eventIdValue, eventIdCopyAddress, false, block);
77 
78  Value *contextValue = VuoCompilerCodeGenUtilities::generateCreateTriggerWorkerContext(module, block, compositionStateValue,
79  dataCopyAsVoidPointer, eventIdCopyAddress);
80 
81  Value *dispatchQueueValue = VuoCompilerCodeGenUtilities::generateGetPortContextTriggerQueue(module, block, portContextValue);
82 
83  VuoCompilerCodeGenUtilities::generateScheduleTriggerWorker(module, block, dispatchQueueValue, contextValue, workerFunction,
84  minThreadsNeeded, maxThreadsNeeded,
85  eventIdValue, compositionStateValue, chainCount);
86 }
87 
92 Function * VuoCompilerTriggerPort::generateSynchronousSubmissionToDispatchQueue(Module *module, BasicBlock *block, Value *nodeContextValue,
93  string workerFunctionName, Value *workerFunctionArg)
94 {
95  Function *workerFunction = getWorkerFunction(module, workerFunctionName);
96 
97  PointerType *voidPointer = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
98  Value *argAsVoidPointer;
99  if (workerFunctionArg)
100  argAsVoidPointer = new BitCastInst(workerFunctionArg, voidPointer, "", block);
101  else
102  argAsVoidPointer = ConstantPointerNull::get(voidPointer);
103 
104  Value *portContextValue = generateGetPortContext(module, block, nodeContextValue);
105  Value *dispatchQueueValue = VuoCompilerCodeGenUtilities::generateGetPortContextTriggerQueue(module, block, portContextValue);
106  VuoCompilerCodeGenUtilities::generateSynchronousSubmissionToDispatchQueue(module, block, dispatchQueueValue, workerFunction, argAsVoidPointer);
107 
108  return workerFunction;
109 }
110 
114 Function * VuoCompilerTriggerPort::getWorkerFunction(Module *module, string functionName, bool isExternal)
115 {
116  PointerType *voidPointer = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
117 
118  vector<Type *> workerFunctionParams;
119  workerFunctionParams.push_back(voidPointer);
120  FunctionType *workerFunctionType = FunctionType::get(Type::getVoidTy(module->getContext()),
121  workerFunctionParams,
122  false);
123 
124  Function *workerFunction = module->getFunction(functionName);
125  if (! workerFunction) {
126  workerFunction = Function::Create(workerFunctionType,
127  isExternal ? GlobalValue::ExternalLinkage : GlobalValue::InternalLinkage,
128  functionName,
129  module);
130  }
131 
132  return workerFunction;
133 }
134 
139 Value * VuoCompilerTriggerPort::generateNonBlockingWaitForSemaphore(Module *module, BasicBlock *block, Value *portContextValue)
140 {
141  ConstantInt *timeoutDeltaValue = ConstantInt::get(module->getContext(), APInt(64, 0));
142  Value *timeoutValue = VuoCompilerCodeGenUtilities::generateCreateDispatchTime(module, block, timeoutDeltaValue);
143  Value *dispatchSemaphoreValue = VuoCompilerCodeGenUtilities::generateGetPortContextTriggerSemaphore(module, block, portContextValue);
144  return VuoCompilerCodeGenUtilities::generateWaitForSemaphore(module, block, dispatchSemaphoreValue, timeoutValue);
145 }
146 
150 void VuoCompilerTriggerPort::generateSignalForSemaphore(Module *module, BasicBlock *block, Value *nodeContextValue)
151 {
152  Value *portContextValue = generateGetPortContext(module, block, nodeContextValue);
153  Value *dispatchSemaphoreValue = VuoCompilerCodeGenUtilities::generateGetPortContextTriggerSemaphore(module, block, portContextValue);
154  VuoCompilerCodeGenUtilities::generateSignalForSemaphore(module, block, dispatchSemaphoreValue);
155 }
156 
160 Value * VuoCompilerTriggerPort::generateLoadFunction(Module *module, BasicBlock *block, Value *nodeContextValue)
161 {
162  Value *portContextValue = generateGetPortContext(module, block, nodeContextValue);
163  return VuoCompilerCodeGenUtilities::generateGetPortContextTriggerFunction(module, block, portContextValue, getClass()->getFunctionType());
164 }
165 
169 void VuoCompilerTriggerPort::generateStoreFunction(Module *module, BasicBlock *block, Value *nodeContextValue, Value *functionValue)
170 {
171  Value *portContextValue = generateGetPortContext(module, block, nodeContextValue);
172  VuoCompilerCodeGenUtilities::generateSetPortContextTriggerFunction(module, block, portContextValue, functionValue);
173 }
174 
178 Value * VuoCompilerTriggerPort::generateLoadPreviousData(Module *module, BasicBlock *block, Value *nodeContextValue)
179 {
180  Value *portContextValue = generateGetPortContext(module, block, nodeContextValue);
181  return VuoCompilerCodeGenUtilities::generateGetPortContextData(module, block, portContextValue, getDataType());
182 }
183 
188 void VuoCompilerTriggerPort::generateFreeContext(Module *module, BasicBlock *block, Function *workerFunction)
189 {
190  Value *contextValue = workerFunction->arg_begin();
192 }
193 
198 Value * VuoCompilerTriggerPort::generateCompositionStateValue(Module *module, BasicBlock *block, Function *workerFunction)
199 {
200  // VuoCompositionState *compositionState = (VuoCompositionState *)((void **)context)[0];
201 
202  Value *contextValue = workerFunction->arg_begin();
203  Type *voidPointerType = contextValue->getType();
204  Type *voidPointerPointerType = PointerType::get(voidPointerType, 0);
205  Type *compositionStatePointerType = PointerType::get(VuoCompilerCodeGenUtilities::getCompositionStateType(module), 0);
206 
207  Value *contextValueAsVoidPointerArray = new BitCastInst(contextValue, voidPointerPointerType, "", block);
208  Value *compositionStateAsVoidPointer = VuoCompilerCodeGenUtilities::generateGetArrayElement(module, block, contextValueAsVoidPointerArray, (size_t)0);
209  return new BitCastInst(compositionStateAsVoidPointer, compositionStatePointerType, "", block);
210 }
211 
216 Value * VuoCompilerTriggerPort::generateDataValue(Module *module, BasicBlock *block, Function *workerFunction)
217 {
218  // PortDataType *dataCopy = (PortDataType *)((void **)context)[1]);
219  // PortDataType data = *dataCopy;
220 
221  Value *contextValue = workerFunction->arg_begin();
222  Type *voidPointerType = contextValue->getType();
223  Type *voidPointerPointerType = PointerType::get(voidPointerType, 0);
224 
225  Value *contextValueAsVoidPointerArray = new BitCastInst(contextValue, voidPointerPointerType, "", block);
226  Value *dataCopyAsVoidPointer = VuoCompilerCodeGenUtilities::generateGetArrayElement(module, block, contextValueAsVoidPointerArray, 1);
227  PointerType *pointerToDataType = PointerType::get(getDataType(), 0);
228  Value *dataCopyValue = new BitCastInst(dataCopyAsVoidPointer, pointerToDataType, "", block);
229  return new LoadInst(dataCopyValue, "", block);
230 }
231 
236 Value * VuoCompilerTriggerPort::generateEventIdValue(Module *module, BasicBlock *block, Function *workerFunction)
237 {
238  // unsigned long *eventIdCopy = (unsigned long *)((void **)context)[2];
239  // unsigned long eventId = *eventIdCopy;
240 
241  Value *contextValue = workerFunction->arg_begin();
242  Type *voidPointerType = contextValue->getType();
243  Type *voidPointerPointerType = PointerType::get(voidPointerType, 0);
244  Type *eventIdType = VuoCompilerCodeGenUtilities::generateNoEventIdConstant(module)->getType();
245 
246  Value *contextValueAsVoidPointerArray = new BitCastInst(contextValue, voidPointerPointerType, "", block);
247  Value *eventIdCopyAsVoidPointer = VuoCompilerCodeGenUtilities::generateGetArrayElement(module, block, contextValueAsVoidPointerArray, 2);
248  PointerType *pointerToEventIdType = PointerType::get(eventIdType, 0);
249  Value *eventIdCopyValue = new BitCastInst(eventIdCopyAsVoidPointer, pointerToEventIdType, "", block);
250  return new LoadInst(eventIdCopyValue, "", block);
251 }
252 
258 Value * VuoCompilerTriggerPort::generateDataValueUpdate(Module *module, BasicBlock *block, Function *workerFunction, Value *nodeContextValue)
259 {
260  Value *currentDataValue = NULL;
261  Type *dataType = getDataType();
262 
263  if (dataType)
264  {
265  // Load the previous data.
266  Value *portContextValue = generateGetPortContext(module, block, nodeContextValue);
267  Value *previousDataValue = VuoCompilerCodeGenUtilities::generateGetPortContextData(module, block, portContextValue, dataType);
268 
269  // Load the current data.
270  //
271  // PortDataType *dataCopy = (PortDataType *)((void **)context)[1]);
272  // PortDataType data = *dataCopy;
273  currentDataValue = generateDataValue(module, block, workerFunction);
274 
275  // The current data becomes the previous data.
276  //
277  // PortDataType_release(previousData);
278  // previousData = data;
279  VuoCompilerCodeGenUtilities::generateSetPortContextData(module, block, portContextValue, currentDataValue);
281  type->generateReleaseCall(module, block, previousDataValue);
282  }
283 
284  return currentDataValue;
285 }
286 
290 void VuoCompilerTriggerPort::generateDataValueDiscardFromScheduler(Module *module, Function *function, BasicBlock *block,
291  VuoType *dataType)
292 {
293  Value *dataValue = VuoCompilerCodeGenUtilities::unlowerArgument(dataType->getCompiler(), function, 0, module, block);
294  dataType->getCompiler()->generateRetainCall(module, block, dataValue);
295  dataType->getCompiler()->generateReleaseCall(module, block, dataValue);
296 }
297 
301 void VuoCompilerTriggerPort::generateDataValueDiscardFromWorker(Module *module, BasicBlock *block, Function *workerFunction)
302 {
303  VuoType *dataType = getClass()->getDataVuoType();
304 
305  if (dataType)
306  {
307  Value *dataValue = generateDataValue(module, block, workerFunction);
308  dataType->getCompiler()->generateReleaseCall(module, block, dataValue);
309  }
310 }
311 
316 {
317  VuoType *vuoType = getClass()->getDataVuoType();
318  return (vuoType == NULL ? NULL : vuoType->getCompiler()->getType());
319 }
320 
325 {
327 }