mirror of https://github.com/aamine/cbc
r4834@macbookpro: aamine | 2009-05-11 03:17:05 +0900
* net/loveruby/cflat/compiler/Compiler.java: objectify assembler. * net/loveruby/cflat/compiler/Compiler.java: objectify linker. * net/loveruby/cflat/compiler/Options.java: provide #assembler, #asOptions, #linker, #ldOptions. * net/loveruby/cflat/sysdep/x86/X86Linux.java -> sysdep/X86Linux.java * net/loveruby/cflat/sysdep/Platform.java: provide #assembler, #linker. * net/loveruby/cflat/sysdep/X86Linux.java: ditto. * net/loveruby/cflat/sysdep/Assembler.java: new interface. * net/loveruby/cflat/sysdep/AssemblerOptions.java: new class. * net/loveruby/cflat/sysdep/GNUAssembler.java: new Assembler implementation. * net/loveruby/cflat/sysdep/Linker.java: new interface. * net/loveruby/cflat/sysdep/LinkerOptions.java: new clas. * net/loveruby/cflat/sysdep/GNULinker.java: new Linker implementation. * net/loveruby/cflat/utils/CommandUtils.java: new class. * net/loveruby/cflat/compiler/LdArg.java -> utils/CommandArg.java * net/loveruby/cflat/compiler/LdOption.java -> utils/CommandArgStr.java * net/loveruby/cflat/compiler/SourceFile.java: implements CommandArg. git-svn-id: file:///Users/aamine/c/gitwork/public/cbc/trunk@4207 1b9489fe-b721-0410-924e-b54b9192deb8
This commit is contained in:
parent
f6c90ab8da
commit
c26eb88f2e
41
ChangeLog
41
ChangeLog
|
|
@ -1,3 +1,44 @@
|
|||
Mon May 11 03:17:32 2009 Minero Aoki <aamine@loveruby.net>
|
||||
|
||||
* net/loveruby/cflat/compiler/Compiler.java: objectify assembler.
|
||||
|
||||
* net/loveruby/cflat/compiler/Compiler.java: objectify linker.
|
||||
|
||||
* net/loveruby/cflat/compiler/Options.java: provide #assembler,
|
||||
#asOptions, #linker, #ldOptions.
|
||||
|
||||
* net/loveruby/cflat/sysdep/x86/X86Linux.java ->
|
||||
sysdep/X86Linux.java
|
||||
|
||||
* net/loveruby/cflat/sysdep/Platform.java: provide #assembler,
|
||||
#linker.
|
||||
|
||||
* net/loveruby/cflat/sysdep/X86Linux.java: ditto.
|
||||
|
||||
* net/loveruby/cflat/sysdep/Assembler.java: new interface.
|
||||
|
||||
* net/loveruby/cflat/sysdep/AssemblerOptions.java: new class.
|
||||
|
||||
* net/loveruby/cflat/sysdep/GNUAssembler.java: new Assembler
|
||||
implementation.
|
||||
|
||||
* net/loveruby/cflat/sysdep/Linker.java: new interface.
|
||||
|
||||
* net/loveruby/cflat/sysdep/LinkerOptions.java: new clas.
|
||||
|
||||
* net/loveruby/cflat/sysdep/GNULinker.java: new Linker
|
||||
implementation.
|
||||
|
||||
* net/loveruby/cflat/utils/CommandUtils.java: new class.
|
||||
|
||||
* net/loveruby/cflat/compiler/LdArg.java -> utils/CommandArg.java
|
||||
|
||||
* net/loveruby/cflat/compiler/LdOption.java ->
|
||||
utils/CommandArgStr.java
|
||||
|
||||
* net/loveruby/cflat/compiler/SourceFile.java: implements
|
||||
CommandArg.
|
||||
|
||||
Mon May 11 01:49:29 2009 Minero Aoki <aamine@loveruby.net>
|
||||
|
||||
* net/loveruby/cflat/parser/Parser.jj: use JDK_VERSION="1.5" to
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ public class Compiler {
|
|||
new Compiler(ProgramName).commandMain(args);
|
||||
}
|
||||
|
||||
protected ErrorHandler errorHandler;
|
||||
private ErrorHandler errorHandler;
|
||||
|
||||
public Compiler(String programName) {
|
||||
this.errorHandler = new ErrorHandler(programName);
|
||||
|
|
@ -67,7 +67,7 @@ public class Compiler {
|
|||
System.exit(1);
|
||||
}
|
||||
|
||||
protected boolean isValidSyntax(SourceFile src, Options opts) {
|
||||
private boolean isValidSyntax(SourceFile src, Options opts) {
|
||||
try {
|
||||
parseFile(src, opts);
|
||||
return true;
|
||||
|
|
@ -82,7 +82,7 @@ public class Compiler {
|
|||
}
|
||||
|
||||
// #@@range/buildTarget{
|
||||
protected void buildTarget(List<SourceFile> srcs, Options opts)
|
||||
public void buildTarget(List<SourceFile> srcs, Options opts)
|
||||
throws CompileException {
|
||||
for (SourceFile src : srcs) {
|
||||
compileFile(src, opts);
|
||||
|
|
@ -97,7 +97,7 @@ public class Compiler {
|
|||
}
|
||||
// #@@}
|
||||
|
||||
protected void compileFile(SourceFile src, Options opts)
|
||||
public void compileFile(SourceFile src, Options opts)
|
||||
throws CompileException {
|
||||
if (src.isCflatSource()) {
|
||||
AST ast = parseFile(src, opts);
|
||||
|
|
@ -163,7 +163,7 @@ public class Compiler {
|
|||
return expr;
|
||||
}
|
||||
|
||||
protected AST parseFile(SourceFile src, Options opts)
|
||||
public AST parseFile(SourceFile src, Options opts)
|
||||
throws SyntaxException, FileException {
|
||||
return Parser.parseFile(new File(src.currentName()),
|
||||
opts.loader(),
|
||||
|
|
@ -171,7 +171,7 @@ public class Compiler {
|
|||
opts.doesDebugParser());
|
||||
}
|
||||
|
||||
protected void semanticAnalysis(AST ast, Options opts)
|
||||
public void semanticAnalysis(AST ast, Options opts)
|
||||
throws SemanticException {
|
||||
new LocalResolver(errorHandler).resolve(ast);
|
||||
new TypeResolver(errorHandler).resolve(ast);
|
||||
|
|
@ -184,129 +184,29 @@ public class Compiler {
|
|||
new TypeChecker(errorHandler).check(ast);
|
||||
}
|
||||
|
||||
protected String generateAssembly(IR ir, Options opts) {
|
||||
public String generateAssembly(IR ir, Options opts) {
|
||||
CodeGenerator gen = opts.codeGenerator(errorHandler);
|
||||
return gen.generate(ir);
|
||||
}
|
||||
|
||||
protected void assemble(String srcPath,
|
||||
private void assemble(String srcPath,
|
||||
String destPath,
|
||||
Options opts) throws IPCException {
|
||||
List<Object> cmd = new ArrayList<Object>();
|
||||
cmd.add("as");
|
||||
cmd.addAll(opts.asOptions());
|
||||
cmd.add("-o");
|
||||
cmd.add(destPath);
|
||||
cmd.add(srcPath);
|
||||
invoke(cmd, opts.isVerboseMode());
|
||||
opts.assembler(errorHandler)
|
||||
.assemble(srcPath, destPath, opts.asOptions());
|
||||
}
|
||||
|
||||
static final protected String DYNAMIC_LINKER = "/lib/ld-linux.so.2";
|
||||
static final protected String C_RUNTIME_INIT = "/usr/lib/crti.o";
|
||||
static final protected String C_RUNTIME_START = "/usr/lib/crt1.o";
|
||||
static final protected String C_RUNTIME_START_PIE = "/usr/lib/Scrt1.o";
|
||||
static final protected String C_RUNTIME_FINI = "/usr/lib/crtn.o";
|
||||
|
||||
protected void generateExecutable(Options opts) throws IPCException {
|
||||
List<Object> cmd = new ArrayList<Object>();
|
||||
cmd.add("ld");
|
||||
cmd.add("-dynamic-linker");
|
||||
cmd.add(DYNAMIC_LINKER);
|
||||
if (opts.isGeneratingPIE()) {
|
||||
cmd.add("-pie");
|
||||
}
|
||||
if (! opts.noStartFiles()) {
|
||||
cmd.add(opts.isGeneratingPIE()
|
||||
? C_RUNTIME_START_PIE
|
||||
: C_RUNTIME_START);
|
||||
cmd.add(C_RUNTIME_INIT);
|
||||
}
|
||||
cmd.addAll(opts.ldArgs());
|
||||
if (! opts.noDefaultLibs()) {
|
||||
cmd.add("-lc");
|
||||
cmd.add("-lcbc");
|
||||
}
|
||||
if (! opts.noStartFiles()) {
|
||||
cmd.add(C_RUNTIME_FINI);
|
||||
}
|
||||
cmd.add("-o");
|
||||
cmd.add(opts.exeFileName());
|
||||
invoke(cmd, opts.isVerboseMode());
|
||||
private void generateExecutable(Options opts) throws IPCException {
|
||||
opts.linker(errorHandler)
|
||||
.generateExecutable(opts.exeFileName(), opts.ldOptions());
|
||||
}
|
||||
|
||||
protected void generateSharedLibrary(Options opts) throws IPCException {
|
||||
List<Object> cmd = new ArrayList<Object>();
|
||||
cmd.add("ld");
|
||||
cmd.add("-shared");
|
||||
if (! opts.noStartFiles()) {
|
||||
cmd.add(C_RUNTIME_INIT);
|
||||
}
|
||||
cmd.addAll(opts.ldArgs());
|
||||
if (! opts.noDefaultLibs()) {
|
||||
cmd.add("-lc");
|
||||
cmd.add("-lcbc");
|
||||
}
|
||||
if (! opts.noStartFiles()) {
|
||||
cmd.add(C_RUNTIME_FINI);
|
||||
}
|
||||
cmd.add("-o");
|
||||
cmd.add(opts.soFileName());
|
||||
invoke(cmd, opts.isVerboseMode());
|
||||
private void generateSharedLibrary(Options opts) throws IPCException {
|
||||
opts.linker(errorHandler)
|
||||
.generateSharedLibrary(opts.soFileName(), opts.ldOptions());
|
||||
}
|
||||
|
||||
protected void invoke(List<Object> cmdArgs, boolean debug) throws IPCException {
|
||||
if (debug) {
|
||||
dumpCommand(cmdArgs);
|
||||
}
|
||||
try {
|
||||
String[] cmd = getStrings(cmdArgs);
|
||||
Process proc = Runtime.getRuntime().exec(cmd);
|
||||
proc.waitFor();
|
||||
passThrough(proc.getInputStream());
|
||||
passThrough(proc.getErrorStream());
|
||||
if (proc.exitValue() != 0) {
|
||||
errorHandler.error(cmd[0] + " failed."
|
||||
+ " (status " + proc.exitValue() + ")");
|
||||
throw new IPCException("compile error");
|
||||
}
|
||||
}
|
||||
catch (InterruptedException ex) {
|
||||
errorHandler.error("gcc interrupted: " + ex.getMessage());
|
||||
throw new IPCException("compile error");
|
||||
}
|
||||
catch (IOException ex) {
|
||||
errorHandler.error(ex.getMessage());
|
||||
throw new IPCException("compile error");
|
||||
}
|
||||
}
|
||||
|
||||
protected String[] getStrings(List<Object> list) {
|
||||
String[] a = new String[list.size()];
|
||||
int idx = 0;
|
||||
for (Object o : list) {
|
||||
a[idx++] = o.toString();
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
protected void dumpCommand(List<Object> args) {
|
||||
String sep = "";
|
||||
for (Object arg : args) {
|
||||
System.out.print(sep); sep = " ";
|
||||
System.out.print(arg.toString());
|
||||
}
|
||||
System.out.println("");
|
||||
}
|
||||
|
||||
protected void passThrough(InputStream s) throws IOException {
|
||||
BufferedReader r = new BufferedReader(new InputStreamReader(s));
|
||||
String line;
|
||||
while ((line = r.readLine()) != null) {
|
||||
System.err.println(line);
|
||||
}
|
||||
}
|
||||
|
||||
protected void writeFile(String path, String str)
|
||||
private void writeFile(String path, String str)
|
||||
throws FileException {
|
||||
try {
|
||||
BufferedWriter f = new BufferedWriter(
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
package net.loveruby.cflat.compiler;
|
||||
|
||||
// package private
|
||||
interface LdArg {
|
||||
abstract public String toString();
|
||||
abstract public boolean isSourceFile();
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
package net.loveruby.cflat.compiler;
|
||||
|
||||
// package private
|
||||
class LdOption implements LdArg {
|
||||
protected String option;
|
||||
|
||||
public LdOption(String option) {
|
||||
this.option = option;
|
||||
}
|
||||
|
||||
public boolean isSourceFile() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return this.option;
|
||||
}
|
||||
}
|
||||
|
|
@ -3,13 +3,13 @@ import net.loveruby.cflat.parser.LibraryLoader;
|
|||
import net.loveruby.cflat.type.TypeTable;
|
||||
import net.loveruby.cflat.asm.*;
|
||||
import net.loveruby.cflat.sysdep.*;
|
||||
import net.loveruby.cflat.sysdep.x86.X86Linux;
|
||||
import net.loveruby.cflat.sysdep.X86Linux;
|
||||
import net.loveruby.cflat.utils.CommandArg;
|
||||
import net.loveruby.cflat.utils.ErrorHandler;
|
||||
import net.loveruby.cflat.exception.*;
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
|
||||
// package scope
|
||||
class Options {
|
||||
CompilerMode mode;
|
||||
LibraryLoader loader = new LibraryLoader();
|
||||
|
|
@ -18,12 +18,8 @@ class Options {
|
|||
boolean verbose = false;
|
||||
boolean debugParser = false;
|
||||
CodeGeneratorOptions genOptions = new CodeGeneratorOptions();
|
||||
List<String> asOptions = new ArrayList<String>();
|
||||
boolean generatingSharedLibrary = false;
|
||||
boolean generatingPIE = false;
|
||||
List<LdArg> ldArgs = new ArrayList<LdArg>();
|
||||
boolean noStartFiles = false;
|
||||
boolean noDefaultLibs = false;
|
||||
AssemblerOptions asOptions = new AssemblerOptions();
|
||||
LinkerOptions ldOptions = new LinkerOptions();
|
||||
|
||||
CompilerMode mode() {
|
||||
return mode;
|
||||
|
|
@ -64,7 +60,7 @@ class Options {
|
|||
|
||||
private List<SourceFile> sourceFiles() {
|
||||
List<SourceFile> result = new ArrayList<SourceFile>();
|
||||
for (LdArg arg : ldArgs) {
|
||||
for (CommandArg arg : ldOptions.args()) {
|
||||
if (arg.isSourceFile()) {
|
||||
result.add((SourceFile)arg);
|
||||
}
|
||||
|
|
@ -72,22 +68,6 @@ class Options {
|
|||
return result;
|
||||
}
|
||||
|
||||
Platform platform() {
|
||||
return platform;
|
||||
}
|
||||
|
||||
TypeTable typeTable() {
|
||||
return platform.typeTable();
|
||||
}
|
||||
|
||||
CodeGenerator codeGenerator(ErrorHandler errorHandler) {
|
||||
return platform.codeGenerator(genOptions, errorHandler);
|
||||
}
|
||||
|
||||
LibraryLoader loader() {
|
||||
return this.loader;
|
||||
}
|
||||
|
||||
String outputFileName() {
|
||||
return this.outputFileName;
|
||||
}
|
||||
|
|
@ -100,28 +80,36 @@ class Options {
|
|||
return this.debugParser;
|
||||
}
|
||||
|
||||
List<String> asOptions() {
|
||||
return this.asOptions;
|
||||
LibraryLoader loader() {
|
||||
return this.loader;
|
||||
}
|
||||
|
||||
TypeTable typeTable() {
|
||||
return platform.typeTable();
|
||||
}
|
||||
|
||||
CodeGenerator codeGenerator(ErrorHandler h) {
|
||||
return platform.codeGenerator(genOptions, h);
|
||||
}
|
||||
|
||||
Assembler assembler(ErrorHandler h) {
|
||||
return platform.assembler(h);
|
||||
}
|
||||
|
||||
AssemblerOptions asOptions() {
|
||||
return asOptions;
|
||||
}
|
||||
|
||||
Linker linker(ErrorHandler h) {
|
||||
return platform.linker(h);
|
||||
}
|
||||
|
||||
LinkerOptions ldOptions() {
|
||||
return ldOptions;
|
||||
}
|
||||
|
||||
boolean isGeneratingSharedLibrary() {
|
||||
return this.generatingSharedLibrary;
|
||||
}
|
||||
|
||||
boolean isGeneratingPIE() {
|
||||
return this.generatingPIE;
|
||||
}
|
||||
|
||||
List<LdArg> ldArgs() {
|
||||
return this.ldArgs;
|
||||
}
|
||||
|
||||
boolean noStartFiles() {
|
||||
return this.noStartFiles;
|
||||
}
|
||||
|
||||
boolean noDefaultLibs() {
|
||||
return this.noDefaultLibs;
|
||||
return ldOptions.generatingSharedLibrary;
|
||||
}
|
||||
|
||||
/** Returns List<SourceFile>. */
|
||||
|
|
@ -170,54 +158,58 @@ class Options {
|
|||
genOptions.generateVerboseAsm();
|
||||
}
|
||||
else if (arg.startsWith("-Wa,")) {
|
||||
asOptions.addAll(parseCommaSeparatedOptions(arg));
|
||||
for (String a : parseCommaSeparatedOptions(arg)) {
|
||||
asOptions.addArg(a);
|
||||
}
|
||||
}
|
||||
else if (arg.equals("-Xassembler")) {
|
||||
asOptions.add(nextArg(arg, args));
|
||||
asOptions.addArg(nextArg(arg, args));
|
||||
}
|
||||
else if (arg.equals("-static")) {
|
||||
ldArgs.add(new LdOption(arg));
|
||||
ldOptions.addArg(arg);
|
||||
}
|
||||
else if (arg.equals("-shared")) {
|
||||
generatingSharedLibrary = true;
|
||||
ldOptions.generatingSharedLibrary = true;
|
||||
}
|
||||
else if (arg.equals("-pie")) {
|
||||
generatingPIE = true;
|
||||
ldOptions.generatingPIE = true;
|
||||
}
|
||||
else if (arg.equals("--readonly-plt")) {
|
||||
ldArgs.add(new LdOption("-z"));
|
||||
ldArgs.add(new LdOption("combreloc"));
|
||||
ldArgs.add(new LdOption("-z"));
|
||||
ldArgs.add(new LdOption("now"));
|
||||
ldArgs.add(new LdOption("-z"));
|
||||
ldArgs.add(new LdOption("relro"));
|
||||
ldOptions.addArg("-z");
|
||||
ldOptions.addArg("combreloc");
|
||||
ldOptions.addArg("-z");
|
||||
ldOptions.addArg("now");
|
||||
ldOptions.addArg("-z");
|
||||
ldOptions.addArg("relro");
|
||||
}
|
||||
else if (arg.startsWith("-L")) {
|
||||
ldArgs.add(new LdOption("-L" + getOptArg(arg, args)));
|
||||
ldOptions.addArg("-L" + getOptArg(arg, args));
|
||||
}
|
||||
else if (arg.startsWith("-l")) {
|
||||
ldArgs.add(new LdOption("-l" + getOptArg(arg, args)));
|
||||
ldOptions.addArg("-l" + getOptArg(arg, args));
|
||||
}
|
||||
else if (arg.equals("-nostartfiles")) {
|
||||
noStartFiles = true;
|
||||
ldOptions.noStartFiles = true;
|
||||
}
|
||||
else if (arg.equals("-nodefaultlibs")) {
|
||||
noDefaultLibs = true;
|
||||
ldOptions.noDefaultLibs = true;
|
||||
}
|
||||
else if (arg.equals("-nostdlib")) {
|
||||
noStartFiles = true;
|
||||
noDefaultLibs = true;
|
||||
ldOptions.noStartFiles = true;
|
||||
ldOptions.noDefaultLibs = true;
|
||||
}
|
||||
else if (arg.startsWith("-Wl,")) {
|
||||
for (String opt : parseCommaSeparatedOptions(arg)) {
|
||||
ldArgs.add(new LdOption(opt));
|
||||
ldOptions.addArg(opt);
|
||||
}
|
||||
}
|
||||
else if (arg.equals("-Xlinker")) {
|
||||
ldArgs.add(new LdOption(nextArg(arg, args)));
|
||||
ldOptions.addArg(nextArg(arg, args));
|
||||
}
|
||||
else if (arg.equals("-v")) {
|
||||
verbose = true;
|
||||
asOptions.verbose = true;
|
||||
ldOptions.verbose = true;
|
||||
}
|
||||
else if (arg.equals("--version")) {
|
||||
System.out.printf("%s version %s",
|
||||
|
|
@ -234,12 +226,12 @@ class Options {
|
|||
}
|
||||
else {
|
||||
// source file
|
||||
addSourceFile(srcs, ldArgs, arg);
|
||||
addSourceFile(srcs, arg);
|
||||
}
|
||||
}
|
||||
// args has more arguments when "--" is appeared.
|
||||
while (args.hasNext()) {
|
||||
addSourceFile(srcs, ldArgs, args.next());
|
||||
addSourceFile(srcs, args.next());
|
||||
}
|
||||
if (srcs.isEmpty()) parseError("no input file");
|
||||
if (mode == null) {
|
||||
|
|
@ -255,11 +247,11 @@ class Options {
|
|||
throw new OptionParseError(msg);
|
||||
}
|
||||
|
||||
private void addSourceFile(List<SourceFile> srcs, List<LdArg> ldArgs, String sourceName) {
|
||||
private void addSourceFile(List<SourceFile> srcs, String sourceName) {
|
||||
SourceFile src = new SourceFile(sourceName);
|
||||
srcs.add(src);
|
||||
// Original argument order does matter when linking.
|
||||
ldArgs.add(src);
|
||||
ldOptions.addArg(src);
|
||||
}
|
||||
|
||||
private String getOptArg(String opt, ListIterator<String> args) {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
package net.loveruby.cflat.compiler;
|
||||
import net.loveruby.cflat.utils.CommandArg;
|
||||
import java.io.File;
|
||||
|
||||
// package private
|
||||
class SourceFile implements LdArg {
|
||||
protected String originalName;
|
||||
protected String currentName;
|
||||
class SourceFile implements CommandArg {
|
||||
private String originalName;
|
||||
private String currentName;
|
||||
|
||||
public SourceFile(String name) {
|
||||
this.originalName = name;
|
||||
|
|
@ -63,19 +64,19 @@ class SourceFile implements LdArg {
|
|||
return or(opts.outputFileName, replaceExt(newExt));
|
||||
}
|
||||
|
||||
protected String or(String x, String y) {
|
||||
private String or(String x, String y) {
|
||||
return x != null ? x : y;
|
||||
}
|
||||
|
||||
protected String replaceExt(String ext) {
|
||||
private String replaceExt(String ext) {
|
||||
return baseName(originalName, true) + ext;
|
||||
}
|
||||
|
||||
protected String baseName(String path) {
|
||||
private String baseName(String path) {
|
||||
return new File(path).getName();
|
||||
}
|
||||
|
||||
protected String baseName(String path, boolean stripExt) {
|
||||
private String baseName(String path, boolean stripExt) {
|
||||
if (stripExt) {
|
||||
return new File(path).getName().replaceFirst("\\.[^.]*$", "");
|
||||
}
|
||||
|
|
@ -84,7 +85,7 @@ class SourceFile implements LdArg {
|
|||
}
|
||||
}
|
||||
|
||||
protected String extName(String path) {
|
||||
private String extName(String path) {
|
||||
int idx = path.lastIndexOf(".");
|
||||
if (idx < 0) return "";
|
||||
return path.substring(idx);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
package net.loveruby.cflat.sysdep;
|
||||
import net.loveruby.cflat.exception.IPCException;
|
||||
|
||||
public interface Assembler {
|
||||
void assemble(String srcPath, String destPath,
|
||||
AssemblerOptions opts) throws IPCException;
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package net.loveruby.cflat.sysdep;
|
||||
import net.loveruby.cflat.utils.CommandArg;
|
||||
import net.loveruby.cflat.utils.CommandArgStr;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class AssemblerOptions {
|
||||
public boolean verbose = false;
|
||||
List<CommandArg> args = new ArrayList<CommandArg>();
|
||||
|
||||
public void addArg(String a) {
|
||||
args.add(new CommandArgStr(a));
|
||||
}
|
||||
|
||||
public void addArg(CommandArg a) {
|
||||
args.add(a);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package net.loveruby.cflat.sysdep;
|
||||
import net.loveruby.cflat.utils.CommandUtils;
|
||||
import net.loveruby.cflat.utils.CommandArg;
|
||||
import net.loveruby.cflat.utils.CommandArgStr;
|
||||
import net.loveruby.cflat.utils.ErrorHandler;
|
||||
import net.loveruby.cflat.exception.IPCException;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
class GNUAssembler implements Assembler {
|
||||
ErrorHandler errorHandler;
|
||||
|
||||
GNUAssembler(ErrorHandler h) {
|
||||
this.errorHandler = h;
|
||||
}
|
||||
|
||||
public void assemble(String srcPath, String destPath,
|
||||
AssemblerOptions opts) throws IPCException {
|
||||
List<CommandArg> cmd = new ArrayList<CommandArg>();
|
||||
cmd.add(arg("as"));
|
||||
cmd.addAll(opts.args);
|
||||
cmd.add(arg("-o"));
|
||||
cmd.add(arg(destPath));
|
||||
cmd.add(arg(srcPath));
|
||||
CommandUtils.invoke(cmd, errorHandler, opts.verbose);
|
||||
}
|
||||
|
||||
private CommandArg arg(String a) {
|
||||
return new CommandArgStr(a);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
package net.loveruby.cflat.sysdep;
|
||||
import net.loveruby.cflat.utils.CommandUtils;
|
||||
import net.loveruby.cflat.utils.CommandArg;
|
||||
import net.loveruby.cflat.utils.CommandArgStr;
|
||||
import net.loveruby.cflat.utils.ErrorHandler;
|
||||
import net.loveruby.cflat.exception.IPCException;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
class GNULinker implements Linker {
|
||||
static final protected String DYNAMIC_LINKER = "/lib/ld-linux.so.2";
|
||||
static final protected String C_RUNTIME_INIT = "/usr/lib/crti.o";
|
||||
static final protected String C_RUNTIME_START = "/usr/lib/crt1.o";
|
||||
static final protected String C_RUNTIME_START_PIE = "/usr/lib/Scrt1.o";
|
||||
static final protected String C_RUNTIME_FINI = "/usr/lib/crtn.o";
|
||||
|
||||
ErrorHandler errorHandler;
|
||||
|
||||
GNULinker(ErrorHandler errorHandler) {
|
||||
this.errorHandler = errorHandler;
|
||||
}
|
||||
|
||||
public void generateExecutable(
|
||||
String destPath, LinkerOptions opts) throws IPCException {
|
||||
List<CommandArg> cmd = new ArrayList<CommandArg>();
|
||||
cmd.add(arg("ld"));
|
||||
cmd.add(arg("-dynamic-linker"));
|
||||
cmd.add(arg(DYNAMIC_LINKER));
|
||||
if (opts.generatingPIE) {
|
||||
cmd.add(arg("-pie"));
|
||||
}
|
||||
if (! opts.noStartFiles) {
|
||||
cmd.add(arg(opts.generatingPIE
|
||||
? C_RUNTIME_START_PIE
|
||||
: C_RUNTIME_START));
|
||||
cmd.add(arg(C_RUNTIME_INIT));
|
||||
}
|
||||
cmd.addAll(opts.args);
|
||||
if (! opts.noDefaultLibs) {
|
||||
cmd.add(arg("-lc"));
|
||||
cmd.add(arg("-lcbc"));
|
||||
}
|
||||
if (! opts.noStartFiles) {
|
||||
cmd.add(arg(C_RUNTIME_FINI));
|
||||
}
|
||||
cmd.add(arg("-o"));
|
||||
cmd.add(arg(destPath));
|
||||
CommandUtils.invoke(cmd, errorHandler, opts.verbose);
|
||||
}
|
||||
|
||||
public void generateSharedLibrary(
|
||||
String destPath, LinkerOptions opts) throws IPCException {
|
||||
List<CommandArg> cmd = new ArrayList<CommandArg>();
|
||||
cmd.add(arg("ld"));
|
||||
cmd.add(arg("-shared"));
|
||||
if (! opts.noStartFiles) {
|
||||
cmd.add(arg(C_RUNTIME_INIT));
|
||||
}
|
||||
cmd.addAll(opts.args);
|
||||
if (! opts.noDefaultLibs) {
|
||||
cmd.add(arg("-lc"));
|
||||
cmd.add(arg("-lcbc"));
|
||||
}
|
||||
if (! opts.noStartFiles) {
|
||||
cmd.add(arg(C_RUNTIME_FINI));
|
||||
}
|
||||
cmd.add(arg("-o"));
|
||||
cmd.add(arg(destPath));
|
||||
CommandUtils.invoke(cmd, errorHandler, opts.verbose);
|
||||
}
|
||||
|
||||
private CommandArg arg(String a) {
|
||||
return new CommandArgStr(a);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package net.loveruby.cflat.sysdep;
|
||||
import net.loveruby.cflat.exception.IPCException;
|
||||
|
||||
public interface Linker {
|
||||
void generateExecutable(String destPath, LinkerOptions opts) throws IPCException;
|
||||
void generateSharedLibrary(String destPath, LinkerOptions opts) throws IPCException;
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package net.loveruby.cflat.sysdep;
|
||||
import net.loveruby.cflat.utils.CommandArg;
|
||||
import net.loveruby.cflat.utils.CommandArgStr;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class LinkerOptions {
|
||||
public boolean generatingSharedLibrary = false;
|
||||
public boolean generatingPIE = false;
|
||||
public boolean noStartFiles = false;
|
||||
public boolean noDefaultLibs = false;
|
||||
public boolean verbose = false;
|
||||
List<CommandArg> args = new ArrayList<CommandArg>();
|
||||
|
||||
public void addArg(String a) {
|
||||
args.add(new CommandArgStr(a));
|
||||
}
|
||||
|
||||
public void addArg(CommandArg a) {
|
||||
args.add(a);
|
||||
}
|
||||
|
||||
public List<CommandArg> args() {
|
||||
return this.args;
|
||||
}
|
||||
}
|
||||
|
|
@ -5,4 +5,6 @@ import net.loveruby.cflat.utils.ErrorHandler;
|
|||
public interface Platform {
|
||||
TypeTable typeTable();
|
||||
CodeGenerator codeGenerator(CodeGeneratorOptions opts, ErrorHandler h);
|
||||
Assembler assembler(ErrorHandler h);
|
||||
Linker linker(ErrorHandler h);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
package net.loveruby.cflat.sysdep.x86;
|
||||
import net.loveruby.cflat.sysdep.Platform;
|
||||
import net.loveruby.cflat.sysdep.CodeGeneratorOptions;
|
||||
package net.loveruby.cflat.sysdep;
|
||||
import net.loveruby.cflat.utils.ErrorHandler;
|
||||
import net.loveruby.cflat.type.TypeTable;
|
||||
|
||||
|
|
@ -11,6 +9,14 @@ public class X86Linux implements Platform {
|
|||
|
||||
public CodeGenerator codeGenerator(
|
||||
CodeGeneratorOptions opts, ErrorHandler h) {
|
||||
return new CodeGenerator(opts, h);
|
||||
return new net.loveruby.cflat.sysdep.x86.CodeGenerator(opts, h);
|
||||
}
|
||||
|
||||
public Assembler assembler(ErrorHandler h) {
|
||||
return new GNUAssembler(h);
|
||||
}
|
||||
|
||||
public Linker linker(ErrorHandler h) {
|
||||
return new GNULinker(h);
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ import net.loveruby.cflat.utils.AsmUtils;
|
|||
import net.loveruby.cflat.utils.ErrorHandler;
|
||||
import java.util.*;
|
||||
|
||||
class CodeGenerator
|
||||
public class CodeGenerator
|
||||
implements net.loveruby.cflat.sysdep.CodeGenerator,
|
||||
IRVisitor<Void,Void>,
|
||||
ELFConstants {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
package net.loveruby.cflat.utils;
|
||||
|
||||
public interface CommandArg {
|
||||
public String toString();
|
||||
public boolean isSourceFile();
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package net.loveruby.cflat.utils;
|
||||
|
||||
public class CommandArgStr implements CommandArg {
|
||||
private String arg;
|
||||
|
||||
public CommandArgStr(String arg) {
|
||||
this.arg = arg;
|
||||
}
|
||||
|
||||
public boolean isSourceFile() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return arg;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
package net.loveruby.cflat.utils;
|
||||
import net.loveruby.cflat.exception.IPCException;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.io.*;
|
||||
|
||||
abstract public class CommandUtils {
|
||||
static public void invoke(List<CommandArg> cmdArgs,
|
||||
ErrorHandler errorHandler, boolean debug) throws IPCException {
|
||||
if (debug) {
|
||||
dumpCommand(cmdArgs);
|
||||
}
|
||||
try {
|
||||
String[] cmd = getStrings(cmdArgs);
|
||||
Process proc = Runtime.getRuntime().exec(cmd);
|
||||
proc.waitFor();
|
||||
passThrough(proc.getInputStream());
|
||||
passThrough(proc.getErrorStream());
|
||||
if (proc.exitValue() != 0) {
|
||||
errorHandler.error(cmd[0] + " failed."
|
||||
+ " (status " + proc.exitValue() + ")");
|
||||
throw new IPCException("compile error");
|
||||
}
|
||||
}
|
||||
catch (InterruptedException ex) {
|
||||
errorHandler.error("gcc interrupted: " + ex.getMessage());
|
||||
throw new IPCException("compile error");
|
||||
}
|
||||
catch (IOException ex) {
|
||||
errorHandler.error(ex.getMessage());
|
||||
throw new IPCException("compile error");
|
||||
}
|
||||
}
|
||||
|
||||
static private String[] getStrings(List<CommandArg> list) {
|
||||
String[] result = new String[list.size()];
|
||||
int idx = 0;
|
||||
for (CommandArg arg : list) {
|
||||
result[idx++] = arg.toString();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static private void dumpCommand(List<CommandArg> args) {
|
||||
String sep = "";
|
||||
for (CommandArg arg : args) {
|
||||
System.out.print(sep); sep = " ";
|
||||
System.out.print(arg.toString());
|
||||
}
|
||||
System.out.println("");
|
||||
}
|
||||
|
||||
static private void passThrough(InputStream s) throws IOException {
|
||||
BufferedReader r = new BufferedReader(new InputStreamReader(s));
|
||||
String line;
|
||||
while ((line = r.readLine()) != null) {
|
||||
System.err.println(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue