diff --git a/juno_frontend/src/main.rs b/juno_frontend/src/main.rs
index 6c2722fc799fc09677ef8815b2983a46c01c3e09..7d855c56f5345dd866d8c1ec98bb92aa112e18de 100644
--- a/juno_frontend/src/main.rs
+++ b/juno_frontend/src/main.rs
@@ -1,8 +1,9 @@
-use juno_compiler::*;
+use std::fs::read_to_string;
+use std::path::PathBuf;
 
 use clap::Parser;
 
-use std::path::PathBuf;
+use juno_compiler::*;
 
 #[derive(Parser)]
 #[clap(author, version, about, long_about = None)]
@@ -12,6 +13,8 @@ struct Cli {
     schedule: Option<String>,
     #[arg(short, long = "output-dir", value_name = "OUTPUT DIR")]
     output_dir: Option<String>,
+    #[arg(short, long, value_name = "TREAT AS HERCULES IR")]
+    ir: bool,
 }
 
 fn main() {
@@ -25,10 +28,27 @@ fn main() {
             .unwrap()
             .to_string(),
     };
-    match compile(args.src_file, args.schedule, output_dir) {
-        Ok(()) => {}
-        Err(errs) => {
-            eprintln!("{}", errs);
+    if args.ir {
+        let Ok(contents) = read_to_string(&args.src_file) else {
+            panic!("Unable to open and read input file.");
+        };
+        let Ok(ir_mod) = hercules_ir::parse::parse(&contents) else {
+            panic!("Unable to parse Hercules IR file.");
+        };
+
+        let module_name = "module".to_string();
+        match compile_ir(ir_mod, args.schedule, output_dir, module_name) {
+            Ok(()) => {}
+            Err(errs) => {
+                eprintln!("{}", errs);
+            }
+        }
+    } else {
+        match compile(args.src_file, args.schedule, output_dir) {
+            Ok(()) => {}
+            Err(errs) => {
+                eprintln!("{}", errs);
+            }
         }
     }
 }
diff --git a/reports/.gitignore b/reports/.gitignore
deleted file mode 100644
index 3eec47da1211f648b0c8623af52105b1f8d67bd3..0000000000000000000000000000000000000000
--- a/reports/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-*.aux
-*.log
-*.pdf
diff --git a/reports/technical1/listings-juno-scheduler.sty b/reports/technical1/listings-juno-scheduler.sty
deleted file mode 100644
index 3b9ed5a2f63f0964dcbfe789c01dc3355644d747..0000000000000000000000000000000000000000
--- a/reports/technical1/listings-juno-scheduler.sty
+++ /dev/null
@@ -1,42 +0,0 @@
-% Based on https://github.com/denki/listings-rust/tree/master
-
-\NeedsTeXFormat{LaTeX2e}[1994/06/01]
-\ProvidesPackage{listings-juno-scheduler}[2024/05/17 listings Language for Juno Scheduler]
-
-\RequirePackage{color}
-\RequirePackage{listings}
-
-\lstdefinelanguage{JunoScheduler}{%
-  sensitive%
-, morecomment=[l]{//}%
-, morecomment=[s]{/*}{*/}%
-, alsodigit={}%
-, alsoother={}%
-%
-%
-% [1] reserve keywords
-% [2] primitive types
-% [3] type parameter kinds
-% [4] value constructors
-%
-, morekeywords={function} % Keywords
-, morekeywords=[2]{parallelize, vectorize, partition, on} % Operations
-, morekeywords=[3]{cpu, gpu} % Devices
-%
-, morecomment=[s][\color{orange!80!black}]{@}{\ } % Labels
-, moredelim=[is]{^}{^}
-}%
-
-\lstdefinestyle{junoScheduler}
-{ language=JunoScheduler,
-  basicstyle=\ttfamily,
-  commentstyle=\color{gray}\ttfamily,
-  stringstyle=\color{red}\ttfamily,
-  keywordstyle=[1]\color[rgb]{0, 0, 1.0}\ttfamily,    % keywords
-  keywordstyle=[2]\color[rgb]{0, 0.5, 0}\ttfamily,    % primitive types
-  keywordstyle=[3]\color[rgb]{0.5, 0, 0.5}\ttfamily,  % type kinds
-  keepspaces=true,
-  showspaces=false,
-  showtabs=false,
-  showstringspaces=false,
-}
diff --git a/reports/technical1/listings-juno.sty b/reports/technical1/listings-juno.sty
deleted file mode 100644
index 892b7cd3cdfe2bf11b6d410232e8f5275cd038c3..0000000000000000000000000000000000000000
--- a/reports/technical1/listings-juno.sty
+++ /dev/null
@@ -1,52 +0,0 @@
-% Based on https://github.com/denki/listings-rust/tree/master
-
-\NeedsTeXFormat{LaTeX2e}[1994/06/01]
-\ProvidesPackage{listings-juno}[2024/05/17 listings Language for Juno]
-
-\RequirePackage{color}
-\RequirePackage{listings}
-
-\lstdefinelanguage{Juno}{%
-  sensitive%
-, morecomment=[l]{//}%
-, morecomment=[s]{/*}{*/}%
-, moredelim=[s][{\itshape\color[rgb]{0,0,0.75}}]{\#[}{]}%
-, morestring=[b]{"}%
-, alsodigit={}%
-, alsoother={}%
-, alsoletter={!}%
-%
-%
-% [1] reserve keywords
-% [2] primitive types
-% [3] type parameter kinds
-% [4] value constructors
-%
-, morekeywords={break, continue, else, for, if, in, match, return, while, to}  % control flow keywords
-, morekeywords={as, const, let,}  % in the context of variables
-, morekeywords={fn, struct, type,}  % in the context of declarations
-, morekeywords={mod, pub}  % in the context of modularisation
-%
-, morekeywords=[2]{bool, f32, f64, i8, i16, i32, i64, u8, u16, u32, u64, unit}  % primitive types
-%
-, morekeywords=[3]{type, number, integer, usize} % type kinds
-%
-, morekeywords=[4]{false, true}  % value constructors
-%
-, morecomment=[s][\color{gray}]{@}{\ } % Labels
-}%
-
-\lstdefinestyle{juno}
-{ language=Juno,
-  basicstyle=\ttfamily,
-  commentstyle=\color{gray}\ttfamily,
-  stringstyle=\color{red}\ttfamily,
-  keywordstyle=[1]\color[rgb]{0, 0, 1.0}\ttfamily,    % keywords
-  keywordstyle=[2]\color[rgb]{0, 0.5, 0}\ttfamily,    % primitive types
-  keywordstyle=[3]\color[rgb]{0.5, 0, 0.5}\ttfamily,  % type kinds
-  keywordstyle=[4]\color[rgb]{0, 0.5, 0}\ttfamily,    % value constructors
-  keepspaces=true,
-  showspaces=false,
-  showtabs=false,
-  showstringspaces=false,
-}
diff --git a/reports/technical1/listings-rust.sty b/reports/technical1/listings-rust.sty
deleted file mode 100644
index 585a6d6fec7b571a094eafe31595823cd5f167d5..0000000000000000000000000000000000000000
--- a/reports/technical1/listings-rust.sty
+++ /dev/null
@@ -1,108 +0,0 @@
-% From: https://github.com/denki/listings-rust
-
-% BSD 3-Clause License
-% 
-% Copyright (c) 2018, Tobias Denkinger
-% All rights reserved.
-% 
-% Redistribution and use in source and binary forms, with or without
-% modification, are permitted provided that the following conditions are met:
-% 
-% * Redistributions of source code must retain the above copyright notice, this
-%   list of conditions and the following disclaimer.
-% 
-% * Redistributions in binary form must reproduce the above copyright notice,
-%   this list of conditions and the following disclaimer in the documentation
-%   and/or other materials provided with the distribution.
-% 
-% * Neither the name of the copyright holder nor the names of its
-%   contributors may be used to endorse or promote products derived from
-%   this software without specific prior written permission.
-% 
-% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-% DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-% FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-% DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-% SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-% CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-% OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-% OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-\NeedsTeXFormat{LaTeX2e}[1994/06/01]
-\ProvidesPackage{listings-rust}[2018/01/23 Custom Package]
-
-\RequirePackage{color}
-\RequirePackage{listings}
-
-\lstdefinelanguage{Rust}{%
-  sensitive%
-, morecomment=[l]{//}%
-, morecomment=[s]{/*}{*/}%
-, moredelim=[s][{\itshape\color[rgb]{0,0,0.75}}]{\#[}{]}%
-, morestring=[b]{"}%
-, alsodigit={}%
-, alsoother={}%
-, alsoletter={!}%
-%
-%
-% [1] reserve keywords
-% [2] traits
-% [3] primitive types
-% [4] type and value constructors
-% [5] identifier
-%
-, morekeywords={break, continue, else, for, if, in, loop, match, return, while}  % control flow keywords
-, morekeywords={as, const, let, move, mut, ref, static}  % in the context of variables
-, morekeywords={dyn, enum, fn, impl, Self, self, struct, trait, type, union, use, where}  % in the context of declarations
-, morekeywords={crate, extern, mod, pub, super}  % in the context of modularisation
-, morekeywords={unsafe}  % markers
-, morekeywords={abstract, alignof, become, box, do, final, macro, offsetof, override, priv, proc, pure, sizeof, typeof, unsized, virtual, yield}  % reserved identifiers
-%
-% grep 'pub trait [A-Za-z][A-Za-z0-9]*' -r . | sed 's/^.*pub trait \([A-Za-z][A-Za-z0-9]*\).*/\1/g' | sort -u | tr '\n' ',' | sed 's/^\(.*\),$/{\1}\n/g' | sed 's/,/, /g'
-, morekeywords=[2]{Add, AddAssign, Any, AsciiExt, AsInner, AsInnerMut, AsMut, AsRawFd, AsRawHandle, AsRawSocket, AsRef, Binary, BitAnd, BitAndAssign, Bitor, BitOr, BitOrAssign, BitXor, BitXorAssign, Borrow, BorrowMut, Boxed, BoxPlace, BufRead, BuildHasher, CastInto, CharExt, Clone, CoerceUnsized, CommandExt, Copy, Debug, DecodableFloat, Default, Deref, DerefMut, DirBuilderExt, DirEntryExt, Display, Div, DivAssign, DoubleEndedIterator, DoubleEndedSearcher, Drop, EnvKey, Eq, Error, ExactSizeIterator, ExitStatusExt, Extend, FileExt, FileTypeExt, Float, Fn, FnBox, FnMut, FnOnce, Freeze, From, FromInner, FromIterator, FromRawFd, FromRawHandle, FromRawSocket, FromStr, FullOps, FusedIterator, Generator, Hash, Hasher, Index, IndexMut, InPlace, Int, Into, IntoCow, IntoInner, IntoIterator, IntoRawFd, IntoRawHandle, IntoRawSocket, IsMinusOne, IsZero, Iterator, JoinHandleExt, LargeInt, LowerExp, LowerHex, MetadataExt, Mul, MulAssign, Neg, Not, Octal, OpenOptionsExt, Ord, OsStrExt, OsStringExt, Packet, PartialEq, PartialOrd, Pattern, PermissionsExt, Place, Placer, Pointer, Product, Put, RangeArgument, RawFloat, Read, Rem, RemAssign, Seek, Shl, ShlAssign, Shr, ShrAssign, Sized, SliceConcatExt, SliceExt, SliceIndex, Stats, Step, StrExt, Sub, SubAssign, Sum, Sync, TDynBenchFn, Terminal, Termination, ToOwned, ToSocketAddrs, ToString, Try, TryFrom, TryInto, UnicodeStr, Unsize, UpperExp, UpperHex, WideInt, Write}
-, morekeywords=[2]{Send}  % additional traits
-%
-, morekeywords=[3]{bool, char, f32, f64, i8, i16, i32, i64, isize, str, u8, u16, u32, u64, unit, usize, i128, u128}  % primitive types
-%
-, morekeywords=[4]{Err, false, None, Ok, Some, true}  % prelude value constructors
-% grep 'pub \(type\|struct\|enum\) [A-Za-z][A-Za-z0-9]*' -r . | sed 's/^.*pub \(type\|struct\|enum\) \([A-Za-z][A-Za-z0-9]*\).*/\2/g' | sort -u | tr '\n' ',' | sed 's/^\(.*\),$/{\1}\n/g' | sed 's/,/, /g'    
-, morekeywords=[3]{AccessError, Adddf3, AddI128, AddoI128, AddoU128, ADDRESS, ADDRESS64, addrinfo, ADDRINFOA, AddrParseError, Addsf3, AddU128, advice, aiocb, Alignment, AllocErr, AnonPipe, Answer, Arc, Args, ArgsInnerDebug, ArgsOs, Argument, Arguments, ArgumentV1, Ashldi3, Ashlti3, Ashrdi3, Ashrti3, AssertParamIsClone, AssertParamIsCopy, AssertParamIsEq, AssertUnwindSafe, AtomicBool, AtomicPtr, Attr, auxtype, auxv, BackPlace, BacktraceContext, Barrier, BarrierWaitResult, Bencher, BenchMode, BenchSamples, BinaryHeap, BinaryHeapPlace, blkcnt, blkcnt64, blksize, BOOL, boolean, BOOLEAN, BoolTrie, BorrowError, BorrowMutError, Bound, Box, bpf, BTreeMap, BTreeSet, Bucket, BucketState, Buf, BufReader, BufWriter, Builder, BuildHasherDefault, BY, BYTE, Bytes, CannotReallocInPlace, cc, Cell, Chain, CHAR, CharIndices, CharPredicateSearcher, Chars, CharSearcher, CharsError, CharSliceSearcher, CharTryFromError, Child, ChildPipes, ChildStderr, ChildStdin, ChildStdio, ChildStdout, Chunks, ChunksMut, ciovec, clock, clockid, Cloned, cmsgcred, cmsghdr, CodePoint, Color, ColorConfig, Command, CommandEnv, Component, Components, CONDITION, condvar, Condvar, CONSOLE, CONTEXT, Count, Cow, cpu, CRITICAL, CStr, CString, CStringArray, Cursor, Cycle, CycleIter, daddr, DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple, Decimal, Decoded, DecodeUtf16, DecodeUtf16Error, DecodeUtf8, DefaultEnvKey, DefaultHasher, dev, device, Difference, Digit32, DIR, DirBuilder, dircookie, dirent, dirent64, DirEntry, Discriminant, DISPATCHER, Display, Divdf3, Divdi3, Divmoddi4, Divmodsi4, Divsf3, Divsi3, Divti3, dl, Dl, Dlmalloc, Dns, DnsAnswer, DnsQuery, dqblk, Drain, DrainFilter, Dtor, Duration, DwarfReader, DWORD, DWORDLONG, DynamicLibrary, Edge, EHAction, EHContext, Elf32, Elf64, Empty, EmptyBucket, EncodeUtf16, EncodeWide, Entry, EntryPlace, Enumerate, Env, epoll, errno, Error, ErrorKind, EscapeDebug, EscapeDefault, EscapeUnicode, event, Event, eventrwflags, eventtype, ExactChunks, ExactChunksMut, EXCEPTION, Excess, ExchangeHeapSingleton, exit, exitcode, ExitStatus, Failure, fd, fdflags, fdsflags, fdstat, ff, fflags, File, FILE, FileAttr, filedelta, FileDesc, FilePermissions, filesize, filestat, FILETIME, filetype, FileType, Filter, FilterMap, Fixdfdi, Fixdfsi, Fixdfti, Fixsfdi, Fixsfsi, Fixsfti, Fixunsdfdi, Fixunsdfsi, Fixunsdfti, Fixunssfdi, Fixunssfsi, Fixunssfti, Flag, FlatMap, Floatdidf, FLOATING, Floatsidf, Floatsisf, Floattidf, Floattisf, Floatundidf, Floatunsidf, Floatunsisf, Floatuntidf, Floatuntisf, flock, ForceResult, FormatSpec, Formatted, Formatter, Fp, FpCategory, fpos, fpos64, fpreg, fpregset, FPUControlWord, Frame, FromBytesWithNulError, FromUtf16Error, FromUtf8Error, FrontPlace, fsblkcnt, fsfilcnt, fsflags, fsid, fstore, fsword, FullBucket, FullBucketMut, FullDecoded, Fuse, GapThenFull, GeneratorState, gid, glob, glob64, GlobalDlmalloc, greg, group, GROUP, Guard, GUID, Handle, HANDLE, Handler, HashMap, HashSet, Heap, HINSTANCE, HMODULE, hostent, HRESULT, id, idtype, if, ifaddrs, IMAGEHLP, Immut, in, in6, Incoming, Infallible, Initializer, ino, ino64, inode, input, InsertResult, Inspect, Instant, int16, int32, int64, int8, integer, IntermediateBox, Internal, Intersection, intmax, IntoInnerError, IntoIter, IntoStringError, intptr, InvalidSequence, iovec, ip, IpAddr, ipc, Ipv4Addr, ipv6, Ipv6Addr, Ipv6MulticastScope, Iter, IterMut, itimerspec, itimerval, jail, JoinHandle, JoinPathsError, KDHELP64, kevent, kevent64, key, Key, Keys, KV, l4, LARGE, lastlog, launchpad, Layout, Lazy, lconv, Leaf, LeafOrInternal, Lines, LinesAny, LineWriter, linger, linkcount, LinkedList, load, locale, LocalKey, LocalKeyState, Location, lock, LockResult, loff, LONG, lookup, lookupflags, LookupHost, LPBOOL, LPBY, LPBYTE, LPCSTR, LPCVOID, LPCWSTR, LPDWORD, LPFILETIME, LPHANDLE, LPOVERLAPPED, LPPROCESS, LPPROGRESS, LPSECURITY, LPSTARTUPINFO, LPSTR, LPVOID, LPWCH, LPWIN32, LPWSADATA, LPWSAPROTOCOL, LPWSTR, Lshrdi3, Lshrti3, lwpid, M128A, mach, major, Map, mcontext, Metadata, Metric, MetricMap, mflags, minor, mmsghdr, Moddi3, mode, Modsi3, Modti3, MonitorMsg, MOUNT, mprot, mq, mqd, msflags, msghdr, msginfo, msglen, msgqnum, msqid, Muldf3, Mulodi4, Mulosi4, Muloti4, Mulsf3, Multi3, Mut, Mutex, MutexGuard, MyCollection, n16, NamePadding, NativeLibBoilerplate, nfds, nl, nlink, NodeRef, NoneError, NonNull, NonZero, nthreads, NulError, OccupiedEntry, off, off64, oflags, Once, OnceState, OpenOptions, Option, Options, OptRes, Ordering, OsStr, OsString, Output, OVERLAPPED, Owned, Packet, PanicInfo, Param, ParseBoolError, ParseCharError, ParseError, ParseFloatError, ParseIntError, ParseResult, Part, passwd, Path, PathBuf, PCONDITION, PCONSOLE, Peekable, PeekMut, Permissions, PhantomData, pid, Pipes, PlaceBack, PlaceFront, PLARGE, PoisonError, pollfd, PopResult, port, Position, Powidf2, Powisf2, Prefix, PrefixComponent, PrintFormat, proc, Process, PROCESS, processentry, protoent, PSRWLOCK, pthread, ptr, ptrdiff, PVECTORED, Queue, radvisory, RandomState, Range, RangeFrom, RangeFull, RangeInclusive, RangeMut, RangeTo, RangeToInclusive, RawBucket, RawFd, RawHandle, RawPthread, RawSocket, RawTable, RawVec, Rc, ReadDir, Receiver, recv, RecvError, RecvTimeoutError, ReentrantMutex, ReentrantMutexGuard, Ref, RefCell, RefMut, REPARSE, Repeat, Result, Rev, Reverse, riflags, rights, rlim, rlim64, rlimit, rlimit64, roflags, Root, RSplit, RSplitMut, RSplitN, RSplitNMut, RUNTIME, rusage, RwLock, RWLock, RwLockReadGuard, RwLockWriteGuard, sa, SafeHash, Scan, sched, scope, sdflags, SearchResult, SearchStep, SECURITY, SeekFrom, segment, Select, SelectionResult, sem, sembuf, send, Sender, SendError, servent, sf, Shared, shmatt, shmid, ShortReader, ShouldPanic, Shutdown, siflags, sigaction, SigAction, sigevent, sighandler, siginfo, Sign, signal, signalfd, SignalToken, sigset, sigval, Sink, SipHasher, SipHasher13, SipHasher24, size, SIZE, Skip, SkipWhile, Slice, SmallBoolTrie, sockaddr, SOCKADDR, sockcred, Socket, SOCKET, SocketAddr, SocketAddrV4, SocketAddrV6, socklen, speed, Splice, Split, SplitMut, SplitN, SplitNMut, SplitPaths, SplitWhitespace, spwd, SRWLOCK, ssize, stack, STACKFRAME64, StartResult, STARTUPINFO, stat, Stat, stat64, statfs, statfs64, StaticKey, statvfs, StatVfs, statvfs64, Stderr, StderrLock, StderrTerminal, Stdin, StdinLock, Stdio, StdioPipes, Stdout, StdoutLock, StdoutTerminal, StepBy, String, StripPrefixError, StrSearcher, subclockflags, Subdf3, SubI128, SuboI128, SuboU128, subrwflags, subscription, Subsf3, SubU128, Summary, suseconds, SYMBOL, SYMBOLIC, SymmetricDifference, SyncSender, sysinfo, System, SystemTime, SystemTimeError, Take, TakeWhile, tcb, tcflag, TcpListener, TcpStream, TempDir, TermInfo, TerminfoTerminal, termios, termios2, TestDesc, TestDescAndFn, TestEvent, TestFn, TestName, TestOpts, TestResult, Thread, threadattr, threadentry, ThreadId, tid, time, time64, timespec, TimeSpec, timestamp, timeval, timeval32, timezone, tm, tms, ToLowercase, ToUppercase, TraitObject, TryFromIntError, TryFromSliceError, TryIter, TryLockError, TryLockResult, TryRecvError, TrySendError, TypeId, U64x2, ucontext, ucred, Udivdi3, Udivmoddi4, Udivmodsi4, Udivmodti4, Udivsi3, Udivti3, UdpSocket, uid, UINT, uint16, uint32, uint64, uint8, uintmax, uintptr, ulflags, ULONG, ULONGLONG, Umoddi3, Umodsi3, Umodti3, UnicodeVersion, Union, Unique, UnixDatagram, UnixListener, UnixStream, Unpacked, UnsafeCell, UNWIND, UpgradeResult, useconds, user, userdata, USHORT, Utf16Encoder, Utf8Error, Utf8Lossy, Utf8LossyChunk, Utf8LossyChunksIter, utimbuf, utmp, utmpx, utsname, uuid, VacantEntry, Values, ValuesMut, VarError, Variables, Vars, VarsOs, Vec, VecDeque, vm, Void, WaitTimeoutResult, WaitToken, wchar, WCHAR, Weak, whence, WIN32, WinConsole, Windows, WindowsEnvKey, winsize, WORD, Wrapping, wrlen, WSADATA, WSAPROTOCOL, WSAPROTOCOLCHAIN, Wtf8, Wtf8Buf, Wtf8CodePoints, xsw, xucred, Zip, zx}
-%
-, morekeywords=[5]{assert!, assert_eq!, assert_ne!, cfg!, column!, compile_error!, concat!, concat_idents!, debug_assert!, debug_assert_eq!, debug_assert_ne!, env!, eprint!, eprintln!, file!, format!, format_args!, include!, include_bytes!, include_str!, line!, module_path!, option_env!, panic!, print!, println!, select!, stringify!, thread_local!, try!, unimplemented!, unreachable!, vec!, write!, writeln!}  % prelude macros
-}%
-
-\lstdefinestyle{colouredRust}%
-{ basicstyle=\ttfamily%
-, language=Rust%
-, identifierstyle=%
-, commentstyle=\color[gray]{0.4}%
-, stringstyle=\color[rgb]{0.5, 0, 0}%
-, keywordstyle=\color[rgb]{0, 0.25, 1}% reserved keywords
-, keywordstyle=[2]\color[rgb]{0.75, 0, 0}% traits
-, keywordstyle=[3]\color[rgb]{0, 0.5, 0}% primitive types
-, keywordstyle=[4]\color[rgb]{0, 0.5, 0}% type and value constructors
-, keywordstyle=[5]\color[rgb]{0, 0, 0.75}% macros
-, columns=spaceflexible%
-, keepspaces=true%
-, showspaces=false%
-, showtabs=false%
-, showstringspaces=true%
-}%
-
-\lstdefinestyle{boxed}{
-  style=colouredRust%
-, numbers=left%
-, firstnumber=auto%
-, numberblanklines=true%
-, frame=trbL%
-, numberstyle=\tiny%
-, frame=leftline%
-, numbersep=7pt%
-, framesep=5pt%
-, framerule=10pt%
-, xleftmargin=15pt%
-, backgroundcolor=\color[gray]{0.97}%
-, rulecolor=\color[gray]{0.90}%
-}
diff --git a/reports/technical1/main.tex b/reports/technical1/main.tex
deleted file mode 100644
index e70625d4cd8adcf9157e1234d45eac177fa1f255..0000000000000000000000000000000000000000
--- a/reports/technical1/main.tex
+++ /dev/null
@@ -1,527 +0,0 @@
-\documentclass{article}
-
-\usepackage[utf8]{inputenc}
-\usepackage[top=2cm,right=2cm,left=2cm,bottom=2cm]{geometry}
-\usepackage{amsfonts}
-\usepackage{listings, listings-rust, listings-juno, listings-juno-scheduler}
-\usepackage{amsmath}
-\usepackage{amssymb}
-\usepackage{amsthm}
-\usepackage[english]{babel}
-\usepackage{fancyhdr}
-\usepackage[dvipsnames]{xcolor}
-\usepackage{hyperref}
-\usepackage{graphicx}
-
-\usepackage{stmaryrd}
-
-\hypersetup{colorlinks=true,
-  linkcolor=blue,
-  filecolor=magenta,
-  urlcolor=blue,
-}
-
-\renewcommand{\thefootnote}{\fnsymbol{footnote}}
-
-\pagestyle{fancy}
-\fancyhf{}
-
-\renewcommand{\footrulewidth}{1pt}
-\rfoot{\thepage}
-
-\allowdisplaybreaks
-
-\title{Hercules}
-\author{Aaron Councilman and Russel Arbore}
-\date{\today}
-
-\chead{Hercules}
-\rhead{Aaron Councilman and Russel Arbore}
-\lhead{\today}
-
-\begin{document}
-\maketitle
-
-\section{Introduction}
-
-This report describes the implementation details of Hercules, a heterogeneous compilation system.
-Our main goals in developing Hercules are the following:
-
-\begin{enumerate}
-  \item Develop a heterogeneous compilation system capable of reasoning about programs executing across devices in a \textit{first class} fashion.
-    \textit{For now}, we call this property ``co-optimization''.
-
-  \item Support (almost) arbitrary code partitioning across devices---this expressivity enables automatic partitioning.
-
-  \item Support data layout flexibility without algorithmic modifications.
-    This allows us to target devices that require unconventional memory layouts.
-
-  \item Develop a high quality implementation that can be the basis of future heterogeneous compilation research (i.e., automatic partitioning techniques, programming abstractions for heterogeneous hardware).
-\end{enumerate}
-
-Goals 1-3 form the academic kernel of our work---these inform our design decisions for the compiler.
-Goal 4 informs our engineering approach. We will describe the technical details of Hercules in this report, and make reference back to these goals as is appropriate.
-
-\section{Structure}
-
-Hercules is written from scratch in Rust.
-We took this approach for several reasons:
-
-\begin{itemize}
-  \item We both have somewhat of a functional programming background - while Rust is not really a functional language in the strict sense, it does have a strong type system that makes it comfortable to program in.
-    Rather than programming in a functional style, we often find ourselves programming in an ``iterator'' style.
-    Making heavy uses of iterators has made writing Hercules must easier---iterators naturally express almost all of the heavy lifting code in Hercules, are easy to read and write, and are compiled to efficient native code.
-    Rust's async language features has also been very useful for writing a generic runtime.
-    Additionally, Rust has a great ecosystem of packages that can be easily used, called ``crates''.
-    There are a couple of crates that have proved crucial to us (\texttt{serde}, \texttt{bitvec}, and \texttt{nom} primarily).
-  \begin{itemize}
-    \item This is the first large Rust project either of us have written---we decided to take the leap of faith, since the only other ``real'' option was C++.
-      After having worked on HPVM for some time, we've both grown tired of C++.
-
-  \end{itemize}
-  \item We decided to write the compiler from scratch because the whole point of Hercules is to see what can be accomplished by taking a clean sheet of paper approach to heterogeneous compilation.
-    We didn't want to be restricted by the design decisions of previous IRs.
-    In hindsight, we probably could express Hercules IR as an MLIR dialect.
-    However, there are three reasons we didn't do this:
-
-  \begin{itemize}
-    \item We didn't think this when we made the decision---at the time, we thought MLIR wouldn't be able to express what we wanted.
-    \item MLIR is a C++ project---see the note on why we chose Rust.
-    \item We received advice to not use MLIR if we could avoid it from a trusted colleague.
-  \end{itemize}
-\end{itemize}
-
-As a Rust project, Hercules is structured into a set of crates.
-Each crates handles one logical component of Hercules.
-The main crates (at the time of writing) are:
-\begin{itemize}
-  \item \texttt{juno\_frontend}: Parser, semantic analyzer, and IR code generator for implementing the Juno frontend language.
-    Juno is a Rust-like simple language for expressing programs using Mutable Value Semantics (MVS).
-    Hercules can in principle have several frontends---we are developing Juno primarily to generate Hercules programs for testing and evaluation.
-
-  \item \texttt{hercules\_ir}: Defines the IR structures, IR analyses, and several utilities for working with Hercules IR.
-    This is the ``main'' crate in the project.
-    Some of the analyses are dataflow, dominator, def-use, anti-dependence, code motion, and loop analysis (code motion is an analysis in our compiler---see Section~\ref{sec:ir_design}).
-    There are also utilities for IR verification, dot graphviz visualization, parsing textual IR, and building the IR programmatically.
-    This crate also defines the ``plan'' structure, which contains both schedules and partitions---schedules are attributes attachable to IR nodes directing the compiler to act in a non-default manner, while partitions are groupings of IR nodes into a single chunk of code that is lowered onto a single device.
-
-  \item \texttt{hercules\_opt}: Defines several optimizations that can be performed on Hercules IR.
-    These include conditional constant propagation, dead code elimination, global value numbering, and predication.
-    This crate also includes a pass manager for sanely setting up optimization pipelines and keeping track of analysis results.
-
-  \item \texttt{hercules\_cg}: Lowers Hercules IR to device-specific code.
-    This is done on a per-partition basis.
-    All of the code is emitted textually as an LLVM IR module (we don't want to pull LLVM in as a hard dependency).
-    This code also generates a ``manifest'' when lowering an IR module.
-    This manifest contains all the information about the code needed by the runtime to actually execute the program.
-
-  \item \texttt{hercules\_rt}: Loads a manifest + ELF object of a compiled Hercules program, and executes it.
-    The Hercules runtime is responsible for loading the ELF object, memory allocation, and calling device-specific APIs for launching execution.
-    All of the information needed to set things up correctly is present in the manifest.
-    Notice that the Hercules runtime is \textit{not} responsible for scheduling, or driving execution.
-    The gist is that the Hercules runtime uses Rust's async feature---the runtime sets up async functions implementing the Hercules code, and an external executor (such as \texttt{tokio} or \texttt{async-std}) actually schedules and executes the async functions.
-    These external executors can be written with a particular operating system in mind (or more interestingly, no operating system).
-    This simplifies the Hercules runtime and makes it much more practical to integrate Hercules code into a larger Rust project, especially those already using an async executor.
-    More details can be found in Section~\ref{sec:runtime}.
-
-  \item \texttt{hercules\_tools}: Contains several tools for manipulating Hercules IR.
-    These are all command line wrappers around code written in the other crates mentioned.
-    The most commonly used one is \texttt{hercules\_driver}, which allows one to run an arbitrary sequence of passes on an input IR module using the pass manager.
-\end{itemize}
-
-The overall structure of the Hercules compiler is fairly classical.
-At the time of writing, the compiler is approximately 14K single lines of code.
-
-\section{IR Design}\label{sec:ir_design}
-
-There are five key aspects of our IR design that merit emphasis:
-
-\begin{itemize}
-  \item Sea-of-nodes structure: each Hercules function is structured as a single, flat, flow graph.
-    The graph consists of nodes, representing both values and operations (the output of an operation is a value that can be used), and edges, representing uses of values.
-    The flow graph is flat, so ``control'' and ``data'' nodes live in the same level.
-    For example, the If node, a control node representing conditional branching, takes as input a condition value, which is a data node indicating which branch to take.
-    Semantically, a control token enters the flow graph at the Start node when the function is called---this control token flows through the control nodes in the flow graph until reaching a Return node---the value returned by the function is the data value used by the Return node.
-
-  \item Immutable value semantics (IVS): Hercules functions are pure---there are no side effecting operations.
-    Additionally, there are no references in Hercules IR.
-    All uses of all data items are known precisely at compile time, and are exactly the edges in the function's flow graph.
-    The most pressing concern is how to represent updates to aggregates (such as arrays).
-    Semantically, aggregates are not updated in-place---they are cloned, with one value updated to a new value.
-    This makes compiler analysis and device partitioning significantly easier.
-    When lowering to device code, mutation is introduced to achieve good performance.
-
-  \item Data parallelism with fork-join nests: the original sea-of-nodes IR, presented by Cliff Click, doesn't contain constructs for representing parallel code.
-    We introduce fork-join nests, a structure in Hercules IR consisting of four node types: fork, join, threadid, and reduce.
-    Fork-join nests represent both SIMT parallelism and reduction parallelism.
-    They are really best explained through examples---see below for more details.
-
-  \item The Plan: this is the data structure that holds scheduling and partitioning information for a Hercules IR module.
-    Schedules are per node attributes that direct compiler operation, while partitions are groupings of IR nodes that should be lowered to a single fragment of device-specific code.
-    A key aspect of both schedules and partitions is that they are both \textit{suggestions}---the compiler is free to discard them if necessary.
-    The way to look at schedules and partitions is that they are overlays on top of the core IR structure.
-    The advantage of this approach is that the compiler can transform code without worrying about editing the plan directly, and the compiler can construct partitions automatically given a Hercules IR function.
-    The downside is that the compiler must ``repair'' the plan after each transformation.
-    We believe this is a reasonable compromise in order to reduce the implementation complexity of transformations inside Hercules.
-
-  \item Dynamic constants: a key question any modern compiler has to answer is how to represent the bounds of an array.
-    The two classic options are as compile time constants or as runtime values.
-    Compile time constants are too restrictive, since we want to generate code that can operate on arbitrary array sizes.
-    However, runtime values are too flexible, since many heterogeneous devices don't support allocating memory dynamically---we can't let the size of an array used on a device be dependent on a value also computed on that device (at least within the same kernel launch).
-    We take a best-of-both-worlds approach, which we call \emph{dynamic constants}.
-    A dynamic constant is a value that is not known at compile time, but is guaranteed to be computable before any Hercules code starts executing.
-    This allows us to compile a single Hercules program capable of running on multiple array sizes and to allocate all memory that needs to be used up-front.
-    Dynamic constants are used to represent array sizes and fork-join launch factors.
-\end{itemize}
-
-We now walk through several example programs in Hercules to illustrate various aspects of the IR design.
-We show the graphviz outputs from the \texttt{Xdot(true)} pass, which omits some information.
-We describe the omitted details when necessary.
-All of these examples are available, in Hercules IR textual form, in the \texttt{hercules\_samples} directory of the repository.
-
-\centerline{\includegraphics[width=0.5\textwidth]{simple1.png}}
-
-The \texttt{simple1} program takes two \texttt{i32} parameters, adds them, and returns the result.
-There are a couple of things to note:
-
-\begin{itemize}
-  \item We color control nodes in red, and data nodes in blue.
-    Black edges denote direct uses between nodes, and green edges denote control dominance.
-    The dark gray rectangle labelled ``simple1'' represents a Hercules function.
-    The light blue rectangle represents a partition that should have code generated for the CPU.
-
-  \item The flow graph has a single entry point (the start node).
-    The parameter, constant, and dynamicconstant nodes take the start node as input to maintain this property.
-    This simplifies dataflow analysis.
-
-  \item Semantically, data nodes are evaluated lazily.
-    Their values are only calculated when needed by a control node.
-    The control token flows through control nodes in the flow graph until reaching a control node that relies on some data input.
-    Once the data calculation is finished, the control token can proceed.
-    In this example, execution proceeds as follows:
-  \begin{itemize}
-    \item The control token starts at the start node.
-    \item The start node always has one control successor---the control token flows to that successor.
-    \item The successor is the return node.
-      At this point, we need to calculate the value that enters the return node on its data input before we can return from the function.
-    \item We need to evaluate the add node.
-      Before we can execute the add operation, we need to evaluate the add node's two inputs.
-    \item The two parameter nodes have known value, at runtime.
-      Their values are just the function call arguments.
-    \item The add node executes, producing the addition of the two values as its value.
-    \item The function can return the result of the addition operation.
-  \end{itemize}
-\end{itemize}
-
-Next, let's look at an example with interesting control flow.
-
-\centerline{\includegraphics[width=0.35\textwidth]{simple2.png}}
-
-This example introduces several new nodes, so let's go through them one-by-one.
-
-\begin{itemize}
-  \item Region: region nodes are the only kind of control node which can have multiple control predecessors---they are where branches ``join'' back together.
-    Control tokens just flow right through them.
-
-  \item Phi: the use of phi nodes makes our IR SSA.
-    Hercules IR contains no mutation primitives, so the IR is SSA by construction.
-    Phi nodes have one control input which must be a region node, and $N$ data inputs, where $N$ is the number of predecessors of the associated region node.
-    The semantics of phi nodes in Hercules IR is most similar to gated SSA form---the data output of a phi node is ``latched'' whenever the control token enters its associated region node.
-    The phi node latches the data input corresponding to which predecessor of the region node the control token came from.
-
-  \item If: if nodes are one of two kinds of control nodes which can have multiple control successors (the other being match).
-    They take a control input (their control predecessor) and a data input, which is the condition to branch on.
-    They send the control token to one of their successor control nodes, depending on the runtime value of the condition input.
-
-  \item Read: there are two distinct uses of read nodes.
-    One is to read an element of an aggregate value.
-    The other, demonstrated in this example, is to select a particular branch from the if node.
-    An implementation detail of the sea-of-nodes IR is that edges from uses to definitions are stored, rather than edges from definitions to uses (as is shown in the graphviz outputs).
-    This means every node stores its \textit{uses}, but not its \textit{users}.
-    The if node needs to identify which \textit{user} is the true branch, and which is the false branch.
-    The solution proposed to this problem in the original paper is to add ``projection'' nodes, which are effectively an edge label---each projection node stores an integer indicating which branch it corresponds to.
-    All if nodes must be followed by exactly two such projection nodes, indicating which branch is which.
-  \begin{itemize}
-    \item \textit{Note: we use Read nodes for this dual purpose since that's how the original sea-of-nodes IR was presented.
-      The original justification is that you can think of the if node as producing two control tokens in a struct, and the successor read nodes each read a particular element of that struct.
-      As one can imagine, this has caused us many headaches for no good reason, and it is confusing to have one type of node used in two completely distinct situations.
-      We are considering adding a dedicated ``Projection'' node to fix this.}
-  \end{itemize}
-
-  \item Constant: takes a constant and produces its value.
-    Constants are defined outside of the flow graph, and are de-duplicated on a per-module basis.
-
-  \item Mul: multiples two values, and produces the result.
-
-  \item Lt: compares two values, and returns whether the first is less than the second.
-\end{itemize}
-
-This example contains an unstructured loop.
-Control flow in the sea-of-nodes is mostly analogous to control flow in a normal control flow graph.
-This example calculates the factorial of an input integer iteratively.
-It contains a loop that executes at least once, and is bounded by the input integer.
-The data flow for the factorial value occurs through the phi node forming a cycle with the mul node.
-
-The semantics of lazily evaluating nodes doesn't apply to phi nodes---they, as mentioned earlier, latch values as soon as the control token passes through their associated region.
-This is important, since cycles amongst data nodes are allowed in Hercules IR, but only if the cycle contains a phi node (or a reduce node, which we'll introduce later).
-Thus, we can always lazily evaluate non-phi data nodes on the fly without running into a cycle.
-
-Let's look at an example that uses fork-join nests, arrays, and dynamic constants.
-
-\centerline{\includegraphics[width=0.7\textwidth]{simple3.png}}
-
-This example takes two arrays, representing vectors, and calculates the dot product of them.
-For this example, we use the fork-join control structure in Hercules IR, rather than an unstructured loop.
-This has two advantages:
-
-\begin{itemize}
-  \item Fork-joins are an explicit construct in the IR, so they are easier to work with than unstructured loops (they are also much simpler in structure).
-  \item This construct represents both SIMT computation and reductions explicitly, which simplifies compiler analyses and code generation (more on this below).
-\end{itemize}
-
-The parameters are the input arrays---we use read nodes (as data nodes) to index into the arrays inside the fork-join.
-This function takes one dynamic constant input, as indicated by the \texttt{<1>} after the function name at the top.
-The arrays are parameterized by a dynamic constant size, \texttt{\#0} (the one and only dynamic constant argument to this function).
-This dynamic constant is also used to indicate the number of threads spawned inside the fork-join.
-
-Fork-joins always form pairs---control always starts from the fork, and always ends at the join (the fork dominates the join, and the join post-dominates the fork).
-Conceptually, when the control token reaches the fork, $N$ control tokens leave the fork to its control user, where $N$ is the runtime value of the dynamic constant replication factor of the fork.
-Once those $N$ control tokens reach the join, one control token leaves to join to its control user.
-Each control token inside the fork-join executes the same static code.
-Since there may be control nodes in between the fork and join nodes, the control tokens may execute different dynamic code.
-
-The fork may have (almost always exactly one) thread ID user node.
-This data node outputs the ID of the thread currently executing.
-Each control token is assigned a different corresponding ID, ranging from $0$ to $N-1$, inclusive.
-Access to data depending on the thread ID node of a fork outside the fork-join must be mediated through a reduce node---if we could access the thread ID node, or some data that depended on the thread ID node, outside the fork-join, what value should that data node output?
-The reduce node represents a reduction over values computed based on the thread ID by each of the $N$ control tokens.
-The reduce node takes three inputs---the join node of the fork-join nest being guarded, an initial reduction value, and the value computed per control token that needs to be reduced.
-The reduce node outputs the value resulting from the reduction.
-To actually form a reduction loop, the reduce node is available as a use inside the fork-join.
-Commonly, this forms a loop between some data node depending on the thread ID and the reduce node.
-In the example above, the reduce node is in a cycle with an add node.
-This represents a summation reduction over the output of the mul node, representing the elementwise multiplication of the two input vectors.
-Semantically, reducting starts from ID $0$, and ends with ID $N-1$.
-If the reduce node isn't used to form a reduction loop, then the reduce node outputs the value corresponding to control token $N-1$.
-
-\section{Juno}\label{sec:juno}
-
-The Juno frontend is our current frontend language for Hercules, it is designed to be a good match for Hercules IR but the design choices we made for Juno are not necessarily the only ones that could be made and it is likely many other languages could be compiled to Hercules IR as well.
-Juno is a relatively simple language based on Rust with some influence from C and some functional languages.
-Juno can be described by the following standard classifications of programming languages:
-
-\begin{itemize}
-  \item \emph{Imperative}: Juno is an imperative language
-  \item \emph{Strongly-Typed}: Juno is a strongly typed language, the type system has a set of standard base types (booleans, singed and unsigned integers of standard bit-lengths, and single and double precision floating point numbers).
-    The type system also allows the user to define struct types and enum types, both like those in Rust; like Rust Juno also has a product type denoted by $(\tau_0, \cdots, \tau_n)$ and the indices of these values can be accessed by $.0, \cdots, .n$ as in Rust.
-    The Juno type system also has types for arrays, denoted by $A[n_1, \cdots, n_k]$ for a type $A$ and dynamic constants $n_i$; like in Hercules IR the dimensions of an array must be specified using dynamic constants.
-    In Juno, casts are only permitted between primitive types, in particular values can be cast between any of the numeric types.
-  \item \emph{First-Order}: Juno is a first-order language, this means that functions are not first-class citizens and cannot be used as values.
-    In other words, there are no function pointers or closures.
-  \item \emph{Parametric Polymorphism}: Juno has polymorphic functions which allows us to define functions on generic types so we can then instantiate them with different types.
-    Unlike C++ style templates where the function is not typed until it is instantiated, in Juno we type check each polymorphic function generically to ensure any instance will be well-typed.
-    To achieve this, we also allow functions to restrict what types a type parameter can take on, currently this is restricted to only numeric and integer types, which allow us to define polymorphic functions that make use of mathematical operators that can only be applied to those types.
-  \item \emph{Mutable-Value Semantics}: Juno uses Mutable-Value Semantics (MVS).
-    In this semantics, everything is a value, this means that the language has no references or pointers and the semantics don't have to model memory as a result.
-    Unlike Hercules IR, Juno uses \emph{mutable}-value semantics which means that the code written in Juno allows assignments to update fields of structs and products as well as elements in arrays.
-    As a result of this, Juno's use of MVS is not terribly obvious from the programmer perspective, except for the lack of references.
-    One final feature of MVS to note is that we provide a call-by-return construct (indicated by labeling a function argument as \texttt{inout}) as this allows us to update values in the caller without having to introduce complex mutations.
-\end{itemize}
-
-To see this in action, we'll show some examples of Juno code that correspond to the example Hercules IR codes shown earlier.
-Note that these examples generate similar IR to those sown above, but not identical IR due to how certain features are generated.
-
-\begin{lstlisting}[style=juno]
-fn simple1(x : i32, y : i32) -> i32 {
-  return x + y;
-}
-\end{lstlisting}
-
-We begin very simply but with an example of the function syntax of Juno.
-This takes a Rust style form, with functions declared by the \lstinline[style=juno]{fn} keyword and then arguments specified with their types following them; the return type of the function is then specified following the \texttt{->}.
-This function, therefore, takes two integer \lstinline[style=juno]{i32} parameters and returns one as well.
-
-\begin{lstlisting}[style=juno]
-fn simple2(n : i32) -> i32 {
-  let res : i32 = 1;
-
-  for i : i32 = 0 to n {
-    res *= i + 1;
-  }
-
-  return res;
-}
-\end{lstlisting}
-
-In this example we see the declaration of a local variable \texttt{res}, again using Rust-like syntax.
-The for-loop takes a slightly non-standard form, but this loop here just indicates a loop for $i = 0, 1, \cdots, n-1$.
-While not shown, we can also specify the step size of a for loop, though this must be an integer literal.
-We also have \lstinline[style=juno]{while} loops which can be used for less structured iteration.
-
-\begin{lstlisting}[style=juno]
-fn simple3<n : usize>(a : i32[n], b : i32[n]) -> i32[n] {
-  let res : i32 = 0;
-
-  for i = 0 to n {
-    res += a[i] * b[i];
-  }
-
-  return res;
-}
-\end{lstlisting}
-
-This example also shows us how dynamic constants are declared and used in Juno.
-The angle bracket notation is used for both type parameters (not shown here) and for dynamic constants, in this example we declare \texttt{n} to be a dynamic constant (by specifying its kind as \lstinline[style=juno]{usize}).
-In the program itself, dynamic constants can just be used like any other value except that they cannot be modified.
-As we've said, the sizes of arrays are specified by dynamic constants, and this is what is denoted by the type \lstinline[style=juno]{i32[n]} which indicates an array of \lstinline[style=juno]{i32} of length \texttt{n}.
-
-It is worth noting that in Juno there are no explicit parallel constructs; we can for-loops (or even while-loops) to represent both sequential loops and loops that can be converted into fork-joins in the IR.
-
-As a final example, that shows a handful of other features, we show a polymorphic matrix multiplication in Juno.
-
-\begin{lstlisting}[style=juno]
-fn matmul<t : number, n, m, q : usize>(a : t[n, m], b : t[m, q]) -> t[n, q] {
-  let res : t[n, q];
-
-  for i = 0 to n {
-    for k = 0 to q {
-      let val : t = 0;
-      for j = 0 to m {
-        val += a[i, j] * b[j, k];
-      }
-      res[i, k] = val;
-    }
-  }
-
-  return res;
-}
-\end{lstlisting}
-
-This example shows how type parameters work in Juno, where we can declare \lstinline[style=juno]{t : number} saying that \texttt{t} is some numeric type, which allows us to define matrix multiplication generically over this type.
-We can also see that Juno has mutable values because we perform multiple assignments to \texttt{res} in the loops.
-
-\subsection{Juno Scheduler}
-In addition to the Juno frontend, we also have the Juno scheduler, which provides a scheduling language that is used to construct the plans (containing partition information and schedule information) for code written in Juno.
-To do this, we introduce labels into the frontend language which we then reference from the scheduling language.
-For example, for simple3 we can achieve the schedule which places the loop in its own partition and indicates that it should be vectorized using the following modified Juno code.
-
-\begin{lstlisting}[style=juno]
-fn simple3<n : usize>(a : i32[n], b : i32[n]) -> i32[n] {
-  let res : i32 = 0;
-
-  @loop
-  for i = 0 to n {
-    res += a[i] * b[i];
-  }
-
-  return res;
-}
-\end{lstlisting}
-
-We indicate labels with an at-sign (@) followed by an identifier name.
-The label is then assigned to the next statement which follows it, this can be a single statement, a loop or conditional, or even a block of code encloded in curly-braces.
-In our scheduling then, setting a label as contained in a particular partition sets all of the code contained within that labeled statement into that partition.
-On the other hand, assigning a schedule to a label assigns that schedule only to the top-level construct.
-For example, the schedule for the above code is as follows
-
-\begin{lstlisting}[style=junoScheduler]
-function simple3 {
-  partition @loop on cpu
-  vectorize @loop ^^
-}
-\end{lstlisting}
-
-This indicates that the loop and its body in the function should be set into their own partition which will run on the CPU and also indicates that this loop should be vectorized.
-
-\section{Runtime}\label{sec:runtime}
-
-The Hercules runtime is the body of code responsible for actually queuing work on various devices simultaneously and managing communication between the devices.
-There are several challenges associated with runtimes for previous heterogeneous systems:
-
-\begin{itemize}
-  \item They must manage $N$ APIs for launching work, managing memory, and synchronizing with $N$ different kinds of devices.
-
-  \item Task parallelism dictates that we must be able to schedule work in an overlapping manner---executing a kernel on the GPU should not preclude us from running unrelated work on the CPU.
-
-  \item Managing memory across devices is challenging, especially if one is trying to dynamically minimize unnecessary cross-device communication.
-\end{itemize}
-
-We've decided to take a different approach with the Hercules runtime, which is motivated by the following observations:
-
-\begin{itemize}
-  \item The real ``value add'' of a heterogeneous programming system is making it easy to execute code on multiple devices in the same program.
-    Thus, supporting $N$ device-specific APIs is actually part of the job.
-
-  \item Thread pools, asynchronous event loops, and parallel runtime systems are a very well understood.
-    We would like to take advantage of existing techniques \textit{and implementations} for sanely running several tasks at one time on semi-arbitrary machines---this includes microcontrollers without a traditional preemptive scheduling primitive.
-    This wheel is not worth reinventing.
-
-  \item Modern applications often already include infrastructure for running several concurrent tasks, sometimes in parallel.
-    Forcing users of Hercules to add another thread pool, state machine executor, or other mechanism for running Hercules code in a task parallel fashion is not acceptable.
-    We want Hercules to be plug-in-play for users who already have mechanisms for running Rust code in parallel.
-\end{itemize}
-
-\subsection{An Aside: Async Rust}
-
-Rust has several language features for representing asynchronous computation---these features are often collectively referred to as ``Async Rust''.
-Here's a 30,000 feet view of what Async Rust is:
-
-\begin{itemize}
-  \item The Rust standard library includes a trait called \texttt{Future}.
-    Futures are objects that can be polled repeatedly until they produce a result.
-    Conceptually, each poll corresponds to performing computation until reaching a blocking point.
-    Once all the blocking points have passed and the computation represented has finished, polling the Future returns the result of the computation.
-    The prototypical example is representing a file read.
-    The read is dispatched to the system on the first poll, and the user of the Future must repeatedly call poll until the read is finished and a datum is actually returned.
-    In a real application, the user would likely go and do something else in between calls to poll.
-
-  \item \texttt{async} is a keyword that can be used to mark functions or blocks in Rust.
-    This converts a function into a Future that can be polled.
-    They provide a very clean way in which Futures can be built by users of Rust.
-
-  \item To run several Futures in parallel, most applications use an ``executor'', which is an object that runs many Futures on many threads (by repeatedly calling poll on each Future, making sure each thread has a set of Futures to run, etc).
-    Popular executors include \texttt{tokio} and \texttt{async-std}.
-\end{itemize}
-
-For a more detailed breakdown of Async Rust, see \href{https://rust-lang.github.io/async-book/}{Asynchronous Programming in Rust}.
-
-\subsection{Another Aside: Proc Macros}
-
-Rust has ``proc'' macros for generating arbitrary Rust code at compile time, using Rust.
-Proc macros are separated into specific crates which are compiled before other crates in a project.
-Once the proc macro is compiled, other crates (that possibly use proc macros) can be compiled.
-
-\subsection{The Runtime}
-
-A user loads a Hercules module using a proc macro in their host Rust code.
-This proc macro generates Rust async function wrappers for all of the Hercules functions in the Hercules module.
-These wrappers effectively implement the runtime facilities on a per Hercules function basis.
-These wrappers are generated using metadata stored alongside the Hercules module, called a manifest.
-The manifest plus the Hercules module itself are loaded from a \texttt{.hbin} file.
-
-Here's an example host code written in Rust:
-
-\begin{lstlisting}[style=colouredRust]
-hercules_rt::use_hbin!("my_module.hbin");
-
-fn main() {
-    async_std::task::block_on(async {
-        println!("{}", my_add(1, 2).await);
-    });
-}
-\end{lstlisting}
-
-The \lstinline[style=colouredRust]{use_hbin!} macro loads the Hercules module and manifest from the specified file.
-This file contains a Hercules function, \texttt{add}, which adds two integers.
-The proc macro automatically generates a type safe Rust wrapper around the x86-64 object code also contained in the Hercules module.
-In main, we use the \texttt{async\_std} crate for its executor.
-We ask it to block on executing an async block which just prints the result of executing the Hercules function on $1$ and $2$.
-Using proc macros, we can translate between the type system of compiled Hercules functions and source-level Rust in a compile-time checked manner.
-
-The advantages of using Async Rust and an external executor is two-fold:
-\begin{itemize}
-  \item We don't have to write a parallel runtime that runs on the host - instead, we can leverage existing parallel runtimes that integrate cleanly with other software written in Rust
-  \item We can abstract asychronous launches and synchronization amongst the $N$ device APIs using Rust Futures - this way, we can use \textit{existing} Async Rust executors to manage execution across many devices in a heterogeneous machine
-\end{itemize}
-
-\end{document}
diff --git a/reports/technical1/simple1.png b/reports/technical1/simple1.png
deleted file mode 100644
index bdb40c4c561a97acc0de61f5d5a298f480892912..0000000000000000000000000000000000000000
Binary files a/reports/technical1/simple1.png and /dev/null differ
diff --git a/reports/technical1/simple2.png b/reports/technical1/simple2.png
deleted file mode 100644
index 6ca87652cff398870432c34ba1557d3a1d0cb01f..0000000000000000000000000000000000000000
Binary files a/reports/technical1/simple2.png and /dev/null differ
diff --git a/reports/technical1/simple3.png b/reports/technical1/simple3.png
deleted file mode 100644
index 5785bf3270ef8b4ddafb8ed53d1ba55fa785d09e..0000000000000000000000000000000000000000
Binary files a/reports/technical1/simple3.png and /dev/null differ