►
From YouTube: OMR Architecture Meeting 20210805
Description
JitBuilder 2.0 (#6125) [ @mstoodle ]
A
Welcome
everyone
to
the
august
5th
omar
architecture
meeting
today
we
have
one
topic
to
discuss
so
mark
stoodley
will
be
presenting
his
work
on
jet
builder
2.0,
and
it's
in
its
latest
state.
All
right
turn
over
to
mark.
B
Thanks
cheryl,
so
this
is
going
to
be
a
fairly
impromptu
update.
I
wasn't
able
to
spend
as
much
time
preparing
slides
and
material
as
I
had
intended,
but
I
do
have
a
few
slides
just
to
kind
of
get
going
and
then
I'll
do
a
bit
of
a
demo
for
where
I
am
right
now.
B
So
fresh,
this
is
still
presentation,
one
all
right,
so
I
thought
I
would
start
by
just
kind
of
giving
everybody
a
bit
of
a
refresher
on
jit
builder
too,
because
it's
been
a
while,
since
I
talked
about
it
here,
so
I
just
wanted
to
kind
of
bring
people
up
this
up
to
speed
on
things.
B
This
is
mostly
a
refresher
of
things
that
existed
the
last
time
I
talked,
but
some
of
it's
a
little
bit
new
and
some
of
them
have
slightly
different
slant,
but
I
I'll
do
my
best
to
go
through
it.
So
this
first
page
just
kind
of
goes
through
the
main
characteristics
of
the
intermediate
language.
That's
that
is
jetbuilder
2,
that
is
the
main
contribution
of
jetbuilder
2.0
over
above
the
the
legit
builder
library
that
exists
in
omar
today.
Is
that
it?
B
It
basically
turns
the
jit
builder
api
into
a
into
a
more
fully
fledged
intermediate
language
that
you
can
introspect
and
work
with
so
in
in
sort
of
I'll
use.
The
term
loosely
formalizing
the
the
builder
api
into
an
il
it
has
sort
of
these
basic
parts
to
it.
There
are
types
as
there
are
in
the
jit
builder
api,
so
the
primitive
types,
a
thing
called,
the
struct
type,
a
union
type
and
a
new
thing,
called
function
type,
so
functions
become
a
more
first-class
citizen
of
the
type
system.
B
B
There
are
other
sort
of
fairly
nice
easily
easy
to
understand
concepts
for
anyone.
Who's
worked
in
compilers,
there's
a
thing
called
a
literal
value
which
just
holds
a
constant
instance
of
some
kind
of
a
type.
So
it's
a
typed
thing.
There
are
symbols
to
represent
things
like
parameters,
local
variables
and
functions.
B
There
are
operations
which
are
are
the
names
for
or
the
the
calls
that
you
would
have
made
in
jit
builder,
to
cause
various
things
to
happen.
B
Like
load,
a
variable
subtract,
two
values
to
produce
a
new
value
index
into
an
array
based
on
a
an
element
size,
do
a
for
loop
or
do
control
flow
like
if
compare
two
values
to
see
which
one,
if
one's
greater
than
the
other,
there
are
values
which
are
consumed
and
produced
by
operations,
and
they
are
typed
just
like
most
compilers
would
do
control
flow
and
control
and
organizing
things,
oops,
sorry
and
organizing
the
sort
of
control
flow
graph.
B
It's
not
quite
like
a
basic
block,
even
though
that
definition
kind
of
makes
it
sound
like
it,
because
the
operations
themselves
can
have
internal
control
flow,
like
that
for
loop
operation,
for
example,
represents
internal
control
flow
over
another
builder
object,
that's
dictated
by
the
values
that
you
pass
to
the
for
loop
operation
and
then
there's
a
special
kind
of
builder
called
a
function
builder,
which
is
essentially
a
a
callable
entry
point
that
has
typed
parameters
and
return
values.
B
B
B
B
I
guess
let
me
just
go
through
them.
So
config
is
a
is
just
a
collection
of
useful
things
right
now,
it's
a
set
of
options
and
flags
and
a
place
to
put
stuff
that
really
needs
to
be
formalized
a
little
bit
better,
given
a
better
life
cycle
for
when,
when
the
config
applies
and
so
on,
but
right
now
it's
just
kind
of
a
place
to
collect
options
and
configuration
things
for
for
running
or
compile.
B
There's
a
thing
called
a
type
graph
which
is
maintained
by
the
type
dictionary
which
is
used
to
record
legal
operation.
Legal
operation,
operand
type
combination.
So
basically,
this
is
the
mechanism
by
which
jit
builder
two
verifies
that
you
don't
create
illegal,
il
or
at
least
some
aspects
of
illegal
il.
So
it
will
verify,
for
example,
that
you
don't
try
to
add
types
that
that
aren't
ads,
that
you
can't
add
together.
So
you
don't
add
an
intake
to
an
in
32.
B
You
have
to
convert
one
of
them
to
this
to
the
same
type
and
then
and
then
add
those
two
types
and
then
the
other
piece
of
the
type
graph
is
that
it.
It
dictates
what
the
what
the
resulting
type
will
be
for
an
operation.
B
So
from
the
input
operand
types
you,
it
will
tell
you
what
the
output
type
is
going
to
be
and
then
from
that
it
can
propagate
all
the
types
through
the
through
the
through
the
il
and
make
sure
that,
when
you're
generating
il,
it
tells
you,
when
you're,
making
mistakes
closer
to
the
point
where
you're
actually
making
them,
rather
than
with
jitbuilder.
You
kind
of
find
out
somewhere
deep
in
the
bowels
of
the
compiler
that
something's
not
quite
right,
and
then
you
have
to
work
backwards.
B
There
are
a
couple
of
very
rudimentary
kinds
of
helper
classes
that
help
you
traverse
il
and
do
things
do
interesting
things
there's
the
visitor
pattern,
which
is
pretty
much
what
it
says.
It
basically
just
allows
a
gives,
an
extensible
class
where
you
can
subclass
an
override.
You
know
trend
visit
operation,
for
example,
and
and
you'll
get
called
for
you
get
callbacks
for
every
every
operation
as
it
walks
through
the
graph.
It
ensures
that
you
visit
every
builder
object
exactly
once
and
every
operation
and
every
builder
exactly
once
so.
B
B
It
allows
you
to
return
a
builder
object
that
says
replace
the
operation
that
I'm
visiting
with
this
builder
object
and
since
a
builder
object
is
an
arbitrary
amount
of
code,
you
can
basically
replace
any
operation
with
any
other
combination
of
other
operations
and,
let's
see,
and
then
there
are
a
few
implementations
of
those
things
in
the
actual
legit
builder
2
code
base.
B
That's
a
that's
a
temporary
state
of
affairs
right
now.
It's
kind
of
the
easiest.
It
was
the
easiest
way
to
bootstrap,
jitbuilder
2,
but
obviously
going
forward.
I
think
the
right
way
would
be
for
code
generate
to
directly
generate
the
il
for
the
omr
compiler
or
in
principle.
It
could
generate
the
il
for
any
compiler
append.
Builder
inliner
is
really
the
first
example
of
a
transformer
that
I
wrote.
B
It's
not
all
that
useful,
but
there
is
an
operation
in
in
jetbuilder
called
append
builder,
which
basically
says
take
this
builder
and
and
act
as
if
it's
in
line
in
the
in
the
current
builder.
B
So,
if
nothing
else
branches
to
that
builder,
like
jumps
directly
to
that
the
the
builder
that's
in
the
event
builder,
then
you
should
be
able
to
actually
just
inline
that
those
code-
and
so
all
of
this,
this
this
append
builder
inliner
just
walks
around
looking
for
append
builder
operations,
where
the
builder
object
isn't
called
by
anything
else,
and
so
it
and
then
it
just
inlines.
The
builder
object
directly
into
the
into
the
parent
builder,
the
builder
that
contains
the
append
builder
operation.
B
B
B
So
that's
I
mean
this
is
basically
where
I
don't
think,
there's
anything
really
new
in
here
compared
to
what
I
would
have
talked
about
before
and
so
now
what's
different.
Now
I
don't
have
a
slide
for
this.
So
on
friday
I
pushed
to
the
the
omar
repo
a
new
pull
request.
That's
I've
marked
it
as
work
in
progress,
but
it's
a
it's
the
implementation.
So
far
at
this
point
of
jet
builder
2.0
it's
well.
B
I
guess
if
you
count
lines
of
code
and
files,
it's
like
16
000
lines
of
code
or
something
at
this
point.
So
it's
a
it's
a
very
substantial
piece
of
stuff,
which
I
don't
recommend
anybody
go
and
review
in
detail
like
don't
nitpick
on
code
style
or
anything
like
that.
I
put
it
there
more
or
less
just
so
that
people
could
take
a
look
at
it
and
see.
B
So
there
are
really
three
kinds
of
facilities
here.
I
think
I
have
talked
about
the
debugger
a
little
bit
on
one
of
my
previous
talks,
but
I'll
I'll
I'll
cover
it
again
now
because
it
has
changed
fairly
substantially
in
the
in
the
meantime.
B
So
the
first
thing
that
I'll
talk
about
is
actually
something
that
I
added
since
friday.
I
pushed
this
I
think,
last
night
or
the
night
before
or
something
like
that
and
added
it
to
the
pull
request.
So
previously,
if
you
were
going
to
add
a
new
type
into
jit
builder
or
a
new
operation
in
a
jit
builder,
you
basically
have
to
go
in
and
start
editing
the
class
files
for
operation
and
type
and
and
and
add
the
new
code
in
there
and
then
compile
it
all
together.
B
And
so,
if
you
were
going
to
maintain
that
as
a
as
a
person
trying
to
maintain
a
compiler,
that's
built
on
top
of
jit
builder
2
it
it's
a
little
bit
more
awkward,
because
you're
always
kind
of
folding
code
in
you'd
always
have
to
be
folding
your
code
into
the
existing
sort
of
base
classes
and
that's
a
little
bit
awkward.
And
it's
not
really
the
way.
I
wanted
it
to
work
ever
because
it
makes
it
hard
to
write
tests
for
that
kind
of
facility.
B
It
gets
hard
to
write
a
test
for
a
new
type
being
added,
because
I
have
to
actually
modify
the
class
in
order
to
add
a
type
and
then
compile
it
into
jitbuilder
2.
So
that's
kind
of
an
awkward
testing
story
and
I
didn't
want
it
to
be
an
awkward
testing
story.
So
what
I,
what
I
managed
to
get
done
this
week,
finally,
was
to
add
more
programmatic
sort
of
ways
to
add
new
types.
B
So
you
don't
necessarily
have
to
add
a
type
class,
but
you
can
add
a
new
type
object
that
can
then
be
referred
to
by
other
things
and
it
can
flow
through.
You
can
create
values
of
those
types
and
operations
will
naturally
be
able
to
work
with
with
those
values,
and
you
can
add
new
operations
in
the
same
similar
kind
of
way.
You
create
a
thing
called
an
operation
builder,
which
is
you
can
think
of
it.
B
Kind
of
like
the
objects
of
operation
builder
are
each
object,
corresponds
to
a
new
kind
of
operation.
So
it
understands
what
the
shape
of
that
operation
is
like.
Does
it
need
one
operand,
two
operands?
Does
it
need
a
literal
value?
Does
it
have
a
type
as
a
parameter,
those
kinds
of
things,
and
then
you
can
pass
the
values
that
you
need
to
those
operations
as
like.
B
There
are
a
few
convenience
mechanisms
that
make
it
easier
to
use.
So
there's
like
a
you
know:
if
you
have
an
operation
builder,
that
just
takes
two
values
and
produces
a
result,
then
there's
a
there's,
a
thing
you
can
call
that
looks
almost
like.
You
just
pass
two
values
in
it
and
it
produces
a
result.
B
So
it's
a
little
bit
more
awkward
to
use
it's
not
quite
as
simple
as
just
saying
add
of
left,
comma
right
and
you
get
a
value
back.
That's
the
the
result
of
the
ad,
but
it's
it's
not
too
bad.
I
would
say,
and
the
advantage
is
being
able
to
do
this
in
a
more
sort
of
programmatic
way
rather
than
having
to
having
to
actually
update
the
classes
themselves
is
actually
quite
quite
powerful,
where
I
think
it
will
be
quite
powerful.
B
I'm
going
to
talk
a
little
bit
more
concretely
about
this
in
the
in
the
in
the
demo
that
I'll
do
in
probably
after
this
slide.
I
think
it
is
my
last
life
all
right.
B
So
that's
that's
the
dynamic
types
and
dynamic
operations,
then
there's
a
second
new
thing
which
actually
it
took
a
long
time
to
piece
together,
because
it's
actually
a
fairly
complicated
thing
is
a
transformer
called
type
replacer
and
basically
you
create
a
type
replacer,
and
then
you
can
tell
it
to
do
one
of
two
things
or
actually
two
of
two
things
you
can
do
all
of
them.
At
the
same
time,
if
you
want,
you
can
tell
it
to
replace
one
type
with
another,
so
all
references
to
a
particular
type.
B
You
can
change
it
into
another
type,
and
that
includes
transforming
literal
values
that
includes
changing
operations
and
so
on.
So
the
the
use
case
that
I
was
kind
of
imagining
here
was
a
you
know.
What,
if
you
had
a
function
builder,
that
you
built
that's
kind
of
like
a
template
class,
so
it
has
like
a
placeholder
type
that
you
want
to
be
able
to
generate
any
kind
of
function
builder
that
operates
on
a
different
kind
of
a
type.
B
B
I'm
not
sure
how
common
that
use
case
is
going
to
be,
but
that's
sort
of
the
idea
I
had
in
my
head
when
I
created
it.
The
second
one
is:
is
a
an
operation
called
explode,
which
basically
is
is
designed
for
taking
a
user
type,
and
actually
one
of
the
things
I
should
have
mentioned
when
I
introduced
dynamic
types.
Is
that
when
you
define
a
dynamic
type,
because
git
builder
2
doesn't
sort
of
natively
understand
what
that
new
type
is
part
of
what
you
have
to
describe
to.
B
It
has
to
be
a
struct
type
and
basically,
that
struct
type
is
is
designed
to
communicate
to
jit
builder
what
it
is
that's
inside
one
of
these
new
types
that
you're
you're
generating,
and
so
this
explode
operation
is,
is
kind
of
taking
a
function
builder
that
refers
to
some
type,
some
user-defined
type
and
then
modifying
it
so
that
it
doesn't
actually
respond
to
that
type,
but
instead
refers
to
the
constituent
pieces
of
that
type.
B
B
It
would
expand
it
into
two
integers
called
x
and
y
and
well
name,
dot,
x
and
name
dot
y
and
then
anywhere
that
something
consumes
a
point.
Two
d:
it
will
actually
generate
two
copies
of
it,
one
which
operates
on
the
x
and
one
which
operates
on
the
y
and
by
default
it
just
replicates
the
operation.
B
So
for
an
add,
for
example,
if
you
had
to
add
two,
if
you're,
adding
two
values
of
type
point2d
in
this
example,
that
would
convert
to
an
add
of
the
two
dot,
x's
and
another
add
of
the
dot
y's.
And
then
it
would
remember
that
there
is
each
one
is
the
result
of
the
part
of
the
result
of
the
the
the
point
2d
that
got
produced
by
the
ad?
I
didn't
say
that
very
well,
but
hopefully
you
get
the
idea.
B
Basically,
you
get
like
left
dot
x,
plus,
left
dot
y
is
stored
into
result.
Dot
x
did
I
say
that
right,
left,
dot,
x
and
right
dot
x,
get
added
together
and
stored
into
result,
dot
x
and
then
left
dot,
y
and
right
dot
y
get
added
together
and
put
into
result.y,
and
then
the
type
replacer
basically
remembers
all
the
mappings
between
the
original
0.2d
values
and
the
constituent,
dot
x
and
dot
y
values
that
get
produced
as
it
replaces
the
operations.
B
Now,
that's
a
very
simplistic
view
of
how
to
do
replacement.
It
doesn't
have
to
be
that
simple.
In
fact,
there
are
examples
where
you
don't
want
it
to
be
that
multiplication
is
one
place
where
it
kind
of
gets
more
complicated,
so
there's
ways
of
augmenting
the
type
replacer
when
you're
specifying
how
the
dynamic
types
are
supposed
to
work
and
how
operations
are
supposed
to
work
that
allow
you
to
override
what
the
type
replacer
will
do
and
specify
new
functionality.
B
So
I'll
give
you
an
example
later,
which
has
complex,
where
each
complex
object
has
a
two
double
values:
real
and
a
match,
and
the
multiply
it
overrides.
How
multiply
works
to
do
the
you
know
real
times
real
minus
image,
times
image
and
then
also
to
for
the
for
the
imaginary
part
to
do
the
real
times.
Imagine
the
match
times
real
for
the
two
values.
B
Hopefully
that
was
somewhat
clear.
I
will.
I
will
talk
a
little
bit
more
about
this
concretely
in
a
few
minutes
and
as
I
say,
this
one
also
supports
all
the
dynamic
types.
In
fact,
it's
built
in
order
to
support
user
types
more
more
usefully
and
then
the
final
piece,
which
I
think
is
one
of
the
more
interesting
parts
and
was
actually
fairly
complicated.
To
get
going
and
working
properly
as
the
the
jb
db,
the
jet
builder
debugger,
so
this
is
basically
an
il
debugger.
I
think
I
demoed
this
briefly
at
one
of
my
other.
B
The
last
talk
that
I
gave
on
this.
Maybe
the
idea
here
is
that
you
have
a
function
builder
and
you
want
to
debug
it
without
necessarily
debugging
the
native
code
that
it
generates,
because
it's
harder
it
can
be
hard
to
to
map
back
from
the
native
code
to
the
jit
builder,
calls
that
you
made,
and
so
at
this
level
you
can
debug
at
the
il
level
and
be
able
to
you
know,
figure
out
what
the
mistakes
are
when
it's
making
mistakes.
B
The
idea
here
is
that,
rather
than
compiling
whether
you're
compiling
a
function
builder
and
generating
a
native
entry
point
that
you
didn't
call
the
native
code
and
it
runs
instead,
you
get
back
at
debug
entry
point
which
looks
exactly
the
same.
It's
actually
a
native
function,
a
callable
function,
point
pointer
that
you
provide
arguments
to
and
you
call
it,
but
once
it
calls
it.
B
What
you're
actually
calling
is
a
func
that
then
initiates
the
debugger
to
run
on
the
il
of
the
of
the
original
of
the
function
builder
and
then
it
actually
it's
a
fairly
complex
system
that
I
don't
really
have
time
to
describe,
and
I
won't
try
to
do
it
verbally
very
much
because
it
is
very
complicated.
I
probably
it
might
be
interesting
to
come
back
and
do
another
talk
on
that
at
some
point.
But
the
the
basic
idea
is
that
it
compiles
every
operation.
B
It
creates
a
little
function,
that's
for
single
stepping
through
each
particular
operation
and
the
reason
it
does.
That
is
so
that
you
don't
have
to
define
a
second
implementation
for
what
an
operation
does.
The
debugger
doesn't
have
to
be
taught
what
operations
do,
even
if
they're
dynamic
operations
that
you've
added
dynamically
to
it,
you
don't
have
to
tell
it
what
the
operation
does
you've
already
done,
that
by
implementing
the
code
generation
function
for
that
for
that
operation.
B
Basically
and
and
even
those
operation
debuggers
are
fairly
complicated
for
things
like
for
loop,
because
you
can,
you
know,
be
calling
out
to
other
other
other
builder
objects
which
contain
other
operations
that
you
might
want
a
single
step
through
so
they're
they're,
really
kind
of
like
little
co-routines
in
a
way
it's
kind
of
cool
actually,
but
I
won't
go
into
any
more
detail
on
that
I'll,
just
kind
of
show
you
how
it
works
at
a
as
a
debugger,
so
in
the
debugger
you
can
print
values,
you
can
print
the
values
of
values.
B
You
can
print
the
values
of
symbols,
even
if
they're
dynamically
dynamic
types
you
don't
have
to
teach
the
debugger
about
that.
You
can
single
step
through
the
il
you
can
set
break
points
based
on
operation
builder
or
times
you
can
break
before
or
after
an
operation
before
after
a
builder
object
or
at
a
particular
time,
so
it
as
it
as
the
debugger
executes
operations.
B
B
The
the
code
that
you
have
to
write
in
order
to
implement
a
dynamic
type
is
parts
of
it
will
integrate
into
the
debugger
itself
so
that
it
it
just
works,
and
one
interesting
benefit
of
this
is
that
it
actually
exercises
the
compiler
quite
a
bit,
because
it's
doing
these
fairly
complex
rewriting
of
the
individual
operations
of
the
target
function
builder.
So
in
the
course
of
debugging
a
matrix
multiply
operation
which
actually
is
reasonably
simple
and
doesn't
require
very
much
code
itself,
it
will
actually
compile.
B
I
think
it's
35,
maybe
36
different
functions,
all
of
which
have
different
kinds
of
builders
and
switches,
and
you
know
it
dynamically-
creates
a
data
type
to
represent
the
values
of
like
the.
What
a
value
can
be
based
on
that
kinds
of
types
that
are
referenced
in
the
function,
so
it
dynamically
creates
that
data
type
it
doesn't
exist
anywhere
in
the
debugger
itself.
B
B
It
had
some
complexity
associated
with
it,
but
I
got
better
at
it
after
a
while
and
that's
so
that's
so
that's,
basically
a
summary
of
what's
new.
What
I
thought
I
would
do
now
is:
let's
see,
stop
sharing
that
and
maybe
I'll.
B
B
Let's
see
how
do
I
want
to
go
through
this?
So
why
don't?
I
start
with
a
simple,
the
matrix
multiply
example.
So
I've
already
compiled
this,
so
I'm
just
gonna,
I'm
just
gonna
run
this
stuff
because
nobody
likes
watching
a
make
file
run.
B
But
basically
this
now
I
haven't
shown
the
matrices
so
this
this
this
example
takes
two
four
by
four
matrices
and
with
double
values
and
multiplies
them
together
and
and
it's
this
I've
set
it
up
so
that
it
it
generates
a
debug
entry
point.
So
it
jumps
into
the
debugger
immediately
when
you
call
the
generated
functions
and
that's
what's
basically
happening
here
and
for
some
reason
it
didn't
show
that
it
was
entering
the
debugger
for
the
first
time.
That's
weird:
okay,
first
inconsistency!
B
So,
basically,
when
you
call
it
it
essentially,
you
know
sets
a
breakpoint
at
the
beginning
of
the
method
and
stops
and
then
asks
you
what
you
want
to
do
so
the
debugger
has
you
know
it's
loosely
based
along
how
how
gdb
works,
but
it
provides
a
bunch
of
sort
of
nice
helper
things
that
you
can
do.
For
example,
if
you
want
to
look
at
the
il
for
the
method
that
you're
talking
about
you,
can
you
can
just
list
it
and
it
will
print
it
out.
B
So,
let's
look
at
this
briefly
again.
This
is
this
will
be
mostly
a
refresher.
I
think
for
for
people.
Who've
seen
this
before
so
I
mentioned
type
dictionary
is
a
thing,
that's
important,
because
it
holds
kind
of
all
the
types
that
your
that
you
work
with.
So
this
is
actually
an
additional
output.
I
added
it
probably
shouldn't
be
there,
but
if
the
type
dictionary,
basically,
everything
has
an
identifier
that
you
can
use
to
kind
of
search
through
here
very
easily.
B
It
lists
the
different
types
which
all
have
their
own
identifiers.
In
this
case,
it's
a
size
in
bits,
the
actual
name
of
the
type
and
and
what
kind
of
a
type
it
is.
So
if
it's,
a
primitive
type
or
pointer
types
are
defined
as
well,
and
if
it's
a
pointer
type,
for
example,
what
the
base
type
of
the
pointer
is
t6,
so
this
is
pointer
to
double.
B
T6
is
double
as
it
as
you'd
expect,
as
you
build
more
and
more
complicated
types
like
structs
and
fields,
and
so
on
are
all
added
into
this
type
dictionary
and
are
all
printed
out
as
part
of
this
output.
The
function
builder
itself
is
here:
it
has
a
name
map
mult,
it
has
its
own
id
function.
Builders
all
have
f
as
their
as
their
prefix,
so
f0
is
function
builder,
zero.
B
It
uses
a
type.
So
d0
was
the
dictionary
we
just
looked
at.
Has
you
know
a
set
of
parameters,
a
set
of
local
variables?
You
can
see
each
one
has
an
underscore
and
then
a
t
value
to
see
what
its
type
is.
Just
so
that
you
can
see
it,
and
those
are
the
types
back
from
the
from
the
type
dictionary
here
so
parameter.
B
The
local
variables
are
listed
along
with
their
names
and
then
finally,
you
get
into
the
operations
of
the
function
builder.
So
this
is
where
they're
listed
here
they
show
which
which
what
the
name
of
the
function
is.
That
they're,
in
which
builder
object,
which
builder
id
so
b0,
is
the
same
as
f0
here,
because
it's
a
function
builder,
but
it's
also
a
builder.
A
function.
B
Builder
is
a
builder,
so
b0
and
f0
are
the
same
thing
and
then
an
operation
with
an
id
to
indicate
what
operation
it
is
so
and
then
the
operations
are,
you
know,
sort
of
very
straightforwardly
written,
so
loading
symbol,
one
symbol.
One
here
is
the
same
as
parameter
one.
So
that's
actually
miswritten
sorry,
so
that's
loading,
a
loading
parameter,
a
loading
parameter
b,
loading
parameter
c.
B
The
the
loads
are
now
off
of
symbols,
not
strings
as
they
were
in
a
previous
version
of
jit
builder,
but
it
shows
the
name
just
as
a
convenience,
so
you
know
what
it
what
it
is
and
then
and
then
the
results
of
them
get
stored
into
values.
Things
that
don't
produce
values
like
this
for
loop
up,
don't
get
stored
into
a
value;
obviously,
but
they
consume.
They
still
consume
values
that
are
produced
earlier.
B
So
the
for
loop
here
loops
over
a
symbol
called
I,
which
is
s5,
which
you
can
see
here,
is
five.
So
this
is
the
outer
loop
and
then
it
goes
from
you
know:
const
zero,
to
const
and
or
to
the
n
value
by
one
and
the
body
of
the
for
loop
is
builder
one
b1.
So
if
you
want
to
find
out
what's
in
the
body
object,
then
you
have
to
go
and
look
at
bot
at
b1,
which
sets
up
the
the
second
loop
over
over
j.
B
It
has
a
body
of
b2
which
sets
up
the
the
the
innermost
loop
which
loops
over
k
and
has
a
body
b3
and
and
then
there's
the
innermost
loop,
which
is
doing
the
loading
values
from
the
it's
a
little
bit
hard
to
parse,
I'm
not
going
to
go
through
it,
but
basically
this
is
doing
an
array
access
into
into
the
a
array
and
array
access
into
the
b
array,
loading,
the
values
and
then
multiplying
them
together,
adding
them
together
with
some
and
storing
it
back
into
some.
B
There
are
some
some
other
kinds
of
flags
and
other
values
can
be
stored
about
the
builder.
So
what
its
parent
builder
is
whether
it's
bound
to
an
object
or
not?
I'm
not.
I
won't
go
into
that
in
this
in
this
talk,
but
that's
kind
of
a
key
feature.
A
key
characteristic
of
a
builder
is
whether
it's
bound
to
an
operation
or
not,
and
then
whether
it's
a
target
of
a
branch
or
not
it's
kind
of
another
interesting
thing-
that's
stored
there.
So
this
has
showed
us
what
the
what
the
il
actually
is.
B
So
then
we
can.
We
can
kind
of
single
step
through
this
thing
and
it
will
execute
an
operation
stop
before
the
next
one,
and
once
I
once
I
do
that,
so
I
can
print
out
a
symbol.
So,
let's
print
out
what
a
is
so
a
is
a
pointer
to
double
and
it
has
this
pointer
address.
So
this
is
the
address
that
would
have
been
passed
into
the
function
when
we
called
the
function,
that's
the
address.
B
We
can
also
verify
by
printing
the
value
of
v0.
We
can
see
that
it
has
the
same
value
now,
because
we
just
loaded
a
into
v0
and
we
can
keep
going
and
doing
that.
You
know
over
time.
We
can
collect
and
look
at
all
the
other
things
we
can
set
a
breakpoint
to
say
at
time
five,
and
then
we
can
continue.
B
It
will
stop
at
time.
Five
it'll
execute
three
more
things,
and
now
you
can
see
we're
at
time
five
and
we're
stopped
ahead
of
this
guy,
which
we
can
then
start
going.
We
can
single
step
into
a
for
loop,
so
that's
s,
and
then
that
goes
inside
the
the
body
in
this
particular
case.
As
long
as
we're
going
to
execute
the
body
it'll
go
into
the
body,
so
you
can
see
now
we're
in
b1,
which
is
the
body
of
the
of
the
for
loop
and
we
can
keep
executing
inside
there.
B
B
So,
let's
see-
let's
just
keep
going
through
here
until
we
get
back
out
to
our
for
loop.
B
That
was
not
the
example
I
was
trying
to
do
so.
Let
me
see
if
I
can
repeat
that,
let's
do
it
this
way,
so
what
I
was
trying
to
show
here.
So
that's
the
k1,
so
I'm
at
the
for
loop
k.
So
before
the
last
time
I
did
this,
I
used
s
to
single
step
inside
the
for
loop.
If
I
do
next,
it
basically
executes
a
whole
iteration
of
for
loop,
so
it
basically
it
single
stepped
these,
but
it
didn't.
It
didn't,
show
me
the
results
inside
here.
B
I
guess
in
principle
I
don't
I
didn't
really
need
to
in.
Like
sorry
in
a
real
scenario,
I
probably
wouldn't
list
these
executings
to
show
that
it's
executing
all
these
things.
It
would
just
do
it
like
in
a
real
debugger
scenario,
but
I
put
these
here
so
that
it's
easier
to
sort
of
follow,
what's
actually
happening,
and
so,
if
I
keep
doing
next
I'll,
execute
all
the
code
and
then
eventually
I'll
get
to
the
end,
and
I
can
continue
and
so
the
the
I
should
have
printed
this
out
first.
B
But
this
is
the
two
arrays
that
are
multiplied
together.
If
you
go
and
multiply
them,
you'll
find
that
that's
the
right
result
and
then
it
returned
and
the
code
finished
so
so
that's
kind
of
how
the
debugger
works
for
the
map.
Mult
that
works
with
double
now
double
is
a
double
as
a
type
that
actually
exists
in
git
builder
2.
So
it's
really
quite
simple:
to
see
the
code
that
was
used
to
write
that,
let
me
just.
B
B
That's
not
what
I
wanted
to
do,
but
anyway
it's
same
thing,
so
this
is
kind
of
the
code
that
I
had
to
write
in
order
to
to
do
this
code.
So
you
can
see
here's
the
and
I've
done
some
stylistic
stuff
here
to
kind
of
make
it
more
obvious
where
the
loops
are
and
so
on.
It's
not
necessary
to
do
this,
but
I
just
did
it
to
make
it
a
little
bit
more
visual,
but
here's
the
for
loop
over.
B
I
here's
the
the
for
loop
over
j,
here's
the
for
loop
over
k-
and
this
is
the
inner
loop
code,
which
calls
off
to
something
some
helper
functions
that
I
wrote
to
load
a
2d
this
loads.
A
of
I
comma
k
this
loads
b
of
k,
comma
j
right
and
and
remembers
the
value
of
that,
and
then
does
the
the
the
multiply,
add
and
stores
it
back
into
some.
B
So
this
is
kind
and
stores
the
result
in
2d
into
the
in
the
j
loop.
It
stores
the
sum
once
the
the
inner
product
has
been
and
once
the
dot
product
has
been
produced.
So
so
this
is
the
code
that
I
had
to
write
for
matrix
multiply.
So
the
next
thing
that
I
did
this
next
example
that
I
wanted
to
sort
of
to
do
was
to
say
what
happens
when
I
add
a
complex
type,
and
so
remember
I
mentioned
that
I
didn't
have
to
modify
any
of
the.
B
I
no
longer
have
to
modify
any
of
the
underlying
classes
of
the
jetbuilder2
implementation
in
order
to
add
a
new
type
or
to
add
a
new
operation.
So
there's
this
file
here
called
complex
support,
which
is
about
230
lines
of
code.
I'm
going
to
start
actually
at
the
end.
B
So
this
is
this
initialize
complex
support
is
something
that
gets
called
from
them
from
your
main
function.
If
you
want
to
add
these
things
in,
you
have
to
pass
in
what
the
type
dictionary
is
that
you're
going
to
use.
B
So
one
of
the
things,
as
I
mentioned,
is
that
you
have
to
create
a
layout
struct
to
define
what
the
shape
of
a
of
this
complex
type
is
going
to
be.
So
that's
all
that
this
code's
doing
it's
defining
a
struct
called.
You
know
this
is
just
a
name
that
I
used.
It
doesn't
have
to
have
this
form,
but
I
just
said
it's
the
complex
type.
Then
it's
it's
layout,
basically
using
a
kind
of
c
scoping
kind
of
naming
format,
it's
really
just
a
string,
so
it
doesn't
really
matter
what's
even
in
there.
B
I
could
call
it
x
if
I
wanted
to,
and
then
it
creates
the
the
two
fields
for
real
and
for
imaginary
and
adds
them
to
the
struct.
It
closes
the
struct
off
and
then
you
do
dynamic
type
create
and
you
pass
in
all
of
this
stuff-
and
I
haven't
shown
you
all
of
this
stuff,
but
the
result
of
that
is.
It
basically
creates
a
type
object,
a
dynamic
type
object
actually,
but
that
extends
type
and
called
complex,
and
then
I've
just
made
complex
into
into
a
global
variable.
B
You
don't
have
doesn't
have
to
be
a
global
variable.
That's
how
I
just
did
it
here
is:
is
it
can
be
accessed
from
anywhere,
so
anything
can
refer
to
complex
and
it
will
be
that
complex
type
object.
Now?
What
are
some
of
these
other
things?
So
I
you
know
you
pat
you,
get
tell
it
which
dictionary
this
type
is
supposed
to
go
into.
You
give
it
a
name
complex
what
its
size
is
going
to
be.
B
So
in
this
case
it's
going
to
be
two
double
objects,
so
it's
128
bits
and
then
some
other
interesting
things.
I
I
mentioned
layout
here.
What's
this
this
complex
printer
thing
is
just
a
little
piece
of
code
that
can
print
out
a
value
of
the
complex
type.
So
it
gets
it's
a
sort
of
a
it's,
a
special
little
piece
of
code
that
you
write
to
extend,
and
so
you
get
past
a
text.
Writer
text
writer
is
just
a
like
a
logging
kind
of
class
that
makes
it
easy
to
print
things
out.
B
You
get
past
what
the
type
is
and
you
get
a
void
star
pointer
to
what
the
actual
vowel
to
the
value.
That's
actually
there.
So
the
first
thing
is:
it
asserts
that
this
is
the
definitely
the
complex
type
that
we
got
passed
so
that
we
can
get
past
something
else
and
then
it
basically
just
redoes
a
reinterpret
cast
on
the
pointer
p
to
a
to
a
a
complex
value
and
then
prints
it
out
as
the
real
part
plus
I
times
the
imaginary
part.
B
So
that's
all
that
was
this
complex
type.
Exploder
is
part
of
the
support
for
type
replacer
to
be
able
to
replace
values
of
type
complex
with
other
things.
So
similarly,
it
has
kind
of
a
defined
form
signature
that
it
accepts
this.
So
it's
going
to
explode
a
literal
value
that
you're
passed
into
its
constituent
pieces,
and
so
I'm
not
going
to
go
through
this
in
detail,
but
basically
it
breaks
apart
the
literal
value
and
creates
two
smaller.
C
B
Similarly,
there's
a
another
type
of
thing
called
a
replacer
which
is
used
for
this
is
how
you
augment
some
of
the
some
of
the
other
translation
stuff
here.
So,
in
particular,
remember
I
mentioned
multiply,
is
one
of
the
ones
that
you
have
to
change.
If
you're
doing,
if
you
are
trying
to
multiply
two
complex
values,
you
can't
just
do
you
know?
B
The
real
part
of
the
result
is
the
is
a
real
left,
dot
real
times
left
dot
right
and
the
imaginary
part
of
the
result
is
right:
dot,
imaginary,
left,
dot,
imaginary
times,
right.imaginary
right,
that's
not
the
right
and
you
won't
get
the
right
answer
if
you
try
to
define
complex
multiplication
that
way.
So
this
is
a
this
is
a
function
that
will
get
called.
B
If,
if
an
operation
has
complex
types,
it
will
be
passed,
it
will
be
passed
to
this
thing
to
first
see
if
there's
something
it
should
do
beyond
what
the
default
implementation
does,
and
so
all
it's
doing
is
detecting
is
there?
Is
it
a
multiply
operation
and
if
it
is,
are
they
both
complex
values
and
if
they
are,
then
it
does?
The
cross
multiply
that
I
talked
about
earlier.
Everyone
knows
how
how
multiplication
is
defined
for
complex
numbers
and,
and
so
it
manages
to
it.
B
It's
given
a
builder
object
and
it
just
places
the
results
into
that
builder
object
and
then
does
some
other
things
to
to
help
with
the
mapping
and
then
finally,
there's
a
thing
called
a
registrar
which
is
used
in
conjunction
with
the
type
graph
to
to
basically
say
what
kinds
of
operations
are
valid
with
this
with
this
class,
and
so
this
gives
you
a
call
back
from
the
type
graph,
and
it
gives
you
it
gives
you
the
actual
type
graph
that
you
can
use
to
register
valid
operation
combinations.
B
So
you
can
say
add
of
a
complex
and
a
complex
gives
you
a
complex,
add
of
a
complex
and
a
double
gives
you
a
complex,
et
cetera,
and
so
these
are
all
combinations
of
types
that
don't
dip
builder
doesn't
know
about
itself
because
it
doesn't
know
about
complex
itself.
But
now
it
knows
that
these
combinations
are
legal,
and
so,
if
it
sees
a
mole
with
a
left
operand,
that's
a
complex
and
a
right
operand,
that's
a
double!
B
It
knows
that
that's
a
valid
operation
and
it
will
produce
a
value
of
complex
type
and
you
can
add
all
kinds
of
things
I
I
put
in
there
there's
some
other
things
that
I
could
have
put
in,
but
they're
not
really
supported
right
now.
So
it's
like
there
are
all
kinds
of
other
stuff
that
you
can
you
can
put
in
here
and
that's
basically
that
for
for
the
type
and
then
I
also
defined
a
couple
of
new
operations.
B
So
the
first
one
is
to
put
into
insert
a
const
complex
operation.
Now
this
probably
could
have
been
folded.
Now
that
I
have
literal
values
in
the
il,
I
could
probably
just
have
a
const
il
function,
which
you
know
accepts
comp,
a
complex
literal
value,
but
but
I'd
show
that
and
do
it
that
way
right
now,
so
this
const
complex
builder,
is
you
create,
like
I
said
you
create
an
operation
builder,
you
you
use
this
new
action
thing.
B
Basically
get
builder
2
will
assign
it
a
new
value
to
correspond
to
this
kind
of
operation
and
give
it
a
name
const
complex.
So
when
it
gets
printed
out,
this
is
the
name
that
will
get
printed
out
in
the
in
the
il,
and
then
you,
you
kind
of
describe
what
the
shape
of
this
builder
object
is,
and
it's
kind
of
a
fluent
api
here.
So
you
know
it's,
it's
got
one
result.
The
result.
Type
is
complex.
B
It
has
one
literal
as
a
as
a
it
takes
one
literal
as
a
kind
of
a
literal
operand
and
then
similarly
to
how
the
dynamic
type
stuff
had
some
of
these
other
like
complex
printer
exploder,
replacer,
there's
kind
of
there's
a
printer
for
for
operations
and
there's
a
kind
of
an
expander
thing
which
helps
with
the.
How
do
you
replace
a
const,
complex.
B
B
I
also
defined
another
operation
which
I
didn't
actually
even
use
anywhere,
but
just
to
show
that
it
could
be
done
a
different
example
of
doing
it.
So
I
got
a
conjugate
operation,
so
another
sort
of
complexity,
kind
of
operation.
So
it's
got
one
result
which
is
going
to
be
of
type
complex.
It
has
one
operand.
That
means
a
value
that
it
would
take
and
it
has
an
expander
and
a
printer
and
it-
and
this
one
also
has
a
registrar.
B
So
this
one,
this
registrar,
is
basically
saying
that
there
are
some
combinations
of
operands
that
need
to
be
tested
here,
and
so,
in
this
case
you
can
see
it
registers
a
valid
operation
for
this
conjugate
builder,
which
I
had
to
get
its
action.
B
I
have
to
get
its
action
from
it
and
then
it's
it
takes
an
operand
of
type
complex
and
produces
a
result
of
type
complex,
and
then
that's
basically
it
that's
the
that's
what
you
have
to
do
to
add
one
new
type
and
two
new
operations
into
the
world,
and
so
with
just
this
code.
Just
this
230
lines
of
code,
type,
replacer
code,
generator
and
and
debugger
all
know
exactly
what
to
do
so
without
modifying
debugger
I
can.
B
All
right-
or
maybe
I
can't
that's
unfortunate-
that's
gonna
blow
my
my
demo
all
right
shoot
unless
it
changed
something.
Yes,
last
night
that
I
didn't
anticipate
all
right.
This
used
to
work,
but
at
least
it's
going
to
show
you
what
the
what
the
code
is
that's
being
generated
here.
So
honestly,
this
is
exactly
this
almost
exactly
the
same
code,
but
the
type
dictionary
has
so
I've,
given
it
a
new
name.
B
So
you
can
see
there's
a
few
new
things
here
in
the
type
dictionary
compared
to
what
we
had
before
the
complex
layout
type
has
been
added
right,
the
one
that
we
created
in
that
initialized
complex
support
right.
So
it's
a
struct
type,
which
has
two
fields
which
are
dictated
by
t10
and
t11
that
the
various
ones
that
offset
zero,
the
l
is
in
the
offset
64..
B
So
eight
bytes
in
t10
is
a
is
the
real
part
which
has
a
field
type
of
t6,
which
is
a
double
and
then
t11
is
the
imaginary
part
offset
64.
B
B
We
got
a
pointer
to
complex
type
that
were
used
here
as
well,
and
so
in
terms
of
what
the
function
builder,
what
changed
in
the
function
builder,
when
we
were
doing
this
is
now
the
parameters
to
the
function
had
to
change,
because
now
you're
taking
pointers
to
complex
arrays,
not
pointers
to
double
arrays,
so
we're
using
that
t13
type,
the
pointer
to
complex
the
values,
like
sum,
are
now
of
type
t12,
so
they're,
the
t12
is
the
complex,
primitive
type,
so
t12
itself
doesn't
know
about
real
and
imaginary
parts.
B
C
B
Change
that
was
needed
in
this
whole
code.
Other
than
you
know,
sort
of
updating
the
type
references
to
use
complex
instead
of
double
is
to
change.
The
initialization
of
the
sum
variable
that's
used
for
the
dot
product
in
the
inner
inner
loop
is
now
starts
off
as
a
const,
complex
value,
which
gets
printed
by
our
little
printer
and
uses
the
name
of
the
operation
that
we
specified
and
other
than
that
the
code
is
identical.
B
It's
it
just
works
with
values
uses
the
original
jit
builder
calls
it's
quite
convenient,
that's
kind
of
annoying
that
that
happened,
and
it's
reproducible
too.
So
I
won't
be
able
to
show
you,
unfortunately,
the
debugger
experience,
but
basically,
once
I
fix
this
problem,
the
the
debugger
will
just
work
it.
B
It
simply
uses
all
of
the
definitions
that
were
provided
to
generate
code
and
to
do
the
type
replacement
and
the
the
way
the
debugger
operates
it.
B
Can
it
basically
queries
every
op
code
and
and
dynamic
operations
can
answer
those
queries
just
as
well
as
built-in
operations
can
and
the
type
replacer
automatically
causes
the
complex
type
to
be
exploded
into
two
doubles
wherever
it
gets
used
and
it
converts
all
of
the
all
of
the
different
operations
appropriately
to
create
all
of
the
operators,
and
so
you
can
single
step
through
that
code,
and
I
wish
I
could
show
it
to
you.
You
can
print
print
a
a
a
symbol
that
has
a
complex
type
and
it
will
print.
B
Does
that
contact
it'll
it'll
do
the
same.
You
know
real
part
plus
imaginary
times,
the
imaginary
part,
if
you
print
values
that
they'll
do
the
same
thing.
You
know
single
stepping
all
that
stuff,
just
kind
of
works
out
of
the
box.
So
it's
it
until
I
ran
into
this
assertion.
I
thought
everything
was
working
quite
quite
handily
with
that.
B
So,
okay,
so
now,
so
that's
the
end
of
the
sort
of
demo
and
doing
with
an
assertion.
Now
I
guess
so.
Where
am
I
going?
Where
is
where
do
things
go
from
here?
So
I
have
created
the
pull
request.
Obviously,
it
needs
to
be
updated,
so
please
don't
merge
it
until
I
fix
this
assertion
the
what
I'm
hoping
to
do
is
or
that's
what
I,
what
I'd
like
to
propose
to
do.
B
I'd
like
feedback
on
this,
I'm
thinking
to
create
a
project
at
the
github
at
our
github
repo
for
this
for
the
jit
builder
to
work
and
then
start
tracking
all
of
the
different
things
that
would
need
to
be
done
in
order
to
get
it
both
integrated
into
the
code
base
as
well,
as
you
know,
begin
to
get
worked
on
by
me,
or
whoever
else
wants
to
help
out
with
this.
B
There
are
a
number
of
areas
that
that
need
improvement
right
now,
so
there
are
some
things:
it's
definitely
a
prototype
right
now.
This
is
not
something
that
I
would
recommend
you
know
should
be
used
aggressively
by
anyone,
even
though
it
does
have
some
fairly
good
and
fairly
broad
functions.
B
Let's
see
some
of
the
things
that
I
would
like
to
fix
about
it,
but
don't
necessarily
have
to
be
done
right
away.
So
I
guess
you
know.
Maybe
I
should
focus
on
things
that
should
be
done
right
away
so
right
now
the
jit
builder
2
implementation
is
completely
unintegrated
into
omar.
B
It's
sitting
in
a
directory
underneath
the
jit
builder
directory
right
now
called
jbl.
It
has
a
little
small
makefile
in
it
that
assumes
that
you've
built
the
jit
builder
library
somewhere
else.
I've
only
ever
run
it
on
mac
os,
but
I
there
isn't
very
much
about
it.
That's
mac
os
specific!
B
There
are
a
number
of
little
code
samples
in
there
they're
very
poorly
named,
but
they
do
things
that
exemplify
how
it
works.
There
is
the
complex
support
case
which
doesn't
quite
work
with
the
debugger.
Yet,
let's
see
so,
I
think,
if
we're
going
to
add
this
into
the
omar
project,
I
think
it
would
be
good
to
at
least
have
it
integrated
into
the
into
the
cmake
build
system.
So
that's
one
thing
that
should
probably
be
done.
You
know
either
either
before
or
as
a
first
priority
once
it's
merged.
B
While
I
I
don't
want
to
use
that
as
an
excuse
at
some
level,
if
we're
gonna
go
through
and
and
try
to
fix
everything
in
that
sixteen
thousand
lines
of
code,
it's
gonna
be
a
long
time
before
it
gets
absorbed
into
the
code
base
in
a
long
time
before
anybody
can
help
me
or
help
like
help
work
on
it.
Basically,
so
I
would
welcome
people's
thoughts
on
how
you
would
prefer
to
integrate
this.
I
know
it's.
It
is
a
big
pull
request
and
I'm
generally
not
a
fan
of
big
pull
requests.
B
So
I'm
I'm
a
little
bit
conflicted
about
this
one
I
have
to
say,
but
I
do
kind
of
want
to
get
this
into
the
code
base
and
accessible
to
people,
and-
and
you
know
if
anybody
wants
to
help,
I
would
very
much
welcome
help
with
that
and
maybe
I'll
just
stop
there.
Basically,
since
I've
been
talking
for
almost
an
hour
now
and
and
see
if
people
have
thoughts
on
the
integration
question.
A
B
A
No,
that
was
very
interesting
mark
yeah.
I
don't
have
any
specific
thoughts
on
the
on
the
integration
aspect
of
it
I
mean
what
you
propose
seems
you
know
seems
reasonable
to
me,
certainly
like
the
idea
about
creating
a
project
to
track
the
different
pieces
of
work
that
need
to
get
done
as
well.
In
fact,
we
should
probably
maybe
even
be
doing
a
little
bit
more
of
that
of
the
omr
project
for
other
things,.
B
Yeah,
so
I
mean
one
of
the
areas
that
I
really
want
to
put
some
focus
on
before
trying
to
expand
the
implementation.
Very
much
further
is
to
put
a
more
of
a
stronger
emphasis
on
writing
tests
for
it.
You
know,
that's
that's
kind
of
a
trap
that
we've
allowed
ourselves
to
get
into
with
the
omar
compiler
technology.
You
know
back
way
back
when
it
was
first
created.
B
One
of
the
reasons
why
I
did
the
dynamic
type
and
dynamic
operation
work
was
to
try
to
facilitate
the
writing
of
tests
in
a
more
sort
of
easy
to
control
way
with
this
code
base,
and
so
I
do
think
I
want
to
spend
some
time
thinking
about
how
to
better
test
both.
What's
there
already
as
well
as
you
know,
sort
of
thinking
about
how
we
continue
to
grow
the
testability
of
the
code
going
forward
so
that
we
can
keep
a
better
eye
on
correctness
throughout
this
whole.
A
Any
questions
from
mark
on
the
design
or
how
it
works,
or
anything
like
that.
C
Enjoyable
talk,
so
one
of
the
things
that
will
be
definitely
helpful
is
the
debugger.
I
think
we
have
been
sort
of
talking
about
that.
You
know
internal
meetings
for
students,
it's
very
beneficial,
and
you
mentioned
my
question-
is
I
guess,
regarding
reference
to
mli
that
you
mentioned,
so
you
you
also
in
our
private
discussions.
You
also
mentioned
that
some
future.
C
Will
be
sort
of
looking
at
data
intensive
computing,
for
instance,
like
employer,
can
do
data
flow
graphs
and
also
yeah
various
loop
optimization.
Do
you
have
our
like
polyhedral,
family
tips
and
so
on?
So
do
you
have
any
thoughts
like
in
future,
maybe
2.5.
B
Well,
I
think
that's
part
of
expanding
the
api
going
forward.
I
mean,
I
think
I
have
ideas
for
creating
a
dataflow
engine.
B
That's
actually
one
of
the
very
you
know
in
addition
to
testability,
there
are
lots
of
things
I'd
like
to
do
next,
but
in
addition
to
testability
one
of
the
things
that
I
think
would
is
important
to
to
to
create
as
a
data
flow
engine
for
the
jit
builder
il
it
has
some
interesting
characteristics
that
well,
I
think
in
it,
have
some
interesting
opportunities
and
also
interesting
challenges
in
trying
to
do
data
flow
efficiently
across
a
function
builder
and
jit
builder.
B
But
one
of
the
main
reasons
to
do
that
is
to
is
to
implement
a
reaching
definitions.
B
You
know
a
reaching
definitions,
analysis
that
can
be
used
to
further
enhance
the
the
correctness
checking
for
when
you're
producing
jit
builder
il
and
making
sure
that
when
you
produce
a
value
and
when
you
consume
a
value
that
there's
definitely
a
flow
edge
between
between
all
the
consumptions
of
a
value
and
at
least
some
definition
of
that
well,
there
can
only
be
one
definition
of
a
value,
but
we
can
do
that
for
local
variables
as
well,
making
sure
that
values
are
available
when
you're
using
them
right
now.
B
Jitbuilder
doesn't
provide
any
kind
of
help
in
that
regard,
and-
and
it's
a
you
know,
it's
a
relatively
well
understood
problem,
so
I
think
we
should
be
able
to
to
you
know
do
that
reasonably
quickly,
but
it
has
like
a
use.
It
is
it's
a
usability
improvement
rather
than
sort
of
a
performance
improvement,
and
I
think
once
you
once
you've
implemented
a
data
flow
engine,
then
that
opens
the
doors
to
start.
B
You
know
implementing
all
kinds
of
different
analyses
using
that
engine
and
and
what
I'd
really
like
to
push
on
is
trying
to
find
ways
to
raise
the
level
of
the
the
api
that
you
have
to
use
to
work
with
the
data
flow
engine
and
to
work
with
compiler
analyses
so
that
you
can,
you
know,
write
right,
analyses
and
optimizations
and
transformations
that,
where
you
get
as
much
of
the
kind
of
mechanics
of
things
out
of
the
way
as
possible
and
be
able
to
focus
on
what
is
the
problem
that
you're
trying
to
solve?
B
You
know
it's
it's
it's
very
much
early
days
in
terms
of
that
kind
of
a
thing,
but
I
think
that's
a
theme
that
I
think
is
important
from
the
from
jet
builders.
You
know
origins.
B
The
idea
has
always
been
to
try
and
make
it
easier
for
people
to
do
these
kinds
of
things,
and
I
think
one
of
the
ways
to
do
that
is
to
raise
the
level
of
interaction
with
it,
so
that
you
don't
have
to
pay
attention
to.
Quite
as
many
details
pay
attention
to
the
details
that
you
need
to
pay
attention
to
and
and
hopefully
have
the
the
system
do
a
good
enough
job
with
the
details
that
you
don't
need
to
that
aren't
sort
of
germane
to
the
problem.
You're
trying
to
solve.
C
Yes,
raising
the
level
of
abstraction
it's
like
for
this
kind
of
problems,.
C
B
So
I
think
so
I
mean
actually
you
know
just
since
supra
you're,
the
one
that
asked
the
question
or
got
me
talking.
So
the
the
the
notion
of
trying
to
to
express
sql
queries
is
one
of
the
one
of
the
things
that
got
me.
Thinking
down
this
line
of
extensible
types
and
extensible
operations
and
being
able
to
have
the
debugger
just
naturally
work
with
those
things
without
having
to
really,
you
know,
implement
a
whole
raft
of
new
code
just
to
be
able
to
debug
it
right.
B
B
A
B
D
Oh
sorry,
I
was
muted.
I
had
a
question.
D
B
D
And
one
of
the
objectives
of
the
microchip
project,
initially
that
we
kind
of
still
have
on
the
roadmap,
was
the
idea
of
a
microjit
and
omr
one
of.
B
D
B
D
B
D
B
E
D
I
was
wondering
if
you
could
speak
about
how
someone
might
take
jit
builder
and
then
augment
it
to
have
more
than
one
code
generator
and
maybe
get
kind
of
like
two
compilers
for
one
out
of
the
same
gif
builder.
B
Yeah,
so
I
mean
basically
you
what
you're
I
mean,
there's
a
there's,
a
classic
jit
builder
too
called
code
generator
that
should
really
be
called
jit
builder
code
generator.
But
I
got
a
little
bit
tired
of
saying
jit
builder,
all
the
time.
I
guess
it
could
be
jb
code
generator,
but
I
mean
essentially
it's
a
it's.
B
It's
a
class
that
visits
over
the
il
of
the
function
builder
and
as
it
visits
each
operation,
it
makes
calls
and
digit
builder,
the
digit
builder
one
calls
the
api
calls
right
and,
and,
like
I
said
any,
you
could
write
a
different
code
generator
that
would
directly
generate
il
from
for
the
omr
compiler
you
could
in
principle
you
could
write
a
code
generator
that
would
generate
llvm
ir.
You
could
generate
a
code
generator
that
would
generate
java
byte
codes
in
principle
right.
It's
all
it
is,
is
just
you
know.
B
As
long
as
you
can,
you
can
imagine
the
transformation
framework
like
what
kind
of
runtime
support
you
need
and
what
kind
of
and
what
you
would
need
to
translate
each
chip
builder
il
call
into
you
can
generate
whatever
you
want.
You
could
generate
even
c
code
if
you
wanted
to.
D
Yeah,
it
may
be
specifically
the
work
of
what
harpreet
will
be
working
on
in
the
future,
but
yeah.
I
would.
I
would
love
to
arrange
for
that
kind
of
a
talk.
B
B
And
the
advantage
of
that
is
that
you
could,
even
if
you
wanted
to
you
could
selectively
add
you
know
even
optimization
passes
and
digit
builder
two,
and
if
you
want
a
micro
jet,
that's
like
a
bare
bones:
micro
jet.
You
could
just
do
that.
If
you
want
to
be
more
elaborate,
you
could
do
more
elaborate
things.
B
I
had
I
had
to
make
a
few
small
changes
inside
jitbuilder
itself,
two
in
order
to
support
kit
builder
two
and
some
of
the
in
particular
the
debugger,
like
the
creation.
Excuse
me
the
dynamic
type
that
the
debugger
creates
required.
A
few
changes
in
the
in
the
way
that
structs
are
defined
in
jit
builder.
I
don't
think
I
changed
anything
fundamentally,
but
I
kind
of
loosened
some
of
the
rules
for
being
able
to
define
structs
that
have
kind
of
union
union
fields
in
them.
B
And
I
think
the
kind
of
thing
that
the
debugger
does
there
is
actually
something
that
you
know
another
another
piece
of
code,
the
interpreter
builder
stuff
that
charlie
gracie
and.
B
Those
that
kind
of
stuff
can
can
also
be
implemented
in
a
similar
kind
of
way.
So
I
think
things
like
interpreter
builder
and-
and
you
know,
sort
of
constructing
your
own
interpreter
and
jit
using
jitbuilder
2
for
other
language,
I
think,
is
going
to
be
a
lot
easier
given
what's
in
jit
builder
2
than
than
it
has
been
in
the
sort
of
previous
version
of
the
the
api.
E
E
Hi,
it's
georgie
and
I
just
have
a
last
minute
question
and
thanks
mark
by
the
way
for
introducing
the
showing
this
work,
because
I
actually
needed
llgb
before
I
knew
that
not
lgb
ll
the
debugger
before
you
introduced
it
yeah.
So
I
didn't
know
I
needed,
but
it
turns
out.
I
did
so.
I
wanted
to
ask
rather
like
your
vision,
question
about
whether
jude
builder
will
support
like
is
philosophically
against
or
it
is
in
plans
to
support
persistence
like
aot
style
and
working
on
aot.
E
But
I
just
wonder
if
the
like.
Currently,
we
are
in
our
home
runtimes
we're
accessing
it
through
by
extending
jit
builder
api,
but
the
code.
But
the
discussion
was
started
like
some
time
ago,
but
it
was
published
for
some
like
we
decided
to
focus,
but
on
persistence
will
be.
There
is
that
builder
plan
to
support
persistence,
or
not
quite.
B
B
I've
actually
kind
of
argued
with
myself
over
the
name
jet
builder
as
well,
just
because
it
it
seems
to
imply
that
dynamic
just
in
time,
compiler
is
sort
of
more
important
to
it
than
other
sort
of
compiler
kinds
of
applications,
and
I
don't
think
that
it
needs
to
be
quite
so
tied
to
jits,
although
I
probably
won't
change
the
name
at
this
point
just
because
it's
been
used
for
so
long,
but
but
I
I'm
perfectly
happy
to
consider
you
know
extensions
to
the
api
to
handle
different
types
of
you
know:
code
storage,
kinds
of
operator
options.
B
I
know
that
that
I
know
the
conversation
you're
talking
about
and
it
did
get
kind
of
paused,
and
I
know
I
haven't
been
as
responsive
in
there
as
I
as
a
as
I
probably
should
have
been,
but
but
yeah
we
can
revisit
that
that
conversation
certainly
going
forward.
E
B
B
B
Yes,
I
swear
that
was
working
last
night
or
the
night
before,
but
anyway,
it's
the
way
of
the
demo
gods.
I
guess.
A
Yeah,
thank
you
mark,
so
I
guess
there's
no
other
questions.
We'll
conclude
today's
call
and
we'll
meet
again
in
two
weeks
thanks.
Everyone
thanks
mark.