ABI Compatibility Through A Customizable Language Kevin Atkinson - - PowerPoint PPT Presentation

abi compatibility through a customizable language
SMART_READER_LITE
LIVE PREVIEW

ABI Compatibility Through A Customizable Language Kevin Atkinson - - PowerPoint PPT Presentation

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


slide-1
SLIDE 1

1

ABI Compatibility Through A Customizable Language

Kevin Atkinson PhD Thesis University of Utah

slide-2
SLIDE 2

2

Application Programmer Interface (API)

Application

int main() { X x; x.f(); } Code Library Library class X { virtual int f(); ... }; API class Y API

slide-3
SLIDE 3

3

Application Binary Interface (ABI)

class X { virtual int f(); ... }; int main() { X x; x.f(); }

Application

API Code Library Library gcc ABI

Class Layout Calling Convention

gcc Object Code class Y API gcc ABI

slide-4
SLIDE 4

4

Source vs Binary Compatibility

Application

Doesn't Change Recompile class X { virtual int f(); virtual int g(); ... }; API Library gcc ABI int main() { X x; x.f(); } Code gcc Object Code

(ABI Fragility)

slide-5
SLIDE 5

5

ABI Incompatibility

Application

Doesn't Change Change Compilers and Recompile class X { virtual int f(); ... }; API Library gcc vc++ ABI int main() { X x; x.f(); } Code vc++ Object Code

slide-6
SLIDE 6

6

Previous Work

  • Some Standardization

Attempts

  • Itanium C++ ABI
  • Some Work Towards

Less Fragile ABIs

  • Delta C++ (Palay, 1992)
  • Object Binary Interface

(Williams and Kindel, 1994)

  • Still Two Common ABIs:
  • GCC
  • Visual C++
  • Sacrifice Performance
  • Not Commonly Used
slide-7
SLIDE 7

7

Thesis Statement

int main() { ... } Object Code Class Impl. Macro Extensible Compiler

ZL

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.

slide-8
SLIDE 8

8

Breaking Binary Compatibility

class X { int x; ... }; gcc class X { int x; int y; ... }; gcc class X int x class X int x int y size 4 size 8 API (.h) API (.h)

slide-9
SLIDE 9

9

Preserving Binary Compatibility

Dummy Member

class X { int x; int dummy; ... }; gcc class X { int x; int y; ... }; gcc class X int x int dummy size 8 class X int x int y size 8 API (.h) API (.h)

slide-10
SLIDE 10

10

Preserving Binary Compatibility

Pointer to Implementation

API (.h) gcc

Implementation

class X { Impl* imp; int get_x(); }; class X::Impl { int x; }; int X::get_x() {imp->x;}

class X

Impl

int x

slide-11
SLIDE 11

11

Breaking Binary Compatibility

class X { virtual void foo(); ... }; gcc class X { virtual void foo(); virtual void bar(); ... }; gcc

  • For Preserving: Options Limited

vtable void foo() size 4 vtable void foo() void bar() size 8

slide-12
SLIDE 12

12

Dummy Member Pointer to Impl.

class X { int x; int dummy; ... }; gcc class X { int x; int y; ... }; gcc class X int x int dummy size 8 class X int x int y size 8

Automate These Patterns

API (.h) gcc

Implementation

class X { Impl* imp; int get_x(); }; class X::Impl { int x; }; int X::get_x() {imp->x;}

class X

Impl

int x

slide-13
SLIDE 13

13

Automation is Not Enough...

Breaking Binary Compatibility

class X { virtual void foo(); ... }; gcc class X { virtual void foo(); virtual void bar(); ... }; gcc

  • For Preserving: Options Limited

vtable void foo() size 4 vtable void foo() void bar() size 8

Breaking Binary Compatibility

class X { virtual void foo(); ... }; gcc class X { virtual void foo(); virtual void bar(); ... }; gcc

  • For Preserving: Options Limited

vtable void foo() size 4 vtable void foo() void bar() size 8

slide-14
SLIDE 14

14 int main() { ... } Extensible Compiler Object Code int main() { ... } Macro Extensible Compiler Object Code Class Impl. Class Impl. Extension

slide-15
SLIDE 15

15 int main() { ... } Object Code Class Impl. import ... int main() { ... } Object Code Class Impl. Library Macro Extensible Compiler Macro Extensible Compiler

slide-16
SLIDE 16

16

Two ABI's at Once

class : ABI(gcc) class : ABI(vc++) Object Code Gcc ABI VC++ ABI Macro Extensible Compiler

slide-17
SLIDE 17

17

ZL

import ...; int main() { ... } Macro Extensible Compiler Object Code default class implementation

  • ther macro

library

C Like Core w/ Minimal Amount of C++

slide-18
SLIDE 18

18

How to Parse This Expression?

f(x/2, y)

Function Call? Macro Invocation?

f(x/2, y) x/2 + y

?

int y = x/2

?

slide-19
SLIDE 19

19

Parsing Overview

  • ZL doesn't parse in a single linear pass
  • Iterative-deepening approach

Raw Text

Parse Syntax Object Raw Text AST Node Syntax Object Partly Expand Compile R e p a r s e

slide-20
SLIDE 20

20

Parsing Details

inline int f() {int x = 10; return x;} int main() {return f();} Parse Expand & Compile (@ (stmt inline int f ("()" "") ("{}" "int x = 10; return x;") (stmt int main ("()" "") ("{}" "return f();")))

Top Level Environment

(stmt int main ...)

...

(stmt inline int f ...)

...

slide-21
SLIDE 21

21

...

(stmt inline int f ...) (fun f "()" int :inline ("{}" "int x = 10; return x;"})

Top Level Environment

Expand Compile ("{}" "int x = 10; return x;")

Function

...

(stmt int main ...)

...

slide-22
SLIDE 22

22

...

("{}" "int x = 10; return x;")

Function

(block (stmt int x = 10) (return (exp x))) Expand & Reparse Compile

Block

(stmt int x = 10)) (return (exp x))

... ...

slide-23
SLIDE 23

23

Hygienic Pattern Macros

macro or(x, y) { ({typeof(x) t = x; t ? t : y;}); }

  • r(0.0,t)

({typeof(0.0) t0 = 0.0; t0 ? t0 : t;});

slide-24
SLIDE 24

24

Procedural Macros

Syntax* foreach(Syntax*) {...} make_macro foreach int main() { Container c; ... foreach(el, c, el.print()); }

Syntax Forms: new_mark syntax make_macro Callbacks: match replace ct_value error

slide-25
SLIDE 25

25

The Class Macro

import_file "class-simple.zlh"; ... .class ParseClass { ... virtual Syntax * parse(Syntax * p) {...} virtual void init() {...} virtual void init_parent_info() {...} ... }; Syntax * parse_class(Syntax * p) { ParseClass * pc = new ParseClass; return pc->parse(p); } make_macro class parse_class;

900 Lines

  • f Code
slide-26
SLIDE 26

26

  • .f()

C::f(...)

Expanding Method Calls

What is f? C o

slide-27
SLIDE 27

27

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() { C o; C::f(x, :this = &o); int x = C::i(:this = &o); } void main() { C o;

  • .f(x);

int x = o.i; }

slide-28
SLIDE 28

28

Classes

class C { int i; int f(int j) {return i + j;} }; user_type C { struct Data { int i; }; associate_type struct Data; int f`internal(C * this, int j) {return i + j;} macro i (:this ths = this) {(*(C *)ths)..i;} macro f(j, :this ths = this) {f`internal(ths, j);} }

slide-29
SLIDE 29

29

Inheritance

class D : public C { int j; }; user_type D { import C; struct Data { struct C::Data parent; int j; }; associate_type struct Data; make_subtype C _up_cast _down_cast; macro _up_cast ... macro _down_cast ... macro j (:this ths = this) {...} }

slide-30
SLIDE 30

30

Virtual Methods

class D : public C { virtual void f(int j); }; user_type D { ... class VTable : public C::VTable { void (*f)(int j); }; struct Data { VTable* _vptr; ... }; associate_type struct Data; macro f(j, :this ths = this) {_vptr->f(ths, j);} ... }

slide-31
SLIDE 31

31

Examples

Using ZL to Mitigate ABI Problems

slide-32
SLIDE 32

32

Example: Fixing Size of Class

class C { int x; char dummy[8] }; class X int x dummy[8] class C : fix_size(12) { int x; }; 8 12 class C { int x; int y; char dummy[4] }; class X int x int y dummy[4] class C : fix_size(12) { int x; int y; }; 4 12

(Complete Macro In Dissertation, 36 Lines of Code)

slide-33
SLIDE 33

33

Example: Allowing More Fields

class C : fix_size(12) { int x; int y; int i; int j; }; int main() { C obj;

  • bj.x;
  • bj.i;

} class X int x int y Overflow int i int j 12

(Expanded Macro, Around 100 Lines of Code)

slide-34
SLIDE 34

34

Example: Pointer to Impl.

class X Overflow int x int y int i; int j;

(Same Macro, Around 100 Lines of Code)

class C : fix_size(0) { int x; int y; int i; int j; }; int main() { C obj;

  • bj.x;
  • bj.i;

}

slide-35
SLIDE 35

35

Fixing Virtual Table Size

class X : fix_vtable_size(8) { virtual void f(); virtual void g(); virtual void h(); };

(Modified Macro, Around 120 Lines of Code)

