PageRenderTime 62ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/oink/xml_value_writer.cc

http://github.com/dsw/oink-stack
C++ | 456 lines | 247 code | 72 blank | 137 comment | 37 complexity | 3cca9990790ba2b714c659028da15fb4 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0, LGPL-2.1
  1. // see License.txt for copyright and terms of use
  2. #include "xml_value_writer.h" // this module
  3. #include "xml_enum.h" // XTOK_*
  4. #include "oink_util.h" // USER_ERROR
  5. #include "stringset.h" // StringSet
  6. #define serializeOracle (dynamic_cast<XVW_SerializeOracle*> (serializeOracle_m))
  7. // NOTE: This does not go here because it is overridden depending on
  8. // whether we are doing an oink analysis (for which we cannot mention
  9. // qvars) or a qual analysis.
  10. // static inline bool shouldSerialize(Value const *value) {return value;}
  11. XmlValueWriter::XmlValueWriter
  12. (IdentityManager &idmgr0,
  13. // VarPredicateFunc *varPred0, ValuePredicateFunc *valuePred0,
  14. ASTVisitor *astVisitor0, ValueVisitor *valueVisitor0,
  15. std::ostream *out0, int &depth0, bool indent0,
  16. XVW_SerializeOracle *serializeOracle0)
  17. : XmlTypeWriter(idmgr0, astVisitor0, out0, depth0, indent0, serializeOracle0)
  18. // , varPred(varPred0)
  19. // , valuePred(valuePred0)
  20. , valueVisitor(valueVisitor0)
  21. {}
  22. char const * const XmlValueWriter::tagName_Value(Value *v) {
  23. switch(v->getTag()) {
  24. default: xfailure("illegal tag");
  25. case Value::V_ATOMIC: return "CVAtomicValue";
  26. case Value::V_POINTER: return "PointerValue";
  27. case Value::V_REFERENCE: return "ReferenceValue";
  28. case Value::V_FUNCTION: return "FunctionValue";
  29. case Value::V_ARRAY: return "ArrayValue";
  30. case Value::V_POINTERTOMEMBER: return "PointerToMemberValue";
  31. }
  32. }
  33. void XmlValueWriter::toXml(Value *v) {
  34. // bool printedRepr;
  35. // if (v->isCVAtomicValue()) {
  36. // printedRepr = idmgr.printed0(v->asCVAtomicValue());
  37. // }
  38. // idempotency
  39. if (idmgr.printed(v)) return;
  40. // visiting
  41. if (valueVisitor) {
  42. if (!valueVisitor->preVisitValue(v)) return;
  43. }
  44. // manual virtual dispatch
  45. switch(v->getTag()) {
  46. default: xfailure("illegal tag");
  47. case Value::V_ATOMIC: {
  48. CVAtomicValue *atom = v->asCVAtomicValue();
  49. // CVAtomicValue *repr_value = atom->find();
  50. BucketOValues *reprBucket = atom->getBucket();
  51. bool printedReprBucket = idmgr.printed0(reprBucket);
  52. // xassert(printedRepr == printedReprBucket);
  53. // CVAtomicValue *orig_ufLink = atom->ufLink;
  54. if (! printedReprBucket) {
  55. // quarl 2006-05-20
  56. // This is the first time we are printing a CVAtomicValue within this
  57. // equivalence class. Thus we make this value the representative of
  58. // this class. This is necessary, because otherwise the
  59. // representative and its bucket might not get printed due to
  60. // shouldSerialize() being false for that object. (The lack of this
  61. // call is why instance sensitivity serialization wasn't working until
  62. // now!)
  63. atom->makeRepresentative();
  64. }
  65. // We are about to print atom->ufLink; make sure the path is already
  66. // compressed so that ufLink is either NULL, or points at the
  67. // representative.
  68. xassert(atom->ufLinkForEquivRelOfDomOfMapToBucket == NULL ||
  69. atom->ufLinkForEquivRelOfDomOfMapToBucket
  70. ->ufLinkForEquivRelOfDomOfMapToBucket == NULL);
  71. if (atom->bucket != NULL) xassert(atom->bucket->isEnabled());
  72. XmlTagPrinter tagPrinter(*this);
  73. if (writingP()) {
  74. tagPrinter.printOpenTag(tagName_Value(atom), atom);
  75. // **** attributes
  76. // * superclasses
  77. toXml_Value_properties(atom);
  78. // * members
  79. printPtr(atom, type);
  80. printPtr(atom, atVoid);
  81. // fprintf(stderr, "## toXml(v=%p): "
  82. // "printedReprBucket=%d, "
  83. // "orig_ufLink=%p, "
  84. // "ufLink=%p, bucket=%p\n",
  85. // v,
  86. // printedReprBucket,
  87. // orig_ufLink,
  88. // atom->ufLink, atom->bucket);
  89. // quarl 2006-05-20
  90. // Since we've permuted the ufLinks above, ufLink should definitely
  91. // point to something within the serialized tree, and that node's
  92. // bucket gets printed. Thus we can print raw 'ufLink' and 'bucket'
  93. // pointers, making deserialization a piece of cake - just read in the
  94. // pointers and satisfy links.
  95. printPtr(atom, ufLinkForEquivRelOfDomOfMapToBucket);
  96. printPtr(atom, bucket);
  97. // printThing(_repr_value, repr_value, xmlPrintPointer(
  98. // xmlPrintPointer(idmgr.idPrefix(bucket), idmgr.uniqueId(bucket))));
  99. // printThing(_repr_bucket, repr_bucket, xmlPrintPointer(
  100. // xmlPrintPointer(idmgr.idPrefix(bucket), idmgr.uniqueId(bucket))));
  101. tagPrinter.tagEnd();
  102. }
  103. // **** subtags
  104. // * superclasses
  105. toXml_Value_subtags(atom);
  106. // * members
  107. trav(atom->type);
  108. trav(atom->atVoid);
  109. // * buckets
  110. // quarl 2006-05-19
  111. // We now inline the BucketOValues, so we serialize it here.
  112. //
  113. // We serialize the bucket of the representative CVAtomicValue now,
  114. // otherwise it may never happen: the representative CVAtomicValue may
  115. // be not reached due to shouldSerialize.
  116. // There need not be a bucket here; this qvar may have never participated
  117. // in data flow, e.g. a struct that was never used.
  118. if (atom->bucket != NULL) {
  119. // This should have been fixed earlier in this function
  120. xassert(atom->bucket->isEnabled());
  121. bool shouldSrzRange = serializeOracle==NULL ||
  122. serializeOracle->shouldSerialize(atom->bucket);
  123. {
  124. Restorer<ValueVisitor*>
  125. restorerKey(this->valueVisitor, shouldSrzRange?this->valueVisitor:NULL);
  126. toXml(atom->bucket);
  127. }
  128. }
  129. if (reprBucket != NULL) {
  130. // quarl 2006-05-20
  131. // We should have printed the bucket either just now, or earlier.
  132. // It is important that printed0(reprBucket) be true here because when
  133. // we visit another CVAtomicValue in this equivalence relation, we'll
  134. // decide whether we've printed that CVAtomicValue based on whether
  135. // the representative bucket has ever been printed.
  136. xassert(idmgr.printed0(reprBucket));
  137. }
  138. break;
  139. }
  140. case Value::V_POINTER: {
  141. PointerValue *ptr = v->asPointerValue();
  142. XmlTagPrinter tagPrinter(*this);
  143. if (writingP()) {
  144. tagPrinter.printOpenTag(tagName_Value(ptr), ptr);
  145. // **** attributes
  146. // * superclasses
  147. toXml_Value_properties(ptr);
  148. // * members
  149. printPtr(ptr, type);
  150. printPtr(ptr, atValue);
  151. tagPrinter.tagEnd();
  152. }
  153. // **** subtags
  154. // * superclasses
  155. toXml_Value_subtags(ptr);
  156. // * members
  157. trav(ptr->type);
  158. trav(ptr->atValue);
  159. break;
  160. }
  161. case Value::V_REFERENCE: {
  162. ReferenceValue *ref = v->asReferenceValue();
  163. XmlTagPrinter tagPrinter(*this);
  164. if (writingP()) {
  165. tagPrinter.printOpenTag(tagName_Value(ref), ref);
  166. // **** attributes
  167. // * superclasses
  168. toXml_Value_properties(ref);
  169. // * members
  170. printPtr(ref, type);
  171. printPtr(ref, atValue);
  172. tagPrinter.tagEnd();
  173. }
  174. // **** subtags
  175. // * superclasses
  176. toXml_Value_subtags(ref);
  177. // * members
  178. trav(ref->type);
  179. trav(ref->atValue);
  180. break;
  181. }
  182. case Value::V_FUNCTION: {
  183. FunctionValue *func = v->asFunctionValue();
  184. XmlTagPrinter tagPrinter(*this);
  185. if (writingP()) {
  186. tagPrinter.printOpenTag(tagName_Value(func), func);
  187. // **** attributes
  188. // * superclasses
  189. toXml_Value_properties(func);
  190. // * members
  191. printPtr(func, type);
  192. printPtr(func, retValue);
  193. printPtr(func, retVar);
  194. printPtr(func, params);
  195. // was this before ellipsis became a pointer to a pointer
  196. printPtr(func, ellipsisHolder);
  197. tagPrinter.tagEnd();
  198. }
  199. // **** subtags
  200. // * superclasses
  201. toXml_Value_subtags(func);
  202. // * members
  203. trav(func->type);
  204. trav(func->retValue);
  205. trav(func->retVar);
  206. travObjListPtr_S(func, FunctionValue, params, Variable_O);
  207. trav(func->ellipsisHolder);
  208. break;
  209. }
  210. case Value::V_ARRAY: {
  211. ArrayValue *arr = v->asArrayValue();
  212. XmlTagPrinter tagPrinter(*this);
  213. if (writingP()) {
  214. tagPrinter.printOpenTag(tagName_Value(arr), arr);
  215. // **** attributes
  216. // * superclasses
  217. toXml_Value_properties(arr);
  218. // * members
  219. printPtr(arr, type);
  220. printPtr(arr, atValue);
  221. tagPrinter.tagEnd();
  222. }
  223. // **** subtags
  224. // * superclasses
  225. toXml_Value_subtags(arr);
  226. // * members
  227. trav(arr->type);
  228. trav(arr->atValue);
  229. break;
  230. }
  231. case Value::V_POINTERTOMEMBER: {
  232. PointerToMemberValue *ptm = v->asPointerToMemberValue();
  233. XmlTagPrinter tagPrinter(*this);
  234. if (writingP()) {
  235. tagPrinter.printOpenTag(tagName_Value(ptm), ptm);
  236. // **** attributes
  237. // * superclasses
  238. toXml_Value_properties(ptm);
  239. // * members
  240. printPtr(ptm, type);
  241. printPtr(ptm, atValue);
  242. tagPrinter.tagEnd();
  243. }
  244. // **** subtags
  245. // * superclasses
  246. toXml_Value_subtags(ptm);
  247. // * members
  248. trav(ptm->type);
  249. trav(ptm->atValue);
  250. break;
  251. }
  252. }
  253. // visiting
  254. if (valueVisitor) {
  255. valueVisitor->postVisitValue(v);
  256. }
  257. }
  258. void XmlValueWriter::toXml(FVEllipsisHolder *fveh) {
  259. // idempotency
  260. if (idmgr.printed(fveh)) return;
  261. // visiting
  262. if (valueVisitor) {
  263. if (!valueVisitor->preVisitFVEllipsisHolder(fveh)) {
  264. return;
  265. }
  266. }
  267. XmlTagPrinter tagPrinter(*this);
  268. if (writingP()) {
  269. tagPrinter.printOpenTag("FVEllipsisHolder", fveh);
  270. // **** attributes
  271. // * members
  272. printPtr(fveh, ellipsis);
  273. tagPrinter.tagEnd();
  274. }
  275. // **** subtags
  276. // * members
  277. trav(fveh->ellipsis);
  278. // visiting
  279. if (valueVisitor) {
  280. valueVisitor->postVisitFVEllipsisHolder(fveh);
  281. }
  282. }
  283. bool XmlValueWriter::XVW_SerializeOracle::shouldSerialize(Variable const *x) {
  284. return serializeVar_O(const_cast<Variable*>(x));
  285. }
  286. char const * const XmlValueWriter::tagName_Variable() {
  287. return "Variable_O";
  288. }
  289. // NOTE: do NOT delegate to the superclass; we handle all of it here
  290. void XmlValueWriter::toXml(Variable *var0) {
  291. Variable_O *var = asVariable_O(var0);
  292. // printf ("## toXml(Variable): var->name '%s'\n", var->name); fflush(stdout);
  293. // idempotency
  294. if (idmgr.printed(var)) return;
  295. // FIX: hack: we use this visitor for serialization but also for
  296. // general visitation so that we can mark qvars as extern; during
  297. // that pass, a serialization oracle is not provided. In general it
  298. // is only the serialization oralce that is preventing variables
  299. // that are not getFilteredKeep() from being visited, so if one is
  300. // not present, this assertion is guaranteed to fail.
  301. if (serializeOracle_m) {
  302. xassert(!var->filteredOut());
  303. }
  304. // avoid varibles that shouldn't be serialized
  305. // FIX: this is off for now
  306. // if (varPred && !varPred(var)) return;
  307. // instead of passing in a varPred, just use preVisitValue or shouldSerialize.
  308. // visiting
  309. if (valueVisitor) {
  310. if (!valueVisitor->preVisitVariable(var)) {
  311. return;
  312. }
  313. }
  314. XmlTagPrinter tagPrinter(*this);
  315. if (writingP()) {
  316. tagPrinter.printOpenTag(tagName_Variable(), var);
  317. // **** attributes
  318. // * superclasses
  319. toXml_Variable_properties(var);
  320. // * members
  321. printPtr(var, abstrValue0);
  322. // NOTE: might bring this back, but for now is serialized as user1
  323. // printXml_bool(hasFuncDefn, var->hasFuncDefn);
  324. tagPrinter.tagEnd();
  325. }
  326. // **** subtags
  327. // * superclasses
  328. toXml_Variable_subtags(var);//SUBTRAVERSAL
  329. // * members
  330. trav(var->abstrValue0);//SUBTRAVERSAL
  331. // visiting
  332. if (valueVisitor) {
  333. valueVisitor->postVisitVariable(var);
  334. }
  335. }
  336. void XmlValueWriter::toXml_externVars(TailList<Variable_O> *list) {
  337. travObjList0(*list, externVars, Variable_O, FOREACH_TAILLIST_NC, TailList);
  338. }
  339. void XmlValueWriter::toXml_Value_properties(Value *value) {
  340. printXml_SourceLoc(loc, value->loc);
  341. printPtr(value, refToMe);
  342. printPtr(value, ptrToMe);
  343. if (!Value::allow_annotation) {
  344. bool usedInDataflow = value->getUsedInDataflow();
  345. printXml_bool(usedInDataflow, usedInDataflow);
  346. }
  347. }
  348. void XmlValueWriter::toXml_Value_subtags(Value *value) {
  349. trav(value->refToMe);
  350. trav(value->ptrToMe);
  351. }
  352. void XmlValueWriter::toXml(BucketOValues *bv) {
  353. xassert(bv->enabled);
  354. // idempotency
  355. if (idmgr.printed(bv)) return;
  356. XmlTagPrinter tagPrinter(*this);
  357. if (writingP()) {
  358. tagPrinter.printOpenTag("BucketOValues", bv);
  359. // **** attributes
  360. printEmbed(bv, nameToValue);
  361. tagPrinter.tagEnd();
  362. }
  363. // **** subtags
  364. if (!idmgr.printed(&bv->nameToValue)) {
  365. XmlTagPrinter tagPrinter2(*this);
  366. if (writingP()) {
  367. tagPrinter2.printOpenTag("NameMap_BucketOValues_nameToValue", &bv->nameToValue);
  368. tagPrinter2.tagEnd();
  369. }
  370. // iterates over them in key-sorted order
  371. for(StringSObjDict<Value>::Iter iter(bv->nameToValue);
  372. !iter.isDone(); iter.next()) {
  373. rostring name = iter.key();
  374. // dsw: do you know how bad it gets if I don't put a const-cast
  375. // here?
  376. Value *value = const_cast<Value*>(iter.value());
  377. XmlTagPrinter tagPrinter3(*this);
  378. if (writingP()) {
  379. tagPrinter3.printNameMapItemOpenTag(name.c_str(), value);
  380. }
  381. toXml(value);
  382. }
  383. }
  384. }