r5032@macbookpro: aamine | 2009-06-07 03:03:18 +0900

* net/loveruby/cflat/sysdep/x86/CodeGenerator.java: refactoring compileFunctionBody.
 * net/loveruby/cflat/sysdep/x86/AssemblyFile.java: objectify VirtualStack.
 * net/loveruby/cflat/asm/IndirectMemoryReference.java: new method .relocatable to generate relocatable IndirectMemoryReference.
 * net/loveruby/cflat/asm/MemoryReference.java: new method #fixOffset.
 * net/loveruby/cflat/asm/DirectMemoryReference.java: new method #fixOffset.
 * net/loveruby/cflat/asm/Assembly.java: remove fixStackOffset.
 * net/loveruby/cflat/asm/Operand.java: ditto.
 


git-svn-id: file:///Users/aamine/c/gitwork/public/cbc/trunk@4277 1b9489fe-b721-0410-924e-b54b9192deb8
This commit is contained in:
Minero Aoki 2009-06-06 19:17:41 +00:00
parent 0f036467ce
commit 4ac683c9d7
10 changed files with 186 additions and 155 deletions

View File

@ -1,3 +1,24 @@
Sun Jun 7 03:02:35 2009 Minero Aoki <aamine@loveruby.net>
* net/loveruby/cflat/sysdep/x86/CodeGenerator.java: refactoring
compileFunctionBody.
* net/loveruby/cflat/sysdep/x86/AssemblyFile.java: objectify
VirtualStack.
* net/loveruby/cflat/asm/IndirectMemoryReference.java: new method
.relocatable to generate relocatable IndirectMemoryReference.
* net/loveruby/cflat/asm/MemoryReference.java: new method
#fixOffset.
* net/loveruby/cflat/asm/DirectMemoryReference.java: new method
#fixOffset.
* net/loveruby/cflat/asm/Assembly.java: remove fixStackOffset.
* net/loveruby/cflat/asm/Operand.java: ditto.
Sat Jun 6 21:36:09 2009 Minero Aoki <aamine@loveruby.net>
* lib/alloca.s: shorten assembly.

View File

@ -23,8 +23,4 @@ abstract public class Assembly {
public void collectStatistics(Statistics stats) {
// does nothing by default.
}
public void fixStackOffset(long diff) {
// does nothing by default.
}
}

View File

@ -15,6 +15,10 @@ public class DirectMemoryReference extends MemoryReference {
value.collectStatistics(stats);
}
public void fixOffset(long diff) {
throw new Error("DirectMemoryReference#fixOffset");
}
public String toString() {
return toSource(SymbolTable.dummy());
}

View File

@ -1,37 +1,39 @@
package net.loveruby.cflat.asm;
public class IndirectMemoryReference extends MemoryReference {
protected Literal offset;
protected Register base;
protected boolean fixed;
public IndirectMemoryReference(Register base) {
this.offset = new IntegerLiteral(0);
this.base = base;
this.fixed = false;
}
Literal offset;
Register base;
boolean fixed;
public IndirectMemoryReference(long offset, Register base) {
this.offset = new IntegerLiteral(offset);
this.base = base;
this.fixed = true;
this(new IntegerLiteral(offset), base, true);
}
public IndirectMemoryReference(Symbol offset, Register base) {
this(offset, base, true);
}
static public IndirectMemoryReference relocatable(long offset, Register base) {
return new IndirectMemoryReference(new IntegerLiteral(offset), base, false);
}
private IndirectMemoryReference(
Literal offset, Register base, boolean fixed) {
this.offset = offset;
this.base = base;
this.fixed = true;
this.fixed = fixed;
}
public Literal offset() {
return offset;
}
public void fixOffset(long realOffset) {
public void fixOffset(long diff) {
if (fixed) {
throw new Error("must not happen: fixed = true");
}
this.offset = new IntegerLiteral(realOffset);
long curr = ((IntegerLiteral)offset).value;
this.offset = new IntegerLiteral(curr + diff);
this.fixed = true;
}
@ -43,10 +45,6 @@ public class IndirectMemoryReference extends MemoryReference {
base.collectStatistics(stats);
}
public void fixStackOffset(long diff) {
offset = offset.plus(diff);
}
public String toString() {
return toSource(SymbolTable.dummy());
}
@ -73,6 +71,7 @@ public class IndirectMemoryReference extends MemoryReference {
public String dump() {
return "(IndirectMemoryReference "
+ (fixed ? "" : "*")
+ offset.dump() + " " + base.dump() + ")";
}
}

View File

@ -88,13 +88,6 @@ public class Instruction extends Assembly {
}
}
public void fixStackOffset(long diff) {
if (!needRelocation) return;
for (int i = 0; i < operands.length; i++) {
operands[i].fixStackOffset(diff);
}
}
public String toSource(SymbolTable table) {
StringBuffer buf = new StringBuffer();
buf.append("\t");

View File

@ -6,6 +6,7 @@ abstract public class MemoryReference
return true;
}
abstract public void fixOffset(long diff);
abstract protected int cmp(DirectMemoryReference mem);
abstract protected int cmp(IndirectMemoryReference mem);
}

