• Nenhum resultado encontrado

Geração de Código Intermediário. Tradução dirigida por sintaxe. Código de três endereços - exemplo. Código de Três Endereços

N/A
N/A
Protected

Academic year: 2021

Share "Geração de Código Intermediário. Tradução dirigida por sintaxe. Código de três endereços - exemplo. Código de Três Endereços"

Copied!
7
0
0

Texto

(1)

Geração de Código Intermediário

• Vantagens do uso de uma notação

intermediária:

– facilidade de retargetting: geração de código para vários processadores diferentes, reusando o máximo possível do código em todos os compiladores, mudando apenas o gerador de código final.

– uso de otimizador único para vários geradores de código diferentes.

Tradução dirigida por sintaxe

parser verificador de código código intermediário gerador de código intermediário gerador de código

front-end

back-end

Código de Três Endereços

• Frequentemente usado como código intermediário, para linguagens imperativas/OO.

• Abstrai um assembler, onde cada instrução básica referencia 3 (ou menos) endereços (i.e. variáveis). • Formato: x := y op z • Exemplo: x + y * z é reescrito para t1:= y * z t2:= x + t1

Código de três endereços

-exemplo

• t

1

:= -c

t

2

:= b * t

1

t

3

:= -c

t

4

:= b * t

3

t

5

:= t

2

+ t

4

a := t

5 * assign + uminus a * uminus c b b c

a = b * -c + b * -c;

Tipos de código de três endereços

• Atribuição do tipo: x = y op z

• Atribuição do tipo: x = op y

• Cópia: x = y

• desvios incondicionais: goto L

• desvios condicionais: if x goto L e ifFalse x

goto L

• desvios condicionais: if x relop y goto L

Tipos de código de três endereços

(cont.)

• chamada de procedimentos:

param x, call p, n e return y

• atribuição indexada: x = y[i] e x[i] = y

• atribuição de endereços e ponteiros:

(2)

Tradução dirigida por sintaxe

para código de três endereços

S  id = E S.code := E.code ||

gen(id.place ‘=‘ E.place)

E  E1+ E2 E.place := newtemp;

E.code := E1.code || E2.code ||

gen(E.place ‘=‘ E1.place ‘+’ E2.place) E  - E1 E.place := newtemp;

E.code := E1.code ||

gen(E.place ‘=‘ ‘uminus’ E1.place) E  ( E1) E.place := E1.place; E.code := E1.code E  id E.place := id.place; E.code := ‘’

Tradução do while

S

 while (E) S

1 Regra Semântica: S.begin := newlabel; S.end := newlabel; S.code := gen(S.begin ‘:’) || E.code ||

gen(‘if’ E.place ‘=‘ ‘0’ ‘goto’ S.end) || S1.code ||

gen(‘goto’ S.begin) || gen(S.end ‘: ‘)

Declarações

• Declarações dentro de um procedimento frequentemente são tratadas como um único grupo, e são acessadas como um offset do ponto onde começam a ser armazenadas (na pilha). • offset inicialmente é zero, e a cada novo símbolo

declarado o valor do offset é guardado na tabela de símbolos, e o offset é incrementado.

• exemplo: procedimento enter(name,type,offset)

Declarações

P  {offset := 0} D D  D ; D

D  id : T { enter(id.name, T.type, offset); offset := offset + T.width } T  integer { T.type := integer;

T.width := 4; } T  real { T.type := real;

T.width := 8; } T  array [ num ] of T1

{ T.type := array(num.val, T1.type);

T.width := num.val * T1.width }

Declarações –tratando escopo

• uma possibilidade é manter tabelas de símbolos

separadas para cada procedimento, com referências ao contexto mais externo (outra tabela de símbolos).

Declarações –tratando escopo

• procedimentos utilizados:

– mktable(previous) – cria uma nova tabela de símbolos, com referência à anterior

– enter(table, name, type, offset) – insere um novo símbolo na tabela

– addwidth(table, width) – incrementa contador do tamanho da tabela

– enterproc(table,name,newtable) – insere um novo símbolo (procedimento) na tabela e pilhas offset e tblptr

(3)

Declarações –tratando escopo

P  M D { addwidth(top(tblptr),top(offset)); pop(tblptr); pop(offset); } M  ε {t := mktable(nil); push(t,tblptr); push(0,offset);} D  D1; D2 D  proc id ; N D1; S { t := top(tblptr); addwidth(t, top(offset)); pop(tblptr); pop(offset); enterproc(top(tblptr),id.name,t)} D  id : T { enter(top(tblptr),id.name,T.type,top(offset));

top(offset) := top(offset) + T.width } N  ε { t := mktable(top(tblptr));

push(t,tblptr); push (0,offset) }

