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>
|
||||
|
||||
* net/loveruby/cflat/compiler/IRGenerator.java: should not return
|
||||
|
|
|
@ -2,16 +2,12 @@ package net.loveruby.cflat.asm;
|
|||
import net.loveruby.cflat.utils.*;
|
||||
import java.util.*;
|
||||
|
||||
public class Assembler {
|
||||
public class AssemblyFile {
|
||||
protected List<Assembly> assemblies;
|
||||
protected Type naturalType;
|
||||
protected int commentIndentLevel;
|
||||
|
||||
static public long align(long n, long alignment) {
|
||||
return (n + alignment - 1) / alignment * alignment;
|
||||
}
|
||||
|
||||
public Assembler(Type naturalType) {
|
||||
public AssemblyFile(Type naturalType) {
|
||||
this.assemblies = new ArrayList<Assembly>();
|
||||
this.naturalType = naturalType;
|
||||
this.commentIndentLevel = 0;
|
|
@ -1,4 +1,5 @@
|
|||
package net.loveruby.cflat.compiler;
|
||||
import net.loveruby.cflat.platform.Platform;
|
||||
import net.loveruby.cflat.ast.Location;
|
||||
import net.loveruby.cflat.entity.*;
|
||||
import net.loveruby.cflat.ir.*;
|
||||
|
@ -8,17 +9,20 @@ import java.util.*;
|
|||
public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
||||
// #@@range/ctor{
|
||||
protected CodeGeneratorOptions options;
|
||||
protected Platform platform;
|
||||
protected ErrorHandler errorHandler;
|
||||
protected LinkedList<Assembler> asStack;
|
||||
protected Assembler as;
|
||||
protected LinkedList<AssemblyFile> asStack;
|
||||
protected AssemblyFile as;
|
||||
protected Type naturalType;
|
||||
protected Label epilogue;
|
||||
|
||||
public CodeGenerator(CodeGeneratorOptions options,
|
||||
Platform platform,
|
||||
ErrorHandler errorHandler) {
|
||||
this.options = options;
|
||||
this.platform = platform;
|
||||
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) {
|
||||
this.naturalType = ir.naturalType();
|
||||
pushAssembler();
|
||||
SymbolTable constSymbols = new SymbolTable(Assembler.CONST_SYMBOL_BASE);
|
||||
SymbolTable constSymbols = new SymbolTable(AssemblyFile.CONST_SYMBOL_BASE);
|
||||
for (ConstantEntry ent : ir.constantTable().entries()) {
|
||||
locateConstant(ent, constSymbols);
|
||||
}
|
||||
|
@ -44,14 +48,14 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
|
||||
// #@@range/pushAssembler{
|
||||
protected void pushAssembler() {
|
||||
this.as = new Assembler(naturalType);
|
||||
this.as = new AssemblyFile(naturalType);
|
||||
asStack.add(this.as);
|
||||
}
|
||||
// #@@}
|
||||
|
||||
// #@@range/popAssembler{
|
||||
protected Assembler popAssembler() {
|
||||
Assembler popped = asStack.removeLast();
|
||||
protected AssemblyFile popAssembler() {
|
||||
AssemblyFile popped = asStack.removeLast();
|
||||
this.as = asStack.isEmpty() ? null : asStack.getLast();
|
||||
return popped;
|
||||
}
|
||||
|
@ -347,17 +351,6 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
* ======================= 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. */
|
||||
// #@@range/compileFunction{
|
||||
public void compileFunction(DefinedFunction func) {
|
||||
|
@ -383,7 +376,7 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
AsmStatistics stats = AsmStatistics.collect(bodyAsms);
|
||||
bodyAsms = reduceLabels(bodyAsms, stats);
|
||||
List<Register> saveRegs = usedCalleeSavedRegistersWithoutBP(stats);
|
||||
long saveRegsBytes = saveRegs.size() * stackWordSize;
|
||||
long saveRegsBytes = platform.stackSizeFromWordNum(saveRegs.size());
|
||||
long lvarBytes = allocateLocalVariables(
|
||||
func.body().scope(), saveRegsBytes);
|
||||
fixTmpOffsets(bodyAsms, saveRegsBytes + lvarBytes);
|
||||
|
@ -537,16 +530,14 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
// #@@}
|
||||
|
||||
// #@@range/allocateParameters{
|
||||
static final private long paramStartWordNum = 2;
|
||||
// return addr and saved bp
|
||||
|
||||
protected void allocateParameters(DefinedFunction func) {
|
||||
long word = paramStartWord;
|
||||
long numWords = paramStartWordNum;
|
||||
for (Parameter var : func.parameters()) {
|
||||
if (stackGrowsLower) {
|
||||
var.setMemref(mem(word * stackWordSize, bp()));
|
||||
}
|
||||
else {
|
||||
throw new Error("unsupported stack layout");
|
||||
}
|
||||
word++;
|
||||
var.setMemref(mem(platform.stackSizeFromWordNum(numWords), bp()));
|
||||
numWords++;
|
||||
}
|
||||
}
|
||||
// #@@}
|
||||
|
@ -579,15 +570,9 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
protected long allocateScope(LocalScope scope, long parentStackLen) {
|
||||
long len = parentStackLen;
|
||||
for (DefinedVariable var : scope.localVariables()) {
|
||||
if (stackGrowsLower) {
|
||||
len = Assembler.align(len + var.allocSize(), stackAlignment);
|
||||
len = platform.alignStack(len + var.allocSize());
|
||||
fixMemref((IndirectMemoryReference)var.memref(), -len);
|
||||
}
|
||||
else {
|
||||
fixMemref((IndirectMemoryReference)var.memref(), len);
|
||||
len = Assembler.align(len + var.allocSize(), stackAlignment);
|
||||
}
|
||||
}
|
||||
// Allocate local variables in child scopes.
|
||||
// We allocate child scopes in the same area (overrapped).
|
||||
long maxLen = len;
|
||||
|
@ -608,26 +593,16 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
// #@@range/extendStack{
|
||||
protected void extendStack(long len) {
|
||||
if (len > 0) {
|
||||
if (stackGrowsLower) {
|
||||
as.sub(imm(len), sp());
|
||||
}
|
||||
else {
|
||||
as.add(imm(len), sp());
|
||||
}
|
||||
}
|
||||
}
|
||||
// #@@}
|
||||
|
||||
// #@@range/rewindStack{
|
||||
protected void rewindStack(long len) {
|
||||
if (len > 0) {
|
||||
if (stackGrowsLower) {
|
||||
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{
|
||||
protected IndirectMemoryReference stackTop() {
|
||||
if (stackGrowsLower) {
|
||||
return mem(-stackPointer, bp());
|
||||
}
|
||||
else {
|
||||
return mem(stackPointer - stackWordSize, bp());
|
||||
}
|
||||
}
|
||||
// #@@}
|
||||
|
||||
// #@@range/virtualPush{
|
||||
protected void virtualPush(Register reg) {
|
||||
extendVirtualStack(stackWordSize);
|
||||
extendVirtualStack(platform.stackWordSize());
|
||||
as.relocatableMov(reg, stackTop());
|
||||
if (options.isVerboseAsm()) {
|
||||
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.relocatableMov(stackTop(), reg);
|
||||
rewindVirtualStack(stackWordSize);
|
||||
rewindVirtualStack(platform.stackWordSize());
|
||||
}
|
||||
// #@@}
|
||||
|
||||
|
@ -694,7 +664,7 @@ public class CodeGenerator implements IRVisitor<Void,Void>, ELFConstants {
|
|||
// #@@range/fixTmpOffsets{
|
||||
protected void fixTmpOffsets(List<Assembly> asms, long offset) {
|
||||
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
|
||||
// >4 bytes arguments are not supported.
|
||||
rewindStack(node.numArgs() * stackWordSize);
|
||||
rewindStack(platform.stackSizeFromWordNum(node.numArgs()));
|
||||
return null;
|
||||
}
|
||||
// #@@}
|
||||
|
|
|
@ -25,12 +25,8 @@ public class Compiler {
|
|||
}
|
||||
// #@@}
|
||||
|
||||
private TypeTable defaultTypeTable() {
|
||||
return TypeTable.ilp32();
|
||||
}
|
||||
|
||||
public void commandMain(String[] origArgs) {
|
||||
Options opts = new Options(defaultTypeTable(), new LibraryLoader());
|
||||
Options opts = new Options();
|
||||
List<SourceFile> srcs = null;
|
||||
try {
|
||||
srcs = opts.parse(Arrays.asList(origArgs));
|
||||
|
@ -118,7 +114,7 @@ public class Compiler {
|
|||
findExpr(ast).dump();
|
||||
return;
|
||||
}
|
||||
ast.setTypeTable(opts.typeTable);
|
||||
ast.setTypeTable(opts.typeTable());
|
||||
semanticAnalysis(ast, opts);
|
||||
switch (opts.mode()) {
|
||||
case DumpReference:
|
||||
|
@ -216,7 +212,8 @@ public class Compiler {
|
|||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
package net.loveruby.cflat.compiler;
|
||||
import net.loveruby.cflat.platform.*;
|
||||
import net.loveruby.cflat.type.TypeTable;
|
||||
import net.loveruby.cflat.asm.*;
|
||||
import net.loveruby.cflat.exception.*;
|
||||
|
@ -7,55 +8,45 @@ import java.io.*;
|
|||
|
||||
// package scope
|
||||
class Options {
|
||||
protected CompilerMode mode;
|
||||
protected TypeTable typeTable;
|
||||
protected LibraryLoader loader;
|
||||
protected String outputFileName;
|
||||
protected boolean verbose;
|
||||
protected boolean debugParser;
|
||||
protected CodeGeneratorOptions genOptions;
|
||||
protected List<String> asOptions;
|
||||
protected boolean generatingSharedLibrary;
|
||||
protected boolean generatingPIE;
|
||||
protected List<LdArg> ldArgs;
|
||||
protected boolean noStartFiles = false;
|
||||
protected boolean noDefaultLibs = false;
|
||||
CompilerMode mode;
|
||||
LibraryLoader loader = new LibraryLoader();
|
||||
Platform platform = new X86Linux();
|
||||
String outputFileName;
|
||||
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;
|
||||
|
||||
public Options(TypeTable typeTable, LibraryLoader loader) {
|
||||
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() {
|
||||
CompilerMode mode() {
|
||||
return mode;
|
||||
}
|
||||
|
||||
public boolean isAssembleRequired() {
|
||||
boolean isAssembleRequired() {
|
||||
return mode.requires(CompilerMode.Assemble);
|
||||
}
|
||||
|
||||
public boolean isLinkRequired() {
|
||||
boolean isLinkRequired() {
|
||||
return mode.requires(CompilerMode.Link);
|
||||
}
|
||||
|
||||
public String outputFileNameFor(CompilerMode mode) {
|
||||
String outputFileNameFor(CompilerMode mode) {
|
||||
return this.mode == mode ? outputFileName : null;
|
||||
}
|
||||
|
||||
public String exeFileName() {
|
||||
String exeFileName() {
|
||||
return getOutputFileName("");
|
||||
}
|
||||
|
||||
public String soFileName() {
|
||||
String soFileName() {
|
||||
return getOutputFileName(".so");
|
||||
}
|
||||
|
||||
protected String getOutputFileName(String newExt) {
|
||||
private String getOutputFileName(String newExt) {
|
||||
if (outputFileName != null) {
|
||||
return outputFileName;
|
||||
}
|
||||
|
@ -68,7 +59,7 @@ class Options {
|
|||
}
|
||||
}
|
||||
|
||||
protected List<SourceFile> sourceFiles() {
|
||||
private List<SourceFile> sourceFiles() {
|
||||
List<SourceFile> result = new ArrayList<SourceFile>();
|
||||
for (LdArg arg : ldArgs) {
|
||||
if (arg.isSourceFile()) {
|
||||
|
@ -78,56 +69,60 @@ class Options {
|
|||
return result;
|
||||
}
|
||||
|
||||
public TypeTable typeTable() {
|
||||
return this.typeTable;
|
||||
Platform platform() {
|
||||
return platform;
|
||||
}
|
||||
|
||||
public LibraryLoader loader() {
|
||||
TypeTable typeTable() {
|
||||
return platform.typeTable();
|
||||
}
|
||||
|
||||
LibraryLoader loader() {
|
||||
return this.loader;
|
||||
}
|
||||
|
||||
public String outputFileName() {
|
||||
String outputFileName() {
|
||||
return this.outputFileName;
|
||||
}
|
||||
|
||||
public boolean isVerboseMode() {
|
||||
boolean isVerboseMode() {
|
||||
return this.verbose;
|
||||
}
|
||||
|
||||
public boolean doesDebugParser() {
|
||||
boolean doesDebugParser() {
|
||||
return this.debugParser;
|
||||
}
|
||||
|
||||
public CodeGeneratorOptions genOptions() {
|
||||
CodeGeneratorOptions genOptions() {
|
||||
return genOptions;
|
||||
}
|
||||
|
||||
public List<String> asOptions() {
|
||||
List<String> asOptions() {
|
||||
return this.asOptions;
|
||||
}
|
||||
|
||||
public boolean isGeneratingSharedLibrary() {
|
||||
boolean isGeneratingSharedLibrary() {
|
||||
return this.generatingSharedLibrary;
|
||||
}
|
||||
|
||||
public boolean isGeneratingPIE() {
|
||||
boolean isGeneratingPIE() {
|
||||
return this.generatingPIE;
|
||||
}
|
||||
|
||||
public List<LdArg> ldArgs() {
|
||||
List<LdArg> ldArgs() {
|
||||
return this.ldArgs;
|
||||
}
|
||||
|
||||
public boolean noStartFiles() {
|
||||
boolean noStartFiles() {
|
||||
return this.noStartFiles;
|
||||
}
|
||||
|
||||
public boolean noDefaultLibs() {
|
||||
boolean noDefaultLibs() {
|
||||
return this.noDefaultLibs;
|
||||
}
|
||||
|
||||
/** Returns List<SourceFile>. */
|
||||
public List<SourceFile> parse(List<String> argsList) {
|
||||
List<SourceFile> parse(List<String> argsList) {
|
||||
List<SourceFile> srcs = new ArrayList<SourceFile>();
|
||||
ListIterator<String> args = argsList.listIterator();
|
||||
while (args.hasNext()) {
|
||||
|
@ -253,18 +248,18 @@ class Options {
|
|||
return srcs;
|
||||
}
|
||||
|
||||
protected void parseError(String msg) {
|
||||
private void parseError(String 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);
|
||||
srcs.add(src);
|
||||
// Original argument order does matter when linking.
|
||||
ldArgs.add(src);
|
||||
}
|
||||
|
||||
protected String getOptArg(String opt, ListIterator<String> args) {
|
||||
private String getOptArg(String opt, ListIterator<String> args) {
|
||||
String path = opt.substring(2);
|
||||
if (path.length() != 0) { // -Ipath
|
||||
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()) {
|
||||
parseError("missing argument for " + opt);
|
||||
}
|
||||
|
@ -282,7 +277,7 @@ class Options {
|
|||
}
|
||||
|
||||
/** "-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(","));
|
||||
opts.remove(0); // remove "-Wl" etc.
|
||||
if (opts.isEmpty()) {
|
||||
|
@ -291,7 +286,7 @@ class Options {
|
|||
return opts;
|
||||
}
|
||||
|
||||
public void printUsage(PrintStream out) {
|
||||
void printUsage(PrintStream out) {
|
||||
out.println("Usage: cbc [options] file...");
|
||||
out.println("Global Options:");
|
||||
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;
|
||||
import net.loveruby.cflat.ast.Slot;
|
||||
import net.loveruby.cflat.ast.Location;
|
||||
import net.loveruby.cflat.asm.Assembler;
|
||||
import net.loveruby.cflat.utils.AsmUtils;
|
||||
import java.util.*;
|
||||
|
||||
public class StructType extends CompositeType {
|
||||
|
@ -20,12 +20,12 @@ public class StructType extends CompositeType {
|
|||
long offset = 0;
|
||||
long maxAlign = 1;
|
||||
for (Slot s : members()) {
|
||||
offset = Assembler.align(offset, s.allocSize());
|
||||
offset = AsmUtils.align(offset, s.allocSize());
|
||||
s.setOffset(offset);
|
||||
offset += s.allocSize();
|
||||
maxAlign = Math.max(maxAlign, s.alignment());
|
||||
}
|
||||
cachedSize = Assembler.align(offset, maxAlign);
|
||||
cachedSize = AsmUtils.align(offset, maxAlign);
|
||||
cachedAlign = maxAlign;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package net.loveruby.cflat.type;
|
||||
import net.loveruby.cflat.ast.Slot;
|
||||
import net.loveruby.cflat.ast.Location;
|
||||
import net.loveruby.cflat.asm.Assembler;
|
||||
import net.loveruby.cflat.utils.AsmUtils;
|
||||
import java.util.*;
|
||||
|
||||
public class UnionType extends CompositeType {
|
||||
|
@ -24,7 +24,7 @@ public class UnionType extends CompositeType {
|
|||
maxSize = Math.max(maxSize, s.allocSize());
|
||||
maxAlign = Math.max(maxAlign, s.alignment());
|
||||
}
|
||||
cachedSize = Assembler.align(maxSize, maxAlign);
|
||||
cachedSize = AsmUtils.align(maxSize, 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