View File

@ -22,8 +22,4 @@ abstract public class Operand implements OperandPattern {
public boolean match(Operand operand) {
return equals(operand);
}
public void fixStackOffset(long diff) {
// does nothing by default
}
}

View File

@ -1,5 +1,8 @@
package net.loveruby.cflat.asm;
import java.util.*;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
public class Statistics {
protected Map<Register, Integer> registerUsage;

View File

@ -6,12 +6,14 @@ import java.util.ArrayList;
import java.io.PrintStream;
public class AssemblyFile implements net.loveruby.cflat.sysdep.AssemblyFile {
private final List<Assembly> assemblies;
final Type naturalType;
final long stackWordSize;
final SymbolTable labelSymbols;
final boolean verbose;
private int commentIndentLevel;
final VirtualStack virtualStack = new VirtualStack();
private List<Assembly> assemblies = new ArrayList<Assembly>();
private int commentIndentLevel = 0;
private Statistics statistics;
AssemblyFile(Type naturalType, long stackWordSize,
SymbolTable labelSymbols, boolean verbose) {
@ -19,9 +21,6 @@ public class AssemblyFile implements net.loveruby.cflat.sysdep.AssemblyFile {
this.stackWordSize = stackWordSize;
this.labelSymbols = labelSymbols;
this.verbose = verbose;
this.assemblies = new ArrayList<Assembly>();
this.commentIndentLevel = 0;
initVirtualStack();
}
List<Assembly> assemblies() {
@ -51,6 +50,21 @@ public class AssemblyFile implements net.loveruby.cflat.sysdep.AssemblyFile {
}
}
void apply(PeepholeOptimizer opt) {
assemblies = opt.optimize(assemblies);
}
private Statistics statistics() {
if (statistics == null) {
statistics = Statistics.collect(assemblies);
}
return statistics;
}
boolean doesUses(Register reg) {
return statistics().doesRegisterUsed(reg);
}
void comment(String str) {
assemblies.add(new Comment(str, commentIndentLevel));
}
@ -71,6 +85,20 @@ public class AssemblyFile implements net.loveruby.cflat.sysdep.AssemblyFile {
assemblies.add(label);
}
void reduceLabels() {
Statistics stats = statistics();
List<Assembly> result = new ArrayList<Assembly>();
for (Assembly asm : assemblies) {
if (asm.isLabel() && ! stats.doesSymbolUsed((Label)asm)) {
;
}
else {
result.add(asm);
}
}
assemblies = result;
}
protected void directive(String direc) {
assemblies.add(new Directive(direc));
}
@ -210,62 +238,85 @@ public class AssemblyFile implements net.loveruby.cflat.sysdep.AssemblyFile {
// Virtual Stack
//
// #@@range/virtual_stack{
private long stackPointer;
private long stackPointerMax;
// #@@range/VirtualStack_ctor{
class VirtualStack {
private long offset;
private long max;
private List<IndirectMemoryReference> memrefs =
new ArrayList<IndirectMemoryReference>();
void initVirtualStack() {
stackPointer = 0;
stackPointerMax = stackPointer;
}
VirtualStack() {
reset();
}
void reset() {
offset = 0;
max = 0;
memrefs.clear();
}
// #@@}
// #@@range/maxTmpBytes{
long maxTmpBytes() {
return stackPointerMax;
}
// #@@}
// #@@range/maxSize{
long maxSize() {
return max;
}
// #@@}
// #@@range/stackTop{
IndirectMemoryReference stackTop() {
return new IndirectMemoryReference(-stackPointer, bp());
}
// #@@}
// #@@range/extend{
void extend(long len) {
offset += len;
max = Math.max(offset, max);
}
// #@@}
private Register bp() {
return new Register(RegisterClass.BP, naturalType);
// #@@range/rewindVirtualStack{
void rewind(long len) {
offset -= len;
}
// #@@}
// #@@range/top{
IndirectMemoryReference top() {
IndirectMemoryReference mem = relocatableMem(-offset, bp());
memrefs.add(mem);
return mem;
}
// #@@}
private IndirectMemoryReference relocatableMem(long offset, Register base) {
return IndirectMemoryReference.relocatable(offset, base);
}
private Register bp() {
return new Register(RegisterClass.BP, naturalType);
}
// #@@range/fixOffset{
void fixOffset(long diff) {
for (IndirectMemoryReference mem : memrefs) {
mem.fixOffset(diff);
}
}
// #@@}
}
// #@@range/virtualPush{
void virtualPush(Register reg) {
if (verbose) {
comment("push " + reg.baseName() + " -> " + stackTop());
comment("push " + reg.baseName() + " -> " + virtualStack.top());
}
extendVirtualStack(stackWordSize);
relocatableMov(reg, stackTop());
virtualStack.extend(stackWordSize);
mov(reg, virtualStack.top());
}
// #@@}
// #@@range/virtualPop{
void virtualPop(Register reg) {
if (verbose) {
comment("pop " + reg.baseName() + " <- " + stackTop());
comment("pop " + reg.baseName() + " <- " + virtualStack.top());
}
relocatableMov(stackTop(), reg);
rewindVirtualStack(stackWordSize);
}
// #@@}
// #@@range/extendVirtualStack{
void extendVirtualStack(long len) {
stackPointer += len;
stackPointerMax = Math.max(stackPointerMax, stackPointer);
}
// #@@}
// #@@range/rewindVirtualStack{
void rewindVirtualStack(long len) {
stackPointer -= len;
mov(virtualStack.top(), reg);
virtualStack.rewind(stackWordSize);
}
// #@@}

View File

@ -396,41 +396,40 @@ public class CodeGenerator
private void compileFunctionBody(
AssemblyFile file, DefinedFunction func) {
locateParameters(func.parameters());
locateLocalVariables(func.body().scope());
long lvarsSize = locateLocalVariables(func.body().scope(), 0);
AssemblyFile body = compileStmts(func);
List<Assembly> bodyAsms = optimize(body.assemblies());
Statistics stats = Statistics.collect(bodyAsms);
bodyAsms = reduceLabels(bodyAsms, stats);
List<Register> saveRegs = usedCalleeSavedRegistersWithoutBP(stats);
long saveRegsBytes = stackSizeFromWordNum(saveRegs.size());
long lvarBytes = fixLocalVariableOffsets(
func.body().scope(), saveRegsBytes);
fixTmpOffsets(bodyAsms, saveRegsBytes + lvarBytes);
AssemblyFile body = optimize(compileStmts(func));
List<Register> saveRegs = usedCalleeSavedRegisters(body);
long saveRegsSize = stackSizeFromWordNum(saveRegs.size());
fixLocalVariableOffsets(func.body().scope(), saveRegsSize);
body.virtualStack.fixOffset(saveRegsSize + lvarsSize);
if (options.isVerboseAsm()) {
printStackFrameLayout(file, saveRegsBytes, lvarBytes,
body.maxTmpBytes(), func.localVariables());
printStackFrameLayout(file, saveRegsSize, lvarsSize,
body.virtualStack.maxSize(), func.localVariables());
}
file.initVirtualStack();
file.virtualStack.reset();
prologue(file, func, saveRegs,
saveRegsBytes + lvarBytes + body.maxTmpBytes());
saveRegsSize + lvarsSize + body.virtualStack.maxSize());
if (options.isPositionIndependent()
&& stats.doesRegisterUsed(GOTBaseReg())) {
&& body.doesUses(GOTBaseReg())) {
loadGOTBaseAddress(file, GOTBaseReg());
}
file.addAll(bodyAsms);
epilogue(file, func, saveRegs, lvarBytes);
file.addAll(body.assemblies());
epilogue(file, func, saveRegs, lvarsSize);
file.virtualStack.fixOffset(0);
}
// #@@}
// #@@range/optimize{
private List<Assembly> optimize(List<Assembly> asms) {
private AssemblyFile optimize(AssemblyFile body) {
if (options.optimizeLevel() < 1) {
return asms;
return body;
}
return PeepholeOptimizer.defaultSet().optimize(asms);
body.apply(PeepholeOptimizer.defaultSet());
body.reduceLabels();
return body;
}
// #@@}
@ -490,41 +489,31 @@ public class CodeGenerator
}
// #@@}
// #@@range/reduceLabels{
private List<Assembly> reduceLabels(
List<Assembly> assemblies, Statistics stats) {
List<Assembly> result = new ArrayList<Assembly>();
for (Assembly asm : assemblies) {
if (asm.isLabel() && ! stats.doesSymbolUsed((Label)asm)) {
;
}
else {
result.add(asm);
}
}
return result;
}
// #@@}
private List<Register> usedCalleeSavedRegistersWithoutBP(Statistics stats) {
// does NOT include BP
private List<Register> usedCalleeSavedRegisters(AssemblyFile asm) {
List<Register> result = new ArrayList<Register>();
for (Register reg : calleeSavedRegisters()) {
if (stats.doesRegisterUsed(reg) && !reg.equals(bp())) {
if (asm.doesUses(reg)) {
result.add(reg);
}
}
result.remove(bp());
return result;
}
static final RegisterClass[] CALLEE_SAVED_REGISTERS = {
RegisterClass.BX, RegisterClass.BP,
RegisterClass.SI, RegisterClass.DI
};
private List<Register> calleeSavedRegistersCache = null;
private List<Register> calleeSavedRegisters() {
if (calleeSavedRegistersCache == null) {
List<Register> regs = new ArrayList<Register>();
regs.add(bx());
regs.add(si());
regs.add(di());
regs.add(bp());
for (RegisterClass c : CALLEE_SAVED_REGISTERS) {
regs.add(new Register(c, naturalType));
}
calleeSavedRegistersCache = regs;
}
return calleeSavedRegistersCache;
@ -586,45 +575,31 @@ public class CodeGenerator
* not determined, assign unfixed IndirectMemoryReference.
*/
// #@@range/locateLocalVariables{
private void locateLocalVariables(LocalScope scope) {
for (DefinedVariable var : scope.allLocalVariables()) {
var.setMemref(new IndirectMemoryReference(bp()));
}
}
// #@@}
/**
* Fixes addresses of local variables.
* Returns byte-length of the local variable area.
*/
// #@@range/fixLocalVariableOffsets{
private long fixLocalVariableOffsets(LocalScope scope, long initLen) {
long maxLen = allocateScope(scope, initLen);
return maxLen - initLen;
}
// #@@}
// #@@range/allocateScope{
private long allocateScope(LocalScope scope, long parentStackLen) {
private long locateLocalVariables(
LocalScope scope, long parentStackLen) {
long len = parentStackLen;
for (DefinedVariable var : scope.localVariables()) {
len = alignStack(len + var.allocSize());
fixMemref((IndirectMemoryReference)var.memref(), -len);
var.setMemref(relocatableMem(-len, bp()));
}
// Allocate local variables in child scopes.
// We allocate child scopes in the same area (overrapped).
long maxLen = len;
for (LocalScope s : scope.children()) {
long childLen = allocateScope(s, len);
long childLen = locateLocalVariables(s, len);
maxLen = Math.max(maxLen, childLen);
}
return maxLen;
}
// #@@}
// #@@range/fixMemref{
private void fixMemref(IndirectMemoryReference memref, long offset) {
memref.fixOffset(offset);
private IndirectMemoryReference relocatableMem(long offset, Register base) {
return IndirectMemoryReference.relocatable(offset, base);
}
// #@@range/fixLocalVariableOffsets{
private void fixLocalVariableOffsets(LocalScope scope, long len) {
for (DefinedVariable var : scope.allLocalVariables()) {
var.memref().fixOffset(-len);
}
}
// #@@}
@ -644,14 +619,6 @@ public class CodeGenerator
}
// #@@}
// #@@range/fixTmpOffsets{
private void fixTmpOffsets(List<Assembly> asms, long offset) {
for (Assembly asm : asms) {
asm.fixStackOffset(-offset);
}
}
// #@@}
/**
* Implements cdecl function call:
* * All arguments are on stack.