Vuo  2.0.0
VuoCompilerType.cc
Go to the documentation of this file.
1 
10 #include <sstream>
13 #include "VuoCompilerType.hh"
14 #include "VuoType.hh"
15 
16 
20 VuoCompilerType::VuoCompilerType(string typeName, Module *module)
21  : VuoBaseDetail<VuoType>("VuoCompilerType", new VuoType(typeName)),
22  VuoCompilerModule(getBase(), module)
23 {
24  getBase()->setCompiler(this);
25 
26  makeFromJsonFunction = NULL;
27  getJsonFunction = NULL;
28  getInterprocessJsonFunction = NULL;
29  makeFromStringFunction = NULL;
30  getStringFunction = NULL;
31  getInterprocessStringFunction = NULL;
32  getSummaryFunction = NULL;
33  areEqualFunction = NULL;
34  isLessThanFunction = NULL;
35  retainFunction = NULL;
36  releaseFunction = NULL;
37  llvmType = NULL;
38 
39  parse();
40 }
41 
46 VuoCompilerType * VuoCompilerType::newType(string typeName, Module *module)
47 {
48  if (! isType(typeName, module))
49  return NULL;
50 
51  return new VuoCompilerType(typeName, module);
52 }
53 
58 bool VuoCompilerType::isType(string typeName, Module *module)
59 {
60  return (module->getNamedValue(typeName + "_makeFromJson") != NULL);
61 }
62 
66 void VuoCompilerType::parse(void)
67 {
69 
70  string typeName = getBase()->getModuleKey();
71  makeFromJsonFunction = parser->getFunction(typeName + "_makeFromJson");
72  getJsonFunction = parser->getFunction(typeName + "_getJson");
73  getInterprocessJsonFunction = parser->getFunction(typeName + "_getInterprocessJson");
74  getSummaryFunction = parser->getFunction(typeName + "_getSummary");
75  areEqualFunction = parser->getFunction(typeName + "_areEqual");
76  isLessThanFunction = parser->getFunction(typeName + "_isLessThan");
77 
78  if (! makeFromJsonFunction)
79  VUserLog("Error: Couldn't find %s_makeFromJson() function.", typeName.c_str());
80  if (! getJsonFunction)
81  VUserLog("Error: Couldn't find %s_getJson() function.", typeName.c_str());
82  if (! getSummaryFunction)
83  VUserLog("Error: Couldn't find %s_getSummary() function.", typeName.c_str());
84 
85  llvmType = VuoCompilerCodeGenUtilities::getParameterTypeBeforeLowering(getJsonFunction, module, typeName);
86 
87  parseOrGenerateValueFromStringFunction();
88  parseOrGenerateStringFromValueFunction(false);
89  if (getInterprocessJsonFunction)
90  parseOrGenerateStringFromValueFunction(true);
91 
92  parseOrGenerateRetainOrReleaseFunction(true);
93  parseOrGenerateRetainOrReleaseFunction(false);
94 }
95 
99 set<string> VuoCompilerType::globalsToRename(void)
100 {
101  set<string> globals = VuoCompilerModule::globalsToRename();
102  return globals;
103 }
104 
122 void VuoCompilerType::parseOrGenerateValueFromStringFunction(void)
123 {
124  string functionName = (getBase()->getModuleKey() + "_makeFromString").c_str();
125  Function *function = parser->getFunction(functionName);
126 
127  bool isReturnInParam = VuoCompilerCodeGenUtilities::isFunctionReturningStructViaParameter(makeFromJsonFunction);
128 
129  if (! function)
130  {
131  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
132  FunctionType *makeFromJsonFunctionType = makeFromJsonFunction->getFunctionType();
133 
134  Type *returnType = makeFromJsonFunctionType->getReturnType();
135 
136  vector<Type *> functionParams;
137  if (isReturnInParam)
138  functionParams.push_back(makeFromJsonFunctionType->getParamType(0));
139  functionParams.push_back(pointerToCharType);
140 
141  FunctionType *functionType = FunctionType::get(returnType, functionParams, false);
142  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
143 
144  if (isReturnInParam)
145  function->setAttributes(makeFromJsonFunction->getAttributes().getParamAttributes(1));
146  }
147 
148  if (function->isDeclaration())
149  {
150  BasicBlock *block = BasicBlock::Create(module->getContext(), "", function);
151 
152  Function::arg_iterator args = function->arg_begin();
153  Value *result = NULL;
154  if (isReturnInParam)
155  {
156  result = args++;
157  result->setName("result");
158  }
159  Value *str = args++;
160  str->setName("str");
161 
162  Function *jsonTokenerParseFunction = VuoCompilerCodeGenUtilities::getJsonTokenerParseFunction(module);
163  Function *jsonObjectPutFunction = VuoCompilerCodeGenUtilities::getJsonObjectPutFunction(module);
164 
165  CallInst *jsonTokenerParseReturn = CallInst::Create(jsonTokenerParseFunction, str, "", block);
166 
167  vector<Value *> makeFromJsonArgs;
168  if (isReturnInParam)
169  makeFromJsonArgs.push_back(result);
170  makeFromJsonArgs.push_back(jsonTokenerParseReturn);
171  Value *makeFromJsonReturn = CallInst::Create(makeFromJsonFunction, makeFromJsonArgs, "", block);
172 
173  CallInst::Create(jsonObjectPutFunction, jsonTokenerParseReturn, "", block);
174 
175  Value *returnValue = (isReturnInParam ? NULL : makeFromJsonReturn);
176  ReturnInst::Create(module->getContext(), returnValue, block);
177  }
178 
179  makeFromStringFunction = function;
180 }
181 
200 void VuoCompilerType::parseOrGenerateStringFromValueFunction(bool isInterprocess)
201 {
202  string functionName = (getBase()->getModuleKey() + (isInterprocess ? "_getInterprocessString" : "_getString")).c_str();
203  Function *function = parser->getFunction(functionName);
204 
205  Function *chosenJsonFromValueFunction = (isInterprocess ? getInterprocessJsonFunction : getJsonFunction);
206 
207  if (! function)
208  {
209  PointerType *pointerToCharType = PointerType::get(IntegerType::get(module->getContext(), 8), 0);
210  FunctionType *getJsonFunctionType = chosenJsonFromValueFunction->getFunctionType();
211 
212  Type *returnType = pointerToCharType;
213 
214  vector<Type *> functionParams;
215  for (int i = 0; i < getJsonFunctionType->getNumParams(); ++i)
216  functionParams.push_back(getJsonFunctionType->getParamType(i));
217 
218  FunctionType *functionType = FunctionType::get(returnType, functionParams, false);
219  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
220 
221  AttributeSet paramAttributeSet = chosenJsonFromValueFunction->getAttributes().getParamAttributes(1);
222  for (int i = 0; i < getJsonFunctionType->getNumParams(); ++i)
223  function->addAttributes(i+1, VuoCompilerCodeGenUtilities::copyAttributesToIndex(paramAttributeSet, i+1));
224  }
225 
226  if (function->isDeclaration())
227  {
228  BasicBlock *block = BasicBlock::Create(module->getContext(), "", function);
229 
230  int argIndex = 0;
231  for (Function::arg_iterator args = function->arg_begin(); args != function->arg_end(); ++args, ++argIndex)
232  {
233  Value *value = args;
234  ostringstream argName;
235  argName << "value" << argIndex;
236  value->setName(argName.str().c_str());
237  }
238 
239  Function *jsonObjectToJsonStringExtFunction = VuoCompilerCodeGenUtilities::getJsonObjectToJsonStringExtFunction(module);
240  Function *strdupFunction = VuoCompilerCodeGenUtilities::getStrdupFunction(module);
241  Function *jsonObjectPutFunction = VuoCompilerCodeGenUtilities::getJsonObjectPutFunction(module);
242 
243  vector<Value *> getJsonArgs;
244  for (Function::arg_iterator args = function->arg_begin(); args != function->arg_end(); ++args)
245  {
246  Value *value = args;
247  getJsonArgs.push_back(value);
248  }
249  CallInst *getJsonReturn = CallInst::Create(chosenJsonFromValueFunction, getJsonArgs, "", block);
250 
251  vector<Value *> jsonObjectToJsonStringExtArgs;
252  jsonObjectToJsonStringExtArgs.push_back(getJsonReturn);
253  jsonObjectToJsonStringExtArgs.push_back(ConstantInt::get(module->getContext(), APInt(32, JSON_C_TO_STRING_PLAIN)));
254  CallInst *jsonObjectToJsonStringExtReturn = CallInst::Create(jsonObjectToJsonStringExtFunction, jsonObjectToJsonStringExtArgs, "", block);
255 
256  CallInst *strdupReturn = CallInst::Create(strdupFunction, jsonObjectToJsonStringExtReturn, "", block);
257 
258  CallInst::Create(jsonObjectPutFunction, getJsonReturn, "", block);
259 
260  ReturnInst::Create(module->getContext(), strdupReturn, block);
261  }
262 
263  if (isInterprocess)
264  getInterprocessStringFunction = function;
265  else
266  getStringFunction = function;
267 }
268 
285 void VuoCompilerType::parseOrGenerateRetainOrReleaseFunction(bool isRetain)
286 {
287  string functionName = (getBase()->getModuleKey() + (isRetain ? "_retain" : "_release")).c_str();
288  Function *function = parser->getFunction(functionName);
289 
290  if (! function)
291  {
292  Type *secondParamType = NULL;
293  Type *firstParamType = getFunctionParameterType(&secondParamType);
294  vector<Type *> functionParams;
295  functionParams.push_back(firstParamType);
296  if (secondParamType)
297  functionParams.push_back(secondParamType);
298  FunctionType *functionType = FunctionType::get(Type::getVoidTy(module->getContext()), functionParams, false);
299  function = Function::Create(functionType, GlobalValue::ExternalLinkage, functionName, module);
300  function->setAttributes(getFunctionParameterAttributes());
301  }
302 
303  if (function->isDeclaration())
304  {
305  BasicBlock *block = BasicBlock::Create(module->getContext(), "", function);
306 
307  Function::arg_iterator args = function->arg_begin();
308  Value *arg = args++;
309  arg->setName("value");
310 
311  arg = VuoCompilerCodeGenUtilities::generateTypeCast(module, block, arg, llvmType);
312 
313  if (isRetain)
315  else
317 
318  ReturnInst::Create(module->getContext(), block);
319  }
320 
321  if (isRetain)
322  retainFunction = function;
323  else
324  releaseFunction = function;
325 }
326 
335 Value * VuoCompilerType::generateValueFromStringFunctionCall(Module *module, BasicBlock *block, Value *arg)
336 {
337  Function *function = declareFunctionInModule(module, makeFromStringFunction);
338 
340  {
341  vector<Value *> functionArgs;
342  functionArgs.push_back(arg);
343  Value *returnVariable = VuoCompilerCodeGenUtilities::callFunctionWithStructReturn(function, functionArgs, block);
344 
345  // Fix return type to match llvmType.
346  returnVariable = new BitCastInst(returnVariable, PointerType::get(llvmType, 0), "", block);
347 
348  return new LoadInst(returnVariable, "", false, block);
349  }
350  else
351  {
352  Value *returnValue = CallInst::Create(function, arg, "", block);
353  return VuoCompilerCodeGenUtilities::generateTypeCast(module, block, returnValue, llvmType);
354  }
355 }
356 
365 Value * VuoCompilerType::generateStringFromValueFunctionCall(Module *module, BasicBlock *block, Value *arg)
366 {
367  return generateFunctionCallWithTypeParameter(module, block, arg, getStringFunction);
368 }
369 
378 Value * VuoCompilerType::generateInterprocessStringFromValueFunctionCall(Module *module, BasicBlock *block, Value *arg)
379 {
380  if (getInterprocessStringFunction)
381  return generateFunctionCallWithTypeParameter(module, block, arg, getInterprocessStringFunction);
382  else
383  return generateStringFromValueFunctionCall(module, block, arg);
384 }
385 
394 Value * VuoCompilerType::generateSummaryFromValueFunctionCall(Module *module, BasicBlock *block, Value *arg)
395 {
396  return generateFunctionCallWithTypeParameter(module, block, arg, getSummaryFunction);
397 }
398 
402 void VuoCompilerType::generateRetainCall(Module *module, BasicBlock *block, Value *arg)
403 {
405  generateFunctionCallWithTypeParameter(module, block, arg, retainFunction);
406 }
407 
411 void VuoCompilerType::generateReleaseCall(Module *module, BasicBlock *block, Value *arg)
412 {
414  generateFunctionCallWithTypeParameter(module, block, arg, releaseFunction);
415 }
416 
420 Value * VuoCompilerType::generateFunctionCallWithTypeParameter(Module *module, BasicBlock *block, Value *arg, Function *sourceFunction)
421 {
422  Function *function = declareFunctionInModule(module, sourceFunction);
423 
424  Value *secondArgument = NULL;
425  Value **secondArgumentIfNeeded = (function->getFunctionType()->getNumParams() == 2 ? &secondArgument : NULL);
426  arg = VuoCompilerCodeGenUtilities::convertArgumentToParameterType(arg, function, 0, secondArgumentIfNeeded, module, block);
427 
428  vector<Value *> args;
429  args.push_back(arg);
430  if (secondArgument)
431  args.push_back(secondArgument);
432  return CallInst::Create(function, args, "", block);
433 }
434 
439 {
440  return llvmType;
441 }
442 
449 {
450  *secondType = (getJsonFunction->getFunctionType()->getNumParams() == 2 ? getJsonFunction->getFunctionType()->getParamType(1) : NULL);
451  return getJsonFunction->getFunctionType()->getParamType(0);
452 }
453 
460 {
461  return getJsonFunction->getAttributes().getParamAttributes(1);
462 }
463 
468 {
469  if (! type)
470  return false;
471 
472  return VuoType::isListTypeName(type->getBase()->getModuleKey());
473 }
474 
479 {
480  return getInterprocessStringFunction != NULL;
481 }
482 
487 {
488  return areEqualFunction != NULL && isLessThanFunction != NULL;
489 }