Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions aeneas/src/core/Eval.v3
Original file line number Diff line number Diff line change
Expand Up @@ -951,6 +951,13 @@ def evalOp(op: Operator, args: Arguments) -> Result {
if (sys == null) prog.system = sys = SystemCallState.new();
return syscall.eval(sys, args);
}
//----------------------------------------------------------------------------
WasmFunctionId => {
var prog = args.getProgram();
var del = Closure.!(args.vals[0]);
if (del == null) return args.throw(V3Exception.NullCheck, null);
return Int.box(prog.makeFunctionId(del.memberRef));
}
_ => ;
}
return args.throw("EvalUnimplemented", op.opcode.name);
Expand Down
1 change: 1 addition & 0 deletions aeneas/src/core/Opcode.v3
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ type Opcode {
case Alloc;
// Wasm target
case WasmFunctionTypeId;
case WasmFunctionId;
// Call
case CallAddress(p: Mach_FuncRep);
case CallKernel(kernel: Kernel);
Expand Down
5 changes: 5 additions & 0 deletions aeneas/src/core/Operator.v3
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,11 @@ component V3Op {
var ta = [paramType, resultType];
return newOp0(Opcode.WasmFunctionTypeId, ta, TypeUtil.NO_TYPES, Int.TYPE);
}
def newWasmFunctionId(paramType: Type, resultType: Type) -> Operator {
var ta = [paramType, resultType];
var funcType = Function.newType(paramType, resultType);
return newOp0(Opcode.WasmFunctionId, ta, [funcType], Int.TYPE);
}
//----------------------------------------------------------------------------
def bestCallVirtual(spec: IrSpec) -> Operator {
if (spec.receiver.typeCon.kind == Kind.CLASS) {
Expand Down
19 changes: 19 additions & 0 deletions aeneas/src/core/Program.v3
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,16 @@ class Program {
var mainRootIndex = -1;
var explicitName: string;
var tprog: TargetProgram;
var numImports = 0;

// dynamic portion of the program, including initialized state
var initState: Array<InitState>;
var compRecords: Array<Record>;
var strRecords: Array<Record>;
var recordCount: int;
var system: SystemCallState;
var wasmFuncId_imported = 0;
var wasmFuncId_internal = 0;

new() {
opBuilder = IrOpMethodBuilder.new(this);
Expand Down Expand Up @@ -193,6 +196,22 @@ class Program {
if (trt != frt) requestMapper(frt, trt); // results are covariant
}
}
def makeFunctionId(meth: IrSpec) -> int {
// XXX: linear search for function id
for (i < ir.roots.length) {
var r = ir.roots[i];
if (r.spec.equals(meth)) {
if (r.functionId < 0) r.functionId = assignFunctionId(meth);
return r.functionId;
}
}
var r = IrRoot.new(null, meth);
ir.roots.put(r);
return r.functionId = assignFunctionId(meth);
}
def assignFunctionId(meth: IrSpec) -> int {
return if(meth.asMethod().isImported(), wasmFuncId_imported++, wasmFuncId_internal++);
}
}
// Representation of the program appropriate for the target, e.g. a machine.
class TargetProgram(prog: Program) {
Expand Down
9 changes: 7 additions & 2 deletions aeneas/src/ir/Ir.v3
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ class IrMethod extends IrMember {
def getMethodType() -> Type {
return sig.funcType();
}
def isImported() -> bool {
return source != null && source.importName != null;
}
}
// a virtual method selector consisting of a method and a vtable index
// (the vtable index may differ from the method's in the case of partial specialization)
Expand Down Expand Up @@ -250,7 +253,9 @@ class IrSpec(receiver: Type, typeArgs: Array<Type>, member: IrMember) {
}
}

class IrRoot(name: string, spec: IrSpec) { }
class IrRoot(name: string, spec: IrSpec) {
var functionId = -1;
}

// Utility methods for dealing with Ir classes, methods, and fields
component IrUtil {
Expand All @@ -263,7 +268,7 @@ component IrUtil {
return HashMap<IrItem, T>.new(IrItem.uid, IrItem.==);
}
}
// representation of a module, including classes, components, methods, etc.
// Representation of a module, including classes, components, methods, etc.
class IrModule {
def classMap = TypeUtil.newTypeMap<IrClass>();
def classes = Vector<IrClass>.new();
Expand Down
4 changes: 3 additions & 1 deletion aeneas/src/ir/Normalization.v3
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,9 @@ class ReachabilityNormalizer(config: NormalizerConfig, ra: ReachabilityAnalyzer)
newIr.roots.length = old.length;
for (i < old.length) {
var o = old[i];
newIr.roots[i] = IrRoot.new(o.name, normalizeMethodRef(o.spec).1);
var r = IrRoot.new(o.name, normalizeMethodRef(o.spec).1);
r.functionId = o.functionId;
newIr.roots[i] = r;
}
ra.prog.ir = newIr;
// do remaining work; normalize record instances
Expand Down
4 changes: 4 additions & 0 deletions aeneas/src/vst/Verifier.v3
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class Verifier(compiler: Compiler, prog: Program) {
def ir = prog.ir = IrModule.new();
var exportMap: PartialMap<string, ExportDecl>;
var methodOverrideChecks: List<(VstCompoundVerifier, VstMethod)>;
var numImports = 0;

def forAll<T>(vec: Vector<T>, do: T -> void) {
for (i < vec.length) {
Expand Down Expand Up @@ -55,6 +56,8 @@ class Verifier(compiler: Compiler, prog: Program) {
for (r in vst.fieldRedefs.asArray()) redefineField(r, tc);
}
if (ERROR.noErrors) forAll(vst.exports, addExport);

prog.wasmFuncId_internal = numImports;
}
def buildFile(file: VstFile) {
if (file == null) return;
Expand Down Expand Up @@ -629,6 +632,7 @@ class VstCompoundVerifier {
if (decl.importName == null) decl.importName = decl.token;
if (decl.typeParams != null) errAtDecl(decl).ImportError("imported methods cannot have type parameters");
}
verifier.numImports++;
}
typeEnv = compound.typeEnv;
if (decl.isIndexed() && VstComponent.?(compound)) {
Expand Down
8 changes: 8 additions & 0 deletions aeneas/src/wasm/WasmCodeGen.v3
Original file line number Diff line number Diff line change
Expand Up @@ -1550,6 +1550,14 @@ class WasmCodeGen extends SsaMachGen {
_ => context.fail1("unimplemented main parameter type %q", t.render);
}
}
def emitUnassignedFunction() {
def b = w.putb;

b(/*body_size=*/3);
b(/*locals_count=*/0);
b(WasmOp.UNREACHABLE.opcode);
b(WasmOp.END.opcode);
}
def emitAllocationStub() {
var gcmeth = rt.getRiGc();
def b = w.putb;
Expand Down
6 changes: 3 additions & 3 deletions aeneas/src/wasm/WasmGcTarget.v3
Original file line number Diff line number Diff line change
Expand Up @@ -1447,9 +1447,8 @@ class WasmGcProgram extends WasmProgram {
if (m.machIndex < 0) context.fail1("method not assigned an index: %q", m.renderLong);
requestIndirectAdapter(m);
}
def addIrMethods() -> Vector<IrMethod> {
def addIrMethods() -> void {
context.fail("addIrMethods called for WasmGc target");
return null;
}
def addIrMethodsGc(infos: Vector<FunctionInfo>) -> Vector<IrMethod> {
var methods = mach.prog.ir.methods;
Expand Down Expand Up @@ -1506,8 +1505,9 @@ class WasmGcProgram extends WasmProgram {
Arrays.copyInto(sorted, methods.array, 0); // update the IrModule's method vector.
return methods;
}
def addMethod(m: IrMethod) {
def addMethod(m: IrMethod, wf: WasmFuncKind) -> int {
context.fail("addMethod called for WasmGc target");
return -1;
}
def addMethodGc(m: IrMethod, infos: Vector<FunctionInfo>, imported: bool) {
var sigIdx = addSig(m.ssa.params[0].vtype, m.sig);
Expand Down
Loading
Loading