Skip to content

Refactor EventFactory, Compilers and Parsers#1009

Open
xeren wants to merge 9 commits intodevelopmentfrom
refactorEventFactory
Open

Refactor EventFactory, Compilers and Parsers#1009
xeren wants to merge 9 commits intodevelopmentfrom
refactorEventFactory

Conversation

@xeren
Copy link
Copy Markdown
Collaborator

@xeren xeren commented Mar 13, 2026

Mostly cleans up some imports, but also

  • outlines some memory barrier generations in compilers.
  • outlines uses of ProgramBuilder.addChild in litmus parsers.
  • integrates FenceNameRepository into EventFactory

Modifications to EventFactory

Added

  • AArch64.newRMWLoadExclusive, AArch64.newRMWStoreExclusive
  • X86.newLoadFence, newStoreFence (still not implemented, but merges two places)
  • RISCV.newRMWLoadExclusive
  • Power.newRMWLoadExclusive

Modified

  • newRMWStoreExclusive, newRMWStoreExclusiveWithMo
  • AArch64.newDmbBarrier, etc.
  • AArch64.newBarrier(String,String) (moved from newFenceOpt)
  • RISCV.newRMWStoreConditional

@hernanponcedeleon
Copy link
Copy Markdown
Owner

@xeren can you please rebase and fix the conflicts?

…actory

# Conflicts:
#	dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusAArch64.java
#	dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusC.java
#	dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusPPC.java
#	dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusPTX.java
#	dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusRISCV.java
#	dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusVulkan.java
#	dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusX86.java
#	dartagnan/src/test/java/com/dat3m/dartagnan/others/miscellaneous/AnalysisTest.java
Copy link
Copy Markdown
Owner

@hernanponcedeleon hernanponcedeleon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you adding newRMWLoadExclusive for each arch if they all end up calling the general case? While I could see an argument in the factory for having the method for each arch, we do have other "common" events that use a single method, e.g. newRMWStoreExclusiveWithMo

AArch64.DSB.newISHLDBarrier() :
null;
Event fence = switch (e.getMo()) {
case Tag.C11.MO_RELEASE, Tag.C11.MO_SC -> AArch64.newDmbIshBarrier();
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are missing the mo.equals(C11.MO_ACQUIRE_RELEASE) case

@ThomasHaas
Copy link
Copy Markdown
Collaborator

Why are you adding newRMWLoadExclusive for each arch if they all end up calling the general case? While I could see an argument in the factory for having the method for each arch, we do have other "common" events that use a single method, e.g. newRMWStoreExclusiveWithMo

I agree with you but maybe from a different point of view. I think it becomes more and more unclear of whether a XYZ.newEvent factory method generates a core event or not. For parsers, you want to NOT generate core events to support compilation(*), but for the Compilation passes you need to ensure to generate only core events.
I think this is particularly true for the C11.newThreadFence events which should NOT be called by the parser (for the most part) and only during Compilation. And those can reasonably well be moved in the dedicated compilation pass.
For example, the LKMM compiler has some helper methods for the lowering that are not otherwise exposed to parsers/other callers.

(*) It is fine to generate core events from the parser, but not if you intend to support compilation to other targets on those events (at least in our current architecture).

@xeren
Copy link
Copy Markdown
Collaborator Author

xeren commented Mar 26, 2026

With the different newRMWLoadExclusive methods, I wanted to group all the usages in the program target-wise. It should have made them easier to be altered per-architecture. Ideally, Common, newRMWLoadExclusive, newLoadWithMo, newStoreWithMo and newFence are never used directly by parsers. As you noticed, my refactoring was incomplete.

Comment on lines +385 to 390
private Expression addCmpXchg(Register register, Expression address, Expression expectedAddress, Expression value,
String mo, boolean strong, OpenCLScopeContext scope, ParserRuleContext ctx) {
final Event event = EventFactory.Atomic.newCompareExchange(register, address, expectedAddress, value, mo, strong);
addScopeTag(event, scope);
append(event, ctx);
return register;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest to not return the register as it is totally unclear why this function should do that.
I would rather have the call-sites explicitly returning the register.

Comment on lines +720 to +723
private Object append(Event event, ParserRuleContext ctx) {
final int line = ctx.getStart().getLine();
return programBuilder.addChild(currentThread, event, line);
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The return type should be as specific as possible, i.e., Event.

Comment on lines +223 to +225
private Object append(Event event, ParserRuleContext ctx) {
return programBuilder.addChild(mainThread, event, ctx.getStart().getLine());
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Return type Event

Comment on lines +335 to +337
private Object append(Event event, ParserRuleContext ctx) {
return programBuilder.addChild(mainThread, event, ctx.getStart().getLine());
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Return type Event

Comment on lines +268 to +270
private Object append(Event event, ParserRuleContext ctx) {
return programBuilder.addChild(mainThread, event, ctx.getStart().getLine());
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Return type Event

Comment on lines +473 to +487
public static GenericVisibleEvent newThreadFenceAcquire() {
return newThreadFence(Tag.C11.MO_ACQUIRE);
}

public static GenericVisibleEvent newThreadFenceRelease() {
return newThreadFence(Tag.C11.MO_RELEASE);
}

public static GenericVisibleEvent newThreadFenceAcquireRelease() {
return newThreadFence(Tag.C11.MO_ACQUIRE_RELEASE);
}

public static GenericVisibleEvent newThreadFenceSequentiallyConsistent() {
return newThreadFence(Tag.C11.MO_SC);
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see much benefit in these 4 functions. They are not really much cleaner just than calling newThreadFence(Tag.C11.MO_XYZ)

Comment on lines +254 to +256
Register statusReg = strong ? null : e.getFunction().newRegister("status(" + e.getLocalId() + ")", types.getBooleanType());
ExecutionStatus optionalExecStatus = strong ? null : newExecutionStatus(statusReg, storeValue);
Local optionalUpdateCasCmpResult = strong ? null : newLocal(booleanResultRegister, expressions.makeNot(statusReg));
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just FYI, eventSequence can actually take nested lists as input and it will flatten them.
So one could write:

List<Event> optional = strong ? List.of() : List.of(
    newExectutionStatus(...),
    newLocal(...)
);

and then use the optional list as input to eventSequence. I don't know whether it's cleaner though.

Actually, I originally added this feature because I wanted to use it for fake control dependencies, where newFakeCtrlDep(Register reg) would return both the jump and the label... Well, we never used this feature and I believe that, except for me, probably no one knew that eventSequence could do this :P.

Comment on lines +88 to +92
Event optionalBarrierBefore = switch (e.getMo()) {
case C11.MO_SC -> leadingSync() ? newSync() : newLwSync();
case C11.MO_RELEASE -> newLwSync();
default -> null;
};
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You added optionalBarrierBefore/After methods that you could use here.
I think you decided halfway during the changes to add the helper function but forgot to use it for the already changed code :P

Load load = newRMWLoadExclusive(dummy, address, "");
Local localOp = newLocal(dummy, expressions.makeIntBinary(dummy, e.getOperator(), e.getOperand()));
Store store = newRMWStoreExclusiveWithMo(address, dummy, true, mo.equals(Tag.Linux.MO_MB) ? Tag.RISCV.MO_REL : "");
Store store = newRMWStoreExclusiveWithMo(address, dummy, true, false, storeMo);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a newRMWStoreConditional, no?

newAssume(expressions.makeEQ(dummy, zero)),
newRMWStoreExclusive(e.getLock(), one, true),
RISCV.newRRWFence()
newRMWStoreExclusive(e.getLock(), one, true, false),
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here: conditional store

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants