From 97dd53d5effb08d61bd737557cce8ce0e3a8567f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 4 Jul 2022 15:26:02 -0400 Subject: [PATCH] remove ancient tex files --- tex/final-presentation/latexmkrc | 12 - tex/final-presentation/rust-logo-512x512.png | Bin 96029 -> 0 bytes tex/final-presentation/slides.tex | 444 ------------- tex/report/latexmkrc | 12 - tex/report/miri-report.tex | 663 ------------------- 5 files changed, 1131 deletions(-) delete mode 100644 tex/final-presentation/latexmkrc delete mode 100644 tex/final-presentation/rust-logo-512x512.png delete mode 100644 tex/final-presentation/slides.tex delete mode 100644 tex/report/latexmkrc delete mode 100644 tex/report/miri-report.tex diff --git a/tex/final-presentation/latexmkrc b/tex/final-presentation/latexmkrc deleted file mode 100644 index 23aa1a481b3e..000000000000 --- a/tex/final-presentation/latexmkrc +++ /dev/null @@ -1,12 +0,0 @@ -# vim: ft=perl - -$pdf_mode = 1; -$pdflatex = 'lualatex --shell-escape %O %S'; -$out_dir = 'out'; - -# This improves latexmk's detection of source files and generated files. -$recorder = 1; - -# Ignore always-regenerated *.pyg files from the minted package when considering -# whether to run pdflatex again. -$hash_calc_ignore_pattern{'pyg'} = '.*'; diff --git a/tex/final-presentation/rust-logo-512x512.png b/tex/final-presentation/rust-logo-512x512.png deleted file mode 100644 index 38484c670e01f3f355672d6c95f79f035a963a44..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 96029 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 - \only<#1>{\pgfkeysalso{highlight}} - \alt<#1->{}{\pgfkeysalso{invisible}} - }, -} - -\title{Miri} -\subtitle{An interpreter for Rust's mid-level intermediate representation} -\author{ - Scott Olson - \texorpdfstring{\\ \scriptsize{Supervisor: Christopher Dutchyn}}{} -} -\institute{ - CMPT 400 \\ - University of Saskatchewan -} -\date{} -\titlegraphic{ - \includegraphics[width=64px,height=64px]{rust-logo-512x512.png} \\ - \scriptsize{\url{https://www.rust-lang.org}} -} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Intro slides -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\begin{document} - -\maketitle - -\begin{frame}[fragile] - \frametitle{What is Rust? \small{[review]}} - - According to the website\dots - - \begin{quote} - \textbf{Rust} is a systems programming language that runs blazingly fast, - prevents nearly all segfaults, and guarantees thread safety. - \end{quote} - - It's a new programming language from Mozilla, and it looks like this: - - \begin{minted}[ - autogobble, - fontsize=\footnotesize, - mathescape, - xleftmargin=.3in, - ]{rust} - fn factorial(n: u64) -> u64 { - (1..n).fold(1, |a, b| a * b) - } - - fn main() { - for x in 1..6 { - println!("{}", factorial(x)); - } - // $\Rightarrow$ 1 - // $\Rightarrow$ 1 - // $\Rightarrow$ 2 - // $\Rightarrow$ 6 - // $\Rightarrow$ 24 - } - \end{minted} -\end{frame} - -\begin{frame} - \frametitle{How does Rust compile code? \onslide<-6>{\small{[review]}}} - - \begin{center} - \begin{tikzpicture}[x=4cm, y=3.5cm, auto, rounded corners] - \tikzstyle{basic-stage}=[rectangle, draw, thick, align=center] - \tikzstyle{stage}=[basic-stage, font=\tiny] - \tikzstyle{pass}=[thick, -stealth] - \tikzstyle{pass-label}=[font=\footnotesize] - - \node[basic-stage] (src) at (0,0) {Source\\Code}; - \node[basic-stage] (mach) at (2,-1) {Machine\\Code}; - - \draw<1>[pass, out=0, in=180] - (src.east) to node[font=\Huge] {?} (mach.west); - - \node[stage, intro=<2>] (ast) at (1,0) - {\normalsize{AST} \\ Abstract Syntax Tree}; - \draw[pass, intro=<2>] - (src) -- node[pass-label] {Parse} (ast); - - \node[stage, intro=<3>] (hir) at (2,0) - {\normalsize{HIR} \\ High-level Intermediate\\Representation}; - \draw[pass, intro=<3>] - (ast) -- node[pass-label] {Simplify} (hir); - - \node[stage, intro=<4>] (mir) at (0,-1) - {\normalsize{MIR} \\ Mid-level Intermediate\\Representation}; - \path (hir.south) -- coordinate (middle) (mir.north); - \draw[pass, intro=<4>] - (hir.south) |- (middle) -| (mir.north); - \node[pass-label, above, intro=<4>] at (middle) {Lower}; - - \node[stage, intro=<5>] (llvm) at (1,-1) - {\normalsize{LLVM IR} \\ Low-level Intermediate\\Representation}; - \draw[pass, intro=<5>] - (mir) -- node[pass-label] {Translate} (llvm); - - \draw<6->[pass, intro=<6>] - (llvm) -- node[pass-label] {Magic} (mach); - - \node[stage, intro=<7>] (exec) at (1,-1.75) - {\normalsize{Execution}}; - \draw[pass, intro=<7>] - (mach) -- node[pass-label] {CPU} (exec); - - \draw[pass, intro=<8>] - (mir) -- node[pass-label] {Miri} (exec); - \end{tikzpicture} - \end{center} -\end{frame} - -\begin{frame} - \frametitle{Why build Miri?} - \begin{itemize} - \item For fun and learning. - - \item I originally planned to use it for testing the compiler and execution - of unsafe code, but shifted my goals along the way. \pause - - \item Now it serves as an experimental implementation of the upcoming - compile-time function evaluation feature in Rust. \pause - - \begin{itemize} - \item Similar to C++14's \mintinline{cpp}{constexpr} feature. - - \item You can do complicated calculations at compile time and compile - their \emph{results} into the executable. \pause - - \item For example, you can compute a ``perfect hash function'' for a - statically-known map at compile-time and have guaranteed no-collision - lookup at runtime. \pause - - \item Miri actually supports far more of Rust than C++14's - \mintinline{cpp}{constexpr} does of C++ --- even heap allocation and - unsafe code. - \end{itemize} - \end{itemize} -\end{frame} - -\begin{frame} - \frametitle{How was it built?} - - At first I wrote a naive version with a number of downsides: - - \begin{itemize} - \item represented values in a traditional dynamic language format, where - every value was the same size. - - \item didn't work well for aggregates (structs, enums, arrays, etc.). - - \item made unsafe programming tricks that make assumptions about low-level - value layout essentially impossible. - \end{itemize} -\end{frame} - -\begin{frame} - \frametitle{How was it built?} - \begin{itemize} - \item Later, a Rust compiler team member proposed a ``Rust abstract - machine'' with specialized value layout which solved my previous problems. - \pause - - \item His proposal was intended for a compile-time function evaluator in the - Rust compiler, so I effectively implemented an experimental version of - that. \pause - - \item After this point, making Miri work well was primarily a software - engineering problem. - \end{itemize} -\end{frame} - -\begin{frame} - \frametitle{Data layout} - \begin{itemize} - \item Memory in Miri is literally a HashMap from ``allocation IDs'' to - ``abstract allocations''. - - \item Allocations are represented by: \pause - \begin{enumerate} - \item An array of \textbf{raw bytes} with a size based on the type of - the value \pause - \item A set of \textbf{relocations} --- pointers into other abstract - allocations \pause - \item A mask determining which bytes are \textbf{undefined} - \end{enumerate} - \end{itemize} -\end{frame} - -\begin{frame}[fragile] - \frametitle{\texttt{square} example} - \begin{center} - \begin{minted}[autogobble,fontsize=\scriptsize]{rust} - // Rust - fn square(n: u64) -> u64 { - n * n - } - - // Generated MIR - fn square(arg0: u64) -> u64 { - let var0: u64; // n // On function entry, Miri creates - // virtual allocations for all the - // arguments, variables, and - // temporaries. - - bb0: { - var0 = arg0; // Copy the argument into `n`. - return = Mul(var0, var0); // Multiply `n` with itself. - goto -> bb1; // Jump to basic block `bb1`. - } - - bb1: { - return; // Return from the current fn. - } - } - \end{minted} - \end{center} -\end{frame} - -\begin{frame}[fragile] - \frametitle{\texttt{sum} example} - \begin{center} - \begin{minted}[autogobble,fontsize=\tiny]{rust} - // Rust - fn sum() -> u64 { - let mut sum = 0; let mut i = 0; - while i < 10 { sum += i; i += 1; } - sum - } - - // Generated MIR - fn sum() -> u64 { - let mut var0: u64; // sum - let mut var1: u64; // i - let mut tmp0: bool; - - bb0: { - // sum = 0; i = 0; - var0 = const 0u64; var1 = const 0u64; goto -> bb1; - } - bb1: { - // if i < 10 { goto bb2; } else { goto bb3; } - tmp0 = Lt(var1, const 10u64); - if(tmp0) -> [true: bb2, false: bb3]; - } - bb2: { - var0 = Add(var0, var1); // sum = sum + i; - var1 = Add(var1, const 1u64); // i = i + 1; - goto -> bb1; - } - bb3: { - return = var0; goto -> bb4; - } - bb4: { return; } - } - \end{minted} - \end{center} -\end{frame} - -\begin{frame}[fragile] - \frametitle{Heap allocations!} - \begin{minted}[autogobble,fontsize=\scriptsize]{rust} - fn make_vec() -> Vec { - // Empty array with space for 4 bytes - allocated on the heap! - let mut vec = Vec::with_capacity(4); - // Initialize the first two slots. - vec.push(1); - vec.push(2); - vec - } - - // For reference: - // struct Vec { capacity: usize, data: *mut T, length: usize } - - // Resulting allocations (on 32-bit little-endian architectures): - // Region A: - // 04 00 00 00 00 00 00 00 02 00 00 00 - // └───(B)───┘ - // - // Region B: - // 01 02 __ __ (underscores denote undefined bytes) - \end{minted} - - \footnotesize{Evaluating the above involves a number of compiler built-ins, - ``unsafe'' code blocks, and more inside the standard library, - but Miri handles it all.} -\end{frame} - -\begin{frame}[fragile] - \frametitle{Unsafe code!} - \begin{minted}[autogobble,fontsize=\scriptsize]{rust} - fn out_of_bounds() -> u8 { - let mut vec = vec![1, 2] - unsafe { *vec.get_unchecked(5) } - } - - // test.rs:3: error: pointer offset outside bounds of allocation - // test.rs:3: unsafe { *vec.get_unchecked(5) } - // ^~~~~~~~~~~~~~~~~~~~~ - - fn undefined_bytes() -> u8 { - let mut vec = Vec::with_capacity(10); - unsafe { *vec.get_unchecked(5) } - } - - // test.rs:3: error: attempted to read undefined bytes - // test.rs:3: unsafe { *vec.get_unchecked(5) } - // ^~~~~~~~~~~~~~~~~~~~~ - \end{minted} -\end{frame} - -\begin{frame} - \frametitle{What can't Miri do?} - \begin{itemize} - \item Miri can't do all the stuff I didn't implement yet. :) - \begin{itemize} - \item non-trivial casts - \item function pointers - \item calling destructors and freeing memory - \item taking target architecture endianess and alignment information - into account when computing data layout - \item handling all constants properly (but, well, Miri might be - replacing the old constants system) - \end{itemize} - \pause - - \item Miri can't do foreign function calls (e.g. calling functions defined - in C or C++), but there is a reasonable way it could be done with libffi. - \begin{itemize} - \item On the other hand, for constant evaluation in the compiler, you - want the evaluator to be deterministic and safe, so FFI calls might be - banned anyway. - \end{itemize} - \pause - - \item Without quite some effort, Miri will probably never handle inline - assembly... - \end{itemize} -\end{frame} - -\begin{frame} - \begin{center} - \LARGE{Questions?} - \end{center} -\end{frame} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Extra slides -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\begin{frame}[fragile] - \frametitle{\texttt{varN} vs. \texttt{argN}} - \begin{center} - \begin{minted}[autogobble,fontsize=\scriptsize]{rust} - // Rust - type Pair = (u64, u64); - fn swap((a, b): Pair) -> Pair { - (b, a) - } - - // Generated MIR - fn swap(arg0: (u64, u64)) -> (u64, u64) { - let var0: u64; // a - let var1: u64; // b - - bb0: { - var0 = arg0.0; // get the 1st part of the pair - var1 = arg0.1; // get the 2nd part of the pair - return = (var1, var0); // build a new pair in the result - goto -> bb1; - } - - bb1: { - return; - } - } - \end{minted} - \end{center} -\end{frame} - -\begin{frame}[fragile] - \frametitle{\texttt{factorial} example} - \begin{center} - \begin{minted}[autogobble,fontsize=\tiny]{rust} - // Rust - fn factorial(n: u64) -> u64 { - (1..n).fold(1, |a, b| a * b) - } - - // Generated MIR - fn factorial(arg0: u64) -> u64 { - let var0: u64; // n - let mut tmp0: Range; // Miri calculates sizes for generics like Range. - let mut tmp1: [closure]; - - bb0: { - var0 = arg0; - - // tmp0 = 1..n - tmp0 = Range { start: const 1u64, end: var0 }; - - // tmp1 = |a, b| a * b - tmp1 = [closure]; - - // This loads the MIR for the `fold` fn from the standard library. - // In general, MIR for any function from any library can be loaded. - // return tmp0.fold(1, tmp1) - return = Range::fold(tmp0, const 1u64, tmp1) -> bb1; - } - - bb1: { - return; - } - } - \end{minted} - \end{center} -\end{frame} - -\end{document} diff --git a/tex/report/latexmkrc b/tex/report/latexmkrc deleted file mode 100644 index 23aa1a481b3e..000000000000 --- a/tex/report/latexmkrc +++ /dev/null @@ -1,12 +0,0 @@ -# vim: ft=perl - -$pdf_mode = 1; -$pdflatex = 'lualatex --shell-escape %O %S'; -$out_dir = 'out'; - -# This improves latexmk's detection of source files and generated files. -$recorder = 1; - -# Ignore always-regenerated *.pyg files from the minted package when considering -# whether to run pdflatex again. -$hash_calc_ignore_pattern{'pyg'} = '.*'; diff --git a/tex/report/miri-report.tex b/tex/report/miri-report.tex deleted file mode 100644 index 27a063de0272..000000000000 --- a/tex/report/miri-report.tex +++ /dev/null @@ -1,663 +0,0 @@ -% vim: tw=100 - -\documentclass[twocolumn]{article} -\usepackage{blindtext} -\usepackage[hypcap]{caption} -\usepackage{fontspec} -\usepackage[colorlinks, urlcolor={blue!80!black}]{hyperref} -\usepackage[outputdir=out]{minted} -\usepackage{relsize} -\usepackage{xcolor} - -\setmonofont{Source Code Pro}[ - BoldFont={* Medium}, - BoldItalicFont={* Medium Italic}, - Scale=MatchLowercase, -] - -\newcommand{\rust}[1]{\mintinline{rust}{#1}} - -\begin{document} - -\title{Miri: \\ \smaller{An interpreter for Rust's mid-level intermediate representation}} -\author{Scott Olson\footnote{\href{mailto:scott@solson.me}{scott@solson.me}} \\ - \smaller{Supervised by Christopher Dutchyn}} -\date{April 12th, 2016} -\maketitle - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\section{Abstract} - -The increasing need for safe low-level code in contexts like operating systems and browsers is -driving the development of Rust\footnote{\url{https://www.rust-lang.org}}, a programming language -promising high performance without the risk of memory unsafety. To make programming more convenient, -it's often desirable to be able to generate code or perform some computation at compile-time. The -former is mostly covered by Rust's existing macro feature or build-time code generation, but the -latter is currently restricted to a limited form of constant evaluation capable of little beyond -simple math. - -The architecture of the compiler at the time the existing constant evaluator was built limited its -potential for future extension. However, a new intermediate representation was recently -added\footnote{\href{https://github.com/rust-lang/rfcs/blob/master/text/1211-mir.md}{Rust RFC \#1211: Mid-level IR (MIR)}} -to the Rust compiler between the abstract syntax tree and the back-end LLVM IR, called mid-level -intermediate representation, or MIR for short. This report will demonstrate that writing an -interpreter for MIR is a surprisingly effective approach for supporting a large proportion of Rust's -features in compile-time execution. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\section{Background} - -The Rust compiler generates an instance of \rust{Mir} for each function [\autoref{fig:mir}]. Each -\rust{Mir} structure represents a control-flow graph for a given function, and contains a list of -``basic blocks'' which in turn contain a list of statements followed by a single terminator. Each -statement is of the form \rust{place = rvalue}. An \rust{Place} is used for referencing variables -and calculating addresses such as when dereferencing pointers, accessing fields, or indexing arrays. -An \rust{Rvalue} represents the core set of operations possible in MIR, including reading a value -from an place, performing math operations, creating new pointers, structures, and arrays, and so -on. Finally, a terminator decides where control will flow next, optionally based on the value of a -boolean or integer. - -\begin{figure}[ht] - \begin{minted}[autogobble]{rust} - struct Mir { - basic_blocks: Vec, - // ... - } - - struct BasicBlockData { - statements: Vec, - terminator: Terminator, - // ... - } - - struct Statement { - place: Place, - rvalue: Rvalue - } - - enum Terminator { - Goto { target: BasicBlock }, - If { - cond: Operand, - targets: [BasicBlock; 2] - }, - // ... - } - \end{minted} - \caption{MIR (simplified)} - \label{fig:mir} -\end{figure} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\section{First implementation} - -\subsection{Basic operation} - -To investigate the possibility of executing Rust at compile-time I wrote an interpreter for MIR -called Miri\footnote{\url{https://github.com/solson/miri}}. The structure of the interpreter closely -mirrors the structure of MIR itself. It starts executing a function by iterating the statement list -in the starting basic block, translating the place into a pointer and using the rvalue to decide -what to write into that pointer. Evaluating the rvalue may involve reads (such as for the two sides -of a binary operation) or construction of new values. When the terminator is reached, it is used to -decide which basic block to jump to next. Finally, Miri repeats this entire process, reading -statements from the new block. - -\subsection{Function calls} - -To handle function call terminators\footnote{Calls occur only as terminators, never as rvalues.}, -Miri is required to store some information in a virtual call stack so that it may pick up where it -left off when the callee returns. Each stack frame stores a reference to the \rust{Mir} for the -function being executed, its local variables, its return value location\footnote{Return value -pointers are passed in by callers.}, and the basic block where execution should resume. When Miri -encounters a \rust{Return} terminator in the MIR, it pops one frame off the stack and resumes the -previous function. Miri's execution ends when the function it was initially invoked with returns, -leaving the call stack empty. - -It should be noted that Miri does not itself recurse when a function is called; it merely pushes a -virtual stack frame and jumps to the top of the interpreter loop. Consequently, Miri can interpret -deeply recursive programs without overflowing its native call stack. This approach would allow Miri -to set a virtual stack depth limit and report an error when a program exceeds it. - -\subsection{Flaws} - -This version of Miri supported quite a bit of the Rust language, including booleans, integers, -if-conditions, while-loops, structures, enums, arrays, tuples, pointers, and function calls, -requiring approximately 400 lines of Rust code. However, it had a particularly naive value -representation with a number of downsides. It resembled the data layout of a dynamic language like -Ruby or Python, where every value has the same size\footnote{An \rust{enum} is a discriminated union -with a tag and space to fit the largest variant, regardless of which variant it contains.} in the -interpreter: - -\begin{minted}[autogobble]{rust} - enum Value { - Uninitialized, - Bool(bool), - Int(i64), - Pointer(Pointer), // index into stack - Aggregate { - variant: usize, - data: Pointer, - }, - } -\end{minted} - -This representation did not work well for aggregate types\footnote{That is, structures, enums, -arrays, tuples, and closures.} and required strange hacks to support them. Their contained values -were allocated elsewhere on the stack and pointed to by the aggregate value, which made it more -complicated to implement copying aggregate values from place to place. - -Moreover, while the aggregate issues could be worked around, this value representation made common -unsafe programming tricks (which make assumptions about the low-level value layout) fundamentally -impossible. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\section{Current implementation} - -Roughly halfway through my time working on Miri, Eduard -Burtescu\footnote{\href{https://github.com/eddyb}{eddyb on GitHub}} from the Rust compiler -team\footnote{\url{https://www.rust-lang.org/team.html\#Compiler}} made a post on Rust's internal -forums about a ``Rust Abstract Machine'' -specification\footnote{\href{https://internals.rust-lang.org/t/mir-constant-evaluation/3143/31}{Burtescu's -reply on ``MIR constant evaluation''}} which could be used to implement more powerful compile-time -function execution, similar to what is supported by C++14's \mintinline{cpp}{constexpr} feature. -After clarifying some of the details of the data layout with Burtescu via IRC, I started -implementing it in Miri. - -\subsection{Raw value representation} - -The main difference in the new value representation was to represent values by ``abstract -allocations'' containing arrays of raw bytes with different sizes depending on their types. This -mimics how Rust values are represented when compiled for physical machines. In addition to the raw -bytes, allocations carry information about pointers and undefined bytes. - -\begin{minted}[autogobble]{rust} - struct Memory { - map: HashMap, - next_id: AllocId, - } - - struct Allocation { - bytes: Vec, - relocations: BTreeMap, - undef_mask: UndefMask, - } -\end{minted} - -\subsubsection{Relocations} - -The abstract machine represents pointers through ``relocations'', which are analogous to relocations -in linkers\footnote{\href{https://en.wikipedia.org/wiki/Relocation_(computing)}{Relocation -(computing) - Wikipedia}}. Instead of storing a global memory address in the raw byte representation -like on a physical machine, we store an offset from the start of the target allocation and add an -entry to the relocation table which maps the index of the offset bytes to the target allocation. - -In \autoref{fig:reloc}, the relocation stored at offset 0 in \rust{y} points to offset 2 in \rust{x} -(the 2nd 16-bit integer). Thus, the relocation table for \rust{y} is \texttt{\{0 => -x\}}, meaning the next $N$ bytes after offset 0 denote an offset into allocation \rust{x} where $N$ -is the size of a pointer (4 in this example). The example shows this as a labelled line beneath the -offset bytes. - -In effect, the abstract machine represents pointers as \rust{(allocation_id, offset)} pairs. This -makes it easy to detect when pointer accesses go out of bounds. - -\begin{figure}[hb] - \begin{minted}[autogobble]{rust} - let x: [i16; 3] = [0xAABB, 0xCCDD, 0xEEFF]; - let y = &x[1]; - // x: BB AA DD CC FF EE (6 bytes) - // y: 02 00 00 00 (4 bytes) - // └───(x)───┘ - \end{minted} - \caption{Example relocation on 32-bit little-endian} - \label{fig:reloc} -\end{figure} - -\subsubsection{Undefined byte mask} - -The final piece of an abstract allocation is the undefined byte mask. Logically, we store a boolean -for the definedness of every byte in the allocation, but there are multiple ways to make the storage -more compact. I tried two implementations: one based on the endpoints of alternating ranges of -defined and undefined bytes and the other based on a bitmask. The former is more compact but I found -it surprisingly difficult to update cleanly. I currently use the much simpler bitmask system. - -See \autoref{fig:undef} for an example of an undefined byte in a value, represented by underscores. -Note that there is a value for the second byte in the byte array, but it doesn't matter what it is. -The bitmask would be $10_2$, i.e.\ \rust{[true, false]}. - -\begin{figure}[hb] - \begin{minted}[autogobble]{rust} - let x: [u8; 2] = unsafe { - [1, std::mem::uninitialized()] - }; - // x: 01 __ (2 bytes) - \end{minted} - \caption{Example undefined byte} - \label{fig:undef} -\end{figure} - -\subsection{Computing data layout} - -Currently, the Rust compiler's data layouts for types are hidden from Miri, so it does its own data -layout computation which will not always match what the compiler does, since Miri doesn't take -target type alignments into account. In the future, the Rust compiler may be modified so that Miri -can use the exact same data layout. - -Miri's data layout calculation is a relatively simple transformation from Rust types to a structure -with constant size values for primitives and sets of fields with offsets for aggregate types. These -layouts are cached for performance. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\section{Deterministic execution} -\label{sec:deterministic} - -In order to be effective as a compile-time evaluator, Miri must have \emph{deterministic execution}, -as explained by Burtescu in the ``Rust Abstract Machine'' post. That is, given a function and -arguments to that function, Miri should always produce identical results. This is important for -coherence in the type checker when constant evaluations are involved in types, such as for sizes of -array types: - -\begin{minted}[autogobble,mathescape]{rust} - const fn get_size() -> usize { /* $\ldots$ */ } - let array: [i32; get_size()]; -\end{minted} - -Since Miri allows execution of unsafe code\footnote{In fact, the distinction between safe and unsafe -doesn't exist at the MIR level.}, it is specifically designed to remain safe while interpreting -potentially unsafe code. When Miri encounters an unrecoverable error, it reports it via the Rust -compiler's usual error reporting mechanism, pointing to the part of the original code where the -error occurred. Below is an example from Miri's -repository.\footnote{\href{https://github.com/solson/miri/blob/master/test/errors.rs}{miri/test/errors.rs}} - -\begin{minted}[autogobble]{rust} - let b = Box::new(42); - let p: *const i32 = &*b; - drop(b); - unsafe { *p } - // ~~ error: dangling pointer - // was dereferenced -\end{minted} -\label{dangling-pointer} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\section{Language support} - -In its current state, Miri supports a large proportion of the Rust language, detailed below. The -major exception is a lack of support for FFI\footnote{Foreign Function Interface, e.g.\ calling -functions defined in Assembly, C, or C++.}, which eliminates possibilities like reading and writing -files, user input, graphics, and more. However, for compile-time evaluation in Rust, this limitation -is desired. - -\subsection{Primitives} - -Miri supports booleans, integers of various sizes and signed-ness (i.e.\ \rust{i8}, \rust{i16}, -\rust{i32}, \rust{i64}, \rust{isize}, \rust{u8}, \rust{u16}, \rust{u32}, \rust{u64}, \rust{usize}), -and unary and binary operations over these types. The \rust{isize} and \rust{usize} types will be -sized according to the target machine's pointer size just like in compiled Rust. The \rust{char} and -float types (\rust{f32}, \rust{f64}) are not supported yet, but there are no known barriers to doing -so. - -When examining a boolean in an \rust{if} condition, Miri will report an error if its byte -representation is not precisely 0 or 1, since having any other value for a boolean is undefined -behaviour in Rust. The \rust{char} type will have similar restrictions once it is implemented. - -\subsection{Pointers} - -Both references and raw pointers are supported, with essentially no difference between them in Miri. -It is also possible to do pointer comparisons and math. However, a few operations are considered -errors and a few require special support. - -Firstly, pointers into the same allocations may be compared for ordering, but pointers into -different allocations are considered unordered and Miri will complain if you attempt this. The -reasoning is that different allocations may have different orderings in the global address space at -runtime, making this non-deterministic. However, pointers into different allocations \emph{may} be -compared for direct equality (they are always unequal). - -Secondly, pointers represented using relocations may be compared against pointers casted from -integers (e.g.\ \rust{0 as *const i32}) for things like null pointer checks. To handle these cases, -Miri has a concept of ``integer pointers'' which are always unequal to abstract pointers. Integer -pointers can be compared and operated upon freely. However, note that it is impossible to go from an -integer pointer to an abstract pointer backed by a relocation. It is not valid to dereference an -integer pointer. - -\subsubsection{Slice pointers} - -Rust supports pointers to ``dynamically-sized types'' such as \rust{[T]} and \rust{str} which -represent arrays of indeterminate size. Pointers to such types contain an address \emph{and} the -length of the referenced array. Miri supports these fully. - -\subsubsection{Trait objects} - -Rust also supports pointers to ``trait objects'' which represent some type that implements a trait, -with the specific type unknown at compile-time. These are implemented using virtual dispatch with a -vtable, similar to virtual methods in C++. Miri does not currently support these at all. - -\subsection{Aggregates} - -Aggregates include types declared with \rust{struct} or \rust{enum} as well as tuples, arrays, and -closures. Miri supports all common usage of all of these types. The main missing piece is to handle -\texttt{\#[repr(..)]} annotations which adjust the layout of a \rust{struct} or \rust{enum}. - -\subsection{Place projections} - -This category includes field accesses, dereferencing, accessing data in an \rust{enum} variant, and -indexing arrays. Miri supports all of these, including nested projections such as -\rust{*foo.bar[2]}. - -\subsection{Control flow} - -All of Rust's standard control flow features, including \rust{loop}, \rust{while}, \rust{for}, -\rust{if}, \rust{if let}, \rust{while let}, \rust{match}, \rust{break}, \rust{continue}, and -\rust{return} are supported. In fact, supporting these was quite easy since the Rust compiler -reduces them all down to a small set of control-flow graph primitives in MIR. - -\subsection{Function calls} - -As previously described, Miri supports arbitrary function calls without growing the native stack -(only its virtual call stack). It is somewhat limited by the fact that cross-crate\footnote{A crate -is a single Rust library (or executable).} calls only work for functions whose MIR is stored in -crate metadata. This is currently true for \rust{const}, generic, and inline functions. -A branch of the compiler could be made that stores MIR for all functions. This would be a non-issue -for a compile-time evaluator based on Miri, since it would only call \rust{const fn}s. - -\subsubsection{Method calls} - -Miri supports trait method calls, including invoking all the compiler-internal lookup needed to find -the correct implementation of the method. - -\subsubsection{Closures} - -Calls to closures are also supported with the exception of one edge case\footnote{Calling a closure -that takes a reference to its captures via a closure interface that passes the captures by value is -not yet supported.}. The value part of a closure that holds the captured variables is handled as an -aggregate and the function call part is mostly the same as a trait method call, but with the added -complication that closures use a separate calling convention within the compiler. - -\subsubsection{Function pointers} - -Function pointers are not currently supported by Miri, but there is a relatively simple way they -could be encoded using a relocation with a special reserved allocation identifier. The offset of the -relocation would determine which function it points to in a special array of functions in the -interpreter. - -\subsubsection{Intrinsics} - -To support unsafe code, and in particular to support Rust's standard library, it became clear that -Miri would have to support calls to compiler -intrinsics\footnote{\url{https://doc.rust-lang.org/stable/std/intrinsics/index.html}}. Intrinsics -are function calls which cause the Rust compiler to produce special-purpose code instead of a -regular function call. Miri simply recognizes intrinsic calls by their unique -ABI\footnote{Application Binary Interface, which defines calling conventions. Includes ``C'', -``Rust'', and ``rust-intrinsic''.} and name and runs special-purpose code to handle them. - -An example of an important intrinsic is \rust{size_of} which will cause Miri to write the size of -the type in question to the return value location. The Rust standard library uses intrinsics heavily -to implement various data structures, so this was a major step toward supporting them. Intrinsics -have been implemented on a case-by-case basis as tests which required them were written, and not all -intrinsics are supported yet. - -\subsubsection{Generic function calls} - -Miri needs special support for generic function calls since Rust is a \emph{monomorphizing} -compiler, meaning it generates a special version of each function for each distinct set of type -parameters it gets called with. Since functions in MIR are still polymorphic, Miri has to do the -same thing and substitute function type parameters into all types it encounters to get fully -concrete, monomorphized types. For example, in\ldots - -\begin{minted}[autogobble]{rust} - fn some(t: T) -> Option { Some(t) } -\end{minted} - -\ldots{}Miri needs to know the size of \rust{T} to copy the right amount of bytes from the argument -to the return value. If we call \rust{some(10i32)} Miri will execute \rust{some} knowing that -\rust{T = i32} and generate a representation for \rust{Option}. - -Miri currently does this monomorphization lazily on-demand unlike the Rust back-end which does it -all ahead of time. - -\subsection{Heap allocations} - -The next piece of the puzzle for supporting interesting programs (and the standard library) was heap -allocations. There are two main interfaces for heap allocation in Rust: the built-in \rust{Box} -rvalue in MIR and a set of C ABI foreign functions including \rust{__rust_allocate}, -\rust{__rust_reallocate}, and \rust{__rust_deallocate}. These correspond approximately to -\mintinline{c}{malloc}, \mintinline{c}{realloc}, and \mintinline{c}{free} in C. - -The \rust{Box} rvalue allocates enough space for a single value of a given type. This was easy to -support in Miri. It simply creates a new abstract allocation in the same manner as for -stack-allocated values, since there's no major difference between them in Miri. - -The allocator functions, which are used to implement things like Rust's standard \rust{Vec} type, -were a bit trickier. Rust declares them as \rust{extern "C" fn} so that different allocator -libraries can be linked in at the user's option. Since Miri doesn't actually support FFI and wants -full control of allocations for safety, it ``cheats'' and recognizes these allocator functions in -essentially the same way it recognizes compiler intrinsics. Then, a call to \rust{__rust_allocate} -simply creates another abstract allocation with the requested size and \rust{__rust_reallocate} -grows one. - -In the future, Miri should also track which allocations came from \rust{__rust_allocate} so it can -reject reallocate or deallocate calls on stack allocations. - -\subsection{Destructors} - -When a value which ``owns'' some resource (like a heap allocation or file handle) goes out of scope, -Rust inserts \emph{drop glue} that calls the user-defined destructor for the type if it has one, and -then drops all of the subfields. Destructors for types like \rust{Box} and \rust{Vec} -deallocate heap memory. - -Miri doesn't yet support calling user-defined destructors, but it has most of the machinery in place -to do so already. There \emph{is} support for dropping \rust{Box} types, including deallocating -their associated allocations. This is enough to properly execute the dangling pointer example in -\autoref{sec:deterministic}. - -\subsection{Constants} - -Only basic integer, boolean, string, and byte-string literals are currently supported. Evaluating -more complicated constant expressions in their current form would be a somewhat pointless exercise -for Miri. Instead, we should lower constant expressions to MIR so Miri can run them directly, which -is precisely what would need be done to use Miri as the compiler's constant evaluator. - -\subsection{Static variables} - -Miri doesn't currently support statics, but they would need support similar to constants. Also note -that while it would be invalid to write to static (i.e.\ global) variables in Miri executions, it -would probably be fine to allow reads. - -\subsection{Standard library} - -Throughout the implementation of the above features, I often followed this process: - -\begin{enumerate} - \item Try using a feature from the standard library. - \item See where Miri runs into stuff it can't handle. - \item Fix the problem. - \item Go to 1. -\end{enumerate} - -At present, Miri supports a number of major non-trivial features from the standard library along -with tons of minor features. Smart pointer types such as \rust{Box}, \rust{Rc}\footnote{Reference -counted shared pointer} and \rust{Arc}\footnote{Atomically reference-counted thread-safe shared -pointer} all seem to work. I've also tested using the shared smart pointer types with \rust{Cell} -and \rust{RefCell}\footnote{\href{https://doc.rust-lang.org/stable/std/cell/index.html}{Rust -documentation for cell types}} for internal mutability, and that works as well, although -\rust{RefCell} can't ever be borrowed twice until I implement destructor calls, since a destructor -is what releases the borrow. - -But the standard library collection I spent the most time on was \rust{Vec}, the standard -dynamically-growable array type, similar to C++'s \texttt{std::vector} or Java's -\texttt{java.util.ArrayList}. In Rust, \rust{Vec} is an extremely pervasive collection, so -supporting it is a big win for supporting a larger swath of Rust programs in Miri. - -See \autoref{fig:vec} for an example (working in Miri today) of initializing a \rust{Vec} with a -small amount of space on the heap and then pushing enough elements to force it to reallocate its -data array. This involves cross-crate generic function calls, unsafe code using raw pointers, heap -allocation, handling of uninitialized memory, compiler intrinsics, and more. - -\begin{figure}[t] - \begin{minted}[autogobble]{rust} - struct Vec { - data: *mut T, // 4 byte pointer - capacity: usize, // 4 byte integer - length: usize, // 4 byte integer - } - - let mut v: Vec = - Vec::with_capacity(2); - // v: 00 00 00 00 02 00 00 00 00 00 00 00 - // └─(data)──┘ - // data: __ __ - - v.push(1); - // v: 00 00 00 00 02 00 00 00 01 00 00 00 - // └─(data)──┘ - // data: 01 __ - - v.push(2); - // v: 00 00 00 00 02 00 00 00 02 00 00 00 - // └─(data)──┘ - // data: 01 02 - - v.push(3); - // v: 00 00 00 00 04 00 00 00 03 00 00 00 - // └─(data)──┘ - // data: 01 02 03 __ - \end{minted} - \caption{\rust{Vec} example on 32-bit little-endian} - \label{fig:vec} -\end{figure} - -Miri supports unsafe operations on \rust{Vec} like \rust{v.set_len(10)} or -\rust{v.get_unchecked(2)}, provided that such calls do no invoke undefined behaviour. If a call -\emph{does} invoke undefined behaviour, Miri will abort with an appropriate error message (see -\autoref{fig:vec-error}). - -\begin{figure}[t] - \begin{minted}[autogobble]{rust} - fn out_of_bounds() -> u8 { - let v = vec![1, 2]; - let p = unsafe { v.get_unchecked(5) }; - *p + 10 - // ~~ error: pointer offset outside - // bounds of allocation - } - - fn undefined_bytes() -> u8 { - let v = Vec::::with_capacity(10); - let p = unsafe { v.get_unchecked(5) }; - *p + 10 - // ~~~~~~~ error: attempted to read - // undefined bytes - } - \end{minted} - \caption{\rust{Vec} examples with undefined behaviour} - \label{fig:vec-error} -\end{figure} - -\newpage - -Here is one final code sample Miri can execute that demonstrates many features at once, including -vectors, heap allocation, iterators, closures, raw pointers, and math: - -\begin{minted}[autogobble]{rust} - let x: u8 = vec![1, 2, 3, 4] - .into_iter() - .map(|x| x * x) - .fold(0, |x, y| x + y); - // x: 1e (that is, the hex value - // 0x1e = 30 = 1 + 4 + 9 + 16) -\end{minted} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\section{Future directions} - -\subsection{Finishing the implementation} - -There are a number of pressing items on my to-do list for Miri, including: - -\begin{itemize} - \item A much more comprehensive and automated test suite. - \item User-defined destructor calls. - \item Non-trivial casts between primitive types like integers and pointers. - \item Handling statics and global memory. - \item Reporting errors for all undefined behaviour.\footnote{\href{https://doc.rust-lang.org/reference.html\#behavior-considered-undefined}{The Rust reference on what is considered undefined behaviour}} - \item Function pointers. - \item Accounting for target machine primitive type alignment and endianness. - \item Optimizations (undefined byte masks, tail-calls). - \item Benchmarking Miri vs. unoptimized Rust. - \item Various \texttt{TODO}s and \texttt{FIXME}s left in the code. - \item Integrating into the compiler proper. -\end{itemize} - -\subsection{Future projects} - -Other possible Miri-related projects include: - -\begin{itemize} - \item A read-eval-print-loop (REPL) for Rust, which may be easier to implement on top of Miri than - the usual LLVM back-end. - \item A graphical or text-mode debugger that steps through MIR execution one statement at a time, - for figuring out why some compile-time execution is raising an error or simply learning how Rust - works at a low level. - \item A less restricted version of Miri that is able to run foreign functions from C/C++ and - generally has full access to the operating system. Such an interpreter could be used to more - quickly prototype changes to the Rust language that would otherwise require changes to the LLVM - back-end. - \item Unit-testing the compiler by comparing the results of Miri's execution against the results - of LLVM-compiled machine code's execution. This would help to guarantee that compile-time - execution works the same as runtime execution. - \item Some kind of Miri-based symbolic evaluator that examines multiple possible code paths at - once to determine if undefined behaviour could be observed on any of them. -\end{itemize} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\section{Final thoughts} - -Writing an interpreter which models values of varying sizes, stack and heap allocation, unsafe -memory operations, and more requires some unconventional techniques compared to conventional -interpreters targeting dynamically-typed languages. However, aside from the somewhat complicated -abstract memory model, making Miri work was primarily a software engineering problem, and not a -particularly tricky one. This is a testament to MIR's suitability as an intermediate representation -for Rust---removing enough unnecessary abstraction to keep it simple. For example, Miri doesn't even -need to know that there are different kinds of loops, or how to match patterns in a \rust{match} -expression. - -Another advantage to targeting MIR is that any new features at the syntax-level or type-level -generally require little to no change in Miri. For example, when the new ``question mark'' syntax -for error handling\footnote{ - \href{https://github.com/rust-lang/rfcs/blob/master/text/0243-trait-based-exception-handling.md} - {Question mark syntax RFC}} -was added to rustc, Miri required no change to support it. -When specialization\footnote{ - \href{https://github.com/rust-lang/rfcs/blob/master/text/1210-impl-specialization.md} - {Specialization RFC}} -was added, Miri supported it with just minor changes to trait method lookup. - -Of course, Miri also has limitations. The inability to execute FFI and inline assembly reduces the -amount of Rust programs Miri could ever execute. The good news is that in the constant evaluator, -FFI can be stubbed out in cases where it makes sense, like I did with \rust{__rust_allocate}. For a -version of Miri not intended for constant evaluation, it may be possible to use libffi to call C -functions from the interpreter. - -In conclusion, Miri is a surprisingly effective project, and a lot of fun to implement. Due to MIR's -tendency to collapse multiple source-level features into one, I often ended up supporting features I -hadn't explicitly intended to. I am excited to work with the compiler team going forward to try to -make Miri useful for constant evaluation in Rust. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -\section{Thanks} - -A big thanks goes to Eduard Burtescu for writing the abstract machine specification and answering my -incessant questions on IRC, to Niko Matsakis for coming up with the idea for Miri and supporting my -desire to work with the Rust compiler, and to my research supervisor Christopher Dutchyn. Thanks -also to everyone else on the compiler team and on Mozilla IRC who helped me figure stuff out. -Finally, thanks to Daniel Keep and everyone else who helped fix my numerous writing mistakes. - -\end{document}