mirror of https://github.com/aamine/cbc
r4808@macbookpro: aamine | 2009-05-10 20:23:48 +0900
* net/loveruby/cflat/asm/Assembler.java -> AssemblyFile.java * net/loveruby/cflat/utils/AsmUtils.java: split #align from AssemblyFile. * net/loveruby/cflat/type/StructType.java: use it. * net/loveruby/cflat/type/UnionType.java: use it. * net/loveruby/cflat/platform: new package to extract platform dependent operations. * net/loveruby/cflat/compiler/Compiler.java: use it. * net/loveruby/cflat/compiler/CodeGenerator.java: use it. * net/loveruby/cflat/compiler/Options.java: provide Platform object. git-svn-id: file:///Users/aamine/c/gitwork/public/cbc/trunk@4194 1b9489fe-b721-0410-924e-b54b9192deb8
This commit is contained in:
parent
6e8bfed7a3
commit
2e1cbdaf66
21
ChangeLog
21
ChangeLog
|
@ -1,3 +1,24 @@
|
||||||
|
Sun May 10 20:24:13 2009 Minero Aoki <aamine@loveruby.net>
|
||||||
|
|
||||||
|
* net/loveruby/cflat/asm/Assembler.java -> AssemblyFile.java
|
||||||
|
|
||||||
|
* net/loveruby/cflat/utils/AsmUtils.java: split #align from
|
||||||
|
AssemblyFile.
|
||||||
|
|
||||||
|
* net/loveruby/cflat/type/StructType.java: use it.
|
||||||
|
|
||||||
|
* net/loveruby/cflat/type/UnionType.java: use it.
|
||||||
|
|
||||||
|
* net/loveruby/cflat/platform: new package to extract platform
|
||||||
|
dependent operations.
|
||||||
|
|
||||||
|
* net/loveruby/cflat/compiler/Compiler.java: use it.
|
||||||
|
|
||||||
|
* net/loveruby/cflat/compiler/CodeGenerator.java: use it.
|
||||||
|
|
||||||
|
* net/loveruby/cflat/compiler/Options.java: provide Platform
|
||||||
|
object.
|
||||||
|
|
||||||
Thu May 7 13:00:09 2009 Minero Aoki <aamine@loveruby.net>
|
Thu May 7 13:00:09 2009 Minero Aoki <aamine@loveruby.net>
|
||||||
|
|
||||||
* net/loveruby/cflat/compiler/IRGenerator.java: should not return
|
* net/loveruby/cflat/compiler/IRGenerator.java: should not return
|
||||||
|
|
|
@ -2,16 +2,12 @@ package net.loveruby.cflat.asm;
|
||||||
import net.loveruby.cflat.utils.*;
|
import net.loveruby.cflat.utils.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class Assembler {
|
public class AssemblyFile {
|
||||||
protected List<Assembly> assemblies;
|
protected List<Assembly> assemblies;
|
||||||
protected Type naturalType;
|
protected Type naturalType;
|
||||||
protected int commentIndentLevel;
|
protected int commentIndentLevel;
|
||||||
|
|
||||||
static public long align(long n, long alignment) {
|
public AssemblyFile(Type naturalType) {
|
||||||
return (n + alignment - 1) / alignment * alignment;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Assembler(Type naturalType) {
|
|
||||||
this.assemblies = new ArrayList<Assembly>();
|
this.assemblies = new ArrayList<Assembly>();
|
||||||
this.naturalType = naturalType;
|
this.naturalType = naturalType;
|
||||||
this.commentIndentLevel = 0;
|
this.commentIndentLevel = 0;
|
|
@ -1,4 +1,5 @@
|
||||||
package net.loveruby.cflat.compiler;
|
package net.loveruby.cflat.compiler;
|
||||||
|
import net.loveruby.cflat.platform.Platform;
|
||||||
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.*;
|
||||||
|
@ -8,17 +9,20 @@ import java.util.*;
|
||||||
public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
public class CodeGenerator implements 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<Assembler> asStack;
|
protected LinkedList<AssemblyFile> asStack;
|
||||||
protected Assembler as;
|
protected AssemblyFile as;
|
||||||
protected Type naturalType;
|
protected Type naturalType;
|
||||||
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<Assembler>();
|
this.asStack = new LinkedList<AssemblyFile>();
|
||||||
}
|
}
|
||||||
// #@@}
|
// #@@}
|
||||||
|
|
||||||
|
@ -27,7 +31,7 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
||||||
public String generate(IR ir) {
|
public String generate(IR ir) {
|
||||||
this.naturalType = ir.naturalType();
|
this.naturalType = ir.naturalType();
|
||||||
pushAssembler();
|
pushAssembler();
|
||||||
SymbolTable constSymbols = new SymbolTable(Assembler.CONST_SYMBOL_BASE);
|
SymbolTable constSymbols = new SymbolTable(AssemblyFile.CONST_SYMBOL_BASE);
|
||||||
for (ConstantEntry ent : ir.constantTable().entries()) {
|
for (ConstantEntry ent : ir.constantTable().entries()) {
|
||||||
locateConstant(ent, constSymbols);
|
locateConstant(ent, constSymbols);
|
||||||
}
|
}
|
||||||
|
@ -44,14 +48,14 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
||||||
|
|
||||||
// #@@range/pushAssembler{
|
// #@@range/pushAssembler{
|
||||||
protected void pushAssembler() {
|
protected void pushAssembler() {
|
||||||
this.as = new Assembler(naturalType);
|
this.as = new AssemblyFile(naturalType);
|
||||||
asStack.add(this.as);
|
asStack.add(this.as);
|
||||||
}
|
}
|
||||||
// #@@}
|
// #@@}
|
||||||
|
|
||||||
// #@@range/popAssembler{
|
// #@@range/popAssembler{
|
||||||
protected Assembler popAssembler() {
|
protected AssemblyFile popAssembler() {
|
||||||
Assembler popped = asStack.removeLast();
|
AssemblyFile popped = asStack.removeLast();
|
||||||
this.as = asStack.isEmpty() ? null : asStack.getLast();
|
this.as = asStack.isEmpty() ? null : asStack.getLast();
|
||||||
return popped;
|
return popped;
|
||||||
}
|
}
|
||||||
|
@ -347,17 +351,6 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
||||||
* ======================= stack bottom
|
* ======================= stack bottom
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
* Platform Dependent Stack Parameters
|
|
||||||
*/
|
|
||||||
// #@@range/stackParams{
|
|
||||||
static final protected boolean stackGrowsLower = true;
|
|
||||||
static final protected long stackWordSize = 4;
|
|
||||||
static final protected long stackAlignment = stackWordSize;
|
|
||||||
static final protected long paramStartWord = 2;
|
|
||||||
// return addr and saved bp
|
|
||||||
// #@@}
|
|
||||||
|
|
||||||
/** Compiles a function. */
|
/** Compiles a function. */
|
||||||
// #@@range/compileFunction{
|
// #@@range/compileFunction{
|
||||||
public void compileFunction(DefinedFunction func) {
|
public void compileFunction(DefinedFunction func) {
|
||||||
|
@ -383,7 +376,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 = saveRegs.size() * stackWordSize;
|
long saveRegsBytes = platform.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);
|
||||||
|
@ -537,16 +530,14 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
||||||
// #@@}
|
// #@@}
|
||||||
|
|
||||||
// #@@range/allocateParameters{
|
// #@@range/allocateParameters{
|
||||||
|
static final private long paramStartWordNum = 2;
|
||||||
|
// return addr and saved bp
|
||||||
|
|
||||||
protected void allocateParameters(DefinedFunction func) {
|
protected void allocateParameters(DefinedFunction func) {
|
||||||
long word = paramStartWord;
|
long numWords = paramStartWordNum;
|
||||||
for (Parameter var : func.parameters()) {
|
for (Parameter var : func.parameters()) {
|
||||||
if (stackGrowsLower) {
|
var.setMemref(mem(platform.stackSizeFromWordNum(numWords), bp()));
|
||||||
var.setMemref(mem(word * stackWordSize, bp()));
|
numWords++;
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new Error("unsupported stack layout");
|
|
||||||
}
|
|
||||||
word++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// #@@}
|
// #@@}
|
||||||
|
@ -579,14 +570,8 @@ 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()) {
|
||||||
if (stackGrowsLower) {
|
len = platform.alignStack(len + var.allocSize());
|
||||||
len = Assembler.align(len + var.allocSize(), stackAlignment);
|
fixMemref((IndirectMemoryReference)var.memref(), -len);
|
||||||
fixMemref((IndirectMemoryReference)var.memref(), -len);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
fixMemref((IndirectMemoryReference)var.memref(), len);
|
|
||||||
len = Assembler.align(len + var.allocSize(), stackAlignment);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Allocate local variables in child scopes.
|
// Allocate local variables in child scopes.
|
||||||
// We allocate child scopes in the same area (overrapped).
|
// We allocate child scopes in the same area (overrapped).
|
||||||
|
@ -608,12 +593,7 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
||||||
// #@@range/extendStack{
|
// #@@range/extendStack{
|
||||||
protected void extendStack(long len) {
|
protected void extendStack(long len) {
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
if (stackGrowsLower) {
|
as.sub(imm(len), sp());
|
||||||
as.sub(imm(len), sp());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
as.add(imm(len), sp());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// #@@}
|
// #@@}
|
||||||
|
@ -621,12 +601,7 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
||||||
// #@@range/rewindStack{
|
// #@@range/rewindStack{
|
||||||
protected void rewindStack(long len) {
|
protected void rewindStack(long len) {
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
if (stackGrowsLower) {
|
as.add(imm(len), sp());
|
||||||
as.add(imm(len), sp());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
as.sub(imm(len), sp());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// #@@}
|
// #@@}
|
||||||
|
@ -649,18 +624,13 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
||||||
|
|
||||||
// #@@range/stackTop{
|
// #@@range/stackTop{
|
||||||
protected IndirectMemoryReference stackTop() {
|
protected IndirectMemoryReference stackTop() {
|
||||||
if (stackGrowsLower) {
|
return mem(-stackPointer, bp());
|
||||||
return mem(-stackPointer, bp());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return mem(stackPointer - stackWordSize, bp());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// #@@}
|
// #@@}
|
||||||
|
|
||||||
// #@@range/virtualPush{
|
// #@@range/virtualPush{
|
||||||
protected void virtualPush(Register reg) {
|
protected void virtualPush(Register reg) {
|
||||||
extendVirtualStack(stackWordSize);
|
extendVirtualStack(platform.stackWordSize());
|
||||||
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());
|
||||||
|
@ -674,7 +644,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(stackWordSize);
|
rewindVirtualStack(platform.stackWordSize());
|
||||||
}
|
}
|
||||||
// #@@}
|
// #@@}
|
||||||
|
|
||||||
|
@ -694,7 +664,7 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
||||||
// #@@range/fixTmpOffsets{
|
// #@@range/fixTmpOffsets{
|
||||||
protected void fixTmpOffsets(List<Assembly> asms, long offset) {
|
protected void fixTmpOffsets(List<Assembly> asms, long offset) {
|
||||||
for (Assembly asm : asms) {
|
for (Assembly asm : asms) {
|
||||||
asm.fixStackOffset(offset * (stackGrowsLower ? -1 : 1));
|
asm.fixStackOffset(-offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// #@@}
|
// #@@}
|
||||||
|
@ -724,7 +694,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(node.numArgs() * stackWordSize);
|
rewindStack(platform.stackSizeFromWordNum(node.numArgs()));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// #@@}
|
// #@@}
|
||||||
|
|
|
@ -25,12 +25,8 @@ public class Compiler {
|
||||||
}
|
}
|
||||||
// #@@}
|
// #@@}
|
||||||
|
|
||||||
private TypeTable defaultTypeTable() {
|
|
||||||
return TypeTable.ilp32();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void commandMain(String[] origArgs) {
|
public void commandMain(String[] origArgs) {
|
||||||
Options opts = new Options(defaultTypeTable(), new LibraryLoader());
|
Options opts = new Options();
|
||||||
List<SourceFile> srcs = null;
|
List<SourceFile> srcs = null;
|
||||||
try {
|
try {
|
||||||
srcs = opts.parse(Arrays.asList(origArgs));
|
srcs = opts.parse(Arrays.asList(origArgs));
|
||||||
|
@ -118,7 +114,7 @@ public class Compiler {
|
||||||
findExpr(ast).dump();
|
findExpr(ast).dump();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ast.setTypeTable(opts.typeTable);
|
ast.setTypeTable(opts.typeTable());
|
||||||
semanticAnalysis(ast, opts);
|
semanticAnalysis(ast, opts);
|
||||||
switch (opts.mode()) {
|
switch (opts.mode()) {
|
||||||
case DumpReference:
|
case DumpReference:
|
||||||
|
@ -216,7 +212,8 @@ public class Compiler {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String generateAssembly(IR ir, Options opts) {
|
protected String generateAssembly(IR ir, Options opts) {
|
||||||
CodeGenerator gen = new CodeGenerator(opts.genOptions(), errorHandler);
|
CodeGenerator gen = new CodeGenerator(
|
||||||
|
opts.genOptions(), opts.platform(), errorHandler);
|
||||||
return gen.generate(ir);
|
return gen.generate(ir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
package net.loveruby.cflat.compiler;
|
package net.loveruby.cflat.compiler;
|
||||||
|
import net.loveruby.cflat.platform.*;
|
||||||
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.*;
|
||||||
|
@ -7,55 +8,45 @@ import java.io.*;
|
||||||
|
|
||||||
// package scope
|
// package scope
|
||||||
class Options {
|
class Options {
|
||||||
protected CompilerMode mode;
|
CompilerMode mode;
|
||||||
protected TypeTable typeTable;
|
LibraryLoader loader = new LibraryLoader();
|
||||||
protected LibraryLoader loader;
|
Platform platform = new X86Linux();
|
||||||
protected String outputFileName;
|
String outputFileName;
|
||||||
protected boolean verbose;
|
boolean verbose = false;
|
||||||
protected boolean debugParser;
|
boolean debugParser = false;
|
||||||
protected CodeGeneratorOptions genOptions;
|
CodeGeneratorOptions genOptions = new CodeGeneratorOptions();
|
||||||
protected List<String> asOptions;
|
List<String> asOptions = new ArrayList<String>();
|
||||||
protected boolean generatingSharedLibrary;
|
boolean generatingSharedLibrary = false;
|
||||||
protected boolean generatingPIE;
|
boolean generatingPIE = false;
|
||||||
protected List<LdArg> ldArgs;
|
List<LdArg> ldArgs = new ArrayList<LdArg>();
|
||||||
protected boolean noStartFiles = false;
|
boolean noStartFiles = false;
|
||||||
protected boolean noDefaultLibs = false;
|
boolean noDefaultLibs = false;
|
||||||
|
|
||||||
public Options(TypeTable typeTable, LibraryLoader loader) {
|
CompilerMode mode() {
|
||||||
this.typeTable = typeTable;
|
|
||||||
this.loader = loader;
|
|
||||||
this.genOptions = new CodeGeneratorOptions();
|
|
||||||
this.asOptions = new ArrayList<String>();
|
|
||||||
this.generatingSharedLibrary = false;
|
|
||||||
this.generatingPIE = false;
|
|
||||||
this.ldArgs = new ArrayList<LdArg>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public CompilerMode mode() {
|
|
||||||
return mode;
|
return mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAssembleRequired() {
|
boolean isAssembleRequired() {
|
||||||
return mode.requires(CompilerMode.Assemble);
|
return mode.requires(CompilerMode.Assemble);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isLinkRequired() {
|
boolean isLinkRequired() {
|
||||||
return mode.requires(CompilerMode.Link);
|
return mode.requires(CompilerMode.Link);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String outputFileNameFor(CompilerMode mode) {
|
String outputFileNameFor(CompilerMode mode) {
|
||||||
return this.mode == mode ? outputFileName : null;
|
return this.mode == mode ? outputFileName : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String exeFileName() {
|
String exeFileName() {
|
||||||
return getOutputFileName("");
|
return getOutputFileName("");
|
||||||
}
|
}
|
||||||
|
|
||||||
public String soFileName() {
|
String soFileName() {
|
||||||
return getOutputFileName(".so");
|
return getOutputFileName(".so");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getOutputFileName(String newExt) {
|
private String getOutputFileName(String newExt) {
|
||||||
if (outputFileName != null) {
|
if (outputFileName != null) {
|
||||||
return outputFileName;
|
return outputFileName;
|
||||||
}
|
}
|
||||||
|
@ -68,7 +59,7 @@ class Options {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected List<SourceFile> sourceFiles() {
|
private List<SourceFile> sourceFiles() {
|
||||||
List<SourceFile> result = new ArrayList<SourceFile>();
|
List<SourceFile> result = new ArrayList<SourceFile>();
|
||||||
for (LdArg arg : ldArgs) {
|
for (LdArg arg : ldArgs) {
|
||||||
if (arg.isSourceFile()) {
|
if (arg.isSourceFile()) {
|
||||||
|
@ -78,56 +69,60 @@ class Options {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypeTable typeTable() {
|
Platform platform() {
|
||||||
return this.typeTable;
|
return platform;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LibraryLoader loader() {
|
TypeTable typeTable() {
|
||||||
|
return platform.typeTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
LibraryLoader loader() {
|
||||||
return this.loader;
|
return this.loader;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String outputFileName() {
|
String outputFileName() {
|
||||||
return this.outputFileName;
|
return this.outputFileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isVerboseMode() {
|
boolean isVerboseMode() {
|
||||||
return this.verbose;
|
return this.verbose;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean doesDebugParser() {
|
boolean doesDebugParser() {
|
||||||
return this.debugParser;
|
return this.debugParser;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CodeGeneratorOptions genOptions() {
|
CodeGeneratorOptions genOptions() {
|
||||||
return genOptions;
|
return genOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> asOptions() {
|
List<String> asOptions() {
|
||||||
return this.asOptions;
|
return this.asOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isGeneratingSharedLibrary() {
|
boolean isGeneratingSharedLibrary() {
|
||||||
return this.generatingSharedLibrary;
|
return this.generatingSharedLibrary;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isGeneratingPIE() {
|
boolean isGeneratingPIE() {
|
||||||
return this.generatingPIE;
|
return this.generatingPIE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<LdArg> ldArgs() {
|
List<LdArg> ldArgs() {
|
||||||
return this.ldArgs;
|
return this.ldArgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean noStartFiles() {
|
boolean noStartFiles() {
|
||||||
return this.noStartFiles;
|
return this.noStartFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean noDefaultLibs() {
|
boolean noDefaultLibs() {
|
||||||
return this.noDefaultLibs;
|
return this.noDefaultLibs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns List<SourceFile>. */
|
/** Returns List<SourceFile>. */
|
||||||
public List<SourceFile> parse(List<String> argsList) {
|
List<SourceFile> parse(List<String> argsList) {
|
||||||
List<SourceFile> srcs = new ArrayList<SourceFile>();
|
List<SourceFile> srcs = new ArrayList<SourceFile>();
|
||||||
ListIterator<String> args = argsList.listIterator();
|
ListIterator<String> args = argsList.listIterator();
|
||||||
while (args.hasNext()) {
|
while (args.hasNext()) {
|
||||||
|
@ -253,18 +248,18 @@ class Options {
|
||||||
return srcs;
|
return srcs;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void parseError(String msg) {
|
private void parseError(String msg) {
|
||||||
throw new OptionParseError(msg);
|
throw new OptionParseError(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void addSourceFile(List<SourceFile> srcs, List<LdArg> ldArgs, String sourceName) {
|
private void addSourceFile(List<SourceFile> srcs, List<LdArg> ldArgs, String sourceName) {
|
||||||
SourceFile src = new SourceFile(sourceName);
|
SourceFile src = new SourceFile(sourceName);
|
||||||
srcs.add(src);
|
srcs.add(src);
|
||||||
// Original argument order does matter when linking.
|
// Original argument order does matter when linking.
|
||||||
ldArgs.add(src);
|
ldArgs.add(src);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getOptArg(String opt, ListIterator<String> args) {
|
private String getOptArg(String opt, ListIterator<String> args) {
|
||||||
String path = opt.substring(2);
|
String path = opt.substring(2);
|
||||||
if (path.length() != 0) { // -Ipath
|
if (path.length() != 0) { // -Ipath
|
||||||
return path;
|
return path;
|
||||||
|
@ -274,7 +269,7 @@ class Options {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String nextArg(String opt, ListIterator<String> args) {
|
private String nextArg(String opt, ListIterator<String> args) {
|
||||||
if (! args.hasNext()) {
|
if (! args.hasNext()) {
|
||||||
parseError("missing argument for " + opt);
|
parseError("missing argument for " + opt);
|
||||||
}
|
}
|
||||||
|
@ -282,7 +277,7 @@ class Options {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** "-Wl,-rpath,/usr/local/lib" -> ["-rpath", "/usr/local/lib"] */
|
/** "-Wl,-rpath,/usr/local/lib" -> ["-rpath", "/usr/local/lib"] */
|
||||||
protected List<String> parseCommaSeparatedOptions(String opt) {
|
private List<String> parseCommaSeparatedOptions(String opt) {
|
||||||
List<String> opts = Arrays.asList(opt.split(","));
|
List<String> opts = Arrays.asList(opt.split(","));
|
||||||
opts.remove(0); // remove "-Wl" etc.
|
opts.remove(0); // remove "-Wl" etc.
|
||||||
if (opts.isEmpty()) {
|
if (opts.isEmpty()) {
|
||||||
|
@ -291,7 +286,7 @@ class Options {
|
||||||
return opts;
|
return opts;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void printUsage(PrintStream out) {
|
void printUsage(PrintStream out) {
|
||||||
out.println("Usage: cbc [options] file...");
|
out.println("Usage: cbc [options] file...");
|
||||||
out.println("Global Options:");
|
out.println("Global Options:");
|
||||||
out.println(" --check-syntax Checks syntax and quit.");
|
out.println(" --check-syntax Checks syntax and quit.");
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
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);
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
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,7 +1,7 @@
|
||||||
package net.loveruby.cflat.type;
|
package net.loveruby.cflat.type;
|
||||||
import net.loveruby.cflat.ast.Slot;
|
import net.loveruby.cflat.ast.Slot;
|
||||||
import net.loveruby.cflat.ast.Location;
|
import net.loveruby.cflat.ast.Location;
|
||||||
import net.loveruby.cflat.asm.Assembler;
|
import net.loveruby.cflat.utils.AsmUtils;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class StructType extends CompositeType {
|
public class StructType extends CompositeType {
|
||||||
|
@ -20,12 +20,12 @@ public class StructType extends CompositeType {
|
||||||
long offset = 0;
|
long offset = 0;
|
||||||
long maxAlign = 1;
|
long maxAlign = 1;
|
||||||
for (Slot s : members()) {
|
for (Slot s : members()) {
|
||||||
offset = Assembler.align(offset, s.allocSize());
|
offset = AsmUtils.align(offset, s.allocSize());
|
||||||
s.setOffset(offset);
|
s.setOffset(offset);
|
||||||
offset += s.allocSize();
|
offset += s.allocSize();
|
||||||
maxAlign = Math.max(maxAlign, s.alignment());
|
maxAlign = Math.max(maxAlign, s.alignment());
|
||||||
}
|
}
|
||||||
cachedSize = Assembler.align(offset, maxAlign);
|
cachedSize = AsmUtils.align(offset, maxAlign);
|
||||||
cachedAlign = maxAlign;
|
cachedAlign = maxAlign;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package net.loveruby.cflat.type;
|
package net.loveruby.cflat.type;
|
||||||
import net.loveruby.cflat.ast.Slot;
|
import net.loveruby.cflat.ast.Slot;
|
||||||
import net.loveruby.cflat.ast.Location;
|
import net.loveruby.cflat.ast.Location;
|
||||||
import net.loveruby.cflat.asm.Assembler;
|
import net.loveruby.cflat.utils.AsmUtils;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class UnionType extends CompositeType {
|
public class UnionType extends CompositeType {
|
||||||
|
@ -24,7 +24,7 @@ public class UnionType extends CompositeType {
|
||||||
maxSize = Math.max(maxSize, s.allocSize());
|
maxSize = Math.max(maxSize, s.allocSize());
|
||||||
maxAlign = Math.max(maxAlign, s.alignment());
|
maxAlign = Math.max(maxAlign, s.alignment());
|
||||||
}
|
}
|
||||||
cachedSize = Assembler.align(maxSize, maxAlign);
|
cachedSize = AsmUtils.align(maxSize, maxAlign);
|
||||||
cachedAlign = maxAlign;
|
cachedAlign = maxAlign;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
package net.loveruby.cflat.utils;
|
||||||
|
|
||||||
|
public abstract class AsmUtils {
|
||||||
|
static public long align(long n, long alignment) {
|
||||||
|
return (n + alignment - 1) / alignment * alignment;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue