r4811@macbookpro: aamine | 2009-05-10 22:41:42 +0900

* 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).
 


git-svn-id: file:///Users/aamine/c/gitwork/public/cbc/trunk@4197 1b9489fe-b721-0410-924e-b54b9192deb8
This commit is contained in:
Minero Aoki 2009-05-10 14:51:56 +00:00
parent 135881389d
commit 2bfba83992
14 changed files with 162 additions and 130 deletions

View File

@ -1,3 +1,38 @@
Sun May 10 22:42:07 2009 Minero Aoki <aamine@loveruby.net>
* 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 <aamine@loveruby.net>
* net/loveruby/cflat/asm/Assembler.java -> AssemblyFile.java

View File

@ -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);
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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<String> asOptions() {
return this.asOptions;
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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));

View File

@ -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<Void,Void>, ELFConstants {
public class CodeGenerator
implements net.loveruby.cflat.compiler.CodeGenerator,
IRVisitor<Void,Void>,
ELFConstants {
// #@@range/ctor{
protected CodeGeneratorOptions options;
protected Platform platform;
protected ErrorHandler errorHandler;
protected LinkedList<AssemblyFile> asStack;
protected AssemblyFile as;
@ -17,10 +21,8 @@ public class CodeGenerator implements IRVisitor<Void,Void>, 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<AssemblyFile>();
}
@ -28,10 +30,12 @@ public class CodeGenerator implements IRVisitor<Void,Void>, 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<Void,Void>, 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<Void,Void>, 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<Void,Void>, 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<Void,Void>, ELFConstants {
AsmStatistics stats = AsmStatistics.collect(bodyAsms);
bodyAsms = reduceLabels(bodyAsms, stats);
List<Register> 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<Void,Void>, ELFConstants {
protected List<Register> calleeSavedRegistersCache = null;
// platform dependent
protected List<Register> calleeSavedRegisters() {
if (calleeSavedRegistersCache == null) {
List<Register> regs = new ArrayList<Register>();
@ -536,7 +551,7 @@ public class CodeGenerator implements IRVisitor<Void,Void>, 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<Void,Void>, 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<Void,Void>, 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<Void,Void>, 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<Void,Void>, ELFConstants {
}
// rewind stack
// >4 bytes arguments are not supported.
rewindStack(platform.stackSizeFromWordNum(node.numArgs()));
rewindStack(stackSizeFromWordNum(node.numArgs()));
return null;
}
// #@@}

View File

@ -1,4 +1,4 @@
package net.loveruby.cflat.asm;
package net.loveruby.cflat.sysdep.x86;
public interface ELFConstants {
// Flags

View File

@ -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();
}
}

View File

@ -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);
}
}