\section{Challenges and Solutions}
This section will describe the challenges faced during each of the tasks and the
solutions found for both the task itself and the challenges.

\subsection{What is MontiumC?}
A critical question popped up during at the beginning of my internship: What is
MontiumC? Previously, there was no real specification of MontiumC. There was
documentation about the functions that could be used, some examples and a lot of
personal knowledge in the heads of the Recore employees, but ultimately MontiumC
was "whatever the compiler eats".

To be able to create a proper set of transformations, the constraints on the
input and output of that transformation process should be properly specified.
This entails two parts: Specifying the MontiumC language, and specifying the
Montium IR constraints, which is is the input to the backend.

Specifying Montium IR was relatively easy, since it is defined directly by the
backend. The MontiumC specification is slightly more complex. There are two
different angles to it: What does the compiler support, and what do we want the
compiler to support.

\subsubsection{What is supported?}
One angle for looking at MontiumC is seeing what the compiler can currently
compile and turn that into a formal specification. This approach works fine to
set a baseline for the compiler: A point to start improving the transformations
from. Apart from that, this initial specification is also useful in reviewing
existing MontiumC code and verifying existing transformations.

Existing MontiumC code is supported by the compiler (since it has been tweaked
until it worked). However, the existing code might not fully work within the
produced specification. This can happen in particular when existing code makes
use of corner cases in the compiler that have been missed in (or left out of)
the specification, because they will not work reliably in all cases.

The best way to detect these cases is making the compiler check its input using
an the specification. This way, any code operating outside of the specification
can be detected automatically.

Existing transformations, on the other hand, might miss a few corner cases. When
writing the specification, a particular feature might appear supported by the
compiler. On closer inspection, the transformation passes might miss some corner
cases, which either need to be fixed or put into the specification.

The best way to detect these cases is writing a lot of structured testing code,
which uses (combinations of) the features that are supported according to the
specification. This way, corner cases exposed by the testing code can be
detected automatically.

Building this initial specification did pose a number of challenges. Since
simply trying all possible C features to see if they are accepted by the
MontiumC compiler and thus valid MontiumC is a lengthy process and only useful
in a limited way. A more constructive way would be to examine the compiler
components to see what transformations are applied and from that derive the
specification for valid MontiumC. However, most of these components are not very
transparent. The Clang frontend supports a lot of C constructs and is not a
trivial piece of code. It also has support for Objective C and partially C++,
which makes it harder to see which code paths are actually used for compiling
MontiumC. This issue is only partially solved, meaning that there might still be
incorrect or missing cases in the specification.

Another problem is the complexity of the C language. Although individual
features can be described and supported with relative ease, combining features
can easily lead to complex constructs which are hard to transform into supported
Montium IR. This became more of an issue after adding features to the base
specification of MontiumC, though.

\subsubsection{What is wanted?}
A completely different angle of looking at this, is from the requirements point
of view. What do we want MontiumC to support? This angle is even harder than the
previous one, since there are a lot of levels of requirements. Ideally, MontiumC
would not exist and our compiler would support the C language fully. However,
this would require a very complicated compiler (both frontend and backend).

Not only that, it is simply not possible to map all valid C programs to the
Montium hardware. "Regular" architectures don't suffer from this problem (as
much), since most instruction sets are not fundamentally different from the
features supported by C (or other imperative languages). This means that
anything is mappable, but with a simple compiler will not result in the most
efficient code. In the Montium case, a lot of things simply cannot be mapped on
the hardware at all.

Considering that our ideal is not reachable (by far), every feature in our
wanted MontiumC should be evaluated thoroughly for feasibility, both in hardware
and in the compiler. In practice, this meant that new language features would be
informally expressed and discussed, and only added to the specification after
being succesfully implemented. This is conforming to the incremental development
of MontiumC that was envisioned at the outset of its development.