Declarações –tratando registros

• nomes de campos de registros também podem ser guardados usando tabelas de símbolos específicas para cada (tipo) registro.

T  record L D end { T.type := record(top(tblptr)); T.width := top(offset); pop(tblptr);

pop(offset); }

L  ε { t := mktable(nil); push(t,tblptr); push (0,offset) }

Revendo Atribuições

S  id = E { p = lookup(id.name);

if (p != nil) gen(p ‘=‘ E.place) else error }

E  E1+ E2 { E.place = newtemp;

gen(E.place ‘=‘ E1.place ‘+’ E2.place) } E  - E1 { E.place = newtemp;

gen(E.place ‘=‘ ‘uminus’ E1.place) } E  ( E1) { E.place = E1.place }

E  id { p = lookup(id.name);

if (p != nil) E.place = p else error }

Reuso de nomes

• Controlando o tempo de vida dos nomes usados dentro de cada statement ou expressão, é possível fazer o reuso de nomes de variáveis temporárias.

• Exemplo: usar contador incrementado para cada novo temporário, e decrementado para cada uso. • evaluate E1to t1

evaluate E2to t2 t := t1+ t2

Reuso de nomes - exemplo

• x = ((a * b) + (c * d)) – (e * f)

• t0 = a * b

t1 = c * d

t0 = t0 + t1

t1 = e * f

t0 = t0 - t1

x = t0

Acesso a Arrays

• controlado de acordo com o tamanho e o tipo do array: base + (i – low) * w

• ou melhor ainda: i * w + (base – low * w) • existem fórmulas genéricas para arrays

multidimensionais:

– 2D: A[i1 , i2]

base + ((i1– low1) * n2+ i2– low2) * w • row-major vs. column-major

(4)

Expressões Booleanas

• Podem ser avaliadas de duas formas:

– codificar true e false como números, e avaliar as expressões da mesma forma que expressões matemáticas.

– usar o fluxo de controle, i.e. representar um valor por uma posição atingida no programa. Usada em if-then-else, while-do etc. Permite “curto-circuito” de expressões: se E1é avaliado como true, na expressão

E1or E2, não é necessário avaliar E2.

Representação numérica

-exemplo

• a or b and not c

• t

1

= not c

t

2

= b and t

1

t

3

= a or t

2

Representação numérica

-exemplo

• a < b

é traduzido para

if (a < b) 1 else 0

• 100: if a < b goto 103 101: t = 0 102: goto 104 103: t = 1 104:

Esquema de Tradução

E  E1or E2 { E.place = newtemp;

gen(E.place ‘=‘ E1.place ‘or’ E2.place) }

E  id1relop id2

{ E.place = newtemp;

gen(‘if’ id1.place relop.op id2.place ‘goto’ nextstat + 3);

gen(E.place ‘=‘ ‘0’); gen(‘goto’ nextstat + 2); gen(E.place ‘=‘ ‘1’) } E  ( E1) { E.place = E1.place }

E  true { E.place = newtemp; gen(E.place ‘=‘ ‘1’) }

Representação numérica

-exemplo

100: if a < b goto 103 101: t1 = 0 102: goto 104 103: t1 = 1 104: if c < d goto 107 105: t2 = 0 106: goto 108 107: t2 = 1 108: if e < f goto 111 109: t3 = 0 110: goto 112 111: t3 = 1 112: t4 = t2 and t3 113: t5 = t1 or t4

a < b or c < d and e < f

Fluxo de controle

• Associamos a cada expressão booleana

desvios para labels caso a expressão seja

avaliada para true ou false.

(5)

Tradução do if-then

S

 if (E) S

1

Regra Semântica:

E.true = newlabel;

E.false = S.next;

S

1

.next = S.next;

S.code = E.code || gen(E.true ‘:’) || S

1

.code

Tradução do if-then-else

S

 if (E) S

1

else S

2

Regra Semântica:

E.true = newlabel; E.false = newlabel;

S

1

.next = S.next; S

2

.next = S.next;

S.code = E.code ||

gen(E.true ‘:’) || S

1

.code

gen(‘goto’ S.next);

gen(E.false ‘:’) || S

2

.code

atributos herdados

Tradução do while

S

 while (E) S

1

Regra Semântica:

S.begin = newlabel; E.true = newlabel;

E.false = S.next; S

1

.next = S.begin;

S.code = gen(S.begin ‘:’) || E.code ||

gen(E.true ‘:’) || S

1

.code ||

