3 import Analysis.Disjoint.HeapAnalysis;
4 import Analysis.Disjoint.Alloc;
11 // This BuildCode Extension (BCX) takes a heap analysis
12 // with points-to information and generates checks at runtime
13 // verifies the allocation site of objects pointed-to. It
14 // doesn't fully verify an analysis but it can reveal bugs!
17 public class BCXPointsToCheckVRuntime implements BuildCodeExtension {
19 protected BuildCode buildCode;
20 protected HeapAnalysis heapAnalysis;
23 public BCXPointsToCheckVRuntime( BuildCode buildCode,
24 HeapAnalysis heapAnalysis ) {
25 this.buildCode = buildCode;
26 this.heapAnalysis = heapAnalysis;
30 public void additionalIncludesMethodsHeader(PrintWriter outmethodheader) {
31 outmethodheader.println("#include \"assert.h\"");
35 public void additionalCodeAtTopFlatMethodBody(PrintWriter output, FlatMethod fm) {
37 for( int i = 0; i < fm.numParameters(); ++i ) {
38 TempDescriptor td = fm.getParameter( i );
39 TypeDescriptor type = td.getType();
41 genAssertRuntimePtrVsHeapResults( output,
44 heapAnalysis.canPointToAfter( td, fm )
51 public void additionalCodePreNode(FlatMethod fm, FlatNode fn, PrintWriter output) {
62 case FKind.FlatOpNode: {
63 FlatOpNode fon = (FlatOpNode) fn;
64 if( fon.getOp().getOp() == Operation.ASSIGN ) {
70 genAssertRuntimePtrVsHeapResults( output,
73 heapAnalysis.canPointToAt( lhs, fn )
76 genAssertRuntimePtrVsHeapResults( output,
79 heapAnalysis.canPointToAt( rhs, fn )
86 case FKind.FlatCastNode: {
87 FlatCastNode fcn = (FlatCastNode) fn;
93 genAssertRuntimePtrVsHeapResults( output,
96 heapAnalysis.canPointToAt( lhs, fn )
99 genAssertRuntimePtrVsHeapResults( output,
102 heapAnalysis.canPointToAt( rhs, fn )
108 case FKind.FlatFieldNode: {
109 FlatFieldNode ffn = (FlatFieldNode) fn;
112 fld = ffn.getField();
114 type = lhs.getType();
116 genAssertRuntimePtrVsHeapResults( output,
119 heapAnalysis.canPointToAt( lhs, fn )
122 genAssertRuntimePtrVsHeapResults( output,
127 heapAnalysis.canPointToAt( rhs, fld, fn )
133 case FKind.FlatElementNode: {
134 FlatElementNode fen = (FlatElementNode) fn;
137 idx = fen.getIndex();
139 type = lhs.getType();
141 genAssertRuntimePtrVsHeapResults( output,
144 heapAnalysis.canPointToAt( lhs, fn )
147 genAssertRuntimePtrVsHeapResults( output,
152 heapAnalysis.canPointToAtElement( rhs, fn )
162 public void additionalCodePostNode(FlatMethod fm,
164 PrintWriter output) {
165 switch( fn.kind() ) {
166 case FKind.FlatCall: {
167 FlatCall fc = (FlatCall) fn;
168 TempDescriptor td = fc.getReturnTemp();
171 TypeDescriptor type = td.getType();
173 genAssertRuntimePtrVsHeapResults( output,
176 heapAnalysis.canPointToAfter( td, fn )
187 genAssertRuntimePtrVsHeapResults( PrintWriter output,
190 Set<Alloc> targetsByAnalysis ) {
192 assert targetsByAnalysis != null;
195 output.println( "" );
196 output.println( "// asserts vs. heap results (DEBUG)" );
199 if( targetsByAnalysis == HeapAnalysis.DONTCARE_PTR ) {
200 output.println( "// ANALYSIS DIDN'T CARE WHAT "+x+" POINTS-TO" );
205 if( targetsByAnalysis.isEmpty() ) {
206 output.println( "assert( "+
207 buildCode.generateTemp( context, x )+
211 output.print( "assert( "+
212 buildCode.generateTemp( context, x )+
215 Iterator<Alloc> aItr = targetsByAnalysis.iterator();
216 while( aItr.hasNext() ) {
217 Alloc a = aItr.next();
218 output.print( buildCode.generateTemp( context, x )+
220 a.getUniqueAllocSiteID()
222 if( aItr.hasNext() ) {
223 output.print( " || " );
227 output.println( " );\n" );
234 genAssertRuntimePtrVsHeapResults( PrintWriter output,
237 FieldDescriptor f, // this null OR
238 TempDescriptor i, // this null
239 Hashtable< Alloc, Set<Alloc> > targetsByAnalysis ) {
240 assert targetsByAnalysis != null;
242 assert f == null || i == null;
244 output.println( "// asserts vs. heap results (DEBUG)" );
247 if( targetsByAnalysis == HeapAnalysis.DONTCARE_DREF ) {
248 output.println( "// ANALYSIS DIDN'T CARE WHAT "+x+" POINTS-TO" );
253 if( targetsByAnalysis.isEmpty() ) {
254 output.println( "assert( "+
255 buildCode.generateTemp( context, x )+
258 output.println( "{" );
260 // if the ptr is null, that's ok, if not check allocsite
261 output.println( "if( "+
262 buildCode.generateTemp( context, x )+
265 // precompute the allocsite, if any, of the object we will
266 // get from hopping through the first ptr
267 output.println( "int allocsiteOneHop = -1;" );
268 output.println( buildCode.strObjType+"* objOneHop;" );
271 output.println( "objOneHop = ("+buildCode.strObjType+"*) "+
272 buildCode.generateTemp( context, x )+
273 "->"+f.getSafeSymbol()+";");
275 output.println( "objOneHop = ("+buildCode.strObjType+"*) "+
276 "((struct "+x.getType().dereference().getSafeSymbol()+"**)"+
277 "(((void*) &("+buildCode.generateTemp( context, x )+"->___length___))+sizeof(int)))"+
278 "["+buildCode.generateTemp( context, i )+"];" );
281 output.println( "if( objOneHop != NULL ) { allocsiteOneHop = objOneHop->allocsite; }" );
283 output.println( "switch( "+
284 buildCode.generateTemp( context, x )+
287 Iterator<Alloc> kItr = targetsByAnalysis.keySet().iterator();
288 while( kItr.hasNext() ) {
289 Alloc k = kItr.next();
291 output.print( "case "+
292 k.getUniqueAllocSiteID()+
295 Set<Alloc> hopTargets = targetsByAnalysis.get( k );
296 if( hopTargets == HeapAnalysis.DONTCARE_PTR ) {
297 output.print( "/* ANALYSIS DOESN'T CARE */" );
300 output.print( "assert( allocsiteOneHop == -1" );
302 if( !hopTargets.isEmpty() ) {
303 output.print( " || " );
306 Iterator<Alloc> aItr = hopTargets.iterator();
307 while( aItr.hasNext() ) {
308 Alloc a = aItr.next();
310 output.print( "allocsiteOneHop == "+
311 a.getUniqueAllocSiteID() );
313 if( aItr.hasNext() ) {
314 output.print( " || " );
318 output.print( " );" );
321 output.println( " break;" );
324 output.println( " default: assert( 0 ); break;" );
325 output.println( "}" );
326 output.println( "}" );
327 output.println( "}\n" );
334 public void printExtraArrayFields(PrintWriter outclassdefs) {}
335 public void outputTransCode(PrintWriter output) {}
336 public void buildCodeSetup() {}
337 public void generateSizeArrayExtensions(PrintWriter outclassdefs) {}
338 public void preCodeGenInitialization() {}
339 public void postCodeGenCleanUp() {}
340 public void additionalClassObjectFields(PrintWriter outclassdefs) {}
341 public void additionalCodeGen(PrintWriter outmethodheader,
342 PrintWriter outstructs,
343 PrintWriter outmethod) {}
344 public void additionalCodeAtTopOfMain(PrintWriter outmethod) {}
345 public void additionalCodeForCommandLineArgs(PrintWriter outmethod, String argsVar) {}
346 public void additionalCodeAtBottomOfMain(PrintWriter outmethod) {}
347 public void additionalIncludesMethodsImplementation(PrintWriter outmethod) {}
348 public void additionalIncludesStructsHeader(PrintWriter outstructs) {}
349 public void additionalCodeAtTopMethodsImplementation(PrintWriter outmethod) {}
350 public void additionalCodeNewObject(PrintWriter outmethod, String dstVar, FlatNew flatNew) {}