macro alt_vtable (name, body) { class name : fix_size(8) {body}; } class X : vtable_class(alt_vtable) { { virtual void f(); virtual void g(); virtual void h(); };

slide-36
SLIDE 36

36 extern "C++" class ClassWithZLABI extern "C++" : "gcc" class ClassWithGCCABI

GCC ABI

.class ParseClascGccABI : public ParseClass {...}

Matching GCC's ABI

ZL Default ABI

.class ParseClass {...} int ClassWithZLABI$get_x$$P$_ClassWithZLABI (); int _ZN15ClassWithGCCABI5get_xEv (); Compiles To {int get_x();} {int get_x();}

(Class Macro 150 lines, Mangler 300 lines)

slide-37
SLIDE 37

37

Demonstration

Simple Spell

slide-38
SLIDE 38

38

Bridge EmailFilter

Simple Spell´s Classes

SessionWFilter Filter

filter(...) reset()

UrlFilter

GCC ABI ZL ABI

Session

... ... reset()

Speller

... personal ... add_to_personal()

GCC ABI

Application

GCC or ZL

slide-39
SLIDE 39

39

Speller Class

... Speller * speller = new Speller(); speller->init(new_lang(), new_master_dict()); ... for (...) { // look through document bool correct = speller->check(word); if (!correct) { // maybe Suggestions * sugs = speller->suggest(); // if indeed correct speller->add_to_session(word); } } ...

class Speller { init(...) check(...) suggest() add_to_session(...) }; struct Suggestions; new_lang(); new_master_dict();

GCC ABI

slide-40
SLIDE 40

40

class Session { virtual new_line(...) virtual next_misspelling() inline mispelled_word() virtual replace(...) }; class SessionWFilters : public Session { virtual add(Filter *) }; Filter * new_url_filter();

Session Class

GCC ABI

...

Speller * speller = new Speller(); speller->init(new_lang(), new_master_dict());

SessionWFilters * session = new SessionWFilters(speller); session->add(new_url_filter()); for (...) { // look through doc. one line at a time session->new_line(line); while (session->next_misspelling()) { word = session->misspelled_word();

bool correct = speller->check(word); if (!correct) { // maybe

Suggestions * sugs = speller->suggest(); // if indeed correct speller->add_to_session(word);

// if incorrect session->replace(new_word) }

}

...

slide-41
SLIDE 41

41

Extension API

class Filter { virtual void filter(char * line) = 0 // blank parts of line not to be checked }

ZL ABI

slide-42
SLIDE 42

42

Simple Application

*Teh* dog swm up the stream. 1) The 2) Tea 3) Ted 4) Tee 5) Tel 6) Ten ... i) Ignore I) Ignore all r) Replace a) Abort

Application GCC Library ZL (Using GCC ABI) Application ZL Library GCC

slide-43
SLIDE 43

43

Email Filter with GCC ABI

session->add(filter_bridge(new_email_filter()));

> This line skippd This line checkd

class EmailFilter : public Filter {...} Filter * new_email_filter();

GCC ABI

class FilterBridge : public Filter {...} Filter * filter_bridge(/* filter in GCC ABI*/)

ZL ABI

slide-44
SLIDE 44

44

Automate Bridge Class

Syntax * parse_mk_bridge(...) { ... } make_macro mk_bridge parse_mk_bridge(); mk_bridge(Filter, filter_bridge, “GCC”) (Macro Just Under 55 Lines of Code)

slide-45
SLIDE 45

45

Support For A Personal Dictionary

Speller data_member_1 data_member_2 ... personal Changes Size Speller : fix_size(...) data_member_1 data_member_2 Overflow ... Speller data_member_1 data_member_2 ... Speller data_member_1 data_member_2 ... OK Still Match GCC ABI

slide-46
SLIDE 46

46

Fixing Size of Speller Class

class SpellerOld { // original Speller class private data members }; class Speller : fix_size(sizeof(SpellerOld)) { // private data members SavableDict * personal; // original methods void add_to_personal(const char *); void save_personal(); };

slide-47
SLIDE 47

47

An ABI Allowing Future Adaptation

class Speller : fix_size(0) { ... }; class Session : fix_size(/* size of members used by inline functions */) : vtable_slots(16) { const char * word ... const char * misspelled_word() {return word;} ... }; class SessionWFilter : fix_size(0) : vtable_slots(16) ... extern “C++” : “better” class Filter { ... }

slide-48
SLIDE 48

48

Simple Spell, Version 2

Add (Back) Support for a Personal Dictionary

class Speller : fix_size(0) { ... SavableDict * personal; ... void add_to_personal(...); void save_personal(); };

slide-49
SLIDE 49

49

class Session : fix_size(...) : vtable_slots (16) { ... void reset(); }; extern “C++” : “better” class Filter { ... void reset() }

Simple Spell, Version 2

Add Support for Stateful Filters

Filter * new_comment_filter() // checks only C and C++ comments

slide-50
SLIDE 50

50

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 Run-time Performance
slide-51
SLIDE 51

51

Conclusion

Demonstrated ABI Compatibility Through Macros

int main() { ... } Object Code Class Impl. Macro Extensible Compiler

ZL