Demonstration venue · read-only. Every page can be browsed; the buttons that would change it are switched off. Create an account to run TaxoReview on your own data.

Norman Ramsey

dblp:r/NormanRamsey · DBLP profile ↗
← Back
35ranked-venue papers
22as first author
1since 2021 · last 2022
0000-0002-5435-1135ORCID · verified

Domains — the database's venue-derived domains; a paper can count in several

Software engineering, systems software and programming languages · 32 · 20 first-author · 1 since 2021Theory of computation · 2Applied, interdisciplinary, general and emerging computing · 2 · 1 first-authorSystems, architecture and hardware · 1 · 1 first-author

Expertise — from the expertise taxonomy: the topics of the expert's papers under the CCF categories. A weight counts papers with recency: 1 for a paper about the topic, 0.3 when the topic is its context, halved every five years.

Software engineering, system software, and programming languages
13 papers
Compilers and program optimization · 58% Programming languages and type systems · 36% Runtime systems and virtual machines · 2%
Artificial intelligence
2 papers
Probabilistic and Bayesian machine learning · 100%
Computer architecture, parallel and distributed computing, and storage systems
2 papers
Distributed systems · 53% Storage systems · 26% Processor architecture and microarchitecture · 21%

Topics — the 30 heaviest of 34, each with the papers that count most for it

TopicWeightPapersLastEvidence papers
Machine learning › Probabilistic and Bayesian machine learning › statistical inference
bayesian inference
0.312017
Exact Bayesian inference by symbolic disintegration · POPL 2017
Machine learning › Probabilistic and Bayesian machine learning › statistical inference › bayesian inference › posterior inference
exact bayesian inference
0.312017
Exact Bayesian inference by symbolic disintegration · POPL 2017
Programming languages and type systems › probabilistic programming
probabilistic program semantics
0.312017
Exact Bayesian inference by symbolic disintegration · POPL 2017
Compilers and program optimization › compiler construction
retargetable compilation
0.332011
Resourceable, retargetable, modular instruction selection using a machine-independent, type-based tiling of low-level intermediate code · POPL 2011
Automatically generating instruction selectors using declarative machine descriptions · POPL 2010
Specifying Representations of Machine Instructions · ACM Trans. Program. Lang. Syst. 1997
Compilers and program optimization › code generation
instruction selection
0.222011
Resourceable, retargetable, modular instruction selection using a machine-independent, type-based tiling of low-level intermediate code · POPL 2011
Automatically generating instruction selectors using declarative machine descriptions · POPL 2010
Compilers and program optimization
code generation
0.122011
Resourceable, retargetable, modular instruction selection using a machine-independent, type-based tiling of low-level intermediate code · POPL 2011
Relocating Machine Instructions by Currying · PLDI 1996
Programming languages and type systems
type systems
0.112011
Resourceable, retargetable, modular instruction selection using a machine-independent, type-based tiling of low-level intermediate code · POPL 2011
Programming languages and type systems
language semantics
0.122002
Stochastic lambda calculus and monads of probability distributions · POPL 2002
A single intermediate language that supports multiple implementations of exceptions · PLDI 2000
Compilers and program optimization › compiler back end
calling conventions
0.112006
Staged allocation: a compositional technique for specifying and implementing procedure calling conventions · POPL 2006
Compilers and program optimization
compiler construction
0.112006
Staged allocation: a compositional technique for specifying and implementing procedure calling conventions · POPL 2006
Programming languages and type systems › program specification
specification composition
0.112006
Staged allocation: a compositional technique for specifying and implementing procedure calling conventions · POPL 2006
Compilers and program optimization › register allocation
graph coloring register allocation
0.012004
A generalized algorithm for graph-coloring register allocation · PLDI 2004
Compilers and program optimization
register allocation
0.012004
A generalized algorithm for graph-coloring register allocation · PLDI 2004
Runtime systems and virtual machines
binary translation
0.012003
A transformational approach to binary translation of delayed branches · ACM Trans. Program. Lang. Syst. 2003
Compilers and program optimization
program transformation
0.012003
A transformational approach to binary translation of delayed branches · ACM Trans. Program. Lang. Syst. 2003
Compilers and program optimization
instruction encoding and decoding
0.021997
Specifying Representations of Machine Instructions · ACM Trans. Program. Lang. Syst. 1997
Automatic Checking of Instruction Specifications · ICSE 1997
Programming languages and type systems › computational effects
monads
0.012002
Stochastic lambda calculus and monads of probability distributions · POPL 2002
Programming languages and type systems › probabilistic programming
stochastic lambda calculus
0.012002
Stochastic lambda calculus and monads of probability distributions · POPL 2002
Compilers and program optimization
compiler back end
0.012010
Automatically generating instruction selectors using declarative machine descriptions · POPL 2010
Distributed systems › distributed coordination
conflict resolution
0.012001
An algebraic approach to file synchronization · ESEC / SIGSOFT FSE 2001
Storage systems › file systems
file synchronization
0.012001
An algebraic approach to file synchronization · ESEC / SIGSOFT FSE 2001
Distributed systems › replication
replica consistency
0.012001
An algebraic approach to file synchronization · ESEC / SIGSOFT FSE 2001
Compilers and program optimization
intermediate representation
0.012000
A single intermediate language that supports multiple implementations of exceptions · PLDI 2000
Program analysis › binary analysis
machine code analysis
0.011997
Specifying Representations of Machine Instructions · ACM Trans. Program. Lang. Syst. 1997
Program verification
specification verification
0.011997
Automatic Checking of Instruction Specifications · ICSE 1997
Processor architecture and microarchitecture › pipelining
delayed branch
0.012003
A transformational approach to binary translation of delayed branches · ACM Trans. Program. Lang. Syst. 2003
Processor architecture and microarchitecture
instruction set architecture
0.012003
A transformational approach to binary translation of delayed branches · ACM Trans. Program. Lang. Syst. 2003
Concurrent programming
concurrency bugs
0.011994
Correctness of Trap-Based Breakpoint Implementations · POPL 1994
Concurrent programming
multithreaded debugging
0.011994
Correctness of Trap-Based Breakpoint Implementations · POPL 1994
Debugging and program repair › debugging tools
debugger implementation
0.011992
A Retargetable Debugger · PLDI 1992

Methods — techniques the papers use, named apart from their topics

symbolic computation · 0.6disintegration · 0.6machine-independent tiling · 0.1automatic generation from declarative semantics · 0.1declarative machine descriptions · 0.1transformational approach · 0.1measure terms · 0.1test suite generation · 0.1formal semantics · 0.1graph coloring · 0.0monadic semantics · 0.0formal specification · 0.0algebra · 0.0
YearPublicationVenuePosition
2022 Beyond Relooper: recursive translation of unstructured control flow to structured control flow (functional pearl)
abstract
In many compilers, control flow is represented using an arbitrary directed graph. But in some interesting target languages, including JavaScript and WebAssembly, intraprocedural control flow can be expressed only in structured ways, using loops, conditionals, and multilevel breaks or exits. As was shown by Peterson, Kasami, and Tokura in 1973, such structured control flow can be obtained by translating arbitrary control flow. The translation uses two standard analyses, but as published, it takes three passes—which may explain why it was overlooked by Emscripten, a popular compiler from C to JavaScript. By tweaking the analyses and by applying fundamental ideas from functional programming (recursive functions and immutable abstract-syntax trees), the translation, along with a couple of code improvements, can be implemented in a single pass. This new implementation is slated to be added to the Glasgow Haskell Compiler. Its single-pass translation, its immutable representation, and its use of dominator trees make it much easier to reason about than the original translation.
Norman Ramsey
Proc. ACM Program. Lang.1
2017 Exact Bayesian inference by symbolic disintegration
abstract
Bayesian inference, of posterior knowledge from prior knowledge and observed evidence, is typically defined by Bayes's rule, which says the posterior multiplied by the probability of an observation equals a joint probability. But the observation of a continuous quantity usually has probability zero, in which case Bayes's rule says only that the unknown times zero is zero. To infer a posterior distribution from a zero-probability observation, the statistical notion of disintegration tells us to specify the observation as an expression rather than a predicate, but does not tell us how to compute the posterior. We present the first method of computing a disintegration from a probabilistic program and an expression of a quantity to be observed, even when the observation has probability zero. Because the method produces an exact posterior term and preserves a semantics in which monadic terms denote measures, it composes with other inference methods in a modular way-without sacrificing accuracy or performance.
Chung-chieh Shan, Norman Ramsey
POPL2
2015 MRFy: Remote Homology Detection for Beta-Structural Proteins Using Markov Random Fields and Stochastic Search
abstract
We introduce MRFy, a tool for protein remote homology detection that captures beta-strand dependencies in the Markov random field. Over a set of 11 SCOP beta-structural superfamilies, MRFy shows a 14 percent improvement in mean Area Under the Curve for the motif recognition problem as compared to HMMER, 25 percent improvement as compared to RAPTOR, 14 percent improvement as compared to HHPred, and a 18 percent improvement as compared to CNFPred and RaptorX. MRFy was implemented in the Haskell functional programming language, and parallelizes well on multi-core systems. MRFy is available, as source code as well as an executable, from http://mrfy.cs.tufts.edu/.
Noah M. Daniels, Andrew Gallant, Norman Ramsey, Lenore Cowen
IEEE ACM Trans. Comput. Biol. Bioinform.3
2014 On teaching *how to design programs*: observations from a newcomer
abstract
This paper presents a personal, qualitative case study of a first course using How to Design Programs and its functional teaching languages. The paper reconceptualizes the book's six-step design process as an eight-step design process ending in a new "review and refactor" step. It recommends specific approaches to students' difficulties with function descriptions, function templates, data examples, and other parts of the design process. It connects the process to interactive "world programs." It recounts significant, informative missteps in course design and delivery. Finally, it identifies some unsolved teaching problems and some potential solutions.
Norman Ramsey
ICFP1
2013 Engineering definitional interpreters
abstract
A definitional interpreter should be clear and easy to write, but it may run 4--10 times slower than a well-crafted bytecode interpreter. In a case study focused on implementation choices, we explore ways of making definitional interpreters faster without expending much programming effort. We implement, in OCaml, interpreters based on three semantics for a simple subset of Lua. We compile the OCaml to x86 native code, and we systematically investigate hundreds of combinations of algorithms and data structures. In this experimental context, our fastest interpreters are based on natural semantics; good algorithms and data structures make them 2--3 times faster than naïve interpreters. Our best interpreter, created using only modest effort, runs only 1.5 times slower than a mature bytecode interpreter implemented in C.
Jan Midtgaard, Norman Ramsey, Bradford Larsen
PPDP2
2012 Experience report: Haskell in computational biology
abstract
Haskell gives computational biologists the flexibility and rapid prototyping of a scripting language, plus the performance of native code. In our experience, higher-order functions, lazy evaluation, and monads really worked, but profiling and debugging presented obstacles. Also, Haskell libraries vary greatly: memoization combinators and parallel-evaluation strategies helped us a lot, but other, nameless libraries mostly got in our way. Despite the obstacles and the uncertain quality of some libraries, Haskell's ecosystem made it easy for us to develop new algorithms in computational biology.
Noah M. Daniels, Andrew Gallant, Norman Ramsey
ICFP3
2011 Resourceable, retargetable, modular instruction selection using a machine-independent, type-based tiling of low-level intermediate code
abstract
We present a novel variation on the standard technique of selecting instructions by tiling an intermediate-code tree. Typical compilers use a different set of tiles for every target machine. By analyzing a formal model of machine-level computation, we have developed a single set of tiles that is machine-independent while retaining the expressive power of machine code. Using this tileset, we reduce the number of tilers required from one per machine to one per architectural family (e.g., register architecture or stack architecture). Because the tiler is the part of the instruction selector that is most difficult to reason about, our technique makes it possible to retarget an instruction selector with significantly less effort than standard techniques. Retargeting effort is further reduced by applying an earlier result which generates the machine-dependent implementation of our tileset automatically from a declarative description of instructions' semantics. Our design has the additional benefit of enabling modular reasoning about three aspects of code generation that are not typically separated: the semantics of the compiler's intermediate representation, the semantics of the target instruction set, and the techniques needed to generate good target code.
Norman Ramsey, João Dias 0005
POPL1
2011 Embedding an interpreted language using higher-order functions and types
abstract
Abstract Using an embedded, interpreted language to control a complicated application can have significant software-engineering benefits. But existing interpreters are designed for embedding into C code. To embed an interpreter into a different language requires an API suited to that language. This paper presents Lua-ML, a new API that is suited to languages that provide higher-order functions and types. The API exploits higher-order functions and types to reduce the amount of glue code needed to use an embedded interpreter. Where embedding in C requires a special-purpose “glue function” for every function to be embedded, embedding in Lua-ML requires only a description of each function's type. Lua-ML also makes it easy to define a Lua function whose behavior depends on the number and types of its arguments.
Norman Ramsey
J. Funct. Program.1
2010 Hoopl: a modular, reusable library for dataflow analysis and transformation
abstract
Dataflow analysis and transformation of control-flow graphs is pervasive in optimizing compilers, but it is typically entangled with the details of a particular compiler. We describe Hoopl, a reusable library that makes it unusually easy to define new analyses and transformations for any compiler written in Haskell. Hoopl's interface is modular and polymorphic, and it offers unusually strong static guarantees. The implementation encapsulates state-of-the-art algorithms (interleaved analysis and rewriting, dynamic error isolation), and it cleanly separates their tricky elements so that they can be understood independently.
Norman Ramsey, João Dias 0005, Simon L. Peyton Jones
Haskell1
2010 Automatically generating instruction selectors using declarative machine descriptions
abstract
Despite years of work on retargetable compilers, creating a good, reliable back end for an optimizing compiler still entails a lot of hard work. Moreover, a critical component of the back end---the instruction selector---must be written by a person who is expert in both the compiler's intermediate code and the target machine's instruction set. By generating the instruction selector from declarative machine descriptions we have (a) made it unnecessary for one person to be both a compiler expert and a machine expert, and (b) made creating an optimizing back end easier than ever before.
João Dias 0005, Norman Ramsey
POPL2
2006 Converting Intermediate Code to Assembly Code Using Declarative Machine Descriptions
João Dias 0005, Norman Ramsey
CC2
2006 Staged allocation: a compositional technique for specifying and implementing procedure calling conventions
abstract
We present staged allocation, a technique for specifying calling conventions by composing tiny allocators called stages. A specification written using staged allocation has a precise, formal semantics, and it can be executed directly inside a compiler. Specifications of nine standard C~calling conventions range in size from 15 to 30 lines each. An implementation of staged allocation takes about 250 lines of ML or 650~lines of C++. Each specification can be used not only to help a compiler implement the calling convention but also to generate a test suite.
Reuben Olinsky, Christian Lindig, Norman Ramsey
POPL3
2005 Source-Level Debugging for Multiple Languages with Modest Programming Effort
Sukyoung Ryu, Norman Ramsey
CC2
2005 An expressive language of signatures
abstract
Current languages allow a programmer to describe an interface only by enumerating its parts, possibly including other interfaces wholesale. Such languages cannot express relationships between interfaces, yet when independently developed software components are combined into a larger system, significant relationships arise.To address this shortcoming, we define, as a conservative extension of ML, a language for manipulating interfaces. Our language includes operations for adding, renaming, and removing components; for changing the type associated with a value; for making manifest types abstract and vice versa; and for combining interfaces. These operations can express useful relationships among interfaces. We have defined a formal semantics in which an interface denotes a group of four sets; we show how these sets determine a subtyping relation, and we sketch the elaboration of an interface into its denotation.
Norman Ramsey, Kathleen Fisher, Paul Govereau
ICFP1
2005 Building the World from First Principles: Declarative Machine Descriptions and Compiler Construction
Norman Ramsey
PADL1
2004 Declarative Composition of Stack Frames
Christian Lindig, Norman Ramsey
CC2
2004 Widening Integer Arithmetic
Kevin Redwine, Norman Ramsey
CC2
2004 The C - compiler infrastructure
abstract
No abstract available.
Norman Ramsey, Simon L. Peyton Jones
ICFP1
2004 A generalized algorithm for graph-coloring register allocation
abstract
Graph-coloring register allocation is an elegant and extremely popular optimization for modern machines. But as currently formulated, it does not handle two characteristics commonly found in commercial architectures. First, a single register name may appear in multiple register classes, where a class is a set of register names that are interchangeable in a particular role. Second, multiple register names may be aliases for a single hardware register. We present a generalization of graph-coloring register allocation that handles these problematic characteristics while preserving the elegance and practicality of traditional graph coloring. Our generalization adapts easily to a new target machine, requiring only the sets of names in the register classes and a map of the register aliases. It also drops easily into a well-known graph-coloring allocator, is efficient at compile time, and produces high-quality code. Categories and subject descriptors D.3.4 [Programming Languages]: Processors—code generation, compilers, optimization, retargetable compilers; G.2.2 [Discrete
Michael D. Smith 0001, Norman Ramsey, Glenn H. Holloway
PLDI2
2003 Pragmatic aspects of reusable program generators
abstract
When writing a program generator requires considerable intellectual effort, it is valuable to amortize that effort by using the generator to build more than one application. When a program generator serves multiple clients, however, the implementor must address pragmatic questions that implementors of single-use program generators can ignore. In how many languages should generated code be written? How should code be packaged? What should the interfaces to the client code look like? How should a user control variations? This paper elaborates on these questions by means of case studies of the New Jersey Machine-Code Toolkit, the $\lambda$ -RTL Translator, and the ASDL program generator. It is hoped that the paper will stimulate the development of better techniques. Most urgently needed are a standard way to support multiple target languages and a simple, clear way to control interfaces to generated code.
Norman Ramsey
J. Funct. Program.1
2003 A transformational approach to binary translation of delayed branches
abstract
A binary translator examines binary code for a source machine and generates code for a target machine. Understanding what to do with delayed branches in binary code can involve tricky case analyses, for example, if there is a branch instruction in a delay slot. This article presents a disciplined method for deriving such case analyses. The method identifies problematic cases, shows the translations for the nonproblematic cases, and gives confidence that all cases are considered. The method supports such common architectures as SPARC, MIPS, and PA-RISC, and it should apply to any tool that analyzes machine instructions. We begin by writing a very simple interpreter for the source machine's code. We then transform the interpreter into an interpreter for a target machine without delayed branches. To maintain the semantics of the program being interpreted, we simultaneously transform the sequence of source-machine instructions into a sequence of target-machine instructions. The transformation of the instructions becomes our algorithm for binary translation.
Norman Ramsey, Cristina Cifuentes
ACM Trans. Program. Lang. Syst.1
2002 Stochastic lambda calculus and monads of probability distributions
abstract
Probability distributions are useful for expressing the meanings of probabilistic languages, which support formal modeling of and reasoning about uncertainty. Probability distributions form a monad, and the monadic definition leads to a simple, natural semantics for a stochastic lambda calculus, as well as simple, clean implementations of common queries. But the monadic implementation of the expectation query can be much less efficient than current best practices in probabilistic modeling. We therefore present a language of measure terms, which can not only denote discrete probability distributions but can also support the best known modeling techniques. We give a translation of stochastic lambda calculus into measure terms. Whether one translates into the probability monad or into measure terms, the results of the translations denote the same probability distribution.
Norman Ramsey, Avi Pfeffer
POPL1
2001 An algebraic approach to file synchronization
abstract
A file synchronizer restores consistency after multiple replicas of a filesystem have been changed independently. We present an algebra for reasoning about operations on filesystems and show that it is sound and complete with respect to a simple model. The algebra enables us to specify a file-synchronization algorithm that can be combined with several different conflict-resolution policies. By contrast, previous work builds the conflict-resolution policy into the specification, or worse, does not specify the synchronizer's behavior precisely. We classify synchronizers by asking whether conflicts can be resolved at a single disconnected replica and whether all replicas are identical after synchronization. We also discuss timestamps and argue that there is no good way to propagate timestamps when there is severe clock skew between replicas.
Norman Ramsey, Elöd Csirmaz
ESEC / SIGSOFT FSE1
2000 A single intermediate language that supports multiple implementations of exceptions
abstract
We present mechanisms that enable our compiler-target language, C--, to express four of the best known techniques for implementing exceptions, all within a single, uniform framework. We define the mechanisms precisely, using a formal operational semantics. We also show that exceptions need not require special treatment in the optimizer; by introducing extra dataflow edges, we make standard optimization techniques work even on programs that use exceptions. Our approach clarifies the design space of exception-handling techniques, and it allows a single optimizer to handle a variety of implementation techniques. Our ultimate goal is to allow a source-language compiler the freedom to choose its exception-handling policy, while encapsulating the architecture-dependent mechanisms and their optimization in an implementation of C--that can be used by compilers for many source languages.
Norman Ramsey, Simon L. Peyton Jones
PLDI1
1999 C--: A Portable Assembly Language that Supports Garbage Collection
Simon L. Peyton Jones, Norman Ramsey, Fermin Reig
PPDP2
1999 Eliminating Spurious Error Messages Using Exceptions, Polymorphism, and Higher-Order Functions
abstract
Many language processors make assumptions after detecting an error. If the assumptions are invalid, a compiler may issue a cascade of error messages in which only the first represents a true error in the input; later messages are side effects of the original error. Eliminating such spurious error messages requires keeping track of values within the compiler that are not available because of a previously detected error. Examples include symbol-table entries, types and intermediate code. This paper presents a discipline for tracking unavailable values and avoiding cascading error messages. The discipline extends the error monad of Spivey [1] and Wadler [2]. The extension is expressed formally as a type constructor and combinators written in Standard ML. The type constructor distinguishes intermediate results that are unavailable because of a previously detected error. The combinators transform ordinary functions, which assume all intermediate results are available, into functions that silently propagate the unavailability of intermediate results. In an ML implementation, the ML type rules enforce the discipline; if the compiler writer does not account for a potentially unavailable value, the source code of the compiler does not type-check. The cost of the discipline is negligible. In an experimental compiler, the discipline adds at most 5–10% to the total compile time, and about 1% in the common case in which no errors are detected.
Norman Ramsey
Comput. J.1
1998 Unparsing Expressions with Prefix and Postfix Operators
abstract
Unparsing is the problem of transforming an internal representation of a program into an external, concrete syntax. In conjunction with prettyprinting, it is useful for generating readable programs from internal representations. If the target language uses prefix and postfix operators, the problem is nontrivial. This paper shows how to unparse expressions using a simple, bottom-up tree walk, which keeps track of the least tightly binding operator not enclosed by parentheses. During the tree walk, this operator is compared with the operator of the parent expression, and parentheses are inserted based on the precedence, associativity, and fixity (infix, prefix, or postfix) of the two operators. The paper is a literate program. It includes code for the unparser and for its inverse parser, both of which can handle operators of dynamically chosen precedence and associativity. Supporting such operators is useful for languages like ML, in which programmers may assign precedence and associativity to their own functions. © 1998 John Wiley & Sons, Ltd.
Norman Ramsey
Softw. Pract. Exp.1
1997 Automatic Checking of Instruction Specifications
abstract
Retargeting applications that process machine code is a tedious and error-prone task.We help automate retargeting by describing instruction sets in a high-level specification language and by generating automatically the code for encoding and decoding instructions.Moreover, we provide automated assistance for checking machine descriptions.We check a specification for consistency both internally and externally.Internal checking forbids impossible instruction specifications, e.g., those that specify two values for a single bit.Internal checking warns about implausible specifications, e.g., those that don't specify values for all bits.Internal checks catch many mistakes, but they cannot guarantee that a specification accurately describes a target machine.Externally, we check a specification for consistency with an independent assembler.This technique increases a user's confidence in a specification's correctness and permits debugging in isolation of the target application.External validation is effective: it identified errors in specifications of the Intel Pentium, the MIPS, and the SPARC, after code generated from the latter two had been used in applications for over a year.
Mary F. Fernández, Norman Ramsey
ICSE2
1997 Specifying Representations of Machine Instructions
abstract
We present SLED, a specification language for Encoding and Decoding, which describes, abstract, binary, and assembly-language representations of machine instructions. Guided by a SLED specification, the New Jersey Machine-Code Toolkit generates bit-manipulating code for use in applications that process machine code. Programmers can write such applications at an assembly language level of abstraction, and the toolkit enables the applications to recognize and emit the binary representations used by the hardware. SLED is suitable for describing both CISC and RISC machines; we have specified representations of MIPS R3000, SPARC, Alpha, and Intel Pentium instructions, and toolkit users have written specifications for the Power PC and Motorola 68000. The article includes representative excerpts from our SPARC and Pentium specifications. SLED uses four elements; fields and tokens describe parts of instructions; patterns describe binary representations of instructions or group of instructions; and constructors map between the abstract and binary levels. By combining the elements in different ways, SLED supports machine-independent implementations of machine-level concepts like conditional assembly, span-dependent instructions, relocatable addresses, object code, sections, and relocation. SLED specifications can be checked automatically for consistency with existing assemblers. The implementation of the toolkit is largely determined by our representations of patterns and constructors. We use a normal form that facilitates construction of encoders and decoders. The article describes the normal form and its use. The toolkit has been used to help build several applications. We have built a retargetable debugger and a retargetable, optimizing linker. Colleagues have built a dynamic code generator, a decompiler, and an execution-time analyzer. The toolkit generates efficient code; for example, the linker emits binary up to 15% faster than it emits assembly language, making it 1.7-2 times faster to produce an a.out directly than by using the assembler.
Norman Ramsey, Mary F. Fernández
ACM Trans. Program. Lang. Syst.1
1996 Relocating Machine Instructions by Currying
abstract
Relocation adjusts machine instructions to account for changes in the locations of the instructions themselves or of external symbols to which they refer. Standard linkers implement a finite set of relocation transformations, suitable for a single architecture. These transformations are enumerated, named, and engraved in a machine-dependent object-file format, and linkers must recognize them by name. These names and their associated transformations are an unnecessary source of machine-dependence. The New Jersey Machine-Code Toolkit is an application generator. It helps programmers create applications that manipulate machine code, including linkers. Guided by a short instruction-set specification, the toolkit generates the bit-manipulating code. Instructions are described by constructors, which denote functions mapping lists of operands to instructions' binary representations. Any operand can be designated as "relocatable," meaning that the operand's value need not be known at the time ...
Norman Ramsey
PLDI1
1996 A Simple Solver for Linear Equations Containing Nonlinear Operators
abstract
This paper presents a simple equation solver. The solver finds solutions for sets of linear equations extended with several nonlinear operators, including integer division and modulus, sign extension, and bit slicing. The solver uses a new technique called {\em balancing}, which can eliminate some nonlinear operators from a set of equations before applying Gaussian elimination. The solver's principal advantages are its simplicity and its ability to handle some nonlinear operators, including nonlinear functions of more than one variable. The solver is part of an application generator that provides encoding and decoding of machine instructions based on equational specifications. The solver is presented not as pseudo code but as a literate program, which guarantees that the code shown in the paper is the same code that is actually used. Using real code exposes more detail than using pseudocode, but literate-programming techniques help manage the detail. The detail should benefit readers who want to implement their own solvers based on the techniques presented here.
Norman Ramsey
Softw. Pract. Exp.1
1995 The New Jersey Machine-Code Toolkit
Norman Ramsey, Mary F. Fernández
USENIX1
1994 Correctness of Trap-Based Breakpoint Implementations
abstract
It is common for debuggers to implement breakpoints by a combination of planting traps and single stepping. When the target program contains multiple threads of execution, a debugger that is not carefully implemented may miss breakpoints. This paper gives a formal model of a breakpoint in a two-threaded program. The model describes correct and incorrect breakpoint implementations. Automatic search of the model's state space shows that the correct implementation does miss a breakpoint. The results apply even to debuggers like dbx and gdb, which are apparently for single-threaded programs; when the user evaluates an expression containing function calls, the debugger executes the call in the target address space, in effect creating a new thread.
Norman Ramsey
POPL1
1992 A Retargetable Debugger
abstract
We are developing techniques for building retargetable debuggers. Our prototype, 1db, debugs C programs compiled for the MIPS R3000, Motorola 68020, SPARC, and VAX architectures. It can use a network to connect to faulty processes and can do cross-architecture debugging. 1db's total code size is about 16,000 lines, but it needs only 250–550 lines of machine-dependent code for each target.
Norman Ramsey, David R. Hanson
PLDI1
1991 Literate Programming on a Team Project
abstract
Abstract We used literate programming on a team project to write a 33,000 line program for the Synthesizer Generator. The program, Penelope, was written using WEB, a tool designed for writing literate programs. Unlike other WEB programs, many of which have been written by WEB's developer or by individuals, Penelope was not intended to be published. We used WEB in the hope that both our team and its final product would benefit from the advantages often attributed to literate programming. The WEB source served as good internal documentation throughout development and maintenance, and it continues to document Penelope's design and implementation. Our experience also uncovered a number of problems with WEB.
Norman Ramsey, Carla Marceau
Softw. Pract. Exp.1