What is a Compiler? Compiler Construction SMD163. Why Translation is Needed: Know your Target: Lecture 8: Introduction to code generation

Similar documents
Compiler Construction D7011E

Process Layout and Function Calls

x86 assembly CS449 Fall 2017

administrivia today start assembly probably won t finish all these slides Assignment 4 due tomorrow any questions?

W4118: PC Hardware and x86. Junfeng Yang

Question 4.2 2: (Solution, p 5) Suppose that the HYMN CPU begins with the following in memory. addr data (translation) LOAD 11110

Function Calls COS 217. Reading: Chapter 4 of Programming From the Ground Up (available online from the course Web site)

CS 33: Week 3 Discussion. x86 Assembly (v1.0) Section 1G

Assembly level Programming. 198:211 Computer Architecture. (recall) Von Neumann Architecture. Simplified hardware view. Lecture 10 Fall 2012

Credits and Disclaimers

CS 31: Intro to Systems ISAs and Assembly. Kevin Webb Swarthmore College February 9, 2016

CS 31: Intro to Systems ISAs and Assembly. Kevin Webb Swarthmore College September 25, 2018

Second Part of the Course

Y86 Processor State. Instruction Example. Encoding Registers. Lecture 7A. Computer Architecture I Instruction Set Architecture Assembly Language View

CS 31: Intro to Systems ISAs and Assembly. Martin Gagné Swarthmore College February 7, 2017

CS241 Computer Organization Spring 2015 IA

x86 architecture et similia

Assembly Language: Function Calls

Assembly Programmer s View Lecture 4A Machine-Level Programming I: Introduction

Assembly Language: Function Calls" Goals of this Lecture"

CS412/CS413. Introduction to Compilers Tim Teitelbaum. Lecture 21: Generating Pentium Code 10 March 08

x86 assembly CS449 Spring 2016

Credits and Disclaimers

Instruction Set Architecture

Instruction Set Architecture

Assembly Language: Function Calls" Goals of this Lecture"

Assembly Language: Function Calls. Goals of this Lecture. Function Call Problems

CSE P 501 Compilers. x86 Lite for Compiler Writers Hal Perkins Autumn /25/ Hal Perkins & UW CSE J-1

Code Generation. Lecture 30

Intro to GNU Assembly Language on Intel Processors

Instruction Set Architecture

CS 31: Intro to Systems Functions and the Stack. Martin Gagne Swarthmore College February 23, 2016

1 /* file cpuid2.s */ 4.asciz "The processor Vendor ID is %s \n" 5.section.bss. 6.lcomm buffer, section.text. 8.globl _start.

Instruction Set Architecture

CISC 360 Instruction Set Architecture

4) C = 96 * B 5) 1 and 3 only 6) 2 and 4 only

Program Exploitation Intro

Winter Compiler Construction T11 Activation records + Introduction to x86 assembly. Today. Tips for PA4. Today:

How Software Executes

Assembly I: Basic Operations. Computer Systems Laboratory Sungkyunkwan University

Software. Hardware. x86 basics. ISA View. a brief history of x86 10/6/15. Program, Application. Programming Language. Compiler/Interpreter

Assembly I: Basic Operations. Jo, Heeseung

Assembly Language: IA-32 Instructions

CPS104 Recitation: Assembly Programming

ASSEMBLY I: BASIC OPERATIONS. Jo, Heeseung

Instructor: Alvin R. Lebeck

Chapter 4 Processor Architecture: Y86 (Sections 4.1 & 4.3) with material from Dr. Bin Ren, College of William & Mary

Machine-Level Programming II: Control and Arithmetic

Lecture 15 Intel Manual, Vol. 1, Chapter 3. Fri, Mar 6, Hampden-Sydney College. The x86 Architecture. Robb T. Koether. Overview of the x86

Low-Level Essentials for Understanding Security Problems Aurélien Francillon

CS24: INTRODUCTION TO COMPUTING SYSTEMS. Spring 2016 Lecture 12

Procedure Calls. Young W. Lim Sat. Young W. Lim Procedure Calls Sat 1 / 27

Lecture Outline. Code Generation. Lecture 30. Example of a Stack Machine Program. Stack Machines

Process Layout, Function Calls, and the Heap

The course that gives CMU its Zip! Machine-Level Programming III: Procedures Sept. 17, 2002

The x86 Architecture

What the CPU Sees Basic Flow Control Conditional Flow Control Structured Flow Control Functions and Scope. C Flow Control.

