Last time we looked at the problem - or
the great advantage, if you like - of using
intermediate codes as a staging point in
our compilers. And we spent a lot of
effort talking about how to improve your
compiler, but still on the same machine,
but with an intermediate code step. 
I would strongly advise you to watch that
video first because what we're now going
to find, in this next one we're doing, is
we're just changing the rules slightly.
instead of B* (improved binary)
we're moving from B' to B''.
We are generating a different
binary for a completely different
architecture. But we are using the front
ends that we've already established that
get us as far as intermediate code. What
we're now talking about is: "How can I
produce a new back end?" And you will find
that the diagrams I draw are remarkably
similar to the ones on a single machine,
for improving yourself. So do watch that
one first unless you're absolutely sure
that you've taken every single thing it
said(!) And then we can go on the adventure
of just how intermediate codes are
pretty well vital for porting compilers.
In the last video we used this as our
home base - if you like - our master
referral point for everything that we
were trying to do. We had source codes
for two vital pieces and then compiled
versions of them over here.
What we're going to find with this one is, yes,
we'll still be having an H compiler
written in H producing intermediate code
the thing that's going to change this
time is instead of saying things like:
"Take my intermediate code and write a
compiler for it that produces B'
I'll be saying: Take that, write it in
high-level language of your choice but
make the binary it produces be for a
brand new machine - that we can't wait to
get some software working on.  So, that B'
will start becoming B''.
And whereas, in the previous episode, we
were obsessed with getting really high
quality B', and [then] we got to B'*
even better! We're not going to be as
obsessed this time with improving the
quality of any binary - although that's
possible in the end - what we are
concerned with is this time saying: "I
don't want better binary for the old
machine I want some brand new binary B'',
for the new machine, and I
don't care how rubbish it is initially, I
just want to get some binary for the new
machine working and established. What we
can say about any cross compiler is it's
going to look like this. It's going to be a
chosen higher-level language; it is going
to originally be written in B' but
it's going to produce B''.
And if you want an actual
example - referring back to previous
episodes - for this: we were in a situation
where our H was 'C'. The original
binary it was running on - on a PDP 11 - and
our B'', over here, was Z80 binaary.
So, there you are then, that's a
generic form of any cross-compiler.
There's my actual example of my first
encounter with cross-compilation.
The bigger question is how does this help
you? If you start saying: "Well, instead of
just sending boatloads of code across to that 
new machine - and having no real control over it -
what happens if I want to, sort of, you
know ... yeah, I did think of it in
those terms, send an Expeditionary Force
onto the foreign machine, set up a few
outposts, do a little bit more on the
foreign land
than just unload the binary that's been
sent on a boat. Actually set up a 'binary
factory' on your newly conquered land, you see? 
Well, yes, and actually, I mean,
intermediate code helps that. This is the
one new piece of software you need to
write, since everything is working to
intermediate code now. It's a
non-optional intermediate stage. Your
front end of your compiler
will quite cheerfully be producing 'I'. 
All you need to do, to get something started
on your new machine, is to write
something in a high-level language which
takes intermediate code but produces B''
at the other side.
So, that's your intervention point. Let me
say again it is a worthwhile step to do.
Because the difference in detail between
a PDP-11 binary and a Z80 binary is
pretty considerable. And if you don't use
intermediate codes you have to go right
back to square one and think: "Oh!  I've got
to create a binary from scratch, all over again".
But I've got to get in there - in that
code generator trying to throw the old
one away" You say is there anything I can
learn from this? And just out of nowhere
bridge the gap between your high-level
language and your new B''
which you've  got. What we're saying is, it's
a lot simpler if you break it into two
parts. Leave the front end as it is, on
the other machine, for the moment and
it's producing I at you, like mad. What you need
is a new back end. So, we're in a
situation, now, that as I've made clear
... any cross-compiler is going to be
running on your old machine, to start
with, producing binary code for some
other new machine. So what we've now got
to do is revisit all we did before.
We said: "Here's how the transformation chain
works with intermediate codes." If all you
want to do is to improve the quality of
the coding for your home machine B'.
This is "similar but different" now. 
We're going to say: "Instead of producing
better quality binary for this home
machine we want to produce brand-new
binary, but for a foreign and different
machine." And we want to know exactly what
processes we're going to have to go
through. Similar to before, but a little
bit different in detail. So, hold tight
this is what we have to do. We've got
this new piece of software something
that takes an intermediate code we know
the spec of that. We can write it in H,
our chosen high-level language. It's always a
good thing.
But we know that, eventually, that thing
has got to be compiled out, down to
binary, but it's going to produce B''.
We take our new piece of
software and we compile it. Now notice
that is my original 'H-to-Intermediate
compiler' that runs on the old machine,
but I'm using it to compile this
new thing. We know what we're going to get
and I write it out up here. H gets
translated into I, via this. So, we are
going to end up with I, B''- but
the H has gone through to I. So, we've now
got a piece of software that takes in I,
is running on I, but produces B''.
Don't forget that there is - as the
fourth component in our chain, always
available to us - an intermediate code
compiler that takes it down to binary.
Now we want, back from the beginnings of
time, the original component number 4,
which is that. So, I've written an I
interpreter, in I, that  produces B''
But, from work on the old machine, I've
got something that takes I runs on B'
[and] produces B'. net result of
all of that  what do we end up with?
We end  up with I, B'', B'.
So, that is the result, if you like, of
compiling the intermediate code right
down to binary. We've now got a really
- well it's close to being wonderful but
not quite (!) - it's an Intermediate Code
Compiler. It produces super duper new B''
for the new machine. 
[The] slight drawback is it runs on the binary for
the old machine [B']. So  we're almost there.
We've established our bridgehead but we've not
quite invaded yet because what we'd love
to do is to get this thing down here
saying B''. It's just a
question again of feeding the right
thing back into itself. We've got I,
written in I, producing B''.
We've compiled that with an I, B', B'
and we've ended up with this:
Intermediate Code producing B''
written in B'. What do you do now that
you've got this executable answer?
Final stage: feed it back to itself. Take the
original thing and do it one more time
If you take this look: I, I, B''
and feed it into your newly created
binary I running on B prime .... hurrah!
let trumpets sound! You have finally
achieved what you wanted to achieve -
which is that goes through there and you
end up with I, B'', B''.
In my original set-out of
pieces of componentry you need, I had 1,
2, 3 and 4. And, looking back at
it now, what we have got is that this is
the equivalent of [piece] 4. Look, back in the
early days when we only had one machine,
you had needed an I compiler, to take I
into B' ... B' there.
What we've now done with all this
jiggery-pokery with T diagrams is: we
have produced ourselves an I, B'', B''
It is totally on the new machine now.
It doesn't rely on B' at all.
Now. those of you who have
soldiered - how should we say? -  really
soldiered hard on the previous episodes
of this, will now recognize that this is
the same old story. You want to have the
binary you are running on being of the
same quality as the best binary you can
produce. Except now it's not so much 
'best binary', it's 'new binary'. Rather than
generating new binary for the new
machine off the old hardware can you
"feed yourself back to yourself" enough so
that eventually you end up with
something that is totally happy on the
new machine and doesn't need old machine
support in terms of B' at all, any more.
So, that's been a bit of a
marathon folks. We've mounted our
galleys, we've invaded the distant shore.
We finally had enough cold compresses on
our head that we think we're clear what
we've done. But if you just go over this
carefully, for yourself, and draw yourself
lots of T-diagrams - or better still make
yourself some T-diagram shapes - and just
experiment with them until you're quite
happy with with what you're doing. And I
hope it's been convincing that although
it is messy at times it is so much
easier when you move to a new machine to
say: "All I need to write, to get myself
going, is an intermediate code compiler".
I don't need to redo the whole chain. That
can be back-filled as we go along. But I
could take the existing front-end and
port it into being a new front-end
simply if I've got the back-end tools
that can produce B'' for me.
It's as simple as that really!
