mirror of https://github.com/aamine/cbc
* net/loveruby/cflat/compiler/CodeGenerator.java: remove simple delegators (to Assembler).
* net/loveruby/cflat/asm/Assembler.java: add _byte(long), etc. * net/loveruby/cflat/ir/IR.java: do not export typeTable, provide natural type instead. git-svn-id: file:///Users/aamine/c/gitwork/public/cbc/trunk@4159 1b9489fe-b721-0410-924e-b54b9192deb8
This commit is contained in:
parent
a5eb1024f9
commit
8e8ae12043
10
ChangeLog
10
ChangeLog
|
@ -1,3 +1,13 @@
|
|||
Mon Apr 27 00:24:24 2009 Minero Aoki <aamine@loveruby.net>
|
||||
|
||||
* net/loveruby/cflat/compiler/CodeGenerator.java: remove simple
|
||||
delegators (to Assembler).
|
||||
|
||||
* net/loveruby/cflat/asm/Assembler.java: add _byte(long), etc.
|
||||
|
||||
* net/loveruby/cflat/ir/IR.java: do not export typeTable, provide
|
||||
natural type instead.
|
||||
|
||||
Sun Apr 26 23:54:47 2009 Minero Aoki <aamine@loveruby.net>
|
||||
|
||||
* net/loveruby/cflat/compiler/IRGenerator.java: use
|
||||
|
|
|
@ -157,6 +157,22 @@ public class Assembler {
|
|||
directive("\t.size\t" + sym.name() + "," + size);
|
||||
}
|
||||
|
||||
public void _byte(long val) {
|
||||
directive(".byte\t" + new IntegerLiteral((byte)val).toSource());
|
||||
}
|
||||
|
||||
public void _value(long val) {
|
||||
directive(".value\t" + new IntegerLiteral((short)val).toSource());
|
||||
}
|
||||
|
||||
public void _long(long val) {
|
||||
directive(".long\t" + new IntegerLiteral((int)val).toSource());
|
||||
}
|
||||
|
||||
public void _quad(long val) {
|
||||
directive(".quad\t" + new IntegerLiteral(val).toSource());
|
||||
}
|
||||
|
||||
public void _byte(Literal val) {
|
||||
directive(".byte\t" + val.toSource());
|
||||
}
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
package net.loveruby.cflat.compiler;
|
||||
import net.loveruby.cflat.type.*;
|
||||
import net.loveruby.cflat.ast.*;
|
||||
import net.loveruby.cflat.ir.*;
|
||||
import net.loveruby.cflat.type.Type;
|
||||
import net.loveruby.cflat.ast.LocalScope;
|
||||
import net.loveruby.cflat.ast.ConstantEntry;
|
||||
import net.loveruby.cflat.ast.Entity;
|
||||
import net.loveruby.cflat.ast.Variable;
|
||||
import net.loveruby.cflat.ast.DefinedVariable;
|
||||
import net.loveruby.cflat.ast.Function;
|
||||
import net.loveruby.cflat.ast.DefinedFunction;
|
||||
import net.loveruby.cflat.ast.Parameter;
|
||||
import net.loveruby.cflat.asm.*;
|
||||
import java.util.*;
|
||||
|
||||
|
@ -11,7 +18,7 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
protected ErrorHandler errorHandler;
|
||||
protected LinkedList<Assembler> asStack;
|
||||
protected Assembler as;
|
||||
protected TypeTable typeTable;
|
||||
protected Type naturalType;
|
||||
protected Label epilogue;
|
||||
|
||||
public CodeGenerator(CodeGeneratorOptions options,
|
||||
|
@ -25,7 +32,7 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
/** Compiles IR and generates assembly code. */
|
||||
// #@@range/generate{
|
||||
public String generate(IR ir) {
|
||||
this.typeTable = ir.typeTable();
|
||||
this.naturalType = ir.naturalType();
|
||||
pushAssembler();
|
||||
SymbolTable constSymbols = new SymbolTable(Assembler.CONST_SYMBOL_BASE);
|
||||
for (ConstantEntry ent : ir.constantTable().entries()) {
|
||||
|
@ -44,7 +51,7 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
|
||||
// #@@range/pushAssembler{
|
||||
protected void pushAssembler() {
|
||||
this.as = newAssembler();
|
||||
this.as = new Assembler(naturalType);
|
||||
asStack.add(this.as);
|
||||
}
|
||||
// #@@}
|
||||
|
@ -57,32 +64,26 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
}
|
||||
// #@@}
|
||||
|
||||
// #@@range/newAssembler{
|
||||
protected Assembler newAssembler() {
|
||||
return new Assembler(typeTable.unsignedLong());
|
||||
}
|
||||
// #@@}
|
||||
|
||||
// #@@range/compileIR{
|
||||
public void compileIR(IR ir) {
|
||||
_file(ir.fileName());
|
||||
as._file(ir.fileName());
|
||||
// .data
|
||||
List<DefinedVariable> gvars = ir.definedGlobalVariables();
|
||||
if (!gvars.isEmpty()) {
|
||||
_data();
|
||||
as._data();
|
||||
for (DefinedVariable gvar : gvars) {
|
||||
dataEntry(gvar);
|
||||
}
|
||||
}
|
||||
if (!ir.constantTable().isEmpty()) {
|
||||
_section(".rodata");
|
||||
as._section(".rodata");
|
||||
for (ConstantEntry ent : ir.constantTable()) {
|
||||
compileStringLiteral(ent);
|
||||
}
|
||||
}
|
||||
// .text
|
||||
if (ir.functionDefined()) {
|
||||
_text();
|
||||
as._text();
|
||||
for (DefinedFunction func : ir.definedFunctions()) {
|
||||
compileFunction(func);
|
||||
}
|
||||
|
@ -169,12 +170,12 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
protected void dataEntry(DefinedVariable ent) {
|
||||
Symbol sym = globalSymbol(ent.symbolString());
|
||||
if (!ent.isPrivate()) {
|
||||
_globl(sym);
|
||||
as._globl(sym);
|
||||
}
|
||||
_align(ent.alignment());
|
||||
_type(sym, "@object");
|
||||
_size(sym, ent.allocSize());
|
||||
label(sym);
|
||||
as._align(ent.alignment());
|
||||
as._type(sym, "@object");
|
||||
as._size(sym, ent.allocSize());
|
||||
as.label(sym);
|
||||
compileImmediate(ent.type(), ent.ir());
|
||||
}
|
||||
// #@@}
|
||||
|
@ -185,10 +186,10 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
if (node instanceof IntValue) {
|
||||
IntValue expr = (IntValue)node;
|
||||
switch ((int)type.allocSize()) {
|
||||
case 1: _byte(expr.value()); break;
|
||||
case 2: _value(expr.value()); break;
|
||||
case 4: _long(expr.value()); break;
|
||||
case 8: _quad(expr.value()); break;
|
||||
case 1: as._byte(expr.value()); break;
|
||||
case 2: as._value(expr.value()); break;
|
||||
case 4: as._long(expr.value()); break;
|
||||
case 8: as._quad(expr.value()); break;
|
||||
default:
|
||||
throw new Error("entry size must be 1,2,4,8");
|
||||
}
|
||||
|
@ -196,8 +197,8 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
else if (node instanceof StringValue) {
|
||||
StringValue expr = (StringValue)node;
|
||||
switch ((int)type.allocSize()) {
|
||||
case 4: _long(expr.symbol()); break;
|
||||
case 8: _quad(expr.symbol()); break;
|
||||
case 4: as._long(expr.symbol()); break;
|
||||
case 8: as._quad(expr.symbol()); break;
|
||||
default:
|
||||
throw new Error("pointer size must be 4,8");
|
||||
}
|
||||
|
@ -213,17 +214,17 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
protected void compileCommonSymbol(DefinedVariable var) {
|
||||
Symbol sym = globalSymbol(var.symbolString());
|
||||
if (var.isPrivate()) {
|
||||
_local(sym);
|
||||
as._local(sym);
|
||||
}
|
||||
_comm(sym, var.allocSize(), var.alignment());
|
||||
as._comm(sym, var.allocSize(), var.alignment());
|
||||
}
|
||||
// #@@}
|
||||
|
||||
/** Generates .rodata entry (constant strings) */
|
||||
// #@@range/compileStringLiteral{
|
||||
protected void compileStringLiteral(ConstantEntry ent) {
|
||||
label(ent.symbol());
|
||||
_string(ent.value());
|
||||
as.label(ent.symbol());
|
||||
as._string(ent.value());
|
||||
}
|
||||
// #@@}
|
||||
|
||||
|
@ -250,8 +251,8 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
new NamedSymbol("_GLOBAL_OFFSET_TABLE_");
|
||||
|
||||
protected void loadGOTBaseAddress(Register reg) {
|
||||
call(PICThunkSymbol(reg));
|
||||
add(imm(GOT), reg);
|
||||
as.call(PICThunkSymbol(reg));
|
||||
as.add(imm(GOT), reg);
|
||||
}
|
||||
|
||||
protected Register GOTBaseReg() {
|
||||
|
@ -299,17 +300,17 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
// #@@range/PICThunk{
|
||||
protected void PICThunk(Register reg) {
|
||||
Symbol sym = PICThunkSymbol(reg);
|
||||
_section(".text" + "." + sym.toSource(),
|
||||
as._section(".text" + "." + sym.toSource(),
|
||||
"\"" + PICThunkSectionFlags + "\"",
|
||||
SectionType_bits, // This section contains data
|
||||
sym.toSource(), // The name of section group
|
||||
Linkage_linkonce); // Only 1 copy should be generated
|
||||
_globl(sym);
|
||||
_hidden(sym);
|
||||
_type(sym, SymbolType_function);
|
||||
label(sym);
|
||||
mov(mem(sp()), reg); // fetch saved EIP to the GOT base register
|
||||
ret();
|
||||
as._globl(sym);
|
||||
as._hidden(sym);
|
||||
as._type(sym, SymbolType_function);
|
||||
as.label(sym);
|
||||
as.mov(mem(sp()), reg); // fetch saved EIP to the GOT base register
|
||||
as.ret();
|
||||
}
|
||||
// #@@}
|
||||
|
||||
|
@ -372,12 +373,12 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
|
||||
Symbol sym = globalSymbol(func.name());
|
||||
if (! func.isPrivate()) {
|
||||
_globl(sym);
|
||||
as._globl(sym);
|
||||
}
|
||||
_type(sym, "@function");
|
||||
label(sym);
|
||||
as._type(sym, "@function");
|
||||
as.label(sym);
|
||||
compileFunctionBody(func);
|
||||
_size(sym, ".-" + sym.toSource());
|
||||
as._size(sym, ".-" + sym.toSource());
|
||||
}
|
||||
// #@@}
|
||||
|
||||
|
@ -434,11 +435,11 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
return x.mem.compareTo(y.mem);
|
||||
}
|
||||
});
|
||||
comment("---- Stack Frame Layout -----------");
|
||||
as.comment("---- Stack Frame Layout -----------");
|
||||
for (MemInfo info : vars) {
|
||||
comment(info.mem.toString() + ": " + info.name);
|
||||
as.comment(info.mem.toString() + ": " + info.name);
|
||||
}
|
||||
comment("-----------------------------------");
|
||||
as.comment("-----------------------------------");
|
||||
}
|
||||
|
||||
class MemInfo {
|
||||
|
@ -458,7 +459,7 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
for (Stmt s : func.ir()) {
|
||||
compileStmt(s);
|
||||
}
|
||||
label(epilogue);
|
||||
as.label(epilogue);
|
||||
return options.optimizer().optimize(popAssembler().assemblies());
|
||||
}
|
||||
// #@@}
|
||||
|
@ -507,8 +508,8 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
protected void prologue(DefinedFunction func,
|
||||
List<Register> saveRegs,
|
||||
long frameSize) {
|
||||
truePush(bp());
|
||||
mov(sp(), bp());
|
||||
as.push(bp());
|
||||
as.mov(sp(), bp());
|
||||
saveRegisters(saveRegs);
|
||||
extendStack(frameSize);
|
||||
}
|
||||
|
@ -519,16 +520,16 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
List<Register> savedRegs,
|
||||
long lvarBytes) {
|
||||
restoreRegisters(savedRegs);
|
||||
mov(bp(), sp());
|
||||
truePop(bp());
|
||||
ret();
|
||||
as.mov(bp(), sp());
|
||||
as.pop(bp());
|
||||
as.ret();
|
||||
}
|
||||
// #@@}
|
||||
|
||||
// #@@range/saveRegisters{
|
||||
protected void saveRegisters(List<Register> saveRegs) {
|
||||
for (Register reg : saveRegs) {
|
||||
push(reg);
|
||||
virtualPush(reg);
|
||||
}
|
||||
}
|
||||
// #@@}
|
||||
|
@ -537,7 +538,7 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
protected void restoreRegisters(List<Register> savedRegs) {
|
||||
ListIterator<Register> regs = savedRegs.listIterator(savedRegs.size());
|
||||
while (regs.hasPrevious()) {
|
||||
pop(regs.previous());
|
||||
virtualPop(regs.previous());
|
||||
}
|
||||
}
|
||||
// #@@}
|
||||
|
@ -615,10 +616,10 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
protected void extendStack(long len) {
|
||||
if (len > 0) {
|
||||
if (stackGrowsLower) {
|
||||
sub(imm(len), sp());
|
||||
as.sub(imm(len), sp());
|
||||
}
|
||||
else {
|
||||
add(imm(len), sp());
|
||||
as.add(imm(len), sp());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -628,10 +629,10 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
protected void rewindStack(long len) {
|
||||
if (len > 0) {
|
||||
if (stackGrowsLower) {
|
||||
add(imm(len), sp());
|
||||
as.add(imm(len), sp());
|
||||
}
|
||||
else {
|
||||
sub(imm(len), sp());
|
||||
as.sub(imm(len), sp());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -664,20 +665,20 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
}
|
||||
// #@@}
|
||||
|
||||
// #@@range/push{
|
||||
protected void push(Register reg) {
|
||||
// #@@range/virtualPush{
|
||||
protected void virtualPush(Register reg) {
|
||||
extendVirtualStack(stackWordSize);
|
||||
as.relocatableMov(reg, stackTop());
|
||||
if (options.isVerboseAsm()) {
|
||||
comment("push " + reg.name() + " -> " + stackTop());
|
||||
as.comment("push " + reg.name() + " -> " + stackTop());
|
||||
}
|
||||
}
|
||||
// #@@}
|
||||
|
||||
// #@@range/pop{
|
||||
protected void pop(Register reg) {
|
||||
// #@@range/virtualPop{
|
||||
protected void virtualPop(Register reg) {
|
||||
if (options.isVerboseAsm()) {
|
||||
comment("pop " + reg.name() + " <- " + stackTop());
|
||||
as.comment("pop " + reg.name() + " <- " + stackTop());
|
||||
}
|
||||
as.relocatableMov(stackTop(), reg);
|
||||
rewindVirtualStack(stackWordSize);
|
||||
|
@ -716,17 +717,17 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
ListIterator<Expr> args = node.finalArg();
|
||||
while (args.hasPrevious()) {
|
||||
compile(args.previous());
|
||||
truePush(reg("ax"));
|
||||
as.push(reg("ax"));
|
||||
}
|
||||
// call
|
||||
if (node.isStaticCall()) {
|
||||
// call via function name
|
||||
call(node.function().callingSymbol());
|
||||
as.call(node.function().callingSymbol());
|
||||
}
|
||||
else {
|
||||
// call via pointer
|
||||
compile(node.expr());
|
||||
callAbsolute(reg("ax"));
|
||||
as.callAbsolute(reg("ax"));
|
||||
}
|
||||
// rewind stack
|
||||
// >4 bytes arguments are not supported.
|
||||
|
@ -740,7 +741,7 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
if (node.expr() != null) {
|
||||
compile(node.expr());
|
||||
}
|
||||
jmp(epilogue);
|
||||
as.jmp(epilogue);
|
||||
return null;
|
||||
}
|
||||
// #@@}
|
||||
|
@ -753,10 +754,10 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
protected void compileStmt(Stmt stmt) {
|
||||
if (options.isVerboseAsm()) {
|
||||
if (stmt.location() == null) {
|
||||
comment("(null)");
|
||||
as.comment("(null)");
|
||||
}
|
||||
else {
|
||||
comment(stmt.location().numberedLine());
|
||||
as.comment(stmt.location().numberedLine());
|
||||
}
|
||||
}
|
||||
stmt.accept(this);
|
||||
|
@ -770,7 +771,7 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
|
||||
// #@@range/testCond{
|
||||
private void testCond(Type t, Register reg) {
|
||||
test(t, reg.forType(t), reg.forType(t));
|
||||
as.test(t, reg.forType(t), reg.forType(t));
|
||||
}
|
||||
// #@@}
|
||||
|
||||
|
@ -778,8 +779,8 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
public Void visit(BranchIf node) {
|
||||
compile(node.cond());
|
||||
testCond(node.cond().type(), reg("ax"));
|
||||
jnz(node.thenLabel());
|
||||
jmp(node.elseLabel());
|
||||
as.jnz(node.thenLabel());
|
||||
as.jmp(node.elseLabel());
|
||||
return null;
|
||||
}
|
||||
// #@@}
|
||||
|
@ -787,27 +788,27 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
// #@@range/compile_Switch{
|
||||
public Void visit(Switch node) {
|
||||
compile(node.cond());
|
||||
Type t = typeTable.signedInt();
|
||||
Type t = node.cond().type();
|
||||
for (Case c : node.cases()) {
|
||||
mov(imm(c.value), reg("cx"));
|
||||
cmp(t, reg("cx", t), reg("ax", t));
|
||||
je(c.label);
|
||||
as.mov(imm(c.value), reg("cx"));
|
||||
as.cmp(t, reg("cx", t), reg("ax", t));
|
||||
as.je(c.label);
|
||||
}
|
||||
jmp(node.defaultLabel());
|
||||
as.jmp(node.defaultLabel());
|
||||
return null;
|
||||
}
|
||||
// #@@}
|
||||
|
||||
// #@@range/compile_LabelStmt{
|
||||
public Void visit(LabelStmt node) {
|
||||
label(node.label());
|
||||
as.label(node.label());
|
||||
return null;
|
||||
}
|
||||
// #@@}
|
||||
|
||||
// #@@range/compile_Jump{
|
||||
public Void visit(Jump node) {
|
||||
jmp(node.label());
|
||||
as.jmp(node.label());
|
||||
return null;
|
||||
}
|
||||
// #@@}
|
||||
|
@ -819,13 +820,13 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
// #@@range/compile{
|
||||
protected void compile(Expr n) {
|
||||
if (options.isVerboseAsm()) {
|
||||
comment(n.getClass().getSimpleName() + " {");
|
||||
as.comment(n.getClass().getSimpleName() + " {");
|
||||
as.indentComment();
|
||||
}
|
||||
n.accept(this);
|
||||
if (options.isVerboseAsm()) {
|
||||
as.unindentComment();
|
||||
comment("}");
|
||||
as.comment("}");
|
||||
}
|
||||
}
|
||||
// #@@}
|
||||
|
@ -844,9 +845,9 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
}
|
||||
else {
|
||||
compile(node.right());
|
||||
push(reg("ax"));
|
||||
virtualPush(reg("ax"));
|
||||
compile(node.left());
|
||||
pop(reg("cx"));
|
||||
virtualPop(reg("cx"));
|
||||
right = reg("cx", node.type());
|
||||
}
|
||||
compileBinaryOp(node.op(), node.type(), right);
|
||||
|
@ -886,81 +887,81 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
// #@@range/compileBinaryOp_arithops{
|
||||
switch (op) {
|
||||
case ADD:
|
||||
add(t, right, reg("ax", t));
|
||||
as.add(t, right, reg("ax", t));
|
||||
break;
|
||||
case SUB:
|
||||
sub(t, right, reg("ax", t));
|
||||
as.sub(t, right, reg("ax", t));
|
||||
break;
|
||||
// #@@range/compileBinaryOp_begin}
|
||||
case MUL:
|
||||
imul(t, right, reg("ax", t));
|
||||
as.imul(t, right, reg("ax", t));
|
||||
break;
|
||||
case DIV:
|
||||
case MOD:
|
||||
if (t.isSigned()) {
|
||||
cltd();
|
||||
idiv(t, reg("cx", t));
|
||||
as.cltd();
|
||||
as.idiv(t, reg("cx", t));
|
||||
}
|
||||
else {
|
||||
mov(imm(0), reg("dx"));
|
||||
div(t, reg("cx", t));
|
||||
as.mov(imm(0), reg("dx"));
|
||||
as.div(t, reg("cx", t));
|
||||
}
|
||||
if (op == Op.MOD) {
|
||||
mov(reg("dx"), reg("ax"));
|
||||
as.mov(reg("dx"), reg("ax"));
|
||||
}
|
||||
break;
|
||||
// #@@}
|
||||
// #@@range/compileBinaryOp_bitops{
|
||||
case BIT_AND:
|
||||
and(t, right, reg("ax", t));
|
||||
as.and(t, right, reg("ax", t));
|
||||
break;
|
||||
case BIT_OR:
|
||||
or(t, right, reg("ax", t));
|
||||
as.or(t, right, reg("ax", t));
|
||||
break;
|
||||
case BIT_XOR:
|
||||
xor(t, right, reg("ax", t));
|
||||
as.xor(t, right, reg("ax", t));
|
||||
break;
|
||||
case RSHIFT:
|
||||
if (t.isSigned()) {
|
||||
sar(t, cl(), reg("ax", t));
|
||||
as.sar(t, cl(), reg("ax", t));
|
||||
}
|
||||
else {
|
||||
shr(t, cl(), reg("ax", t));
|
||||
as.shr(t, cl(), reg("ax", t));
|
||||
}
|
||||
break;
|
||||
case LSHIFT:
|
||||
sal(t, cl(), reg("ax", t));
|
||||
as.sal(t, cl(), reg("ax", t));
|
||||
break;
|
||||
// #@@}
|
||||
// #@@range/compileBinaryOp_cmpops{
|
||||
default:
|
||||
// Comparison operators
|
||||
cmp(t, right, reg("ax", t));
|
||||
as.cmp(t, right, reg("ax", t));
|
||||
if (!t.isPointer() && t.isSigned()) {
|
||||
switch (op) {
|
||||
case EQ: sete (al()); break;
|
||||
case NEQ: setne(al()); break;
|
||||
case GT: setg (al()); break;
|
||||
case GTEQ: setge(al()); break;
|
||||
case LT: setl (al()); break;
|
||||
case LTEQ: setle(al()); break;
|
||||
case EQ: as.sete (al()); break;
|
||||
case NEQ: as.setne(al()); break;
|
||||
case GT: as.setg (al()); break;
|
||||
case GTEQ: as.setge(al()); break;
|
||||
case LT: as.setl (al()); break;
|
||||
case LTEQ: as.setle(al()); break;
|
||||
default:
|
||||
throw new Error("unknown binary operator: " + op);
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch (op) {
|
||||
case EQ: sete (al()); break;
|
||||
case NEQ: setne(al()); break;
|
||||
case GT: seta (al()); break;
|
||||
case GTEQ: setae(al()); break;
|
||||
case LT: setb (al()); break;
|
||||
case LTEQ: setbe(al()); break;
|
||||
case EQ: as.sete (al()); break;
|
||||
case NEQ: as.setne(al()); break;
|
||||
case GT: as.seta (al()); break;
|
||||
case GTEQ: as.setae(al()); break;
|
||||
case LT: as.setb (al()); break;
|
||||
case LTEQ: as.setbe(al()); break;
|
||||
default:
|
||||
throw new Error("unknown binary operator: " + op);
|
||||
}
|
||||
}
|
||||
movzb(t, al(), reg("ax", t));
|
||||
as.movzb(t, al(), reg("ax", t));
|
||||
}
|
||||
// #@@}
|
||||
// #@@range/compileBinaryOp_end{
|
||||
|
@ -972,25 +973,25 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
compile(node.expr());
|
||||
switch (node.op()) {
|
||||
case UMINUS:
|
||||
neg(node.expr().type(), reg("ax", node.expr().type()));
|
||||
as.neg(node.expr().type(), reg("ax", node.expr().type()));
|
||||
break;
|
||||
case BIT_NOT:
|
||||
not(node.expr().type(), reg("ax", node.expr().type()));
|
||||
as.not(node.expr().type(), reg("ax", node.expr().type()));
|
||||
break;
|
||||
case NOT:
|
||||
testCond(node.expr().type(), reg("ax"));
|
||||
sete(al());
|
||||
movzbl(al(), reg("ax"));
|
||||
as.sete(al());
|
||||
as.movzbl(al(), reg("ax"));
|
||||
break;
|
||||
case CAST:
|
||||
Type src = node.expr().type();
|
||||
Type dest = node.type();
|
||||
if (src.isSigned()) {
|
||||
movsx(src, dest,
|
||||
as.movsx(src, dest,
|
||||
reg("ax").forType(src), reg("ax").forType(dest));
|
||||
}
|
||||
else {
|
||||
movzx(src, dest,
|
||||
as.movzx(src, dest,
|
||||
reg("ax").forType(src), reg("ax").forType(dest));
|
||||
}
|
||||
break;
|
||||
|
@ -1049,16 +1050,16 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
}
|
||||
else if (node.rhs().isConstant()) {
|
||||
compileLHS(node.lhs());
|
||||
mov(reg("ax"), reg("cx"));
|
||||
as.mov(reg("ax"), reg("cx"));
|
||||
loadConstant(node.rhs(), reg("ax"));
|
||||
save(node.lhs().type(), reg("ax"), mem(reg("cx")));
|
||||
}
|
||||
else {
|
||||
compile(node.rhs());
|
||||
push(reg("ax"));
|
||||
virtualPush(reg("ax"));
|
||||
compileLHS(node.lhs());
|
||||
mov(reg("ax"), reg("cx"));
|
||||
pop(reg("ax"));
|
||||
as.mov(reg("ax"), reg("cx"));
|
||||
virtualPop(reg("ax"));
|
||||
save(node.lhs().type(), reg("ax"), mem(reg("cx")));
|
||||
}
|
||||
return null;
|
||||
|
@ -1091,10 +1092,10 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
// #@@range/loadConstant{
|
||||
protected void loadConstant(Expr node, Register reg) {
|
||||
if (node.asmValue() != null) {
|
||||
mov(node.asmValue(), reg);
|
||||
as.mov(node.asmValue(), reg);
|
||||
}
|
||||
else if (node.memref() != null) {
|
||||
lea(node.memref(), reg);
|
||||
as.lea(node.memref(), reg);
|
||||
}
|
||||
else {
|
||||
throw new Error("must not happen: constant has no asm value");
|
||||
|
@ -1108,14 +1109,8 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
*/
|
||||
// #@@range/loadVariable{
|
||||
protected void loadVariable(Expr node, Register dest) {
|
||||
/*
|
||||
if (node.shouldEvaluatedToAddress()) {
|
||||
// "int[4] a; a" implies &a
|
||||
// "x = puts" implies &puts
|
||||
loadVariableAddress(node, dest);
|
||||
}
|
||||
else*/ if (node.memref() == null) {
|
||||
mov(node.address(), dest);
|
||||
if (node.memref() == null) {
|
||||
as.mov(node.address(), dest);
|
||||
load(node.type(), mem(dest), dest);
|
||||
}
|
||||
else {
|
||||
|
@ -1133,10 +1128,10 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
// #@@range/loadVariableAddress{
|
||||
protected void loadVariableAddress(Expr node, Register dest) {
|
||||
if (node.address() != null) {
|
||||
mov(node.address(), dest);
|
||||
as.mov(node.address(), dest);
|
||||
}
|
||||
else {
|
||||
lea(node.memref(), dest);
|
||||
as.lea(node.memref(), dest);
|
||||
}
|
||||
}
|
||||
// #@@}
|
||||
|
@ -1199,20 +1194,20 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
switch ((int)type.size()) {
|
||||
case 1:
|
||||
if (type.isSigned()) { // signed char
|
||||
movsbl(mem, reg);
|
||||
as.movsbl(mem, reg);
|
||||
} else { // unsigned char
|
||||
movzbl(mem, reg);
|
||||
as.movzbl(mem, reg);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (type.isSigned()) { // signed short
|
||||
movswl(mem, reg);
|
||||
as.movswl(mem, reg);
|
||||
} else { // unsigned short
|
||||
movzwl(mem, reg);
|
||||
as.movzwl(mem, reg);
|
||||
}
|
||||
break;
|
||||
default: // int, long, long_long
|
||||
mov(type, mem, reg.forType(type));
|
||||
as.mov(type, mem, reg.forType(type));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1220,90 +1215,7 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
|
||||
// #@@range/save{
|
||||
protected void save(Type type, Register reg, MemoryReference mem) {
|
||||
mov(type, reg.forType(type), mem);
|
||||
as.mov(type, reg.forType(type), mem);
|
||||
}
|
||||
// #@@}
|
||||
|
||||
// #@@range/dsl_directives{
|
||||
public void comment(String str) { as.comment(str); }
|
||||
public void _file(String name) { as._file(name); }
|
||||
public void _text() { as._text(); }
|
||||
public void _data() { as._data(); }
|
||||
public void _section(String name) { as._section(name); }
|
||||
// #@@}
|
||||
public void _section(String name, String flags, String type, String group, String linkage) { as._section(name, flags, type, group, linkage); }
|
||||
public void _globl(Symbol sym) { as._globl(sym); }
|
||||
public void _local(Symbol sym) { as._local(sym); }
|
||||
public void _hidden(Symbol sym) { as._hidden(sym); }
|
||||
public void _comm(Symbol sym, long sz, long a) { as._comm(sym, sz, a); }
|
||||
public void _align(long n) { as._align(n); }
|
||||
public void _type(Symbol sym, String type) { as._type(sym, type); }
|
||||
public void _size(Symbol sym, long size) { as._size(sym, size); }
|
||||
public void _size(Symbol sym, String size) { as._size(sym, size); }
|
||||
public void _byte(long n) { as._byte(new IntegerLiteral(n)); }
|
||||
public void _value(long n) { as._value(new IntegerLiteral(n)); }
|
||||
public void _long(long n) { as._long(new IntegerLiteral(n)); }
|
||||
public void _long(Symbol sym) { as._long(sym); }
|
||||
public void _quad(long n) { as._quad(new IntegerLiteral(n)); }
|
||||
public void _quad(Symbol sym) { as._quad(sym); }
|
||||
public void _string(String str) { as._string(str); }
|
||||
public void label(Symbol sym) { as.label(sym); }
|
||||
public void label(Label label) { as.label(label); }
|
||||
|
||||
public void jmp(Label label) { as.jmp(label); }
|
||||
public void jz(Label label) { as.jz(label); }
|
||||
public void jnz(Label label) { as.jnz(label); }
|
||||
public void je(Label label) { as.je(label); }
|
||||
public void jne(Label label) { as.jne(label); }
|
||||
public void cmp(Type t, AsmOperand a, Register b) { as.cmp(t, a, b); }
|
||||
public void sete(Register reg) { as.sete(reg); }
|
||||
public void setne(Register reg) { as.setne(reg); }
|
||||
public void seta(Register reg) { as.seta(reg); }
|
||||
public void setae(Register reg) { as.setae(reg); }
|
||||
public void setb(Register reg) { as.setb(reg); }
|
||||
public void setbe(Register reg) { as.setbe(reg); }
|
||||
public void setg(Register reg) { as.setg(reg); }
|
||||
public void setge(Register reg) { as.setge(reg); }
|
||||
public void setl(Register reg) { as.setl(reg); }
|
||||
public void setle(Register reg) { as.setle(reg); }
|
||||
public void test(Type type, Register a, Register b) { as.test(type, a, b); }
|
||||
protected void truePush(Register reg) { as.push(reg); }
|
||||
protected void truePop(Register reg) { as.pop(reg); }
|
||||
public void call(Symbol sym) { as.call(sym); }
|
||||
public void callAbsolute(Register reg) { as.callAbsolute(reg); }
|
||||
public void ret() { as.ret(); }
|
||||
// #@@range/dsl_ops2{
|
||||
public void mov(AsmOperand src, AsmOperand dest) { as.mov(src, dest); }
|
||||
public void mov(Type type, AsmOperand src, AsmOperand dest) { as.mov(type, src, dest); }
|
||||
public void movsx(Type from, Type to, AsmOperand src, AsmOperand dest) { as.movsx(from, to, src, dest); }
|
||||
public void movzx(Type from, Type to, AsmOperand src, AsmOperand dest) { as.movzx(from, to, src, dest); }
|
||||
// #@@}
|
||||
public void movsbl(AsmOperand src, AsmOperand dest) { as.movsbl(src, dest); }
|
||||
public void movswl(AsmOperand src, AsmOperand dest) { as.movswl(src, dest); }
|
||||
public void movzb(Type type, AsmOperand src, AsmOperand dest) { as.movzb(type, src, dest); }
|
||||
public void movzbl(AsmOperand src, AsmOperand dest) { as.movzbl(src, dest); }
|
||||
public void movzwl(AsmOperand src, AsmOperand dest) { as.movzwl(src, dest); }
|
||||
public void lea(AsmOperand src, AsmOperand dest) { as.lea(src, dest); }
|
||||
public void lea(Type type, AsmOperand src, AsmOperand dest) { as.lea(type, src, dest); }
|
||||
public void neg(Type type, Register reg) { as.neg(type, reg); }
|
||||
public void inc(Type type, AsmOperand reg) { as.inc(type, reg); }
|
||||
public void dec(Type type, AsmOperand reg) { as.dec(type, reg); }
|
||||
// #@@range/dsl_ops1{
|
||||
public void add(AsmOperand diff, AsmOperand base) { as.add(diff, base); }
|
||||
public void add(Type type, AsmOperand diff, AsmOperand base) { as.add(type, diff, base); }
|
||||
public void sub(AsmOperand diff, AsmOperand base) { as.sub(diff, base); }
|
||||
public void sub(Type type, AsmOperand diff, AsmOperand base) { as.sub(type, diff, base); }
|
||||
public void imul(AsmOperand m, Register base) { as.imul(m, base); }
|
||||
public void imul(Type type, AsmOperand m, Register base) { as.imul(type, m, base); }
|
||||
public void cltd() { as.cltd(); }
|
||||
public void div(Type type, Register base) { as.div(type, base); }
|
||||
public void idiv(Type type, Register base) { as.idiv(type, base); }
|
||||
// #@@}
|
||||
public void not(Type type, Register reg) { as.not(type, reg); }
|
||||
public void and(Type type, AsmOperand bits, Register base) { as.and(type, bits, base); }
|
||||
public void or(Type type, AsmOperand bits, Register base) { as.or(type, bits, base); }
|
||||
public void xor(Type type, AsmOperand bits, Register base) { as.xor(type, bits, base); }
|
||||
public void sar(Type type, Register n, Register base) { as.sar(type, n, base); }
|
||||
public void sal(Type type, Register n, Register base) { as.sal(type, n, base); }
|
||||
public void shr(Type type, Register n, Register base) { as.shr(type, n, base); }
|
||||
}
|
||||
|
|
|
@ -7,8 +7,8 @@ import net.loveruby.cflat.ast.DefinedFunction;
|
|||
import net.loveruby.cflat.ast.UndefinedFunction;
|
||||
import net.loveruby.cflat.ast.ConstantTable;
|
||||
import net.loveruby.cflat.ast.ToplevelScope;
|
||||
import net.loveruby.cflat.ast.Scope;
|
||||
import net.loveruby.cflat.type.TypeTable;
|
||||
import net.loveruby.cflat.type.Type;
|
||||
import java.io.PrintStream;
|
||||
import java.util.*;
|
||||
|
||||
|
@ -88,8 +88,8 @@ public class IR {
|
|||
return constantTable;
|
||||
}
|
||||
|
||||
public TypeTable typeTable() {
|
||||
return this.typeTable;
|
||||
public Type naturalType() {
|
||||
return this.typeTable.unsignedLong();
|
||||
}
|
||||
|
||||
public void dump() {
|
||||
|
|
Loading…
Reference in New Issue