from WRITE GREAT CODE Volume 2: Thinking Low-Level, Writing High-Level ONLINE APPENDIX A The Minimal 80x86 Instruction Set by Randall Hyde

Credits and Disclaimers

X86 Review Process Layout, ISA, etc. CS642: Computer Security. Drew Davidson

Lab 10: Introduction to x86 Assembly

Assembly III: Procedures. Jin-Soo Kim Computer Systems Laboratory Sungkyunkwan University

Turning C into Object Code Code in files p1.c p2.c Compile with command: gcc -O p1.c p2.c -o p Use optimizations (-O) Put resulting binary in file p

x86 Assembly Crash Course Don Porter

Practical Malware Analysis

Procedure Calls. Young W. Lim Mon. Young W. Lim Procedure Calls Mon 1 / 29

CSE2421 FINAL EXAM SPRING Name KEY. Instructions: Signature

Intel Instruction Set (gas)

Credits to Randy Bryant & Dave O Hallaron

2.7 Supporting Procedures in hardware. Why procedures or functions? Procedure calls

CS429: Computer Organization and Architecture

Assembly Language: Overview!

Homework. In-line Assembly Code Machine Language Program Efficiency Tricks Reading PAL, pp 3-6, Practice Exam 1

Sistemi Operativi. Lez. 16 Elementi del linguaggio Assembler AT&T

Assembly III: Procedures. Jo, Heeseung

Assignment 11: functions, calling conventions, and the stack

ASSEMBLY III: PROCEDURES. Jo, Heeseung

CS213. Machine-Level Programming III: Procedures

The Hardware/Software Interface CSE351 Spring 2013

Sungkyunkwan University

Machine Level Programming II: Arithmetic &Control

System Programming and Computer Architecture (Fall 2009)

CS241 Computer Organization Spring Introduction to Assembly

Machine-Level Programming II: Arithmetic & Control /18-243: Introduction to Computer Systems 6th Lecture, 5 June 2012

CS642: Computer Security

ASSEMBLY II: CONTROL FLOW. Jo, Heeseung

CSC 8400: Computer Systems. Machine-Level Representation of Programs

Machine-Level Programming I: Introduction Jan. 30, 2001

Computer Science 104:! Y86 & Single Cycle Processor Design!

Machine-level Programming (3)

Credits and Disclaimers

Machine Programming 1: Introduction

CSCE 212H, Spring 2008 Lab Assignment 3: Assembly Language Assigned: Feb. 7, Due: Feb. 14, 11:59PM

Machine Programming 3: Procedures

Lecture #16: Introduction to Runtime Organization. Last modified: Fri Mar 19 00:17: CS164: Lecture #16 1

An Introduction to x86 ASM

CSC 2400: Computer Systems. Towards the Hardware: Machine-Level Representation of Programs

Chapter 4! Processor Architecture!

Handout #2: Machine-Level Programs

Compiler construction. x86 architecture. This lecture. Lecture 6: Code generation for x86. x86: assembly for a real machine.

Transcription:

Compiler Construction SMD163 Lecture 8: Introduction to code generation Viktor Leijon & Peter Jonsson with slides by Johan Nordlander Contains material generously provided by Mark P. Jones What is a Compiler? Compilers are translators. But so far, we have spent our time just looking at how a compiler can make sense of its input!! From character streams! to token streams! to structured representations! to validated representations. Now, at last, we are ready to start looking at the translation process itself. 1 2 Why Translation is Needed: We write programs at a higher level than the machine can execute directly.! Spreadsheet: sum [A1:A3]! Java: a[1] + a[2] + a[3]! Machine language: movl $0, %eax addl 4(a), %eax addl 8(a), %eax addl 12(a), %eax High-level languages describe what is to be done without worrying about all the details. In machine languages, every step must be carefully spelled out. Know your Target: The source language has been the driving force in each of the compiler phases that we have studied so far. As we move to the backend of a compiler, the target language becomes more important. But the source language still has a role to play:! How do we map source language datatypes and primitives to the target machine?! How do we map source program constructs to the target machine instruction set? 3 4

