ABI Compatibility Through A Customizable Language Kevin Atkinson, Matthew Flatt, Gary Lindstrom 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 gcc x.f(); Code } 3
Source vs Binary Compatibility (ABI Fragility) class X { virtual int f(); virtual int g(); Library ABI gcc API ... }; int main() { Application X x; Code Object gcc x.f(); Code } Doesn't Change Recompile 4
ABI Incompatibility class X { virtual int f(); Library gcc ABI ... API vc++ }; int main() { Application X x; Code Object vc++ x.f(); 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 ● GCC ● Not Commonly Used ● Visual C++ 6
Our Contribution ABI Compatibility Through Macros Class Impl. ZL int main() { Macro Extensible ... Object Compiler } Code 7
Breaking Binary Compatibility class X { class X int x; size 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 { virtual void foo(); vtable 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 int main() { Object Compiler Code ... } 15
Two ABI's at Once Gcc ABI VC++ ABI class : ABI(gcc) Macro Extensible Object Compiler class : ABI(vc++) 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
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) 18
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 19
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; 20
Expanding Method Calls C o C::f(...) o.f() What is f? 21
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); } } 22
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);} } 23
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) {...} } 24
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);} ... } 25
Examples Mitigating the ABI Problem Through Macros 26
Example: Fixing Size of Class class C class C { class X : fix_size(12) int x; int x { char dummy[8] int x; dummy[8] 12 }; 8 }; class C class C { : fix_size(12) class X int x; { int x int y; int x; char dummy[4] int y 12 int y; }; dummy[4] }; 4 (Complete Macro In Paper, 36 Lines of Code) 27
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 ; int j obj .x; obj .i; } (Expanded Macro, Around 100 Lines of Code) 28
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; int j; obj .i; } (Same Macro, Around 100 Lines of Code) 29
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) 30
Matching Other ABIs ZL Class This Global Variable Implementation .class ParseClassNewABI .class ParseClass { : public ParseClass ... { } ... } v1 v2 class : ABI(v1) class : ABI(v2) Implemented In Under 45 Lines of Code 31
ZL Implementation Status ● Prototype Compiler ● Most Of C ● Enough C++ to Demonstrate Approach ● Compiled Several Real Applications ● C: bzip2, gzip ● C++: randprog ● Compile Time 2-3 slower ● No Impact on Performance 32
Conclusion Demonstrated ABI Compatibility Through Macros Class Impl. ZL int main() { Macro Extensible ... Object Compiler } Code 33
Recommend
More recommend