gen(‘goto’ S.begin)

Fluxo de controle

• a < b traduzido para:

if a < b goto E.true

goto E.false

Esquema de Tradução

E  E1or E2 { E1.true := E.true; E1.false := newlabel;

E2.true := E.true; E2.false := E.false; E.code := E1.code ||

gen(E1.false ‘:’) || E2.code) } E  E1and E2 {E1.true := newlabel; E1.false := E.false;

E2.true := E.true; E2.false := E.false; E.code := E1.code ||

gen(E1.true ‘:’) || E2.code) }

Esquema de Tradução

E  not E1 { E1.true := E.false; E1.false := E.true;

E.code := E1.code} E  id1relop id2

{E.code := gen(‘if’ id1.place relop.op id2.place ‘goto’ E.true ||

gen(‘goto’ E.false) } E  true {E.code := gen(‘goto’ E.true } E  false {E.code := gen(‘goto’ E.false }

(6)

Exemplo 1

• a < b or c < d and e < f • if a < b goto Ltrue goto L1 L1: if c < d goto L2 goto Lfalse L2: if e < f goto Ltrue goto LFalse

• é possível otimizar o código acima.

Exemplo 2

• while a < b do if c < d then x := y + z else x := y – z • L1: if a < b goto L2 goto Lnext L2: if c < d goto L3 goto L4 L3: t1 := y + z x := t1 goto L1 L4: t2 := y – z x := t2 goto L1

switch/case

• switch expression begin

case value: statement case value: statement

case value: statement default: statement end

implementação de switch/case

• sequência de goto’s condicionais, um para cada caso. • loop percorrendo uma tabela de valores e labels para

o código do statement correspodente. • hash table com valores e labels

• criar um array de labels, com o label para o statement j na posição da tabela índice j.

tradução de switch/case

• switch E begin case V1: S1 case V2: S2case Vn-1: Sn-1 default: Sn end

tradução de switch/case

código para avaliar E em t

goto test L1: código para S1 goto next L2: código para S2 goto next … Ln-1: código para Sn-1 goto next Ln: código para Sn goto next test: if t = V1goto L1 if t = V2goto L2 … if t = Vn-1 goto Ln-1 goto Ln next:

(7)

outra tradução de switch/case

código para avaliar E em t

if t ≠ V1goto L1 código para S1 goto next L1: if t ≠ V2goto L2 código para S2 goto next L2: … Ln-2: if t ≠ Vn-1goto Ln-1 código para Sn-1 goto next Ln-1: código para Sn next:

Backpatching

• uso de um passo extra para resolver as referências a labels definidos posteriormente.

Esquema de Tradução

E  E1or M E2

{ backpatch(E1.falselist,M.quad); E.truelist := merge(E1.truelist,E2.truelist); E.falselist := E2.falselist }

M  ε {M.quad := nextquad } E  E1and M E2

{ backpatch(E1.truelist,M.quad); E.truelist := E2.truelist;

E.falselist := merge(E1.falselist,E2.falselist); }

Esquema de Tradução

E  true { E.truelist := makelist(nextquad); emit(‘goto _’) } E  false { E.falselist := makelist(nextquad); emit(‘goto _’) }

Referências

Documentos relacionados

O PAEF/PORTUGAL: situação antes da ajuda (2011) Após a adesão à CE, Portugal experimentou vários anos de crescimento significativo; contudo, a adaptação à moeda

Este artigo considera como violação de norma antidopagem a associação de carater profissional ou desportivo de um Praticante Desportivo, ou de outra pessoa, com um membro do

Se, entretanto, um escravo do estado ou escravo de um homem livre casar com a filha de um homem livre, e após o casamento ela trouxer um dote da casa de seu pai, se então os

Fornecer instruções precisas (especialmente no cumprimento da lei). Comunicar claramente a importância da ética e integridade e incentivar seus funcionários a usar o código de

hormonal (análogos do GnRH, progestagênios e contraceptivos hormonais) para tratamento da doença na ocasião da cirurgia e nos três meses anteriores a esta. Quarenta pacientes

449 - Não poderá servir o jurado que: (Redação dada pela Lei nº 11.689, de 2008) I - tiver funcionado em julgamento anterior do mesmo processo, independentemente da causa

§ 2° - A largura mínima do compartimento destinado do depósito de lixo Será de 0,80 m (oitenta centímetros) para até 2000 (dois mil metros quadrados) de área útil da edificação

Compete ao Conselho de Ética da raps receber consulta ou denúncia de membros da raps, bem como de terceiros, interpretar e responder a quaisquer questionamentos que possam