mirror of https://github.com/aamine/cbc
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:
parent
135881389d
commit
2bfba83992
35
ChangeLog
35
ChangeLog
|
@ -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>
|
Sun May 10 20:24:13 2009 Minero Aoki <aamine@loveruby.net>
|
||||||
|
|
||||||
* net/loveruby/cflat/asm/Assembler.java -> AssemblyFile.java
|
* net/loveruby/cflat/asm/Assembler.java -> AssemblyFile.java
|
||||||
|
|
|
@ -1,31 +1,15 @@
|
||||||
package net.loveruby.cflat.asm;
|
package net.loveruby.cflat.asm;
|
||||||
|
|
||||||
public class Register extends AsmOperand {
|
abstract public class Register extends AsmOperand {
|
||||||
protected int size;
|
protected int size;
|
||||||
protected String name;
|
protected String name;
|
||||||
|
|
||||||
// platform dependent
|
|
||||||
static final protected int naturalSize = 4;
|
|
||||||
|
|
||||||
public Register(String name) {
|
|
||||||
this(naturalSize, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Register(int size, String name) {
|
public Register(int size, String name) {
|
||||||
this.size = size;
|
this.size = size;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Register forType(Type t) {
|
abstract 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 boolean isRegister() {
|
public boolean isRegister() {
|
||||||
return true;
|
return true;
|
||||||
|
@ -40,9 +24,7 @@ public class Register extends AsmOperand {
|
||||||
return name.hashCode();
|
return name.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** size difference does NOT matter. */
|
||||||
* size difference does NOT matter.
|
|
||||||
*/
|
|
||||||
public boolean equals(Register reg) {
|
public boolean equals(Register reg) {
|
||||||
return name.equals(reg.baseName());
|
return name.equals(reg.baseName());
|
||||||
}
|
}
|
||||||
|
@ -51,36 +33,14 @@ public class Register extends AsmOperand {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// default implementation
|
||||||
public String name() {
|
public String name() {
|
||||||
switch (size) {
|
return name;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void collectStatistics(AsmStatistics stats) {
|
public void collectStatistics(AsmStatistics stats) {
|
||||||
stats.registerUsed(this);
|
stats.registerUsed(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toSource(SymbolTable table) {
|
abstract public String toSource(SymbolTable table);
|
||||||
return "%" + name();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ package net.loveruby.cflat.compiler;
|
||||||
import net.loveruby.cflat.asm.*;
|
import net.loveruby.cflat.asm.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
class CodeGeneratorOptions {
|
public class CodeGeneratorOptions {
|
||||||
protected int optimizeLevel;
|
protected int optimizeLevel;
|
||||||
protected boolean generatePIC;
|
protected boolean generatePIC;
|
||||||
protected boolean generatePIE;
|
protected boolean generatePIE;
|
||||||
|
|
|
@ -212,8 +212,7 @@ public class Compiler {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String generateAssembly(IR ir, Options opts) {
|
protected String generateAssembly(IR ir, Options opts) {
|
||||||
CodeGenerator gen = new CodeGenerator(
|
CodeGenerator gen = opts.codeGenerator(errorHandler);
|
||||||
opts.genOptions(), opts.platform(), errorHandler);
|
|
||||||
return gen.generate(ir);
|
return gen.generate(ir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
package net.loveruby.cflat.compiler;
|
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.type.TypeTable;
|
||||||
import net.loveruby.cflat.asm.*;
|
import net.loveruby.cflat.asm.*;
|
||||||
import net.loveruby.cflat.exception.*;
|
import net.loveruby.cflat.exception.*;
|
||||||
|
@ -77,6 +77,10 @@ class Options {
|
||||||
return platform.typeTable();
|
return platform.typeTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CodeGenerator codeGenerator(ErrorHandler errorHandler) {
|
||||||
|
return platform.codeGenerator(genOptions, errorHandler);
|
||||||
|
}
|
||||||
|
|
||||||
LibraryLoader loader() {
|
LibraryLoader loader() {
|
||||||
return this.loader;
|
return this.loader;
|
||||||
}
|
}
|
||||||
|
@ -93,10 +97,6 @@ class Options {
|
||||||
return this.debugParser;
|
return this.debugParser;
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeGeneratorOptions genOptions() {
|
|
||||||
return genOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<String> asOptions() {
|
List<String> asOptions() {
|
||||||
return this.asOptions;
|
return this.asOptions;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -78,11 +78,6 @@ public class IR {
|
||||||
return constantTable;
|
return constantTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public net.loveruby.cflat.asm.Type naturalType() {
|
|
||||||
// platform dependent!!!
|
|
||||||
return Type.INT32;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void dump() {
|
public void dump() {
|
||||||
dump(System.out);
|
dump(System.out);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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 net.loveruby.cflat.utils.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
@ -21,11 +22,7 @@ public class AssemblyFile {
|
||||||
this.assemblies.addAll(assemblies);
|
this.assemblies.addAll(assemblies);
|
||||||
}
|
}
|
||||||
|
|
||||||
static final public String CODE_SYMBOL_BASE = ".L";
|
public String toSource(SymbolTable symbolTable) {
|
||||||
static final public String CONST_SYMBOL_BASE = ".LC";
|
|
||||||
|
|
||||||
public String toSource() {
|
|
||||||
SymbolTable symbolTable = new SymbolTable(CODE_SYMBOL_BASE);
|
|
||||||
StringBuffer buf = new StringBuffer();
|
StringBuffer buf = new StringBuffer();
|
||||||
for (Assembly asm : assemblies) {
|
for (Assembly asm : assemblies) {
|
||||||
buf.append(asm.toSource(symbolTable));
|
buf.append(asm.toSource(symbolTable));
|
|
@ -1,15 +1,19 @@
|
||||||
package net.loveruby.cflat.compiler;
|
package net.loveruby.cflat.sysdep.x86;
|
||||||
import net.loveruby.cflat.platform.Platform;
|
import net.loveruby.cflat.compiler.CodeGeneratorOptions;
|
||||||
|
import net.loveruby.cflat.compiler.ErrorHandler;
|
||||||
import net.loveruby.cflat.ast.Location;
|
import net.loveruby.cflat.ast.Location;
|
||||||
import net.loveruby.cflat.entity.*;
|
import net.loveruby.cflat.entity.*;
|
||||||
import net.loveruby.cflat.ir.*;
|
import net.loveruby.cflat.ir.*;
|
||||||
import net.loveruby.cflat.asm.*;
|
import net.loveruby.cflat.asm.*;
|
||||||
|
import net.loveruby.cflat.utils.AsmUtils;
|
||||||
import java.util.*;
|
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{
|
// #@@range/ctor{
|
||||||
protected CodeGeneratorOptions options;
|
protected CodeGeneratorOptions options;
|
||||||
protected Platform platform;
|
|
||||||
protected ErrorHandler errorHandler;
|
protected ErrorHandler errorHandler;
|
||||||
protected LinkedList<AssemblyFile> asStack;
|
protected LinkedList<AssemblyFile> asStack;
|
||||||
protected AssemblyFile as;
|
protected AssemblyFile as;
|
||||||
|
@ -17,10 +21,8 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
||||||
protected Label epilogue;
|
protected Label epilogue;
|
||||||
|
|
||||||
public CodeGenerator(CodeGeneratorOptions options,
|
public CodeGenerator(CodeGeneratorOptions options,
|
||||||
Platform platform,
|
|
||||||
ErrorHandler errorHandler) {
|
ErrorHandler errorHandler) {
|
||||||
this.options = options;
|
this.options = options;
|
||||||
this.platform = platform;
|
|
||||||
this.errorHandler = errorHandler;
|
this.errorHandler = errorHandler;
|
||||||
this.asStack = new LinkedList<AssemblyFile>();
|
this.asStack = new LinkedList<AssemblyFile>();
|
||||||
}
|
}
|
||||||
|
@ -28,10 +30,12 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
||||||
|
|
||||||
/** Compiles IR and generates assembly code. */
|
/** Compiles IR and generates assembly code. */
|
||||||
// #@@range/generate{
|
// #@@range/generate{
|
||||||
|
static final private String CONST_SYMBOL_BASE = ".LC";
|
||||||
|
static final private String LABEL_SYMBOL_BASE = ".L";
|
||||||
|
|
||||||
public String generate(IR ir) {
|
public String generate(IR ir) {
|
||||||
this.naturalType = ir.naturalType();
|
|
||||||
pushAssembler();
|
pushAssembler();
|
||||||
SymbolTable constSymbols = new SymbolTable(AssemblyFile.CONST_SYMBOL_BASE);
|
SymbolTable constSymbols = new SymbolTable(CONST_SYMBOL_BASE);
|
||||||
for (ConstantEntry ent : ir.constantTable().entries()) {
|
for (ConstantEntry ent : ir.constantTable().entries()) {
|
||||||
locateConstant(ent, constSymbols);
|
locateConstant(ent, constSymbols);
|
||||||
}
|
}
|
||||||
|
@ -42,11 +46,13 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
||||||
locateFunction(func);
|
locateFunction(func);
|
||||||
}
|
}
|
||||||
compileIR(ir);
|
compileIR(ir);
|
||||||
return popAssembler().toSource();
|
return popAssembler().toSource(new SymbolTable(LABEL_SYMBOL_BASE));
|
||||||
}
|
}
|
||||||
// #@@}
|
// #@@}
|
||||||
|
|
||||||
// #@@range/pushAssembler{
|
// #@@range/pushAssembler{
|
||||||
|
static final private Type NATURAL_TYPE = Type.INT32;
|
||||||
|
|
||||||
protected void pushAssembler() {
|
protected void pushAssembler() {
|
||||||
this.as = new AssemblyFile(naturalType);
|
this.as = new AssemblyFile(naturalType);
|
||||||
asStack.add(this.as);
|
asStack.add(this.as);
|
||||||
|
@ -226,14 +232,12 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
||||||
// #@@}
|
// #@@}
|
||||||
|
|
||||||
// #@@range/globalSymbol{
|
// #@@range/globalSymbol{
|
||||||
// platform dependent
|
|
||||||
protected Symbol globalSymbol(String sym) {
|
protected Symbol globalSymbol(String sym) {
|
||||||
return new NamedSymbol(sym);
|
return new NamedSymbol(sym);
|
||||||
}
|
}
|
||||||
// #@@}
|
// #@@}
|
||||||
|
|
||||||
// #@@range/privateSymbol{
|
// #@@range/privateSymbol{
|
||||||
// platform dependent
|
|
||||||
protected Symbol privateSymbol(String sym) {
|
protected Symbol privateSymbol(String sym) {
|
||||||
return new NamedSymbol(sym);
|
return new NamedSymbol(sym);
|
||||||
}
|
}
|
||||||
|
@ -351,6 +355,18 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
||||||
* ======================= stack bottom
|
* ======================= 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. */
|
/** Compiles a function. */
|
||||||
// #@@range/compileFunction{
|
// #@@range/compileFunction{
|
||||||
public void compileFunction(DefinedFunction func) {
|
public void compileFunction(DefinedFunction func) {
|
||||||
|
@ -376,7 +392,7 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
||||||
AsmStatistics stats = AsmStatistics.collect(bodyAsms);
|
AsmStatistics stats = AsmStatistics.collect(bodyAsms);
|
||||||
bodyAsms = reduceLabels(bodyAsms, stats);
|
bodyAsms = reduceLabels(bodyAsms, stats);
|
||||||
List<Register> saveRegs = usedCalleeSavedRegistersWithoutBP(stats);
|
List<Register> saveRegs = usedCalleeSavedRegistersWithoutBP(stats);
|
||||||
long saveRegsBytes = platform.stackSizeFromWordNum(saveRegs.size());
|
long saveRegsBytes = stackSizeFromWordNum(saveRegs.size());
|
||||||
long lvarBytes = allocateLocalVariables(
|
long lvarBytes = allocateLocalVariables(
|
||||||
func.body().scope(), saveRegsBytes);
|
func.body().scope(), saveRegsBytes);
|
||||||
fixTmpOffsets(bodyAsms, saveRegsBytes + lvarBytes);
|
fixTmpOffsets(bodyAsms, saveRegsBytes + lvarBytes);
|
||||||
|
@ -477,7 +493,6 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
||||||
|
|
||||||
protected List<Register> calleeSavedRegistersCache = null;
|
protected List<Register> calleeSavedRegistersCache = null;
|
||||||
|
|
||||||
// platform dependent
|
|
||||||
protected List<Register> calleeSavedRegisters() {
|
protected List<Register> calleeSavedRegisters() {
|
||||||
if (calleeSavedRegistersCache == null) {
|
if (calleeSavedRegistersCache == null) {
|
||||||
List<Register> regs = new ArrayList<Register>();
|
List<Register> regs = new ArrayList<Register>();
|
||||||
|
@ -536,7 +551,7 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
||||||
protected void allocateParameters(DefinedFunction func) {
|
protected void allocateParameters(DefinedFunction func) {
|
||||||
long numWords = paramStartWordNum;
|
long numWords = paramStartWordNum;
|
||||||
for (Parameter var : func.parameters()) {
|
for (Parameter var : func.parameters()) {
|
||||||
var.setMemref(mem(platform.stackSizeFromWordNum(numWords), bp()));
|
var.setMemref(mem(stackSizeFromWordNum(numWords), bp()));
|
||||||
numWords++;
|
numWords++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -570,7 +585,7 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
||||||
protected long allocateScope(LocalScope scope, long parentStackLen) {
|
protected long allocateScope(LocalScope scope, long parentStackLen) {
|
||||||
long len = parentStackLen;
|
long len = parentStackLen;
|
||||||
for (DefinedVariable var : scope.localVariables()) {
|
for (DefinedVariable var : scope.localVariables()) {
|
||||||
len = platform.alignStack(len + var.allocSize());
|
len = alignStack(len + var.allocSize());
|
||||||
fixMemref((IndirectMemoryReference)var.memref(), -len);
|
fixMemref((IndirectMemoryReference)var.memref(), -len);
|
||||||
}
|
}
|
||||||
// Allocate local variables in child scopes.
|
// Allocate local variables in child scopes.
|
||||||
|
@ -630,7 +645,7 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
||||||
|
|
||||||
// #@@range/virtualPush{
|
// #@@range/virtualPush{
|
||||||
protected void virtualPush(Register reg) {
|
protected void virtualPush(Register reg) {
|
||||||
extendVirtualStack(platform.stackWordSize());
|
extendVirtualStack(STACK_WORD_SIZE);
|
||||||
as.relocatableMov(reg, stackTop());
|
as.relocatableMov(reg, stackTop());
|
||||||
if (options.isVerboseAsm()) {
|
if (options.isVerboseAsm()) {
|
||||||
as.comment("push " + reg.name() + " -> " + stackTop());
|
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.comment("pop " + reg.name() + " <- " + stackTop());
|
||||||
}
|
}
|
||||||
as.relocatableMov(stackTop(), reg);
|
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
|
// rewind stack
|
||||||
// >4 bytes arguments are not supported.
|
// >4 bytes arguments are not supported.
|
||||||
rewindStack(platform.stackSizeFromWordNum(node.numArgs()));
|
rewindStack(stackSizeFromWordNum(node.numArgs()));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// #@@}
|
// #@@}
|
|
@ -1,4 +1,4 @@
|
||||||
package net.loveruby.cflat.asm;
|
package net.loveruby.cflat.sysdep.x86;
|
||||||
|
|
||||||
public interface ELFConstants {
|
public interface ELFConstants {
|
||||||
// Flags
|
// Flags
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue