diff --git a/ChangeLog b/ChangeLog index 67f302b..f8541bb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,38 @@ +Sun May 10 22:42:07 2009 Minero Aoki + + * net/loveruby/cflat/sysdep/x86: new package. + + * net/loveruby/cflat/asm/ELFConstants.java -> + net/loveruby/cflat/sysdep/x86 + + * net/loveruby/cflat/asm/AssemblyFile.java -> + net/loveruby/cflat/sysdep/x86 + + net/loveruby/cflat/asm/Register.java + + * net/loveruby/cflat/platform/X86Linux.java -> + net/loveruby/cflat/sysdep/x86 + + * net/loveruby/cflat/compiler/CodeGenerator.java -> + net/loveruby/cflat/sysdep/x86 + + * net/loveruby/cflat/platform/Platform.java -> + net/loveruby/cflat/compiler + + * net/loveruby/cflat/sysdep/x86/Register.java: new file. + + * net/loveruby/cflat/compiler/Options.java: new method + #codeGenerator. + + * net/loveruby/cflat/compiler/Compiler.java: get CodeGenerator + from Options. + + * net/loveruby/cflat/compiler/CodeGeneratorOptions.java: make + public. + + * net/loveruby/cflat/ir/IR.java: now naturalType is useless + (provided by CodeGenerator). + Sun May 10 20:24:13 2009 Minero Aoki * net/loveruby/cflat/asm/Assembler.java -> AssemblyFile.java diff --git a/net/loveruby/cflat/asm/Register.java b/net/loveruby/cflat/asm/Register.java index fbf8702..239d31c 100644 --- a/net/loveruby/cflat/asm/Register.java +++ b/net/loveruby/cflat/asm/Register.java @@ -1,31 +1,15 @@ package net.loveruby.cflat.asm; -public class Register extends AsmOperand { +abstract public class Register extends AsmOperand { protected int size; protected String name; - // platform dependent - static final protected int naturalSize = 4; - - public Register(String name) { - this(naturalSize, name); - } - public Register(int size, String name) { this.size = size; this.name = name; } - public Register forType(Type t) { - switch (t.size()) { - case 1: - case 2: - case 4: - return new Register(t.size(), name); - default: - throw new Error("invalid register size: " + t.size()); - } - } + abstract public Register forType(Type t); public boolean isRegister() { return true; @@ -40,9 +24,7 @@ public class Register extends AsmOperand { return name.hashCode(); } - /** - * size difference does NOT matter. - */ + /** size difference does NOT matter. */ public boolean equals(Register reg) { return name.equals(reg.baseName()); } @@ -51,36 +33,14 @@ public class Register extends AsmOperand { return name; } + // default implementation public String name() { - switch (size) { - case 1: return lowerByteRegister(name); - case 2: return name; - case 4: return "e" + name; - default: - throw new Error("invalid register size: " + size); - } - } - - protected String lowerByteRegister(String baseName) { - if (! hasLowerByteRegister(baseName)) { - throw new Error("does not have lower-byte register: " + baseName); - } - return baseName.substring(0, 1) + "l"; - } - - protected boolean hasLowerByteRegister(String baseName) { - if (baseName.equals("ax")) return true; - if (baseName.equals("bx")) return true; - if (baseName.equals("cx")) return true; - if (baseName.equals("dx")) return true; - return false; + return name; } public void collectStatistics(AsmStatistics stats) { stats.registerUsed(this); } - public String toSource(SymbolTable table) { - return "%" + name(); - } + abstract public String toSource(SymbolTable table); } diff --git a/net/loveruby/cflat/compiler/CodeGeneratorOptions.java b/net/loveruby/cflat/compiler/CodeGeneratorOptions.java index d115a8d..713c6e2 100644 --- a/net/loveruby/cflat/compiler/CodeGeneratorOptions.java +++ b/net/loveruby/cflat/compiler/CodeGeneratorOptions.java @@ -2,7 +2,7 @@ package net.loveruby.cflat.compiler; import net.loveruby.cflat.asm.*; import java.util.*; -class CodeGeneratorOptions { +public class CodeGeneratorOptions { protected int optimizeLevel; protected boolean generatePIC; protected boolean generatePIE; diff --git a/net/loveruby/cflat/compiler/Compiler.java b/net/loveruby/cflat/compiler/Compiler.java index 0d54a41..6a23cf5 100644 --- a/net/loveruby/cflat/compiler/Compiler.java +++ b/net/loveruby/cflat/compiler/Compiler.java @@ -212,8 +212,7 @@ public class Compiler { } protected String generateAssembly(IR ir, Options opts) { - CodeGenerator gen = new CodeGenerator( - opts.genOptions(), opts.platform(), errorHandler); + CodeGenerator gen = opts.codeGenerator(errorHandler); return gen.generate(ir); } diff --git a/net/loveruby/cflat/compiler/Options.java b/net/loveruby/cflat/compiler/Options.java index 6eddea9..27d72fc 100644 --- a/net/loveruby/cflat/compiler/Options.java +++ b/net/loveruby/cflat/compiler/Options.java @@ -1,5 +1,5 @@ package net.loveruby.cflat.compiler; -import net.loveruby.cflat.platform.*; +import net.loveruby.cflat.sysdep.x86.X86Linux; import net.loveruby.cflat.type.TypeTable; import net.loveruby.cflat.asm.*; import net.loveruby.cflat.exception.*; @@ -77,6 +77,10 @@ class Options { return platform.typeTable(); } + CodeGenerator codeGenerator(ErrorHandler errorHandler) { + return platform.codeGenerator(genOptions, errorHandler); + } + LibraryLoader loader() { return this.loader; } @@ -93,10 +97,6 @@ class Options { return this.debugParser; } - CodeGeneratorOptions genOptions() { - return genOptions; - } - List asOptions() { return this.asOptions; } diff --git a/net/loveruby/cflat/compiler/Platform.java b/net/loveruby/cflat/compiler/Platform.java new file mode 100644 index 0000000..236d17e --- /dev/null +++ b/net/loveruby/cflat/compiler/Platform.java @@ -0,0 +1,7 @@ +package net.loveruby.cflat.compiler; +import net.loveruby.cflat.type.TypeTable; + +public interface Platform { + TypeTable typeTable(); + CodeGenerator codeGenerator(CodeGeneratorOptions opts, ErrorHandler h); +} diff --git a/net/loveruby/cflat/ir/IR.java b/net/loveruby/cflat/ir/IR.java index fde932d..b83e4a4 100644 --- a/net/loveruby/cflat/ir/IR.java +++ b/net/loveruby/cflat/ir/IR.java @@ -78,11 +78,6 @@ public class IR { return constantTable; } - public net.loveruby.cflat.asm.Type naturalType() { - // platform dependent!!! - return Type.INT32; - } - public void dump() { dump(System.out); } diff --git a/net/loveruby/cflat/platform/Platform.java b/net/loveruby/cflat/platform/Platform.java deleted file mode 100644 index dbb4654..0000000 --- a/net/loveruby/cflat/platform/Platform.java +++ /dev/null @@ -1,10 +0,0 @@ -package net.loveruby.cflat.platform; - -public interface Platform { - net.loveruby.cflat.type.TypeTable typeTable(); - net.loveruby.cflat.asm.Type naturalType(); - long align(long size); - long stackWordSize(); - long alignStack(long size); - long stackSizeFromWordNum(long numWords); -} diff --git a/net/loveruby/cflat/platform/X86Linux.java b/net/loveruby/cflat/platform/X86Linux.java deleted file mode 100644 index ed6f92d..0000000 --- a/net/loveruby/cflat/platform/X86Linux.java +++ /dev/null @@ -1,36 +0,0 @@ -package net.loveruby.cflat.platform; -import net.loveruby.cflat.type.TypeTable; -import net.loveruby.cflat.asm.Type; -import net.loveruby.cflat.utils.AsmUtils; - -public class X86Linux implements Platform { - static final Type naturalType = Type.INT32; - static final long alignment = 4; - // #@@range/stackParams{ - static final long stackWordSize = 4; - // #@@} - - public TypeTable typeTable() { - return TypeTable.ilp32(); - } - - public Type naturalType() { - return naturalType; - } - - public long align(long size) { - return AsmUtils.align(size, alignment); - } - - public long stackWordSize() { - return stackWordSize; - } - - public long alignStack(long size) { - return AsmUtils.align(size, stackWordSize); - } - - public long stackSizeFromWordNum(long num) { - return num * stackWordSize; - } -} diff --git a/net/loveruby/cflat/asm/AssemblyFile.java b/net/loveruby/cflat/sysdep/x86/AssemblyFile.java similarity index 97% rename from net/loveruby/cflat/asm/AssemblyFile.java rename to net/loveruby/cflat/sysdep/x86/AssemblyFile.java index 0f55b85..19de08e 100644 --- a/net/loveruby/cflat/asm/AssemblyFile.java +++ b/net/loveruby/cflat/sysdep/x86/AssemblyFile.java @@ -1,4 +1,5 @@ -package net.loveruby.cflat.asm; +package net.loveruby.cflat.sysdep.x86; +import net.loveruby.cflat.asm.*; import net.loveruby.cflat.utils.*; import java.util.*; @@ -21,11 +22,7 @@ public class AssemblyFile { this.assemblies.addAll(assemblies); } - static final public String CODE_SYMBOL_BASE = ".L"; - static final public String CONST_SYMBOL_BASE = ".LC"; - - public String toSource() { - SymbolTable symbolTable = new SymbolTable(CODE_SYMBOL_BASE); + public String toSource(SymbolTable symbolTable) { StringBuffer buf = new StringBuffer(); for (Assembly asm : assemblies) { buf.append(asm.toSource(symbolTable)); diff --git a/net/loveruby/cflat/compiler/CodeGenerator.java b/net/loveruby/cflat/sysdep/x86/CodeGenerator.java similarity index 96% rename from net/loveruby/cflat/compiler/CodeGenerator.java rename to net/loveruby/cflat/sysdep/x86/CodeGenerator.java index 13d79cc..c9d9b53 100644 --- a/net/loveruby/cflat/compiler/CodeGenerator.java +++ b/net/loveruby/cflat/sysdep/x86/CodeGenerator.java @@ -1,15 +1,19 @@ -package net.loveruby.cflat.compiler; -import net.loveruby.cflat.platform.Platform; +package net.loveruby.cflat.sysdep.x86; +import net.loveruby.cflat.compiler.CodeGeneratorOptions; +import net.loveruby.cflat.compiler.ErrorHandler; import net.loveruby.cflat.ast.Location; import net.loveruby.cflat.entity.*; import net.loveruby.cflat.ir.*; import net.loveruby.cflat.asm.*; +import net.loveruby.cflat.utils.AsmUtils; import java.util.*; -public class CodeGenerator implements IRVisitor, ELFConstants { +public class CodeGenerator + implements net.loveruby.cflat.compiler.CodeGenerator, + IRVisitor, + ELFConstants { // #@@range/ctor{ protected CodeGeneratorOptions options; - protected Platform platform; protected ErrorHandler errorHandler; protected LinkedList asStack; protected AssemblyFile as; @@ -17,10 +21,8 @@ public class CodeGenerator implements IRVisitor, ELFConstants { protected Label epilogue; public CodeGenerator(CodeGeneratorOptions options, - Platform platform, ErrorHandler errorHandler) { this.options = options; - this.platform = platform; this.errorHandler = errorHandler; this.asStack = new LinkedList(); } @@ -28,10 +30,12 @@ public class CodeGenerator implements IRVisitor, ELFConstants { /** Compiles IR and generates assembly code. */ // #@@range/generate{ + static final private String CONST_SYMBOL_BASE = ".LC"; + static final private String LABEL_SYMBOL_BASE = ".L"; + public String generate(IR ir) { - this.naturalType = ir.naturalType(); pushAssembler(); - SymbolTable constSymbols = new SymbolTable(AssemblyFile.CONST_SYMBOL_BASE); + SymbolTable constSymbols = new SymbolTable(CONST_SYMBOL_BASE); for (ConstantEntry ent : ir.constantTable().entries()) { locateConstant(ent, constSymbols); } @@ -42,11 +46,13 @@ public class CodeGenerator implements IRVisitor, ELFConstants { locateFunction(func); } compileIR(ir); - return popAssembler().toSource(); + return popAssembler().toSource(new SymbolTable(LABEL_SYMBOL_BASE)); } // #@@} // #@@range/pushAssembler{ + static final private Type NATURAL_TYPE = Type.INT32; + protected void pushAssembler() { this.as = new AssemblyFile(naturalType); asStack.add(this.as); @@ -226,14 +232,12 @@ public class CodeGenerator implements IRVisitor, ELFConstants { // #@@} // #@@range/globalSymbol{ - // platform dependent protected Symbol globalSymbol(String sym) { return new NamedSymbol(sym); } // #@@} // #@@range/privateSymbol{ - // platform dependent protected Symbol privateSymbol(String sym) { return new NamedSymbol(sym); } @@ -351,6 +355,18 @@ public class CodeGenerator implements IRVisitor, ELFConstants { * ======================= stack bottom */ + // #@@range/stackParams{ + static final private long STACK_WORD_SIZE = 4; + // #@@} + + public long alignStack(long size) { + return AsmUtils.align(size, STACK_WORD_SIZE); + } + + public long stackSizeFromWordNum(long numWords) { + return numWords * STACK_WORD_SIZE; + } + /** Compiles a function. */ // #@@range/compileFunction{ public void compileFunction(DefinedFunction func) { @@ -376,7 +392,7 @@ public class CodeGenerator implements IRVisitor, ELFConstants { AsmStatistics stats = AsmStatistics.collect(bodyAsms); bodyAsms = reduceLabels(bodyAsms, stats); List saveRegs = usedCalleeSavedRegistersWithoutBP(stats); - long saveRegsBytes = platform.stackSizeFromWordNum(saveRegs.size()); + long saveRegsBytes = stackSizeFromWordNum(saveRegs.size()); long lvarBytes = allocateLocalVariables( func.body().scope(), saveRegsBytes); fixTmpOffsets(bodyAsms, saveRegsBytes + lvarBytes); @@ -477,7 +493,6 @@ public class CodeGenerator implements IRVisitor, ELFConstants { protected List calleeSavedRegistersCache = null; - // platform dependent protected List calleeSavedRegisters() { if (calleeSavedRegistersCache == null) { List regs = new ArrayList(); @@ -536,7 +551,7 @@ public class CodeGenerator implements IRVisitor, ELFConstants { protected void allocateParameters(DefinedFunction func) { long numWords = paramStartWordNum; for (Parameter var : func.parameters()) { - var.setMemref(mem(platform.stackSizeFromWordNum(numWords), bp())); + var.setMemref(mem(stackSizeFromWordNum(numWords), bp())); numWords++; } } @@ -570,7 +585,7 @@ public class CodeGenerator implements IRVisitor, ELFConstants { protected long allocateScope(LocalScope scope, long parentStackLen) { long len = parentStackLen; for (DefinedVariable var : scope.localVariables()) { - len = platform.alignStack(len + var.allocSize()); + len = alignStack(len + var.allocSize()); fixMemref((IndirectMemoryReference)var.memref(), -len); } // Allocate local variables in child scopes. @@ -630,7 +645,7 @@ public class CodeGenerator implements IRVisitor, ELFConstants { // #@@range/virtualPush{ protected void virtualPush(Register reg) { - extendVirtualStack(platform.stackWordSize()); + extendVirtualStack(STACK_WORD_SIZE); as.relocatableMov(reg, stackTop()); if (options.isVerboseAsm()) { as.comment("push " + reg.name() + " -> " + stackTop()); @@ -644,7 +659,7 @@ public class CodeGenerator implements IRVisitor, ELFConstants { as.comment("pop " + reg.name() + " <- " + stackTop()); } as.relocatableMov(stackTop(), reg); - rewindVirtualStack(platform.stackWordSize()); + rewindVirtualStack(STACK_WORD_SIZE); } // #@@} @@ -694,7 +709,7 @@ public class CodeGenerator implements IRVisitor, ELFConstants { } // rewind stack // >4 bytes arguments are not supported. - rewindStack(platform.stackSizeFromWordNum(node.numArgs())); + rewindStack(stackSizeFromWordNum(node.numArgs())); return null; } // #@@} diff --git a/net/loveruby/cflat/asm/ELFConstants.java b/net/loveruby/cflat/sysdep/x86/ELFConstants.java similarity index 95% rename from net/loveruby/cflat/asm/ELFConstants.java rename to net/loveruby/cflat/sysdep/x86/ELFConstants.java index ba00895..18c6fd6 100644 --- a/net/loveruby/cflat/asm/ELFConstants.java +++ b/net/loveruby/cflat/sysdep/x86/ELFConstants.java @@ -1,4 +1,4 @@ -package net.loveruby.cflat.asm; +package net.loveruby.cflat.sysdep.x86; public interface ELFConstants { // Flags diff --git a/net/loveruby/cflat/sysdep/x86/Register.java b/net/loveruby/cflat/sysdep/x86/Register.java new file mode 100644 index 0000000..7af7d12 --- /dev/null +++ b/net/loveruby/cflat/sysdep/x86/Register.java @@ -0,0 +1,54 @@ +package net.loveruby.cflat.sysdep.x86; +import net.loveruby.cflat.asm.*; + +public class Register extends net.loveruby.cflat.asm.Register { + static final private int naturalSize = 4; + + public Register(String name) { + super(naturalSize, name); + } + + public Register(int size, String name) { + super(size, name); + } + + public Register forType(Type t) { + switch (t.size()) { + case 1: + case 2: + case 4: + return new Register(t.size(), name); + default: + throw new Error("invalid register size: " + t.size()); + } + } + + public String name() { + switch (size) { + case 1: return lowerByteRegister(name); + case 2: return name; + case 4: return "e" + name; + default: + throw new Error("invalid register size: " + size); + } + } + + private String lowerByteRegister(String baseName) { + if (! hasLowerByteRegister(baseName)) { + throw new Error("does not have lower-byte register: " + baseName); + } + return baseName.substring(0, 1) + "l"; + } + + private boolean hasLowerByteRegister(String baseName) { + if (baseName.equals("ax")) return true; + if (baseName.equals("bx")) return true; + if (baseName.equals("cx")) return true; + if (baseName.equals("dx")) return true; + return false; + } + + public String toSource(SymbolTable table) { + return "%" + name(); + } +} diff --git a/net/loveruby/cflat/sysdep/x86/X86Linux.java b/net/loveruby/cflat/sysdep/x86/X86Linux.java new file mode 100644 index 0000000..500cbf2 --- /dev/null +++ b/net/loveruby/cflat/sysdep/x86/X86Linux.java @@ -0,0 +1,16 @@ +package net.loveruby.cflat.sysdep.x86; +import net.loveruby.cflat.compiler.Platform; +import net.loveruby.cflat.compiler.CodeGeneratorOptions; +import net.loveruby.cflat.compiler.ErrorHandler; +import net.loveruby.cflat.type.TypeTable; + +public class X86Linux implements Platform { + public TypeTable typeTable() { + return TypeTable.ilp32(); + } + + public CodeGenerator codeGenerator( + CodeGeneratorOptions opts, ErrorHandler h) { + return new CodeGenerator(opts, h); + } +}