#include <stdio.h>
int sub(int a, int b);
int main(void) {
printf("%d\n", sub(3, 9)); return 0;
}
.text
.globl sub
.type sub, @function
sub: pushq %rbp
movq %rsp, %rbp
movl %edi, %eax
addl %esi, %eax
leave
ret
#include <stdio.h>
int sub(int n, int a[]);
int b[] = { 5, 1, 6, 8, 2, 7, 4, 3 };
int main(void) {
printf("%d\n", sub(8, b)); return 0;
}
.text
.globl sub
.type sub, @function
sub: pushq %rbp
movq %rsp, %rbp
movl 0(%rsi), %eax
.L1: dec %edi
cltq
jl .L2
movl 0(%rsi,%rdi,4), %edx
cmpl %edx, %eax
jge .L1
movl %edx, %eax
jmp .L1
.L2: leave
ret
Package samb3;
Helpers
digit = ['0'..'9'] ;
lcase = ['a'..'z'] ;
ucase = ['A'..'Z'] ;
letter = lcase | ucase ;
Tokens
iconst = digit+ ;
blank = (' '|13|10)+ ;
int = 'int' ;
if = 'if' ;
while = 'while' ;
semi = ';' ;
assign = '=' ;
add = '+' ;
sub = '-' ;
aster = '*' ;
slash = '/' ;
lt = '<' ;
gt = '>' ;
lbra = '{' ;
rbra = '}' ;
lpar = '(' ;
rpar = ')' ;
lsbr = '[' ;
rsbr = ']' ;
ident = letter (letter|digit)* ;
Ignored Tokens
blank;
Productions
prog = {main} int ident lpar dcls rpar stat
;
dcls = {lst} dcls semi dcl
| {one} dcl
;
dcl = {idcl} int ident
| {adcl} int ident lsbr rsbr
;
stlist = {stat} stlist stat
| {empty}
;
stat = {idcl} int ident semi
| {assign} ident assign expr semi
| {aassign} ident lsbr [idx]:expr rsbr assign expr semi
| {if} if lpar expr rpar stat
| {while} while lpar expr rpar stat
| {block} lbra stlist rbra
;
expr = {gt} [left]:nexp gt [right]:nexp
| {lt} [left]:nexp lt [right]:nexp
| {one} nexp
;
nexp = {add} nexp add term
| {sub} nexp sub term
| {one} term
;
term = {mul} term aster fact
| {div} term slash fact
| {one} fact
;
fact = {iconst} iconst
| {ident} ident
| {aref} ident lsbr expr rsbr
| {one} lpar expr rpar
;
package samb3;
import samb3.parser.*;
import samb3.lexer.*;
import samb3.node.*;
import java.io.*;
import java.util.*;
public class SamB3 {
public static void main(String[] args) throws Exception {
Parser p = new Parser(new Lexer(new PushbackReader(
new InputStreamReader(new FileInputStream(args[0]), "JISAutoDetect"),
1024)));
Start tree = p.parse();
Symtab st = new Symtab();
HashMap<Node,Integer> vtbl = new HashMap<Node,Integer>();
TypeChecker tck = new TypeChecker(st, vtbl); tree.apply(tck); st.show();
if(Log.getError() > 0) { return; }
Generator gen = new Generator(st, vtbl); tree.apply(gen);
}
}
class Log {
public static int err = 0;
public static void pError(String s) { System.out.println(s); ++err; }
public static int getError() { return err; }
}
class Symtab {
public static final int ITYPE = 1, ATYPE = 2, UNDEF = -1;
List<Ent> tbl = new ArrayList<Ent>();
Stack<Integer> stk = new Stack<Integer>();
int mark;
private boolean duplCheck(String n) {
for(int i = mark; i < tbl.size(); ++i) {
Ent e = tbl.get(i);
if(e.alive && e.name.equals(n)) { return true; }
}
return false;
}
public Ent addDef(String n, int t) {
if(duplCheck(n)) {
Log.pError("dublicate: "+n); return new Ent(n, UNDEF, 0);
}
Ent e = new Ent(n, t, tbl.size()); tbl.add(e); return e;
}
public void enterScope() { stk.push(mark); mark = tbl.size(); }
public void exitScope() {
for(int i = mark; i < tbl.size(); ++i) { tbl.get(i).alive = false; }
mark = stk.pop();
}
public Ent lookup(String n) {
for(int i = tbl.size()-1; i >= 0; --i) {
Ent e = tbl.get(i);
if(e.alive && e.name.equals(n)) { return e; }
}
return new Ent(n, UNDEF, 0);
}
public int getGsize() { return tbl.size(); }
public void show() { for(Ent e: tbl) { System.out.println(" " + e); } }
public static class Ent {
public String name;
public boolean alive = true;
public int type, pos = 0;
public Ent(String n, int t, int p) { name = n; type = t; pos = p; }
public String toString() {
return String.format("%s%s[%d %d]", name, alive?"_":"!", type, pos);
}
}
}
package samb3;
import samb3.analysis.*;
import samb3.node.*;
import java.io.*;
import java.util.*;
class TypeChecker extends DepthFirstAdapter {
Symtab st;
HashMap vtbl;
public TypeChecker(Symtab tb, HashMap vt) { st = tb; vtbl = vt; }
private void ckv(Node n, int t, int l, String s) {
if(getOut(n) instanceof Integer && (Integer)getOut(n) == t) { return; }
Log.pError(l+": "+s);
}
private int cki(String i, int t, int l) {
Symtab.Ent e = st.lookup(i);
if(e.type != t) { Log.pError(l+": identyfier is not of expexted type: "+i); }
return e.pos;
}
@Override
public void inAMainProg(AMainProg node) {
st.addDef("$dummy$", Symtab.ITYPE);
st.addDef(node.getIdent().getText(), Symtab.ITYPE);
}
@Override
public void outAIdclDcl(AIdclDcl node) {
Symtab.Ent e = st.addDef(node.getIdent().getText(), Symtab.ITYPE);
vtbl.put(node, e.pos);
}
@Override
public void outAAdclDcl(AAdclDcl node) {
Symtab.Ent e = st.addDef(node.getIdent().getText(), Symtab.ATYPE);
vtbl.put(node, e.pos);
}
@Override
public void outAIdclStat(AIdclStat node) {
st.addDef(node.getIdent().getText(), Symtab.ITYPE);
}
@Override
public void outAAssignStat(AAssignStat node) {
int p = cki(node.getIdent().getText(), Symtab.ITYPE, node.getIdent().getLine());
ckv(node.getExpr(), Symtab.ITYPE, node.getAssign().getLine(), "non-int val");
vtbl.put(node, p);
}
@Override
public void outAAassignStat(AAassignStat node) {
int p = cki(node.getIdent().getText(), Symtab.ATYPE, node.getIdent().getLine());
ckv(node.getIdx(), Symtab.ITYPE, node.getLsbr().getLine(), "non-int index");
ckv(node.getExpr(), Symtab.ITYPE, node.getAssign().getLine(), "non-int val");
vtbl.put(node, p);
}
@Override
public void outAIfStat(AIfStat node) {
ckv(node.getExpr(), Symtab.ITYPE, node.getLpar().getLine(), "non-int cond");
}
@Override
public void outAWhileStat(AWhileStat node) {
ckv(node.getExpr(), Symtab.ITYPE, node.getLpar().getLine(), "non-int cond");
}
@Override
public void inABlockStat(ABlockStat node) { st.enterScope(); }
@Override
public void outABlockStat(ABlockStat node) { st.exitScope(); }
@Override
public void outAGtExpr(AGtExpr node) {
ckv(node.getLeft(), Symtab.ITYPE, node.getGt().getLine(), "non-int val");
ckv(node.getRight(), Symtab.ITYPE, node.getGt().getLine(), "non-int val");
setOut(node, new Integer(Symtab.ITYPE));
}
@Override
public void outALtExpr(ALtExpr node) {
ckv(node.getLeft(), Symtab.ITYPE, node.getLt().getLine(), "non-int val");
ckv(node.getRight(), Symtab.ITYPE, node.getLt().getLine(), "non-int val");
setOut(node, new Integer(Symtab.ITYPE));
}
@Override
public void outAOneExpr(AOneExpr node) { setOut(node, getOut(node.getNexp())); }
@Override
public void outAAddNexp(AAddNexp node) {
ckv(node.getNexp(), Symtab.ITYPE, node.getAdd().getLine(), "non-int val");
ckv(node.getTerm(), Symtab.ITYPE, node.getAdd().getLine(), "non-int val");
setOut(node, new Integer(Symtab.ITYPE));
}
@Override
public void outASubNexp(ASubNexp node) {
ckv(node.getNexp(), Symtab.ITYPE, node.getSub().getLine(), "non-int val");
ckv(node.getTerm(), Symtab.ITYPE, node.getSub().getLine(), "non-int val");
setOut(node, new Integer(Symtab.ITYPE));
}
@Override
public void outAOneNexp(AOneNexp node) { setOut(node, getOut(node.getTerm())); }
@Override
public void outAMulTerm(AMulTerm node) {
ckv(node.getTerm(), Symtab.ITYPE, node.getAster().getLine(), "non-int val");
ckv(node.getFact(), Symtab.ITYPE, node.getAster().getLine(), "non-int val");
setOut(node, new Integer(Symtab.ITYPE));
}
@Override
public void outADivTerm(ADivTerm node) {
ckv(node.getTerm(), Symtab.ITYPE, node.getSlash().getLine(), "non-int val");
ckv(node.getFact(), Symtab.ITYPE, node.getSlash().getLine(), "non-int val");
setOut(node, new Integer(Symtab.ITYPE));
}
@Override
public void outAOneTerm(AOneTerm node) { setOut(node, getOut(node.getFact())); }
@Override
public void outAIconstFact(AIconstFact node) {
setOut(node, new Integer(Symtab.ITYPE));
}
@Override
public void outAIdentFact(AIdentFact node) {
Symtab.Ent e = st.lookup(node.getIdent().getText());
setOut(node, new Integer(e.type)); vtbl.put(node, e.pos);
}
@Override
public void outAArefFact(AArefFact node) {
int p = cki(node.getIdent().getText(), Symtab.ATYPE, node.getIdent().getLine());
ckv(node.getExpr(), Symtab.ITYPE, node.getLsbr().getLine(), "non-int index");
setOut(node, new Integer(Symtab.ITYPE)); vtbl.put(node, p);
}
@Override
public void outAOneFact(AOneFact node) { setOut(node, getOut(node.getExpr())); }
}
package samb3;
import samb3.analysis.*;
import samb3.node.*;
import java.io.*;
import java.util.*;
class Generator extends DepthFirstAdapter {
HashMap<Node,Integer> pos;
Symtab st;
PrintStream pr;
static String preg[] = {"%rdi", "%rsi", "%rdx", "%rcx", "%r8", "%r9"};
int pcnt = 0, lcnt = 0;
public Generator(Symtab s, HashMap<Node,Integer> p) throws Exception {
st = s; pos = p; pr = new PrintStream(new File("asm.s"));
}
@Override
public void inAMainProg(AMainProg node) {
String name = node.getIdent().getText();
pr.printf(" .text\n");
pr.printf(" .globl %s\n", name);
pr.printf(" .type %s, @function\n", name);
pr.printf("%s: pushq %%rbp\n", name);
pr.printf(" movq %%rsp, %%rbp\n");
pr.printf(" subq $.STSIZE, %%rsp\n");
}
@Override
public void outAMainProg(AMainProg node) {
pr.printf(" movl -8(%%rbp), %%eax\n");
pr.printf(" addq $.STSIZE, %%rsp\n");
pr.printf(" leave\n");
pr.printf(" ret\n");
pr.printf(".STSIZE = %d\n", st.getGsize()*8);
}
@Override
public void outAIdclDcl(AIdclDcl node) {
pr.printf(" movq %s, -%d(%%rbp)\n", preg[pcnt++], pos.get(node)*8);
}
@Override
public void outAAdclDcl(AAdclDcl node) {
pr.printf(" movq %s, -%d(%%rbp)\n", preg[pcnt++], pos.get(node)*8);
}
@Override
public void outAAssignStat(AAssignStat node) {
pr.printf(" movl -%s(%%rbp), %%eax\n", getOut(node.getExpr()));
pr.printf(" movl %%eax, -%d(%%rbp)\n", pos.get(node)*8);
}
@Override
public void outAAassignStat(AAassignStat node) {
pr.printf(" movq -%d(%%rbp), %%rcx\n", pos.get(node)*8);
pr.printf(" movl -%s(%%rbp), %%edx\n", getOut(node.getIdx()));
pr.printf(" cltq\n");
pr.printf(" movl -%s(%%rbp), %%eax\n", getOut(node.getExpr()));
pr.printf(" movl %%eax, 0(%%rcx,%%rdx,4)\n");
}
@Override
public void caseAIfStat(AIfStat node) {
int lbl = lcnt; lcnt += 1;
node.getExpr().apply(this);
pr.printf(" movl -%s(%%rbp), %%eax\n", getOut(node.getExpr()));
pr.printf(" testl %%eax,%%eax\n");
pr.printf(" je .L%d\n", lbl);
node.getStat().apply(this);
pr.printf(".L%d:\n", lbl);
}
@Override
public void caseAWhileStat(AWhileStat node) {
int lbl = lcnt; lcnt += 2;
pr.printf(".L%d:\n", lbl);
node.getExpr().apply(this);
pr.printf(" movl -%s(%%rbp), %%eax\n", getOut(node.getExpr()));
pr.printf(" testl %%eax,%%eax\n");
pr.printf(" je .L%d\n", lbl+1);
node.getStat().apply(this);
pr.printf(" jmp .L%d\n", lbl);
pr.printf(".L%d:\n", lbl+1);
}
@Override
public void outAGtExpr(AGtExpr node) {
pr.printf(" movl -%s(%%rbp), %%eax\n", getOut(node.getRight()));
pr.printf(" cmpl -%s(%%rbp), %%eax\n", getOut(node.getLeft()));
pr.printf(" jg .L%d\n", lcnt);
pr.printf(" mov $1, %%eax\n");
pr.printf(" jmp .L%d\n", lcnt+1);
pr.printf(".L%d: movl $0, %%eax\n", lcnt++);
Symtab.Ent f = st.addDef(".t" + pcnt++, Symtab.ITYPE);
pr.printf(".L%d: movl %%eax, -%d(%%rbp)\n", lcnt++, f.pos*8);
setOut(node, new Integer(f.pos*8));
}
@Override
public void outALtExpr(ALtExpr node) {
pr.printf(" movl -%s(%%rbp), %%eax\n", getOut(node.getRight()));
pr.printf(" cmpl -%s(%%rbp), %%eax\n", getOut(node.getLeft()));
pr.printf(" jl .L%d\n", lcnt);
pr.printf(" mov $1, %%eax\n");
pr.printf(" jmp .L%d\n", lcnt+1);
pr.printf(".L%d: movl $0, %%eax\n", lcnt++);
Symtab.Ent f = st.addDef(".t" + pcnt++, Symtab.ITYPE);
pr.printf(".L%d: movl %%eax, -%d(%%rbp)\n", lcnt++, f.pos*8);
setOut(node, new Integer(f.pos*8));
}
@Override
public void outAOneExpr(AOneExpr node) { setOut(node, getOut(node.getNexp())); }
@Override
public void outAAddNexp(AAddNexp node) {
pr.printf(" movl -%s(%%rbp), %%eax\n", getOut(node.getNexp()));
pr.printf(" addl -%s(%%rbp), %%eax\n", getOut(node.getTerm()));
Symtab.Ent f = st.addDef(".t" + pcnt++, Symtab.ITYPE);
pr.printf(" movl %%eax, -%d(%%rbp)\n", f.pos*8);
setOut(node, new Integer(f.pos*8));
}
@Override
public void outASubNexp(ASubNexp node) {
pr.printf(" movl -%s(%%rbp), %%eax\n", getOut(node.getNexp()));
pr.printf(" subl -%s(%%rbp), %%eax\n", getOut(node.getTerm()));
Symtab.Ent f = st.addDef(".t" + pcnt++, Symtab.ITYPE);
pr.printf(" movl %%eax, -%d(%%rbp)\n", f.pos*8);
setOut(node, new Integer(f.pos*8));
}
@Override
public void outAOneNexp(AOneNexp node) { setOut(node, getOut(node.getTerm())); }
@Override
public void outAMulTerm(AMulTerm node) {
pr.printf(" movl -%s(%%rbp), %%eax\n", getOut(node.getTerm()));
pr.printf(" imull -%s(%%rbp), %%eax\n", getOut(node.getFact()));
Symtab.Ent f = st.addDef(".t" + pcnt++, Symtab.ITYPE);
pr.printf(" movl %%eax, -%d(%%rbp)\n", f.pos*8);
setOut(node, new Integer(f.pos*8));
}
@Override
public void outADivTerm(ADivTerm node) {
pr.printf(" movl -%s(%%rbp), %%eax\n", getOut(node.getFact()));
pr.printf(" cltd\n");
pr.printf(" idivl -%s(%%rbp)\n", getOut(node.getTerm()));
Symtab.Ent f = st.addDef(".t" + pcnt++, Symtab.ITYPE);
pr.printf(" movl %%eax, -%d(%%rbp)\n", f.pos*8);
setOut(node, new Integer(f.pos*8));
}
@Override
public void outAOneTerm(AOneTerm node) { setOut(node, getOut(node.getFact())); }
@Override
public void outAIconstFact(AIconstFact node) {
Symtab.Ent e = st.addDef(".t" + pcnt++, Symtab.ITYPE);
pr.printf(" movl $%s, %%eax\n", node.getIconst().getText());
pr.printf(" movl %%eax, -%d(%%rbp)\n", e.pos*8);
setOut(node, new Integer(e.pos*8));
}
@Override
public void outAIdentFact(AIdentFact node) {
setOut(node, new Integer(pos.get(node)*8));
}
@Override
public void outAArefFact(AArefFact node) {
pr.printf(" movq -%d(%%rbp), %%rdx\n", pos.get(node)*8);
pr.printf(" movl -%s(%%rbp), %%ecx\n", getOut(node.getExpr()));
pr.printf(" cltq\n");
pr.printf(" movl 0(%%rdx,%%rcx,4), %%eax\n");
Symtab.Ent f = st.addDef(".t" + pcnt++, Symtab.ITYPE);
pr.printf(" movl %%eax, -%d(%%rbp)\n", f.pos*8);
setOut(node, new Integer(f.pos*8));
}
@Override
public void outAOneFact(AOneFact node) { setOut(node, getOut(node.getExpr())); }
}
int sub(int n; int a[]) {
int remain; remain = 1;
while(remain) {
remain = 0; int i; i = 1;
while(i < n) {
if(a[i-1]>a[i]) { int z; z=a[i-1]; a[i-1]=a[i]; a[i]=z; remain=1; }
i = i + 1; } } }
#include <stdio.h>
int sub(int n, int a[]);
int main(void) {
int a[] = { 7, 1, 6, 3, 2, 4, 8 };
sub(7, a);
for(int i = 0; i < 7; ++i) { printf("%d\n", a[i]); }
}