Our Target: To begin with, we will compile MiniJava programs directly to the assembly language of IA32 processors like the Intel 386 and above. We will look at general techniques, and then focus on details that are needed for the implementation of functions and objects. An Introduction to Assembly Language Programming for IA32 Later, we will consider an alternative approach to code generation that introduces an intermediate language that allows better code generation and optimization. 5 6 Programming the 386: Notes: 386/486/Pentium class machines are 32 bit CISC processors (Complex Instruction Set Processors). Although we focus on the 386, most of what we do here will be directly applicable to other processors. In concrete terms, a 386 program is just a collection of byte values stored in memory (machine code), which the processor executes. No in-depth knowledge of 386 programming will be assumed, and we will only use a small part of the 386 instruction set. For practical purposes, 386 programs can be written in a textual format called an assembly language. If you re looking to become an expert on 386 programming, you need to look for another class! A compiler that translates assembly language into machine language is called an assembler. 7 We will use the AT&T syntax for 386 assembly language rather than the Intel syntax. This is the syntax used by the free GNU tools in Linux (as well as Cygwin or DJGPP under Windows). 8

A 386 s view of the World: Central Processing Unit Accumulator Base Count Data Source Index Destination Index Base Pointer Stack Pointer Instruction Pointer Flags eax ebx ecx edx esi edi ebp esp eip eflag (Greatly Simplified!) 386 instructions can: Main Memory & The Outside World Read values from memory into registers; Operate on the values in registers; Write results back to memory. Memory slow, registers fast! 9 386 Registers: All the registers hold 32 bits; There s a lot of history here:! As the names suggest, some of the registers have special purposes.! Smaller portions of these registers can be accessed by other names: hi byte byte eax byte ah ax byte al lo 10 Addressing Modes: Instruction Format: How do we tell the assembler where data comes from? Register accesses (reg):! %eax: The value in register eax. Memory accesses (mem):! var: the value at memory location address var.! 8(%eax): the value at the memory location formed by adding 8 and the contents of the eax register. Immediate (immed):! $123: the constant value, 123.! $var: the address of memory location var. 11 A typical 386 instruction has the form: opcode src, dst what to do input source result destination A suffix on the opcode indicates the size of the data that is being operated on:! 32 bit values use the suffix l(ong);! 16 bit values use the suffix w(ord);! 8 bit values use the suffix b(yte). We ll only be using the 32 bit instructions. 12

Move Instructions: Copy data from src to dst: movl src, dst Any of the following combinations of arguments is allowed.! movl reg, (reg mem)! movl mem, reg! movl immed, (reg mem) Note that we can t move mem to mem in one instruction. Examples: Suppose that memory (starting at address 0) contains the following (four byte) values: 8 Then: 6 2 Instruction 4 movl $12, %eax 0 movl (%eax), %eax movl 12(%eax), %eax 2 4 1 7 3 4 12 4 0 5 6 Contents of eax 13 14 The Exchange Instruction: Exchanging data between two locations: xchgl (reg mem), reg Consider the following sequence of instructions in a high-level language: int tmp = x; x = y; y = tmp; If the compiler is clever enough, and if x and y are being held in registers, then it can compile this code to a single xchgl instruction! 15 Jumping and Labels: We can transfer control and start executing instructions at address addr by using a jump instruction: jmp addr Labels can be attached to each instruction in an assembly language program: start: jmp b a : jmp c b : jmp a c : Modern, pipelined machines work well on sequences of instructions that appear in consecutive locations. Jumps can be expensive: one of the goals of an optimizing compiler is to avoid unnecessary jumps. 16

Arithmetic Instructions: Combine a given src value with a given dst value and leave the result in dst: addl src, dst subl src, dst imull src, dst andl src, dst orl src, dst xorl src, dst number arithmetic bitwise arithmetic 17 Examples: To compute x 2 +y 2 and store the result in z: movl x, %eax imull %eax, %eax movl y, %ebx imull %ebx, %ebx addl %ebx, %eax movl %eax, z 18 Flags: More Conditional Jumps: In addition to performing the required arithmetic operation, arithmetic instructions set flags in the eflag register that indicate:! Was the result zero?! Was the result positive/negative?! Did a carry occur?! Etc jnz addr jl addr jnl addr jg addr jng addr etc... Jump if non-zero Jump if less than Jump if not less than Jump if greater than Jump if not greater than We can test these flags in conditional jump instructions like:! jz addr (jump to addr if zero) For example: subl %eax, %ebx jl addr will branch to addr if the result is less than 0. 19 20

