210 likes | 341 Views
XCISE 2.0.6 Dead Code Elimination by Exploiting ASX. Ian Davis University of Waterloo. Capturing the build process. Wrap gcc & g++ Capture build history What program What parameters Where invoked Repeat the build process Adjusting parameters Request compilation to assembler
E N D
XCISE 2.0.6Dead Code Elimination by Exploiting ASX Ian Davis University of Waterloo
Capturing the build process • Wrap gcc & g++ • Capture build history • What program • What parameters • Where invoked • Repeat the build process • Adjusting parameters • Request compilation to assembler • Present each assembler built to ASX Dead Code Elimination
Key Idea • Compile source to assembler • Scan the assembler for: • Function declarations • Function invocation • Direct Function Calls • Indirect Function Calls via pointer • Functions called as part of initialisation • Class information • Vtables, Typeinfo structs, etc. • Map back to the source code • Source & line no function body starts at Dead Code Elimination
Relevant Standards • Intel 386 assembler • Function boundaries, calls & pointer manipulation • Source file name and line no information • Dwarf 3.0 (Symbolic Information) • Recover frame base, and class of this pointer • Recover vtable mapping to functions • Itanium Application Binary Interface (ABI) • Unmangle g++ function signatures Dead Code Elimination
Virtual Function Call Pattern • With any registers + interleaved assembler • movq -24(%rbp), %rax • // Class pointer -> %rax • movq (%rax), %rax • // Vtable -> %rax • addq $8, %rax • // Optional -- absent if $0 • movq (%rax), %rax • // Function pointer • call *%rax Dead Code Elimination
Output TA • Output from ASX • Consolidated call graph • Viewable using LSEdit • Readable by C++ and Java code • Human readable ascii file Dead Code Elimination
Phase Two • XCISE • Load graph into a C++ program • From all mainline functions • main • Function calls as part of variable assignment • Flag all reachable functions • Report those not reachable • Remove them from source code Dead Code Elimination
Basic Problems • Requires holistic approach • Will break compilation if we remove casually • What about nasty invocations through pointer • Problematic issues.. • Function declarations in class files • Macros • Friend classes • Polymorphism • Abstract classes • Implicit polymorphism • Class .v. Namespace Dead Code Elimination
What to remove • Constructors / Destructors ? • Default constructors/destructors ! • Illegal function invocation trapping code • Classes ? • Friends • Inheritance • Risks re polymorphism • Risks re abstract classes • If we don’t remove a dead function • Can’t remove anything it calls Dead Code Elimination
What about functions in header files • Inlined function declarations • Can appear in multiple assembler files • Static functions in header files • Likewise • Consolidate based on file and line number • Inviolate header files • /usr/include • Call back mechanisms from libraries • Really problematic Dead Code Elimination
What about template functions • Can identify template function by signature • No explicit function body that can be removed • Can only remove template if no instantiations • Templates occur in header files.. • Not all templated classes likely to be used • Do we even want to remove them • Can’t presume usage over time unchanged Dead Code Elimination
Polymorphism • See a polymorphic call to A::foo() • But for all X : X subclass of A might be • Call to X::foo() • Visit A::foo() polymorphically • => Visit all such X::foo() polymorphically • Discovery using vtable & typeinfo structures Dead Code Elimination
Dead Code Removal • Given only file and line no of start of body • Want to remove function with this body • Hard to parse source • Comments • Macros • Run the source through cpp • Use original build parameters re source • Use file and line number info to map back to source • Eliminates all macros, comments, etc. Dead Code Elimination
Removal strategy • g++ -Dlinux –Uwin32 –Dversion=v2 main.cpp • #if !defined(_DEAD_) && • defined(linux) && !defined(win32) && • defined(version) && (version == v2) • #define _DEAD_20110312203041 • #endif /* _DEAD_ */ • Eliminate • #ifndef _DEAD_20110312203041 • int foo() {} • #endif /* _DEAD_20110312203041 */ Dead Code Elimination
Removal choices • Create new output file • Can’t then compile upgraded source • Overwrite existing source • Risky • Create backup • Really hard to debug introduced errors • Massive systemic changes hard to debug • Hard to work out why something illegally removed • Possibly provide incremental removal • Remove top level dead code first Dead Code Elimination
Current status • Removal of regular functions works well • Removal of all dead functions problematic • Not catching all polymorphic calls ? • Not catching other types of function addressing • Not sure why things don’t compile • Don’t want to plough through 1’000s of error messages • Can’t break problem down easily • Might all be resolved with a single bug fix • Might not get resolved with many bug fixes Dead Code Elimination
Source Code • ASX 3.0.8 • www.swag.uwaterloo.ca/asx • XCISE 2.0.6 • www.swag.uwaterloo.ca/xcise • LSEdit 7.3.14 • www.swag.uwaterloo.ca/lsedit Dead Code Elimination