(IFRS, 2015) Em relação a fase de síntese de um compilador, analise as alternativas a seguir, assinalando V, se verdadeiras, ou F, se falsas.
( ) No processo de traduzir um programa fonte para um código objeto, um compilador pode produzir uma ou mais representações intermediárias, as quais podem ter diversas formas.
( ) A fase de otimização de código depende única e exclusivamente das arquiteturas de máquinas para fazer transformações no código intermediário.
( ) O processo de otimização de código desenvolve-se em duas fases, uma que inclui técnicas para eliminar atribuições redundantes e suprimir subexpressões comuns, e outra, que inclui a troca de instruções de máquina por instruções mais rápidas e da melhor utilização de registradores.
( ) O processo de geração de código objeto compreende três principais tarefas: seleção de instrução; alocação e atribuição de registrador; e escolha de instruções apropriadas da arquitetura alvo para implementar os comandos da representação intermediária.
A ordem correta de preenchimento dos parênteses, de cima para baixo, é:
a. V – V – V – V
b. V – V – V – F
c. V – V – F – V
d. V – F – V – V
e. F – V – V – V
(POSCOMP, 2017) Uma representação intermediária do programa fonte pode ser gerada com a transformação da árvore de derivação em um segmento de código. Em relação à etapa de geração de código intermediário do compilador, analise as alternativas a seguir, assinalando V, se verdadeiras, ou F, se falsas.
( ) Definindo-se uma representação intermediária adequada, um compilador construído pode combinar um front-end para uma linguagem x com um back-end para a linguagem y.
( ) Árvores de sintaxe e códigos de três endereços são algumas das possibilidades de representação intermediária.
( ) Linguagens de alto nível, como, por exemplo, a linguagem C, podem ser utilizadas como uma forma de representação intermediária.
( ) Na geração de código intermediário, são realizadas tarefas como seleção de instruções, alocação e atribuição de registrador e escalonamento de instruções que dependem do conhecimento da máquina-alvo para a qual será gerado o código objeto.
( ) Uma das vantagens da aplicação da fase de geração de código intermediário é a possibilidade de realização de otimização e a tradução do código para diversas máquinas.
A ordem correta de preenchimento dos parênteses, de cima para baixo, é:
a. V – V – F – V – V
b. V – V – V – F – V
c. V – V – F – F – V
d. V – F – F – V – V
e. F – V – V – F – V
(POSCOMP, 2004) Dado o trecho de programa a seguir:
var a, b: integer;
procedure P (T1 x: integer; T2 y: integer);
var z: integer;
begin
z := x + a;
x := y + 1;
y := y + z;
end;
begin
a := 2;
b := 3;
P(a, b);
writeln(a, b);
end.
Onde T1 e T2 indicam mecanismos de passagem de parâmetros (por valor ou por referência). A tabela a seguir deve ser preenchida com os valores a serem impressos pelo programa para cada combinação de T1 e T2.
T1 | |||
---|---|---|---|
valor | referência | ||
T2 | valor | ||
referência |
Qual das alternativas abaixo preenche a tabela acima com os valores a serem impressos pelo trecho de programa?
a.
T1 | |||
---|---|---|---|
valor | referência | ||
T2 | valor | 2 3 | 4 3 |
referência | 2 7 | 4 7 |
b.
T1 | |||
---|---|---|---|
valor | referência | ||
T2 | valor | 2 3 | 2 7 |
referência | 4 3 | 4 7 |
c.
T1 | |||
---|---|---|---|
valor | referência | ||
T2 | valor | 2 3 | 4 7 |
referência | 2 3 | 4 7 |
d.
T1 | |||
---|---|---|---|
valor | referência | ||
T2 | valor | 2 3 | 2 3 |
referência | 2 3 | 2 3 |
e.
T1 | |||
---|---|---|---|
valor | referência | ||
T2 | valor | 4 7 | 4 7 |
referência | 4 7 | 4 7 |
(Deitel, 2003) Considere o programa escrito em Simpletron Machine Language, apresento a seguir.
Posição | Palavra | Instrução |
---|---|---|
00 | +1017 | read N |
01 | +2017 | load N |
02 | +4114 | branch negative to 14 |
03 | +4214 | branch zero to 14 |
04 | +3317 | multiply N |
05 | +3018 | add S |
06 | +2118 | store S |
07 | +2017 | load N |
08 | +3016 | add -1 |
09 | +2117 | store N |
10 | +4212 | branch zero to 12 |
11 | +4004 | branch to 04 |
12 | +1118 | write S |
13 | +4300 | halt |
14 | +1116 | write -1 |
15 | +4300 | halt |
16 | -0001 | variable -1 |
17 | +0000 | variable N |
18 | +0000 | variable S |
Com base no programa apresentado, avalie as assertivas a seguir.
A respeito dessas asserções, assinale a alternativa correta.
a. apenas as assertivas I e II.
b. apenas as assertivas I e III.
c. apenas as assertivas II e III.
d. apenas as assertivas II e IV.
e. apenas as assertivas III e IV.
(Price, 2005) A notação tradicional para expressões aritméticas, que representa uma operação binária na forma x + y, ou seja, com o operador entre seus dois operandos, é conhecida como notação infixada. Uma notação alternativa para esse tipo de expressão é a notação pré-fixada, na qual o operador é expresso antes de seus operandos, como por exemplo, + x y. Outra notação alternativa é a notação pós-fixada, na qual o operador é expresso após seus operandos, como por exemplo, x y +. O atrativo das notações pré-fixada e pós-fixada é que elas dispensam o uso de parênteses ao adotar a noção de pilha para a representação das expressões. Analise as assertivas a seguir, considerando a gramática livre de contexto G.
G = ({A, E, T, F, V}, {a, b, c, d, e, f, g, =, +, -, *, /, (, )}, P, A)
P = {A → V=E
E → E+T | E-T | T
T → T*F | T/F | F
F → (E) | V
V → a | b | c | d | e | f | g}
Quais das assertivas apresentadas estão corretas?
a. apenas as assertivas I e II.
b. apenas as assertivas I e III.
c. apenas as assertivas II e III.
d. apenas as assertivas II e IV.
e. apenas as assertivas III e IV.
A fase de otimização do código intermediário vem logo após a fase de geração desse código e tem por objetivo tornar o código intermediário mais apropriado para a produção de código objeto (código de máquina) eficiente, tanto em relação ao tamanho como ao tempo de execução. Uma das técnicas de otimização de código intermediário consiste em identificar segmentos sequencias do programa, chamados blocos básicos, e representá-los através de grafos dirigidos e submetê-los a um processo de otimização. Apresente o código de três endereços não otimizado da seguinte sequência de comandos, sobre a gramática livre de contexto G.
a = b * c + d;
b = g / (c + d) * e + f;
c = i * h - e + f;
G = ({A, E, T, V}, {a, b, c, d, e, f, g, h, i, =, +, -, *, /, (, )}, P, A)
P = {A → V=E
E → T+E | T-E | T*E | T/E | T
T → (E) | V
V → a | b | c | d | e | f | g | h | i}
oper | arg1 | arg2 | result | |
---|---|---|---|---|
(0) | + | c | d | T1 |
(1) | * | b | T1 | T2 |
(2) | = | T2 | a | |
(3) | + | c | d | T3 |
(4) | + | e | f | T4 |
(5) | * | T3 | T4 | T5 |
(6) | / | g | T5 | T6 |
(7) | = | T6 | b | |
(8) | + | e | f | T7 |
(9) | - | h | T7 | T8 |
(10) | * | i | T8 | T9 |
(11) | = | T9 | c |
Um grafo acíclico dirigido também é uma representação intermediária de um compilador, sendo utilizado para a identificação de subexpressões comuns existentes no mesmo bloco básico. Apresente o grafo acíclico dirigido para blocos básicos, do código de três endereços não otimizado elaborado na questão 06.
Com o grafo acíclico dirigido para blocos básicos produzido na questão 07, onde foram identificados as subexpressões comuns existentes no bloco básico considerado, apresente o código de três endereços otimizado, o qual futuramente será convertido em código objeto.
oper | arg1 | arg2 | result | |
---|---|---|---|---|
(0) | + | c | d | T1 |
(1) | * | b | T1 | T2 |
(2) | = | T2 | a | |
(3) | + | e | f | T3 |
(4) | * | T1 | T3 | T4 |
(5) | / | g | T4 | T5 |
(6) | = | T5 | b | |
(7) | - | h | T3 | T6 |
(8) | * | i | T6 | T7 |
(9) | = | T7 | c |