\subsection{Familiarizing with LLVM}
Since during my internship I have been working mainly with LLVM (code), one of
the first challenges was to get myself familiar with LLVM. There are two main
aspects to this: Getting to know my way around the LLVM codebase and getting to
know the LLVM community.

Since LLVM has a pretty large amount of documentation, I spent most of my first
weeks with reading tutorials and documents. Since there was already a (very
preliminary) version of the clang-based frontend, I also had some code to play
with.

During this period, it was not completely clear what the frontend should
be doing and what transformations should be written. To prevent circular
dependencies in my tasks (I can't write any code before I know what needs to be
written, but I can't really tell what's needed until I know how the code works,
which I can't effectively learn without actively working with it, etc.) I
started out with adapting the loop unrolling pass in LLVM to be better suited to
the Montium architecture. Eventually, this code didn't turn out to be
immediately useful (it's still not included currently), but it proved very
insightful as to how the LLVM framework is built and what its possibilities are.

Additionally, during my working with the code in this stage I also produced a
number of patches for LLVM, containing bugfixes, some cleanup and documentation
improvements. Since the best way to integrate with any open source project seems
to be contributing code, I was giving commit access to the LLVM tree not long
thereafter. This access has proved very useful during the rest of the
internship, since it was now a a lot easier to make (simple) changes to the LLVM
framework to better suit the needs of Recore.

A major challenge during my internship was to find the balance between doing
work specifically for Recore, and doing work that is useful for LLVM in general.
Any tasks that are required by the Montium frontend and the LLVM changes they
directly need are obvious. However, usually when making changes to the main LLVM
code, just changing enough for Recore is not engough for LLVM. Since the LLVM
code must work on any program, not just MontiumC programs, extra changes are
required (see also parapgrah \ref{StayingGeneric}. This is also an issue of
building up credit within the LLVM community: The more you contribute to LLVM,
the more influence you have when things need changing. 

Lastly, this is also a matter of efficiency: If I have been working
with a particular piece of code intensively, it is more efficient for me to fix
a bug in that code than most others, even though the particular bug does not
interfere with the MontiumC frontend. In the end, I think I managed to find a
decent balance, though it might have been tipped slighly in favour of the LLVM
project.

\subsection{Coding}
This section says something about the challenges encountered while actually
writing code, if I can think of enough things to say here.

\subsection{Working together}
This section says something about working with colleagues in various ways.

\subsection{Staying generic}
\label{StayingGeneric}
The toughest challenge by far was to fit the features and changes required by
Recore into code that is maintained by the LLVM project. The main problem here
is clash of goals: The LLVM project aims for code that performs well on their
supported architectures, while Recore aims for code that performs well (or more
often, can compile at all) on the Montium architecture.

In general, these problems mainly occur because MontiumC and in particular
MontiumIR poses a number of constraints that are not present in other
architectures. This means that some transformations present in LLVM will violate
these constraints (which would result in better code on most other
architectures) resulting in miscompiled or uncompilable code.

In some cases, these extra constraints can be formulated in a generic way, such
that the LLVM code can handle architectures with or without the constraint.
In a lot of cases, however, the constraint is so Montium specific that changing
LLVM to support it is not feasible. In a few cases, this meant that the backend
was changed to support more features of the LLVM IR. In other cases, a
Recore-specific pass was added to solve these problems. In a few more cases, the
problems are still unresolved, effectively resulting in additional constraints
on the MontiumC language.

\subsection{Pipelined scheduling}
I've also been involved for a bit with the instruction scheduling algorithm
required for the new (pipelined) hardware design. Even though this is completely
outside of the area of my assignment, the initial prototype of that scheduler
was created using LLVM by someone else, so I have been assisting him with that.
Initially mostly helping out with hints on LLVM coding, but later also
with thinking about the scheduler and hardware design.

I will not go into much detail about the new hardware and its scheduler here,
but I will highlight the most important challenges and tradeoffs. I'll also
spend a few words on the observed merits of hardware/software codesign.
