• Nenhum resultado encontrado

Compiladores (CC3001) Aula 11: Implementação de código intermédio

N/A
N/A
Protected

Academic year: 2021

Share "Compiladores (CC3001) Aula 11: Implementação de código intermédio"

Copied!
18
0
0

Texto

(1)

Compiladores (CC3001)

Aula 11: Implementação de código intermédio

Pedro Vasconcelos

DCC/FCUP

(2)

Esta aula

Geração de código intermédio Implementação em C

(3)

Re-lembrar: fases dum compilador

texto do programa ↓ Análise lexical ↓ sequência de tokens ↓ Análise sintática ↓

árvore sintática abstrata ↓

Análise semântica ↓

AST & tabela de símbolos

Geração de código ↓

código intermédio

Seleção de instruções ↓

código assembly simbólico ↓

Alocação de registos ↓

código assembly concreto ↓

Assembler & linker ↓

(4)

Geração de código intermédio

I Na aula passada: esquemas de tradução de uma linguagem imperativa para código intermédio de 3 endereços

I Nesta aula: vamos ver algumas formas para implementar esses esquemas de tradução em C e Haskell

(5)

Representação de instruções em C

#include <stdint.h>

typedef struct { Opcode opcode;

Addr arg1, arg2, arg3, ...; // argumentos } Instr;

typedef enum { MOVE, MOVEI, ... } Opcode; // código da instrução typedef intptr_t Addr; // endereço (inteiro ou apontador)

I Estruturas com número xo de campos

I Denimos um código distinto para cada tipo de instrução (MOVE, MOVEI, etc.) I A maioria da instruções usa 2 ou 3 argumentos (exceção: COND)

(6)

Temporários e etiquetas

I Representar variáveis e etiquetas temporárias por inteiros

I Usamos contadores globais para gerar novos temporários e etiquetas: int temp_count = 0, label_count = 0;

int newTemp() { return temp_count ++; } int newLabel () { return label_count ++; }

(7)

Geração de instruções

I Em vez de listas podemos gerar um vector de instruçõesglobal

I Funções auxiliares para acrescentar uma nova instrução ao nal (marcado pelo instruction pointer)

I Intercalando emit com as chamadas recursivas podemos evitar a necessidade de concatenações de listas void emit2(opc,arg1,arg2); void emit3(opc,arg1,arg2,arg3); ... instr 1 instr 2 ... instr n IP → =⇒ instr 1 instr 2 ... instr n instr n+1 IP →

(8)

Geração de instruções (cont.)

void transExp(Exp exp, dest) {

switch(...) { case BINOP:

t1 = newTemp(); t2 = newTemp();

transExp(exp->binop.left, t1); // lado esquerdo transExp(exp->binop.right, t2); // lado direito

emit3(opcode(exp->binop.op), dest, t1, t2); // instrução final break;

} }

(9)

Implementação em Haskell

I Representar instruções como um tipo algébrico I As funções de tradução retornam listas de instruções I Geração de variáveis temporárias e etiquetas

I passar explicitamente contadores; ou

(10)

Representação de instruções

data Instr = MOVE Temp Temp - temp1 := temp2

| MOVEI Temp Int - temp1 := num

| OP BinOp Temp Temp Temp - temp1 := temp2 op temp3 | OPI BinOp Temp Temp Int - temp1 := temp2 op num | LABEL Label

| JUMP Label

| COND Temp RelOp Temp Label Label type Temp = String

type Label = String

- operadores da linguagem data BinOp = Plus | Minus | ... data RelOp = Lt | Lteq | Eq | ...

(11)

Geração de variáveis e etiquetas

type Count = (Int, Int) - contadores de temporários e etiquetas newTemp :: Count -> (Temp, Count)

newTemp (temps, labels) = ("t"++show temps, (temps+1,labels)) newLabel :: Count -> (Label, Count)

(12)

Exemplo de tradução

Com passagem explicita dos contadores.

transExpr :: Expr -> Table -> Temp -> Count -> ([Instr], Count) transExpr (Num n) table dest count

= ([MOVEI dest n], count)

transExpr (Op op e1 e2) table dest count0 = let (t1, count1) = newTemp count0

(t2, count2) = newTemp count1

(code1, count3) = transExpr e1 table t1 count2 (code2, count4) = transExpr e2 table t2 count3 code = code1 ++ code2 ++ [OP op dest t1 t2] in (code, count4)

(13)

Passagem implícita dos contadores

I Passagem explícita étrabalhosae dada a erros

I usar count0 para obter count1, count1 para obter count2, . . .

I em caso de engano vamos re-utilizar temporários e gerar código errado I Podemos modicar o programa para que apassagem seja implicita

(14)

Passagem implícita dos contadores (cont.)

I Importamos Control.Monad.State

I Alteramos o tipo da função

transExpr :: Expr -> Table -> Temp -> Count -> ([Instr], Count)

para

transExpr :: Expr -> Table -> Temp -> State Count [Instr]

I O tipo State Count signica que a função tem:

I um argumento implícito (o contador inicial)

(15)

Passagem implícita dos contadores (cont.)

Casos terminais: removemos os contadores e introduzimos return. - versão explícita

transExpr (Num n) table dest count = ([MOVEI dest n], count)

- versão implícita

(16)

Passagem implícita dos contadores (cont.)

Casos recursivos: removemos os contadores e usamos notação-do em vez de let. - versão explícita

transExpr (Op op e1 e2) table dest count0

= let (t1, count1) = newTemp count0

(t2, count2) = newTemp count1

(code1, count3) = transExpr e1 table t1 count2

(code2, count4) = transExpr e2 table t2 count3

in (code1 ++ code2 ++ [OP op dest t1 t2], count4) - versão implícita

transExpr (Op op e1 e2) table dest = do t1 <- newTemp

t2 <- newTemp

code1 <- transExpr e1 table t1 code2 <- transExpr e2 table t2

(17)

Passagem implícita dos contadores (cont.)

Para executar a tradução usamosrunStatecom os valores iniciais dos contadores. > let expr = Op Mult (Num 3) (Op Plus (Num 4) (Num 5))

> runState (transExpr expr Map.empty "x") (0,0) ([MOVEI "t0" 3, MOVEI "t2" 4, MOVEI "t3" 5,

OP Plus "t1" "t2" "t3", OP Mult "x" "t0" "t1"], (4,0)) Se não queremos o valor nal dos contadores podemos usarevalState. > evalState (transExpr expr Map.empty "x") (0,0)

[MOVEI "t0" 3, "MOVEI "t2" 4, MOVEI "t3" 5, OP Plus "t1" "t2" "t3", OP Mult "x" "t0" "t1"]

(18)

Passagem implícita dos contadores (cont.)

Temos ainda de mudar ligeiramente as funções auxiliares. type Count = (Int,Int)

newTemp :: State Count Temp

newTemp = do (temps,labels)<-get put (temps+1,labels) return ("t"++show temps) newLabel :: State Count Label

newLabel = do (temps,labels)<-get put (temps,labels+1) return ("L"++show labels)

Referências

Documentos relacionados

A clínica gestáltica tem o intuito de desenvolver um trabalho baseado na relação dialógica, que facilita o processo de autorregulação e ajustamento criativo para as pessoas.. Tais

Figura 13 – Espetros de UV/Vis da curva de calibração (solução-tampão pH = 3,46) De seguida e após a análise dos dados registou-se a absorvância ao comprimento de onda de 287

Contudo, ainda que a disponibilidade de indicadores sociais para uso no diagnóstico da realidade social empírica ou na análise da mudança social esteja condicionada à oferta e

Os maiores coeficientes da razão área/perímetro são das edificações Kanimbambo (12,75) e Barão do Rio Branco (10,22) ou seja possuem uma maior área por unidade de

A revolta do 1º de Dezembro e a guerra da Restauração Motim Restauração Cortes - Observação e legendagem de imagens; - Análise de transparências; - Elaboração

Com base nesses pressupostos, a presente pesquisa tem como objetivo analisar as políticas públicas habitacionais no continuo urbano transfronteiriço de Letícia na

To identify a source of ligands able to activate Olfr692- expressing cells, we first exposed adult animals to bio- logically relevant stimuli and then labeled the activated neurons

O rebocador convencional está claramente na sua melhor condição quando pode utilizar sua potência máxima e pode aplicar toda a sua força de tração estática na linha