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:
Minero Aoki 2009-05-10 14:51:53 +00:00
parent 6e8bfed7a3
commit 2e1cbdaf66
10 changed files with 158 additions and 126 deletions

View File

@ -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

View File

@ -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;

View File

@ -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;
} }
// #@@} // #@@}

View File

@ -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);
} }

View File

@ -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.");

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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;
}
}