implements PR-08.2
This commit is contained in:
parent
40188b67ab
commit
0490f64870
@ -19,6 +19,7 @@ import p.studio.compiler.source.identifiers.CallableShapeId;
|
||||
import p.studio.compiler.source.identifiers.CallableId;
|
||||
import p.studio.compiler.source.identifiers.FileId;
|
||||
import p.studio.compiler.source.identifiers.IntrinsicId;
|
||||
import p.studio.compiler.source.identifiers.ModuleId;
|
||||
import p.studio.compiler.source.identifiers.NameId;
|
||||
import p.studio.compiler.source.identifiers.TypeSurfaceId;
|
||||
import p.studio.compiler.source.tables.CallableShapeTable;
|
||||
@ -26,6 +27,7 @@ import p.studio.compiler.source.tables.CallableSignatureRef;
|
||||
import p.studio.compiler.source.tables.CallableTable;
|
||||
import p.studio.compiler.source.tables.IntrinsicReference;
|
||||
import p.studio.compiler.source.tables.IntrinsicTable;
|
||||
import p.studio.compiler.source.tables.ModuleReference;
|
||||
import p.studio.compiler.source.tables.NameTable;
|
||||
import p.studio.compiler.source.tables.TypeSurfaceTable;
|
||||
import p.studio.utilities.structures.ReadOnlyList;
|
||||
@ -71,7 +73,16 @@ public final class PbsFrontendCompiler {
|
||||
? PbsParser.ParseMode.INTERFACE_MODULE
|
||||
: PbsParser.ParseMode.ORDINARY;
|
||||
final var ast = PbsParser.parse(tokens, fileId, diagnostics, parseMode);
|
||||
final var irBackendFile = compileParsedFile(fileId, ast, diagnostics, sourceKind, "", hostAdmissionContext, nameTable);
|
||||
final var irBackendFile = compileParsedFile(
|
||||
fileId,
|
||||
ast,
|
||||
diagnostics,
|
||||
sourceKind,
|
||||
ModuleId.none(),
|
||||
"",
|
||||
ReadOnlyList.empty(),
|
||||
hostAdmissionContext,
|
||||
nameTable);
|
||||
if (diagnostics.errorCount() > admissionBaseline) {
|
||||
return IRBackendFile.empty(fileId);
|
||||
}
|
||||
@ -99,7 +110,16 @@ public final class PbsFrontendCompiler {
|
||||
final DiagnosticSink diagnostics,
|
||||
final SourceKind sourceKind,
|
||||
final HostAdmissionContext hostAdmissionContext) {
|
||||
return compileParsedFile(fileId, ast, diagnostics, sourceKind, "", hostAdmissionContext, new NameTable());
|
||||
return compileParsedFile(
|
||||
fileId,
|
||||
ast,
|
||||
diagnostics,
|
||||
sourceKind,
|
||||
ModuleId.none(),
|
||||
"",
|
||||
ReadOnlyList.empty(),
|
||||
hostAdmissionContext,
|
||||
new NameTable());
|
||||
}
|
||||
|
||||
public IRBackendFile compileParsedFile(
|
||||
@ -109,7 +129,16 @@ public final class PbsFrontendCompiler {
|
||||
final SourceKind sourceKind,
|
||||
final String moduleKey,
|
||||
final HostAdmissionContext hostAdmissionContext) {
|
||||
return compileParsedFile(fileId, ast, diagnostics, sourceKind, moduleKey, hostAdmissionContext, new NameTable());
|
||||
return compileParsedFile(
|
||||
fileId,
|
||||
ast,
|
||||
diagnostics,
|
||||
sourceKind,
|
||||
ModuleId.none(),
|
||||
moduleKey,
|
||||
ReadOnlyList.empty(),
|
||||
hostAdmissionContext,
|
||||
new NameTable());
|
||||
}
|
||||
|
||||
public IRBackendFile compileParsedFile(
|
||||
@ -117,7 +146,9 @@ public final class PbsFrontendCompiler {
|
||||
final PbsAst.File ast,
|
||||
final DiagnosticSink diagnostics,
|
||||
final SourceKind sourceKind,
|
||||
final ModuleId moduleId,
|
||||
final String moduleKey,
|
||||
final ReadOnlyList<ModuleReference> modulePool,
|
||||
final HostAdmissionContext hostAdmissionContext,
|
||||
final NameTable nameTable) {
|
||||
return compileParsedFile(
|
||||
@ -125,7 +156,9 @@ public final class PbsFrontendCompiler {
|
||||
ast,
|
||||
diagnostics,
|
||||
sourceKind,
|
||||
moduleId,
|
||||
moduleKey,
|
||||
modulePool,
|
||||
hostAdmissionContext,
|
||||
nameTable,
|
||||
ReadOnlyList.empty(),
|
||||
@ -138,12 +171,16 @@ public final class PbsFrontendCompiler {
|
||||
final PbsAst.File ast,
|
||||
final DiagnosticSink diagnostics,
|
||||
final SourceKind sourceKind,
|
||||
final ModuleId moduleId,
|
||||
final String moduleKey,
|
||||
final ReadOnlyList<ModuleReference> modulePool,
|
||||
final HostAdmissionContext hostAdmissionContext,
|
||||
final NameTable nameTable,
|
||||
final ReadOnlyList<PbsAst.TopDecl> supplementalTopDecls,
|
||||
final ReadOnlyList<ImportedCallableSurface> importedCallables,
|
||||
final IRReservedMetadata importedReservedMetadata) {
|
||||
final var effectiveModuleId = moduleId == null ? ModuleId.none() : moduleId;
|
||||
final var effectiveModulePool = modulePool == null ? ReadOnlyList.<ModuleReference>empty() : modulePool;
|
||||
final var effectiveNameTable = nameTable == null ? new NameTable() : nameTable;
|
||||
final var effectiveSupplementalTopDecls = supplementalTopDecls == null
|
||||
? ReadOnlyList.<PbsAst.TopDecl>empty()
|
||||
@ -187,6 +224,7 @@ public final class PbsFrontendCompiler {
|
||||
fileId,
|
||||
ast,
|
||||
effectiveSupplementalTopDecls,
|
||||
effectiveModuleId,
|
||||
moduleKey,
|
||||
effectiveReservedMetadata,
|
||||
effectiveNameTable,
|
||||
@ -200,6 +238,7 @@ public final class PbsFrontendCompiler {
|
||||
functions,
|
||||
executableLowering.executableFunctions(),
|
||||
reservedMetadata,
|
||||
effectiveModulePool,
|
||||
executableLowering.callableSignatures(),
|
||||
executableLowering.intrinsicPool());
|
||||
}
|
||||
@ -221,12 +260,14 @@ public final class PbsFrontendCompiler {
|
||||
final FileId fileId,
|
||||
final PbsAst.File ast,
|
||||
final ReadOnlyList<PbsAst.TopDecl> supplementalTopDecls,
|
||||
final ModuleId moduleId,
|
||||
final String moduleKey,
|
||||
final IRReservedMetadata reservedMetadata,
|
||||
final NameTable nameTable,
|
||||
final DiagnosticSink diagnostics,
|
||||
final ReadOnlyList<ImportedCallableSurface> importedCallables) {
|
||||
final var normalizedModuleKey = moduleKey == null ? "" : moduleKey;
|
||||
final var normalizedModuleId = moduleId == null ? ModuleId.none() : moduleId;
|
||||
final var hostByMethodName = new HashMap<NameId, List<IRReservedMetadata.HostMethodBinding>>();
|
||||
for (final var hostBinding : reservedMetadata.hostMethodBindings()) {
|
||||
hostByMethodName
|
||||
@ -318,6 +359,7 @@ public final class PbsFrontendCompiler {
|
||||
final var declaredFn = declaredCallable.functionDecl();
|
||||
final var callableShapeId = callableShapeId(declaredFn, typeSurfaceTable, callableShapeTable);
|
||||
final var callableId = callableIdTable.register(
|
||||
normalizedModuleId,
|
||||
normalizedModuleKey,
|
||||
declaredCallable.callableName(),
|
||||
declaredFn.parameters().size(),
|
||||
@ -333,6 +375,7 @@ public final class PbsFrontendCompiler {
|
||||
}
|
||||
for (final var importedCallable : importedCallables) {
|
||||
final var callableId = callableIdTable.register(
|
||||
importedCallable.moduleId(),
|
||||
importedCallable.moduleKey(),
|
||||
importedCallable.callableName(),
|
||||
importedCallable.arity(),
|
||||
@ -359,6 +402,7 @@ public final class PbsFrontendCompiler {
|
||||
localSlotByNameId.put(nameTable.register(fn.parameters().get(paramIndex).name()), paramIndex);
|
||||
}
|
||||
final var loweringContext = new ExecutableLoweringContext(
|
||||
normalizedModuleId,
|
||||
normalizedModuleKey,
|
||||
diagnostics,
|
||||
nameTable,
|
||||
@ -401,6 +445,7 @@ public final class PbsFrontendCompiler {
|
||||
final var end = safeToInt(fn.span().getEnd());
|
||||
executableFunctions.add(new IRBackendExecutableFunction(
|
||||
fileId,
|
||||
normalizedModuleId,
|
||||
normalizedModuleKey,
|
||||
callable.callableName(),
|
||||
functionCallableId,
|
||||
@ -921,6 +966,7 @@ public final class PbsFrontendCompiler {
|
||||
final var calleeCallableId = callableCandidates.getFirst();
|
||||
context.instructions().add(new IRBackendExecutableFunction.Instruction(
|
||||
IRBackendExecutableFunction.InstructionKind.CALL_FUNC,
|
||||
context.moduleId(),
|
||||
context.moduleKey(),
|
||||
calleeIdentity.primaryCallableDisplayName(),
|
||||
calleeCallableId,
|
||||
@ -1292,6 +1338,7 @@ public final class PbsFrontendCompiler {
|
||||
}
|
||||
|
||||
private static final class ExecutableLoweringContext {
|
||||
private final ModuleId moduleId;
|
||||
private final String moduleKey;
|
||||
private final DiagnosticSink diagnostics;
|
||||
private final NameTable nameTable;
|
||||
@ -1308,6 +1355,7 @@ public final class PbsFrontendCompiler {
|
||||
private int nextLabelId = 0;
|
||||
|
||||
private ExecutableLoweringContext(
|
||||
final ModuleId moduleId,
|
||||
final String moduleKey,
|
||||
final DiagnosticSink diagnostics,
|
||||
final NameTable nameTable,
|
||||
@ -1319,6 +1367,7 @@ public final class PbsFrontendCompiler {
|
||||
final Map<CallableId, Integer> returnSlotsByCallableId,
|
||||
final IntrinsicTable intrinsicIdTable,
|
||||
final Map<NameId, Integer> localSlotByNameId) {
|
||||
this.moduleId = moduleId == null ? ModuleId.none() : moduleId;
|
||||
this.moduleKey = moduleKey;
|
||||
this.diagnostics = diagnostics;
|
||||
this.nameTable = nameTable;
|
||||
@ -1332,6 +1381,10 @@ public final class PbsFrontendCompiler {
|
||||
this.localSlotByNameId = localSlotByNameId == null ? Map.of() : localSlotByNameId;
|
||||
}
|
||||
|
||||
private ModuleId moduleId() {
|
||||
return moduleId;
|
||||
}
|
||||
|
||||
private String moduleKey() {
|
||||
return moduleKey;
|
||||
}
|
||||
@ -1440,11 +1493,15 @@ public final class PbsFrontendCompiler {
|
||||
}
|
||||
|
||||
public record ImportedCallableSurface(
|
||||
ModuleId moduleId,
|
||||
String moduleKey,
|
||||
String callableName,
|
||||
int arity,
|
||||
int returnSlots,
|
||||
String shapeSurface) {
|
||||
public ImportedCallableSurface {
|
||||
moduleId = moduleId == null ? ModuleId.none() : moduleId;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ExecutableLoweringAnalysisException extends RuntimeException {
|
||||
|
||||
@ -159,6 +159,7 @@ public class PBSFrontendPhaseService implements FrontendPhaseService {
|
||||
markModulesWithLinkingErrors(diagnostics, moduleIdByFile, failedModuleIds);
|
||||
final var moduleDependencyGraph = buildModuleDependencyGraph(parsedSourceFiles, moduleTable);
|
||||
final var importedSemanticContexts = buildImportedSemanticContexts(parsedSourceFiles, moduleTable);
|
||||
final var canonicalModulePool = emitModulePool(moduleTable);
|
||||
|
||||
final var compiledSourceFiles = new ArrayList<CompiledSourceFile>(parsedSourceFiles.size());
|
||||
for (final var parsedSource : parsedSourceFiles) {
|
||||
@ -175,7 +176,9 @@ public class PBSFrontendPhaseService implements FrontendPhaseService {
|
||||
parsedSource.ast(),
|
||||
diagnostics,
|
||||
parsedSource.sourceKind(),
|
||||
parsedSource.moduleId(),
|
||||
renderModuleKey(moduleTable, parsedSource.moduleId()),
|
||||
canonicalModulePool,
|
||||
ctx.hostAdmissionContext(),
|
||||
nameTable,
|
||||
importedSemanticContext.supplementalTopDecls(),
|
||||
@ -431,6 +434,7 @@ public class PBSFrontendPhaseService implements FrontendPhaseService {
|
||||
importedCallables,
|
||||
importedCallableKeys,
|
||||
new PbsFrontendCompiler.ImportedCallableSurface(
|
||||
importedModuleId,
|
||||
importedModuleKey,
|
||||
localName + "." + method.name(),
|
||||
method.parameters().size(),
|
||||
@ -444,6 +448,7 @@ public class PBSFrontendPhaseService implements FrontendPhaseService {
|
||||
importedCallables,
|
||||
importedCallableKeys,
|
||||
new PbsFrontendCompiler.ImportedCallableSurface(
|
||||
importedModuleId,
|
||||
importedModuleKey,
|
||||
localName,
|
||||
functionDecl.parameters().size(),
|
||||
@ -793,6 +798,14 @@ public class PBSFrontendPhaseService implements FrontendPhaseService {
|
||||
return moduleReference.project() + ":" + String.join("/", moduleReference.pathSegments().asList());
|
||||
}
|
||||
|
||||
private ReadOnlyList<ModuleReference> emitModulePool(final ModuleTable moduleTable) {
|
||||
final var pool = new ArrayList<ModuleReference>(moduleTable.size());
|
||||
for (final var moduleId : moduleTable.identifiers()) {
|
||||
pool.add(moduleTable.get(moduleId));
|
||||
}
|
||||
return ReadOnlyList.wrap(pool);
|
||||
}
|
||||
|
||||
private static final class MutableModuleUnit {
|
||||
private final ArrayList<PbsModuleVisibilityValidator.SourceFile> sources = new ArrayList<>();
|
||||
private final ArrayList<PbsModuleVisibilityValidator.BarrelFile> barrels = new ArrayList<>();
|
||||
|
||||
@ -6,19 +6,15 @@ import p.studio.compiler.models.IRBackend;
|
||||
import p.studio.compiler.models.IRBackendExecutableFunction;
|
||||
import p.studio.compiler.source.Span;
|
||||
import p.studio.compiler.source.identifiers.CallableId;
|
||||
import p.studio.compiler.source.identifiers.ModuleId;
|
||||
import p.studio.compiler.source.tables.ModuleReference;
|
||||
import p.studio.utilities.structures.ReadOnlyList;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
public class LowerToIRVMService {
|
||||
private static final Comparator<IRBackendExecutableFunction> FUNCTION_ORDER = Comparator
|
||||
.comparing(IRBackendExecutableFunction::moduleKey)
|
||||
.thenComparing(IRBackendExecutableFunction::callableName)
|
||||
.thenComparingInt(function -> function.callableId().getIndex())
|
||||
.thenComparingInt(IRBackendExecutableFunction::sourceStart);
|
||||
|
||||
private final IRVMValidator validator;
|
||||
|
||||
public LowerToIRVMService() {
|
||||
@ -301,7 +297,23 @@ public class LowerToIRVMService {
|
||||
"frontend IRBackend entrypoint declaration is missing");
|
||||
}
|
||||
final var sorted = new ArrayList<>(backend.getExecutableFunctions().asList());
|
||||
sorted.sort(FUNCTION_ORDER);
|
||||
sorted.sort((left, right) -> {
|
||||
final var leftModuleKey = moduleSortKey(backend, left.moduleId(), left.moduleKey());
|
||||
final var rightModuleKey = moduleSortKey(backend, right.moduleId(), right.moduleKey());
|
||||
final var moduleCmp = leftModuleKey.compareTo(rightModuleKey);
|
||||
if (moduleCmp != 0) {
|
||||
return moduleCmp;
|
||||
}
|
||||
final var nameCmp = left.callableName().compareTo(right.callableName());
|
||||
if (nameCmp != 0) {
|
||||
return nameCmp;
|
||||
}
|
||||
final var idCmp = Integer.compare(left.callableId().getIndex(), right.callableId().getIndex());
|
||||
if (idCmp != 0) {
|
||||
return idCmp;
|
||||
}
|
||||
return Integer.compare(left.sourceStart(), right.sourceStart());
|
||||
});
|
||||
final var entrypoints = sorted.stream()
|
||||
.filter(candidate -> entryPointCallableName.equals(candidate.callableName()))
|
||||
.toList();
|
||||
@ -328,6 +340,27 @@ public class LowerToIRVMService {
|
||||
return ReadOnlyList.wrap(ordered);
|
||||
}
|
||||
|
||||
private String moduleSortKey(
|
||||
final IRBackend backend,
|
||||
final ModuleId moduleId,
|
||||
final String fallbackModuleKey) {
|
||||
if (moduleId != null && !moduleId.isNone()) {
|
||||
final var index = moduleId.getIndex();
|
||||
if (index >= 0 && index < backend.getModulePool().size()) {
|
||||
return canonicalModuleSortKey(backend.getModulePool().get(index));
|
||||
}
|
||||
}
|
||||
return fallbackModuleKey == null ? "" : fallbackModuleKey;
|
||||
}
|
||||
|
||||
private String canonicalModuleSortKey(final ModuleReference reference) {
|
||||
final var joiner = new StringJoiner("/", reference.project() + ":", "");
|
||||
for (final var segment : reference.pathSegments()) {
|
||||
joiner.add(segment);
|
||||
}
|
||||
return joiner.toString();
|
||||
}
|
||||
|
||||
private BytecodeModule.SourceSpan toBytecodeSpan(
|
||||
final int fallbackFileId,
|
||||
final Span span) {
|
||||
|
||||
@ -7,7 +7,9 @@ import p.studio.compiler.source.Span;
|
||||
import p.studio.compiler.source.identifiers.CallableId;
|
||||
import p.studio.compiler.source.identifiers.FileId;
|
||||
import p.studio.compiler.source.identifiers.IntrinsicId;
|
||||
import p.studio.compiler.source.identifiers.ModuleId;
|
||||
import p.studio.compiler.source.tables.IntrinsicReference;
|
||||
import p.studio.compiler.source.tables.ModuleReference;
|
||||
import p.studio.utilities.structures.ReadOnlyList;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
@ -199,6 +201,27 @@ class LowerToIRVMServiceTest {
|
||||
assertEquals(IRVMLoweringErrorCode.LOWER_IRVM_ENTRYPOINT_AMBIGUOUS, thrown.code());
|
||||
}
|
||||
|
||||
@Test
|
||||
void lowerMustUseModulePoolCanonicalIdentityForNonEntrypointOrdering() {
|
||||
final var backend = IRBackend.builder()
|
||||
.entryPointCallableName("frame")
|
||||
.modulePool(ReadOnlyList.from(
|
||||
new ModuleReference("app", ReadOnlyList.from("alpha")),
|
||||
new ModuleReference("app", ReadOnlyList.from("zeta"))))
|
||||
.executableFunctions(ReadOnlyList.from(
|
||||
fnWithModule("helper_in_zeta", "legacy/zeta", 1, 21, ReadOnlyList.from(ret())),
|
||||
fnWithModule("frame", "legacy/zeta", 1, 20, ReadOnlyList.from(ret())),
|
||||
fnWithModule("helper_in_alpha", "legacy/alpha", 0, 22, ReadOnlyList.from(ret()))))
|
||||
.build();
|
||||
|
||||
final var lowered = new LowerToIRVMService().lower(backend);
|
||||
|
||||
assertEquals(3, lowered.module().functions().size());
|
||||
assertEquals("frame", lowered.module().functions().get(0).name());
|
||||
assertEquals("helper_in_alpha", lowered.module().functions().get(1).name());
|
||||
assertEquals("helper_in_zeta", lowered.module().functions().get(2).name());
|
||||
}
|
||||
|
||||
private static IRBackendExecutableFunction fn(
|
||||
final String name,
|
||||
final String moduleKey,
|
||||
@ -219,6 +242,28 @@ class LowerToIRVMServiceTest {
|
||||
Span.none());
|
||||
}
|
||||
|
||||
private static IRBackendExecutableFunction fnWithModule(
|
||||
final String name,
|
||||
final String moduleKey,
|
||||
final int moduleId,
|
||||
final int callableId,
|
||||
final ReadOnlyList<IRBackendExecutableFunction.Instruction> instructions) {
|
||||
return new IRBackendExecutableFunction(
|
||||
new FileId(0),
|
||||
new ModuleId(moduleId),
|
||||
moduleKey,
|
||||
name,
|
||||
new CallableId(callableId),
|
||||
0,
|
||||
10,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
4,
|
||||
instructions,
|
||||
Span.none());
|
||||
}
|
||||
|
||||
private static IRBackendExecutableFunction.Instruction ret() {
|
||||
return new IRBackendExecutableFunction.Instruction(
|
||||
IRBackendExecutableFunction.InstructionKind.RET,
|
||||
|
||||
@ -1,7 +1,17 @@
|
||||
package p.studio.compiler.source.identifiers;
|
||||
|
||||
public class ModuleId extends SourceIdentifier {
|
||||
public static final ModuleId NONE = new ModuleId(-1);
|
||||
|
||||
public ModuleId(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public static ModuleId none() {
|
||||
return NONE;
|
||||
}
|
||||
|
||||
public boolean isNone() {
|
||||
return this == NONE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,14 +1,29 @@
|
||||
package p.studio.compiler.source.tables;
|
||||
|
||||
import p.studio.compiler.source.identifiers.ModuleId;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public record CallableSignatureRef(
|
||||
ModuleId moduleId,
|
||||
String moduleKey,
|
||||
String callableName,
|
||||
int arity,
|
||||
String typeShape) {
|
||||
|
||||
public CallableSignatureRef(
|
||||
final String moduleKey,
|
||||
final String callableName,
|
||||
final int arity,
|
||||
final String typeShape) {
|
||||
this(ModuleId.none(), moduleKey, callableName, arity, typeShape);
|
||||
}
|
||||
|
||||
public CallableSignatureRef {
|
||||
moduleId = moduleId == null ? ModuleId.none() : moduleId;
|
||||
if (!moduleId.isNone()) {
|
||||
moduleId.getIndex();
|
||||
}
|
||||
moduleKey = moduleKey == null ? "" : moduleKey;
|
||||
callableName = Objects.requireNonNull(callableName, "callableName");
|
||||
typeShape = typeShape == null ? "" : typeShape;
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package p.studio.compiler.source.tables;
|
||||
|
||||
import p.studio.compiler.source.identifiers.CallableId;
|
||||
import p.studio.compiler.source.identifiers.ModuleId;
|
||||
|
||||
public class CallableTable extends InternTable<CallableId, CallableSignatureRef> implements CallableTableReader {
|
||||
|
||||
@ -13,6 +14,15 @@ public class CallableTable extends InternTable<CallableId, CallableSignatureRef>
|
||||
final String callableName,
|
||||
final int arity,
|
||||
final String typeShape) {
|
||||
return register(new CallableSignatureRef(moduleKey, callableName, arity, typeShape));
|
||||
return register(new CallableSignatureRef(ModuleId.none(), moduleKey, callableName, arity, typeShape));
|
||||
}
|
||||
|
||||
public CallableId register(
|
||||
final ModuleId moduleId,
|
||||
final String moduleKey,
|
||||
final String callableName,
|
||||
final int arity,
|
||||
final String typeShape) {
|
||||
return register(new CallableSignatureRef(moduleId, moduleKey, callableName, arity, typeShape));
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,14 +4,18 @@ import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import p.studio.compiler.source.identifiers.CallableId;
|
||||
import p.studio.compiler.source.identifiers.IntrinsicId;
|
||||
import p.studio.compiler.source.identifiers.ModuleId;
|
||||
import p.studio.compiler.source.tables.CallableSignatureRef;
|
||||
import p.studio.compiler.source.tables.CallableTable;
|
||||
import p.studio.compiler.source.tables.IntrinsicReference;
|
||||
import p.studio.compiler.source.tables.IntrinsicTable;
|
||||
import p.studio.compiler.source.tables.ModuleReference;
|
||||
import p.studio.compiler.source.tables.ModuleTable;
|
||||
import p.studio.utilities.structures.ReadOnlyList;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
|
||||
@Builder
|
||||
@Getter
|
||||
@ -23,6 +27,8 @@ public class IRBackend {
|
||||
@Builder.Default
|
||||
private final ReadOnlyList<IRBackendExecutableFunction> executableFunctions = ReadOnlyList.empty();
|
||||
@Builder.Default
|
||||
private final ReadOnlyList<ModuleReference> modulePool = ReadOnlyList.empty();
|
||||
@Builder.Default
|
||||
private final ReadOnlyList<CallableSignatureRef> callableSignatures = ReadOnlyList.empty();
|
||||
@Builder.Default
|
||||
private final ReadOnlyList<IntrinsicReference> intrinsicPool = ReadOnlyList.empty();
|
||||
@ -37,6 +43,7 @@ public class IRBackend {
|
||||
private String entryPointCallableName;
|
||||
private final ArrayList<IRFunction> functions = new ArrayList<>();
|
||||
private final ArrayList<IRBackendExecutableFunction> executableFunctions = new ArrayList<>();
|
||||
private final ModuleTable moduleTable = new ModuleTable();
|
||||
private final CallableTable callableTable = new CallableTable();
|
||||
private final IntrinsicTable intrinsicTable = new IntrinsicTable();
|
||||
private final ArrayList<IRReservedMetadata.HostMethodBinding> hostMethodBindings = new ArrayList<>();
|
||||
@ -49,10 +56,11 @@ public class IRBackend {
|
||||
return;
|
||||
}
|
||||
functions.addAll(backendFile.functions().asList());
|
||||
final var callableRemap = reindexCallables(backendFile.callableSignatures());
|
||||
final var moduleRemap = reindexModules(backendFile.modulePool());
|
||||
final var callableRemap = reindexCallables(backendFile.callableSignatures(), moduleRemap);
|
||||
final var intrinsicRemap = reindexIntrinsics(backendFile.intrinsicPool());
|
||||
for (final var function : backendFile.executableFunctions()) {
|
||||
executableFunctions.add(remapExecutableFunction(function, callableRemap, intrinsicRemap));
|
||||
executableFunctions.add(remapExecutableFunction(function, moduleRemap, callableRemap, intrinsicRemap));
|
||||
}
|
||||
final var metadata = backendFile.reservedMetadata();
|
||||
hostMethodBindings.addAll(metadata.hostMethodBindings().asList());
|
||||
@ -68,22 +76,52 @@ public class IRBackend {
|
||||
return this;
|
||||
}
|
||||
|
||||
private CallableId[] reindexCallables(final ReadOnlyList<CallableSignatureRef> localCallableSignatures) {
|
||||
private ModuleId[] reindexModules(final ReadOnlyList<ModuleReference> localModulePool) {
|
||||
if (localModulePool == null || localModulePool.isEmpty()) {
|
||||
return new ModuleId[0];
|
||||
}
|
||||
final var remap = new ModuleId[localModulePool.size()];
|
||||
for (var i = 0; i < localModulePool.size(); i++) {
|
||||
remap[i] = moduleTable.register(localModulePool.get(i));
|
||||
}
|
||||
return remap;
|
||||
}
|
||||
|
||||
private CallableId[] reindexCallables(
|
||||
final ReadOnlyList<CallableSignatureRef> localCallableSignatures,
|
||||
final ModuleId[] moduleRemap) {
|
||||
if (localCallableSignatures == null || localCallableSignatures.isEmpty()) {
|
||||
return new CallableId[0];
|
||||
}
|
||||
final var remap = new CallableId[localCallableSignatures.size()];
|
||||
for (var i = 0; i < localCallableSignatures.size(); i++) {
|
||||
remap[i] = callableTable.register(localCallableSignatures.get(i));
|
||||
final var signature = localCallableSignatures.get(i);
|
||||
final var remappedModuleId = remapModuleId(
|
||||
signature.moduleId(),
|
||||
signature.moduleKey(),
|
||||
moduleRemap,
|
||||
"callable signature");
|
||||
remap[i] = callableTable.register(
|
||||
remappedModuleId,
|
||||
signature.moduleKey(),
|
||||
signature.callableName(),
|
||||
signature.arity(),
|
||||
signature.typeShape());
|
||||
}
|
||||
return remap;
|
||||
}
|
||||
|
||||
private IRBackendExecutableFunction remapExecutableFunction(
|
||||
final IRBackendExecutableFunction function,
|
||||
final ModuleId[] moduleRemap,
|
||||
final CallableId[] callableRemap,
|
||||
final IntrinsicId[] intrinsicRemap) {
|
||||
final var remappedInstructions = new ArrayList<IRBackendExecutableFunction.Instruction>(function.instructions().size());
|
||||
final var remappedFunctionModuleId = remapModuleId(
|
||||
function.moduleId(),
|
||||
function.moduleKey(),
|
||||
moduleRemap,
|
||||
"function");
|
||||
for (final var instruction : function.instructions()) {
|
||||
final CallableId remappedCallee;
|
||||
if (instruction.calleeCallableId() == null) {
|
||||
@ -101,8 +139,14 @@ public class IRBackend {
|
||||
} else {
|
||||
remappedIntrinsic = instruction.intrinsicCall();
|
||||
}
|
||||
final var remappedCalleeModuleId = remapModuleId(
|
||||
instruction.calleeModuleId(),
|
||||
instruction.calleeModuleKey(),
|
||||
moduleRemap,
|
||||
"callee");
|
||||
remappedInstructions.add(new IRBackendExecutableFunction.Instruction(
|
||||
instruction.kind(),
|
||||
remappedCalleeModuleId,
|
||||
instruction.calleeModuleKey(),
|
||||
instruction.calleeCallableName(),
|
||||
remappedCallee,
|
||||
@ -116,6 +160,7 @@ public class IRBackend {
|
||||
}
|
||||
return new IRBackendExecutableFunction(
|
||||
function.fileId(),
|
||||
remappedFunctionModuleId,
|
||||
function.moduleKey(),
|
||||
function.callableName(),
|
||||
remapCallableId(function.callableId(), callableRemap, "function"),
|
||||
@ -129,6 +174,45 @@ public class IRBackend {
|
||||
function.span());
|
||||
}
|
||||
|
||||
private ModuleId remapModuleId(
|
||||
final ModuleId localModuleId,
|
||||
final String moduleKey,
|
||||
final ModuleId[] moduleRemap,
|
||||
final String label) {
|
||||
if (localModuleId != null && !localModuleId.isNone()) {
|
||||
final var localIndex = localModuleId.getIndex();
|
||||
if (localIndex < 0 || localIndex >= moduleRemap.length) {
|
||||
throw new IllegalArgumentException("invalid local " + label + " module id: " + localModuleId);
|
||||
}
|
||||
return moduleRemap[localIndex];
|
||||
}
|
||||
final var fallbackReference = moduleReferenceFromKey(moduleKey);
|
||||
if (fallbackReference != null) {
|
||||
return moduleTable.register(fallbackReference);
|
||||
}
|
||||
return ModuleId.none();
|
||||
}
|
||||
|
||||
private ModuleReference moduleReferenceFromKey(final String moduleKey) {
|
||||
if (moduleKey == null || moduleKey.isBlank()) {
|
||||
return null;
|
||||
}
|
||||
final var separator = moduleKey.indexOf(':');
|
||||
if (separator <= 0) {
|
||||
return null;
|
||||
}
|
||||
final var project = moduleKey.substring(0, separator).trim();
|
||||
final var rawPath = moduleKey.substring(separator + 1).trim();
|
||||
if (project.isBlank()) {
|
||||
return null;
|
||||
}
|
||||
if (rawPath.isBlank()) {
|
||||
return new ModuleReference(project, ReadOnlyList.empty());
|
||||
}
|
||||
final var segments = List.of(rawPath.split("/"));
|
||||
return new ModuleReference(project, ReadOnlyList.wrap(segments));
|
||||
}
|
||||
|
||||
private CallableId remapCallableId(
|
||||
final CallableId localCallableId,
|
||||
final CallableId[] callableRemap,
|
||||
@ -169,6 +253,14 @@ public class IRBackend {
|
||||
return ReadOnlyList.wrap(signatures);
|
||||
}
|
||||
|
||||
private ReadOnlyList<ModuleReference> emitModulePool() {
|
||||
final var modules = new ArrayList<ModuleReference>(moduleTable.size());
|
||||
for (final var moduleId : moduleTable.identifiers()) {
|
||||
modules.add(moduleTable.get(moduleId));
|
||||
}
|
||||
return ReadOnlyList.wrap(modules);
|
||||
}
|
||||
|
||||
private ReadOnlyList<IntrinsicReference> emitIntrinsicPool() {
|
||||
final var pool = new ArrayList<IntrinsicReference>(intrinsicTable.size());
|
||||
for (final var intrinsicId : intrinsicTable.identifiers()) {
|
||||
@ -183,6 +275,7 @@ public class IRBackend {
|
||||
.entryPointCallableName(resolveEntryPointCallableName())
|
||||
.functions(ReadOnlyList.wrap(functions))
|
||||
.executableFunctions(ReadOnlyList.wrap(executableFunctions))
|
||||
.modulePool(emitModulePool())
|
||||
.callableSignatures(emitCallableSignatures())
|
||||
.intrinsicPool(emitIntrinsicPool())
|
||||
.reservedMetadata(new IRReservedMetadata(
|
||||
@ -206,6 +299,7 @@ public class IRBackend {
|
||||
sb.append("IRBackend{entrypoint=").append(entryPointCallableName)
|
||||
.append(", functions=").append(functions.size())
|
||||
.append(", executableFunctions=").append(executableFunctions.size())
|
||||
.append(", modulePool=").append(modulePool.size())
|
||||
.append(", callableSignatures=").append(callableSignatures.size())
|
||||
.append(", intrinsicPool=").append(intrinsicPool.size())
|
||||
.append(", hostBindings=").append(reservedMetadata.hostMethodBindings().size())
|
||||
|
||||
@ -4,12 +4,14 @@ import p.studio.compiler.source.Span;
|
||||
import p.studio.compiler.source.identifiers.CallableId;
|
||||
import p.studio.compiler.source.identifiers.FileId;
|
||||
import p.studio.compiler.source.identifiers.IntrinsicId;
|
||||
import p.studio.compiler.source.identifiers.ModuleId;
|
||||
import p.studio.utilities.structures.ReadOnlyList;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public record IRBackendExecutableFunction(
|
||||
FileId fileId,
|
||||
ModuleId moduleId,
|
||||
String moduleKey,
|
||||
String callableName,
|
||||
CallableId callableId,
|
||||
@ -22,8 +24,41 @@ public record IRBackendExecutableFunction(
|
||||
ReadOnlyList<Instruction> instructions,
|
||||
Span span) {
|
||||
|
||||
public IRBackendExecutableFunction(
|
||||
final FileId fileId,
|
||||
final String moduleKey,
|
||||
final String callableName,
|
||||
final CallableId callableId,
|
||||
final int sourceStart,
|
||||
final int sourceEnd,
|
||||
final int paramSlots,
|
||||
final int localSlots,
|
||||
final int returnSlots,
|
||||
final int maxStackSlots,
|
||||
final ReadOnlyList<Instruction> instructions,
|
||||
final Span span) {
|
||||
this(
|
||||
fileId,
|
||||
ModuleId.none(),
|
||||
moduleKey,
|
||||
callableName,
|
||||
callableId,
|
||||
sourceStart,
|
||||
sourceEnd,
|
||||
paramSlots,
|
||||
localSlots,
|
||||
returnSlots,
|
||||
maxStackSlots,
|
||||
instructions,
|
||||
span);
|
||||
}
|
||||
|
||||
public IRBackendExecutableFunction {
|
||||
fileId = Objects.requireNonNull(fileId, "fileId");
|
||||
moduleId = moduleId == null ? ModuleId.none() : moduleId;
|
||||
if (!moduleId.isNone()) {
|
||||
moduleId.getIndex();
|
||||
}
|
||||
moduleKey = moduleKey == null ? "" : moduleKey;
|
||||
callableName = Objects.requireNonNull(callableName, "callableName");
|
||||
if (callableName.isBlank()) {
|
||||
@ -52,6 +87,7 @@ public record IRBackendExecutableFunction(
|
||||
|
||||
public record Instruction(
|
||||
InstructionKind kind,
|
||||
ModuleId calleeModuleId,
|
||||
String calleeModuleKey,
|
||||
String calleeCallableName,
|
||||
CallableId calleeCallableId,
|
||||
@ -64,13 +100,78 @@ public record IRBackendExecutableFunction(
|
||||
Span span) {
|
||||
public Instruction(
|
||||
final InstructionKind kind,
|
||||
final ModuleId calleeModuleId,
|
||||
final String calleeModuleKey,
|
||||
final String calleeCallableName,
|
||||
final CallableId calleeCallableId,
|
||||
final HostCallMetadata hostCall,
|
||||
final IntrinsicCallMetadata intrinsicCall,
|
||||
final Span span) {
|
||||
this(kind, calleeModuleKey, calleeCallableName, calleeCallableId, hostCall, intrinsicCall, null, null, null, null, span);
|
||||
this(kind, calleeModuleId, calleeModuleKey, calleeCallableName, calleeCallableId, hostCall, intrinsicCall, null, null, null, null, span);
|
||||
}
|
||||
|
||||
public Instruction(
|
||||
final InstructionKind kind,
|
||||
final ModuleId calleeModuleId,
|
||||
final String calleeModuleKey,
|
||||
final String calleeCallableName,
|
||||
final CallableId calleeCallableId,
|
||||
final HostCallMetadata hostCall,
|
||||
final IntrinsicCallMetadata intrinsicCall,
|
||||
final Integer expectedArgSlots,
|
||||
final Integer expectedRetSlots,
|
||||
final Span span) {
|
||||
this(kind, calleeModuleId, calleeModuleKey, calleeCallableName, calleeCallableId, hostCall, intrinsicCall, null, null, expectedArgSlots, expectedRetSlots, span);
|
||||
}
|
||||
|
||||
public Instruction(
|
||||
final InstructionKind kind,
|
||||
final ModuleId calleeModuleId,
|
||||
final String calleeModuleKey,
|
||||
final String calleeCallableName,
|
||||
final HostCallMetadata hostCall,
|
||||
final IntrinsicCallMetadata intrinsicCall,
|
||||
final Span span) {
|
||||
this(kind, calleeModuleId, calleeModuleKey, calleeCallableName, null, hostCall, intrinsicCall, null, null, null, null, span);
|
||||
}
|
||||
|
||||
public Instruction(
|
||||
final InstructionKind kind,
|
||||
final ModuleId calleeModuleId,
|
||||
final String calleeModuleKey,
|
||||
final String calleeCallableName,
|
||||
final HostCallMetadata hostCall,
|
||||
final IntrinsicCallMetadata intrinsicCall,
|
||||
final Integer expectedArgSlots,
|
||||
final Integer expectedRetSlots,
|
||||
final Span span) {
|
||||
this(kind, calleeModuleId, calleeModuleKey, calleeCallableName, null, hostCall, intrinsicCall, null, null, expectedArgSlots, expectedRetSlots, span);
|
||||
}
|
||||
|
||||
public Instruction(
|
||||
final InstructionKind kind,
|
||||
final String calleeModuleKey,
|
||||
final String calleeCallableName,
|
||||
final CallableId calleeCallableId,
|
||||
final HostCallMetadata hostCall,
|
||||
final IntrinsicCallMetadata intrinsicCall,
|
||||
final String label,
|
||||
final String targetLabel,
|
||||
final Integer expectedArgSlots,
|
||||
final Integer expectedRetSlots,
|
||||
final Span span) {
|
||||
this(kind, ModuleId.none(), calleeModuleKey, calleeCallableName, calleeCallableId, hostCall, intrinsicCall, label, targetLabel, expectedArgSlots, expectedRetSlots, span);
|
||||
}
|
||||
|
||||
public Instruction(
|
||||
final InstructionKind kind,
|
||||
final String calleeModuleKey,
|
||||
final String calleeCallableName,
|
||||
final CallableId calleeCallableId,
|
||||
final HostCallMetadata hostCall,
|
||||
final IntrinsicCallMetadata intrinsicCall,
|
||||
final Span span) {
|
||||
this(kind, ModuleId.none(), calleeModuleKey, calleeCallableName, calleeCallableId, hostCall, intrinsicCall, null, null, null, null, span);
|
||||
}
|
||||
|
||||
public Instruction(
|
||||
@ -83,7 +184,7 @@ public record IRBackendExecutableFunction(
|
||||
final Integer expectedArgSlots,
|
||||
final Integer expectedRetSlots,
|
||||
final Span span) {
|
||||
this(kind, calleeModuleKey, calleeCallableName, calleeCallableId, hostCall, intrinsicCall, null, null, expectedArgSlots, expectedRetSlots, span);
|
||||
this(kind, ModuleId.none(), calleeModuleKey, calleeCallableName, calleeCallableId, hostCall, intrinsicCall, null, null, expectedArgSlots, expectedRetSlots, span);
|
||||
}
|
||||
|
||||
public Instruction(
|
||||
@ -93,7 +194,7 @@ public record IRBackendExecutableFunction(
|
||||
final HostCallMetadata hostCall,
|
||||
final IntrinsicCallMetadata intrinsicCall,
|
||||
final Span span) {
|
||||
this(kind, calleeModuleKey, calleeCallableName, null, hostCall, intrinsicCall, null, null, null, null, span);
|
||||
this(kind, ModuleId.none(), calleeModuleKey, calleeCallableName, null, hostCall, intrinsicCall, null, null, null, null, span);
|
||||
}
|
||||
|
||||
public Instruction(
|
||||
@ -105,12 +206,16 @@ public record IRBackendExecutableFunction(
|
||||
final Integer expectedArgSlots,
|
||||
final Integer expectedRetSlots,
|
||||
final Span span) {
|
||||
this(kind, calleeModuleKey, calleeCallableName, null, hostCall, intrinsicCall, null, null, expectedArgSlots, expectedRetSlots, span);
|
||||
this(kind, ModuleId.none(), calleeModuleKey, calleeCallableName, null, hostCall, intrinsicCall, null, null, expectedArgSlots, expectedRetSlots, span);
|
||||
}
|
||||
|
||||
public Instruction {
|
||||
Objects.requireNonNull(kind, "kind");
|
||||
span = span == null ? Span.none() : span;
|
||||
calleeModuleId = calleeModuleId == null ? ModuleId.none() : calleeModuleId;
|
||||
if (!calleeModuleId.isNone()) {
|
||||
calleeModuleId.getIndex();
|
||||
}
|
||||
calleeModuleKey = calleeModuleKey == null ? "" : calleeModuleKey;
|
||||
calleeCallableName = calleeCallableName == null ? "" : calleeCallableName;
|
||||
label = label == null ? "" : label;
|
||||
|
||||
@ -3,6 +3,7 @@ package p.studio.compiler.models;
|
||||
import p.studio.compiler.source.identifiers.FileId;
|
||||
import p.studio.compiler.source.tables.CallableSignatureRef;
|
||||
import p.studio.compiler.source.tables.IntrinsicReference;
|
||||
import p.studio.compiler.source.tables.ModuleReference;
|
||||
import p.studio.utilities.structures.ReadOnlyList;
|
||||
|
||||
import java.util.Objects;
|
||||
@ -12,6 +13,7 @@ public record IRBackendFile(
|
||||
ReadOnlyList<IRFunction> functions,
|
||||
ReadOnlyList<IRBackendExecutableFunction> executableFunctions,
|
||||
IRReservedMetadata reservedMetadata,
|
||||
ReadOnlyList<ModuleReference> modulePool,
|
||||
ReadOnlyList<CallableSignatureRef> callableSignatures,
|
||||
ReadOnlyList<IntrinsicReference> intrinsicPool) {
|
||||
public IRBackendFile {
|
||||
@ -19,6 +21,7 @@ public record IRBackendFile(
|
||||
functions = functions == null ? ReadOnlyList.empty() : functions;
|
||||
executableFunctions = executableFunctions == null ? ReadOnlyList.empty() : executableFunctions;
|
||||
reservedMetadata = reservedMetadata == null ? IRReservedMetadata.empty() : reservedMetadata;
|
||||
modulePool = modulePool == null ? ReadOnlyList.empty() : modulePool;
|
||||
callableSignatures = callableSignatures == null ? ReadOnlyList.empty() : callableSignatures;
|
||||
intrinsicPool = intrinsicPool == null ? ReadOnlyList.empty() : intrinsicPool;
|
||||
}
|
||||
@ -26,17 +29,55 @@ public record IRBackendFile(
|
||||
public IRBackendFile(
|
||||
final FileId fileId,
|
||||
final ReadOnlyList<IRFunction> functions) {
|
||||
this(fileId, functions, ReadOnlyList.empty(), IRReservedMetadata.empty(), ReadOnlyList.empty(), ReadOnlyList.empty());
|
||||
this(
|
||||
fileId,
|
||||
functions,
|
||||
ReadOnlyList.empty(),
|
||||
IRReservedMetadata.empty(),
|
||||
ReadOnlyList.empty(),
|
||||
ReadOnlyList.empty(),
|
||||
ReadOnlyList.empty());
|
||||
}
|
||||
|
||||
public static IRBackendFile empty(final FileId fileId) {
|
||||
return new IRBackendFile(fileId, ReadOnlyList.empty(), ReadOnlyList.empty(), IRReservedMetadata.empty(), ReadOnlyList.empty(), ReadOnlyList.empty());
|
||||
return new IRBackendFile(
|
||||
fileId,
|
||||
ReadOnlyList.empty(),
|
||||
ReadOnlyList.empty(),
|
||||
IRReservedMetadata.empty(),
|
||||
ReadOnlyList.empty(),
|
||||
ReadOnlyList.empty(),
|
||||
ReadOnlyList.empty());
|
||||
}
|
||||
|
||||
public IRBackendFile(
|
||||
final FileId fileId,
|
||||
final ReadOnlyList<IRFunction> functions,
|
||||
final IRReservedMetadata reservedMetadata) {
|
||||
this(fileId, functions, ReadOnlyList.empty(), reservedMetadata, ReadOnlyList.empty(), ReadOnlyList.empty());
|
||||
this(
|
||||
fileId,
|
||||
functions,
|
||||
ReadOnlyList.empty(),
|
||||
reservedMetadata,
|
||||
ReadOnlyList.empty(),
|
||||
ReadOnlyList.empty(),
|
||||
ReadOnlyList.empty());
|
||||
}
|
||||
|
||||
public IRBackendFile(
|
||||
final FileId fileId,
|
||||
final ReadOnlyList<IRFunction> functions,
|
||||
final ReadOnlyList<IRBackendExecutableFunction> executableFunctions,
|
||||
final IRReservedMetadata reservedMetadata,
|
||||
final ReadOnlyList<CallableSignatureRef> callableSignatures,
|
||||
final ReadOnlyList<IntrinsicReference> intrinsicPool) {
|
||||
this(
|
||||
fileId,
|
||||
functions,
|
||||
executableFunctions,
|
||||
reservedMetadata,
|
||||
ReadOnlyList.empty(),
|
||||
callableSignatures,
|
||||
intrinsicPool);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,8 +5,10 @@ import p.studio.compiler.source.Span;
|
||||
import p.studio.compiler.source.identifiers.CallableId;
|
||||
import p.studio.compiler.source.identifiers.FileId;
|
||||
import p.studio.compiler.source.identifiers.IntrinsicId;
|
||||
import p.studio.compiler.source.identifiers.ModuleId;
|
||||
import p.studio.compiler.source.tables.CallableSignatureRef;
|
||||
import p.studio.compiler.source.tables.IntrinsicReference;
|
||||
import p.studio.compiler.source.tables.ModuleReference;
|
||||
import p.studio.utilities.structures.ReadOnlyList;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
@ -300,4 +302,76 @@ class IRBackendExecutableContractTest {
|
||||
assertEquals(21, emittedInstructionSpan.getStart());
|
||||
assertEquals(34, emittedInstructionSpan.getEnd());
|
||||
}
|
||||
|
||||
@Test
|
||||
void aggregatorMustReindexModulesIntoGlobalDensePool() {
|
||||
final var fileA = new IRBackendFile(
|
||||
new FileId(1),
|
||||
ReadOnlyList.empty(),
|
||||
ReadOnlyList.from(new IRBackendExecutableFunction(
|
||||
new FileId(1),
|
||||
new ModuleId(0),
|
||||
"app:mod/a",
|
||||
"entry",
|
||||
new CallableId(0),
|
||||
0,
|
||||
5,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
ReadOnlyList.from(new IRBackendExecutableFunction.Instruction(
|
||||
IRBackendExecutableFunction.InstructionKind.RET,
|
||||
"",
|
||||
"",
|
||||
null,
|
||||
null,
|
||||
Span.none())),
|
||||
Span.none())),
|
||||
IRReservedMetadata.empty(),
|
||||
ReadOnlyList.from(new ModuleReference("app", ReadOnlyList.from("mod", "a"))),
|
||||
ReadOnlyList.from(new CallableSignatureRef(new ModuleId(0), "app:mod/a", "entry", 0, "() -> unit")),
|
||||
ReadOnlyList.empty());
|
||||
final var fileB = new IRBackendFile(
|
||||
new FileId(2),
|
||||
ReadOnlyList.empty(),
|
||||
ReadOnlyList.from(new IRBackendExecutableFunction(
|
||||
new FileId(2),
|
||||
new ModuleId(0),
|
||||
"app:mod/b",
|
||||
"aux",
|
||||
new CallableId(0),
|
||||
6,
|
||||
10,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
ReadOnlyList.from(new IRBackendExecutableFunction.Instruction(
|
||||
IRBackendExecutableFunction.InstructionKind.RET,
|
||||
"",
|
||||
"",
|
||||
null,
|
||||
null,
|
||||
Span.none())),
|
||||
Span.none())),
|
||||
IRReservedMetadata.empty(),
|
||||
ReadOnlyList.from(new ModuleReference("app", ReadOnlyList.from("mod", "b"))),
|
||||
ReadOnlyList.from(new CallableSignatureRef(new ModuleId(0), "app:mod/b", "aux", 0, "() -> unit")),
|
||||
ReadOnlyList.empty());
|
||||
|
||||
final var aggregator = IRBackend.aggregator();
|
||||
aggregator.merge(fileA);
|
||||
aggregator.merge(fileB);
|
||||
final var backend = aggregator.emit();
|
||||
|
||||
assertEquals(2, backend.getModulePool().size());
|
||||
assertEquals("mod", backend.getModulePool().get(0).pathSegments().get(0));
|
||||
assertEquals("a", backend.getModulePool().get(0).pathSegments().get(1));
|
||||
assertEquals("b", backend.getModulePool().get(1).pathSegments().get(1));
|
||||
assertEquals(0, backend.getExecutableFunctions().get(0).moduleId().getIndex());
|
||||
assertEquals(1, backend.getExecutableFunctions().get(1).moduleId().getIndex());
|
||||
assertEquals(0, backend.getCallableSignatures().get(0).moduleId().getIndex());
|
||||
assertEquals(1, backend.getCallableSignatures().get(1).moduleId().getIndex());
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user