mirror of https://github.com/aamine/cbc
* net/loveruby/cflat/compiler/CodeGenerator.java: should access file-local gvar directly (with @GOTOFF) in PIE.
* net/loveruby/cflat/ast/Entity.java: all entities should have memref or address. * net/loveruby/cflat/ast/Variable.java: ditto. * net/loveruby/cflat/ast/DefinedVariable.java: ditto. * net/loveruby/cflat/ast/UndefinedVariable.java: ditto. * net/loveruby/cflat/ast/Function.java: ditto. * net/loveruby/cflat/ast/DefinedFunction.java: ditto. * import/stdlib.hb: add new declarations. * import/unistd.hb: add new declarations. git-svn-id: file:///Users/aamine/c/gitwork/public/cbc/trunk@4082 1b9489fe-b721-0410-924e-b54b9192deb8
This commit is contained in:
parent
6b24625a87
commit
aa030b42b7
22
ChangeLog
22
ChangeLog
|
@ -1,3 +1,25 @@
|
|||
Sun Nov 16 20:01:06 2008 Minero Aoki <aamine@loveruby.net>
|
||||
|
||||
* net/loveruby/cflat/compiler/CodeGenerator.java: should access
|
||||
file-local gvar directly (with @GOTOFF) in PIE.
|
||||
|
||||
* net/loveruby/cflat/ast/Entity.java: all entities should have
|
||||
memref or address.
|
||||
|
||||
* net/loveruby/cflat/ast/Variable.java: ditto.
|
||||
|
||||
* net/loveruby/cflat/ast/DefinedVariable.java: ditto.
|
||||
|
||||
* net/loveruby/cflat/ast/UndefinedVariable.java: ditto.
|
||||
|
||||
* net/loveruby/cflat/ast/Function.java: ditto.
|
||||
|
||||
* net/loveruby/cflat/ast/DefinedFunction.java: ditto.
|
||||
|
||||
* import/stdlib.hb: add new declarations.
|
||||
|
||||
* import/unistd.hb: add new declarations.
|
||||
|
||||
Sun Nov 2 18:27:01 2008 Minero Aoki <aamine@loveruby.net>
|
||||
|
||||
* net/loveruby/cflat/compiler/Options.java: new option
|
||||
|
|
2
ToDo
2
ToDo
|
@ -6,9 +6,9 @@
|
|||
* "extern char*[] sys_errlist" is array, not pointer
|
||||
* &puts should be typed as int(*)(char*)*, not int(*)(char*)**
|
||||
* check opassign semantic as operator
|
||||
* use enum for compiler mode.
|
||||
* -fPIE, -pie
|
||||
* implement difference against PIC
|
||||
* remove all FIXME
|
||||
|
||||
== Done
|
||||
|
||||
|
|
|
@ -1 +1,9 @@
|
|||
// stdlib.hb
|
||||
|
||||
import stddef; // for size_t
|
||||
|
||||
extern void exit(int status);
|
||||
extern void* calloc(size_t nmemb, size_t size);
|
||||
extern void* malloc(size_t size);
|
||||
extern void free(void* ptr);
|
||||
extern void* realloc(void* ptr, size_t size);
|
||||
|
|
|
@ -6,3 +6,4 @@ extern void _exit(int status);
|
|||
extern pid_t fork(void);
|
||||
extern pid_t getpid(void);
|
||||
extern pid_t getppid(void);
|
||||
extern unsigned int sleep(unsigned int secs);
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.compiler.ErrorHandler;
|
||||
import net.loveruby.cflat.type.*;
|
||||
import net.loveruby.cflat.asm.Symbol;
|
||||
import net.loveruby.cflat.asm.BaseSymbol;
|
||||
import net.loveruby.cflat.asm.Label;
|
||||
import net.loveruby.cflat.exception.*;
|
||||
import java.util.*;
|
||||
|
|
|
@ -23,16 +23,6 @@ public class DefinedVariable extends Variable {
|
|||
this.sequence = seq;
|
||||
}
|
||||
|
||||
public Symbol symbol() {
|
||||
if (symbol != null) {
|
||||
return symbol;
|
||||
}
|
||||
else {
|
||||
symbol = new NamedSymbol(symbolString());
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
|
||||
public String symbolString() {
|
||||
return (sequence < 0) ? name : (name + "." + sequence);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.type.*;
|
||||
import net.loveruby.cflat.asm.Symbol;
|
||||
import net.loveruby.cflat.asm.NamedSymbol;
|
||||
import net.loveruby.cflat.asm.AsmOperand;
|
||||
import net.loveruby.cflat.asm.MemoryReference;
|
||||
|
||||
|
@ -10,6 +9,8 @@ abstract public class Entity extends Node {
|
|||
protected boolean isPrivate;
|
||||
protected TypeNode typeNode;
|
||||
protected long nRefered;
|
||||
protected MemoryReference memref;
|
||||
protected MemoryReference address;
|
||||
|
||||
public Entity(boolean priv, TypeNode type, String name) {
|
||||
this.name = name;
|
||||
|
@ -22,8 +23,8 @@ abstract public class Entity extends Node {
|
|||
return name;
|
||||
}
|
||||
|
||||
public Symbol symbol() {
|
||||
return new NamedSymbol(name);
|
||||
public String symbolString() {
|
||||
return name();
|
||||
}
|
||||
|
||||
abstract public boolean isDefined();
|
||||
|
@ -61,8 +62,29 @@ abstract public class Entity extends Node {
|
|||
|
||||
abstract public boolean cannotLoad();
|
||||
|
||||
abstract public MemoryReference memref();
|
||||
abstract public AsmOperand address();
|
||||
public void setMemref(MemoryReference mem) {
|
||||
this.memref = mem;
|
||||
}
|
||||
|
||||
public MemoryReference memref() {
|
||||
checkAddress();
|
||||
return memref;
|
||||
}
|
||||
|
||||
public void setAddress(MemoryReference mem) {
|
||||
this.address = mem;
|
||||
}
|
||||
|
||||
public AsmOperand address() {
|
||||
checkAddress();
|
||||
return address;
|
||||
}
|
||||
|
||||
protected void checkAddress() {
|
||||
if (memref == null && address == null) {
|
||||
throw new Error("address did not resolved: " + name);
|
||||
}
|
||||
}
|
||||
|
||||
public Location location() {
|
||||
return typeNode.location();
|
||||
|
|
|
@ -1,16 +1,12 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.type.*;
|
||||
import net.loveruby.cflat.asm.Label;
|
||||
import net.loveruby.cflat.asm.Symbol;
|
||||
import net.loveruby.cflat.asm.NamedSymbol;
|
||||
import net.loveruby.cflat.asm.AsmOperand;
|
||||
import net.loveruby.cflat.asm.MemoryReference;
|
||||
import net.loveruby.cflat.asm.Label;
|
||||
import java.util.*;
|
||||
|
||||
abstract public class Function extends Entity {
|
||||
protected Symbol symbol;
|
||||
protected Symbol callingSymbol;
|
||||
protected Label label;
|
||||
protected AsmOperand address;
|
||||
|
||||
public Function(boolean priv, TypeNode t, String name) {
|
||||
super(priv, t, name);
|
||||
|
@ -37,18 +33,18 @@ abstract public class Function extends Entity {
|
|||
return true;
|
||||
}
|
||||
|
||||
public void setSymbol(Symbol sym) {
|
||||
if (this.symbol != null) {
|
||||
throw new Error("must not happen: Function#symbol was set again");
|
||||
public void setCallingSymbol(Symbol sym) {
|
||||
if (this.callingSymbol != null) {
|
||||
throw new Error("must not happen: Function#callingSymbol was set again");
|
||||
}
|
||||
this.symbol = sym;
|
||||
this.callingSymbol = sym;
|
||||
}
|
||||
|
||||
public Symbol symbol() {
|
||||
if (this.symbol == null) {
|
||||
throw new Error("must not happen: Function#symbol called but null");
|
||||
public Symbol callingSymbol() {
|
||||
if (this.callingSymbol == null) {
|
||||
throw new Error("must not happen: Function#callingSymbol called but null");
|
||||
}
|
||||
return this.symbol;
|
||||
return this.callingSymbol;
|
||||
}
|
||||
|
||||
public Label label() {
|
||||
|
@ -56,22 +52,7 @@ abstract public class Function extends Entity {
|
|||
return label;
|
||||
}
|
||||
else {
|
||||
return label = new Label(symbol());
|
||||
return label = new Label(callingSymbol());
|
||||
}
|
||||
}
|
||||
|
||||
public MemoryReference memref() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setAddress(AsmOperand addr) {
|
||||
this.address = addr;
|
||||
}
|
||||
|
||||
public AsmOperand address() {
|
||||
if (address == null) {
|
||||
throw new Error("must not happen: Function.address == null");
|
||||
}
|
||||
return this.address;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,10 +10,6 @@ public class UndefinedVariable extends Variable {
|
|||
public boolean isPrivate() { return false; }
|
||||
public boolean isInitialized() { return false; }
|
||||
|
||||
public String symbolString() {
|
||||
return name();
|
||||
}
|
||||
|
||||
protected void _dump(Dumper d) {
|
||||
d.printMember("name", name);
|
||||
d.printMember("isPrivate", isPrivate());
|
||||
|
|
|
@ -1,43 +1,12 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.type.*;
|
||||
import net.loveruby.cflat.asm.AsmOperand;
|
||||
import net.loveruby.cflat.asm.MemoryReference;
|
||||
|
||||
abstract public class Variable extends Entity {
|
||||
protected MemoryReference memref;
|
||||
protected MemoryReference address;
|
||||
|
||||
public Variable(boolean priv, TypeNode type, String name) {
|
||||
super(priv, type, name);
|
||||
}
|
||||
|
||||
abstract public String symbolString();
|
||||
|
||||
public boolean cannotLoad() {
|
||||
return type().isAllocatedArray();
|
||||
}
|
||||
|
||||
public void setMemref(MemoryReference mem) {
|
||||
this.memref = mem;
|
||||
}
|
||||
|
||||
public MemoryReference memref() {
|
||||
checkAddress();
|
||||
return memref;
|
||||
}
|
||||
|
||||
public void setAddress(MemoryReference mem) {
|
||||
this.address = mem;
|
||||
}
|
||||
|
||||
public AsmOperand address() {
|
||||
checkAddress();
|
||||
return address;
|
||||
}
|
||||
|
||||
protected void checkAddress() {
|
||||
if (memref == null && address == null) {
|
||||
throw new Error("address did not resolved: " + name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@ public class CodeGenerator
|
|||
compileCommonSymbol(var);
|
||||
}
|
||||
// others
|
||||
if (options.isPICRequired()) {
|
||||
if (options.isPositionIndependent()) {
|
||||
PICThunk(GOTBaseReg());
|
||||
}
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ public class CodeGenerator
|
|||
|
||||
protected void locateConstant(ConstantEntry ent, SymbolTable symbols) {
|
||||
ent.setSymbol(symbols.newSymbol());
|
||||
if (options.isPICRequired()) {
|
||||
if (options.isPositionIndependent()) {
|
||||
Symbol offset = localGOTSymbol(ent.symbol());
|
||||
ent.setMemref(mem(offset, GOTBaseReg()));
|
||||
}
|
||||
|
@ -99,52 +99,49 @@ public class CodeGenerator
|
|||
}
|
||||
}
|
||||
|
||||
protected void locateGlobalVariable(Variable var) {
|
||||
MemoryReference mem;
|
||||
if (options.isPICRequired()) {
|
||||
if (var.isPrivate()) {
|
||||
mem = mem(localGOTSymbol(var.symbol()), GOTBaseReg());
|
||||
var.setMemref(mem);
|
||||
protected void locateGlobalVariable(Entity ent) {
|
||||
Symbol sym = ent.isPrivate() ? privateSymbol(ent.symbolString())
|
||||
: globalSymbol(ent.symbolString());
|
||||
if (options.isPositionIndependent()) {
|
||||
MemoryReference mem;
|
||||
if (ent.isPrivate() || optimizeGvarAccess(ent)) {
|
||||
mem = mem(localGOTSymbol(sym), GOTBaseReg());
|
||||
ent.setMemref(mem);
|
||||
}
|
||||
else {
|
||||
mem = mem(globalGOTSymbol(var.symbol()), GOTBaseReg());
|
||||
var.setAddress(mem);
|
||||
mem = mem(globalGOTSymbol(sym), GOTBaseReg());
|
||||
ent.setAddress(mem);
|
||||
}
|
||||
}
|
||||
else {
|
||||
mem = mem(globalSymbol(var.symbolString()));
|
||||
var.setMemref(mem);
|
||||
ent.setMemref(mem(sym));
|
||||
}
|
||||
}
|
||||
|
||||
protected void locateFunction(Function func) {
|
||||
func.setSymbol(functionSymbol(func));
|
||||
func.setAddress(functionAddress(func));
|
||||
func.setCallingSymbol(callingSymbol(func));
|
||||
locateGlobalVariable(func);
|
||||
}
|
||||
|
||||
protected Symbol functionSymbol(Function func) {
|
||||
if (func.isDefined()) {
|
||||
return globalSymbol(func.name());
|
||||
protected Symbol callingSymbol(Function func) {
|
||||
if (func.isPrivate()) {
|
||||
return privateSymbol(func.symbolString());
|
||||
}
|
||||
else {
|
||||
Symbol sym = privateSymbol(func.name());
|
||||
return options.isPICRequired() ? PLTSymbol(sym) : sym;
|
||||
Symbol sym = globalSymbol(func.symbolString());
|
||||
return doesIndirectAccess(func) ? PLTSymbol(sym) : sym;
|
||||
}
|
||||
}
|
||||
|
||||
protected AsmOperand functionAddress(Function func) {
|
||||
Symbol sym = new NamedSymbol(func.name());
|
||||
if (options.isPICRequired()) {
|
||||
if (func.isPrivate()) {
|
||||
return mem(localGOTSymbol(sym), GOTBaseReg());
|
||||
}
|
||||
else {
|
||||
return mem(globalGOTSymbol(sym), GOTBaseReg());
|
||||
}
|
||||
}
|
||||
else {
|
||||
return imm(sym);
|
||||
}
|
||||
// condition to use indirect access (using PLT to call, GOT to refer).
|
||||
// In PIC, we do use indirect access for all global variables.
|
||||
// In PIE, we do use direct access for file-local reference.
|
||||
protected boolean doesIndirectAccess(Entity ent) {
|
||||
return options.isPositionIndependent() && !optimizeGvarAccess(ent);
|
||||
}
|
||||
|
||||
protected boolean optimizeGvarAccess(Entity ent) {
|
||||
return options.isPIERequired() && ent.isDefined();
|
||||
}
|
||||
|
||||
/** Generates initialized entries */
|
||||
|
@ -225,7 +222,7 @@ public class CodeGenerator
|
|||
// #@@}
|
||||
|
||||
//
|
||||
// PIC related constants and codes
|
||||
// PIC/PIE related constants and codes
|
||||
//
|
||||
|
||||
static protected final Symbol GOT = new NamedSymbol("_GLOBAL_OFFSET_TABLE_");
|
||||
|
@ -314,7 +311,7 @@ public class CodeGenerator
|
|||
long lvarBytes = allocateLocalVariables(func.body().scope(),
|
||||
saveRegs.size());
|
||||
prologue(func, saveRegs, lvarBytes);
|
||||
if (options.isPICRequired() && stats.doesRegisterUsed(GOTBaseReg())) {
|
||||
if (options.isPositionIndependent() && stats.doesRegisterUsed(GOTBaseReg())) {
|
||||
loadGOTBaseAddress(GOTBaseReg());
|
||||
}
|
||||
as.addAll(bodyAsms);
|
||||
|
@ -551,7 +548,7 @@ public class CodeGenerator
|
|||
// call
|
||||
if (node.isStaticCall()) {
|
||||
// call via function name
|
||||
call(node.function().symbol());
|
||||
call(node.function().callingSymbol());
|
||||
}
|
||||
else {
|
||||
// call via pointer
|
||||
|
|
Loading…
Reference in New Issue