The Compare Instruction: The cmpl instruction behaves like subl, except that the result is not saved. For example: cmpl %eax, %ebx jl addr will branch to addr if ebx is less than eax, but will not change the values in either register. Conditionals have limited range: On a 386, the addr in a conditional jump must be within ± 32K, so the following won t work: jz lab 40K bytes of instructions lab: For longer jumps, use: jnz lab1 jmp lab lab1: 40K bytes of instructions lab: 21 but we won t worry about this here! 22 Unary Operations: The following arithmetic operations have only a single argument: negl notl incl decl (reg mem) (reg mem) (reg mem) (reg mem) negation complement increment decrement Like the binary operators, they also set the flags for subsequent testing. 23 Division: Divide implicit destination (edx:eax) by src, with result in eax, remainder in edx: idivl src Division produces multiple results: a quotient and a remainder. Division uses special registers: we d better not store any other values in eax or edx if there s a chance that a division instruction might be executed. 24

Stack Accesses: Push value onto the stack : pushl src src can be reg, mem, or immed. What is the Stack? The 386 register %esp is the stack pointer. When a program begins, %esp is usually initialized to point to the top of a reserved area of memory called the stack. Pop value off the stack : popl dst dst can be mem, or reg. esp The stack is an area of scratch space that can be used to store temporary values. 25 26 Stacks Grow Downwards: A complex instruction set? Rougly speaking:! pushl src = subl $4, %esp; movl src, (%esp)! popl dst = movl (%esp), dst; addl $4, %esp A classic memory layout: program data free stack The stack can grow to use up all the memory that is left after the program and main data. 27 The 386 is as a CISC because it has a complex instruction set: one instruction can do many things. For example: movl 8(%ebx,%eax,4), %eax does the same as: imul $4, %eax addl %ebx, %eax addl $8, %eax movl (%eax), %eax You need to read the technical documentation to find out which one is faster/takes fewer bytes. On a CISC machine, the single instruction is usually the winner. Using CISC instructions effectively is a major challenge for compiler writers. 28

RISC vs CISC: RISC machines have a reduced instruction set: multiple RISC instructions must be used to simulate one CISC instruction but each RISC instruction can potentially run more quickly. Easier compiler targets? RISC machines are simpler and more regular than typical CISC machines. They often have more registers than a CISC machine too. Harder compiler targets? The general philosophy of RISC machines is to let compilers (rather than CPUs) handle the complex tasks. Call and Return: A special instructions for calling a function: call addr push $lab jmp addr lab: And a special instruction for returning: ret pop %eax jmp *%eax Assuming we were not using eax for something else We will see that additional instructions are often needed in practice to deal with parameter passing 29 30 The GNU Assembler, gas: Assembly code goes in files with a.s suffix. We will use gcc to invoke the assembler:! gcc o output assemblycode.s runtime.c You can also invoke gas directly. A detailed manual is available from: http://www.gnu.org/manual/ Look for gas-2.9.1, and then in particular for the section on 80386 Dependent Features. This information provided only for the curious; for this class, all the details that you need should be on these slides or in the distributed source code. 31 386 Programming, Summary: A 386 machine has:! A fixed set of registers;! Instructions for moving and operating on data;! Instructions for testing and control transfer. To generate good code for the 386 we need:! To select appropriate instructions;! To make good use of registers and avoid unnecessary memory accesses;! To avoid using registers that are already in use;! To keep the number of jumps as low as possible. 32

Doing vs Thinking about Doing: First Steps To Code Generation Use your calculator to evaluate (1+2)+(3+4):! Answer: 10 Tell me what buttons to press on your calculator to evaluate (1+2)+(3+4):! Answer: Press 1 + 2 = M 3 + 4 = + MR = There is a big difference between doing something, and thinking about/describing how to do something. 33 34 Interpreters vs Compilers: Thinking about Translating: Interpreters do : interpreter Source Diagnostics Compilers think about doing : compiler Source Diagnostics Input Output Input program Output There are two levels of translation that we need to consider: How will the values of types in the source language be mapped to values of types in the target language? How will the constructs of the source language be mapped to constructs in the target language? 35 36

