ABI Compatibility Through A Customizable Language Kevin Atkinson PhD Thesis University of Utah 1
Application Programmer Interface (API) class X { virtual int f(); Library ... API }; Application Library class Y API int main() { X x; Code x.f(); } 2
Application Binary Interface (ABI) ABI class X { virtual int f(); Class Library ... gcc API Layout }; Calling Convention Application Library class Y ABI gcc API int main() { X x; Code Object x.f(); gcc Code } 3
Source vs Binary Compatibility (ABI Fragility) class X { virtual int f(); virtual int g(); Library gcc ABI API ... }; Application int main() { X x; Code Object x.f(); gcc Code } Doesn't Change Recompile 4
ABI Incompatibility class X { virtual int f(); Library gcc ... ABI API vc++ }; Application int main() { X x; Code Object x.f(); vc++ Code } Doesn't Change Change Compilers and Recompile 5
Previous Work ● Some Standardization ● Some Work Towards Attempts Less Fragile ABIs ● Itanium C++ ABI ● Delta C++ (Palay, 1992) ● Object Binary Interface (Williams and Kindel, 1994) ● Still Two Common ABIs: ● Sacrifice Performance ● Not Commonly Used ● GCC ● Visual C++ 6
Thesis Statement Fragile and incompatible ABIs are a major problem in software maintenance and evolution that can be systematically dealt with and effectively managed using a macro-based system that allows the programmer to control how an API maps to an ABI. Class Impl. ZL int main() { Macro Extensible ... Object Compiler } Code 7
Breaking Binary Compatibility class X class X { size int x; API (.h) int x 4 ... gcc }; class X { class X int x; API (.h) int x size int y; gcc 8 ... int y }; 8
Preserving Binary Compatibility Dummy Member class X { class X int x; int x API (.h) size int dummy; gcc 8 ... int dummy }; class X { class X int x; int x size API (.h) int y; gcc 8 ... int y }; 9
Preserving Binary Compatibility Pointer to Implementation class X { class X Impl* imp; API (.h) int get_x(); gcc }; class X::Impl { Implementation int x; }; Impl int x int X::get_x() {imp->x;} 10
Breaking Binary Compatibility class X { vtable virtual void foo(); ... size gcc void foo() 4 }; class X { virtual void foo(); vtable virtual void bar(); void foo() size ... gcc 8 void bar() }; ● For Preserving: Options Limited 11
Pointer to Impl. Dummy Member class X { class X class X { int x; class X Impl* imp; API (.h) int x size int dummy; int get_x(); gcc gcc 8 ... int dummy }; }; … class X::Impl { Implementation int x; Impl }; class X { class X int x int x; int x int X::get_x() size int y; gcc 8 {imp->x;} ... int y }; Automate These Patterns 12
Automation is Not Enough... Breaking Binary Compatibility Breaking Binary Compatibility class X { class X { virtual void foo(); vtable virtual void foo(); vtable size ... gcc void foo() ... size gcc void foo() 4 }; 4 }; class X { class X { virtual void foo(); vtable virtual void foo(); vtable virtual void bar(); void foo() size virtual void bar(); void foo() size ... gcc 8 gcc ... void bar() 8 }; void bar() }; ● For Preserving: Options Limited ● For Preserving: Options Limited 13
Extension Class Impl. int main() { ... Object } Extensible Code Compiler Class Impl. int main() { Macro Extensible Object ... Compiler Code } 14
Class Impl. Macro Extensible int main() { Object Compiler ... Code } Library Class Impl. import ... Macro Extensible Object int main() { Compiler Code ... } 15
Two ABI's at Once Gcc ABI VC++ ABI class : ABI(gcc) Macro Extensible Object class : ABI(vc++) Compiler Code 16
ZL default class other macro implementation library import ...; int main() { Macro Extensible Object ... Compiler Code } C Like Core w/ Minimal Amount of C++ 17
How to Parse This Expression? f(x/2, y) Function Call? Macro Invocation? x/2 + y ? f(x/2, y) ? int y = x/2 18
Parsing Overview ● ZL doesn't parse in a single linear pass ● Iterative-deepening approach Parse Partly Expand Syntax Syntax Raw Text Object Object e s r a p e R Compile AST Node Raw Text 19
Parsing inline int f() {int x = 10; return x;} int main() {return f();} Details Parse (@ (stmt inline int f ("()" "") ("{}" "int x = 10; return x;") (stmt int main ("()" "") ("{}" "return f();"))) Expand & Compile Top Level Environment (stmt inline int f ...) ... (stmt int main ...) ... 20
Top Level Environment (stmt inline int f ...) ... Expand (fun f "()" int :inline ("{}" "int x = 10; return x;"}) Compile Function ("{}" "int x = 10; return x;") ... (stmt int main ...) ... 21
Function ("{}" "int x = 10; return x;") ... Expand & Reparse (block (stmt int x = 10) (return (exp x))) Compile Block (stmt int x = 10)) ... (return (exp x)) ... 22
Hygienic Pattern Macros macro or( x , y ) { ({typeof( x ) t = x ; t ? t : y ;}); } ({typeof(0.0) t 0 = 0.0; t 0 ? t 0 : t;}); or(0.0,t) 23
Procedural Macros Syntax* foreach(Syntax*) {...} make_macro foreach int main() { Container c; ... foreach(el, c, el.print()); } Syntax Forms: new_mark Callbacks: match syntax replace make_macro ct_value error 24
The Class Macro import_file "class-simple.zlh"; ... .class ParseClass { ... virtual Syntax * parse(Syntax * p) {...} virtual void init() {...} 900 Lines virtual void init_parent_info() {...} ... of Code }; Syntax * parse_class(Syntax * p) { ParseClass * pc = new ParseClass; return pc->parse(p); } make_macro class parse_class; 25
Expanding Method Calls C o C::f(...) o.f() What is f? 26
User Types (ZL's Notion of Classes) user_type C { struct Data { int i; }; associate_type struct Data; int foo(int j) macro i(:this ths) {...} macro f(x, :this ths) {...} } void main() { void main() { C o; C o; o.f(x); C::f(x, :this = &o); int x = o.i; int x = C::i(:this = &o); } } 27
Classes user_type C { struct Data { int i; }; class C { associate_type struct Data; int f`internal(C * this, int j) int i; {return i + j;} int f(int j) {return i + j;} macro i (:this ths = this) {(*(C *)ths)..i;} }; macro f(j, :this ths = this) {f`internal(ths, j);} } 28
Inheritance user_type D { import C; struct Data { class D : public C struct C::Data parent; { int j; }; int j; associate_type struct Data; }; make_subtype C _up_cast _down_cast; macro _up_cast ... macro _down_cast ... macro j (:this ths = this) {...} } 29
Virtual Methods user_type D { ... class VTable : public C::VTable { void (*f)(int j); }; class D : public C struct Data { { VTable* _vptr; virtual ... void f(int j); }; } ; associate_type struct Data; macro f(j, :this ths = this) {_vptr->f(ths, j);} ... } 30
Examples Using ZL to Mitigate ABI Problems 31
Example: Fixing Size of Class class C class X class C { : fix_size(12) int x; int x { char dummy[8] int x; dummy[8] 12 }; 8 }; class C class C { class X : fix_size(12) int x; { int x int y; int x; char dummy[4] 12 int y int y; }; }; dummy[4] 4 (Complete Macro In Dissertation, 36 Lines of Code) 32
Example: Allowing More Fields class C : class X fix_size(12) int x { int x; int y 12 int y; int i; int j; }; Overflow int main() { int i C obj ; obj .x; int j obj .i; } (Expanded Macro, Around 100 Lines of Code) 33
Example: Pointer to Impl. class C : class X fix_size(0) { int x; int y; int i; int j; Overflow }; int x int main() { int y C obj ; int i; obj .x; obj .i; int j; } (Same Macro, Around 100 Lines of Code) 34
Fixing Virtual Table Size macro alt_vtable ( name , body ) { class name : fix_size(8) { body }; class X } : fix_vtable_size(8) { class X : vtable_class(alt_vtable) { virtual void f(); { virtual void g(); virtual void f(); virtual void h(); virtual void g(); }; virtual void h(); }; (Modified Macro, Around 120 Lines of Code) 35
Matching GCC's ABI ZL Default ABI GCC ABI .class ParseClascGccABI .class ParseClass {...} : public ParseClass {...} {int get_x();} extern "C++" class ClassWithZLABI {int get_x();} extern "C++" : "gcc" class ClassWithGCCABI Compiles To int ClassWithZLABI$get_x$$P$_ClassWithZLABI (); int _ZN15ClassWithGCCABI5get_xEv (); (Class Macro 150 lines, Mangler 300 lines) 36
Demonstration Simple Spell 37
Simple Spell´s Classes GCC ABI ZL ABI Speller Session ... ... Filter personal ... reset() ... filter(...) add_to_personal() reset() SessionWFilter Bridge GCC or ZL UrlFilter EmailFilter Application GCC ABI 38
Recommend
More recommend