Translating Values: How do we represent source language values in the target language? We only have a few primitive types so far:! We ll represent ints by 32 bit words;! We ll represent booleans by 32 bit words using: " 0 to represent false; " 1 to represent true. The representation of objects will take a little more work but that ll be next lecture! Translating Statements/Expressions: A statement describes an action:! So compilation of a statement should produce code to execute that action. An expression describes a value:! So compilation of an expression should produce code that can be executed to calculate that value. To make this work we need:! A general strategy;! A mapping of that strategy onto our target machine. 37 38 A General Strategy (1 st version): Suppose we had just two registers, eax and ebx. Where will we store intermediate results?! In registers? Not enough of them!! In memory? But how do we allocate storage for them?! On the stack: push a value on to the stack when we need to save it pop value off later to recover it. Our general strategy for compiling code will be:! Calculate a value for the expression and leave the result in eax.! Use the stack for temporary saving the contents of Compiling Addition: For example, to compile the expression e 1 +e 2 : code to evaluate e 1, leaving result in eax pushl %eax code to evaluate e 2, leaving result in eax popl %ebx addl %ebx, %eax The result of any subexpression is found in eax The value of eax is saved on the stack when it must survive the computation of another subexpression eax when necessary 39 40

A More Formal Description: We can capture this rule for compilation more formally using: E[e 1 +e 2 ] = E[e 1 ] pushl %eax E[e 2 ] popl %ebx addl %ebx, %eax We can extend the compilation scheme E to a other forms of expression: E[n] = movl $n, %eax continued: Compilation of conditional logic operators: E[e 1 &&e 2 ] = E[e 1 ] cmpl $1, %eax jnz lab1 E[e 2 ] lab1: Compilation of variable references: E[var] = movl var, %eax a new label 41 42 Or, in Java: Add a method to the Exp class: abstract void compile(assembly a); Add the following to class Plus: void compile(assembly a) { e1.compile(a); a.emit( pushl, %eax ); e2.compile(a); a.emit( popl, %ebx ); a.emit( addl, %ebx, %eax ); } continued: Add the following to class IntegerLiteral: void compile(assembly a) { a.emit( movl, a.immed(i), %eax ); } Add the following to class IdentifierExp: void compile(assembly a) { a.emit( movl, s, %eax ); } and so on 43 44

Assembly Code Output: We use objects of type Assembly to represent output assembly files: public class Assembly { static Assembly assembletofile(string name); String newlabel(); void emitlabel(string name); void emit(string op); void emit(string op, String op1); void emit(string op, String op1, String op2); String immed(int v); String indirect(int n, String s); For Example: (2+4) * (3+5) ; eax ebx stack movl 2,%eax ; 2 pushl %eax ; 2 2 movl 4,%eax ; 4 2 popl %ebx ; 4 2 add %ebx,%eax ; 6 2 pushl %eax ; 6 2 6 movl 3,%eax ; 3 2 6 pushl %eax ; 3 2 3 6 movl 5,%eax ; 5 2 3 6 popl %ebx ; 5 3 6 add %ebx,%eax ; 8 3 6 popl %ebx ; 8 6 mull %ebx,%eax ; 48 6 } 45 46 We Need Register Allocation: But why use the stack at all? We have more than two registers: movl $2, %eax movl $4, %ebx addl %ebx, %eax movl $3, %ebx movl $5, %ecx addl %ecx, %ebx imull %ebx, %eax How can we modify our compilation schemes to make good use of machine registers? 47 We Need Better Schemes: Further improvements are also possible by making better use of the instruction set: movl $2, %eax addl $4, %eax movl $3, %ebx addl $5, %ebx imull %ebx, %eax This just requires a specialized version of our revised compilation scheme: E 1 [e 1 +n] = E 1 [e 1 ] addl $n,%eax 48

Compiling Statements: We introduce a new compilation scheme for statements: S[if (e) s 1 else s 2 ] = E[e] cmpl $1, %eax jnz lab1 S[s 1 ] jmp lab2 lab1: S[s 2 ] lab2: continued: S[e;] = E[e] S[while (e) s] = lab1: E[e] lab2: cmpl $1, %eax jnz lab2 S[s] jmp lab1 lab1, lab2 are new labels. 49 lab1, lab2 are new labels. 50 Our First Optimization! Summary: An alternative compilation rule: The constructs of high-level languages can be implemented using sequences of machine instructions. S[while (e) s] = jmp lab2 lab1: lab2: S[s] E[e] cmpl $1, %eax jz lab1 Question: When is this an improvement? Why? 51 It is important to select good target instructions for each source construct. Compilation schemes can be used to describe the mapping between languages. To get better code quality, we should:! Make good use of the target s instructions, registers, etc! Use refined compilation schemes to deal with special cases.! [This is the topic for next week] Next lecture: implementing functions and objects! 52