From 595744ef16a77519d6e3d8fc0e6cc1b226bb5119 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pascal=20Maseli?= Date: Mon, 12 Jan 2026 15:52:48 +0100 Subject: [PATCH 1/8] Refactor --- .../program/visitors/VisitorAsmArm.java | 90 ++-- .../program/visitors/VisitorAsmPPC.java | 44 +- .../program/visitors/VisitorAsmRISCV.java | 60 +-- .../program/visitors/VisitorAsmX86.java | 17 +- .../visitors/VisitorLitmusAArch64.java | 10 +- .../program/visitors/VisitorLitmusC.java | 257 +++++----- .../program/visitors/VisitorLitmusPPC.java | 87 ++-- .../program/visitors/VisitorLitmusPTX.java | 117 +++-- .../program/visitors/VisitorLitmusRISCV.java | 94 ++-- .../program/visitors/VisitorLitmusVulkan.java | 113 ++--- .../program/visitors/VisitorLitmusX86.java | 72 +-- .../visitors/spirv/VisitorOpsAtomic.java | 16 +- .../dartagnan/program/event/EventFactory.java | 198 +++++--- .../program/event/FenceNameRepository.java | 10 - .../processing/compilation/VisitorArm7.java | 10 +- .../processing/compilation/VisitorArm8.java | 168 +++---- .../processing/compilation/VisitorC11.java | 44 +- .../processing/compilation/VisitorIMM.java | 45 +- .../processing/compilation/VisitorLKMM.java | 2 +- .../processing/compilation/VisitorPTX.java | 27 +- .../processing/compilation/VisitorPower.java | 467 +++++------------- .../processing/compilation/VisitorRISCV.java | 122 +++-- .../compilation/VisitorSpirvOpenCL.java | 10 +- .../compilation/VisitorSpirvVulkan.java | 15 +- .../others/miscellaneous/AnalysisTest.java | 2 +- 25 files changed, 961 insertions(+), 1136 deletions(-) delete mode 100644 dartagnan/src/main/java/com/dat3m/dartagnan/program/event/FenceNameRepository.java diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorAsmArm.java b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorAsmArm.java index 01141d3544..e0921fe90d 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorAsmArm.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorAsmArm.java @@ -1,13 +1,12 @@ package com.dat3m.dartagnan.parsers.program.visitors; -import com.dat3m.dartagnan.exception.ParsingException; import com.dat3m.dartagnan.expression.Expression; import com.dat3m.dartagnan.expression.ExpressionFactory; import com.dat3m.dartagnan.expression.Type; import com.dat3m.dartagnan.expression.integers.IntCmpOp; import com.dat3m.dartagnan.expression.type.IntegerType; import com.dat3m.dartagnan.parsers.AsmArmBaseVisitor; -import com.dat3m.dartagnan.parsers.AsmArmParser; +import com.dat3m.dartagnan.parsers.AsmArmParser.*; import com.dat3m.dartagnan.parsers.program.utils.AsmUtils; import com.dat3m.dartagnan.program.Function; import com.dat3m.dartagnan.program.Register; @@ -126,7 +125,7 @@ public VisitorAsmArm(Function llvmFunction, Register returnRegister, List visitAsm(AsmArmParser.AsmContext ctx) { + public List visitAsm(AsmContext ctx) { visitChildren(ctx); List events = new ArrayList<>(); events.addAll(inputAssignments); @@ -136,27 +135,27 @@ public List visitAsm(AsmArmParser.AsmContext ctx) { } // Tells if a constraint is a numeric one, e.g. '3' - private boolean isConstraintNumeric(AsmArmParser.ConstraintContext constraint) { + private boolean isConstraintNumeric(ConstraintContext constraint) { return constraint.overlapInOutRegister() != null; } // Tells if the constraint is a memory location '=*m' - private boolean isConstraintMemoryLocation(AsmArmParser.ConstraintContext constraint) { + private boolean isConstraintMemoryLocation(ConstraintContext constraint) { return constraint.pointerToMemoryLocation() != null; } // Tells if the constraint is an output one, e.g. '=r' or '=&r' - private boolean isConstraintOutputConstraint(AsmArmParser.ConstraintContext constraint) { + private boolean isConstraintOutputConstraint(ConstraintContext constraint) { return constraint.outputOpAssign() != null; } // Tells us if the constraint is an input one, e.g. 'Q' or '*Q' or 'r' - private boolean isConstraintInputConstraint(AsmArmParser.ConstraintContext constraint) { + private boolean isConstraintInputConstraint(ConstraintContext constraint) { return constraint.memoryAddress() != null || constraint.inputOpGeneralReg() != null; } @Override - public Object visitLoad(AsmArmParser.LoadContext ctx) { + public Object visitLoad(LoadContext ctx) { Register register = (Register) ctx.register(0).accept(this); Register address = (Register) ctx.register(1).accept(this); asmInstructions.add(EventFactory.newLoad(register, address)); @@ -164,7 +163,7 @@ public Object visitLoad(AsmArmParser.LoadContext ctx) { } @Override - public Object visitLoadAcquire(AsmArmParser.LoadAcquireContext ctx) { + public Object visitLoadAcquire(LoadAcquireContext ctx) { Register register = (Register) ctx.register(0).accept(this); Register address = (Register) ctx.register(1).accept(this); asmInstructions.add(EventFactory.newLoadWithMo(register, address, Tag.ARMv8.MO_ACQ)); @@ -172,7 +171,7 @@ public Object visitLoadAcquire(AsmArmParser.LoadAcquireContext ctx) { } @Override - public Object visitLoadExclusive(AsmArmParser.LoadExclusiveContext ctx) { + public Object visitLoadExclusive(LoadExclusiveContext ctx) { Register register = (Register) ctx.register(0).accept(this); Register address = (Register) ctx.register(1).accept(this); asmInstructions.add(EventFactory.newRMWLoadExclusive(register, address)); @@ -180,7 +179,7 @@ public Object visitLoadExclusive(AsmArmParser.LoadExclusiveContext ctx) { } @Override - public Object visitLoadAcquireExclusive(AsmArmParser.LoadAcquireExclusiveContext ctx) { + public Object visitLoadAcquireExclusive(LoadAcquireExclusiveContext ctx) { Register register = (Register) ctx.register(0).accept(this); Register address = (Register) ctx.register(1).accept(this); asmInstructions.add(EventFactory.newRMWLoadExclusiveWithMo(register, address, Tag.ARMv8.MO_ACQ)); @@ -188,7 +187,7 @@ public Object visitLoadAcquireExclusive(AsmArmParser.LoadAcquireExclusiveContext } @Override - public Object visitAdd(AsmArmParser.AddContext ctx) { + public Object visitAdd(AddContext ctx) { Register resultRegister = (Register) ctx.register(0).accept(this); Register lhs = (Register) ctx.register(1).accept(this); expectedType = lhs.getType(); @@ -199,7 +198,7 @@ public Object visitAdd(AsmArmParser.AddContext ctx) { } @Override - public Object visitSub(AsmArmParser.SubContext ctx) { + public Object visitSub(SubContext ctx) { Register resultRegister = (Register) ctx.register(0).accept(this); Register lhs = (Register) ctx.register(1).accept(this); expectedType = lhs.getType(); @@ -210,7 +209,7 @@ public Object visitSub(AsmArmParser.SubContext ctx) { } @Override - public Object visitOr(AsmArmParser.OrContext ctx) { + public Object visitOr(OrContext ctx) { Register resultRegister = (Register) ctx.register(0).accept(this); Register leftRegister = (Register) ctx.register(1).accept(this); Register rightRegister = (Register) ctx.register(2).accept(this); @@ -220,7 +219,7 @@ public Object visitOr(AsmArmParser.OrContext ctx) { } @Override - public Object visitAnd(AsmArmParser.AndContext ctx) { + public Object visitAnd(AndContext ctx) { Register resultRegister = (Register) ctx.register(0).accept(this); Register leftRegister = (Register) ctx.register(1).accept(this); Register rightRegister = (Register) ctx.register(2).accept(this); @@ -230,7 +229,7 @@ public Object visitAnd(AsmArmParser.AndContext ctx) { } @Override - public Object visitStore(AsmArmParser.StoreContext ctx) { + public Object visitStore(StoreContext ctx) { Register value = (Register) ctx.register(0).accept(this); Register address = (Register) ctx.register(1).accept(this); asmInstructions.add(EventFactory.newStore(address, value)); @@ -238,7 +237,7 @@ public Object visitStore(AsmArmParser.StoreContext ctx) { } @Override - public Object visitStoreRelease(AsmArmParser.StoreReleaseContext ctx) { + public Object visitStoreRelease(StoreReleaseContext ctx) { Register value = (Register) ctx.register(0).accept(this); Register address = (Register) ctx.register(1).accept(this); asmInstructions.add(EventFactory.newStoreWithMo(address, value, Tag.ARMv8.MO_REL)); @@ -246,7 +245,7 @@ public Object visitStoreRelease(AsmArmParser.StoreReleaseContext ctx) { } @Override - public Object visitStoreExclusive(AsmArmParser.StoreExclusiveContext ctx) { + public Object visitStoreExclusive(StoreExclusiveContext ctx) { Register freshResultRegister = (Register) ctx.register(0).accept(this); Register value = (Register) ctx.register(1).accept(this); Register address = (Register) ctx.register(2).accept(this); @@ -255,7 +254,7 @@ public Object visitStoreExclusive(AsmArmParser.StoreExclusiveContext ctx) { } @Override - public Object visitStoreReleaseExclusive(AsmArmParser.StoreReleaseExclusiveContext ctx) { + public Object visitStoreReleaseExclusive(StoreReleaseExclusiveContext ctx) { Register freshResultRegister = (Register) ctx.register(0).accept(this); Register value = (Register) ctx.register(1).accept(this); Register address = (Register) ctx.register(2).accept(this); @@ -264,7 +263,7 @@ public Object visitStoreReleaseExclusive(AsmArmParser.StoreReleaseExclusiveConte } @Override - public Object visitCompare(AsmArmParser.CompareContext ctx) { + public Object visitCompare(CompareContext ctx) { Register firstRegister = (Register) ctx.register().accept(this); expectedType = firstRegister.getType(); Expression secondRegister = (Expression) ctx.expr().accept(this); @@ -273,7 +272,7 @@ public Object visitCompare(AsmArmParser.CompareContext ctx) { } @Override - public Object visitCompareBranchNonZero(AsmArmParser.CompareBranchNonZeroContext ctx) { + public Object visitCompareBranchNonZero(CompareBranchNonZeroContext ctx) { Label label = AsmUtils.getOrNewLabel(labelsDefined, ctx.Numbers().getText()); Register firstRegister = (Register) ctx.register().accept(this); Expression zero = expressions.makeZero((IntegerType) firstRegister.getType()); @@ -283,7 +282,7 @@ public Object visitCompareBranchNonZero(AsmArmParser.CompareBranchNonZeroContext } @Override - public Object visitMove(AsmArmParser.MoveContext ctx) { + public Object visitMove(MoveContext ctx) { Register toRegister = (Register) ctx.register(0).accept(this); Register fromRegister = (Register) ctx.register(1).accept(this); asmInstructions.add(EventFactory.newLocal(toRegister, fromRegister)); @@ -291,7 +290,7 @@ public Object visitMove(AsmArmParser.MoveContext ctx) { } @Override - public Object visitBranchEqual(AsmArmParser.BranchEqualContext ctx) { + public Object visitBranchEqual(BranchEqualContext ctx) { Label label = AsmUtils.getOrNewLabel(labelsDefined, ctx.Numbers().getText()); Expression expr = expressions.makeIntCmp(comparator.left(), IntCmpOp.EQ, comparator.right()); asmInstructions.add(EventFactory.newJump(expr, label)); @@ -299,7 +298,7 @@ public Object visitBranchEqual(AsmArmParser.BranchEqualContext ctx) { } @Override - public Object visitBranchNotEqual(AsmArmParser.BranchNotEqualContext ctx) { + public Object visitBranchNotEqual(BranchNotEqualContext ctx) { Label label = AsmUtils.getOrNewLabel(labelsDefined, ctx.Numbers().getText()); Expression expr = expressions.makeIntCmp(comparator.left(), IntCmpOp.NEQ, comparator.right()); asmInstructions.add(EventFactory.newJump(expr, label)); @@ -307,7 +306,7 @@ public Object visitBranchNotEqual(AsmArmParser.BranchNotEqualContext ctx) { } @Override - public Object visitLabelDefinition(AsmArmParser.LabelDefinitionContext ctx) { + public Object visitLabelDefinition(LabelDefinitionContext ctx) { String labelID = ctx.Numbers().getText(); Label label = AsmUtils.getOrNewLabel(labelsDefined, labelID); asmInstructions.add(label); @@ -320,7 +319,7 @@ public Object visitLabelDefinition(AsmArmParser.LabelDefinitionContext ctx) { // if we created a register which will be mapped to the return Register, we have to add to "pendingRegisters", // as we are going to need it while visiting the metadata to create the output assignment @Override - public Object visitRegister(AsmArmParser.RegisterContext ctx) { + public Object visitRegister(RegisterContext ctx) { String registerNumber = ctx.Numbers().getText(); int registerID = Integer.parseInt(registerNumber); if (asmRegisters.containsKey(registerID)) { @@ -345,15 +344,15 @@ public Object visitRegister(AsmArmParser.RegisterContext ctx) { // We just have to read the constraints, and based on their type, understand if they are going to be mapped // to the args registers or to the return register. @Override - public Object visitAsmMetadataEntries(AsmArmParser.AsmMetadataEntriesContext ctx) { - List constraints = ctx.constraint(); + public Object visitAsmMetadataEntries(AsmMetadataEntriesContext ctx) { + List constraints = ctx.constraint(); boolean isOutputRegistersInitialized = returnRegister == null; // We iterate until we find the first non-output constraint. Then we immediately initialize the return register // (the right-hand side of the assignment will be either a single register or an aggregate type depending on how many output constraints we processed). // We then map args registers to asm registers (we need to shift the register ID to find the corresponding args position of the matching register). // Numeric constraint just map the registerID with the corresponding numeric position. (https://llvm.org/docs/LangRef.html#input-constraints) for (int i = 0; i < constraints.size(); i++) { - AsmArmParser.ConstraintContext constraint = constraints.get(i); + ConstraintContext constraint = constraints.get(i); if (isConstraintMemoryLocation(constraint)) { isOutputRegistersInitialized = true; continue; @@ -388,7 +387,7 @@ public Object visitAsmMetadataEntries(AsmArmParser.AsmMetadataEntriesContext ctx } @Override - public Object visitValue(AsmArmParser.ValueContext ctx) { + public Object visitValue(ValueContext ctx) { checkState(expectedType instanceof IntegerType, "Expected type is not an integer type"); String valueString = ctx.Numbers().getText(); BigInteger value = new BigInteger(valueString); @@ -396,34 +395,11 @@ public Object visitValue(AsmArmParser.ValueContext ctx) { } @Override - public Object visitArmFence(AsmArmParser.ArmFenceContext ctx) { + public Object visitArmFence(ArmFenceContext ctx) { // check which type of fence it is : DataMemoryBarrier or DataSynchronizationBarrier - String type = ctx.DataMemoryBarrier() == null ? ctx.DataSynchronizationBarrier().getText() : ctx.DataMemoryBarrier().getText(); - String option = ctx.FenceArmOpt().getText(); - String barrier = type + " " + option; - Event fence = switch (barrier) { - case "dmb ish" -> - EventFactory.AArch64.DMB.newISHBarrier(); - case "dmb ishld" -> - EventFactory.AArch64.DMB.newISHLDBarrier(); - case "dmb sy" -> - EventFactory.AArch64.DMB.newSYBarrier(); - case "dmb st" -> - EventFactory.AArch64.DMB.newSTBarrier(); - case "dmb ishst" -> - EventFactory.AArch64.DMB.newISHSTBarrier(); - case "dsb ish" -> - EventFactory.AArch64.DSB.newISHBarrier(); - case "dsb ishld" -> - EventFactory.AArch64.DSB.newISHLDBarrier(); - case "dsb sy" -> - EventFactory.AArch64.DSB.newSYBarrier(); - case "dsb ishst" -> - EventFactory.AArch64.DSB.newISHSTBarrier(); - default -> - throw new ParsingException("Barrier not implemented"); - }; - asmInstructions.add(fence); + final String type = (ctx.DataMemoryBarrier() == null ? ctx.DataSynchronizationBarrier() : ctx.DataMemoryBarrier()).getText(); + final String option = ctx.FenceArmOpt().getText(); + asmInstructions.add(EventFactory.AArch64.newBarrier(type.toUpperCase(), option.toUpperCase())); return null; } } diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorAsmPPC.java b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorAsmPPC.java index a730c73e82..b2a841627d 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorAsmPPC.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorAsmPPC.java @@ -7,7 +7,7 @@ import com.dat3m.dartagnan.expression.integers.IntCmpOp; import com.dat3m.dartagnan.expression.type.IntegerType; import com.dat3m.dartagnan.parsers.AsmPPCBaseVisitor; -import com.dat3m.dartagnan.parsers.AsmPPCParser; +import com.dat3m.dartagnan.parsers.AsmPPCParser.*; import com.dat3m.dartagnan.parsers.program.utils.AsmUtils; import com.dat3m.dartagnan.program.Function; import com.dat3m.dartagnan.program.Register; @@ -52,22 +52,22 @@ public VisitorAsmPPC(Function llvmFunction, Register returnRegister, List visitAsm(AsmPPCParser.AsmContext ctx) { + public List visitAsm(AsmContext ctx) { visitChildren(ctx); List events = new ArrayList<>(); events.addAll(inputAssignments); @@ -77,7 +77,7 @@ public List visitAsm(AsmPPCParser.AsmContext ctx) { } @Override - public Object visitLoad(AsmPPCParser.LoadContext ctx) { + public Object visitLoad(LoadContext ctx) { Register register = (Register) ctx.register(0).accept(this); Register address = (Register) ctx.register(1).accept(this); asmInstructions.add(EventFactory.newLoad(register, address)); @@ -85,7 +85,7 @@ public Object visitLoad(AsmPPCParser.LoadContext ctx) { } @Override - public Object visitLoadReserve(AsmPPCParser.LoadReserveContext ctx) { + public Object visitLoadReserve(LoadReserveContext ctx) { Register register = (Register) ctx.register(0).accept(this); Register address = (Register) ctx.register(1).accept(this); expectedType = address.getType(); @@ -96,7 +96,7 @@ public Object visitLoadReserve(AsmPPCParser.LoadReserveContext ctx) { } @Override - public Object visitStore(AsmPPCParser.StoreContext ctx) { + public Object visitStore(StoreContext ctx) { Register value = (Register) ctx.register(0).accept(this); Register address = (Register) ctx.register(1).accept(this); asmInstructions.add(EventFactory.newStore(address, value)); @@ -104,7 +104,7 @@ public Object visitStore(AsmPPCParser.StoreContext ctx) { } @Override - public Object visitStoreConditional(AsmPPCParser.StoreConditionalContext ctx) { + public Object visitStoreConditional(StoreConditionalContext ctx) { Register value = (Register) ctx.register(0).accept(this); Register address = (Register) ctx.register(1).accept(this); expectedType = address.getType(); @@ -117,7 +117,7 @@ public Object visitStoreConditional(AsmPPCParser.StoreConditionalContext ctx) { } @Override - public Object visitCompare(AsmPPCParser.CompareContext ctx) { + public Object visitCompare(CompareContext ctx) { Register firstRegister = (Register) ctx.register(0).accept(this); expectedType = firstRegister.getType(); Expression secondRegister = (Expression) ctx.register(1).accept(this); @@ -126,7 +126,7 @@ public Object visitCompare(AsmPPCParser.CompareContext ctx) { } @Override - public Object visitBranchNotEqual(AsmPPCParser.BranchNotEqualContext ctx) { + public Object visitBranchNotEqual(BranchNotEqualContext ctx) { Label label = AsmUtils.getOrNewLabel(labelsDefined, ctx.Numbers().getText()); Expression expr = expressions.makeIntCmp(comparator.left(), IntCmpOp.NEQ, comparator.right()); asmInstructions.add(EventFactory.newJump(expr, label)); @@ -134,13 +134,13 @@ public Object visitBranchNotEqual(AsmPPCParser.BranchNotEqualContext ctx) { } @Override - public Object visitNop(AsmPPCParser.NopContext ctx) { + public Object visitNop(NopContext ctx) { // or 1, 1, 1 is a nop, so we do not perform anything. return null; } @Override - public Object visitAdd(AsmPPCParser.AddContext ctx) { + public Object visitAdd(AddContext ctx) { Register resultRegister = (Register) ctx.register(0).accept(this); Register leftRegister = (Register) ctx.register(1).accept(this); Register rightRegister = (Register) ctx.register(2).accept(this); @@ -150,7 +150,7 @@ public Object visitAdd(AsmPPCParser.AddContext ctx) { } @Override - public Object visitAddImmediateCarry(AsmPPCParser.AddImmediateCarryContext ctx) { + public Object visitAddImmediateCarry(AddImmediateCarryContext ctx) { // TODO : // It also sets the Carry bit of fixed-point exception register in HW // https://www.ibm.com/docs/sv/aix/7.2?topic=set-addic-ai-add-immediate-carrying-instruction @@ -164,7 +164,7 @@ public Object visitAddImmediateCarry(AsmPPCParser.AddImmediateCarryContext ctx) } @Override - public Object visitSubtractFrom(AsmPPCParser.SubtractFromContext ctx) { + public Object visitSubtractFrom(SubtractFromContext ctx) { Register resultRegister = (Register) ctx.register(0).accept(this); Register leftRegister = (Register) ctx.register(1).accept(this); Register rightRegister = (Register) ctx.register(2).accept(this); @@ -175,7 +175,7 @@ public Object visitSubtractFrom(AsmPPCParser.SubtractFromContext ctx) { @Override - public Object visitLabelDefinition(AsmPPCParser.LabelDefinitionContext ctx) { + public Object visitLabelDefinition(LabelDefinitionContext ctx) { String labelID = ctx.Numbers().getText(); Label label = AsmUtils.getOrNewLabel(labelsDefined, labelID); asmInstructions.add(label); @@ -183,7 +183,7 @@ public Object visitLabelDefinition(AsmPPCParser.LabelDefinitionContext ctx) { } @Override - public Object visitValue(AsmPPCParser.ValueContext ctx) { + public Object visitValue(ValueContext ctx) { checkState(expectedType instanceof IntegerType, "Expected type is not an integer type"); String valueString = ctx.Numbers().getText(); BigInteger value = new BigInteger(valueString); @@ -197,7 +197,7 @@ public Object visitValue(AsmPPCParser.ValueContext ctx) { // if we created a register which will be mapped to the return Register, we have to add to "pendingRegisters", // as we are going to need it while visiting the metadata to create the output assignment @Override - public Object visitRegister(AsmPPCParser.RegisterContext ctx) { + public Object visitRegister(RegisterContext ctx) { String registerNumber = ctx.Numbers().getText(); int registerID = Integer.parseInt(registerNumber); if (asmRegisters.containsKey(registerID)) { @@ -222,15 +222,15 @@ public Object visitRegister(AsmPPCParser.RegisterContext ctx) { // We just have to read the constraints, and based on their type, understand if they are going to be mapped // to the args registers or to the return register. @Override - public Object visitAsmMetadataEntries(AsmPPCParser.AsmMetadataEntriesContext ctx) { - List constraints = ctx.constraint(); + public Object visitAsmMetadataEntries(AsmMetadataEntriesContext ctx) { + List constraints = ctx.constraint(); boolean isOutputRegistersInitialized = returnRegister == null; // We iterate until we find the first non-output constraint. Then we immediately initialize the return register // (the right-hand side of the assignment will be either a single register or an aggregate type depending on how many output constraints we processed). // We then map args registers to asm registers (we need to shift the register ID to find the corresponding args position of the matching register). // Numeric constraint just map the registerID with the corresponding numeric position. (https://llvm.org/docs/LangRef.html#input-constraints) for (int i = 0; i < constraints.size(); i++) { - AsmPPCParser.ConstraintContext constraint = constraints.get(i); + ConstraintContext constraint = constraints.get(i); if (isConstraintOutputConstraint(constraint)) { continue; } @@ -261,7 +261,7 @@ public Object visitAsmMetadataEntries(AsmPPCParser.AsmMetadataEntriesContext ctx } @Override - public Object visitPpcFence(AsmPPCParser.PpcFenceContext ctx) { + public Object visitPpcFence(PpcFenceContext ctx) { String barrier = ctx.PPCFence().getText(); Event fence = switch (barrier) { case "sync" -> diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorAsmRISCV.java b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorAsmRISCV.java index 01b238abe3..06e6015070 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorAsmRISCV.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorAsmRISCV.java @@ -13,7 +13,7 @@ import com.dat3m.dartagnan.expression.integers.IntCmpOp; import com.dat3m.dartagnan.expression.type.IntegerType; import com.dat3m.dartagnan.parsers.AsmRISCVBaseVisitor; -import com.dat3m.dartagnan.parsers.AsmRISCVParser; +import com.dat3m.dartagnan.parsers.AsmRISCVParser.*; import com.dat3m.dartagnan.parsers.program.utils.AsmUtils; import com.dat3m.dartagnan.program.Function; import com.dat3m.dartagnan.program.Register; @@ -57,7 +57,7 @@ public VisitorAsmRISCV(Function llvmFunction, Register returnRegister, List visitAsm(AsmRISCVParser.AsmContext ctx) { + public List visitAsm(AsmContext ctx) { visitChildren(ctx); List events = new ArrayList<>(); events.addAll(inputAssignments); @@ -67,22 +67,22 @@ public List visitAsm(AsmRISCVParser.AsmContext ctx) { } // Tells if a constraint is a numeric one, e.g. '3' - private boolean isConstraintNumeric(AsmRISCVParser.ConstraintContext constraint) { + private boolean isConstraintNumeric(ConstraintContext constraint) { return constraint.overlapInOutRegister() != null; } // Tells if the constraint is an output one, e.g. '=r' or '=&r' - private boolean isConstraintOutputConstraint(AsmRISCVParser.ConstraintContext constraint) { + private boolean isConstraintOutputConstraint(ConstraintContext constraint) { return constraint.outputOpAssign() != null; } // Tells us if the constraint is an input one, e.g 'r' or 'A' - private boolean isConstraintInputConstraint(AsmRISCVParser.ConstraintContext constraint) { + private boolean isConstraintInputConstraint(ConstraintContext constraint) { return constraint.inputOpGeneralReg() != null; } @Override - public Object visitLoad(AsmRISCVParser.LoadContext ctx) { + public Object visitLoad(LoadContext ctx) { Register register = (Register) ctx.register(0).accept(this); Register address = (Register) ctx.register(1).accept(this); expectedType = address.getType(); @@ -93,7 +93,7 @@ public Object visitLoad(AsmRISCVParser.LoadContext ctx) { } @Override - public Object visitLoadImmediate(AsmRISCVParser.LoadImmediateContext ctx) { + public Object visitLoadImmediate(LoadImmediateContext ctx) { Register register = (Register) ctx.register().accept(this); expectedType = register.getType(); Expression value = (Expression) ctx.value().accept(this); @@ -102,23 +102,23 @@ public Object visitLoadImmediate(AsmRISCVParser.LoadImmediateContext ctx) { } @Override - public Object visitLoadExclusive(AsmRISCVParser.LoadExclusiveContext ctx) { + public Object visitLoadExclusive(LoadExclusiveContext ctx) { Register register = (Register) ctx.register(0).accept(this); Register address = (Register) ctx.register(1).accept(this); - asmInstructions.add(EventFactory.newRMWLoadExclusive(register, address)); + asmInstructions.add(EventFactory.RISCV.newRMWLoadExclusive(register, address, "")); return null; } @Override - public Object visitLoadAcquireExclusive(AsmRISCVParser.LoadAcquireExclusiveContext ctx) { + public Object visitLoadAcquireExclusive(LoadAcquireExclusiveContext ctx) { Register register = (Register) ctx.register(0).accept(this); Register address = (Register) ctx.register(1).accept(this); - asmInstructions.add(EventFactory.newRMWLoadExclusiveWithMo(register, address, Tag.RISCV.MO_ACQ)); + asmInstructions.add(EventFactory.RISCV.newRMWLoadExclusive(register, address, Tag.RISCV.MO_ACQ)); return null; } @Override - public Object visitAdd(AsmRISCVParser.AddContext ctx) { + public Object visitAdd(AddContext ctx) { Register resultRegister = (Register) ctx.register(0).accept(this); Register leftRegister = (Register) ctx.register(1).accept(this); Register rightRegister = (Register) ctx.register(2).accept(this); @@ -128,7 +128,7 @@ public Object visitAdd(AsmRISCVParser.AddContext ctx) { } @Override - public Object visitSub(AsmRISCVParser.SubContext ctx) { + public Object visitSub(SubContext ctx) { Register resultRegister = (Register) ctx.register(0).accept(this); Register leftRegister = (Register) ctx.register(1).accept(this); Register rightRegister = (Register) ctx.register(2).accept(this); @@ -138,7 +138,7 @@ public Object visitSub(AsmRISCVParser.SubContext ctx) { } @Override - public Object visitStore(AsmRISCVParser.StoreContext ctx) { + public Object visitStore(StoreContext ctx) { Register value = (Register) ctx.register(0).accept(this); Register address = (Register) ctx.register(1).accept(this); expectedType = address.getType(); @@ -150,7 +150,7 @@ public Object visitStore(AsmRISCVParser.StoreContext ctx) { @Override - public Object visitStoreConditional(AsmRISCVParser.StoreConditionalContext ctx) { + public Object visitStoreConditional(StoreConditionalContext ctx) { Register freshResultRegister = (Register) ctx.register(0).accept(this); Register value = (Register) ctx.register(1).accept(this); Register address = (Register) ctx.register(2).accept(this); @@ -159,7 +159,7 @@ public Object visitStoreConditional(AsmRISCVParser.StoreConditionalContext ctx) } @Override - public Object visitStoreConditionalRelease(AsmRISCVParser.StoreConditionalReleaseContext ctx) { + public Object visitStoreConditionalRelease(StoreConditionalReleaseContext ctx) { Register freshResultRegister = (Register) ctx.register(0).accept(this); Register value = (Register) ctx.register(1).accept(this); Register address = (Register) ctx.register(2).accept(this); @@ -168,7 +168,7 @@ public Object visitStoreConditionalRelease(AsmRISCVParser.StoreConditionalReleas } @Override - public Object visitMove(AsmRISCVParser.MoveContext ctx) { + public Object visitMove(MoveContext ctx) { Register toRegister = (Register) ctx.register(0).accept(this); Register fromRegister = (Register) ctx.register(1).accept(this); asmInstructions.add(EventFactory.newLocal(toRegister, fromRegister)); @@ -176,7 +176,7 @@ public Object visitMove(AsmRISCVParser.MoveContext ctx) { } @Override - public Object visitBranchNotEqual(AsmRISCVParser.BranchNotEqualContext ctx) { + public Object visitBranchNotEqual(BranchNotEqualContext ctx) { Label label = AsmUtils.getOrNewLabel(labelsDefined, ctx.Numbers().getText()); Register firstRegister = (Register) ctx.register(0).accept(this); Register secondRegister = (Register) ctx.register(1).accept(this); @@ -186,7 +186,7 @@ public Object visitBranchNotEqual(AsmRISCVParser.BranchNotEqualContext ctx) { } @Override - public Object visitBranchNotEqualZero(AsmRISCVParser.BranchNotEqualZeroContext ctx) { + public Object visitBranchNotEqualZero(BranchNotEqualZeroContext ctx) { Label label = AsmUtils.getOrNewLabel(labelsDefined, ctx.Numbers().getText()); Register firstRegister = (Register) ctx.register().accept(this); Expression zero = expressions.makeZero((IntegerType) firstRegister.getType()); @@ -196,7 +196,7 @@ public Object visitBranchNotEqualZero(AsmRISCVParser.BranchNotEqualZeroContext c } @Override - public Object visitLabelDefinition(AsmRISCVParser.LabelDefinitionContext ctx) { + public Object visitLabelDefinition(LabelDefinitionContext ctx) { String labelID = ctx.Numbers().getText(); Label label = AsmUtils.getOrNewLabel(labelsDefined, labelID); asmInstructions.add(label); @@ -204,7 +204,7 @@ public Object visitLabelDefinition(AsmRISCVParser.LabelDefinitionContext ctx) { } @Override - public Object visitNegate(AsmRISCVParser.NegateContext ctx){ + public Object visitNegate(NegateContext ctx){ // neg $0 $1 -> sub $0, #0, $1 Register destinationRegister = (Register) ctx.register(0).accept(this); Register sourceRegister = (Register) ctx.register(1).accept(this); @@ -215,17 +215,17 @@ public Object visitNegate(AsmRISCVParser.NegateContext ctx){ } @Override - public Object visitAtomicAdd(AsmRISCVParser.AtomicAddContext ctx){ + public Object visitAtomicAdd(AtomicAddContext ctx){ throw new UnsupportedOperationException(ctx.AtomicAdd().getText()); } @Override - public Object visitAtomicAddRelease(AsmRISCVParser.AtomicAddReleaseContext ctx){ + public Object visitAtomicAddRelease(AtomicAddReleaseContext ctx){ throw new UnsupportedOperationException(ctx.AtomicAddRelease().getText()); } @Override - public Object visitAtomicAddAcquireRelease(AsmRISCVParser.AtomicAddAcquireReleaseContext ctx){ + public Object visitAtomicAddAcquireRelease(AtomicAddAcquireReleaseContext ctx){ throw new UnsupportedOperationException(ctx.AtomicAddAcquireRelease().getText()); } @@ -235,7 +235,7 @@ public Object visitAtomicAddAcquireRelease(AsmRISCVParser.AtomicAddAcquireReleas // if we created a register which will be mapped to the return Register, we have to add to "pendingRegisters", // as we are going to need it while visiting the metadata to create the output assignment @Override - public Object visitRegister(AsmRISCVParser.RegisterContext ctx) { + public Object visitRegister(RegisterContext ctx) { String registerNumber = ctx.Numbers().getText(); int registerID = Integer.parseInt(registerNumber); if (asmRegisters.containsKey(registerID)) { @@ -260,14 +260,14 @@ public Object visitRegister(AsmRISCVParser.RegisterContext ctx) { // We just have to read the constraints, and based on their type, understand if they are going to be mapped // to the args registers or to the return register. @Override - public Object visitAsmMetadataEntries(AsmRISCVParser.AsmMetadataEntriesContext ctx) { - List constraints = ctx.constraint(); + public Object visitAsmMetadataEntries(AsmMetadataEntriesContext ctx) { + List constraints = ctx.constraint(); boolean isOutputRegistersInitialized = returnRegister == null; // We iterate until we find the first non-output constraint. Then we immediately initialize the return register // (the right-hand side of the assignment will be either a single register or an aggregate type depending on how many output constraints we processed). // We then map args registers to asm registers (we need to shift the register ID to find the corresponding args position of the matching register). for (int i = 0; i < constraints.size(); i++) { - AsmRISCVParser.ConstraintContext constraint = constraints.get(i); + ConstraintContext constraint = constraints.get(i); if (isConstraintOutputConstraint(constraint)) { continue; } @@ -302,7 +302,7 @@ public Object visitAsmMetadataEntries(AsmRISCVParser.AsmMetadataEntriesContext c } @Override - public Object visitRiscvFence(AsmRISCVParser.RiscvFenceContext ctx) { + public Object visitRiscvFence(RiscvFenceContext ctx) { String mo = ctx.fenceOptions().mode; Event fence = switch(mo) { case "r r" -> EventFactory.RISCV.newRRFence(); @@ -323,7 +323,7 @@ public Object visitRiscvFence(AsmRISCVParser.RiscvFenceContext ctx) { } @Override - public Object visitValue(AsmRISCVParser.ValueContext ctx) { + public Object visitValue(ValueContext ctx) { checkState(expectedType instanceof IntegerType, "Expected type is not an integer type"); String valueString = ctx.Numbers().getText(); BigInteger value = new BigInteger(valueString); diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorAsmX86.java b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorAsmX86.java index b51ac241e1..ad935c3ae5 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorAsmX86.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorAsmX86.java @@ -3,7 +3,7 @@ import com.dat3m.dartagnan.exception.ParsingException; import com.dat3m.dartagnan.expression.Expression; import com.dat3m.dartagnan.parsers.AsmX86BaseVisitor; -import com.dat3m.dartagnan.parsers.AsmX86Parser; +import com.dat3m.dartagnan.parsers.AsmX86Parser.*; import com.dat3m.dartagnan.program.Function; import com.dat3m.dartagnan.program.Register; import com.dat3m.dartagnan.program.event.Event; @@ -19,19 +19,18 @@ public class VisitorAsmX86 extends AsmX86BaseVisitor { public VisitorAsmX86(Function llvmFunction, Register returnRegister, List llvmArguments) {} @Override - public List visitAsm(AsmX86Parser.AsmContext ctx) { + public List visitAsm(AsmContext ctx) { visitChildren(ctx); return new ArrayList<>(asmInstructions); } @Override - public Object visitX86Fence(AsmX86Parser.X86FenceContext ctx) { - String barrier = ctx.X86Fence().getText(); - Event fence = switch (barrier) { - case "mfence" -> - EventFactory.X86.newMemoryFence(); - default -> - throw new ParsingException("Barrier not implemented"); + public Object visitX86Fence(X86FenceContext ctx) { + final Event fence = switch (ctx.X86Fence().getText()) { + case "mfence" -> EventFactory.X86.newMemoryFence(); + case "lfence" -> EventFactory.X86.newLoadFence(); + case "sfence" -> EventFactory.X86.newStoreFence(); + default -> throw new ParsingException("Unknown barrier '%s'", ctx.X86Fence()); }; asmInstructions.add(fence); return null; diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusAArch64.java b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusAArch64.java index e0562829c7..8f1d2cb8dc 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusAArch64.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusAArch64.java @@ -229,7 +229,7 @@ public Object visitLoadExclusive(LoadExclusiveContext ctx) { final Register register = shrinkRegister(r64, ctx.rD32, inst.halfWordSize, inst.byteSize); final Expression address = parseAddress(ctx.address()); final String mo = inst.acquire ? MO_ACQ : ""; - add(EventFactory.newRMWLoadExclusiveWithMo(register, address, mo)); + add(EventFactory.AArch64.newRMWLoadExclusive(register, address, mo)); addRegister64Update(r64, register); return null; } @@ -303,7 +303,7 @@ public Object visitSwap(SwapContext ctx) { } // TODO: Can lReg and sReg match? If so, we get a problem here. - final Xchg xchg = EventFactory.Common.newXchg(lReg, address, value); + final Event xchg = EventFactory.Common.newXchg(lReg, address, value); xchg.addTags(mo); xchg.setMetadata(SWP_PRINTER); @@ -345,7 +345,7 @@ public Object visitCas(CasContext ctx) { mo.add(MO_REL); } - final CAS cas = EventFactory.Common.newCAS(rs, address, cmpVal, val); + final Event cas = EventFactory.Common.newCAS(rs, address, cmpVal, val); cas.addTags(mo); cas.setMetadata(CAS_PRINTER); @@ -467,7 +467,7 @@ public Object visitLoadOp(LoadOpContext ctx) { } final Expression address = parseAddress(ctx.address()); - final RMWFetchOp ldOp = EventFactory.Common.newRmwFetchOp(rt, address, info.op, operand); + final Event ldOp = EventFactory.Common.newRmwFetchOp(rt, address, info.op, operand); ldOp.addTags(mo); ldOp.setMetadata(LDOP_PRINTER); @@ -509,7 +509,7 @@ public Object visitBranchLabel(BranchLabelContext ctx) { @Override public Object visitFence(FenceContext ctx) { - return add(EventFactory.newFenceOpt(ctx.Fence().getText(), ctx.opt)); + return add(EventFactory.AArch64.newBarrier(ctx.Fence().getText(), ctx.opt)); } @Override diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusC.java b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusC.java index b1e18c4fc2..5b76f82f60 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusC.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusC.java @@ -8,7 +8,7 @@ import com.dat3m.dartagnan.expression.type.IntegerType; import com.dat3m.dartagnan.expression.type.TypeFactory; import com.dat3m.dartagnan.parsers.LitmusCBaseVisitor; -import com.dat3m.dartagnan.parsers.LitmusCParser; +import com.dat3m.dartagnan.parsers.LitmusCParser.*; import com.dat3m.dartagnan.parsers.program.utils.ProgramBuilder; import com.dat3m.dartagnan.program.Program; import com.dat3m.dartagnan.program.Register; @@ -16,7 +16,6 @@ import com.dat3m.dartagnan.program.event.EventFactory; import com.dat3m.dartagnan.program.event.Tag; import com.dat3m.dartagnan.program.event.core.*; -import com.dat3m.dartagnan.program.event.lang.catomic.*; import com.dat3m.dartagnan.program.memory.MemoryObject; import java.util.ArrayList; @@ -45,14 +44,14 @@ public VisitorLitmusC(){ // Entry point @Override - public Program visitMain(LitmusCParser.MainContext ctx) { + public Program visitMain(MainContext ctx) { isOpenCL = ctx.LitmusLanguage().getText().equals("OPENCL"); - for (LitmusCParser.ThreadDeclaratorContext threadDeclaratorContext : ctx.threadDeclarator()) { + for (ThreadDeclaratorContext threadDeclaratorContext : ctx.threadDeclarator()) { visitThreadDeclarator(threadDeclaratorContext); } visitVariableDeclaratorList(ctx.variableDeclaratorList()); int threadIndex = 0; - for (LitmusCParser.ThreadContentContext threadContentContext : ctx.threadContent()) { + for (ThreadContentContext threadContentContext : ctx.threadContent()) { scope = currentThread = threadIds.get(threadIndex++); visitThreadContent(threadContentContext); } @@ -65,7 +64,7 @@ public Program visitMain(LitmusCParser.MainContext ctx) { // Variable declarator list, e.g., { int 0:a=0; int 1:b=1; int x=2; } @Override - public Object visitGlobalDeclaratorLocation(LitmusCParser.GlobalDeclaratorLocationContext ctx) { + public Object visitGlobalDeclaratorLocation(GlobalDeclaratorLocationContext ctx) { if (ctx.initConstantValue() != null) { IntLiteral value = expressions.parseValue(ctx.initConstantValue().constant().getText(), archType); programBuilder.initLocEqConst(ctx.varName().getText(), value); @@ -74,7 +73,7 @@ public Object visitGlobalDeclaratorLocation(LitmusCParser.GlobalDeclaratorLocati } @Override - public Object visitGlobalDeclaratorRegister(LitmusCParser.GlobalDeclaratorRegisterContext ctx) { + public Object visitGlobalDeclaratorRegister(GlobalDeclaratorRegisterContext ctx) { if (ctx.initConstantValue() != null) { IntLiteral value = expressions.parseValue(ctx.initConstantValue().constant().getText(), archType); programBuilder.initRegEqConst(ctx.threadId().id,ctx.varName().getText(), value); @@ -83,7 +82,7 @@ public Object visitGlobalDeclaratorRegister(LitmusCParser.GlobalDeclaratorRegist } @Override - public Object visitGlobalDeclaratorLocationLocation(LitmusCParser.GlobalDeclaratorLocationLocationContext ctx) { + public Object visitGlobalDeclaratorLocationLocation(GlobalDeclaratorLocationLocationContext ctx) { if(ctx.Ast() == null) { programBuilder.initLocEqLocPtr(ctx.varName(0).getText(), ctx.varName(1).getText()); } else { @@ -99,7 +98,7 @@ public Object visitGlobalDeclaratorLocationLocation(LitmusCParser.GlobalDeclarat } @Override - public Object visitGlobalDeclaratorRegisterLocation(LitmusCParser.GlobalDeclaratorRegisterLocationContext ctx) { + public Object visitGlobalDeclaratorRegisterLocation(GlobalDeclaratorRegisterLocationContext ctx) { // FIXME: We visit declarators before threads, so we need to create threads early if(ctx.Ast() == null){ programBuilder.initRegEqLocPtr(ctx.threadId().id, ctx.varName(0).getText(), ctx.varName(1).getText(), archType); @@ -116,7 +115,7 @@ public Object visitGlobalDeclaratorRegisterLocation(LitmusCParser.GlobalDeclarat } @Override - public Object visitGlobalDeclaratorArray(LitmusCParser.GlobalDeclaratorArrayContext ctx) { + public Object visitGlobalDeclaratorArray(GlobalDeclaratorArrayContext ctx) { String name = ctx.varName().getText(); Integer size = ctx.DigitSequence() != null ? Integer.parseInt(ctx.DigitSequence().getText()) : null; @@ -127,7 +126,7 @@ public Object visitGlobalDeclaratorArray(LitmusCParser.GlobalDeclaratorArrayCont if(ctx.initArray() != null){ if(size == null || ctx.initArray().arrayElement().size() == size){ List values = new ArrayList<>(); - for(LitmusCParser.ArrayElementContext elCtx : ctx.initArray().arrayElement()){ + for(ArrayElementContext elCtx : ctx.initArray().arrayElement()){ if(elCtx.constant() != null){ values.add(expressions.parseValue(elCtx.constant().getText(), archType)); } else { @@ -157,7 +156,7 @@ public Object visitGlobalDeclaratorArray(LitmusCParser.GlobalDeclaratorArrayCont // Threads (the program itself) @Override - public Object visitThreadDeclarator(LitmusCParser.ThreadDeclaratorContext ctx) { + public Object visitThreadDeclarator(ThreadDeclaratorContext ctx) { scope = currentThread = ctx.threadId().id; threadIds.add(currentThread); if (isOpenCL && ctx.threadScope() != null) { @@ -173,17 +172,17 @@ public Object visitThreadDeclarator(LitmusCParser.ThreadDeclaratorContext ctx) { } @Override - public Object visitThreadContent(LitmusCParser.ThreadContentContext ctx) { + public Object visitThreadContent(ThreadContentContext ctx) { visitThreadArguments(ctx.threadArguments()); - for(LitmusCParser.ExpressionContext expressionContext : ctx.expression()) + for(ExpressionContext expressionContext : ctx.expression()) expressionContext.accept(this); return null; } @Override - public Object visitThreadArguments(LitmusCParser.ThreadArgumentsContext ctx){ + public Object visitThreadArguments(ThreadArgumentsContext ctx){ if(ctx != null){ - for(LitmusCParser.ThreadArgumentContext threadArgumentContext : ctx.threadArgument()){ + for(ThreadArgumentContext threadArgumentContext : ctx.threadArgument()){ threadArgumentContext.accept(this); } } @@ -191,7 +190,7 @@ public Object visitThreadArguments(LitmusCParser.ThreadArgumentsContext ctx){ } @Override - public Object visitThreadArgument(LitmusCParser.ThreadArgumentContext ctx) { + public Object visitThreadArgument(ThreadArgumentContext ctx) { // TODO: Possibly parse attributes/type modifiers (const, ...) // For now, herd7 also seems to ignore most modifiers, in particular the atomic one. String name = ctx.varName().getText(); @@ -209,12 +208,12 @@ public Object visitThreadArgument(LitmusCParser.ThreadArgumentContext ctx) { object.addFeatureTag(Tag.OpenCL.DEFAULT_SPACE); } } - programBuilder.addChild(currentThread, EventFactory.newLocal(register, object)); + append(EventFactory.newLocal(register, object)); return null; } @Override - public Object visitIfExpression(LitmusCParser.IfExpressionContext ctx) { + public Object visitIfExpression(IfExpressionContext ctx) { Expression expr = (Expression) ctx.re().accept(this); ifId++; @@ -222,38 +221,38 @@ public Object visitIfExpression(LitmusCParser.IfExpressionContext ctx) { Label endL = programBuilder.getOrCreateLabel(currentThread,"end_" + ifId); IfAsJump ifEvent = EventFactory.newIfJumpUnless(expressions.makeBooleanCast(expr), elseL, endL); - programBuilder.addChild(currentThread, ifEvent); + append(ifEvent); - for(LitmusCParser.ExpressionContext expressionContext : ctx.expression()) + for(ExpressionContext expressionContext : ctx.expression()) expressionContext.accept(this); CondJump jumpToEnd = EventFactory.newGoto(endL); - programBuilder.addChild(currentThread, jumpToEnd); + append(jumpToEnd); - programBuilder.addChild(currentThread, elseL); + append(elseL); if(ctx.elseExpression() != null){ ctx.elseExpression().accept(this); } - programBuilder.addChild(currentThread, endL); + append(endL); return null; } @Override - public Object visitWhileExpression(LitmusCParser.WhileExpressionContext ctx) { + public Object visitWhileExpression(WhileExpressionContext ctx) { whileId++; Label headL = programBuilder.getOrCreateLabel(currentThread,"head_" + whileId); Label endL = programBuilder.getOrCreateLabel(currentThread,"end_" + whileId); - programBuilder.addChild(currentThread, headL); + append(headL); Expression expr = (Expression) ctx.re().accept(this); - programBuilder.addChild(currentThread, EventFactory.newJumpUnless(expr, endL)); + append(EventFactory.newJumpUnless(expr, endL)); - for(LitmusCParser.ExpressionContext expressionContext : ctx.expression()) { + for(ExpressionContext expressionContext : ctx.expression()) { expressionContext.accept(this); } - programBuilder.addChild(currentThread, EventFactory.newGoto(headL)); - programBuilder.addChild(currentThread, endL); + append(EventFactory.newGoto(headL)); + append(endL); return null; } @@ -263,188 +262,184 @@ public Object visitWhileExpression(LitmusCParser.WhileExpressionContext ctx) { // Returns new value (the value after computation) @Override - public Expression visitReAtomicOpReturn(LitmusCParser.ReAtomicOpReturnContext ctx){ + public Expression visitReAtomicOpReturn(ReAtomicOpReturnContext ctx){ Register register = getReturnRegister(true); Expression value = returnExpressionOrOne(ctx.value); Event event = EventFactory.Linux.newRMWOpReturn(getAddress(ctx.address), register, value, ctx.op, ctx.mo); - programBuilder.addChild(currentThread, event); + append(event); return register; } // Returns old value (the value before computation) @Override - public Expression visitReAtomicFetchOp(LitmusCParser.ReAtomicFetchOpContext ctx){ + public Expression visitReAtomicFetchOp(ReAtomicFetchOpContext ctx){ Register register = getReturnRegister(true); Expression value = returnExpressionOrOne(ctx.value); Event event = EventFactory.Linux.newRMWFetchOp(getAddress(ctx.address), register, value, ctx.op, ctx.mo); - programBuilder.addChild(currentThread, event); + append(event); return register; } @Override - public Expression visitC11AtomicOp(LitmusCParser.C11AtomicOpContext ctx) { + public Expression visitC11AtomicOp(C11AtomicOpContext ctx) { Register register = getReturnRegister(true); Expression value = returnExpressionOrOne(ctx.value); Expression address = getAddress(ctx.address); Event event = EventFactory.Atomic.newFetchOp(register, address, value, ctx.op, ctx.c11Mo().mo); addScopeTag(event, ctx.openCLScope()); - programBuilder.addChild(currentThread, event); + append(event); return register; } @Override - public Expression visitReAtomicOpAndTest(LitmusCParser.ReAtomicOpAndTestContext ctx){ + public Expression visitReAtomicOpAndTest(ReAtomicOpAndTestContext ctx){ Register register = getReturnRegister(true); Expression value = returnExpressionOrOne(ctx.value); Event event = EventFactory.Linux.newRMWOpAndTest(getAddress(ctx.address), register, value, ctx.op); - programBuilder.addChild(currentThread, event); + append(event); return register; } // Returns non-zero if the addition was executed, zero otherwise @Override - public Expression visitReAtomicAddUnless(LitmusCParser.ReAtomicAddUnlessContext ctx){ + public Expression visitReAtomicAddUnless(ReAtomicAddUnlessContext ctx){ Register register = getReturnRegister(true); Expression value = (Expression) ctx.value.accept(this); Expression cmp = (Expression) ctx.cmp.accept(this); - programBuilder.addChild(currentThread, EventFactory.Linux.newRMWAddUnless(getAddress(ctx.address), register, cmp, value)); + append(EventFactory.Linux.newRMWAddUnless(getAddress(ctx.address), register, cmp, value)); return register; } @Override - public Expression visitReC11AtomicXchg(LitmusCParser.ReC11AtomicXchgContext ctx) { + public Expression visitReC11AtomicXchg(ReC11AtomicXchgContext ctx) { Register register = getReturnRegister(true); Expression value = (Expression) ctx.value.accept(this); Expression address = getAddress(ctx.address); Event event = EventFactory.Atomic.newExchange(register, address, value, Tag.C11.MO_SC); addScopeTag(event, null); - programBuilder.addChild(currentThread, event); + append(event); return register; } @Override - public Expression visitReC11AtomicXchgExplicit(LitmusCParser.ReC11AtomicXchgExplicitContext ctx) { + public Expression visitReC11AtomicXchgExplicit(ReC11AtomicXchgExplicitContext ctx) { Register register = getReturnRegister(true); Expression value = (Expression) ctx.value.accept(this); Expression address = getAddress(ctx.address); Event event = EventFactory.Atomic.newExchange(register, address, value, ctx.c11Mo().mo); addScopeTag(event, ctx.openCLScope()); - programBuilder.addChild(currentThread, event); + append(event); return register; } @Override - public Expression visitReXchg(LitmusCParser.ReXchgContext ctx){ + public Expression visitReXchg(ReXchgContext ctx){ Register register = getReturnRegister(true); Expression value = (Expression) ctx.value.accept(this); Event event = EventFactory.Linux.newRMWExchange(getAddress(ctx.address), register, value, ctx.mo); - programBuilder.addChild(currentThread, event); + append(event); return register; } @Override - public Expression visitReC11SCmpXchgExplicit(LitmusCParser.ReC11SCmpXchgExplicitContext ctx) { + public Expression visitReC11SCmpXchgExplicit(ReC11SCmpXchgExplicitContext ctx) { Register register = getReturnRegister(true); Expression value = (Expression)ctx.value.accept(this); Expression address = getAddress(ctx.address); Expression expectedAdd = getAddress(ctx.expectedAdd); String mo = ctx.c11Mo(0).mo; - Event event = EventFactory.Atomic.newCompareExchange(register, address, expectedAdd, value, mo, true); - addScopeTag(event, ctx.openCLScope()); - programBuilder.addChild(currentThread, event); - return register; + return addCmpXchg(register, address, expectedAdd, value, mo, true, ctx.openCLScope()); } @Override - public Expression visitReC11SCmpXchg(LitmusCParser.ReC11SCmpXchgContext ctx) { + public Expression visitReC11SCmpXchg(ReC11SCmpXchgContext ctx) { Register register = getReturnRegister(true); Expression value = (Expression)ctx.value.accept(this); Expression address = getAddress(ctx.address); Expression expectedAdd = getAddress(ctx.expectedAdd); - Event event = EventFactory.Atomic.newCompareExchange(register, address, expectedAdd, value, - C11.DEFAULT_MO, true); - addScopeTag(event, null); - programBuilder.addChild(currentThread, event); - return register; + return addCmpXchg(register, address, expectedAdd, value, C11.DEFAULT_MO, true, null); } @Override - public Expression visitReC11WCmpXchgExplicit(LitmusCParser.ReC11WCmpXchgExplicitContext ctx) { + public Expression visitReC11WCmpXchgExplicit(ReC11WCmpXchgExplicitContext ctx) { Register register = getReturnRegister(true); Expression value = (Expression)ctx.value.accept(this); Expression address = getAddress(ctx.address); Expression expectedAdd = getAddress(ctx.expectedAdd); String mo = ctx.c11Mo(0).mo; - Event event = EventFactory.Atomic.newCompareExchange(register, address, expectedAdd, value, mo, false); - addScopeTag(event, ctx.openCLScope()); - programBuilder.addChild(currentThread, event); - return register; + return addCmpXchg(register, address, expectedAdd, value, mo, false, ctx.openCLScope()); } @Override - public Expression visitReC11WCmpXchg(LitmusCParser.ReC11WCmpXchgContext ctx) { + public Expression visitReC11WCmpXchg(ReC11WCmpXchgContext ctx) { Register register = getReturnRegister(true); Expression value = (Expression)ctx.value.accept(this); Expression address = getAddress(ctx.address); Expression expectedAdd = getAddress(ctx.expectedAdd); - Event event = EventFactory.Atomic.newCompareExchange(register, address, expectedAdd, value, - C11.DEFAULT_MO, false); - addScopeTag(event, null); - programBuilder.addChild(currentThread, event); + return addCmpXchg(register, address, expectedAdd, value, C11.DEFAULT_MO, false, null); + } + + private Expression addCmpXchg(Register register, Expression address, Expression expectedAddress, Expression value, + String mo, boolean strong, OpenCLScopeContext scope) { + final Event event = EventFactory.Atomic.newCompareExchange(register, address, expectedAddress, value, mo, strong); + addScopeTag(event, scope); + append(event); return register; } @Override - public Expression visitReCmpXchg(LitmusCParser.ReCmpXchgContext ctx){ + public Expression visitReCmpXchg(ReCmpXchgContext ctx){ Register register = getReturnRegister(true); Expression cmp = (Expression)ctx.cmp.accept(this); Expression value = (Expression)ctx.value.accept(this); Event event = EventFactory.Linux.newRMWCompareExchange(getAddress(ctx.address), register, cmp, value, ctx.mo); - programBuilder.addChild(currentThread, event); + append(event); return register; } - @Override public Expression visitReC11LoadExplicit(LitmusCParser.ReC11LoadExplicitContext ctx) { + @Override + public Expression visitReC11LoadExplicit(ReC11LoadExplicitContext ctx) { Register register = getReturnRegister(true); Expression address = getAddress(ctx.address); - AtomicLoad event = EventFactory.Atomic.newLoad(register, address, ctx.c11Mo().mo); + Event event = EventFactory.Atomic.newLoad(register, address, ctx.c11Mo().mo); addScopeTag(event, ctx.openCLScope()); - programBuilder.addChild(currentThread, event); + append(event); return register; } - @Override public Expression visitReC11Load(LitmusCParser.ReC11LoadContext ctx) { + @Override + public Expression visitReC11Load(ReC11LoadContext ctx) { Register register = getReturnRegister(true); Expression address = getAddress(ctx.address); - AtomicLoad event = EventFactory.Atomic.newLoad(register, address, C11.DEFAULT_MO); + Event event = EventFactory.Atomic.newLoad(register, address, C11.DEFAULT_MO); addScopeTag(event, null); - programBuilder.addChild(currentThread, event); + append(event); return register; } @Override - public Expression visitReLoad(LitmusCParser.ReLoadContext ctx){ + public Expression visitReLoad(ReLoadContext ctx){ Register register = getReturnRegister(true); Event event = EventFactory.Linux.newLKMMLoad(register, getAddress(ctx.address), ctx.mo); - programBuilder.addChild(currentThread, event); + append(event); return register; } @Override - public Expression visitReReadOnce(LitmusCParser.ReReadOnceContext ctx){ + public Expression visitReReadOnce(ReReadOnceContext ctx){ Register register = getReturnRegister(true); Event event = EventFactory.Linux.newLKMMLoad(register, getAddress(ctx.address), ctx.mo); - programBuilder.addChild(currentThread, event); + append(event); return register; } @Override - public Expression visitReReadNa(LitmusCParser.ReReadNaContext ctx){ + public Expression visitReReadNa(ReReadNaContext ctx){ Register register = getReturnRegister(true); Expression address = getAddress(ctx.address); Load event = EventFactory.newLoadWithMo(register, address, C11.NONATOMIC); - programBuilder.addChild(currentThread, event); + append(event); return register; } @@ -452,7 +447,7 @@ public Expression visitReReadNa(LitmusCParser.ReReadNaContext ctx){ // Return expressions (register for return value is optional) @Override - public Expression visitReOpCompare(LitmusCParser.ReOpCompareContext ctx){ + public Expression visitReOpCompare(ReOpCompareContext ctx){ Register register = getReturnRegister(false); Expression v1 = (Expression)ctx.re(0).accept(this); Expression v2 = (Expression)ctx.re(1).accept(this); @@ -461,7 +456,7 @@ public Expression visitReOpCompare(LitmusCParser.ReOpCompareContext ctx){ } @Override - public Expression visitReOpArith(LitmusCParser.ReOpArithContext ctx){ + public Expression visitReOpArith(ReOpArithContext ctx){ Register register = getReturnRegister(false); Expression v1 = (Expression)ctx.re(0).accept(this); Expression v2 = (Expression)ctx.re(1).accept(this); @@ -470,7 +465,7 @@ public Expression visitReOpArith(LitmusCParser.ReOpArithContext ctx){ } @Override - public Expression visitReOpBool(LitmusCParser.ReOpBoolContext ctx){ + public Expression visitReOpBool(ReOpBoolContext ctx){ Register register = getReturnRegister(false); Expression v1 = (Expression)ctx.re(0).accept(this); Expression v2 = (Expression)ctx.re(1).accept(this); @@ -481,7 +476,7 @@ public Expression visitReOpBool(LitmusCParser.ReOpBoolContext ctx){ } @Override - public Expression visitReOpBoolNot(LitmusCParser.ReOpBoolNotContext ctx){ + public Expression visitReOpBoolNot(ReOpBoolNotContext ctx){ Register register = getReturnRegister(false); Expression v = (Expression)ctx.re().accept(this); v = expressions.makeBooleanCast(v); @@ -490,24 +485,24 @@ public Expression visitReOpBoolNot(LitmusCParser.ReOpBoolNotContext ctx){ } @Override - public Expression visitReBoolConst(LitmusCParser.ReBoolConstContext ctx){ + public Expression visitReBoolConst(ReBoolConstContext ctx){ return expressions.makeValue(ctx.boolConst().value); } @Override - public Expression visitReParenthesis(LitmusCParser.ReParenthesisContext ctx){ + public Expression visitReParenthesis(ReParenthesisContext ctx){ return (Expression)ctx.re().accept(this); } @Override - public Expression visitReCast(LitmusCParser.ReCastContext ctx){ + public Expression visitReCast(ReCastContext ctx){ Register register = getReturnRegister(false); Expression result = (Expression)ctx.re().accept(this); return assignToReturnRegister(register, result); } @Override - public Expression visitReVarName(LitmusCParser.ReVarNameContext ctx){ + public Expression visitReVarName(ReVarNameContext ctx){ Register register = getReturnRegister(false); Expression variable = visitVarName(ctx.varName()); if (variable instanceof Register result) { @@ -517,7 +512,7 @@ public Expression visitReVarName(LitmusCParser.ReVarNameContext ctx){ } @Override - public Expression visitReConst(LitmusCParser.ReConstContext ctx){ + public Expression visitReConst(ReConstContext ctx){ Register register = getReturnRegister(false); IntLiteral result = expressions.parseValue(ctx.getText(), archType); return assignToReturnRegister(register, result); @@ -528,46 +523,46 @@ public Expression visitReConst(LitmusCParser.ReConstContext ctx){ // NonReturn expressions (all other return expressions are reduced to these ones) @Override - public Object visitNreAtomicOp(LitmusCParser.NreAtomicOpContext ctx){ + public Object visitNreAtomicOp(NreAtomicOpContext ctx){ Expression value = returnExpressionOrOne(ctx.value); Event event = EventFactory.Linux.newRMWOp(getAddress(ctx.address), value, ctx.op); - return programBuilder.addChild(currentThread, event); + return append(event); } @Override - public Object visitNreStore(LitmusCParser.NreStoreContext ctx){ + public Object visitNreStore(NreStoreContext ctx){ Expression value = (Expression)ctx.value.accept(this); Event event = EventFactory.Linux.newLKMMStore(getAddress(ctx.address), value, ctx.mo); - return programBuilder.addChild(currentThread, event); + return append(event); } @Override - public Object visitNreWriteOnce(LitmusCParser.NreWriteOnceContext ctx){ + public Object visitNreWriteOnce(NreWriteOnceContext ctx){ Expression value = (Expression)ctx.value.accept(this); Event event = EventFactory.Linux.newLKMMStore(getAddress(ctx.address), value, ctx.mo); - return programBuilder.addChild(currentThread, event); + return append(event); } @Override - public Object visitNreC11StoreExplicit(LitmusCParser.NreC11StoreExplicitContext ctx) { + public Object visitNreC11StoreExplicit(NreC11StoreExplicitContext ctx) { Expression value = (Expression)ctx.value.accept(this); Expression address = getAddress(ctx.address); - AtomicStore event = EventFactory.Atomic.newStore(address, value, ctx.c11Mo().mo); + Event event = EventFactory.Atomic.newStore(address, value, ctx.c11Mo().mo); addScopeTag(event, ctx.openCLScope()); - return programBuilder.addChild(currentThread, event); + return append(event); } @Override - public Object visitNreC11Store(LitmusCParser.NreC11StoreContext ctx) { + public Object visitNreC11Store(NreC11StoreContext ctx) { Expression value = (Expression)ctx.value.accept(this); Expression address = getAddress(ctx.address); - AtomicStore event = EventFactory.Atomic.newStore(address, value, C11.DEFAULT_MO); + Event event = EventFactory.Atomic.newStore(address, value, C11.DEFAULT_MO); addScopeTag(event, null); - return programBuilder.addChild(currentThread, event); + return append(event); } @Override - public Object visitNreAssignment(LitmusCParser.NreAssignmentContext ctx){ + public Object visitNreAssignment(NreAssignmentContext ctx){ Expression variable = (Expression)ctx.varName().accept(this); if(ctx.Ast() == null){ if(variable instanceof Register reg){ @@ -584,13 +579,13 @@ public Object visitNreAssignment(LitmusCParser.NreAssignmentContext ctx){ if (isOpenCL) { event.addTags(Tag.OpenCL.DEFAULT_WEAK_SCOPE); } - return programBuilder.addChild(currentThread, event); + return append(event); } throw new ParsingException("Invalid syntax near " + ctx.getText()); } @Override - public Object visitNreRegDeclaration(LitmusCParser.NreRegDeclarationContext ctx){ + public Object visitNreRegDeclaration(NreRegDeclarationContext ctx){ Register register = programBuilder.getRegister(scope, ctx.varName().getText()); if(register == null){ register = programBuilder.getOrNewRegister(scope, ctx.varName().getText(), archType); @@ -604,32 +599,32 @@ public Object visitNreRegDeclaration(LitmusCParser.NreRegDeclarationContext ctx) } @Override - public Object visitNreC11Fence(LitmusCParser.NreC11FenceContext ctx) { - AtomicThreadFence fence = EventFactory.Atomic.newFence(ctx.c11Mo().mo); - return programBuilder.addChild(currentThread, fence); + public Object visitNreC11Fence(NreC11FenceContext ctx) { + Event fence = EventFactory.Atomic.newFence(ctx.c11Mo().mo); + return append(fence); } @Override - public Object visitNreFence(LitmusCParser.NreFenceContext ctx){ - return programBuilder.addChild(currentThread, EventFactory.Linux.newLKMMFence(ctx.name)); + public Object visitNreFence(NreFenceContext ctx){ + return append(EventFactory.Linux.newLKMMFence(ctx.name)); } @Override - public Object visitNreOpenCLFence(LitmusCParser.NreOpenCLFenceContext ctx){ - AtomicThreadFence fence = EventFactory.Atomic.newFence(ctx.c11Mo().mo); + public Object visitNreOpenCLFence(NreOpenCLFenceContext ctx){ + Event fence = EventFactory.Atomic.newFence(ctx.c11Mo().mo); if (ctx.openCLScope() != null) { fence.addTags(ctx.openCLScope().scope); } if (ctx.openCLFenceFlags() != null) { - for (LitmusCParser.OpenCLFenceFlagContext flagCtx : ctx.openCLFenceFlags().openCLFenceFlag()) { + for (OpenCLFenceFlagContext flagCtx : ctx.openCLFenceFlags().openCLFenceFlag()) { fence.addTags(flagCtx.flag); } } - return programBuilder.addChild(currentThread, fence); + return append(fence); } @Override - public Object visitNreOpenCLBarrier(LitmusCParser.NreOpenCLBarrierContext ctx){ + public Object visitNreOpenCLBarrier(NreOpenCLBarrierContext ctx){ List flags = ctx.openCLFenceFlags().openCLFenceFlag().stream().map(f -> f.flag).toList(); String barrierScope = ctx.openCLScope() != null ? ctx.openCLScope().scope : Tag.OpenCL.WORK_GROUP; String name = String.format("barrier(%s.%s)", ctx.openCLFenceFlags().getText(), barrierScope).toLowerCase(); @@ -639,29 +634,29 @@ public Object visitNreOpenCLBarrier(LitmusCParser.NreOpenCLBarrierContext ctx){ throw new ParsingException("Unsupported control barrier scope '%s'", barrierScope); } fence.addTags(barrierScope); - return programBuilder.addChild(currentThread, fence); + return append(fence); } @Override - public Object visitNreSpinLock(LitmusCParser.NreSpinLockContext ctx) { - return programBuilder.addChild(currentThread, EventFactory.Linux.newLock(getAddress(ctx.address))); + public Object visitNreSpinLock(NreSpinLockContext ctx) { + return append(EventFactory.Linux.newLock(getAddress(ctx.address))); } @Override - public Object visitNreSpinUnlock(LitmusCParser.NreSpinUnlockContext ctx) { - return programBuilder.addChild(currentThread, EventFactory.Linux.newUnlock(getAddress(ctx.address))); + public Object visitNreSpinUnlock(NreSpinUnlockContext ctx) { + return append(EventFactory.Linux.newUnlock(getAddress(ctx.address))); } @Override - public Object visitNreSrcuSync(LitmusCParser.NreSrcuSyncContext ctx) { - return programBuilder.addChild(currentThread, EventFactory.Linux.newSrcuSync(getAddress(ctx.address))); + public Object visitNreSrcuSync(NreSrcuSyncContext ctx) { + return append(EventFactory.Linux.newSrcuSync(getAddress(ctx.address))); } // ---------------------------------------------------------------------------------------------------------------- // Utils @Override - public Expression visitVarName(LitmusCParser.VarNameContext ctx){ + public Expression visitVarName(VarNameContext ctx){ if(scope > -1){ Register register = programBuilder.getRegister(scope, ctx.getText()); if(register != null){ @@ -670,18 +665,18 @@ public Expression visitVarName(LitmusCParser.VarNameContext ctx){ MemoryObject object = programBuilder.getMemoryObject(ctx.getText()); if(object != null){ register = programBuilder.getOrNewRegister(scope, null, archType); - programBuilder.addChild(currentThread, EventFactory.newLoadWithMo(register, object, C11.NONATOMIC)); + append(EventFactory.newLoadWithMo(register, object, C11.NONATOMIC)); return register; } return programBuilder.getOrNewRegister(scope, ctx.getText(), archType); } MemoryObject object = programBuilder.newMemoryObject(ctx.getText(), archSize); Register register = programBuilder.getOrNewRegister(scope, null, archType); - programBuilder.addChild(currentThread, EventFactory.newLoadWithMo(register, object, C11.NONATOMIC)); + append(EventFactory.newLoadWithMo(register, object, C11.NONATOMIC)); return register; } - private Expression getAddress(LitmusCParser.ReContext ctx){ + private Expression getAddress(ReContext ctx){ Expression address = (Expression)ctx.accept(this); if(address.getType() instanceof IntegerType){ return address; @@ -689,7 +684,7 @@ private Expression getAddress(LitmusCParser.ReContext ctx){ throw new ParsingException("Invalid syntax near " + ctx.getText()); } - private Expression returnExpressionOrOne(LitmusCParser.ReContext ctx) { + private Expression returnExpressionOrOne(ReContext ctx) { return ctx != null ? (Expression) ctx.accept(this) : expressions.makeOne(archType); } @@ -705,12 +700,12 @@ private Register getReturnRegister(boolean createOnNull){ private Expression assignToReturnRegister(Register register, Expression value) { if (register != null) { Expression cast = expressions.makeCast(value, register.getType()); - programBuilder.addChild(currentThread, EventFactory.newLocal(register, cast)); + append(EventFactory.newLocal(register, cast)); } return value; } - private void addScopeTag(Event event, LitmusCParser.OpenCLScopeContext ctx) { + private void addScopeTag(Event event, OpenCLScopeContext ctx) { if (isOpenCL) { if (ctx != null) { event.addTags(ctx.scope); @@ -719,4 +714,8 @@ private void addScopeTag(Event event, LitmusCParser.OpenCLScopeContext ctx) { } } } + + private Object append(Event event) { + return programBuilder.addChild(currentThread, event); + } } diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusPPC.java b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusPPC.java index a9a4f88ef5..856b2b2b68 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusPPC.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusPPC.java @@ -8,23 +8,20 @@ import com.dat3m.dartagnan.expression.type.IntegerType; import com.dat3m.dartagnan.expression.type.TypeFactory; import com.dat3m.dartagnan.parsers.LitmusPPCBaseVisitor; -import com.dat3m.dartagnan.parsers.LitmusPPCParser; +import com.dat3m.dartagnan.parsers.LitmusPPCParser.*; import com.dat3m.dartagnan.parsers.program.utils.ProgramBuilder; import com.dat3m.dartagnan.program.Program; import com.dat3m.dartagnan.program.Register; +import com.dat3m.dartagnan.program.event.Event; import com.dat3m.dartagnan.program.event.EventFactory; import com.dat3m.dartagnan.program.event.core.Label; -import com.google.common.collect.ImmutableSet; import java.util.HashMap; import java.util.Map; -import static com.dat3m.dartagnan.program.event.FenceNameRepository.*; - public class VisitorLitmusPPC extends LitmusPPCBaseVisitor { private record CmpInstruction(Expression left, Expression right) {} - private final static ImmutableSet fences = ImmutableSet.of(SYNC, LWSYNC, ISYNC); private final ProgramBuilder programBuilder = ProgramBuilder.forArch(Program.SourceLanguage.LITMUS, Arch.POWER); private final TypeFactory types = programBuilder.getTypeFactory(); @@ -41,7 +38,7 @@ public VisitorLitmusPPC() { // Entry point @Override - public Object visitMain(LitmusPPCParser.MainContext ctx) { + public Object visitMain(MainContext ctx) { visitThreadDeclaratorList(ctx.program().threadDeclaratorList()); visitVariableDeclaratorList(ctx.variableDeclaratorList()); visitInstructionList(ctx.program().instructionList()); @@ -54,27 +51,27 @@ public Object visitMain(LitmusPPCParser.MainContext ctx) { // Variable declarator list, e.g., { 0:EAX=0; 1:EAX=1; x=2; } @Override - public Object visitVariableDeclaratorLocation(LitmusPPCParser.VariableDeclaratorLocationContext ctx) { + public Object visitVariableDeclaratorLocation(VariableDeclaratorLocationContext ctx) { IntLiteral value = expressions.parseValue(ctx.constant().getText(), archType); programBuilder.initLocEqConst(ctx.location().getText(), value); return null; } @Override - public Object visitVariableDeclaratorRegister(LitmusPPCParser.VariableDeclaratorRegisterContext ctx) { + public Object visitVariableDeclaratorRegister(VariableDeclaratorRegisterContext ctx) { IntLiteral value = expressions.parseValue(ctx.constant().getText(), archType); programBuilder.initRegEqConst(ctx.threadId().id, ctx.register().getText(), value); return null; } @Override - public Object visitVariableDeclaratorRegisterLocation(LitmusPPCParser.VariableDeclaratorRegisterLocationContext ctx) { + public Object visitVariableDeclaratorRegisterLocation(VariableDeclaratorRegisterLocationContext ctx) { programBuilder.initRegEqLocPtr(ctx.threadId().id, ctx.register().getText(), ctx.location().getText(), archType); return null; } @Override - public Object visitVariableDeclaratorLocationLocation(LitmusPPCParser.VariableDeclaratorLocationLocationContext ctx) { + public Object visitVariableDeclaratorLocationLocation(VariableDeclaratorLocationLocationContext ctx) { programBuilder.initLocEqLocPtr(ctx.location(0).getText(), ctx.location(1).getText()); return null; } @@ -84,8 +81,8 @@ public Object visitVariableDeclaratorLocationLocation(LitmusPPCParser.VariableDe // Thread declarator list (on top of instructions), e.g. " P0 | P1 | P2 ;" @Override - public Object visitThreadDeclaratorList(LitmusPPCParser.ThreadDeclaratorListContext ctx) { - for(LitmusPPCParser.ThreadIdContext threadCtx : ctx.threadId()){ + public Object visitThreadDeclaratorList(ThreadDeclaratorListContext ctx) { + for(ThreadIdContext threadCtx : ctx.threadId()){ programBuilder.newThread(threadCtx.id); threadCount++; } @@ -97,7 +94,7 @@ public Object visitThreadDeclaratorList(LitmusPPCParser.ThreadDeclaratorListCont // Instruction list (the program itself) @Override - public Object visitInstructionRow(LitmusPPCParser.InstructionRowContext ctx) { + public Object visitInstructionRow(InstructionRowContext ctx) { for(int i = 0; i < threadCount; i++){ mainThread = i; visitInstruction(ctx.instruction(i)); @@ -106,48 +103,48 @@ public Object visitInstructionRow(LitmusPPCParser.InstructionRowContext ctx) { } @Override - public Object visitLi(LitmusPPCParser.LiContext ctx) { + public Object visitLi(LiContext ctx) { Register register = (Register) ctx.register().accept(this); IntLiteral constant = expressions.parseValue(ctx.constant().getText(), archType); - return programBuilder.addChild(mainThread, EventFactory.newLocal(register, constant)); + return append(EventFactory.newLocal(register, constant)); } @Override - public Object visitLwz(LitmusPPCParser.LwzContext ctx) { + public Object visitLwz(LwzContext ctx) { Register r1 = (Register) ctx.register(0).accept(this); Register ra = (Register) ctx.register(1).accept(this); - return programBuilder.addChild(mainThread, EventFactory.newLoad(r1, ra)); + return append(EventFactory.newLoad(r1, ra)); } @Override - public Object visitLwzx(LitmusPPCParser.LwzxContext ctx) { + public Object visitLwzx(LwzxContext ctx) { // TODO: Implementation throw new ParsingException("lwzx is not implemented"); } @Override - public Object visitLwarx(LitmusPPCParser.LwarxContext ctx) { + public Object visitLwarx(LwarxContext ctx) { Register r1 = (Register) ctx.register(0).accept(this); Register ra = (Register) ctx.register(1).accept(this); Register rb = (Register) ctx.register(2).accept(this); - return programBuilder.addChild(mainThread, EventFactory.newRMWLoadExclusive(r1, expressions.makeAdd(ra, rb))); + return append(EventFactory.Power.newRMWLoadExclusive(r1, expressions.makeAdd(ra, rb))); } @Override - public Object visitStw(LitmusPPCParser.StwContext ctx) { + public Object visitStw(StwContext ctx) { Register r1 = (Register) ctx.register(0).accept(this); Register ra = (Register) ctx.register(1).accept(this); - return programBuilder.addChild(mainThread, EventFactory.newStore(ra, r1)); + return append(EventFactory.newStore(ra, r1)); } @Override - public Object visitStwx(LitmusPPCParser.StwxContext ctx) { + public Object visitStwx(StwxContext ctx) { // TODO: Implementation throw new ParsingException("stwx is not implemented"); } @Override - public Object visitStwcx(LitmusPPCParser.StwcxContext ctx) { + public Object visitStwcx(StwcxContext ctx) { // This instruction is usually followed by a branch instruction. // Thus, the execution status of the store is saved in r0 // (the default register for branch conditions). @@ -155,34 +152,34 @@ public Object visitStwcx(LitmusPPCParser.StwcxContext ctx) { Register r1 = (Register) ctx.register(0).accept(this); Register ra = (Register) ctx.register(1).accept(this); Register rb = (Register) ctx.register(2).accept(this); - return programBuilder.addChild(mainThread, EventFactory.Common.newExclusiveStore(rs, expressions.makeAdd(ra, rb), r1, "")); + return append(EventFactory.Common.newExclusiveStore(rs, expressions.makeAdd(ra, rb), r1, "")); } @Override - public Object visitMr(LitmusPPCParser.MrContext ctx) { + public Object visitMr(MrContext ctx) { Register r1 = (Register) ctx.register(0).accept(this); Register r2 = (Register) ctx.register(1).accept(this); - return programBuilder.addChild(mainThread, EventFactory.newLocal(r1, r2)); + return append(EventFactory.newLocal(r1, r2)); } @Override - public Object visitAddi(LitmusPPCParser.AddiContext ctx) { + public Object visitAddi(AddiContext ctx) { Register r1 = (Register) ctx.register(0).accept(this); Register r2 = (Register) ctx.register(1).accept(this); IntLiteral constant = expressions.parseValue(ctx.constant().getText(), archType); - return programBuilder.addChild(mainThread, EventFactory.newLocal(r1, expressions.makeAdd(r2, constant))); + return append(EventFactory.newLocal(r1, expressions.makeAdd(r2, constant))); } @Override - public Object visitXor(LitmusPPCParser.XorContext ctx) { + public Object visitXor(XorContext ctx) { Register r1 = (Register) ctx.register(0).accept(this); Register r2 = (Register) ctx.register(1).accept(this); Register r3 = (Register) ctx.register(2).accept(this); - return programBuilder.addChild(mainThread, EventFactory.newLocal(r1, expressions.makeIntXor(r2, r3))); + return append(EventFactory.newLocal(r1, expressions.makeIntXor(r2, r3))); } @Override - public Object visitCmpw(LitmusPPCParser.CmpwContext ctx) { + public Object visitCmpw(CmpwContext ctx) { Register r1 = (Register) ctx.register(0).accept(this); Register r2 = (Register) ctx.register(1).accept(this); lastCmpInstructionPerThread.put(mainThread, new CmpInstruction(r1, r2)); @@ -190,7 +187,7 @@ public Object visitCmpw(LitmusPPCParser.CmpwContext ctx) { } @Override - public Object visitBranchCond(LitmusPPCParser.BranchCondContext ctx) { + public Object visitBranchCond(BranchCondContext ctx) { Label label = programBuilder.getOrCreateLabel(mainThread, ctx.Label().getText()); CmpInstruction cmp = lastCmpInstructionPerThread.put(mainThread, null); Expression expr = cmp == null ? @@ -198,26 +195,30 @@ public Object visitBranchCond(LitmusPPCParser.BranchCondContext ctx) { // the value of r0 is used as the branching condition expressions.makeBooleanCast(programBuilder.getOrNewRegister(mainThread, "r0")) : expressions.makeIntCmp(cmp.left, ctx.cond().op, cmp.right); - return programBuilder.addChild(mainThread, EventFactory.newJump(expr, label)); + return append(EventFactory.newJump(expr, label)); } @Override - public Object visitLabel(LitmusPPCParser.LabelContext ctx) { - return programBuilder.addChild(mainThread, programBuilder.getOrCreateLabel(mainThread, ctx.Label().getText())); + public Object visitLabel(LabelContext ctx) { + return append(programBuilder.getOrCreateLabel(mainThread, ctx.Label().getText())); } @Override - public Object visitFence(LitmusPPCParser.FenceContext ctx) { - String name = ctx.getText().toLowerCase(); - if(fences.contains(name)){ - return programBuilder.addChild(mainThread, EventFactory.newFence(name)); - } - throw new ParsingException("Unrecognised fence " + name); + public Object visitFence(FenceContext ctx) { + return append(switch (ctx.getText().toLowerCase()) { + case "sync" -> EventFactory.Power.newSyncBarrier(); + case "lwsync" -> EventFactory.Power.newLwSyncBarrier(); + case "isync" -> EventFactory.Power.newISyncBarrier(); + default -> throw new ParsingException("Unrecognised fence %s", ctx.getText()); + }); } @Override - public Register visitRegister(LitmusPPCParser.RegisterContext ctx) { + public Register visitRegister(RegisterContext ctx) { return programBuilder.getOrNewRegister(mainThread, ctx.getText(), archType); } + private Object append(Event event) { + return programBuilder.addChild(mainThread, event); + } } diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusPTX.java b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusPTX.java index 2f7da8d178..17425acb6b 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusPTX.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusPTX.java @@ -9,20 +9,14 @@ import com.dat3m.dartagnan.expression.type.IntegerType; import com.dat3m.dartagnan.expression.type.TypeFactory; import com.dat3m.dartagnan.parsers.LitmusPTXBaseVisitor; -import com.dat3m.dartagnan.parsers.LitmusPTXParser; +import com.dat3m.dartagnan.parsers.LitmusPTXParser.*; import com.dat3m.dartagnan.parsers.program.utils.ProgramBuilder; import com.dat3m.dartagnan.program.Program; import com.dat3m.dartagnan.program.Register; import com.dat3m.dartagnan.program.event.Event; import com.dat3m.dartagnan.program.event.EventFactory; import com.dat3m.dartagnan.program.event.Tag; -import com.dat3m.dartagnan.program.event.arch.ptx.PTXAtomCAS; -import com.dat3m.dartagnan.program.event.arch.ptx.PTXAtomExch; -import com.dat3m.dartagnan.program.event.arch.ptx.PTXAtomOp; -import com.dat3m.dartagnan.program.event.arch.ptx.PTXRedOp; import com.dat3m.dartagnan.program.event.core.Label; -import com.dat3m.dartagnan.program.event.core.Load; -import com.dat3m.dartagnan.program.event.core.Store; import com.dat3m.dartagnan.program.memory.MemoryObject; public class VisitorLitmusPTX extends LitmusPTXBaseVisitor { @@ -40,7 +34,7 @@ public VisitorLitmusPTX() { // Entry point @Override - public Object visitMain(LitmusPTXParser.MainContext ctx) { + public Object visitMain(MainContext ctx) { visitThreadDeclaratorList(ctx.program().threadDeclaratorList()); visitVariableDeclaratorList(ctx.variableDeclaratorList()); visitInstructionList(ctx.program().instructionList()); @@ -52,28 +46,28 @@ public Object visitMain(LitmusPTXParser.MainContext ctx) { // ---------------------------------------------------------------------------------------------------------------- // Variable declarator list @Override - public Object visitVariableDeclaratorLocation(LitmusPTXParser.VariableDeclaratorLocationContext ctx) { + public Object visitVariableDeclaratorLocation(VariableDeclaratorLocationContext ctx) { programBuilder.initVirLocEqCon(ctx.location().getText(), (IntLiteral) ctx.constant().accept(this)); return null; } @Override - public Object visitVariableDeclaratorRegister(LitmusPTXParser.VariableDeclaratorRegisterContext ctx) { + public Object visitVariableDeclaratorRegister(VariableDeclaratorRegisterContext ctx) { programBuilder.initRegEqConst(ctx.threadId().id, ctx.register().getText(), (IntLiteral) ctx.constant().accept(this)); return null; } @Override - public Object visitVariableDeclaratorRegisterLocation(LitmusPTXParser.VariableDeclaratorRegisterLocationContext ctx) { + public Object visitVariableDeclaratorRegisterLocation(VariableDeclaratorRegisterLocationContext ctx) { programBuilder.initRegEqLocPtr(ctx.threadId().id, ctx.register().getText(), ctx.location().getText(), archType); return null; } @Override - public Object visitVariableDeclaratorLocationLocation(LitmusPTXParser.VariableDeclaratorLocationLocationContext ctx) { + public Object visitVariableDeclaratorLocationLocation(VariableDeclaratorLocationLocationContext ctx) { programBuilder.initVirLocEqLoc(ctx.location(0).getText(), ctx.location(1).getText()); return null; } @@ -81,7 +75,7 @@ public Object visitVariableDeclaratorLocationLocation(LitmusPTXParser.VariableDe // ---------------------------------------------------------------------------------------------------------------- // Proxy declarator list @Override - public Object visitVariableDeclaratorProxy(LitmusPTXParser.VariableDeclaratorProxyContext ctx) { + public Object visitVariableDeclaratorProxy(VariableDeclaratorProxyContext ctx) { if (ctx.proxyType().content.equals(Tag.PTX.GEN)) { programBuilder.initVirLocEqLocAliasGen(ctx.location(0).getText(), ctx.location(1).getText()); @@ -95,8 +89,8 @@ public Object visitVariableDeclaratorProxy(LitmusPTXParser.VariableDeclaratorPro // ---------------------------------------------------------------------------------------------------------------- // Thread declarator list (on top of instructions) @Override - public Object visitThreadDeclaratorList(LitmusPTXParser.ThreadDeclaratorListContext ctx) { - for (LitmusPTXParser.ThreadScopeContext threadScopeContext : ctx.threadScope()) { + public Object visitThreadDeclaratorList(ThreadDeclaratorListContext ctx) { + for (ThreadScopeContext threadScopeContext : ctx.threadScope()) { int ctaID = threadScopeContext.scopeID().ctaID().id; int gpuID = threadScopeContext.scopeID().gpuID().id; // NB: the order of scopeIDs is important @@ -109,17 +103,17 @@ public Object visitThreadDeclaratorList(LitmusPTXParser.ThreadDeclaratorListCont // ---------------------------------------------------------------------------------------------------------------- // Instruction list (the program itself) @Override - public Object visitConstant(LitmusPTXParser.ConstantContext ctx) { + public Object visitConstant(ConstantContext ctx) { return ExpressionFactory.getInstance().parseValue(ctx.getText(), archType); } @Override - public Object visitRegister(LitmusPTXParser.RegisterContext ctx) { + public Object visitRegister(RegisterContext ctx) { return programBuilder.getOrNewRegister(mainThread, ctx.getText(), archType); } @Override - public Object visitInstructionRow(LitmusPTXParser.InstructionRowContext ctx) { + public Object visitInstructionRow(InstructionRowContext ctx) { for (int i = 0; i < threadCount; i++) { mainThread = i; visitInstruction(ctx.instruction(i)); @@ -128,11 +122,11 @@ public Object visitInstructionRow(LitmusPTXParser.InstructionRowContext ctx) { } @Override - public Object visitStoreInstruction(LitmusPTXParser.StoreInstructionContext ctx) { + public Object visitStoreInstruction(StoreInstructionContext ctx) { MemoryObject object = programBuilder.getOrNewVirtualMemoryObject(ctx.location().getText()); Expression constant = (Expression) ctx.value().accept(this); String mo = ctx.mo().content; - Store store = EventFactory.newStoreWithMo(object, constant, mo); + Event store = EventFactory.newStoreWithMo(object, constant, mo); switch (mo) { case Tag.PTX.WEAK -> { if (ctx.scope() != null) { @@ -143,58 +137,58 @@ public Object visitStoreInstruction(LitmusPTXParser.StoreInstructionContext ctx) default -> throw new ParsingException("Store instruction doesn't support mo: " + mo); } store.addTags(ctx.store().storeProxy); - return programBuilder.addChild(mainThread, store); + return append(store); } @Override - public Object visitLocalValue(LitmusPTXParser.LocalValueContext ctx) { + public Object visitLocalValue(LocalValueContext ctx) { Register register = (Register) ctx.register().accept(this); Expression value = (Expression) ctx.value().accept(this); - return programBuilder.addChild(mainThread, EventFactory.newLocal(register, value)); + return append(EventFactory.newLocal(register, value)); } @Override - public Object visitLocalAdd(LitmusPTXParser.LocalAddContext ctx) { + public Object visitLocalAdd(LocalAddContext ctx) { Register rd = (Register) ctx.register().accept(this); Expression lhs = (Expression) ctx.value(0).accept(this); Expression rhs = (Expression) ctx.value(1).accept(this); Expression exp = expressions.makeAdd(lhs, rhs); - return programBuilder.addChild(mainThread, EventFactory.newLocal(rd, exp)); + return append(EventFactory.newLocal(rd, exp)); } @Override - public Object visitLocalSub(LitmusPTXParser.LocalSubContext ctx) { + public Object visitLocalSub(LocalSubContext ctx) { Register rd = (Register) ctx.register().accept(this); Expression lhs = (Expression) ctx.value(0).accept(this); Expression rhs = (Expression) ctx.value(1).accept(this); Expression exp = expressions.makeSub(lhs, rhs); - return programBuilder.addChild(mainThread, EventFactory.newLocal(rd, exp)); + return append(EventFactory.newLocal(rd, exp)); } @Override - public Object visitLocalMul(LitmusPTXParser.LocalMulContext ctx) { + public Object visitLocalMul(LocalMulContext ctx) { Register rd = (Register) ctx.register().accept(this); Expression lhs = (Expression) ctx.value(0).accept(this); Expression rhs = (Expression) ctx.value(1).accept(this); Expression exp = expressions.makeMul(lhs, rhs); - return programBuilder.addChild(mainThread, EventFactory.newLocal(rd, exp)); + return append(EventFactory.newLocal(rd, exp)); } @Override - public Object visitLocalDiv(LitmusPTXParser.LocalDivContext ctx) { + public Object visitLocalDiv(LocalDivContext ctx) { Register rd = (Register) ctx.register().accept(this); Expression lhs = (Expression) ctx.value(0).accept(this); Expression rhs = (Expression) ctx.value(1).accept(this); Expression exp = expressions.makeDiv(lhs, rhs, true); - return programBuilder.addChild(mainThread, EventFactory.newLocal(rd, exp)); + return append(EventFactory.newLocal(rd, exp)); } @Override - public Object visitLoadLocation(LitmusPTXParser.LoadLocationContext ctx) { + public Object visitLoadLocation(LoadLocationContext ctx) { Register register = (Register) ctx.register().accept(this); MemoryObject location = programBuilder.getOrNewVirtualMemoryObject(ctx.location().getText()); String mo = ctx.mo().content; - Load load = EventFactory.newLoadWithMo(register, location, mo); + Event load = EventFactory.newLoadWithMo(register, location, mo); switch (mo) { case Tag.PTX.WEAK -> { if (ctx.scope() != null) { @@ -205,11 +199,11 @@ public Object visitLoadLocation(LitmusPTXParser.LoadLocationContext ctx) { default -> throw new ParsingException("Load instruction doesn't support mo: " + mo); } load.addTags(ctx.load().loadProxy); - return programBuilder.addChild(mainThread, load); + return append(load); } @Override - public Object visitAtomOp(LitmusPTXParser.AtomOpContext ctx) { + public Object visitAtomOp(AtomOpContext ctx) { Register register_destination = (Register) ctx.register().accept(this); MemoryObject object = programBuilder.getOrNewVirtualMemoryObject(ctx.location().getText()); Expression value = (Expression) ctx.value().accept(this); @@ -219,13 +213,13 @@ public Object visitAtomOp(LitmusPTXParser.AtomOpContext ctx) { if (!(mo.equals(Tag.PTX.ACQ) || mo.equals(Tag.PTX.REL) || mo.equals(Tag.PTX.ACQ_REL) || mo.equals(Tag.PTX.RLX))) { throw new ParsingException("Atom instruction doesn't support mo: " + mo); } - PTXAtomOp atom = EventFactory.PTX.newAtomOp(object, register_destination, value, op, mo, scope); + Event atom = EventFactory.PTX.newAtomOp(object, register_destination, value, op, mo, scope); atom.addTags(ctx.atom().atomProxy); - return programBuilder.addChild(mainThread, atom); + return append(atom); } @Override - public Object visitAtomCAS(LitmusPTXParser.AtomCASContext ctx) { + public Object visitAtomCAS(AtomCASContext ctx) { Register register_destination = programBuilder.getOrNewRegister(mainThread, ctx.register().getText(), archType); MemoryObject object = programBuilder.getOrNewVirtualMemoryObject(ctx.location().getText()); Expression expected = (Expression) ctx.value(0).accept(this); @@ -235,13 +229,13 @@ public Object visitAtomCAS(LitmusPTXParser.AtomCASContext ctx) { if (!(mo.equals(Tag.PTX.ACQ) || mo.equals(Tag.PTX.REL) || mo.equals(Tag.PTX.ACQ_REL) || mo.equals(Tag.PTX.RLX))) { throw new ParsingException("Atom instruction doesn't support mo: " + mo); } - PTXAtomCAS atom = EventFactory.PTX.newAtomCAS(object, register_destination, expected, value, mo, scope); + Event atom = EventFactory.PTX.newAtomCAS(object, register_destination, expected, value, mo, scope); atom.addTags(ctx.atom().atomProxy); - return programBuilder.addChild(mainThread, atom); + return append(atom); } @Override - public Object visitAtomExchange(LitmusPTXParser.AtomExchangeContext ctx) { + public Object visitAtomExchange(AtomExchangeContext ctx) { Register register_destination = programBuilder.getOrNewRegister(mainThread, ctx.register().getText(), archType); MemoryObject object = programBuilder.getOrNewVirtualMemoryObject(ctx.location().getText()); Expression value = (Expression) ctx.value().accept(this); @@ -250,13 +244,13 @@ public Object visitAtomExchange(LitmusPTXParser.AtomExchangeContext ctx) { if (!(mo.equals(Tag.PTX.ACQ) || mo.equals(Tag.PTX.REL) || mo.equals(Tag.PTX.ACQ_REL) || mo.equals(Tag.PTX.RLX))) { throw new ParsingException("Atom instruction doesn't support mo: " + mo); } - PTXAtomExch atom = EventFactory.PTX.newAtomExch(object, register_destination, value, mo, scope); + Event atom = EventFactory.PTX.newAtomExch(object, register_destination, value, mo, scope); atom.addTags(ctx.atom().atomProxy); - return programBuilder.addChild(mainThread, atom); + return append(atom); } @Override - public Object visitRedInstruction(LitmusPTXParser.RedInstructionContext ctx) { + public Object visitRedInstruction(RedInstructionContext ctx) { MemoryObject object = programBuilder.getOrNewVirtualMemoryObject(ctx.location().getText()); Expression value = (Expression) ctx.value().accept(this); IntBinaryOp op = ctx.operation().op; @@ -265,13 +259,13 @@ public Object visitRedInstruction(LitmusPTXParser.RedInstructionContext ctx) { if (!(mo.equals(Tag.PTX.ACQ) || mo.equals(Tag.PTX.REL) || mo.equals(Tag.PTX.ACQ_REL) || mo.equals(Tag.PTX.RLX))) { throw new ParsingException("Red instruction doesn't support mo: " + mo); } - PTXRedOp red = EventFactory.PTX.newRedOp(object, value, op, mo, scope); + Event red = EventFactory.PTX.newRedOp(object, value, op, mo, scope); red.addTags(ctx.red().redProxy); - return programBuilder.addChild(mainThread, red); + return append(red); } @Override - public Object visitFencePhysic(LitmusPTXParser.FencePhysicContext ctx) { + public Object visitFencePhysic(FencePhysicContext ctx) { String mo = ctx.mo().content; String scope = ctx.scope().content; if (!(mo.equals(Tag.PTX.ACQ_REL) || mo.equals(Tag.PTX.SC))) { @@ -279,25 +273,25 @@ public Object visitFencePhysic(LitmusPTXParser.FencePhysicContext ctx) { } Event fence = EventFactory.newFence(ctx.getText().toLowerCase()); fence.addTags(mo, scope, Tag.PTX.GEN); - return programBuilder.addChild(mainThread, fence); + return append(fence); } @Override - public Object visitFenceProxy(LitmusPTXParser.FenceProxyContext ctx) { + public Object visitFenceProxy(FenceProxyContext ctx) { Event fence = EventFactory.newFence(ctx.getText().toLowerCase()); fence.addTags(ctx.proxyType().content); - return programBuilder.addChild(mainThread, fence); + return append(fence); } @Override - public Object visitFenceAlias(LitmusPTXParser.FenceAliasContext ctx) { + public Object visitFenceAlias(FenceAliasContext ctx) { Event fence = EventFactory.newFence(ctx.getText().toLowerCase()); fence.addTags(Tag.PTX.ALIAS); - return programBuilder.addChild(mainThread, fence); + return append(fence); } @Override - public Object visitBarrier(LitmusPTXParser.BarrierContext ctx) { + public Object visitBarrier(BarrierContext ctx) { String name = ctx.barrierMode().getText(); String instanceId = ctx.constant().getText(); Event barrier; @@ -314,27 +308,30 @@ public Object visitBarrier(LitmusPTXParser.BarrierContext ctx) { if(ctx.barrierMode().Arrive() != null) { barrier.addTags(Tag.PTX.ARRIVE); } - return programBuilder.addChild(mainThread, barrier); + return append(barrier); } @Override - public Object visitLabel(LitmusPTXParser.LabelContext ctx) { - return programBuilder.addChild(mainThread, programBuilder.getOrCreateLabel(mainThread, ctx.Label().getText())); + public Object visitLabel(LabelContext ctx) { + return append(programBuilder.getOrCreateLabel(mainThread, ctx.Label().getText())); } @Override - public Object visitBranchCond(LitmusPTXParser.BranchCondContext ctx) { + public Object visitBranchCond(BranchCondContext ctx) { Label label = programBuilder.getOrCreateLabel(mainThread, ctx.Label().getText()); Expression lhs = (Expression) ctx.value(0).accept(this); Expression rhs = (Expression) ctx.value(1).accept(this); Expression expr = expressions.makeIntCmp(lhs, ctx.cond().op, rhs); - return programBuilder.addChild(mainThread, EventFactory.newJump(expr, label)); + return append(EventFactory.newJump(expr, label)); } @Override - public Object visitJump(LitmusPTXParser.JumpContext ctx) { + public Object visitJump(JumpContext ctx) { Label label = programBuilder.getOrCreateLabel(mainThread, ctx.Label().getText()); - return programBuilder.addChild(mainThread, EventFactory.newGoto(label)); + return append(EventFactory.newGoto(label)); } + private Object append(Event event) { + return programBuilder.addChild(mainThread, event); + } } \ No newline at end of file diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusRISCV.java b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusRISCV.java index 875ddb5fbf..445ce535a1 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusRISCV.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusRISCV.java @@ -8,7 +8,7 @@ import com.dat3m.dartagnan.expression.type.IntegerType; import com.dat3m.dartagnan.expression.type.TypeFactory; import com.dat3m.dartagnan.parsers.LitmusRISCVBaseVisitor; -import com.dat3m.dartagnan.parsers.LitmusRISCVParser; +import com.dat3m.dartagnan.parsers.LitmusRISCVParser.*; import com.dat3m.dartagnan.parsers.program.utils.ProgramBuilder; import com.dat3m.dartagnan.program.Program; import com.dat3m.dartagnan.program.Register; @@ -37,7 +37,7 @@ public VisitorLitmusRISCV(){ // Entry point @Override - public Object visitMain(LitmusRISCVParser.MainContext ctx) { + public Object visitMain(MainContext ctx) { visitThreadDeclaratorList(ctx.program().threadDeclaratorList()); visitVariableDeclaratorList(ctx.variableDeclaratorList()); visitInstructionList(ctx.program().instructionList()); @@ -51,27 +51,27 @@ public Object visitMain(LitmusRISCVParser.MainContext ctx) { // Variable declarator list @Override - public Object visitVariableDeclaratorLocation(LitmusRISCVParser.VariableDeclaratorLocationContext ctx) { + public Object visitVariableDeclaratorLocation(VariableDeclaratorLocationContext ctx) { IntLiteral value = expressions.parseValue(ctx.constant().getText(), archType); programBuilder.initLocEqConst(ctx.location().getText(), value); return null; } @Override - public Object visitVariableDeclaratorRegister(LitmusRISCVParser.VariableDeclaratorRegisterContext ctx) { + public Object visitVariableDeclaratorRegister(VariableDeclaratorRegisterContext ctx) { IntLiteral value = expressions.parseValue(ctx.constant().getText(), archType); programBuilder.initRegEqConst(ctx.threadId().id, ctx.register().getText(), value); return null; } @Override - public Object visitVariableDeclaratorRegisterLocation(LitmusRISCVParser.VariableDeclaratorRegisterLocationContext ctx) { + public Object visitVariableDeclaratorRegisterLocation(VariableDeclaratorRegisterLocationContext ctx) { programBuilder.initRegEqLocPtr(ctx.threadId().id, ctx.register().getText(), ctx.location().getText(), archType); return null; } @Override - public Object visitVariableDeclaratorLocationLocation(LitmusRISCVParser.VariableDeclaratorLocationLocationContext ctx) { + public Object visitVariableDeclaratorLocationLocation(VariableDeclaratorLocationLocationContext ctx) { programBuilder.initLocEqLocPtr(ctx.location(0).getText(), ctx.location(1).getText()); return null; } @@ -81,8 +81,8 @@ public Object visitVariableDeclaratorLocationLocation(LitmusRISCVParser.Variable // Thread declarator list (on top of instructions), e.g. " P0 | P1 | P2 ;" @Override - public Object visitThreadDeclaratorList(LitmusRISCVParser.ThreadDeclaratorListContext ctx) { - for(LitmusRISCVParser.ThreadIdContext threadCtx : ctx.threadId()){ + public Object visitThreadDeclaratorList(ThreadDeclaratorListContext ctx) { + for(ThreadIdContext threadCtx : ctx.threadId()){ programBuilder.newThread(threadCtx.id); threadCount++; } @@ -94,7 +94,7 @@ public Object visitThreadDeclaratorList(LitmusRISCVParser.ThreadDeclaratorListCo // Instruction list (the program itself) @Override - public Object visitInstructionRow(LitmusRISCVParser.InstructionRowContext ctx) { + public Object visitInstructionRow(InstructionRowContext ctx) { for(int i = 0; i < threadCount; i++){ mainThread = i; visitInstruction(ctx.instruction(i)); @@ -103,125 +103,125 @@ public Object visitInstructionRow(LitmusRISCVParser.InstructionRowContext ctx) { } @Override - public Object visitLi(LitmusRISCVParser.LiContext ctx) { + public Object visitLi(LiContext ctx) { Register register = programBuilder.getOrNewRegister(mainThread, ctx.register().getText(), archType); IntLiteral constant = expressions.parseValue(ctx.constant().getText(), archType); - return programBuilder.addChild(mainThread, EventFactory.newLocal(register, constant)); + return append(EventFactory.newLocal(register, constant)); } @Override - public Object visitXor(LitmusRISCVParser.XorContext ctx) { + public Object visitXor(XorContext ctx) { Register r1 = programBuilder.getOrNewRegister(mainThread, ctx.register(0).getText(), archType); Register r2 = programBuilder.getOrErrorRegister(mainThread, ctx.register(1).getText()); Register r3 = programBuilder.getOrErrorRegister(mainThread, ctx.register(2).getText()); - return programBuilder.addChild(mainThread, EventFactory.newLocal(r1, expressions.makeIntXor(r2, r3))); + return append(EventFactory.newLocal(r1, expressions.makeIntXor(r2, r3))); } @Override - public Object visitAnd(LitmusRISCVParser.AndContext ctx) { + public Object visitAnd(AndContext ctx) { Register r1 = programBuilder.getOrNewRegister(mainThread, ctx.register(0).getText(), archType); Register r2 = programBuilder.getOrErrorRegister(mainThread, ctx.register(1).getText()); Register r3 = programBuilder.getOrErrorRegister(mainThread, ctx.register(2).getText()); - return programBuilder.addChild(mainThread, EventFactory.newLocal(r1, expressions.makeIntAnd(r2, r3))); + return append(EventFactory.newLocal(r1, expressions.makeIntAnd(r2, r3))); } @Override - public Object visitOr(LitmusRISCVParser.OrContext ctx) { + public Object visitOr(OrContext ctx) { Register r1 = programBuilder.getOrNewRegister(mainThread, ctx.register(0).getText(), archType); Register r2 = programBuilder.getOrErrorRegister(mainThread, ctx.register(1).getText()); Register r3 = programBuilder.getOrErrorRegister(mainThread, ctx.register(2).getText()); - return programBuilder.addChild(mainThread, EventFactory.newLocal(r1, expressions.makeIntOr(r2, r3))); + return append(EventFactory.newLocal(r1, expressions.makeIntOr(r2, r3))); } @Override - public Object visitAdd(LitmusRISCVParser.AddContext ctx) { + public Object visitAdd(AddContext ctx) { Register r1 = programBuilder.getOrNewRegister(mainThread, ctx.register(0).getText(), archType); Register r2 = programBuilder.getOrErrorRegister(mainThread, ctx.register(1).getText()); Register r3 = programBuilder.getOrErrorRegister(mainThread, ctx.register(2).getText()); - return programBuilder.addChild(mainThread, EventFactory.newLocal(r1, expressions.makeAdd(r2, r3))); + return append(EventFactory.newLocal(r1, expressions.makeAdd(r2, r3))); } @Override - public Object visitXori(LitmusRISCVParser.XoriContext ctx) { + public Object visitXori(XoriContext ctx) { Register r1 = programBuilder.getOrNewRegister(mainThread, ctx.register(0).getText(), archType); Register r2 = programBuilder.getOrErrorRegister(mainThread, ctx.register(1).getText()); IntLiteral constant = expressions.parseValue(ctx.constant().getText(), archType); - return programBuilder.addChild(mainThread, EventFactory.newLocal(r1, expressions.makeIntXor(r2, constant))); + return append(EventFactory.newLocal(r1, expressions.makeIntXor(r2, constant))); } @Override - public Object visitAndi(LitmusRISCVParser.AndiContext ctx) { + public Object visitAndi(AndiContext ctx) { Register r1 = programBuilder.getOrNewRegister(mainThread, ctx.register(0).getText(), archType); Register r2 = programBuilder.getOrErrorRegister(mainThread, ctx.register(1).getText()); IntLiteral constant = expressions.parseValue(ctx.constant().getText(), archType); - return programBuilder.addChild(mainThread, EventFactory.newLocal(r1, expressions.makeIntAnd(r2, constant))); + return append(EventFactory.newLocal(r1, expressions.makeIntAnd(r2, constant))); } @Override - public Object visitOri(LitmusRISCVParser.OriContext ctx) { + public Object visitOri(OriContext ctx) { Register r1 = programBuilder.getOrNewRegister(mainThread, ctx.register(0).getText(), archType); Register r2 = programBuilder.getOrNewRegister(mainThread, ctx.register(1).getText(), archType); IntLiteral constant = expressions.parseValue(ctx.constant().getText(), archType); - return programBuilder.addChild(mainThread, EventFactory.newLocal(r1, expressions.makeIntOr(r2, constant))); + return append(EventFactory.newLocal(r1, expressions.makeIntOr(r2, constant))); } @Override - public Object visitAddi(LitmusRISCVParser.AddiContext ctx) { + public Object visitAddi(AddiContext ctx) { Register r1 = programBuilder.getOrNewRegister(mainThread, ctx.register(0).getText(), archType); Register r2 = programBuilder.getOrNewRegister(mainThread, ctx.register(1).getText(), archType); IntLiteral constant = expressions.parseValue(ctx.constant().getText(), archType); - return programBuilder.addChild(mainThread, EventFactory.newLocal(r1, expressions.makeAdd(r2, constant))); + return append(EventFactory.newLocal(r1, expressions.makeAdd(r2, constant))); } @Override - public Object visitLw(LitmusRISCVParser.LwContext ctx) { + public Object visitLw(LwContext ctx) { Register r1 = programBuilder.getOrNewRegister(mainThread, ctx.register(0).getText(), archType); Register ra = programBuilder.getOrErrorRegister(mainThread, ctx.register(1).getText()); - return programBuilder.addChild(mainThread, EventFactory.newLoadWithMo(r1, ra, getMo(ctx.moRISCV(0), ctx.moRISCV(1)))); + return append(EventFactory.newLoadWithMo(r1, ra, getMo(ctx.moRISCV(0), ctx.moRISCV(1)))); } @Override - public Object visitSw(LitmusRISCVParser.SwContext ctx) { + public Object visitSw(SwContext ctx) { Register r1 = programBuilder.getOrErrorRegister(mainThread, ctx.register(0).getText()); Register ra = programBuilder.getOrErrorRegister(mainThread, ctx.register(1).getText()); - return programBuilder.addChild(mainThread, EventFactory.newStoreWithMo(ra, r1, getMo(ctx.moRISCV(0), ctx.moRISCV(1)))); + return append(EventFactory.newStoreWithMo(ra, r1, getMo(ctx.moRISCV(0), ctx.moRISCV(1)))); } @Override - public Object visitLr(LitmusRISCVParser.LrContext ctx) { + public Object visitLr(LrContext ctx) { Register r1 = programBuilder.getOrNewRegister(mainThread, ctx.register(0).getText(), archType); Register ra = programBuilder.getOrErrorRegister(mainThread, ctx.register(1).getText()); - return programBuilder.addChild(mainThread, EventFactory.newRMWLoadExclusiveWithMo(r1, ra, getMo(ctx.moRISCV(0), ctx.moRISCV(1)))); + return append(EventFactory.RISCV.newRMWLoadExclusive(r1, ra, getMo(ctx.moRISCV(0), ctx.moRISCV(1)))); } @Override - public Object visitSc(LitmusRISCVParser.ScContext ctx) { + public Object visitSc(ScContext ctx) { Register r1 = programBuilder.getOrNewRegister(mainThread, ctx.register(0).getText(), archType); Register r2 = programBuilder.getOrNewRegister(mainThread, ctx.register(1).getText(), archType); Register ra = programBuilder.getOrErrorRegister(mainThread, ctx.register(2).getText()); - return programBuilder.addChild(mainThread, EventFactory.Common.newExclusiveStore(r1, ra, r2, getMo(ctx.moRISCV(0), ctx.moRISCV(1)))); + return append(EventFactory.Common.newExclusiveStore(r1, ra, r2, getMo(ctx.moRISCV(0), ctx.moRISCV(1)))); } @Override - public Object visitLabel(LitmusRISCVParser.LabelContext ctx) { - return programBuilder.addChild(mainThread, programBuilder.getOrCreateLabel(mainThread, ctx.Label().getText())); + public Object visitLabel(LabelContext ctx) { + return append(programBuilder.getOrCreateLabel(mainThread, ctx.Label().getText())); } @Override - public Object visitBranchCond(LitmusRISCVParser.BranchCondContext ctx) { + public Object visitBranchCond(BranchCondContext ctx) { Label label = programBuilder.getOrCreateLabel(mainThread, ctx.Label().getText()); Register r1 = programBuilder.getOrNewRegister(mainThread, ctx.register(0).getText(), archType); Register r2 = programBuilder.getOrNewRegister(mainThread, ctx.register(1).getText(), archType); Expression expr = expressions.makeIntCmp(r1, ctx.cond().op, r2); - return programBuilder.addChild(mainThread, EventFactory.newJump(expr, label)); + return append(EventFactory.newJump(expr, label)); } @Override - public Object visitFence(LitmusRISCVParser.FenceContext ctx) { + public Object visitFence(FenceContext ctx) { String mo = ctx.fenceMode().mode; Event fence = switch(mo) { case "r.r" -> EventFactory.RISCV.newRRFence(); @@ -237,20 +237,20 @@ public Object visitFence(LitmusRISCVParser.FenceContext ctx) { case "i" -> EventFactory.RISCV.newSynchronizeFence(); default -> throw new ParsingException("Invalid fence mode " + mo); }; - return programBuilder.addChild(mainThread, fence); + return append(fence); } @Override - public Object visitAmoadd(LitmusRISCVParser.AmoaddContext ctx) { + public Object visitAmoadd(AmoaddContext ctx) { throw new ParsingException("No support for amoadd instructions"); } @Override - public Object visitAmoor(LitmusRISCVParser.AmoorContext ctx) { + public Object visitAmoor(AmoorContext ctx) { throw new ParsingException("No support for amoor instructions"); } @Override - public Object visitAmoswap(LitmusRISCVParser.AmoswapContext ctx) { + public Object visitAmoswap(AmoswapContext ctx) { throw new ParsingException("No support for amoswap instructions"); } @@ -258,9 +258,13 @@ public Object visitAmoswap(LitmusRISCVParser.AmoswapContext ctx) { // ================ Utils ================ // ======================================= - private String getMo(LitmusRISCVParser.MoRISCVContext mo1, LitmusRISCVParser.MoRISCVContext mo2) { + private String getMo(MoRISCVContext mo1, MoRISCVContext mo2) { String moR = mo1 != null ? mo1.mo : ""; String moW = mo2 != null ? mo2.mo : ""; return !moR.isEmpty() ? (!moW.isEmpty() ? Tag.RISCV.MO_ACQ_REL : moR) : moW; } + + private Object append(Event event) { + return programBuilder.addChild(mainThread, event); + } } diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusVulkan.java b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusVulkan.java index b26aa5bdd9..9ea7a905d2 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusVulkan.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusVulkan.java @@ -8,7 +8,7 @@ import com.dat3m.dartagnan.expression.type.IntegerType; import com.dat3m.dartagnan.expression.type.TypeFactory; import com.dat3m.dartagnan.parsers.LitmusVulkanBaseVisitor; -import com.dat3m.dartagnan.parsers.LitmusVulkanParser; +import com.dat3m.dartagnan.parsers.LitmusVulkanParser.*; import com.dat3m.dartagnan.parsers.program.utils.ProgramBuilder; import com.dat3m.dartagnan.program.Program; import com.dat3m.dartagnan.program.Register; @@ -22,6 +22,8 @@ import com.dat3m.dartagnan.program.memory.MemoryObject; import org.antlr.v4.runtime.ParserRuleContext; +import java.util.List; + public class VisitorLitmusVulkan extends LitmusVulkanBaseVisitor { private final ProgramBuilder programBuilder = ProgramBuilder.forArch(Program.SourceLanguage.LITMUS, Arch.VULKAN); private final ExpressionFactory expressions = programBuilder.getExpressionFactory(); @@ -34,13 +36,13 @@ public class VisitorLitmusVulkan extends LitmusVulkanBaseVisitor { // Entry point @Override - public Object visitMain(LitmusVulkanParser.MainContext ctx) { + public Object visitMain(MainContext ctx) { visitThreadDeclaratorList(ctx.program().threadDeclaratorList()); visitVariableDeclaratorList(ctx.variableDeclaratorList()); visitSswDeclaratorList(ctx.sswDeclaratorList()); visitInstructionList(ctx.program().instructionList()); if (ctx.sswDeclaratorList() != null) { - for (LitmusVulkanParser.SswDeclaratorContext sswDeclaratorContext : ctx.sswDeclaratorList().sswDeclarator()) { + for (SswDeclaratorContext sswDeclaratorContext : ctx.sswDeclaratorList().sswDeclarator()) { int threadId0 = sswDeclaratorContext.threadId(0).id; int threadId1 = sswDeclaratorContext.threadId(1).id; programBuilder.addSwwPairThreads(threadId0, threadId1); @@ -54,33 +56,33 @@ public Object visitMain(LitmusVulkanParser.MainContext ctx) { // ---------------------------------------------------------------------------------------------------------------- // Variable declarator list @Override - public Object visitVariableDeclaratorLocation(LitmusVulkanParser.VariableDeclaratorLocationContext ctx) { + public Object visitVariableDeclaratorLocation(VariableDeclaratorLocationContext ctx) { programBuilder.initVirLocEqCon(ctx.location().getText(), (IntLiteral) ctx.constant().accept(this)); return null; } @Override - public Object visitVariableDeclaratorRegister(LitmusVulkanParser.VariableDeclaratorRegisterContext ctx) { + public Object visitVariableDeclaratorRegister(VariableDeclaratorRegisterContext ctx) { programBuilder.initRegEqConst(ctx.threadId().id, ctx.register().getText(), (IntLiteral) ctx.constant().accept(this)); return null; } @Override - public Object visitVariableDeclaratorRegisterLocation(LitmusVulkanParser.VariableDeclaratorRegisterLocationContext ctx) { + public Object visitVariableDeclaratorRegisterLocation(VariableDeclaratorRegisterLocationContext ctx) { programBuilder.initRegEqLocPtr(ctx.threadId().id, ctx.register().getText(), ctx.location().getText(), archType); return null; } @Override - public Object visitVariableDeclaratorLocationLocation(LitmusVulkanParser.VariableDeclaratorLocationLocationContext ctx) { + public Object visitVariableDeclaratorLocationLocation(VariableDeclaratorLocationLocationContext ctx) { programBuilder.initVirLocEqLoc(ctx.location(0).getText(), ctx.location(1).getText()); return null; } @Override - public Object visitVariableDeclaratorProxy(LitmusVulkanParser.VariableDeclaratorProxyContext ctx) { + public Object visitVariableDeclaratorProxy(VariableDeclaratorProxyContext ctx) { programBuilder.initVirLocEqLocAliasGen(ctx.location(0).getText(), ctx.location(1).getText()); return null; @@ -89,9 +91,9 @@ public Object visitVariableDeclaratorProxy(LitmusVulkanParser.VariableDeclarator // ---------------------------------------------------------------------------------------------------------------- // SSW declarator list @Override - public Object visitSswDeclaratorList(LitmusVulkanParser.SswDeclaratorListContext ctx) { + public Object visitSswDeclaratorList(SswDeclaratorListContext ctx) { if (ctx != null) { - for (LitmusVulkanParser.SswDeclaratorContext sswDeclaratorContext : ctx.sswDeclarator()) { + for (SswDeclaratorContext sswDeclaratorContext : ctx.sswDeclarator()) { int threadId0 = sswDeclaratorContext.threadId(0).id; int threadId1 = sswDeclaratorContext.threadId(1).id; programBuilder.addSwwPairThreads(threadId0, threadId1); @@ -103,8 +105,8 @@ public Object visitSswDeclaratorList(LitmusVulkanParser.SswDeclaratorListContext // ---------------------------------------------------------------------------------------------------------------- // Thread declarator list (on top of instructions) @Override - public Object visitThreadDeclaratorList(LitmusVulkanParser.ThreadDeclaratorListContext ctx) { - for (LitmusVulkanParser.ThreadScopeContext threadScopeContext : ctx.threadScope()) { + public Object visitThreadDeclaratorList(ThreadDeclaratorListContext ctx) { + for (ThreadScopeContext threadScopeContext : ctx.threadScope()) { int subgroupID = threadScopeContext.subgroupScope().scopeID().id; int workgroupID = threadScopeContext.workgroupScope().scopeID().id; int queuefamilyID = threadScopeContext.queuefamilyScope().scopeID().id; @@ -119,17 +121,17 @@ public Object visitThreadDeclaratorList(LitmusVulkanParser.ThreadDeclaratorListC // ---------------------------------------------------------------------------------------------------------------- // Instruction list (the program itself) @Override - public Object visitConstant(LitmusVulkanParser.ConstantContext ctx) { + public Object visitConstant(ConstantContext ctx) { return ExpressionFactory.getInstance().parseValue(ctx.getText(), archType); } @Override - public Object visitRegister(LitmusVulkanParser.RegisterContext ctx) { + public Object visitRegister(RegisterContext ctx) { return programBuilder.getOrNewRegister(mainThread, ctx.getText(), archType); } @Override - public Object visitInstructionRow(LitmusVulkanParser.InstructionRowContext ctx) { + public Object visitInstructionRow(InstructionRowContext ctx) { for (int i = 0; i < threadCount; i++) { mainThread = i; visitInstruction(ctx.instruction(i)); @@ -138,7 +140,7 @@ public Object visitInstructionRow(LitmusVulkanParser.InstructionRowContext ctx) } @Override - public Object visitStoreInstruction(LitmusVulkanParser.StoreInstructionContext ctx) { + public Object visitStoreInstruction(StoreInstructionContext ctx) { MemoryObject object = programBuilder.getOrNewVirtualMemoryObject(ctx.location().getText()); Expression value = (Expression) ctx.value().accept(this); Store store = EventFactory.newStore(object, value); @@ -151,11 +153,11 @@ public Object visitStoreInstruction(LitmusVulkanParser.StoreInstructionContext c store.addTags(Tag.Vulkan.AVAILABLE); store.addTags(ctx.scope().content); } - return programBuilder.addChild(mainThread, store); + return append(store); } @Override - public Object visitLoadInstruction(LitmusVulkanParser.LoadInstructionContext ctx) { + public Object visitLoadInstruction(LoadInstructionContext ctx) { Register register = (Register) ctx.register().accept(this); MemoryObject location = programBuilder.getOrNewVirtualMemoryObject(ctx.location().getText()); Load load = EventFactory.newLoad(register, location); @@ -168,11 +170,11 @@ public Object visitLoadInstruction(LitmusVulkanParser.LoadInstructionContext ctx load.addTags(Tag.Vulkan.VISIBLE); load.addTags(ctx.scope().content); } - return programBuilder.addChild(mainThread, load); + return append(load); } @Override - public Object visitAtomicStoreInstruction(LitmusVulkanParser.AtomicStoreInstructionContext ctx) { + public Object visitAtomicStoreInstruction(AtomicStoreInstructionContext ctx) { MemoryObject object = programBuilder.getOrNewVirtualMemoryObject(ctx.location().getText()); Expression value = (Expression) ctx.value().accept(this); String mo = ctx.moRel() != null ? Tag.Vulkan.RELEASE : Tag.Vulkan.ATOM; @@ -188,11 +190,11 @@ public Object visitAtomicStoreInstruction(LitmusVulkanParser.AtomicStoreInstruct store.addTags(Tag.Vulkan.SEM_AVAILABLE); } store.addTags(ctx.semSc().stream().map(c -> c.content).toList()); - return programBuilder.addChild(mainThread, store); + return append(store); } @Override - public Object visitAtomicLoadInstruction(LitmusVulkanParser.AtomicLoadInstructionContext ctx) { + public Object visitAtomicLoadInstruction(AtomicLoadInstructionContext ctx) { Register register = (Register) ctx.register().accept(this); MemoryObject location = programBuilder.getOrNewVirtualMemoryObject(ctx.location().getText()); String mo = ctx.moAcq() != null ? Tag.Vulkan.ACQUIRE : Tag.Vulkan.ATOM; @@ -208,11 +210,11 @@ public Object visitAtomicLoadInstruction(LitmusVulkanParser.AtomicLoadInstructio load.addTags(Tag.Vulkan.SEM_VISIBLE); } load.addTags(ctx.semSc().stream().map(c -> c.content).toList()); - return programBuilder.addChild(mainThread, load); + return append(load); } @Override - public Object visitAtomicRmwInstruction(LitmusVulkanParser.AtomicRmwInstructionContext ctx) { + public Object visitAtomicRmwInstruction(AtomicRmwInstructionContext ctx) { Register register = (Register) ctx.register().accept(this); MemoryObject location = programBuilder.getOrNewVirtualMemoryObject(ctx.location().getText()); Expression value = (Expression) ctx.value().accept(this); @@ -233,29 +235,26 @@ public Object visitAtomicRmwInstruction(LitmusVulkanParser.AtomicRmwInstructionC rmw.addTags(Tag.Vulkan.SEM_VISIBLE); } rmw.addTags(ctx.semSc().stream().map(c -> c.content).toList()); - return programBuilder.addChild(mainThread, rmw); + return append(rmw); } @Override - public Object visitMemoryBarrierInstruction(LitmusVulkanParser.MemoryBarrierInstructionContext ctx) { - Event fence = EventFactory.newFence(Tag.FENCE); - String mo = getMemoryOrderOrDefault(ctx, null); - if (mo != null) { - fence.addTags(mo); - } - fence.addTags(ctx.scope().content); - if (ctx.semAv() != null) { - fence.addTags(Tag.Vulkan.SEM_AVAILABLE); - } - if (ctx.semVis() != null) { - fence.addTags(Tag.Vulkan.SEM_VISIBLE); - } - fence.addTags(ctx.semSc().stream().map(c -> c.content).toList()); - return programBuilder.addChild(mainThread, fence); + public Object visitMemoryBarrierInstruction(MemoryBarrierInstructionContext ctx) { + final String scope = ctx.scope().content; + final List semantics = ctx.semSc().stream().map(c -> c.content).toList(); + final boolean av = ctx.semAv() != null; + final boolean vis = ctx.semVis() != null; + final Event fence = switch (getMemoryOrderOrDefault(ctx, null)) { + case Tag.Vulkan.ACQUIRE -> EventFactory.Vulkan.newAcqBarrier(scope, semantics, vis); + case Tag.Vulkan.RELEASE -> EventFactory.Vulkan.newRelBarrier(scope, semantics, av); + case Tag.Vulkan.ACQ_REL -> EventFactory.Vulkan.newAcqRelBarrier(scope, semantics, av, vis); + default -> throw new ParsingException("Unknown barrier type"); + }; + return append(fence); } @Override - public Object visitControlBarrierInstruction(LitmusVulkanParser.ControlBarrierInstructionContext ctx) { + public Object visitControlBarrierInstruction(ControlBarrierInstructionContext ctx) { String name = ctx.getText().substring(0, ctx.getText().length() - ctx.constant().getText().length()); String instanceId = ctx.constant().getText(); Event barrier; @@ -283,40 +282,40 @@ public Object visitControlBarrierInstruction(LitmusVulkanParser.ControlBarrierIn } barrier.addTags(ctx.semSc().stream().map(c -> c.content).toList()); } - return programBuilder.addChild(mainThread, barrier); + return append(barrier); } @Override - public Object visitLocalInstruction(LitmusVulkanParser.LocalInstructionContext ctx) { + public Object visitLocalInstruction(LocalInstructionContext ctx) { Register rd = (Register) ctx.register().accept(this); Expression lhs = (Expression) ctx.value(0).accept(this); Expression rhs = (Expression) ctx.value(1).accept(this); Expression exp = expressions.makeIntBinary(lhs, ctx.operation().op, rhs); - return programBuilder.addChild(mainThread, EventFactory.newLocal(rd, exp)); + return append(EventFactory.newLocal(rd, exp)); } @Override - public Object visitLabelInstruction(LitmusVulkanParser.LabelInstructionContext ctx) { - return programBuilder.addChild(mainThread, programBuilder.getOrCreateLabel(mainThread, ctx.Label().getText())); + public Object visitLabelInstruction(LabelInstructionContext ctx) { + return append(programBuilder.getOrCreateLabel(mainThread, ctx.Label().getText())); } @Override - public Object visitJumpInstruction(LitmusVulkanParser.JumpInstructionContext ctx) { + public Object visitJumpInstruction(JumpInstructionContext ctx) { Label label = programBuilder.getOrCreateLabel(mainThread, ctx.Label().getText()); - return programBuilder.addChild(mainThread, EventFactory.newGoto(label)); + return append(EventFactory.newGoto(label)); } @Override - public Object visitCondJumpInstruction(LitmusVulkanParser.CondJumpInstructionContext ctx) { + public Object visitCondJumpInstruction(CondJumpInstructionContext ctx) { Label label = programBuilder.getOrCreateLabel(mainThread, ctx.Label().getText()); Expression lhs = (Expression) ctx.value(0).accept(this); Expression rhs = (Expression) ctx.value(1).accept(this); Expression expr = expressions.makeIntCmp(lhs, ctx.cond().op, rhs); - return programBuilder.addChild(mainThread, EventFactory.newJump(expr, label)); + return append(EventFactory.newJump(expr, label)); } @Override - public Object visitDeviceOperation(LitmusVulkanParser.DeviceOperationContext ctx) { + public Object visitDeviceOperation(DeviceOperationContext ctx) { Event e; if (ctx.getText().equalsIgnoreCase(Tag.Vulkan.AVDEVICE)) { e = EventFactory.Vulkan.newAvDevice(); @@ -325,19 +324,23 @@ public Object visitDeviceOperation(LitmusVulkanParser.DeviceOperationContext ctx } else { throw new ParsingException("Unknown device operation"); } - return programBuilder.addChild(mainThread, e); + return append(e); } private String getMemoryOrderOrDefault(ParserRuleContext ctx, String defaultMo) { - if (ctx.getRuleContext(LitmusVulkanParser.MoAcqContext.class, 0) != null) { + if (ctx.getRuleContext(MoAcqContext.class, 0) != null) { return Tag.Vulkan.ACQUIRE; } - if(ctx.getRuleContext(LitmusVulkanParser.MoRelContext.class, 0) != null) { + if(ctx.getRuleContext(MoRelContext.class, 0) != null) { return Tag.Vulkan.RELEASE; } - if (ctx.getRuleContext(LitmusVulkanParser.MoAcqRelContext.class, 0) != null) { + if (ctx.getRuleContext(MoAcqRelContext.class, 0) != null) { return Tag.Vulkan.ACQ_REL; } return defaultMo; } + + private Object append(Event event) { + return programBuilder.addChild(mainThread, event); + } } \ No newline at end of file diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusX86.java b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusX86.java index dfd674dbfb..14e15a8ef6 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusX86.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusX86.java @@ -7,20 +7,16 @@ import com.dat3m.dartagnan.expression.type.IntegerType; import com.dat3m.dartagnan.expression.type.TypeFactory; import com.dat3m.dartagnan.parsers.LitmusX86BaseVisitor; -import com.dat3m.dartagnan.parsers.LitmusX86Parser; +import com.dat3m.dartagnan.parsers.LitmusX86Parser.*; import com.dat3m.dartagnan.parsers.program.utils.ProgramBuilder; import com.dat3m.dartagnan.program.Program; import com.dat3m.dartagnan.program.Register; +import com.dat3m.dartagnan.program.event.Event; import com.dat3m.dartagnan.program.event.EventFactory; import com.dat3m.dartagnan.program.memory.MemoryObject; -import com.google.common.collect.ImmutableSet; - -import static com.dat3m.dartagnan.program.event.FenceNameRepository.*; public class VisitorLitmusX86 extends LitmusX86BaseVisitor { - private final static ImmutableSet fences = ImmutableSet.of(MFENCE); - private final ProgramBuilder programBuilder = ProgramBuilder.forArch(Program.SourceLanguage.LITMUS, Arch.TSO); private final TypeFactory types = programBuilder.getTypeFactory(); private final ExpressionFactory expressions = programBuilder.getExpressionFactory(); @@ -35,7 +31,7 @@ public VisitorLitmusX86(){ // Entry point @Override - public Object visitMain(LitmusX86Parser.MainContext ctx) { + public Object visitMain(MainContext ctx) { visitThreadDeclaratorList(ctx.program().threadDeclaratorList()); visitVariableDeclaratorList(ctx.variableDeclaratorList()); visitInstructionList(ctx.program().instructionList()); @@ -48,27 +44,27 @@ public Object visitMain(LitmusX86Parser.MainContext ctx) { // Variable declarator list, e.g., { 0:EAX=0; 1:EAX=1; x=2; } @Override - public Object visitVariableDeclaratorLocation(LitmusX86Parser.VariableDeclaratorLocationContext ctx) { + public Object visitVariableDeclaratorLocation(VariableDeclaratorLocationContext ctx) { IntLiteral value = expressions.parseValue(ctx.constant().getText(), archType); programBuilder.initLocEqConst(ctx.location().getText(), value); return null; } @Override - public Object visitVariableDeclaratorRegister(LitmusX86Parser.VariableDeclaratorRegisterContext ctx) { + public Object visitVariableDeclaratorRegister(VariableDeclaratorRegisterContext ctx) { IntLiteral value = expressions.parseValue(ctx.constant().getText(), archType); programBuilder.initRegEqConst(ctx.threadId().id, ctx.register().getText(), value); return null; } @Override - public Object visitVariableDeclaratorRegisterLocation(LitmusX86Parser.VariableDeclaratorRegisterLocationContext ctx) { + public Object visitVariableDeclaratorRegisterLocation(VariableDeclaratorRegisterLocationContext ctx) { programBuilder.initRegEqLocPtr(ctx.threadId().id, ctx.register().getText(), ctx.location().getText(), archType); return null; } @Override - public Object visitVariableDeclaratorLocationLocation(LitmusX86Parser.VariableDeclaratorLocationLocationContext ctx) { + public Object visitVariableDeclaratorLocationLocation(VariableDeclaratorLocationLocationContext ctx) { programBuilder.initLocEqLocPtr(ctx.location(0).getText(), ctx.location(1).getText()); return null; } @@ -78,8 +74,8 @@ public Object visitVariableDeclaratorLocationLocation(LitmusX86Parser.VariableDe // Thread declarator list (on top of instructions), e.g. " P0 | P1 | P2 ;" @Override - public Object visitThreadDeclaratorList(LitmusX86Parser.ThreadDeclaratorListContext ctx) { - for(LitmusX86Parser.ThreadIdContext threadCtx : ctx.threadId()){ + public Object visitThreadDeclaratorList(ThreadDeclaratorListContext ctx) { + for(ThreadIdContext threadCtx : ctx.threadId()){ programBuilder.newThread(threadCtx.id); threadCount++; } @@ -91,7 +87,7 @@ public Object visitThreadDeclaratorList(LitmusX86Parser.ThreadDeclaratorListCont // Instruction list (the program itself) @Override - public Object visitInstructionRow(LitmusX86Parser.InstructionRowContext ctx) { + public Object visitInstructionRow(InstructionRowContext ctx) { for(int i = 0; i < threadCount; i++){ mainThread = i; visitInstruction(ctx.instruction(i)); @@ -100,76 +96,82 @@ public Object visitInstructionRow(LitmusX86Parser.InstructionRowContext ctx) { } @Override - public Object visitLoadValueToRegister(LitmusX86Parser.LoadValueToRegisterContext ctx) { + public Object visitLoadValueToRegister(LoadValueToRegisterContext ctx) { Register register = programBuilder.getOrNewRegister(mainThread, ctx.register().getText(), archType); IntLiteral constant = expressions.parseValue(ctx.constant().getText(), archType); - return programBuilder.addChild(mainThread, EventFactory.newLocal(register, constant)); + return append(EventFactory.newLocal(register, constant)); } @Override - public Object visitLoadLocationToRegister(LitmusX86Parser.LoadLocationToRegisterContext ctx) { + public Object visitLoadLocationToRegister(LoadLocationToRegisterContext ctx) { Register register = programBuilder.getOrNewRegister(mainThread, ctx.register().getText(), archType); MemoryObject object = programBuilder.getOrNewMemoryObject(ctx.location().getText()); - return programBuilder.addChild(mainThread, EventFactory.newLoad(register, object)); + return append(EventFactory.newLoad(register, object)); } @Override - public Object visitStoreValueToLocation(LitmusX86Parser.StoreValueToLocationContext ctx) { + public Object visitStoreValueToLocation(StoreValueToLocationContext ctx) { MemoryObject object = programBuilder.getOrNewMemoryObject(ctx.location().getText()); IntLiteral constant = expressions.parseValue(ctx.constant().getText(), archType); - return programBuilder.addChild(mainThread, EventFactory.newStore(object, constant)); + return append(EventFactory.newStore(object, constant)); } @Override - public Object visitStoreRegisterToLocation(LitmusX86Parser.StoreRegisterToLocationContext ctx) { + public Object visitStoreRegisterToLocation(StoreRegisterToLocationContext ctx) { Register register = programBuilder.getOrErrorRegister(mainThread, ctx.register().getText()); MemoryObject object = programBuilder.getOrNewMemoryObject(ctx.location().getText()); - return programBuilder.addChild(mainThread, EventFactory.newStore(object, register)); + return append(EventFactory.newStore(object, register)); } @Override - public Object visitExchangeRegisterLocation(LitmusX86Parser.ExchangeRegisterLocationContext ctx) { + public Object visitExchangeRegisterLocation(ExchangeRegisterLocationContext ctx) { Register register = programBuilder.getOrErrorRegister(mainThread, ctx.register().getText()); MemoryObject object = programBuilder.getOrNewMemoryObject(ctx.location().getText()); - return programBuilder.addChild(mainThread, EventFactory.X86.newExchange(object, register)); + return append(EventFactory.X86.newExchange(object, register)); } @Override - public Object visitIncrementLocation(LitmusX86Parser.IncrementLocationContext ctx) { + public Object visitIncrementLocation(IncrementLocationContext ctx) { // TODO: Implementation throw new ParsingException("INC is not implemented"); } @Override - public Object visitCompareRegisterValue(LitmusX86Parser.CompareRegisterValueContext ctx) { + public Object visitCompareRegisterValue(CompareRegisterValueContext ctx) { // TODO: Implementation throw new ParsingException("CMP is not implemented"); } @Override - public Object visitCompareLocationValue(LitmusX86Parser.CompareLocationValueContext ctx) { + public Object visitCompareLocationValue(CompareLocationValueContext ctx) { // TODO: Implementation throw new ParsingException("CMP is not implemented"); } @Override - public Object visitAddRegisterRegister(LitmusX86Parser.AddRegisterRegisterContext ctx) { + public Object visitAddRegisterRegister(AddRegisterRegisterContext ctx) { // TODO: Implementation throw new ParsingException("ADD is not implemented"); } @Override - public Object visitAddRegisterValue(LitmusX86Parser.AddRegisterValueContext ctx) { + public Object visitAddRegisterValue(AddRegisterValueContext ctx) { // TODO: Implementation throw new ParsingException("ADD is not implemented"); } @Override - public Object visitFence(LitmusX86Parser.FenceContext ctx) { - String name = ctx.getText().toLowerCase(); - if(fences.contains(name)) { - return programBuilder.addChild(mainThread, EventFactory.newFence(name)); - } - throw new ParsingException("Unrecognised fence " + name); + public Object visitFence(FenceContext ctx) { + Event fence = switch (ctx.getText().toLowerCase()) { + case "mfence" -> EventFactory.X86.newMemoryFence(); + case "lfence" -> EventFactory.X86.newLoadFence(); + case "sfence" -> EventFactory.X86.newStoreFence(); + default -> throw new ParsingException("Unrecognised fence '%s'", ctx.getText()); + }; + return append(fence); + } + + private Object append(Event event) { + return programBuilder.addChild(mainThread, event); } } \ No newline at end of file diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/spirv/VisitorOpsAtomic.java b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/spirv/VisitorOpsAtomic.java index fe1a8f0910..3292922c38 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/spirv/VisitorOpsAtomic.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/spirv/VisitorOpsAtomic.java @@ -12,7 +12,6 @@ import com.dat3m.dartagnan.parsers.program.visitors.spirv.builders.ProgramBuilder; import com.dat3m.dartagnan.program.Register; import com.dat3m.dartagnan.program.event.Event; -import com.dat3m.dartagnan.program.event.lang.spirv.*; import java.util.Set; @@ -33,8 +32,7 @@ public Event visitOpAtomicLoad(SpirvParser.OpAtomicLoadContext ctx) { String scope = getScopeTag(ctx.memory().getText()); Set tags = getMemorySemanticsTags(ctx.semantics().getText()); tags.add(builder.getPointerStorageClass(ctx.pointer().getText())); - SpirvLoad event = newSpirvLoad(register, ptr, scope, tags); - return builder.addEvent(event); + return builder.addEvent(newSpirvLoad(register, ptr, scope, tags)); } @Override @@ -44,8 +42,7 @@ public Event visitOpAtomicStore(SpirvParser.OpAtomicStoreContext ctx) { String scope = getScopeTag(ctx.memory().getText()); Set tags = getMemorySemanticsTags(ctx.semantics().getText()); tags.add(builder.getPointerStorageClass(ctx.pointer().getText())); - SpirvStore event = newSpirvStore(ptr, value, scope, tags); - return builder.addEvent(event); + return builder.addEvent(newSpirvStore(ptr, value, scope, tags)); } @Override @@ -56,8 +53,7 @@ public Event visitOpAtomicExchange(SpirvParser.OpAtomicExchangeContext ctx) { String scope = getScopeTag(ctx.memory().getText()); Set tags = getMemorySemanticsTags(ctx.semantics().getText()); tags.add(builder.getPointerStorageClass(ctx.pointer().getText())); - SpirvXchg event = newSpirvXchg(register, ptr, value, scope, tags); - return builder.addEvent(event); + return builder.addEvent(newSpirvXchg(register, ptr, value, scope, tags)); } @Override @@ -160,8 +156,7 @@ private Event visitOpAtomicCompareExchange( neqTags.add(builder.getPointerStorageClass(ptrCtx.getText())); Expression value = builder.getExpression(valCtx.getText()); Expression cmp = builder.getExpression(cmpCtx.getText()); - SpirvCmpXchg event = newSpirvCmpXchg(register, ptr, cmp, value, scope, eqTags, neqTags); - return builder.addEvent(event); + return builder.addEvent(newSpirvCmpXchg(register, ptr, cmp, value, scope, eqTags, neqTags)); } private Event visitAtomicOpIncDec( @@ -208,8 +203,7 @@ private Event visitAtomicOp( String scope = getScopeTag(scopeCtx.getText()); Set tags = getMemorySemanticsTags(tagsCtx.getText()); tags.add(builder.getPointerStorageClass(ptrCtx.getText())); - SpirvRmw event = newSpirvRmw(register, ptr, op, value, scope, tags); - return builder.addEvent(event); + return builder.addEvent(newSpirvRmw(register, ptr, op, value, scope, tags)); } private String getScopeTag(String scopeId) { diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/program/event/EventFactory.java b/dartagnan/src/main/java/com/dat3m/dartagnan/program/event/EventFactory.java index 33c7d2825e..294863885e 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/program/event/EventFactory.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/program/event/EventFactory.java @@ -31,7 +31,7 @@ import java.util.*; import java.util.stream.Collectors; -import static com.dat3m.dartagnan.program.event.FenceNameRepository.*; +import static com.google.common.base.Preconditions.checkArgument; public class EventFactory { @@ -136,12 +136,6 @@ public static GenericVisibleEvent newFence(String name) { return new GenericVisibleEvent(name, name, Tag.FENCE); } - public static GenericVisibleEvent newFenceOpt(String name, String opt) { - GenericVisibleEvent fence = newFence(name + "." + opt); - fence.addTags(name); - return fence; - } - public static ControlBarrier newControlBarrier(String name, String instanceId, String execScope) { return new ControlBarrier(name, instanceId, execScope); } @@ -309,12 +303,14 @@ public static Load newRMWLoadExclusiveWithMo(Register reg, Expression address, S return load; } - public static RMWStoreExclusive newRMWStoreExclusive(Expression address, Expression value, boolean isStrong) { - return new RMWStoreExclusive(address, value, isStrong, false); + public static RMWStoreExclusive newRMWStoreExclusive(Expression address, Expression value, boolean isStrong, + boolean requiresMatchingAddresses) { + return new RMWStoreExclusive(address, value, isStrong, requiresMatchingAddresses); } - public static RMWStoreExclusive newRMWStoreExclusiveWithMo(Expression address, Expression value, boolean isStrong, String mo) { - RMWStoreExclusive store = newRMWStoreExclusive(address, value, isStrong); + public static RMWStoreExclusive newRMWStoreExclusiveWithMo(Expression address, Expression value, boolean isStrong, + boolean requiresMatchingAddresses, String mo) { + final RMWStoreExclusive store = newRMWStoreExclusive(address, value, isStrong, requiresMatchingAddresses); store.setMemoryOrder(mo); return store; } @@ -467,6 +463,34 @@ public static AtomicXchg newExchange(Register register, Expression address, Expr return new AtomicXchg(register, address, value, mo); } } + + // ============================================================================================= + // ======================================== C11 / IMM ========================================== + // ============================================================================================= + + public static class C11 { + + 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); + } + + public static GenericVisibleEvent newThreadFence(String mo) { + return new GenericVisibleEvent("atomic_thread_fence(%s)".formatted(mo), mo, Tag.FENCE); + } + } + // ============================================================================================= // =========================================== LLVM ============================================ // ============================================================================================= @@ -527,53 +551,64 @@ public static class AArch64 { private AArch64() { } - public static class DMB { - private DMB() { - } + public static Load newRMWLoadExclusive(Register register, Expression address, String mo) { + return newRMWLoadExclusiveWithMo(register, address, mo); + } - public static GenericVisibleEvent newSYBarrier() { - return newFence("DMB.SY"); - } + public static Store newRMWStoreExclusive(Expression address, Expression value, boolean strong, String mo) { + return newRMWStoreExclusiveWithMo(address, value, strong, false, mo); + } - public static GenericVisibleEvent newSTBarrier() { - return newFence("DMB.ST"); - } + public static GenericVisibleEvent newDmbBarrier() { + return newBarrier("DMB", "SY"); + } - public static GenericVisibleEvent newISHBarrier() { - return newFence("DMB.ISH"); - } + public static GenericVisibleEvent newDmbStBarrier() { + return newBarrier("DMB", "ST"); + } - public static GenericVisibleEvent newISHLDBarrier() { - return newFence("DMB.ISHLD"); - } + public static GenericVisibleEvent newDmbIshBarrier() { + return newBarrier("DMB", "ISH"); + } - public static GenericVisibleEvent newISHSTBarrier() { - return newFence("DMB.ISHST"); - } + public static GenericVisibleEvent newDmbIshLdBarrier() { + return newBarrier("DMB", "ISHLD"); } - public static class DSB { - private DSB() { - } + public static GenericVisibleEvent newDmbIshStBarrier() { + return newBarrier("DMB", "ISHST"); + } - public static GenericVisibleEvent newSYBarrier() { - return newFence("DSB.SY"); - } + public static GenericVisibleEvent newDsbBarrier() { + return newBarrier("DSB", "SY"); + } - public static GenericVisibleEvent newISHBarrier() { - return newFence("DSB.ISH"); - } + public static GenericVisibleEvent newDsbIshBarrier() { + return newBarrier("DSB", "ISH"); + } - public static GenericVisibleEvent newISHLDBarrier() { - return newFence("DSB.ISHLD"); - } + public static GenericVisibleEvent newDsbIshLdBarrier() { + return newBarrier("DSB", "ISHLD"); + } - public static GenericVisibleEvent newISHSTBarrier() { - return newFence("DSB.ISHST"); - } + public static GenericVisibleEvent newDsbIshStBarrier() { + return newBarrier("DSB", "ISHST"); + } + public static GenericVisibleEvent newBarrier(String type, String option) { + final String typeUpper = type.toUpperCase(); + final String optionUpper = option.toUpperCase(); + checkArgument(BARRIER_TYPE.contains(typeUpper), "Unknown barrier type %s", type); + checkArgument(BARRIER_OPT.contains(optionUpper), "Unknown barrier option %s"); + final String name = "%s.%s".formatted(typeUpper, optionUpper); + return new GenericVisibleEvent(name, name, Tag.FENCE, typeUpper); } + private static final Set BARRIER_TYPE = Set.of("DMB", "DSB", "ISB"); + + private static final Set BARRIER_OPT = Set.of( + "SY", "LD", "ST", "ISH", "ISHLD", "ISHST", "OSH", "OSHLD", "OSHST", "NSH", "NSHLD", "NSHST" + ); } // ============================================================================================= @@ -642,6 +677,9 @@ public static GenericMemoryEvent newSrcuSync(Expression address) { return srcuSync; } + public static GenericVisibleEvent newFence(String fenceType) { + return EventFactory.newFence(fenceType); + } } @@ -657,7 +695,15 @@ public static TSOXchg newExchange(MemoryObject address, Register register) { } public static GenericVisibleEvent newMemoryFence() { - return newFence(MFENCE); + return newFence("mfence"); + } + + public static GenericVisibleEvent newLoadFence() { + throw new UnsupportedOperationException(); + } + + public static GenericVisibleEvent newStoreFence() { + throw new UnsupportedOperationException(); } } @@ -669,15 +715,14 @@ public static class RISCV { private RISCV() { } - public static RMWStoreExclusive newRMWStoreConditional(Expression address, Expression value, String mo, boolean isStrong) { - RMWStoreExclusive store = new RMWStoreExclusive(address, value, isStrong, true); - store.addTags(Tag.RISCV.STCOND); - store.setMemoryOrder(mo); - return store; + public static Load newRMWLoadExclusive(Register register, Expression value, String mo) { + return EventFactory.newRMWLoadExclusiveWithMo(register, value, mo); } - public static RMWStoreExclusive newRMWStoreConditional(Expression address, Expression value, String mo) { - return RISCV.newRMWStoreConditional(address, value, mo, false); + public static Store newRMWStoreConditional(Expression address, Expression value, boolean strong, String mo) { + Store store = newRMWStoreExclusiveWithMo(address, value, strong, true, mo); + store.addTags(Tag.RISCV.STCOND); + return store; } public static GenericVisibleEvent newRRFence() { @@ -732,20 +777,24 @@ public static class Power { private Power() { } - public static RMWStoreExclusive newRMWStoreConditional(Expression address, Expression value, boolean isStrong) { - return new RMWStoreExclusive(address, value, isStrong, true); + public static Load newRMWLoadExclusive(Register register, Expression address) { + return EventFactory.newRMWLoadExclusive(register, address); + } + + public static Store newRMWStoreConditional(Expression address, Expression value, boolean isStrong) { + return newRMWStoreExclusive(address, value, isStrong, true); } public static GenericVisibleEvent newISyncBarrier() { - return newFence(ISYNC); + return newFence("isync"); } public static GenericVisibleEvent newSyncBarrier() { - return newFence(SYNC); + return newFence("sync"); } public static GenericVisibleEvent newLwSyncBarrier() { - return newFence(LWSYNC); + return newFence("lwsync"); } } @@ -755,30 +804,30 @@ public static GenericVisibleEvent newLwSyncBarrier() { public static class PTX { private PTX() {} - public static PTXAtomOp newAtomOp(Expression address, Register register, Expression value, - IntBinaryOp op, String mo, String scope) { + public static Event newAtomOp(Expression address, Register register, Expression value, + IntBinaryOp op, String mo, String scope) { // PTX (currently) only generates memory orders ACQ_REL and RLX for atom. PTXAtomOp atom = new PTXAtomOp(register, address, op, value, mo); atom.addTags(scope); return atom; } - public static PTXAtomCAS newAtomCAS(Expression address, Register register, Expression expected, + public static Event newAtomCAS(Expression address, Register register, Expression expected, Expression value, String mo, String scope) { PTXAtomCAS atom = new PTXAtomCAS(register, address, expected, value, mo); atom.addTags(scope); return atom; } - public static PTXAtomExch newAtomExch(Expression address, Register register, - Expression value, String mo, String scope) { + public static Event newAtomExch(Expression address, Register register, + Expression value, String mo, String scope) { PTXAtomExch atom = new PTXAtomExch(register, address, value, mo); atom.addTags(scope); return atom; } - public static PTXRedOp newRedOp(Expression address, Expression value, - IntBinaryOp op, String mo, String scope) { + public static Event newRedOp(Expression address, Expression value, + IntBinaryOp op, String mo, String scope) { // PTX (currently) only generates memory orders ACQ_REL and RLX for red. PTXRedOp red = new PTXRedOp(address, value, op, mo); red.addTags(scope); @@ -807,6 +856,27 @@ public static VulkanCmpXchg newVulkanCmpXchg(Expression address, Register regist return new VulkanCmpXchg(register, address, expected, value, mo, scope); } + public static GenericVisibleEvent newAcqBarrier(String scope, List semantics, boolean visible) { + final GenericVisibleEvent barrier = newFence(Tag.FENCE); + barrier.addTags(semantics); + barrier.addTags(Tag.Vulkan.ACQUIRE, scope, visible ? Tag.Vulkan.SEM_VISIBLE : ""); + return barrier; + } + + public static GenericVisibleEvent newRelBarrier(String scope, List semantics, boolean available) { + final GenericVisibleEvent barrier = newFence(Tag.FENCE); + barrier.addTags(semantics); + barrier.addTags(Tag.Vulkan.RELEASE, scope, available ? Tag.Vulkan.SEM_AVAILABLE : ""); + return barrier; + } + + public static Event newAcqRelBarrier(String scope, List semantics, boolean available, boolean visible) { + final GenericVisibleEvent barrier = newFence(Tag.FENCE); + barrier.addTags(semantics); + barrier.addTags(Tag.Vulkan.ACQ_REL, scope, available ? Tag.Vulkan.SEM_AVAILABLE : "", visible ? Tag.Vulkan.SEM_VISIBLE : ""); + return barrier; + } + public static GenericVisibleEvent newAvDevice() { return new GenericVisibleEvent("avdevice", Tag.Vulkan.AVDEVICE); } diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/program/event/FenceNameRepository.java b/dartagnan/src/main/java/com/dat3m/dartagnan/program/event/FenceNameRepository.java deleted file mode 100644 index 5f635a8d5b..0000000000 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/program/event/FenceNameRepository.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.dat3m.dartagnan.program.event; - -public class FenceNameRepository { - - public static final String MFENCE = "mfence"; - public static final String SYNC = "sync"; - public static final String ISYNC = "isync"; - public static final String LWSYNC = "lwsync"; - -} diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorArm7.java b/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorArm7.java index f0fd798bcb..0b89a37425 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorArm7.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorArm7.java @@ -18,7 +18,7 @@ protected VisitorArm7() {} @Override public List visitStoreExclusive(StoreExclusive e) { - RMWStoreExclusive store = newRMWStoreExclusiveWithMo(e.getAddress(), e.getMemValue(), false, e.getMo()); + Store store = newRMWStoreExclusiveWithMo(e.getAddress(), e.getMemValue(), false, false, e.getMo()); return eventSequence( store, @@ -33,14 +33,14 @@ public List visitStoreExclusive(StoreExclusive e) { public List visitAtomicLoad(AtomicLoad e) { return eventSequence( newLoad(e.getResultRegister(), e.getAddress()), - isAtomicAcquire(e.getMo()) ? AArch64.DMB.newISHBarrier() : null + isAtomicAcquire(e.getMo()) ? AArch64.newDmbIshBarrier() : null ); } @Override public List visitAtomicStore(AtomicStore e) { return eventSequence( - isAtomicRelease(e.getMo()) ? AArch64.DMB.newISHBarrier() : null, + isAtomicRelease(e.getMo()) ? AArch64.newDmbIshBarrier() : null, newStore(e.getAddress(), e.getMemValue()) ); } @@ -51,7 +51,7 @@ public List visitAtomicFetchOp(AtomicFetchOp e) { final Load load = newRMWLoad(e.getResultRegister(), e.getAddress()); return eventSequence( load, - isAtomicAcquire(e.getMo()) || isAtomicRelease(e.getMo()) ? AArch64.DMB.newISHBarrier() : null, + isAtomicAcquire(e.getMo()) || isAtomicRelease(e.getMo()) ? AArch64.newDmbIshBarrier() : null, newRMWStore(load, e.getAddress(), value) ); } @@ -62,7 +62,7 @@ public List visitLKMMFetchOp(LKMMFetchOp e) { final Load load = newRMWLoad(e.getResultRegister(), e.getAddress()); return eventSequence( load, - isAtomicAcquire(e.getMo()) || isAtomicRelease(e.getMo()) ? AArch64.DMB.newISHBarrier() : null, + isAtomicAcquire(e.getMo()) || isAtomicRelease(e.getMo()) ? AArch64.newDmbIshBarrier() : null, newRMWStore(load, e.getAddress(), value) ); } diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorArm8.java b/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorArm8.java index 8fa38cc9ef..9bed5e8cbb 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorArm8.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorArm8.java @@ -7,8 +7,6 @@ import com.dat3m.dartagnan.program.Register; import com.dat3m.dartagnan.program.event.Event; import com.dat3m.dartagnan.program.event.Tag; -import com.dat3m.dartagnan.program.event.Tag.ARMv8; -import com.dat3m.dartagnan.program.event.Tag.C11; import com.dat3m.dartagnan.program.event.arch.*; import com.dat3m.dartagnan.program.event.core.*; import com.dat3m.dartagnan.program.event.lang.catomic.*; @@ -19,6 +17,7 @@ import java.util.List; import static com.dat3m.dartagnan.program.event.EventFactory.*; +import static com.dat3m.dartagnan.program.event.Tag.ARMv8.*; import static com.google.common.base.Verify.verify; class VisitorArm8 extends VisitorBase { @@ -34,7 +33,7 @@ protected VisitorArm8(boolean useRC11Scheme) { @Override public List visitStoreExclusive(StoreExclusive e) { - final RMWStoreExclusive store = newRMWStoreExclusiveWithMo(e.getAddress(), e.getMemValue(), false, e.getMo()); + Store store = AArch64.newRMWStoreExclusive(e.getAddress(), e.getMemValue(), false, e.getMo()); return eventSequence( store, @@ -46,14 +45,14 @@ public List visitStoreExclusive(StoreExclusive e) { public List visitXchg(Xchg xchg) { final Register resultRegister = xchg.getResultRegister(); final Expression address = xchg.getAddress(); - final String loadMo = xchg.hasTag(ARMv8.MO_ACQ) ? ARMv8.MO_ACQ : ""; - final String storeMo = xchg.hasTag(ARMv8.MO_REL) ? ARMv8.MO_REL : ""; + final String loadMo = xchg.hasTag(MO_ACQ) ? MO_ACQ : ""; + final String storeMo = xchg.hasTag(MO_REL) ? MO_REL : ""; final Register dummy = xchg.getFunction().newRegister(resultRegister.getType()); return eventSequence( - propagateNoRet(xchg, newRMWLoadExclusiveWithMo(dummy, address, loadMo)), - newRMWStoreExclusiveWithMo(address, xchg.getValue(), true, storeMo), + propagateNoRet(xchg, AArch64.newRMWLoadExclusive(dummy, address, loadMo)), + AArch64.newRMWStoreExclusive(address, xchg.getValue(), true, storeMo), newLocal(resultRegister, dummy) ); } @@ -63,20 +62,18 @@ public List visitCas(CAS cas) { final Register resultRegister = cas.getResultRegister(); final Expression address = cas.getAddress(); - final String loadMo = cas.hasTag(ARMv8.MO_ACQ) ? ARMv8.MO_ACQ : ""; - final String storeMo = cas.hasTag(ARMv8.MO_REL) ? ARMv8.MO_REL : ""; - + final String loadMo = cas.hasTag(MO_ACQ) ? MO_ACQ : ""; + final String storeMo = cas.hasTag(MO_REL) ? MO_REL : ""; final Register dummy = cas.getFunction().newRegister(resultRegister.getType()); final Load load = propagateNoRet(cas, newRMWLoadWithMo(dummy, address, loadMo)); final Store store = newRMWStoreWithMo(load, address, cas.getStoreValue(), storeMo); final Expression cmp = expressions.makeEQ(dummy, cas.getExpectedValue()); final Label casEnd = newLabel("CAS_end"); - final CondJump branchOnCasCmpResult = newJumpUnless(cmp, casEnd); return eventSequence( load, - branchOnCasCmpResult, + newJumpUnless(cmp, casEnd), store, casEnd, newLocal(resultRegister, dummy) @@ -85,14 +82,14 @@ public List visitCas(CAS cas) { @Override public List visitRMWOp(RMWOp rmwOp) { - Preconditions.checkArgument(!rmwOp.hasTag(ARMv8.MO_ACQ), "Unexpected MO_ACQ tag for RMWOp"); + Preconditions.checkArgument(!rmwOp.hasTag(MO_ACQ), "Unexpected MO_ACQ tag for RMWOp"); final Expression address = rmwOp.getAddress(); - final String storeMo = rmwOp.hasTag(ARMv8.MO_REL) ? ARMv8.MO_REL : ""; + final String storeMo = rmwOp.hasTag(MO_REL) ? MO_REL : ""; final Register dummy = rmwOp.getFunction().newRegister(rmwOp.getAccessType()); final Load load = newRMWLoad(dummy, address); - load.addTags(Tag.ARMv8.NO_RET); + load.addTags(NO_RET); final Expression value = expressions.makeBinary(dummy, rmwOp.getOperator(), rmwOp.getOperand()); return eventSequence( @@ -105,8 +102,8 @@ public List visitRMWOp(RMWOp rmwOp) { public List visitRMWFetchOp(RMWFetchOp rmwOp) { final Register resultRegister = rmwOp.getResultRegister(); final Expression address = rmwOp.getAddress(); - final String loadMo = rmwOp.hasTag(ARMv8.MO_ACQ) ? ARMv8.MO_ACQ : ""; - final String storeMo = rmwOp.hasTag(ARMv8.MO_REL) ? ARMv8.MO_REL : ""; + final String loadMo = rmwOp.hasTag(MO_ACQ) ? MO_ACQ : ""; + final String storeMo = rmwOp.hasTag(MO_REL) ? MO_REL : ""; final Register dummy = rmwOp.getFunction().newRegister(resultRegister.getType()); final Load load = propagateNoRet(rmwOp, newRMWLoadWithMo(dummy, address, loadMo)); @@ -120,8 +117,8 @@ public List visitRMWFetchOp(RMWFetchOp rmwOp) { } private T propagateNoRet(Event orig, T newEv) { - if (orig.hasTag(ARMv8.NO_RET)) { - newEv.addTags(Tag.ARMv8.NO_RET); + if (orig.hasTag(NO_RET)) { + newEv.addTags(NO_RET); } return newEv; } @@ -132,7 +129,7 @@ private T propagateNoRet(Event orig, T newEv) { @Override public List visitLlvmLoad(LlvmLoad e) { - Load load = newLoadWithMo(e.getResultRegister(), e.getAddress(), ARMv8.extractLoadMoFromCMo(e.getMo())); + Load load = newLoadWithMo(e.getResultRegister(), e.getAddress(), extractLoadMoFromCMo(e.getMo())); return eventSequence( load @@ -141,7 +138,7 @@ public List visitLlvmLoad(LlvmLoad e) { @Override public List visitLlvmStore(LlvmStore e) { - Store store = newStoreWithMo(e.getAddress(), e.getMemValue(), ARMv8.extractStoreMoFromCMo(e.getMo())); + Store store = newStoreWithMo(e.getAddress(), e.getMemValue(), extractStoreMoFromCMo(e.getMo())); return eventSequence( store @@ -154,8 +151,8 @@ public List visitLlvmXchg(LlvmXchg e) { Expression address = e.getAddress(); String mo = e.getMo(); - Load load = newRMWLoadExclusiveWithMo(resultRegister, address, ARMv8.extractLoadMoFromCMo(mo)); - Store store = newRMWStoreExclusiveWithMo(address, e.getValue(), true, ARMv8.extractStoreMoFromCMo(mo)); + Load load = AArch64.newRMWLoadExclusive(resultRegister, address, extractLoadMoFromCMo(mo)); + Store store = AArch64.newRMWStoreExclusive(address, e.getValue(), true, extractStoreMoFromCMo(mo)); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(resultRegister, label); @@ -176,8 +173,8 @@ public List visitLlvmRMW(LlvmRMW e) { Register dummyReg = e.getFunction().newRegister(resultRegister.getType()); Local localOp = newLocal(dummyReg, expressions.makeIntBinary(resultRegister, e.getOperator(), e.getOperand())); - Load load = newRMWLoadExclusiveWithMo(resultRegister, address, ARMv8.extractLoadMoFromCMo(mo)); - Store store = newRMWStoreExclusiveWithMo(address, dummyReg, true, ARMv8.extractStoreMoFromCMo(mo)); + Load load = AArch64.newRMWLoadExclusive(resultRegister, address, extractLoadMoFromCMo(mo)); + Store store = AArch64.newRMWStoreExclusive(address, dummyReg, true, extractStoreMoFromCMo(mo)); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(resultRegister, label); @@ -199,8 +196,8 @@ protected List newLlvmCmpXchg(Register oldValue, Register success, Expres final Label casEnd = newLabel("CAS_end"); final CondJump branchOnCasCmpResult = newJumpUnless(success, casEnd); - final Load load = newRMWLoadExclusiveWithMo(oldValue, address, ARMv8.extractLoadMoFromCMo(mo)); - final Store store = newRMWStoreExclusiveWithMo(address, newValue, strong, ARMv8.extractStoreMoFromCMo(mo)); + final Load load = AArch64.newRMWLoadExclusive(oldValue, address, extractLoadMoFromCMo(mo)); + final Store store = AArch64.newRMWStoreExclusive(address, newValue, strong, extractStoreMoFromCMo(mo)); return eventSequence( load, @@ -215,12 +212,11 @@ protected List newLlvmCmpXchg(Register oldValue, Register success, Expres @Override public List visitLlvmFence(LlvmFence e) { - String mo = e.getMo(); - Event fence = mo.equals(C11.MO_RELEASE) || mo.equals(C11.MO_ACQUIRE_RELEASE) || mo.equals(C11.MO_SC) ? - AArch64.DMB.newISHBarrier() : - mo.equals(C11.MO_ACQUIRE) ? - AArch64.DSB.newISHLDBarrier() : - null; + Event fence = switch (e.getMo()) { + case Tag.C11.MO_RELEASE, Tag.C11.MO_SC -> AArch64.newDmbIshBarrier(); + case Tag.C11.MO_ACQUIRE -> AArch64.newDsbIshLdBarrier(); + default -> null; + }; return eventSequence( fence @@ -237,6 +233,7 @@ public List visitAtomicCmpXchg(AtomicCmpXchg e) { Expression address = e.getAddress(); Expression value = e.getStoreValue(); String mo = e.getMo(); + boolean strong = e.isStrong(); Expression expectedAddr = e.getAddressOfExpected(); Type type = resultRegister.getType(); Register booleanResultRegister = type instanceof BooleanType ? resultRegister : @@ -252,15 +249,11 @@ public List visitAtomicCmpXchg(AtomicCmpXchg e) { Local casCmpResult = newLocal(booleanResultRegister, expressions.makeEQ(regValue, regExpected)); CondJump branchOnCasCmpResult = newJumpUnless(booleanResultRegister, casFail); CondJump gotoCasEnd = newGoto(casEnd); - Load loadValue = newRMWLoadExclusiveWithMo(regValue, address, ARMv8.extractLoadMoFromCMo(mo)); - Store storeValue = newRMWStoreExclusiveWithMo(address, value, e.isStrong(), ARMv8.extractStoreMoFromCMo(mo)); - ExecutionStatus optionalExecStatus = null; - Local optionalUpdateCasCmpResult = null; - if (e.isWeak()) { - Register statusReg = e.getFunction().newRegister("status(" + e.getLocalId() + ")", types.getBooleanType()); - optionalExecStatus = newExecutionStatus(statusReg, storeValue); - optionalUpdateCasCmpResult = newLocal(booleanResultRegister, expressions.makeNot(statusReg)); - } + Load loadValue = AArch64.newRMWLoadExclusive(regValue, address, extractLoadMoFromCMo(mo)); + Store storeValue = AArch64.newRMWStoreExclusive(address, value, strong, extractStoreMoFromCMo(mo)); + 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)); return eventSequence( loadExpected, loadValue, @@ -285,9 +278,9 @@ public List visitAtomicFetchOp(AtomicFetchOp e) { Register dummyReg = e.getFunction().newRegister(resultRegister.getType()); - Load load = newRMWLoadExclusiveWithMo(resultRegister, address, ARMv8.extractLoadMoFromCMo(mo)); + Load load = AArch64.newRMWLoadExclusive(resultRegister, address, extractLoadMoFromCMo(mo)); Local localOp = newLocal(dummyReg, expressions.makeIntBinary(resultRegister, e.getOperator(), e.getOperand())); - Store store = newRMWStoreExclusiveWithMo(address, dummyReg, true, ARMv8.extractStoreMoFromCMo(mo)); + Store store = AArch64.newRMWStoreExclusive(address, dummyReg, true, extractStoreMoFromCMo(mo)); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(resultRegister, label); @@ -303,22 +296,24 @@ public List visitAtomicFetchOp(AtomicFetchOp e) { @Override public List visitAtomicLoad(AtomicLoad e) { return eventSequence( - newLoadWithMo(e.getResultRegister(), e.getAddress(), ARMv8.extractLoadMoFromCMo(e.getMo())) + newLoadWithMo(e.getResultRegister(), e.getAddress(), extractLoadMoFromCMo(e.getMo())) ); } @Override public List visitAtomicStore(AtomicStore e) { return eventSequence( - newStoreWithMo(e.getAddress(), e.getMemValue(), useRC11Scheme ? ARMv8.MO_REL : ARMv8.extractStoreMoFromCMo(e.getMo())) + newStoreWithMo(e.getAddress(), e.getMemValue(), useRC11Scheme ? MO_REL : extractStoreMoFromCMo(e.getMo())) ); } @Override public List visitAtomicThreadFence(AtomicThreadFence e) { - String mo = e.getMo(); - Event fence = mo.equals(C11.MO_RELEASE) || mo.equals(C11.MO_ACQUIRE_RELEASE) || mo.equals(C11.MO_SC) ? AArch64.DMB.newISHBarrier() - : mo.equals(C11.MO_ACQUIRE) ? AArch64.DSB.newISHLDBarrier() : null; + Event fence = switch (e.getMo()) { + case Tag.C11.MO_RELEASE, Tag.C11.MO_ACQUIRE_RELEASE, Tag.C11.MO_SC -> AArch64.newDmbIshBarrier(); + case Tag.C11.MO_ACQUIRE -> AArch64.newDsbIshLdBarrier(); + default -> null; + }; return eventSequence( fence @@ -331,8 +326,8 @@ public List visitAtomicXchg(AtomicXchg e) { Expression address = e.getAddress(); String mo = e.getMo(); - Load load = newRMWLoadExclusiveWithMo(resultRegister, address, ARMv8.extractLoadMoFromCMo(mo)); - Store store = newRMWStoreExclusiveWithMo(address, e.getValue(), true, ARMv8.extractStoreMoFromCMo(mo)); + Load load = AArch64.newRMWLoadExclusive(resultRegister, address, extractLoadMoFromCMo(mo)); + Store store = AArch64.newRMWStoreExclusive(address, e.getValue(), true, extractStoreMoFromCMo(mo)); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(resultRegister, label); @@ -356,7 +351,7 @@ public List visitLKMMLoad(LKMMLoad e) { Expression address = e.getAddress(); String mo = e.getMo(); - Load load = newLoadWithMo(resultRegister, address, ARMv8.extractLoadMoFromLKMo(mo)); + Load load = newLoadWithMo(resultRegister, address, extractLoadMoFromLKMo(mo)); return eventSequence( load @@ -371,8 +366,8 @@ public List visitLKMMStore(LKMMStore e) { Expression address = e.getAddress(); String mo = e.getMo(); - Store store = newStoreWithMo(address, value, mo.equals(Tag.Linux.MO_RELEASE) ? Tag.ARMv8.MO_REL : ""); - Event optionalMemoryBarrier = mo.equals(Tag.Linux.MO_MB) ? AArch64.DSB.newISHBarrier() : null; + Store store = newStoreWithMo(address, value, mo.equals(Tag.Linux.MO_RELEASE) ? MO_REL : ""); + Event optionalMemoryBarrier = mo.equals(Tag.Linux.MO_MB) ? AArch64.newDsbIshBarrier() : null; return eventSequence( store, @@ -386,27 +381,26 @@ public List visitLKMMStore(LKMMStore e) { public List visitLKMMFence(LKMMFence e) { Event optionalMemoryBarrier = switch (e.getName()) { // mb() - case Tag.Linux.MO_MB -> AArch64.DSB.newISHBarrier(); + case Tag.Linux.MO_MB -> AArch64.newDsbIshBarrier(); // rmb() - case Tag.Linux.MO_RMB -> AArch64.DSB.newISHLDBarrier(); + case Tag.Linux.MO_RMB -> AArch64.newDsbIshLdBarrier(); // wmb() - case Tag.Linux.MO_WMB -> AArch64.DSB.newISHSTBarrier(); + case Tag.Linux.MO_WMB -> AArch64.newDsbIshStBarrier(); // __smp_mb() // https://elixir.bootlin.com/linux/v5.18/source/include/asm-generic/barrier.h case Tag.Linux.BEFORE_ATOMIC, - Tag.Linux.AFTER_ATOMIC -> AArch64.DMB.newISHBarrier(); + Tag.Linux.AFTER_ATOMIC -> AArch64.newDmbIshBarrier(); // #define smp_mb__after_spinlock() smp_mb() // https://elixir.bootlin.com/linux/v6.1/source/arch/arm64/include/asm/spinlock.h#L12 - case Tag.Linux.AFTER_SPINLOCK -> AArch64.DSB.newISHBarrier(); + case Tag.Linux.AFTER_SPINLOCK -> AArch64.newDsbIshBarrier(); // #define smp_mb__after_unlock_lock() smp_mb() /* Full ordering for lock. */ // https://elixir.bootlin.com/linux/v6.1/source/include/linux/rcupdate.h#L1008 // It seem to be only used for RCU related stuff in the kernel so it makes sense // it is defined in that header file - case Tag.Linux.AFTER_UNLOCK_LOCK -> AArch64.DSB.newISHBarrier(); + case Tag.Linux.AFTER_UNLOCK_LOCK -> AArch64.newDsbIshBarrier(); // https://elixir.bootlin.com/linux/v6.1/source/include/linux/compiler.h#L86 case Tag.Linux.BARRIER -> null; - default -> - throw new UnsupportedOperationException("Compilation of fence " + e.getName() + " is not supported"); + default -> throw new UnsupportedOperationException("Compilation of fence " + e.getName() + " is not supported"); }; return eventSequence( @@ -436,11 +430,11 @@ public List visitLKMMCmpXchg(LKMMCmpXchg e) { // equivalent and XOR harms performance substantially. CondJump branchOnCasCmpResult = newJump(expressions.makeNEQ(dummy, e.getExpectedValue()), casEnd); - Load load = newRMWLoadExclusiveWithMo(dummy, address, ARMv8.extractLoadMoFromLKMo(mo)); - Store store = newRMWStoreExclusiveWithMo(address, e.getStoreValue(), true, ARMv8.extractStoreMoFromLKMo(mo)); + Load load = AArch64.newRMWLoadExclusive(dummy, address, extractLoadMoFromLKMo(mo)); + Store store = AArch64.newRMWStoreExclusive(address, e.getStoreValue(), true, extractStoreMoFromLKMo(mo)); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(dummy, label); - Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? AArch64.DMB.newISHBarrier() : null; + Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? AArch64.newDmbIshBarrier() : null; return eventSequence( load, @@ -463,11 +457,11 @@ public List visitLKMMXchg(LKMMXchg e) { String mo = e.getMo(); Register dummy = e.getFunction().newRegister(resultRegister.getType()); - Load load = newRMWLoadExclusiveWithMo(dummy, address, ARMv8.extractLoadMoFromLKMo(mo)); - Store store = newRMWStoreExclusiveWithMo(address, e.getValue(), true, ARMv8.extractStoreMoFromLKMo(mo)); + Load load = AArch64.newRMWLoadExclusive(dummy, address, extractLoadMoFromLKMo(mo)); + Store store = AArch64.newRMWStoreExclusive(address, e.getValue(), true, extractStoreMoFromLKMo(mo)); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(dummy, label); - Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? AArch64.DMB.newISHBarrier() : null; + Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? AArch64.newDmbIshBarrier() : null; return eventSequence( load, @@ -487,8 +481,8 @@ public List visitLKMMOpNoReturn(LKMMOpNoReturn e) { Register dummy = e.getFunction().newRegister(e.getAccessType()); Expression storeValue = expressions.makeIntBinary(dummy, e.getOperator(), e.getOperand()); - Load load = newRMWLoadExclusive(dummy, address); - Store store = newRMWStoreExclusive(address, storeValue, true); + Load load = AArch64.newRMWLoadExclusive(dummy, address, ""); + Store store = AArch64.newRMWStoreExclusive(address, storeValue, true, ""); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(dummy, label); @@ -509,11 +503,11 @@ public List visitLKMMOpReturn(LKMMOpReturn e) { String mo = e.getMo(); Register dummy = e.getFunction().newRegister(resultRegister.getType()); - Load load = newRMWLoadExclusiveWithMo(dummy, address, ARMv8.extractLoadMoFromLKMo(mo)); - Store store = newRMWStoreExclusiveWithMo(address, dummy, true, ARMv8.extractStoreMoFromLKMo(mo)); + Load load = AArch64.newRMWLoadExclusive(dummy, address, extractLoadMoFromLKMo(mo)); + Store store = AArch64.newRMWStoreExclusive(address, dummy, true, extractStoreMoFromLKMo(mo)); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(dummy, label); - Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? AArch64.DMB.newISHBarrier() : null; + Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? AArch64.newDmbIshBarrier() : null; return eventSequence( load, @@ -535,12 +529,12 @@ public List visitLKMMFetchOp(LKMMFetchOp e) { String mo = e.getMo(); Register dummy = e.getFunction().newRegister(resultRegister.getType()); - Load load = newRMWLoadExclusiveWithMo(dummy, address, ARMv8.extractLoadMoFromLKMo(mo)); - Store store = newRMWStoreExclusiveWithMo(address, expressions.makeIntBinary(dummy, e.getOperator(), e.getOperand()), - true, ARMv8.extractStoreMoFromLKMo(mo)); + Expression value = expressions.makeIntBinary(dummy, e.getOperator(), e.getOperand()); + Load load = AArch64.newRMWLoadExclusive(dummy, address, extractLoadMoFromLKMo(mo)); + Store store = AArch64.newRMWStoreExclusive(address, value, true, extractStoreMoFromLKMo(mo)); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(dummy, label); - Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? AArch64.DMB.newISHBarrier() : null; + Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? AArch64.newDmbIshBarrier() : null; return eventSequence( load, @@ -565,8 +559,9 @@ public List visitLKMMAddUnless(LKMMAddUnless e) { Type type = resultRegister.getType(); Register regValue = e.getFunction().newRegister(type); - Load load = newRMWLoadExclusiveWithMo(regValue, address, ARMv8.extractLoadMoFromLKMo(mo)); - Store store = newRMWStoreExclusiveWithMo(address, expressions.makeAdd(regValue, e.getOperand()), true, ARMv8.extractStoreMoFromLKMo(mo)); + Expression value = expressions.makeAdd(regValue, e.getOperand()); + Load load = AArch64.newRMWLoadExclusive(regValue, address, extractLoadMoFromLKMo(mo)); + Store store = AArch64.newRMWStoreExclusive(address, value, true, extractStoreMoFromLKMo(mo)); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(regValue, label); @@ -575,7 +570,7 @@ public List visitLKMMAddUnless(LKMMAddUnless e) { Expression unless = e.getCmp(); Label cauEnd = newLabel("CAddU_end"); CondJump branchOnCauCmpResult = newJumpUnless(expressions.makeBooleanCast(dummy), cauEnd); - Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? AArch64.DMB.newISHBarrier() : null; + Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? AArch64.newDmbIshBarrier() : null; return eventSequence( load, @@ -602,13 +597,13 @@ public List visitLKMMOpAndTest(LKMMOpAndTest e) { Register dummy = e.getFunction().newRegister(e.getAccessType()); Expression testResult = expressions.makeNot(expressions.makeBooleanCast(dummy)); - Load load = newRMWLoadExclusiveWithMo(dummy, address, ARMv8.extractLoadMoFromLKMo(mo)); + Load load = AArch64.newRMWLoadExclusive(dummy, address, extractLoadMoFromLKMo(mo)); Local localOp = newLocal(dummy, expressions.makeIntBinary(dummy, e.getOperator(), e.getOperand())); - Store store = newRMWStoreExclusiveWithMo(address, dummy, true, ARMv8.extractStoreMoFromLKMo(mo)); + Store store = AArch64.newRMWStoreExclusive(address, dummy, true, extractStoreMoFromLKMo(mo)); Local testOp = newLocal(resultRegister, expressions.makeCast(testResult, resultRegister.getType())); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(dummy, label); - Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? AArch64.DMB.newISHBarrier() : null; + Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? AArch64.newDmbIshBarrier() : null; return eventSequence( load, @@ -631,9 +626,9 @@ public List visitLKMMLock(LKMMLock e) { // With this we miss a ctrl dependency, but this does not matter // because the load is an acquire one. return eventSequence( - newRMWLoadExclusiveWithMo(dummy, e.getLock(), ARMv8.MO_ACQ), + AArch64.newRMWLoadExclusive(dummy, e.getLock(), MO_ACQ), newAssume(expressions.makeEQ(dummy, zero)), - newRMWStoreExclusive(e.getLock(), one, true) + AArch64.newRMWStoreExclusive(e.getLock(), one, true, "") ); } @@ -641,8 +636,7 @@ public List visitLKMMLock(LKMMLock e) { public List visitLKMMUnlock(LKMMUnlock e) { Expression zero = expressions.makeZero((IntegerType)e.getAccessType()); return eventSequence( - newStoreWithMo(e.getAddress(), zero, ARMv8.MO_REL) + newStoreWithMo(e.getAddress(), zero, MO_REL) ); } - } \ No newline at end of file diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorC11.java b/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorC11.java index e573706340..54397972a5 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorC11.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorC11.java @@ -9,7 +9,6 @@ import com.dat3m.dartagnan.program.event.EventFactory; import com.dat3m.dartagnan.program.event.MemoryEvent; import com.dat3m.dartagnan.program.event.Tag; -import com.dat3m.dartagnan.program.event.Tag.C11; import com.dat3m.dartagnan.program.event.core.*; import com.dat3m.dartagnan.program.event.lang.catomic.*; import com.dat3m.dartagnan.program.event.lang.llvm.*; @@ -18,6 +17,7 @@ import java.util.List; import static com.dat3m.dartagnan.program.event.EventFactory.*; +import static com.dat3m.dartagnan.program.event.Tag.C11.*; import static com.google.common.base.Verify.verify; public class VisitorC11 extends VisitorBase { @@ -56,8 +56,8 @@ public List visitAtomicCmpXchg(AtomicCmpXchg e) { Local casCmpResult = newLocal(booleanResultRegister, expressions.makeEQ(regValue, regExpected)); CondJump branchOnCasCmpResult = newJumpUnless(booleanResultRegister, casFail); CondJump gotoCasEnd = newGoto(casEnd); - Load loadValue = newRMWLoadWithMo(regValue, address, Tag.C11.loadMO(mo)); - Store storeValue = newRMWStoreWithMo(loadValue, address, e.getStoreValue(), Tag.C11.storeMO(mo)); + Load loadValue = newRMWLoadWithMo(regValue, address, loadMO(mo)); + Store storeValue = newRMWStoreWithMo(loadValue, address, e.getStoreValue(), storeMO(mo)); return tagList(e, eventSequence( loadExpected, @@ -80,9 +80,9 @@ public List visitAtomicFetchOp(AtomicFetchOp e) { String mo = e.getMo(); Register dummyReg = e.getFunction().newRegister(resultRegister.getType()); - Load load = newRMWLoadWithMo(resultRegister, address, Tag.C11.loadMO(mo)); + Load load = newRMWLoadWithMo(resultRegister, address, loadMO(mo)); Local localOp = newLocal(dummyReg, expressions.makeIntBinary(resultRegister, e.getOperator(), e.getOperand())); - RMWStore store = newRMWStoreWithMo(load, address, dummyReg, Tag.C11.storeMO(mo)); + RMWStore store = newRMWStoreWithMo(load, address, dummyReg, storeMO(mo)); return tagList(e, eventSequence( load, @@ -94,21 +94,21 @@ public List visitAtomicFetchOp(AtomicFetchOp e) { @Override public List visitAtomicLoad(AtomicLoad e) { return tagList(e, eventSequence( - newLoadWithMo(e.getResultRegister(), e.getAddress(), Tag.C11.loadMO(e.getMo())) + newLoadWithMo(e.getResultRegister(), e.getAddress(), loadMO(e.getMo())) )); } @Override public List visitAtomicStore(AtomicStore e) { return tagList(e, eventSequence( - newStoreWithMo(e.getAddress(), e.getMemValue(), Tag.C11.storeMO(e.getMo())) + newStoreWithMo(e.getAddress(), e.getMemValue(), storeMO(e.getMo())) )); } @Override public List visitAtomicThreadFence(AtomicThreadFence e) { return tagList(e, eventSequence( - newFence(e.getMo()) + C11.newThreadFence(e.getMo()) )); } @@ -117,8 +117,8 @@ public List visitAtomicXchg(AtomicXchg e) { Expression address = e.getAddress(); String mo = e.getMo(); - Load load = newRMWLoadWithMo(e.getResultRegister(), address, Tag.C11.loadMO(mo)); - RMWStore store = newRMWStoreWithMo(load, address, e.getValue(), Tag.C11.storeMO(mo)); + Load load = newRMWLoadWithMo(e.getResultRegister(), address, loadMO(mo)); + RMWStore store = newRMWStoreWithMo(load, address, e.getValue(), storeMO(mo)); return tagList(e, eventSequence( load, @@ -129,7 +129,7 @@ public List visitAtomicXchg(AtomicXchg e) { @Override public List visitControlBarrier(ControlBarrier e) { Event barrier = EventFactory.newControlBarrier(e.getName(), e.getInstanceId(), e.getExecScope()); - barrier.addTags(C11.MO_ACQUIRE_RELEASE); + barrier.addTags(MO_ACQUIRE_RELEASE); return tagList(e, eventSequence(barrier)); } @@ -140,14 +140,14 @@ public List visitControlBarrier(ControlBarrier e) { @Override public List visitLlvmLoad(LlvmLoad e) { return tagList(eventSequence( - newLoadWithMo(e.getResultRegister(), e.getAddress(), Tag.C11.loadMO(e.getMo())) + newLoadWithMo(e.getResultRegister(), e.getAddress(), loadMO(e.getMo())) )); } @Override public List visitLlvmStore(LlvmStore e) { return tagList(eventSequence( - newStoreWithMo(e.getAddress(), e.getMemValue(), Tag.C11.storeMO(e.getMo())) + newStoreWithMo(e.getAddress(), e.getMemValue(), storeMO(e.getMo())) )); } @@ -157,8 +157,8 @@ public List visitLlvmXchg(LlvmXchg e) { Expression address = e.getAddress(); String mo = e.getMo(); - Load load = newRMWLoadExclusiveWithMo(resultRegister, address, Tag.C11.loadMO(mo)); - Store store = newRMWStoreExclusiveWithMo(address, e.getValue(), true, Tag.C11.storeMO(mo)); + Load load = newRMWLoadExclusiveWithMo(resultRegister, address, loadMO(mo)); + Store store = newRMWStoreExclusiveWithMo(address, e.getValue(), true, false, storeMO(mo)); return tagList(eventSequence( load, @@ -175,8 +175,8 @@ public List visitLlvmRMW(LlvmRMW e) { Register dummyReg = e.getFunction().newRegister(resultRegister.getType()); Local localOp = newLocal(dummyReg, expressions.makeIntBinary(resultRegister, e.getOperator(), e.getOperand())); - Load load = newRMWLoadExclusiveWithMo(resultRegister, address, Tag.C11.loadMO(mo)); - Store store = newRMWStoreExclusiveWithMo(address, dummyReg, true, Tag.C11.storeMO(mo)); + Load load = newRMWLoadExclusiveWithMo(resultRegister, address, loadMO(mo)); + Store store = newRMWStoreExclusiveWithMo(address, dummyReg, true, false, storeMO(mo)); return tagList(eventSequence( load, @@ -194,8 +194,8 @@ protected List newLlvmCmpXchg(Register oldValue, Register success, Expres Label casEnd = newLabel("CAS_end"); CondJump branchOnCasCmpResult = newJumpUnless(success, casEnd); - Load load = newRMWLoadExclusiveWithMo(oldValue, address, Tag.C11.loadMO(mo)); - Store store = newRMWStoreExclusiveWithMo(address, newValue, strong, Tag.C11.storeMO(mo)); + Load load = newRMWLoadExclusiveWithMo(oldValue, address, loadMO(mo)); + Store store = newRMWStoreExclusiveWithMo(address, newValue, strong, false, storeMO(mo)); return tagList(eventSequence( load, @@ -211,7 +211,7 @@ protected List newLlvmCmpXchg(Register oldValue, Register success, Expres @Override public List visitLlvmFence(LlvmFence e) { return tagList(eventSequence( - newFence(e.getMo()) + C11.newThreadFence(e.getMo()) )); } @@ -238,8 +238,8 @@ private void tagEvent(Event originalEvent, Event e) { } if (e instanceof MemoryEvent) { MemoryOrder mo = e.getMetadata(MemoryOrder.class); - boolean canRace = mo == null || mo.value().equals(C11.NONATOMIC); - e.addTags(canRace ? C11.NONATOMIC : C11.ATOMIC); + boolean canRace = mo == null || mo.value().equals(NONATOMIC); + e.addTags(canRace ? NONATOMIC : ATOMIC); } } } \ No newline at end of file diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorIMM.java b/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorIMM.java index b3f461d916..e537c870bd 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorIMM.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorIMM.java @@ -6,14 +6,11 @@ import com.dat3m.dartagnan.program.Register; import com.dat3m.dartagnan.program.event.Event; import com.dat3m.dartagnan.program.event.Tag; -import com.dat3m.dartagnan.program.event.Tag.C11; -import com.dat3m.dartagnan.program.event.Tag.IMM; import com.dat3m.dartagnan.program.event.core.*; import com.dat3m.dartagnan.program.event.lang.catomic.*; import com.dat3m.dartagnan.program.event.lang.llvm.*; import com.dat3m.dartagnan.program.event.metadata.MemoryOrder; -import java.util.Collections; import java.util.List; import static com.dat3m.dartagnan.program.event.EventFactory.*; @@ -27,9 +24,9 @@ class VisitorIMM extends VisitorBase { public List visitLoad(Load e) { // FIXME: It is weird to compile a core-level load by transforming its tagging. final MemoryOrder mo = e.getMetadata(MemoryOrder.class); - final boolean isNonAtomic = (mo == null || mo.value().equals(C11.NONATOMIC)); + final boolean isNonAtomic = (mo == null || mo.value().equals(Tag.C11.NONATOMIC)); return eventSequence( - newLoadWithMo(e.getResultRegister(), e.getAddress(), isNonAtomic ? C11.MO_RELAXED : mo.value()) + newLoadWithMo(e.getResultRegister(), e.getAddress(), isNonAtomic ? Tag.C11.MO_RELAXED : mo.value()) ); } @@ -37,9 +34,9 @@ public List visitLoad(Load e) { public List visitStore(Store e) { // FIXME: It is weird to compile a core-level load by transforming its tagging. final MemoryOrder mo = e.getMetadata(MemoryOrder.class); - final boolean isNonAtomic = (mo == null || mo.value().equals(C11.NONATOMIC)); + final boolean isNonAtomic = (mo == null || mo.value().equals(Tag.C11.NONATOMIC)); return eventSequence( - newStoreWithMo(e.getAddress(), e.getMemValue(), isNonAtomic ? C11.MO_RELAXED : mo.value()) + newStoreWithMo(e.getAddress(), e.getMemValue(), isNonAtomic ? Tag.C11.MO_RELAXED : mo.value()) ); } @@ -52,8 +49,8 @@ public List visitAtomicCmpXchg(AtomicCmpXchg e) { Register resultRegister = e.getResultRegister(); Expression address = e.getAddress(); String mo = e.getMo(); - Event optionalFenceLoad = mo.equals(Tag.C11.MO_SC) ? newFence(Tag.C11.MO_SC) : null; - Event optionalFenceStore = mo.equals(Tag.C11.MO_SC) ? newFence(Tag.C11.MO_SC) : null; + Event optionalFenceLoad = mo.equals(Tag.C11.MO_SC) ? C11.newThreadFenceSequentiallyConsistent() : null; + Event optionalFenceStore = mo.equals(Tag.C11.MO_SC) ? C11.newThreadFenceSequentiallyConsistent() : null; Expression expectedAddr = e.getAddressOfExpected(); Type type = resultRegister.getType(); Register booleanResultRegister = type instanceof BooleanType ? resultRegister : @@ -112,7 +109,7 @@ public List visitAtomicFetchOp(AtomicFetchOp e) { @Override public List visitAtomicLoad(AtomicLoad e) { String mo = e.getMo(); - Event optionalFence = mo.equals(Tag.C11.MO_SC) ? newFence(Tag.C11.MO_SC) : null; + Event optionalFence = mo.equals(Tag.C11.MO_SC) ? C11.newThreadFenceSequentiallyConsistent() : null; return eventSequence( optionalFence, newLoadWithMo(e.getResultRegister(), e.getAddress(), extractLoadMo(mo)) @@ -122,7 +119,7 @@ public List visitAtomicLoad(AtomicLoad e) { @Override public List visitAtomicStore(AtomicStore e) { String mo = e.getMo(); - Event optionalFence = mo.equals(Tag.C11.MO_SC) ? newFence(Tag.C11.MO_SC) : null; + Event optionalFence = mo.equals(Tag.C11.MO_SC) ? C11.newThreadFenceSequentiallyConsistent() : null; return eventSequence( optionalFence, newStoreWithMo(e.getAddress(), e.getMemValue(), extractStoreMo(mo)) @@ -131,15 +128,17 @@ public List visitAtomicStore(AtomicStore e) { @Override public List visitAtomicThreadFence(AtomicThreadFence e) { - return Collections.singletonList(newFence(e.getMo())); + return eventSequence( + C11.newThreadFence(e.getMo()) + ); } @Override public List visitAtomicXchg(AtomicXchg e) { Expression address = e.getAddress(); String mo = e.getMo(); - Event optionalFenceLoad = mo.equals(Tag.C11.MO_SC) ? newFence(Tag.C11.MO_SC) : null; - Event optionalFenceStore = mo.equals(Tag.C11.MO_SC) ? newFence(Tag.C11.MO_SC) : null; + Event optionalFenceLoad = mo.equals(Tag.C11.MO_SC) ? C11.newThreadFenceSequentiallyConsistent() : null; + Event optionalFenceStore = mo.equals(Tag.C11.MO_SC) ? C11.newThreadFenceSequentiallyConsistent() : null; Load load = newRMWLoadWithMo(e.getResultRegister(), address, mo); @@ -158,14 +157,14 @@ public List visitAtomicXchg(AtomicXchg e) { @Override public List visitLlvmLoad(LlvmLoad e) { return eventSequence( - newLoadWithMo(e.getResultRegister(), e.getAddress(), IMM.extractLoadMo(e.getMo())) + newLoadWithMo(e.getResultRegister(), e.getAddress(), extractLoadMo(e.getMo())) ); } @Override public List visitLlvmStore(LlvmStore e) { return eventSequence( - newStoreWithMo(e.getAddress(), e.getMemValue(), IMM.extractStoreMo(e.getMo())) + newStoreWithMo(e.getAddress(), e.getMemValue(), extractStoreMo(e.getMo())) ); } @@ -175,8 +174,8 @@ public List visitLlvmXchg(LlvmXchg e) { Expression address = e.getAddress(); String mo = e.getMo(); - Load load = newRMWLoadExclusiveWithMo(resultRegister, address, IMM.extractLoadMo(mo)); - Store store = newRMWStoreExclusiveWithMo(address, e.getValue(), true, IMM.extractStoreMo(mo)); + Load load = newRMWLoadExclusiveWithMo(resultRegister, address, extractLoadMo(mo)); + Store store = newRMWStoreExclusiveWithMo(address, e.getValue(), true, false, extractStoreMo(mo)); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(resultRegister, label); @@ -197,8 +196,8 @@ public List visitLlvmRMW(LlvmRMW e) { Register dummyReg = e.getFunction().newRegister(resultRegister.getType()); Local localOp = newLocal(dummyReg, expressions.makeIntBinary(resultRegister, e.getOperator(), e.getOperand())); - Load load = newRMWLoadExclusiveWithMo(resultRegister, address, IMM.extractLoadMo(mo)); - Store store = newRMWStoreExclusiveWithMo(address, dummyReg, true, IMM.extractStoreMo(mo)); + Load load = newRMWLoadExclusiveWithMo(resultRegister, address, extractLoadMo(mo)); + Store store = newRMWStoreExclusiveWithMo(address, dummyReg, true, false, extractStoreMo(mo)); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(resultRegister, label); @@ -220,8 +219,8 @@ protected List newLlvmCmpXchg(Register oldValue, Register success, Expres Label casEnd = newLabel("CAS_end"); CondJump branchOnCasCmpResult = newJumpUnless(success, casEnd); - Load load = newRMWLoadExclusiveWithMo(oldValue, address, IMM.extractLoadMo(mo)); - Store store = newRMWStoreExclusiveWithMo(address, newValue, strong, IMM.extractStoreMo(mo)); + Load load = newRMWLoadExclusiveWithMo(oldValue, address, extractLoadMo(mo)); + Store store = newRMWStoreExclusiveWithMo(address, newValue, strong, false, extractStoreMo(mo)); return eventSequence( load, @@ -237,7 +236,7 @@ protected List newLlvmCmpXchg(Register oldValue, Register success, Expres @Override public List visitLlvmFence(LlvmFence e) { return eventSequence( - newFence(e.getMo()) + C11.newThreadFence(e.getMo()) ); } diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorLKMM.java b/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorLKMM.java index 256d110787..8e11b555c2 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorLKMM.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorLKMM.java @@ -149,7 +149,7 @@ public List visitLKMMOpReturn(LKMMOpReturn e) { @Override public List visitLKMMFence(LKMMFence e) { return eventSequence( - newFence(e.getName()) + Linux.newFence(e.getName()) ); } diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorPTX.java b/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorPTX.java index 162118d376..9bd04a0109 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorPTX.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorPTX.java @@ -23,11 +23,11 @@ public List visitPtxAtomOp(PTXAtomOp e) { String mo = e.getMo(); Expression address = e.getAddress(); Register dummy = e.getFunction().newRegister(resultRegister.getType()); + Expression value = expressions.makeIntBinary(dummy, e.getOperator(), e.getOperand()); Load load = newRMWLoadWithMo(dummy, address, Tag.PTX.loadMO(mo)); - RMWStore store = newRMWStoreWithMo(load, address, - expressions.makeIntBinary(dummy, e.getOperator(), e.getOperand()), Tag.PTX.storeMO(mo)); - this.propagateTags(e, load); - this.propagateTags(e, store); + RMWStore store = newRMWStoreWithMo(load, address, value, Tag.PTX.storeMO(mo)); + propagateTags(e, load); + propagateTags(e, store); return eventSequence( load, store, @@ -52,11 +52,12 @@ public List visitPtxAtomCAS(PTXAtomCAS e) { newValue, resultRegister); Load load = newRMWLoadWithMo(resultRegister, address, Tag.PTX.loadMO(mo)); RMWStore store = newRMWStoreWithMo(load, address, storeValue, Tag.PTX.storeMO(mo)); - this.propagateTags(e, load); - this.propagateTags(e, store); + propagateTags(e, load); + propagateTags(e, store); return eventSequence( load, - store); + store + ); } // PTX Exch semantics @@ -68,8 +69,8 @@ public List visitPtxAtomExch(PTXAtomExch e) { Register dummy = e.getFunction().newRegister(resultRegister.getType()); Load load = newRMWLoadWithMo(dummy, address, Tag.PTX.loadMO(mo)); RMWStore store = newRMWStoreWithMo(load, address, e.getValue(), Tag.PTX.storeMO(mo)); - this.propagateTags(e, load); - this.propagateTags(e, store); + propagateTags(e, load); + propagateTags(e, store); return eventSequence( load, store, @@ -81,11 +82,11 @@ public List visitPtxAtomExch(PTXAtomExch e) { public List visitPtxRedOp(PTXRedOp e) { Expression address = e.getAddress(); Register dummy = e.getFunction().newRegister(e.getAccessType()); + Expression value = expressions.makeIntBinary(dummy, e.getOperator(), e.getOperand()); Load load = newRMWLoadWithMo(dummy, address, Tag.PTX.loadMO(e.getMo())); - RMWStore store = newRMWStoreWithMo(load, address, - expressions.makeIntBinary(dummy, e.getOperator(), e.getOperand()), Tag.PTX.storeMO(e.getMo())); - this.propagateTags(e, load); - this.propagateTags(e, store); + RMWStore store = newRMWStoreWithMo(load, address, value, Tag.PTX.storeMO(e.getMo())); + propagateTags(e, load); + propagateTags(e, store); return eventSequence( load, store diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorPower.java b/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorPower.java index e9fc54d97e..e5fc0a607f 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorPower.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorPower.java @@ -17,7 +17,6 @@ import java.util.List; import static com.dat3m.dartagnan.program.event.EventFactory.*; -import static com.dat3m.dartagnan.program.processing.compilation.VisitorPower.PowerScheme.LEADING_SYNC; import static com.google.common.base.Verify.verify; public class VisitorPower extends VisitorBase { @@ -44,7 +43,7 @@ protected VisitorPower(boolean useRC11Scheme, PowerScheme cToPowerScheme) { @Override public List visitStoreExclusive(StoreExclusive e) { - RMWStoreExclusive store = newRMWStoreExclusiveWithMo(e.getAddress(), e.getMemValue(), true, e.getMo()); + Store store = newRMWStoreExclusiveWithMo(e.getAddress(), e.getMemValue(), true, false, e.getMo()); return eventSequence( store, @@ -60,36 +59,21 @@ public List visitStoreExclusive(StoreExclusive e) { public List visitLlvmLoad(LlvmLoad e) { Register resultRegister = e.getResultRegister(); - Event optionalBarrierBefore = null; + Event optionalBarrierBefore = e.getMo().equals(C11.MO_SC) && leadingSync() ? Power.newSyncBarrier() : null; Load load = newLoad(resultRegister, e.getAddress()); - Label optionalLabel = null; - CondJump optionalFakeCtrlDep = null; - Event optionalBarrierAfter = null; - - switch (e.getMo()) { - case C11.MO_SC: - if (cToPowerScheme.equals(LEADING_SYNC)) { - optionalBarrierBefore = Power.newSyncBarrier(); - optionalLabel = newLabel("FakeDep"); - optionalFakeCtrlDep = newFakeCtrlDep(resultRegister, optionalLabel); - optionalBarrierAfter = Power.newISyncBarrier(); - } else { - optionalBarrierAfter = Power.newSyncBarrier(); - } - break; - case C11.MO_ACQUIRE: - optionalLabel = newLabel("FakeDep"); - optionalFakeCtrlDep = newFakeCtrlDep(resultRegister, optionalLabel); - optionalBarrierAfter = Power.newISyncBarrier(); - break; - case C11.MO_RELAXED: - if (useRC11Scheme) { - optionalLabel = newLabel("FakeDep"); - optionalFakeCtrlDep = newFakeCtrlDep(resultRegister, optionalLabel); - } - break; - } - + final boolean doCtrlDependency = switch (e.getMo()) { + case C11.MO_SC -> leadingSync(); + case C11.MO_ACQUIRE -> true; + case C11.MO_RELAXED -> useRC11Scheme; + default -> false; + }; + Label optionalLabel = doCtrlDependency ? newLabel("FakeDep") : null; + CondJump optionalFakeCtrlDep = doCtrlDependency ? newFakeCtrlDep(resultRegister, optionalLabel) : null; + Event optionalBarrierAfter = switch (e.getMo()) { + case C11.MO_SC -> leadingSync() ? Power.newISyncBarrier() : Power.newSyncBarrier(); + case C11.MO_ACQUIRE -> Power.newISyncBarrier(); + default -> null; + }; return eventSequence( optionalBarrierBefore, load, @@ -100,24 +84,13 @@ public List visitLlvmLoad(LlvmLoad e) { @Override public List visitLlvmStore(LlvmStore e) { - Event optionalBarrierBefore = null; + Event optionalBarrierBefore = switch (e.getMo()) { + case C11.MO_SC -> leadingSync() ? Power.newSyncBarrier() : Power.newLwSyncBarrier(); + case C11.MO_RELEASE -> Power.newLwSyncBarrier(); + default -> null; + }; Store store = newStore(e.getAddress(), e.getMemValue()); - Event optionalBarrierAfter = null; - - switch (e.getMo()) { - case C11.MO_SC: - if (cToPowerScheme.equals(LEADING_SYNC)) { - optionalBarrierBefore = Power.newSyncBarrier(); - } else { - optionalBarrierBefore = Power.newLwSyncBarrier(); - optionalBarrierAfter = Power.newSyncBarrier(); - } - break; - case C11.MO_RELEASE: - optionalBarrierBefore = Power.newLwSyncBarrier(); - break; - } - + Event optionalBarrierAfter = e.getMo().equals(C11.MO_SC) && !leadingSync() ? Power.newSyncBarrier() : null; return eventSequence( optionalBarrierBefore, store, @@ -128,101 +101,46 @@ public List visitLlvmStore(LlvmStore e) { public List visitLlvmXchg(LlvmXchg e) { Register resultRegister = e.getResultRegister(); Expression address = e.getAddress(); - String mo = e.getMo(); // Power does not have mo tags, thus we use null - Load load = newRMWLoadExclusive(resultRegister, address); + Load load = Power.newRMWLoadExclusive(resultRegister, address); Store store = Power.newRMWStoreConditional(address, e.getValue(), true); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(resultRegister, label); - Event optionalBarrierBefore = null; - Event optionalBarrierAfter = null; - - switch (mo) { - case C11.MO_SC: - if (cToPowerScheme.equals(LEADING_SYNC)) { - optionalBarrierBefore = Power.newSyncBarrier(); - optionalBarrierAfter = Power.newISyncBarrier(); - } else { - optionalBarrierBefore = Power.newLwSyncBarrier(); - optionalBarrierAfter = Power.newSyncBarrier(); - } - break; - case C11.MO_ACQUIRE: - optionalBarrierAfter = Power.newISyncBarrier(); - break; - case C11.MO_RELEASE: - optionalBarrierBefore = Power.newLwSyncBarrier(); - break; - case C11.MO_ACQUIRE_RELEASE: - optionalBarrierBefore = Power.newLwSyncBarrier(); - optionalBarrierAfter = Power.newISyncBarrier(); - break; - } - return eventSequence( - optionalBarrierBefore, + optionalBarrierBefore(e.getMo()), load, fakeCtrlDep, label, store, - optionalBarrierAfter); + optionalBarrierAfter(e.getMo()) + ); } @Override public List visitLlvmRMW(LlvmRMW e) { Register resultRegister = e.getResultRegister(); Expression address = e.getAddress(); - String mo = e.getMo(); Register dummyReg = e.getFunction().newRegister(resultRegister.getType()); Local localOp = newLocal(dummyReg, expressions.makeIntBinary(resultRegister, e.getOperator(), e.getOperand())); // Power does not have mo tags, thus we use null - Load load = newRMWLoadExclusive(resultRegister, address); + Load load = Power.newRMWLoadExclusive(resultRegister, address); Store store = Power.newRMWStoreConditional(address, dummyReg, true); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(resultRegister, label); - Event optionalBarrierBefore = null; - // Academics papers (e.g. https://plv.mpi-sws.org/imm/paper.pdf) say an isync - // barrier is enough - // However, power compilers in godbolt.org use a lwsync. - // We stick to the literature to potentially find bugs in what researchers - // claim. - Event optionalBarrierAfter = null; - - switch (mo) { - case C11.MO_SC: - if (cToPowerScheme.equals(LEADING_SYNC)) { - optionalBarrierBefore = Power.newSyncBarrier(); - optionalBarrierAfter = Power.newISyncBarrier(); - } else { - optionalBarrierBefore = Power.newLwSyncBarrier(); - optionalBarrierAfter = Power.newSyncBarrier(); - } - break; - case C11.MO_ACQUIRE: - optionalBarrierAfter = Power.newISyncBarrier(); - break; - case C11.MO_RELEASE: - optionalBarrierBefore = Power.newLwSyncBarrier(); - break; - case C11.MO_ACQUIRE_RELEASE: - optionalBarrierBefore = Power.newLwSyncBarrier(); - optionalBarrierAfter = Power.newISyncBarrier(); - break; - } - return eventSequence( - optionalBarrierBefore, + optionalBarrierBefore(e.getMo()), load, fakeCtrlDep, label, localOp, store, - optionalBarrierAfter); + optionalBarrierAfter(e.getMo()) + ); } @Override @@ -234,36 +152,11 @@ protected List newLlvmCmpXchg(Register oldValue, Register success, Expres Label casEnd = newLabel("CAS_end"); CondJump branchOnCasCmpResult = newJumpUnless(success, casEnd); - Load load = newRMWLoadExclusive(oldValue, address); + Load load = Power.newRMWLoadExclusive(oldValue, address); Store store = Power.newRMWStoreConditional(address, newValue, strong); - Event optionalBarrierBefore = null; - Event optionalBarrierAfter = null; - - switch (mo) { - case C11.MO_SC: - if (cToPowerScheme.equals(LEADING_SYNC)) { - optionalBarrierBefore = Power.newSyncBarrier(); - optionalBarrierAfter = Power.newISyncBarrier(); - } else { - optionalBarrierBefore = Power.newLwSyncBarrier(); - optionalBarrierAfter = Power.newSyncBarrier(); - } - break; - case C11.MO_ACQUIRE: - optionalBarrierAfter = Power.newISyncBarrier(); - break; - case C11.MO_RELEASE: - optionalBarrierBefore = Power.newLwSyncBarrier(); - break; - case C11.MO_ACQUIRE_RELEASE: - optionalBarrierBefore = Power.newLwSyncBarrier(); - optionalBarrierAfter = Power.newISyncBarrier(); - break; - } - return eventSequence( - optionalBarrierBefore, + optionalBarrierBefore(mo), load, casCmpResult, branchOnCasCmpResult, @@ -271,15 +164,18 @@ protected List newLlvmCmpXchg(Register oldValue, Register success, Expres strong ? null : newExecutionStatus(success, store), strong ? null : newLocal(success, expressions.makeNot(success)), casEnd, - optionalBarrierAfter); + optionalBarrierAfter(mo) + ); } @Override public List visitLlvmFence(LlvmFence e) { - Event fence = e.getMo().equals(Tag.C11.MO_SC) ? Power.newSyncBarrier() : Power.newLwSyncBarrier(); + String mo = e.getMo(); + Event fence = mo.equals(Tag.C11.MO_SC) ? Power.newSyncBarrier() : Power.newLwSyncBarrier(); return eventSequence( - fence); + fence + ); } // ============================================================================================= @@ -291,7 +187,6 @@ public List visitAtomicCmpXchg(AtomicCmpXchg e) { Register resultRegister = e.getResultRegister(); Expression address = e.getAddress(); Expression value = e.getStoreValue(); - String mo = e.getMo(); Expression expectedAddr = e.getAddressOfExpected(); Type type = resultRegister.getType(); Register booleanResultRegister = type instanceof BooleanType ? resultRegister : @@ -308,7 +203,7 @@ public List visitAtomicCmpXchg(AtomicCmpXchg e) { CondJump branchOnCasCmpResult = newJumpUnless(booleanResultRegister, casFail); CondJump gotoCasEnd = newGoto(casEnd); // Power does not have mo tags, thus we use the empty string - Load loadValue = newRMWLoadExclusive(regValue, address); + Load loadValue = Power.newRMWLoadExclusive(regValue, address); Store storeValue = Power.newRMWStoreConditional(address, value, e.isStrong()); ExecutionStatus optionalExecStatus = null; Local optionalUpdateCasCmpResult = null; @@ -317,31 +212,8 @@ public List visitAtomicCmpXchg(AtomicCmpXchg e) { optionalExecStatus = newExecutionStatus(statusReg, storeValue); optionalUpdateCasCmpResult = newLocal(booleanResultRegister, expressions.makeNot(statusReg)); } - Event optionalBarrierBefore = null; - Event optionalBarrierAfter = null; - switch (mo) { - case C11.MO_SC: - if (cToPowerScheme.equals(LEADING_SYNC)) { - optionalBarrierBefore = Power.newSyncBarrier(); - optionalBarrierAfter = Power.newISyncBarrier(); - } else { - optionalBarrierBefore = Power.newLwSyncBarrier(); - optionalBarrierAfter = Power.newSyncBarrier(); - } - break; - case C11.MO_ACQUIRE: - optionalBarrierAfter = Power.newISyncBarrier(); - break; - case C11.MO_RELEASE: - optionalBarrierBefore = Power.newLwSyncBarrier(); - break; - case C11.MO_ACQUIRE_RELEASE: - optionalBarrierBefore = Power.newLwSyncBarrier(); - optionalBarrierAfter = Power.newISyncBarrier(); - break; - } return eventSequence( - optionalBarrierBefore, + optionalBarrierBefore(e.getMo()), loadExpected, loadValue, casCmpResult, @@ -353,7 +225,7 @@ public List visitAtomicCmpXchg(AtomicCmpXchg e) { casFail, storeExpected, casEnd, - optionalBarrierAfter, + optionalBarrierAfter(e.getMo()), castResult ); } @@ -362,52 +234,24 @@ public List visitAtomicCmpXchg(AtomicCmpXchg e) { public List visitAtomicFetchOp(AtomicFetchOp e) { Register resultRegister = e.getResultRegister(); Expression address = e.getAddress(); - String mo = e.getMo(); Register dummyReg = e.getFunction().newRegister(resultRegister.getType()); Local localOp = newLocal(dummyReg, expressions.makeIntBinary(resultRegister, e.getOperator(), e.getOperand())); - Load load = newRMWLoadExclusive(resultRegister, address); + Load load = Power.newRMWLoadExclusive(resultRegister, address); Store store = Power.newRMWStoreConditional(address, dummyReg, true); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(resultRegister, label); - Event optionalBarrierBefore = null; - // Academics papers (e.g. https://plv.mpi-sws.org/imm/paper.pdf) say an isync barrier is enough - // However, power compilers in godbolt.org use a lwsync. - // We stick to the literature to potentially find bugs in what researchers claim. - Event optionalBarrierAfter = null; - - switch (mo) { - case C11.MO_SC: - if (cToPowerScheme.equals(LEADING_SYNC)) { - optionalBarrierBefore = Power.newSyncBarrier(); - optionalBarrierAfter = Power.newISyncBarrier(); - } else { - optionalBarrierBefore = Power.newLwSyncBarrier(); - optionalBarrierAfter = Power.newSyncBarrier(); - } - break; - case C11.MO_ACQUIRE: - optionalBarrierAfter = Power.newISyncBarrier(); - break; - case C11.MO_RELEASE: - optionalBarrierBefore = Power.newLwSyncBarrier(); - break; - case C11.MO_ACQUIRE_RELEASE: - optionalBarrierBefore = Power.newLwSyncBarrier(); - optionalBarrierAfter = Power.newISyncBarrier(); - break; - } return eventSequence( - optionalBarrierBefore, + optionalBarrierBefore(e.getMo()), load, fakeCtrlDep, label, localOp, store, - optionalBarrierAfter + optionalBarrierAfter(e.getMo()) ); } @@ -417,35 +261,21 @@ public List visitAtomicLoad(AtomicLoad e) { Expression address = e.getAddress(); String mo = e.getMo(); - Event optionalBarrierBefore = null; + Event optionalBarrierBefore = mo.equals(C11.MO_SC) && leadingSync() ? Power.newSyncBarrier() : null; Load load = newLoad(resultRegister, address); - Label optionalLabel = null; - CondJump optionalFakeCtrlDep = null; - Event optionalBarrierAfter = null; - - switch (mo) { - case C11.MO_SC: - if (cToPowerScheme.equals(LEADING_SYNC)) { - optionalBarrierBefore = Power.newSyncBarrier(); - optionalLabel = newLabel("FakeDep"); - optionalFakeCtrlDep = newFakeCtrlDep(resultRegister, optionalLabel); - optionalBarrierAfter = Power.newISyncBarrier(); - } else { - optionalBarrierAfter = Power.newSyncBarrier(); - } - break; - case C11.MO_ACQUIRE: - optionalLabel = newLabel("FakeDep"); - optionalFakeCtrlDep = newFakeCtrlDep(resultRegister, optionalLabel); - optionalBarrierAfter = Power.newISyncBarrier(); - break; - case C11.MO_RELAXED: - if (useRC11Scheme) { - optionalLabel = newLabel("FakeDep"); - optionalFakeCtrlDep = newFakeCtrlDep(resultRegister, optionalLabel); - } - break; - } + final boolean doControlDependency = switch (mo) { + case C11.MO_SC -> leadingSync(); + case C11.MO_ACQUIRE -> true; + case C11.MO_RELAXED -> useRC11Scheme; + default -> false; + }; + Label optionalLabel = doControlDependency ? newLabel("FakeDep") : null; + CondJump optionalFakeCtrlDep = doControlDependency ? newFakeCtrlDep(resultRegister, optionalLabel) : null; + Event optionalBarrierAfter = switch (mo) { + case C11.MO_SC -> leadingSync() ? Power.newISyncBarrier() : Power.newSyncBarrier(); + case C11.MO_ACQUIRE -> Power.newISyncBarrier(); + default -> null; + }; return eventSequence( optionalBarrierBefore, @@ -460,25 +290,14 @@ public List visitAtomicLoad(AtomicLoad e) { public List visitAtomicStore(AtomicStore e) { Expression value = e.getMemValue(); Expression address = e.getAddress(); - String mo = e.getMo(); - Event optionalBarrierBefore = null; + Event optionalBarrierBefore = switch (e.getMo()) { + case C11.MO_SC -> leadingSync() ? Power.newSyncBarrier() : Power.newLwSyncBarrier(); + case C11.MO_RELEASE -> Power.newLwSyncBarrier(); + default -> null; + }; Store store = newStore(address, value); - Event optionalBarrierAfter = null; - - switch (mo) { - case C11.MO_SC: - if (cToPowerScheme.equals(LEADING_SYNC)) { - optionalBarrierBefore = Power.newSyncBarrier(); - } else { - optionalBarrierBefore = Power.newLwSyncBarrier(); - optionalBarrierAfter = Power.newSyncBarrier(); - } - break; - case C11.MO_RELEASE: - optionalBarrierBefore = Power.newLwSyncBarrier(); - break; - } + Event optionalBarrierAfter = e.getMo().equals(C11.MO_SC) && !leadingSync() ? Power.newSyncBarrier() : null; return eventSequence( optionalBarrierBefore, @@ -501,48 +320,41 @@ public List visitAtomicThreadFence(AtomicThreadFence e) { public List visitAtomicXchg(AtomicXchg e) { Register resultRegister = e.getResultRegister(); Expression address = e.getAddress(); - String mo = e.getMo(); - Load load = newRMWLoadExclusive(resultRegister, address); + Load load = Power.newRMWLoadExclusive(resultRegister, address); Store store = Power.newRMWStoreConditional(address, e.getValue(), true); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(resultRegister, label); - Event optionalBarrierBefore = null; - Event optionalBarrierAfter = null; - - switch (mo) { - case C11.MO_SC: - if (cToPowerScheme.equals(LEADING_SYNC)) { - optionalBarrierBefore = Power.newSyncBarrier(); - optionalBarrierAfter = Power.newISyncBarrier(); - } else { - optionalBarrierBefore = Power.newLwSyncBarrier(); - optionalBarrierAfter = Power.newSyncBarrier(); - } - break; - case C11.MO_ACQUIRE: - optionalBarrierAfter = Power.newISyncBarrier(); - break; - case C11.MO_RELEASE: - optionalBarrierBefore = Power.newLwSyncBarrier(); - break; - case C11.MO_ACQUIRE_RELEASE: - optionalBarrierBefore = Power.newLwSyncBarrier(); - optionalBarrierAfter = Power.newISyncBarrier(); - break; - } - return eventSequence( - optionalBarrierBefore, + optionalBarrierBefore(e.getMo()), load, fakeCtrlDep, label, store, - optionalBarrierAfter + optionalBarrierAfter(e.getMo()) ); } + private Event optionalBarrierBefore(String mo) { + return switch (mo) { + case C11.MO_SC -> leadingSync() ? Power.newISyncBarrier() : Power.newSyncBarrier(); + case C11.MO_ACQUIRE, C11.MO_ACQUIRE_RELEASE -> Power.newISyncBarrier(); + default -> null; + }; + } + + private Event optionalBarrierAfter(String mo) { + // Academics papers (e.g. https://plv.mpi-sws.org/imm/paper.pdf) say an isync barrier is enough + // However, power compilers in godbolt.org use a lwsync. + // We stick to the literature to potentially find bugs in what researchers claim. + return switch (mo) { + case C11.MO_SC -> leadingSync() ? Power.newISyncBarrier() : Power.newSyncBarrier(); + case C11.MO_ACQUIRE, C11.MO_ACQUIRE_RELEASE -> Power.newISyncBarrier(); + default -> null; + }; + } + // ============================================================================================= // =========================================== LKMM ============================================ // ============================================================================================= @@ -645,30 +457,24 @@ public List visitLKMMFence(LKMMFence e) { public List visitLKMMCmpXchg(LKMMCmpXchg e) { Register resultRegister = e.getResultRegister(); Expression address = e.getAddress(); - String mo = e.getMo(); Register dummy = e.getFunction().newRegister(e.getResultRegister().getType()); Label casEnd = newLabel("CAS_end"); CondJump branchOnCasCmpResult = newJump(expressions.makeNEQ(dummy, e.getExpectedValue()), casEnd); - Load load = newRMWLoadExclusive(dummy, address); + Load load = Power.newRMWLoadExclusive(dummy, address); Store store = Power.newRMWStoreConditional(address, e.getStoreValue(), true); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(dummy, label); - Event optionalMemoryBarrierBefore = mo.equals(Tag.Linux.MO_MB) ? Power.newSyncBarrier() - : mo.equals(Tag.Linux.MO_RELEASE) ? Power.newLwSyncBarrier() : null; - Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? Power.newSyncBarrier() - : mo.equals(Tag.Linux.MO_ACQUIRE) ? Power.newISyncBarrier() : null; - return eventSequence( - optionalMemoryBarrierBefore, + optionalMemoryBarrierBefore(e.getMo()), load, branchOnCasCmpResult, store, fakeCtrlDep, label, - optionalMemoryBarrierAfter, + optionalMemoryBarrierAfter(e.getMo()), casEnd, newLocal(resultRegister, dummy) ); @@ -678,56 +484,43 @@ public List visitLKMMCmpXchg(LKMMCmpXchg e) { public List visitLKMMXchg(LKMMXchg e) { Register resultRegister = e.getResultRegister(); Expression address = e.getAddress(); - String mo = e.getMo(); Register dummy = e.getFunction().newRegister(resultRegister.getType()); - Load load = newRMWLoadExclusive(dummy, address); + Load load = Power.newRMWLoadExclusive(dummy, address); Store store = Power.newRMWStoreConditional(address, e.getValue(), true); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(dummy, label); - Event optionalMemoryBarrierBefore = mo.equals(Tag.Linux.MO_MB) ? Power.newSyncBarrier() - : mo.equals(Tag.Linux.MO_RELEASE) ? Power.newLwSyncBarrier() : null; - Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? Power.newSyncBarrier() - : mo.equals(Tag.Linux.MO_ACQUIRE) ? Power.newISyncBarrier() : null; - return eventSequence( - optionalMemoryBarrierBefore, + optionalMemoryBarrierBefore(e.getMo()), load, store, newLocal(resultRegister, dummy), fakeCtrlDep, label, - optionalMemoryBarrierAfter + optionalMemoryBarrierAfter(e.getMo()) ); } @Override public List visitLKMMOpNoReturn(LKMMOpNoReturn e) { Expression address = e.getAddress(); - String mo = e.getMo(); Register dummy = e.getFunction().newRegister(e.getAccessType()); Expression storeValue = expressions.makeIntBinary(dummy, e.getOperator(), e.getOperand()); // Power does not have mo tags, thus we use the empty string - Load load = newRMWLoadExclusive(dummy, address); + Load load = Power.newRMWLoadExclusive(dummy, address); Store store = Power.newRMWStoreConditional(address, storeValue, true); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(dummy, label); - Event optionalMemoryBarrierBefore = mo.equals(Tag.Linux.MO_MB) ? Power.newSyncBarrier() - : mo.equals(Tag.Linux.MO_RELEASE) ? Power.newLwSyncBarrier() : null; - Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? Power.newSyncBarrier() - : mo.equals(Tag.Linux.MO_ACQUIRE) ? Power.newISyncBarrier() : null; - - return eventSequence( - optionalMemoryBarrierBefore, + optionalMemoryBarrierBefore(e.getMo()), load, store, fakeCtrlDep, label, - optionalMemoryBarrierAfter + optionalMemoryBarrierAfter(e.getMo()) ); } @@ -735,29 +528,22 @@ public List visitLKMMOpNoReturn(LKMMOpNoReturn e) { public List visitLKMMOpReturn(LKMMOpReturn e) { Register resultRegister = e.getResultRegister(); Expression address = e.getAddress(); - String mo = e.getMo(); Register dummy = e.getFunction().newRegister(resultRegister.getType()); - Load load = newRMWLoadExclusive(dummy, address); + Load load = Power.newRMWLoadExclusive(dummy, address); Store store = Power.newRMWStoreConditional(address, dummy, true); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(dummy, label); - Event optionalMemoryBarrierBefore = mo.equals(Tag.Linux.MO_MB) ? Power.newSyncBarrier() - : mo.equals(Tag.Linux.MO_RELEASE) ? Power.newLwSyncBarrier() : null; - Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? Power.newSyncBarrier() - : mo.equals(Tag.Linux.MO_ACQUIRE) ? Power.newISyncBarrier() : null; - - return eventSequence( - optionalMemoryBarrierBefore, + optionalMemoryBarrierBefore(e.getMo()), load, newLocal(dummy, expressions.makeIntBinary(dummy, e.getOperator(), e.getOperand())), store, newLocal(resultRegister, dummy), fakeCtrlDep, label, - optionalMemoryBarrierAfter + optionalMemoryBarrierAfter(e.getMo()) ); } @@ -765,27 +551,21 @@ public List visitLKMMOpReturn(LKMMOpReturn e) { public List visitLKMMFetchOp(LKMMFetchOp e) { Register resultRegister = e.getResultRegister(); Expression address = e.getAddress(); - String mo = e.getMo(); Register dummy = e.getFunction().newRegister(resultRegister.getType()); - Load load = newRMWLoadExclusive(dummy, address); + Load load = Power.newRMWLoadExclusive(dummy, address); Store store = Power.newRMWStoreConditional(address, expressions.makeIntBinary(dummy, e.getOperator(), e.getOperand()), true); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(dummy, label); - Event optionalMemoryBarrierBefore = mo.equals(Tag.Linux.MO_MB) ? Power.newSyncBarrier() - : mo.equals(Tag.Linux.MO_RELEASE) ? Power.newLwSyncBarrier() : null; - Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? Power.newSyncBarrier() - : mo.equals(Tag.Linux.MO_ACQUIRE) ? Power.newISyncBarrier() : null; - return eventSequence( - optionalMemoryBarrierBefore, + optionalMemoryBarrierBefore(e.getMo()), load, store, newLocal(resultRegister, dummy), fakeCtrlDep, label, - optionalMemoryBarrierAfter + optionalMemoryBarrierAfter(e.getMo()) ); } @@ -798,12 +578,11 @@ public List visitLKMMFetchOp(LKMMFetchOp e) { public List visitLKMMAddUnless(LKMMAddUnless e) { Register resultRegister = e.getResultRegister(); Expression address = e.getAddress(); - String mo = e.getMo(); Type type = resultRegister.getType(); Register regValue = e.getFunction().newRegister(type); // Power does not have mo tags, thus we use the empty string - Load load = newRMWLoadExclusive(regValue, address); + Load load = Power.newRMWLoadExclusive(regValue, address); Store store = Power.newRMWStoreConditional(address, expressions.makeAdd(regValue, e.getOperand()), true); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(regValue, label); @@ -813,20 +592,15 @@ public List visitLKMMAddUnless(LKMMAddUnless e) { Label cauEnd = newLabel("CAddU_end"); CondJump branchOnCauCmpResult = newJumpUnless(dummy, cauEnd); - Event optionalMemoryBarrierBefore = mo.equals(Tag.Linux.MO_MB) ? Power.newSyncBarrier() - : mo.equals(Tag.Linux.MO_RELEASE) ? Power.newLwSyncBarrier() : null; - Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? Power.newSyncBarrier() - : mo.equals(Tag.Linux.MO_ACQUIRE) ? Power.newISyncBarrier() : null; - return eventSequence( - optionalMemoryBarrierBefore, + optionalMemoryBarrierBefore(e.getMo()), load, newLocal(dummy, expressions.makeNEQ(regValue, unless)), branchOnCauCmpResult, store, fakeCtrlDep, label, - optionalMemoryBarrierAfter, + optionalMemoryBarrierAfter(e.getMo()), cauEnd, newLocal(resultRegister, expressions.makeCast(dummy, resultRegister.getType())) ); @@ -840,31 +614,24 @@ public List visitLKMMAddUnless(LKMMAddUnless e) { public List visitLKMMOpAndTest(LKMMOpAndTest e) { Register resultRegister = e.getResultRegister(); Expression address = e.getAddress(); - String mo = e.getMo(); Register dummy = e.getFunction().newRegister(e.getAccessType()); Expression testResult = expressions.makeNot(expressions.makeBooleanCast(dummy)); - Load load = newRMWLoadExclusive(dummy, address); + Load load = Power.newRMWLoadExclusive(dummy, address); Local localOp = newLocal(dummy, expressions.makeIntBinary(dummy, e.getOperator(), e.getOperand())); Store store = Power.newRMWStoreConditional(address, dummy, true); Local testOp = newLocal(resultRegister, expressions.makeCast(testResult, resultRegister.getType())); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(dummy, label); - Event optionalMemoryBarrierBefore = mo.equals(Tag.Linux.MO_MB) ? Power.newSyncBarrier() - : mo.equals(Tag.Linux.MO_RELEASE) ? Power.newLwSyncBarrier() : null; - Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? Power.newSyncBarrier() - : mo.equals(Tag.Linux.MO_ACQUIRE) ? Power.newISyncBarrier() : null; - - return eventSequence( - optionalMemoryBarrierBefore, + optionalMemoryBarrierBefore(e.getMo()), load, localOp, store, fakeCtrlDep, label, - optionalMemoryBarrierAfter, + optionalMemoryBarrierAfter(e.getMo()), testOp ); } @@ -878,7 +645,7 @@ public List visitLKMMLock(LKMMLock e) { Label label = newLabel("FakeDep"); // Spinlock events are guaranteed to succeed, i.e. we can use assumes return eventSequence( - newRMWLoadExclusive(dummy, e.getLock()), + Power.newRMWLoadExclusive(dummy, e.getLock()), newAssume(expressions.makeEQ(dummy, zero)), Power.newRMWStoreConditional(e.getLock(), one, true), // Fake dependency to guarantee acquire semantics @@ -896,7 +663,27 @@ public List visitLKMMUnlock(LKMMUnlock e) { ); } + private Event optionalMemoryBarrierBefore(String mo) { + return switch (mo) { + case Tag.Linux.MO_MB -> Power.newSyncBarrier(); + case Tag.Linux.MO_RELEASE -> Power.newLwSyncBarrier(); + default -> null; + }; + } + + private Event optionalMemoryBarrierAfter(String mo) { + return switch (mo) { + case Tag.Linux.MO_MB -> Power.newSyncBarrier(); + case Tag.Linux.MO_ACQUIRE -> Power.newISyncBarrier(); + default -> null; + }; + } + public enum PowerScheme { LEADING_SYNC, TRAILING_SYNC } + + private boolean leadingSync() { + return cToPowerScheme.equals(PowerScheme.LEADING_SYNC); + } } \ No newline at end of file diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorRISCV.java b/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorRISCV.java index 7c0eec1a58..c3052b3c57 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorRISCV.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorRISCV.java @@ -16,7 +16,7 @@ import java.util.List; import static com.dat3m.dartagnan.program.event.EventFactory.*; -import static com.dat3m.dartagnan.program.event.Tag.Linux.MO_ACQUIRE; +import static com.dat3m.dartagnan.program.event.Tag.RISCV.*; import static com.google.common.base.Verify.verify; //FIXME: Some compilations generate simple load/store operations with memory orderings, however, @@ -36,7 +36,7 @@ protected VisitorRISCV(boolean useRC11Scheme) { @Override public List visitStoreExclusive(StoreExclusive e) { - RMWStoreExclusive store = RISCV.newRMWStoreConditional(e.getAddress(), e.getMemValue(), e.getMo()); + Store store = RISCV.newRMWStoreConditional(e.getAddress(), e.getMemValue(), false, e.getMo()); return eventSequence( store, @@ -81,8 +81,8 @@ public List visitLlvmXchg(LlvmXchg e) { Expression address = e.getAddress(); String mo = e.getMo(); - Load load = newRMWLoadExclusiveWithMo(resultRegister, address, Tag.RISCV.extractLoadMoFromCMo(mo)); - Store store = RISCV.newRMWStoreConditional(address, e.getValue(), Tag.RISCV.extractStoreMoFromCMo(mo), true); + Load load = RISCV.newRMWLoadExclusive(resultRegister, address, extractLoadMoFromCMo(mo)); + Store store = RISCV.newRMWStoreConditional(address, e.getValue(), true, extractStoreMoFromCMo(mo)); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(resultRegister, label); @@ -104,8 +104,8 @@ public List visitLlvmRMW(LlvmRMW e) { Register dummyReg = e.getFunction().newRegister(type); Local localOp = newLocal(dummyReg, expressions.makeIntBinary(resultRegister, e.getOperator(), e.getOperand())); - Load load = newRMWLoadExclusiveWithMo(resultRegister, address, Tag.RISCV.extractLoadMoFromCMo(mo)); - Store store = RISCV.newRMWStoreConditional(address, dummyReg, Tag.RISCV.extractStoreMoFromCMo(mo), true); + Load load = RISCV.newRMWLoadExclusive(resultRegister, address, extractLoadMoFromCMo(mo)); + Store store = RISCV.newRMWStoreConditional(address, dummyReg, true, extractStoreMoFromCMo(mo)); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(resultRegister, label); @@ -127,8 +127,8 @@ protected List newLlvmCmpXchg(Register oldValue, Register success, Expres Label casEnd = newLabel("CAS_end"); CondJump branchOnCasCmpResult = newJumpUnless(success, casEnd); - Load load = newRMWLoadExclusiveWithMo(oldValue, address, Tag.RISCV.extractLoadMoFromCMo(mo)); - Store store = newRMWStoreExclusiveWithMo(address, newValue, strong, Tag.RISCV.extractStoreMoFromCMo(mo)); + Load load = RISCV.newRMWLoadExclusive(oldValue, address, extractLoadMoFromCMo(mo)); + Store store = newRMWStoreExclusiveWithMo(address, newValue, strong, false, extractStoreMoFromCMo(mo)); return eventSequence( load, @@ -180,8 +180,8 @@ public List visitAtomicCmpXchg(AtomicCmpXchg e) { Local casCmpResult = newLocal(booleanResultRegister, expressions.makeEQ(regValue, regExpected)); CondJump branchOnCasCmpResult = newJumpUnless(booleanResultRegister, casFail); CondJump gotoCasEnd = newGoto(casEnd); - Load loadValue = newRMWLoadExclusiveWithMo(regValue, address, Tag.RISCV.extractLoadMoFromCMo(mo)); - Store storeValue = RISCV.newRMWStoreConditional(address, value, Tag.RISCV.extractStoreMoFromCMo(mo), e.isStrong()); + Load loadValue = RISCV.newRMWLoadExclusive(regValue, address, extractLoadMoFromCMo(mo)); + Store storeValue = RISCV.newRMWStoreConditional(address, value, e.isStrong(), extractStoreMoFromCMo(mo)); Register statusReg = e.getFunction().newRegister("status(" + e.getLocalId() + ")", types.getBooleanType()); // We normally make the following two events optional. // Here we make them mandatory to guarantee correct dependencies. @@ -215,8 +215,8 @@ public List visitAtomicFetchOp(AtomicFetchOp e) { Register dummyReg = e.getFunction().newRegister(type); Local localOp = newLocal(dummyReg, expressions.makeIntBinary(resultRegister, e.getOperator(), e.getOperand())); - Load load = newRMWLoadExclusiveWithMo(resultRegister, address, Tag.RISCV.extractLoadMoFromCMo(mo)); - Store store = RISCV.newRMWStoreConditional(address, dummyReg, Tag.RISCV.extractStoreMoFromCMo(mo), true); + Load load = RISCV.newRMWLoadExclusive(resultRegister, address, extractLoadMoFromCMo(mo)); + Store store = RISCV.newRMWStoreConditional(address, dummyReg, true, extractStoreMoFromCMo(mo)); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(resultRegister, label); @@ -274,8 +274,8 @@ public List visitAtomicXchg(AtomicXchg e) { Expression address = e.getAddress(); String mo = e.getMo(); - Load load = newRMWLoadExclusiveWithMo(resultRegister, address, Tag.RISCV.extractLoadMoFromCMo(mo)); - Store store = RISCV.newRMWStoreConditional(address, e.getValue(), Tag.RISCV.extractStoreMoFromCMo(mo), true); + Load load = RISCV.newRMWLoadExclusive(resultRegister, address, extractLoadMoFromCMo(mo)); + Store store = RISCV.newRMWStoreConditional(address, e.getValue(), true, extractStoreMoFromCMo(mo)); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(resultRegister, label); @@ -297,7 +297,7 @@ public List visitAtomicXchg(AtomicXchg e) { @Override public List visitLKMMLoad(LKMMLoad e) { String mo = e.getMo(); - Event optionalMemoryBarrier = mo.equals(MO_ACQUIRE) ? RISCV.newRRWFence() : null; + Event optionalMemoryBarrier = mo.equals(Tag.Linux.MO_ACQUIRE) ? RISCV.newRRWFence() : null; return eventSequence( newLoad(e.getResultRegister(), e.getAddress()), @@ -367,23 +367,22 @@ public List visitLKMMCmpXchg(LKMMCmpXchg e) { Label casEnd = newLabel("CAS_end"); CondJump branchOnCasCmpResult = newJump(expressions.makeNEQ(dummy, e.getExpectedValue()), casEnd); - Load load = newRMWLoadExclusive(dummy, address); // TODO: No mo on the load? - Store store = RISCV.newRMWStoreConditional(address, e.getStoreValue(), mo.equals(Tag.Linux.MO_MB) ? Tag.RISCV.MO_REL : "", true); + Load load = RISCV.newRMWLoadExclusive(dummy, address, ""); // TODO: No mo on the load? + String moStore = mo.equals(Tag.Linux.MO_MB) ? MO_REL : ""; + Store store = RISCV.newRMWStoreConditional(address, e.getStoreValue(), true, moStore); ExecutionStatus status = newExecutionStatusWithDependencyTracking(statusReg, store); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newJump(statusReg, label); // TODO: Do we really need a fakedep from the store? - Event optionalMemoryBarrierBefore = mo.equals(Tag.Linux.MO_RELEASE) ? RISCV.newRWWFence() : null; - Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? RISCV.newRWRWFence() : mo.equals(Tag.Linux.MO_ACQUIRE) ? RISCV.newRRWFence() : null; return eventSequence( - optionalMemoryBarrierBefore, + optionalMemoryBarrierBefore(mo), load, branchOnCasCmpResult, store, status, fakeCtrlDep, label, - optionalMemoryBarrierAfter, + optionalMemoryBarrierAfter(mo), casEnd, newLocal(resultRegister, dummy) ); @@ -401,14 +400,13 @@ public List visitLKMMXchg(LKMMXchg e) { Register dummy = e.getFunction().newRegister(type); Register statusReg = e.getFunction().newRegister(types.getBooleanType()); - String moLoad = mo.equals(Tag.Linux.MO_MB) || mo.equals(Tag.Linux.MO_ACQUIRE) ? Tag.RISCV.MO_ACQ : ""; - Load load = newRMWLoadExclusiveWithMo(dummy, address, moLoad); - String moStore = mo.equals(Tag.Linux.MO_MB) || mo.equals(Tag.Linux.MO_RELEASE) ? Tag.RISCV.MO_ACQ_REL : ""; - Store store = RISCV.newRMWStoreConditional(address, e.getValue(), moStore, true); + String moLoad = mo.equals(Tag.Linux.MO_MB) || mo.equals(Tag.Linux.MO_ACQUIRE) ? MO_ACQ : ""; + Load load = RISCV.newRMWLoadExclusive(dummy, address, moLoad); + String moStore = mo.equals(Tag.Linux.MO_MB) || mo.equals(Tag.Linux.MO_RELEASE) ? MO_ACQ_REL : ""; + Store store = RISCV.newRMWStoreConditional(address, e.getValue(), true, moStore); ExecutionStatus status = newExecutionStatusWithDependencyTracking(statusReg, store); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newJump(statusReg, label); // TODO: Do we really need a fakedep from the store? - Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? RISCV.newRWRWFence() : mo.equals(Tag.Linux.MO_ACQUIRE) ? RISCV.newRRWFence() : null; return eventSequence( load, @@ -417,7 +415,7 @@ public List visitLKMMXchg(LKMMXchg e) { newLocal(resultRegister, dummy), fakeCtrlDep, label, - optionalMemoryBarrierAfter + optionalMemoryBarrierAfter(mo) ); } @@ -433,10 +431,10 @@ public List visitLKMMOpNoReturn(LKMMOpNoReturn e) { Register dummy = e.getFunction().newRegister(type); Register statusReg = e.getFunction().newRegister(types.getBooleanType()); Expression storeValue = expressions.makeIntBinary(dummy, e.getOperator(), e.getOperand()); - String moLoad = mo.equals(Tag.Linux.MO_MB) || mo.equals(Tag.Linux.MO_ACQUIRE) ? Tag.RISCV.MO_ACQ : ""; - Load load = newRMWLoadExclusiveWithMo(dummy, address, moLoad); - String moStore = mo.equals(Tag.Linux.MO_MB) || mo.equals(Tag.Linux.MO_RELEASE) ? Tag.RISCV.MO_ACQ_REL : ""; - Store store = RISCV.newRMWStoreConditional(address, storeValue, moStore, true); + String moLoad = mo.equals(Tag.Linux.MO_MB) || mo.equals(Tag.Linux.MO_ACQUIRE) ? MO_ACQ : ""; + Load load = RISCV.newRMWLoadExclusive(dummy, address, moLoad); + String moStore = mo.equals(Tag.Linux.MO_MB) || mo.equals(Tag.Linux.MO_RELEASE) ? MO_ACQ_REL : ""; + Store store = RISCV.newRMWStoreConditional(address, storeValue, true, moStore); ExecutionStatus status = newExecutionStatusWithDependencyTracking(statusReg, store); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newJump(statusReg, label); // TODO: Do we really need a fakedep from the store? @@ -464,25 +462,24 @@ public List visitLKMMFetchOp(LKMMFetchOp e) { Register dummy = e.getFunction().newRegister(type); Register statusReg = e.getFunction().newRegister(types.getBooleanType()); + Expression value = expressions.makeIntBinary(dummy, e.getOperator(), e.getOperand()); - Load load = newRMWLoadExclusive(dummy, address); // TODO: No mo on the load? - Store store = RISCV.newRMWStoreConditional(address, expressions.makeIntBinary(dummy, e.getOperator(), e.getOperand()), - mo.equals(Tag.Linux.MO_MB) ? Tag.RISCV.MO_REL : "", true); + Load load = RISCV.newRMWLoadExclusive(dummy, address, ""); // TODO: No mo on the load? + String moStore = mo.equals(Tag.Linux.MO_MB) ? MO_REL : ""; + Store store = RISCV.newRMWStoreConditional(address, value, true, moStore); ExecutionStatus status = newExecutionStatusWithDependencyTracking(statusReg, store); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newJump(statusReg, label); // TODO: Do we really need a fakedep from the store? - Event optionalMemoryBarrierBefore = mo.equals(Tag.Linux.MO_RELEASE) ? RISCV.newRWWFence() : null; - Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? RISCV.newRWRWFence() : mo.equals(Tag.Linux.MO_ACQUIRE) ? RISCV.newRRWFence() : null; return eventSequence( - optionalMemoryBarrierBefore, + optionalMemoryBarrierBefore(mo), load, store, status, newLocal(resultRegister, dummy), fakeCtrlDep, label, - optionalMemoryBarrierAfter + optionalMemoryBarrierAfter(mo) ); } @@ -501,16 +498,15 @@ public List visitLKMMOpReturn(LKMMOpReturn e) { Register dummy = e.getFunction().newRegister(type); Register statusReg = e.getFunction().newRegister(types.getBooleanType()); - Load load = newRMWLoadExclusive(dummy, address); // TODO: No mo on the load? - Store store = RISCV.newRMWStoreConditional(address, dummy, mo.equals(Tag.Linux.MO_MB) ? Tag.RISCV.MO_REL : "", true); + Load load = RISCV.newRMWLoadExclusive(dummy, address, ""); // TODO: No mo on the load? + String moStore = mo.equals(Tag.Linux.MO_MB) ? MO_REL : ""; + Store store = RISCV.newRMWStoreConditional(address, dummy, true, moStore); ExecutionStatus status = newExecutionStatusWithDependencyTracking(statusReg, store); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newJump(statusReg, label); // TODO: Do we really need a fakedep from the store? - Event optionalMemoryBarrierBefore = mo.equals(Tag.Linux.MO_RELEASE) ? RISCV.newRWWFence() : null; - Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? RISCV.newRWRWFence() : mo.equals(Tag.Linux.MO_ACQUIRE) ? RISCV.newRRWFence() : null; return eventSequence( - optionalMemoryBarrierBefore, + optionalMemoryBarrierBefore(mo), load, newLocal(dummy, expressions.makeIntBinary(dummy, e.getOperator(), e.getOperand())), store, @@ -518,7 +514,7 @@ public List visitLKMMOpReturn(LKMMOpReturn e) { newLocal(resultRegister, dummy), fakeCtrlDep, label, - optionalMemoryBarrierAfter + optionalMemoryBarrierAfter(mo) ); } @@ -535,9 +531,11 @@ public List visitLKMMAddUnless(LKMMAddUnless e) { String mo = e.getMo(); Register regValue = e.getFunction().newRegister(type); + Expression value = expressions.makeAdd(regValue, e.getOperand()); - Load load = newRMWLoadExclusive(regValue, address); // TODO: No mo on the load? - Store store = RISCV.newRMWStoreConditional(address, expressions.makeAdd(regValue, e.getOperand()), mo.equals(Tag.Linux.MO_MB) ? Tag.RISCV.MO_REL : "", true); + Load load = RISCV.newRMWLoadExclusive(regValue, address, ""); // TODO: No mo on the load? + String moStore = mo.equals(Tag.Linux.MO_MB) ? MO_REL : ""; + Store store = RISCV.newRMWStoreConditional(address, value, true, moStore); // TODO: Why does this use a different fake dep (from the load) than the other RMW events (from the store)? Label label = newLabel("FakeDep"); @@ -547,7 +545,6 @@ public List visitLKMMAddUnless(LKMMAddUnless e) { Expression unless = e.getCmp(); Label cauEnd = newLabel("CAddU_end"); CondJump branchOnCauCmpResult = newJumpUnless(dummy, cauEnd); - Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? RISCV.newRWRWFence() : mo.equals(Tag.Linux.MO_ACQUIRE) ? RISCV.newRRWFence() : null; return eventSequence( load, @@ -556,7 +553,7 @@ public List visitLKMMAddUnless(LKMMAddUnless e) { store, fakeCtrlDep, label, - optionalMemoryBarrierAfter, + optionalMemoryBarrierAfter(mo), cauEnd, newLocal(resultRegister, expressions.makeCast(dummy, resultRegister.getType())) ); @@ -574,13 +571,15 @@ public List visitLKMMOpAndTest(LKMMOpAndTest e) { Register dummy = e.getFunction().newRegister(e.getAccessType()); Expression testResult = expressions.makeNot(expressions.makeBooleanCast(dummy)); - Load load = newRMWLoadExclusive(dummy, address); // TODO: No mo on the load? + // TODO: No mo on the load? + String storeMo = mo.equals(Tag.Linux.MO_MB) ? MO_REL : ""; + + Load load = RISCV.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); Local testOp = newLocal(resultRegister, expressions.makeCast(testResult, resultRegister.getType())); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(dummy, label); - Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? RISCV.newRWRWFence() : mo.equals(Tag.Linux.MO_ACQUIRE) ? RISCV.newRRWFence() : null; return eventSequence( load, @@ -588,7 +587,7 @@ public List visitLKMMOpAndTest(LKMMOpAndTest e) { store, fakeCtrlDep, label, - optionalMemoryBarrierAfter, + optionalMemoryBarrierAfter(mo), testOp ); } @@ -603,9 +602,9 @@ public List visitLKMMLock(LKMMLock e) { // https://github.com/westerndigitalcorporation/RISC-V-Linux/blob/master/linux/arch/riscv/include/asm/spinlock.h // We replace AMO instructions with LL/SC return eventSequence( - newRMWLoadExclusive(dummy, e.getLock()), + RISCV.newRMWLoadExclusive(dummy, e.getLock(), ""), newAssume(expressions.makeEQ(dummy, zero)), - newRMWStoreExclusive(e.getLock(), one, true), + newRMWStoreExclusive(e.getLock(), one, true, false), RISCV.newRRWFence() ); } @@ -617,4 +616,19 @@ public List visitLKMMUnlock(LKMMUnlock e) { newStore(e.getAddress(), expressions.makeZero((IntegerType)e.getAccessType())) ); } + + private Event optionalMemoryBarrierBefore(String mo) { + return switch (mo) { + case Tag.Linux.MO_RELEASE -> RISCV.newRWWFence(); + default -> null; + }; + } + + private Event optionalMemoryBarrierAfter(String mo) { + return switch (mo) { + case Tag.Linux.MO_MB -> RISCV.newRWRWFence(); + case Tag.Linux.MO_ACQUIRE -> RISCV.newRRWFence(); + default -> null; + }; + } } \ No newline at end of file diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorSpirvOpenCL.java b/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorSpirvOpenCL.java index bff00693e5..80b10f2681 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorSpirvOpenCL.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorSpirvOpenCL.java @@ -6,8 +6,6 @@ import com.dat3m.dartagnan.program.event.EventFactory; import com.dat3m.dartagnan.program.event.Tag; import com.dat3m.dartagnan.program.event.core.*; -import com.dat3m.dartagnan.program.event.lang.catomic.AtomicFetchOp; -import com.dat3m.dartagnan.program.event.lang.catomic.AtomicXchg; import com.dat3m.dartagnan.program.event.lang.spirv.*; import java.util.HashSet; @@ -55,21 +53,21 @@ public List visitSpirvStore(SpirvStore e) { @Override public List visitSpirvXchg(SpirvXchg e) { String mo = moToOpenCLTag(Tag.Spirv.getMoTag(e.getTags())); - AtomicXchg rmw = Atomic.newExchange(e.getResultRegister(), e.getAddress(), + Event rmw = Atomic.newExchange(e.getResultRegister(), e.getAddress(), e.getValue(), mo); rmw.addTags(toOpenCLTags(e.getTags())); rmw.setFunction(e.getFunction()); - return visitAtomicXchg(rmw); + return rmw.accept(this); } @Override public List visitSpirvRMW(SpirvRmw e) { String mo = moToOpenCLTag(Tag.Spirv.getMoTag(e.getTags())); - AtomicFetchOp rmwOp = Atomic.newFetchOp(e.getResultRegister(), e.getAddress(), + Event rmwOp = Atomic.newFetchOp(e.getResultRegister(), e.getAddress(), e.getOperand(), e.getOperator(), mo); rmwOp.setFunction(e.getFunction()); rmwOp.addTags(toOpenCLTags(e.getTags())); - return visitAtomicFetchOp(rmwOp); + return rmwOp.accept(this); } @Override diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorSpirvVulkan.java b/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorSpirvVulkan.java index 4503156a84..b2e12254ee 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorSpirvVulkan.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorSpirvVulkan.java @@ -4,9 +4,6 @@ import com.dat3m.dartagnan.program.event.Event; import com.dat3m.dartagnan.program.event.EventFactory; import com.dat3m.dartagnan.program.event.Tag; -import com.dat3m.dartagnan.program.event.arch.vulkan.VulkanCmpXchg; -import com.dat3m.dartagnan.program.event.arch.vulkan.VulkanRMW; -import com.dat3m.dartagnan.program.event.arch.vulkan.VulkanRMWOp; import com.dat3m.dartagnan.program.event.core.ControlBarrier; import com.dat3m.dartagnan.program.event.core.GenericVisibleEvent; import com.dat3m.dartagnan.program.event.core.Load; @@ -72,21 +69,21 @@ public List visitControlBarrier(ControlBarrier e) { public List visitSpirvXchg(SpirvXchg e) { String mo = moToVulkanTag(Tag.Spirv.getMoTag(e.getTags())); String scope = Tag.Spirv.toVulkanTag(Tag.Spirv.getScopeTag(e.getTags())); - VulkanRMW rmw = EventFactory.Vulkan.newRMW(e.getAddress(), e.getResultRegister(), e.getValue(), mo, scope); + Event rmw = EventFactory.Vulkan.newRMW(e.getAddress(), e.getResultRegister(), e.getValue(), mo, scope); rmw.addTags(Tag.Vulkan.NON_PRIVATE, Tag.Vulkan.AVAILABLE, Tag.Vulkan.VISIBLE); addVulkanTags(e, rmw); - return visitVulkanRMW(rmw); + return rmw.accept(this); } @Override public List visitSpirvRMW(SpirvRmw e) { String mo = moToVulkanTag(Tag.Spirv.getMoTag(e.getTags())); String scope = Tag.Spirv.toVulkanTag(Tag.Spirv.getScopeTag(e.getTags())); - VulkanRMWOp rmwOp = EventFactory.Vulkan.newRMWOp(e.getAddress(), e.getResultRegister(), e.getOperand(), + Event rmwOp = EventFactory.Vulkan.newRMWOp(e.getAddress(), e.getResultRegister(), e.getOperand(), e.getOperator(), mo, scope); rmwOp.addTags(Tag.Vulkan.NON_PRIVATE, Tag.Vulkan.AVAILABLE, Tag.Vulkan.VISIBLE); addVulkanTags(e, rmwOp); - return visitVulkanRMWOp(rmwOp); + return rmwOp.accept(this); } @Override @@ -104,11 +101,11 @@ public List visitSpirvCmpXchg(SpirvCmpXchg e) { "Spir-V CmpXchg with unequal tag sets is not supported"); } String scope = Tag.Spirv.toVulkanTag(Tag.Spirv.getScopeTag(e.getTags())); - VulkanCmpXchg cmpXchg = EventFactory.Vulkan.newVulkanCmpXchg(e.getAddress(), e.getResultRegister(), + Event cmpXchg = EventFactory.Vulkan.newVulkanCmpXchg(e.getAddress(), e.getResultRegister(), e.getExpectedValue(), e.getStoreValue(), moToVulkanTag(spvMoEq), scope); addVulkanTags(e, cmpXchg); cmpXchg.addTags(Tag.Vulkan.NON_PRIVATE, Tag.Vulkan.AVAILABLE, Tag.Vulkan.VISIBLE); - return visitVulkanCmpXchg(cmpXchg); + return cmpXchg.accept(this); } private Event addVulkanTags(Event source, Event target) { diff --git a/dartagnan/src/test/java/com/dat3m/dartagnan/others/miscellaneous/AnalysisTest.java b/dartagnan/src/test/java/com/dat3m/dartagnan/others/miscellaneous/AnalysisTest.java index cecfb737e9..486da06745 100644 --- a/dartagnan/src/test/java/com/dat3m/dartagnan/others/miscellaneous/AnalysisTest.java +++ b/dartagnan/src/test/java/com/dat3m/dartagnan/others/miscellaneous/AnalysisTest.java @@ -801,7 +801,7 @@ public void mixedSizeReadModifyWrite() throws Exception { IntegerType u64 = types.getIntegerType(64); Register r64 = b.getOrNewRegister(0, "r64", u64); b.addChild(0, newRMWLoadExclusive(r64, x)); - b.addChild(0, newRMWStoreExclusive(x, expressions.makeValue(0, u64), true)); + b.addChild(0, newRMWStoreExclusive(x, expressions.makeValue(0, u64), true, false)); b.addChild(1, newStore(x, expressions.makeValue(0, u32))); Program program = b.build(); From 62a9f5823681a4cd4b551b6104ded6cc07b62b78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pascal=20Maseli?= Date: Mon, 16 Mar 2026 17:26:44 +0100 Subject: [PATCH 2/8] fixup! Refactor --- .../program/processing/compilation/VisitorPower.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorPower.java b/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorPower.java index e5fc0a607f..bda633d002 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorPower.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorPower.java @@ -338,8 +338,8 @@ public List visitAtomicXchg(AtomicXchg e) { private Event optionalBarrierBefore(String mo) { return switch (mo) { - case C11.MO_SC -> leadingSync() ? Power.newISyncBarrier() : Power.newSyncBarrier(); - case C11.MO_ACQUIRE, C11.MO_ACQUIRE_RELEASE -> Power.newISyncBarrier(); + case C11.MO_SC -> leadingSync() ? Power.newSyncBarrier() : Power.newLwSyncBarrier(); + case C11.MO_RELEASE, C11.MO_ACQUIRE_RELEASE -> Power.newLwSyncBarrier(); default -> null; }; } From 952ad54af328dbfb7486f5a162a97230313885ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pascal=20Maseli?= Date: Thu, 26 Mar 2026 18:23:12 +0100 Subject: [PATCH 3/8] fixup! Refactor Fix missing tag. --- .../dartagnan/program/processing/compilation/VisitorArm8.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorArm8.java b/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorArm8.java index 9bed5e8cbb..0ae2b2e6de 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorArm8.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorArm8.java @@ -213,7 +213,7 @@ protected List newLlvmCmpXchg(Register oldValue, Register success, Expres @Override public List visitLlvmFence(LlvmFence e) { Event fence = switch (e.getMo()) { - case Tag.C11.MO_RELEASE, Tag.C11.MO_SC -> AArch64.newDmbIshBarrier(); + case Tag.C11.MO_RELEASE, Tag.C11.MO_ACQUIRE_RELEASE, Tag.C11.MO_SC -> AArch64.newDmbIshBarrier(); case Tag.C11.MO_ACQUIRE -> AArch64.newDsbIshLdBarrier(); default -> null; }; From b6d6ab21f2e46b342bed6f20d0f555d08b331127 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pascal=20Maseli?= Date: Thu, 26 Mar 2026 18:27:14 +0100 Subject: [PATCH 4/8] Move newRMWLoadExclusive from EventFactory to compilers --- .../dartagnan/program/event/EventFactory.java | 26 ---- .../processing/compilation/VisitorArm8.java | 120 +++++++++------ .../processing/compilation/VisitorPower.java | 137 ++++++++++------- .../processing/compilation/VisitorRISCV.java | 141 +++++++++++------- 4 files changed, 239 insertions(+), 185 deletions(-) diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/program/event/EventFactory.java b/dartagnan/src/main/java/com/dat3m/dartagnan/program/event/EventFactory.java index 294863885e..4e3ac766e1 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/program/event/EventFactory.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/program/event/EventFactory.java @@ -551,14 +551,6 @@ public static class AArch64 { private AArch64() { } - public static Load newRMWLoadExclusive(Register register, Expression address, String mo) { - return newRMWLoadExclusiveWithMo(register, address, mo); - } - - public static Store newRMWStoreExclusive(Expression address, Expression value, boolean strong, String mo) { - return newRMWStoreExclusiveWithMo(address, value, strong, false, mo); - } - public static GenericVisibleEvent newDmbBarrier() { return newBarrier("DMB", "SY"); } @@ -715,16 +707,6 @@ public static class RISCV { private RISCV() { } - public static Load newRMWLoadExclusive(Register register, Expression value, String mo) { - return EventFactory.newRMWLoadExclusiveWithMo(register, value, mo); - } - - public static Store newRMWStoreConditional(Expression address, Expression value, boolean strong, String mo) { - Store store = newRMWStoreExclusiveWithMo(address, value, strong, true, mo); - store.addTags(Tag.RISCV.STCOND); - return store; - } - public static GenericVisibleEvent newRRFence() { return newFence("Fence.r.r"); } @@ -777,14 +759,6 @@ public static class Power { private Power() { } - public static Load newRMWLoadExclusive(Register register, Expression address) { - return EventFactory.newRMWLoadExclusive(register, address); - } - - public static Store newRMWStoreConditional(Expression address, Expression value, boolean isStrong) { - return newRMWStoreExclusive(address, value, isStrong, true); - } - public static GenericVisibleEvent newISyncBarrier() { return newFence("isync"); } diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorArm8.java b/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorArm8.java index 0ae2b2e6de..9972f15f7e 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorArm8.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorArm8.java @@ -33,7 +33,7 @@ protected VisitorArm8(boolean useRC11Scheme) { @Override public List visitStoreExclusive(StoreExclusive e) { - Store store = AArch64.newRMWStoreExclusive(e.getAddress(), e.getMemValue(), false, e.getMo()); + Store store = newRMWStoreExclusive(e.getAddress(), e.getMemValue(), false, e.getMo()); return eventSequence( store, @@ -51,8 +51,8 @@ public List visitXchg(Xchg xchg) { final Register dummy = xchg.getFunction().newRegister(resultRegister.getType()); return eventSequence( - propagateNoRet(xchg, AArch64.newRMWLoadExclusive(dummy, address, loadMo)), - AArch64.newRMWStoreExclusive(address, xchg.getValue(), true, storeMo), + propagateNoRet(xchg, newRMWLoadExclusive(dummy, address, loadMo)), + newRMWStoreExclusive(address, xchg.getValue(), true, storeMo), newLocal(resultRegister, dummy) ); } @@ -151,8 +151,8 @@ public List visitLlvmXchg(LlvmXchg e) { Expression address = e.getAddress(); String mo = e.getMo(); - Load load = AArch64.newRMWLoadExclusive(resultRegister, address, extractLoadMoFromCMo(mo)); - Store store = AArch64.newRMWStoreExclusive(address, e.getValue(), true, extractStoreMoFromCMo(mo)); + Load load = newRMWLoadExclusive(resultRegister, address, extractLoadMoFromCMo(mo)); + Store store = newRMWStoreExclusive(address, e.getValue(), true, extractStoreMoFromCMo(mo)); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(resultRegister, label); @@ -173,8 +173,8 @@ public List visitLlvmRMW(LlvmRMW e) { Register dummyReg = e.getFunction().newRegister(resultRegister.getType()); Local localOp = newLocal(dummyReg, expressions.makeIntBinary(resultRegister, e.getOperator(), e.getOperand())); - Load load = AArch64.newRMWLoadExclusive(resultRegister, address, extractLoadMoFromCMo(mo)); - Store store = AArch64.newRMWStoreExclusive(address, dummyReg, true, extractStoreMoFromCMo(mo)); + Load load = newRMWLoadExclusive(resultRegister, address, extractLoadMoFromCMo(mo)); + Store store = newRMWStoreExclusive(address, dummyReg, true, extractStoreMoFromCMo(mo)); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(resultRegister, label); @@ -196,8 +196,8 @@ protected List newLlvmCmpXchg(Register oldValue, Register success, Expres final Label casEnd = newLabel("CAS_end"); final CondJump branchOnCasCmpResult = newJumpUnless(success, casEnd); - final Load load = AArch64.newRMWLoadExclusive(oldValue, address, extractLoadMoFromCMo(mo)); - final Store store = AArch64.newRMWStoreExclusive(address, newValue, strong, extractStoreMoFromCMo(mo)); + final Load load = newRMWLoadExclusive(oldValue, address, extractLoadMoFromCMo(mo)); + final Store store = newRMWStoreExclusive(address, newValue, strong, extractStoreMoFromCMo(mo)); return eventSequence( load, @@ -213,8 +213,8 @@ protected List newLlvmCmpXchg(Register oldValue, Register success, Expres @Override public List visitLlvmFence(LlvmFence e) { Event fence = switch (e.getMo()) { - case Tag.C11.MO_RELEASE, Tag.C11.MO_ACQUIRE_RELEASE, Tag.C11.MO_SC -> AArch64.newDmbIshBarrier(); - case Tag.C11.MO_ACQUIRE -> AArch64.newDsbIshLdBarrier(); + case Tag.C11.MO_RELEASE, Tag.C11.MO_ACQUIRE_RELEASE, Tag.C11.MO_SC -> newDmbIsh(); + case Tag.C11.MO_ACQUIRE -> newDsbIshLd(); default -> null; }; @@ -249,8 +249,8 @@ public List visitAtomicCmpXchg(AtomicCmpXchg e) { Local casCmpResult = newLocal(booleanResultRegister, expressions.makeEQ(regValue, regExpected)); CondJump branchOnCasCmpResult = newJumpUnless(booleanResultRegister, casFail); CondJump gotoCasEnd = newGoto(casEnd); - Load loadValue = AArch64.newRMWLoadExclusive(regValue, address, extractLoadMoFromCMo(mo)); - Store storeValue = AArch64.newRMWStoreExclusive(address, value, strong, extractStoreMoFromCMo(mo)); + Load loadValue = newRMWLoadExclusive(regValue, address, extractLoadMoFromCMo(mo)); + Store storeValue = newRMWStoreExclusive(address, value, strong, extractStoreMoFromCMo(mo)); 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)); @@ -278,9 +278,9 @@ public List visitAtomicFetchOp(AtomicFetchOp e) { Register dummyReg = e.getFunction().newRegister(resultRegister.getType()); - Load load = AArch64.newRMWLoadExclusive(resultRegister, address, extractLoadMoFromCMo(mo)); + Load load = newRMWLoadExclusive(resultRegister, address, extractLoadMoFromCMo(mo)); Local localOp = newLocal(dummyReg, expressions.makeIntBinary(resultRegister, e.getOperator(), e.getOperand())); - Store store = AArch64.newRMWStoreExclusive(address, dummyReg, true, extractStoreMoFromCMo(mo)); + Store store = newRMWStoreExclusive(address, dummyReg, true, extractStoreMoFromCMo(mo)); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(resultRegister, label); @@ -310,8 +310,8 @@ public List visitAtomicStore(AtomicStore e) { @Override public List visitAtomicThreadFence(AtomicThreadFence e) { Event fence = switch (e.getMo()) { - case Tag.C11.MO_RELEASE, Tag.C11.MO_ACQUIRE_RELEASE, Tag.C11.MO_SC -> AArch64.newDmbIshBarrier(); - case Tag.C11.MO_ACQUIRE -> AArch64.newDsbIshLdBarrier(); + case Tag.C11.MO_RELEASE, Tag.C11.MO_ACQUIRE_RELEASE, Tag.C11.MO_SC -> newDmbIsh(); + case Tag.C11.MO_ACQUIRE -> newDsbIshLd(); default -> null; }; @@ -326,8 +326,8 @@ public List visitAtomicXchg(AtomicXchg e) { Expression address = e.getAddress(); String mo = e.getMo(); - Load load = AArch64.newRMWLoadExclusive(resultRegister, address, extractLoadMoFromCMo(mo)); - Store store = AArch64.newRMWStoreExclusive(address, e.getValue(), true, extractStoreMoFromCMo(mo)); + Load load = newRMWLoadExclusive(resultRegister, address, extractLoadMoFromCMo(mo)); + Store store = newRMWStoreExclusive(address, e.getValue(), true, extractStoreMoFromCMo(mo)); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(resultRegister, label); @@ -367,7 +367,7 @@ public List visitLKMMStore(LKMMStore e) { String mo = e.getMo(); Store store = newStoreWithMo(address, value, mo.equals(Tag.Linux.MO_RELEASE) ? MO_REL : ""); - Event optionalMemoryBarrier = mo.equals(Tag.Linux.MO_MB) ? AArch64.newDsbIshBarrier() : null; + Event optionalMemoryBarrier = mo.equals(Tag.Linux.MO_MB) ? newDsbIsh() : null; return eventSequence( store, @@ -381,23 +381,23 @@ public List visitLKMMStore(LKMMStore e) { public List visitLKMMFence(LKMMFence e) { Event optionalMemoryBarrier = switch (e.getName()) { // mb() - case Tag.Linux.MO_MB -> AArch64.newDsbIshBarrier(); + case Tag.Linux.MO_MB -> newDsbIsh(); // rmb() - case Tag.Linux.MO_RMB -> AArch64.newDsbIshLdBarrier(); + case Tag.Linux.MO_RMB -> newDsbIshLd(); // wmb() - case Tag.Linux.MO_WMB -> AArch64.newDsbIshStBarrier(); + case Tag.Linux.MO_WMB -> newDsbIshSt(); // __smp_mb() // https://elixir.bootlin.com/linux/v5.18/source/include/asm-generic/barrier.h case Tag.Linux.BEFORE_ATOMIC, - Tag.Linux.AFTER_ATOMIC -> AArch64.newDmbIshBarrier(); + Tag.Linux.AFTER_ATOMIC -> newDmbIsh(); // #define smp_mb__after_spinlock() smp_mb() // https://elixir.bootlin.com/linux/v6.1/source/arch/arm64/include/asm/spinlock.h#L12 - case Tag.Linux.AFTER_SPINLOCK -> AArch64.newDsbIshBarrier(); + case Tag.Linux.AFTER_SPINLOCK -> newDsbIsh(); // #define smp_mb__after_unlock_lock() smp_mb() /* Full ordering for lock. */ // https://elixir.bootlin.com/linux/v6.1/source/include/linux/rcupdate.h#L1008 // It seem to be only used for RCU related stuff in the kernel so it makes sense // it is defined in that header file - case Tag.Linux.AFTER_UNLOCK_LOCK -> AArch64.newDsbIshBarrier(); + case Tag.Linux.AFTER_UNLOCK_LOCK -> newDsbIsh(); // https://elixir.bootlin.com/linux/v6.1/source/include/linux/compiler.h#L86 case Tag.Linux.BARRIER -> null; default -> throw new UnsupportedOperationException("Compilation of fence " + e.getName() + " is not supported"); @@ -430,11 +430,11 @@ public List visitLKMMCmpXchg(LKMMCmpXchg e) { // equivalent and XOR harms performance substantially. CondJump branchOnCasCmpResult = newJump(expressions.makeNEQ(dummy, e.getExpectedValue()), casEnd); - Load load = AArch64.newRMWLoadExclusive(dummy, address, extractLoadMoFromLKMo(mo)); - Store store = AArch64.newRMWStoreExclusive(address, e.getStoreValue(), true, extractStoreMoFromLKMo(mo)); + Load load = newRMWLoadExclusive(dummy, address, extractLoadMoFromLKMo(mo)); + Store store = newRMWStoreExclusive(address, e.getStoreValue(), true, extractStoreMoFromLKMo(mo)); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(dummy, label); - Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? AArch64.newDmbIshBarrier() : null; + Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? newDmbIsh() : null; return eventSequence( load, @@ -457,11 +457,11 @@ public List visitLKMMXchg(LKMMXchg e) { String mo = e.getMo(); Register dummy = e.getFunction().newRegister(resultRegister.getType()); - Load load = AArch64.newRMWLoadExclusive(dummy, address, extractLoadMoFromLKMo(mo)); - Store store = AArch64.newRMWStoreExclusive(address, e.getValue(), true, extractStoreMoFromLKMo(mo)); + Load load = newRMWLoadExclusive(dummy, address, extractLoadMoFromLKMo(mo)); + Store store = newRMWStoreExclusive(address, e.getValue(), true, extractStoreMoFromLKMo(mo)); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(dummy, label); - Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? AArch64.newDmbIshBarrier() : null; + Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? newDmbIsh() : null; return eventSequence( load, @@ -481,8 +481,8 @@ public List visitLKMMOpNoReturn(LKMMOpNoReturn e) { Register dummy = e.getFunction().newRegister(e.getAccessType()); Expression storeValue = expressions.makeIntBinary(dummy, e.getOperator(), e.getOperand()); - Load load = AArch64.newRMWLoadExclusive(dummy, address, ""); - Store store = AArch64.newRMWStoreExclusive(address, storeValue, true, ""); + Load load = newRMWLoadExclusive(dummy, address, ""); + Store store = newRMWStoreExclusive(address, storeValue, true, ""); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(dummy, label); @@ -503,11 +503,11 @@ public List visitLKMMOpReturn(LKMMOpReturn e) { String mo = e.getMo(); Register dummy = e.getFunction().newRegister(resultRegister.getType()); - Load load = AArch64.newRMWLoadExclusive(dummy, address, extractLoadMoFromLKMo(mo)); - Store store = AArch64.newRMWStoreExclusive(address, dummy, true, extractStoreMoFromLKMo(mo)); + Load load = newRMWLoadExclusive(dummy, address, extractLoadMoFromLKMo(mo)); + Store store = newRMWStoreExclusive(address, dummy, true, extractStoreMoFromLKMo(mo)); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(dummy, label); - Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? AArch64.newDmbIshBarrier() : null; + Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? newDmbIsh() : null; return eventSequence( load, @@ -530,11 +530,11 @@ public List visitLKMMFetchOp(LKMMFetchOp e) { Register dummy = e.getFunction().newRegister(resultRegister.getType()); Expression value = expressions.makeIntBinary(dummy, e.getOperator(), e.getOperand()); - Load load = AArch64.newRMWLoadExclusive(dummy, address, extractLoadMoFromLKMo(mo)); - Store store = AArch64.newRMWStoreExclusive(address, value, true, extractStoreMoFromLKMo(mo)); + Load load = newRMWLoadExclusive(dummy, address, extractLoadMoFromLKMo(mo)); + Store store = newRMWStoreExclusive(address, value, true, extractStoreMoFromLKMo(mo)); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(dummy, label); - Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? AArch64.newDmbIshBarrier() : null; + Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? newDmbIsh() : null; return eventSequence( load, @@ -560,8 +560,8 @@ public List visitLKMMAddUnless(LKMMAddUnless e) { Register regValue = e.getFunction().newRegister(type); Expression value = expressions.makeAdd(regValue, e.getOperand()); - Load load = AArch64.newRMWLoadExclusive(regValue, address, extractLoadMoFromLKMo(mo)); - Store store = AArch64.newRMWStoreExclusive(address, value, true, extractStoreMoFromLKMo(mo)); + Load load = newRMWLoadExclusive(regValue, address, extractLoadMoFromLKMo(mo)); + Store store = newRMWStoreExclusive(address, value, true, extractStoreMoFromLKMo(mo)); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(regValue, label); @@ -570,7 +570,7 @@ public List visitLKMMAddUnless(LKMMAddUnless e) { Expression unless = e.getCmp(); Label cauEnd = newLabel("CAddU_end"); CondJump branchOnCauCmpResult = newJumpUnless(expressions.makeBooleanCast(dummy), cauEnd); - Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? AArch64.newDmbIshBarrier() : null; + Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? newDmbIsh() : null; return eventSequence( load, @@ -597,13 +597,13 @@ public List visitLKMMOpAndTest(LKMMOpAndTest e) { Register dummy = e.getFunction().newRegister(e.getAccessType()); Expression testResult = expressions.makeNot(expressions.makeBooleanCast(dummy)); - Load load = AArch64.newRMWLoadExclusive(dummy, address, extractLoadMoFromLKMo(mo)); + Load load = newRMWLoadExclusive(dummy, address, extractLoadMoFromLKMo(mo)); Local localOp = newLocal(dummy, expressions.makeIntBinary(dummy, e.getOperator(), e.getOperand())); - Store store = AArch64.newRMWStoreExclusive(address, dummy, true, extractStoreMoFromLKMo(mo)); + Store store = newRMWStoreExclusive(address, dummy, true, extractStoreMoFromLKMo(mo)); Local testOp = newLocal(resultRegister, expressions.makeCast(testResult, resultRegister.getType())); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(dummy, label); - Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? AArch64.newDmbIshBarrier() : null; + Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? newDmbIsh() : null; return eventSequence( load, @@ -626,9 +626,9 @@ public List visitLKMMLock(LKMMLock e) { // With this we miss a ctrl dependency, but this does not matter // because the load is an acquire one. return eventSequence( - AArch64.newRMWLoadExclusive(dummy, e.getLock(), MO_ACQ), + newRMWLoadExclusive(dummy, e.getLock(), MO_ACQ), newAssume(expressions.makeEQ(dummy, zero)), - AArch64.newRMWStoreExclusive(e.getLock(), one, true, "") + newRMWStoreExclusive(e.getLock(), one, true, "") ); } @@ -639,4 +639,28 @@ public List visitLKMMUnlock(LKMMUnlock e) { newStoreWithMo(e.getAddress(), zero, MO_REL) ); } + + private Load newRMWLoadExclusive(Register value, Expression address, String mo) { + return newRMWLoadExclusiveWithMo(value, address, mo); + } + + private Store newRMWStoreExclusive(Expression address, Expression value, boolean strong, String mo) { + return newRMWStoreExclusiveWithMo(address, value, strong, false, mo); + } + + private Event newDmbIsh() { + return AArch64.newDmbIshBarrier(); + } + + private Event newDsbIsh() { + return AArch64.newDsbIshBarrier(); + } + + private Event newDsbIshLd() { + return AArch64.newDsbIshLdBarrier(); + } + + private Event newDsbIshSt() { + return AArch64.newDsbIshStBarrier(); + } } \ No newline at end of file diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorPower.java b/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorPower.java index bda633d002..369ae614c0 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorPower.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorPower.java @@ -6,6 +6,7 @@ import com.dat3m.dartagnan.expression.type.IntegerType; import com.dat3m.dartagnan.program.Register; import com.dat3m.dartagnan.program.event.Event; +import com.dat3m.dartagnan.program.event.EventFactory; import com.dat3m.dartagnan.program.event.Tag; import com.dat3m.dartagnan.program.event.Tag.C11; import com.dat3m.dartagnan.program.event.arch.StoreExclusive; @@ -59,7 +60,7 @@ public List visitStoreExclusive(StoreExclusive e) { public List visitLlvmLoad(LlvmLoad e) { Register resultRegister = e.getResultRegister(); - Event optionalBarrierBefore = e.getMo().equals(C11.MO_SC) && leadingSync() ? Power.newSyncBarrier() : null; + Event optionalBarrierBefore = e.getMo().equals(C11.MO_SC) && leadingSync() ? newSync() : null; Load load = newLoad(resultRegister, e.getAddress()); final boolean doCtrlDependency = switch (e.getMo()) { case C11.MO_SC -> leadingSync(); @@ -70,8 +71,8 @@ public List visitLlvmLoad(LlvmLoad e) { Label optionalLabel = doCtrlDependency ? newLabel("FakeDep") : null; CondJump optionalFakeCtrlDep = doCtrlDependency ? newFakeCtrlDep(resultRegister, optionalLabel) : null; Event optionalBarrierAfter = switch (e.getMo()) { - case C11.MO_SC -> leadingSync() ? Power.newISyncBarrier() : Power.newSyncBarrier(); - case C11.MO_ACQUIRE -> Power.newISyncBarrier(); + case C11.MO_SC -> leadingSync() ? newISync() : newSync(); + case C11.MO_ACQUIRE -> newISync(); default -> null; }; return eventSequence( @@ -85,12 +86,12 @@ public List visitLlvmLoad(LlvmLoad e) { @Override public List visitLlvmStore(LlvmStore e) { Event optionalBarrierBefore = switch (e.getMo()) { - case C11.MO_SC -> leadingSync() ? Power.newSyncBarrier() : Power.newLwSyncBarrier(); - case C11.MO_RELEASE -> Power.newLwSyncBarrier(); + case C11.MO_SC -> leadingSync() ? newSync() : newLwSync(); + case C11.MO_RELEASE -> newLwSync(); default -> null; }; Store store = newStore(e.getAddress(), e.getMemValue()); - Event optionalBarrierAfter = e.getMo().equals(C11.MO_SC) && !leadingSync() ? Power.newSyncBarrier() : null; + Event optionalBarrierAfter = e.getMo().equals(C11.MO_SC) && !leadingSync() ? newSync() : null; return eventSequence( optionalBarrierBefore, store, @@ -103,8 +104,8 @@ public List visitLlvmXchg(LlvmXchg e) { Expression address = e.getAddress(); // Power does not have mo tags, thus we use null - Load load = Power.newRMWLoadExclusive(resultRegister, address); - Store store = Power.newRMWStoreConditional(address, e.getValue(), true); + Load load = newRMWLoadExclusive(resultRegister, address); + Store store = newRMWStoreConditional(address, e.getValue(), true); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(resultRegister, label); @@ -127,8 +128,8 @@ public List visitLlvmRMW(LlvmRMW e) { Local localOp = newLocal(dummyReg, expressions.makeIntBinary(resultRegister, e.getOperator(), e.getOperand())); // Power does not have mo tags, thus we use null - Load load = Power.newRMWLoadExclusive(resultRegister, address); - Store store = Power.newRMWStoreConditional(address, dummyReg, true); + Load load = newRMWLoadExclusive(resultRegister, address); + Store store = newRMWStoreConditional(address, dummyReg, true); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(resultRegister, label); @@ -152,8 +153,8 @@ protected List newLlvmCmpXchg(Register oldValue, Register success, Expres Label casEnd = newLabel("CAS_end"); CondJump branchOnCasCmpResult = newJumpUnless(success, casEnd); - Load load = Power.newRMWLoadExclusive(oldValue, address); - Store store = Power.newRMWStoreConditional(address, newValue, strong); + Load load = newRMWLoadExclusive(oldValue, address); + Store store = newRMWStoreConditional(address, newValue, strong); return eventSequence( optionalBarrierBefore(mo), @@ -171,7 +172,7 @@ protected List newLlvmCmpXchg(Register oldValue, Register success, Expres @Override public List visitLlvmFence(LlvmFence e) { String mo = e.getMo(); - Event fence = mo.equals(Tag.C11.MO_SC) ? Power.newSyncBarrier() : Power.newLwSyncBarrier(); + Event fence = mo.equals(Tag.C11.MO_SC) ? newSync() : newLwSync(); return eventSequence( fence @@ -203,8 +204,8 @@ public List visitAtomicCmpXchg(AtomicCmpXchg e) { CondJump branchOnCasCmpResult = newJumpUnless(booleanResultRegister, casFail); CondJump gotoCasEnd = newGoto(casEnd); // Power does not have mo tags, thus we use the empty string - Load loadValue = Power.newRMWLoadExclusive(regValue, address); - Store storeValue = Power.newRMWStoreConditional(address, value, e.isStrong()); + Load loadValue = newRMWLoadExclusive(regValue, address); + Store storeValue = newRMWStoreConditional(address, value, e.isStrong()); ExecutionStatus optionalExecStatus = null; Local optionalUpdateCasCmpResult = null; if (e.isWeak()) { @@ -238,8 +239,8 @@ public List visitAtomicFetchOp(AtomicFetchOp e) { Register dummyReg = e.getFunction().newRegister(resultRegister.getType()); Local localOp = newLocal(dummyReg, expressions.makeIntBinary(resultRegister, e.getOperator(), e.getOperand())); - Load load = Power.newRMWLoadExclusive(resultRegister, address); - Store store = Power.newRMWStoreConditional(address, dummyReg, true); + Load load = newRMWLoadExclusive(resultRegister, address); + Store store = newRMWStoreConditional(address, dummyReg, true); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(resultRegister, label); @@ -261,7 +262,7 @@ public List visitAtomicLoad(AtomicLoad e) { Expression address = e.getAddress(); String mo = e.getMo(); - Event optionalBarrierBefore = mo.equals(C11.MO_SC) && leadingSync() ? Power.newSyncBarrier() : null; + Event optionalBarrierBefore = mo.equals(C11.MO_SC) && leadingSync() ? newSync() : null; Load load = newLoad(resultRegister, address); final boolean doControlDependency = switch (mo) { case C11.MO_SC -> leadingSync(); @@ -272,8 +273,8 @@ public List visitAtomicLoad(AtomicLoad e) { Label optionalLabel = doControlDependency ? newLabel("FakeDep") : null; CondJump optionalFakeCtrlDep = doControlDependency ? newFakeCtrlDep(resultRegister, optionalLabel) : null; Event optionalBarrierAfter = switch (mo) { - case C11.MO_SC -> leadingSync() ? Power.newISyncBarrier() : Power.newSyncBarrier(); - case C11.MO_ACQUIRE -> Power.newISyncBarrier(); + case C11.MO_SC -> leadingSync() ? newISync() : newSync(); + case C11.MO_ACQUIRE -> newISync(); default -> null; }; @@ -292,12 +293,12 @@ public List visitAtomicStore(AtomicStore e) { Expression address = e.getAddress(); Event optionalBarrierBefore = switch (e.getMo()) { - case C11.MO_SC -> leadingSync() ? Power.newSyncBarrier() : Power.newLwSyncBarrier(); - case C11.MO_RELEASE -> Power.newLwSyncBarrier(); + case C11.MO_SC -> leadingSync() ? newSync() : newLwSync(); + case C11.MO_RELEASE -> newLwSync(); default -> null; }; Store store = newStore(address, value); - Event optionalBarrierAfter = e.getMo().equals(C11.MO_SC) && !leadingSync() ? Power.newSyncBarrier() : null; + Event optionalBarrierAfter = e.getMo().equals(C11.MO_SC) && !leadingSync() ? newSync() : null; return eventSequence( optionalBarrierBefore, @@ -309,7 +310,7 @@ public List visitAtomicStore(AtomicStore e) { @Override public List visitAtomicThreadFence(AtomicThreadFence e) { String mo = e.getMo(); - Event fence = mo.equals(Tag.C11.MO_SC) ? Power.newSyncBarrier() : Power.newLwSyncBarrier(); + Event fence = mo.equals(Tag.C11.MO_SC) ? newSync() : newLwSync(); return eventSequence( fence @@ -321,8 +322,8 @@ public List visitAtomicXchg(AtomicXchg e) { Register resultRegister = e.getResultRegister(); Expression address = e.getAddress(); - Load load = Power.newRMWLoadExclusive(resultRegister, address); - Store store = Power.newRMWStoreConditional(address, e.getValue(), true); + Load load = newRMWLoadExclusive(resultRegister, address); + Store store = newRMWStoreConditional(address, e.getValue(), true); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(resultRegister, label); @@ -338,8 +339,8 @@ public List visitAtomicXchg(AtomicXchg e) { private Event optionalBarrierBefore(String mo) { return switch (mo) { - case C11.MO_SC -> leadingSync() ? Power.newSyncBarrier() : Power.newLwSyncBarrier(); - case C11.MO_RELEASE, C11.MO_ACQUIRE_RELEASE -> Power.newLwSyncBarrier(); + case C11.MO_SC -> leadingSync() ? newSync() : newLwSync(); + case C11.MO_RELEASE, C11.MO_ACQUIRE_RELEASE -> newLwSync(); default -> null; }; } @@ -349,8 +350,8 @@ private Event optionalBarrierAfter(String mo) { // However, power compilers in godbolt.org use a lwsync. // We stick to the literature to potentially find bugs in what researchers claim. return switch (mo) { - case C11.MO_SC -> leadingSync() ? Power.newISyncBarrier() : Power.newSyncBarrier(); - case C11.MO_ACQUIRE, C11.MO_ACQUIRE_RELEASE -> Power.newISyncBarrier(); + case C11.MO_SC -> leadingSync() ? newISync() : newSync(); + case C11.MO_ACQUIRE, C11.MO_ACQUIRE_RELEASE -> newISync(); default -> null; }; } @@ -369,7 +370,7 @@ public List visitLKMMLoad(LKMMLoad e) { // Power does not have mo tags, thus we use the empty string Load load = newLoad(resultRegister, address); - Event optionalMemoryBarrier = mo.equals(Tag.Linux.MO_ACQUIRE) ? Power.newLwSyncBarrier() : null; + Event optionalMemoryBarrier = mo.equals(Tag.Linux.MO_ACQUIRE) ? newLwSync() : null; return eventSequence( load, @@ -386,8 +387,8 @@ public List visitLKMMStore(LKMMStore e) { String mo = e.getMo(); Store store = newStore(address, value); - Event optionalMemoryBarrierBefore = mo.equals(Tag.Linux.MO_RELEASE) ? Power.newLwSyncBarrier() : null; - Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? Power.newSyncBarrier() : null; + Event optionalMemoryBarrierBefore = mo.equals(Tag.Linux.MO_RELEASE) ? newLwSync() : null; + Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? newSync() : null; return eventSequence( optionalMemoryBarrierBefore, @@ -405,15 +406,15 @@ public List visitLKMMFence(LKMMFence e) { Tag.Linux.MO_RMB, Tag.Linux.MO_WMB, Tag.Linux.BEFORE_ATOMIC, - Tag.Linux.AFTER_ATOMIC -> Power.newSyncBarrier(); + Tag.Linux.AFTER_ATOMIC -> newSync(); // #define smp_mb__after_spinlock() smp_mb() // https://elixir.bootlin.com/linux/v6.1/source/arch/powerpc/include/asm/spinlock.h#L14 - case Tag.Linux.AFTER_SPINLOCK -> Power.newSyncBarrier(); + case Tag.Linux.AFTER_SPINLOCK -> newSync(); // #define smp_mb__after_unlock_lock() smp_mb() /* Full ordering for lock. */ // https://elixir.bootlin.com/linux/v6.1/source/include/linux/rcupdate.h#L1008 // It seem to be only used for RCU related stuff in the kernel so it makes sense // it is defined in that header file - case Tag.Linux.AFTER_UNLOCK_LOCK -> Power.newSyncBarrier(); + case Tag.Linux.AFTER_UNLOCK_LOCK -> newSync(); // https://elixir.bootlin.com/linux/v6.1/source/include/linux/compiler.h#L86 case Tag.Linux.BARRIER -> null; default -> @@ -462,8 +463,8 @@ public List visitLKMMCmpXchg(LKMMCmpXchg e) { Label casEnd = newLabel("CAS_end"); CondJump branchOnCasCmpResult = newJump(expressions.makeNEQ(dummy, e.getExpectedValue()), casEnd); - Load load = Power.newRMWLoadExclusive(dummy, address); - Store store = Power.newRMWStoreConditional(address, e.getStoreValue(), true); + Load load = newRMWLoadExclusive(dummy, address); + Store store = newRMWStoreConditional(address, e.getStoreValue(), true); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(dummy, label); @@ -486,8 +487,8 @@ public List visitLKMMXchg(LKMMXchg e) { Expression address = e.getAddress(); Register dummy = e.getFunction().newRegister(resultRegister.getType()); - Load load = Power.newRMWLoadExclusive(dummy, address); - Store store = Power.newRMWStoreConditional(address, e.getValue(), true); + Load load = newRMWLoadExclusive(dummy, address); + Store store = newRMWStoreConditional(address, e.getValue(), true); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(dummy, label); @@ -509,8 +510,8 @@ public List visitLKMMOpNoReturn(LKMMOpNoReturn e) { Register dummy = e.getFunction().newRegister(e.getAccessType()); Expression storeValue = expressions.makeIntBinary(dummy, e.getOperator(), e.getOperand()); // Power does not have mo tags, thus we use the empty string - Load load = Power.newRMWLoadExclusive(dummy, address); - Store store = Power.newRMWStoreConditional(address, storeValue, true); + Load load = newRMWLoadExclusive(dummy, address); + Store store = newRMWStoreConditional(address, storeValue, true); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(dummy, label); @@ -530,8 +531,8 @@ public List visitLKMMOpReturn(LKMMOpReturn e) { Expression address = e.getAddress(); Register dummy = e.getFunction().newRegister(resultRegister.getType()); - Load load = Power.newRMWLoadExclusive(dummy, address); - Store store = Power.newRMWStoreConditional(address, dummy, true); + Load load = newRMWLoadExclusive(dummy, address); + Store store = newRMWStoreConditional(address, dummy, true); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(dummy, label); @@ -553,8 +554,8 @@ public List visitLKMMFetchOp(LKMMFetchOp e) { Expression address = e.getAddress(); Register dummy = e.getFunction().newRegister(resultRegister.getType()); - Load load = Power.newRMWLoadExclusive(dummy, address); - Store store = Power.newRMWStoreConditional(address, expressions.makeIntBinary(dummy, e.getOperator(), e.getOperand()), true); + Load load = newRMWLoadExclusive(dummy, address); + Store store = newRMWStoreConditional(address, expressions.makeIntBinary(dummy, e.getOperator(), e.getOperand()), true); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(dummy, label); @@ -582,8 +583,8 @@ public List visitLKMMAddUnless(LKMMAddUnless e) { Register regValue = e.getFunction().newRegister(type); // Power does not have mo tags, thus we use the empty string - Load load = Power.newRMWLoadExclusive(regValue, address); - Store store = Power.newRMWStoreConditional(address, expressions.makeAdd(regValue, e.getOperand()), true); + Load load = newRMWLoadExclusive(regValue, address); + Store store = newRMWStoreConditional(address, expressions.makeAdd(regValue, e.getOperand()), true); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(regValue, label); @@ -617,9 +618,9 @@ public List visitLKMMOpAndTest(LKMMOpAndTest e) { Register dummy = e.getFunction().newRegister(e.getAccessType()); Expression testResult = expressions.makeNot(expressions.makeBooleanCast(dummy)); - Load load = Power.newRMWLoadExclusive(dummy, address); + Load load = newRMWLoadExclusive(dummy, address); Local localOp = newLocal(dummy, expressions.makeIntBinary(dummy, e.getOperator(), e.getOperand())); - Store store = Power.newRMWStoreConditional(address, dummy, true); + Store store = newRMWStoreConditional(address, dummy, true); Local testOp = newLocal(resultRegister, expressions.makeCast(testResult, resultRegister.getType())); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(dummy, label); @@ -645,40 +646,60 @@ public List visitLKMMLock(LKMMLock e) { Label label = newLabel("FakeDep"); // Spinlock events are guaranteed to succeed, i.e. we can use assumes return eventSequence( - Power.newRMWLoadExclusive(dummy, e.getLock()), + newRMWLoadExclusive(dummy, e.getLock()), newAssume(expressions.makeEQ(dummy, zero)), - Power.newRMWStoreConditional(e.getLock(), one, true), + newRMWStoreConditional(e.getLock(), one, true), // Fake dependency to guarantee acquire semantics newFakeCtrlDep(dummy, label), label, - Power.newISyncBarrier() + newISync() ); } @Override public List visitLKMMUnlock(LKMMUnlock e) { return eventSequence( - Power.newLwSyncBarrier(), + newLwSync(), newStore(e.getAddress(), expressions.makeZero((IntegerType)e.getAccessType())) ); } private Event optionalMemoryBarrierBefore(String mo) { return switch (mo) { - case Tag.Linux.MO_MB -> Power.newSyncBarrier(); - case Tag.Linux.MO_RELEASE -> Power.newLwSyncBarrier(); + case Tag.Linux.MO_MB -> newSync(); + case Tag.Linux.MO_RELEASE -> newLwSync(); default -> null; }; } private Event optionalMemoryBarrierAfter(String mo) { return switch (mo) { - case Tag.Linux.MO_MB -> Power.newSyncBarrier(); - case Tag.Linux.MO_ACQUIRE -> Power.newISyncBarrier(); + case Tag.Linux.MO_MB -> newSync(); + case Tag.Linux.MO_ACQUIRE -> newISync(); default -> null; }; } + private Load newRMWLoadExclusive(Register value, Expression address) { + return EventFactory.newRMWLoadExclusive(value, address); + } + + private Store newRMWStoreConditional(Expression address, Expression value, boolean strong) { + return newRMWStoreExclusive(address, value, strong, true); + } + + private Event newISync() { + return Power.newISyncBarrier(); + } + + private Event newLwSync() { + return Power.newLwSyncBarrier(); + } + + private Event newSync() { + return Power.newSyncBarrier(); + } + public enum PowerScheme { LEADING_SYNC, TRAILING_SYNC } diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorRISCV.java b/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorRISCV.java index c3052b3c57..9400927f11 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorRISCV.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorRISCV.java @@ -36,7 +36,7 @@ protected VisitorRISCV(boolean useRC11Scheme) { @Override public List visitStoreExclusive(StoreExclusive e) { - Store store = RISCV.newRMWStoreConditional(e.getAddress(), e.getMemValue(), false, e.getMo()); + Store store = newRMWStoreConditional(e.getAddress(), e.getMemValue(), false, e.getMo()); return eventSequence( store, @@ -51,8 +51,8 @@ public List visitStoreExclusive(StoreExclusive e) { @Override public List visitLlvmLoad(LlvmLoad e) { String mo = e.getMo(); - Event optionalBarrierBefore = Tag.C11.MO_SC.equals(mo) ? RISCV.newRWRWFence() : null; - Event optionalBarrierAfter = Tag.C11.MO_SC.equals(mo) || Tag.C11.MO_ACQUIRE.equals(mo) ? RISCV.newRRWFence() + Event optionalBarrierBefore = Tag.C11.MO_SC.equals(mo) ? newRWRWFence() : null; + Event optionalBarrierAfter = Tag.C11.MO_SC.equals(mo) || Tag.C11.MO_ACQUIRE.equals(mo) ? newRRWFence() : null; return eventSequence( @@ -66,7 +66,7 @@ public List visitLlvmLoad(LlvmLoad e) { public List visitLlvmStore(LlvmStore e) { String mo = e.getMo(); Event optionalBarrierBefore = Tag.C11.MO_SC.equals(mo) || Tag.C11.MO_RELEASE.equals(mo) || useRC11Scheme - ? RISCV.newRWWFence() + ? newRWWFence() : null; return eventSequence( @@ -81,8 +81,8 @@ public List visitLlvmXchg(LlvmXchg e) { Expression address = e.getAddress(); String mo = e.getMo(); - Load load = RISCV.newRMWLoadExclusive(resultRegister, address, extractLoadMoFromCMo(mo)); - Store store = RISCV.newRMWStoreConditional(address, e.getValue(), true, extractStoreMoFromCMo(mo)); + Load load = newRMWLoadExclusive(resultRegister, address, extractLoadMoFromCMo(mo)); + Store store = newRMWStoreConditional(address, e.getValue(), true, extractStoreMoFromCMo(mo)); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(resultRegister, label); @@ -104,8 +104,8 @@ public List visitLlvmRMW(LlvmRMW e) { Register dummyReg = e.getFunction().newRegister(type); Local localOp = newLocal(dummyReg, expressions.makeIntBinary(resultRegister, e.getOperator(), e.getOperand())); - Load load = RISCV.newRMWLoadExclusive(resultRegister, address, extractLoadMoFromCMo(mo)); - Store store = RISCV.newRMWStoreConditional(address, dummyReg, true, extractStoreMoFromCMo(mo)); + Load load = newRMWLoadExclusive(resultRegister, address, extractLoadMoFromCMo(mo)); + Store store = newRMWStoreConditional(address, dummyReg, true, extractStoreMoFromCMo(mo)); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(resultRegister, label); @@ -127,7 +127,7 @@ protected List newLlvmCmpXchg(Register oldValue, Register success, Expres Label casEnd = newLabel("CAS_end"); CondJump branchOnCasCmpResult = newJumpUnless(success, casEnd); - Load load = RISCV.newRMWLoadExclusive(oldValue, address, extractLoadMoFromCMo(mo)); + Load load = newRMWLoadExclusive(oldValue, address, extractLoadMoFromCMo(mo)); Store store = newRMWStoreExclusiveWithMo(address, newValue, strong, false, extractStoreMoFromCMo(mo)); return eventSequence( @@ -144,10 +144,10 @@ protected List newLlvmCmpXchg(Register oldValue, Register success, Expres @Override public List visitLlvmFence(LlvmFence e) { Event fence = switch (e.getMo()) { - case Tag.C11.MO_ACQUIRE -> RISCV.newRRWFence(); - case Tag.C11.MO_RELEASE -> RISCV.newRWWFence(); - case Tag.C11.MO_ACQUIRE_RELEASE -> RISCV.newTsoFence(); - case Tag.C11.MO_SC -> RISCV.newRWRWFence(); + case Tag.C11.MO_ACQUIRE -> newRRWFence(); + case Tag.C11.MO_RELEASE -> newRWWFence(); + case Tag.C11.MO_ACQUIRE_RELEASE -> newTsoFence(); + case Tag.C11.MO_SC -> newRWRWFence(); default -> null; }; @@ -180,8 +180,8 @@ public List visitAtomicCmpXchg(AtomicCmpXchg e) { Local casCmpResult = newLocal(booleanResultRegister, expressions.makeEQ(regValue, regExpected)); CondJump branchOnCasCmpResult = newJumpUnless(booleanResultRegister, casFail); CondJump gotoCasEnd = newGoto(casEnd); - Load loadValue = RISCV.newRMWLoadExclusive(regValue, address, extractLoadMoFromCMo(mo)); - Store storeValue = RISCV.newRMWStoreConditional(address, value, e.isStrong(), extractStoreMoFromCMo(mo)); + Load loadValue = newRMWLoadExclusive(regValue, address, extractLoadMoFromCMo(mo)); + Store storeValue = newRMWStoreConditional(address, value, e.isStrong(), extractStoreMoFromCMo(mo)); Register statusReg = e.getFunction().newRegister("status(" + e.getLocalId() + ")", types.getBooleanType()); // We normally make the following two events optional. // Here we make them mandatory to guarantee correct dependencies. @@ -215,8 +215,8 @@ public List visitAtomicFetchOp(AtomicFetchOp e) { Register dummyReg = e.getFunction().newRegister(type); Local localOp = newLocal(dummyReg, expressions.makeIntBinary(resultRegister, e.getOperator(), e.getOperand())); - Load load = RISCV.newRMWLoadExclusive(resultRegister, address, extractLoadMoFromCMo(mo)); - Store store = RISCV.newRMWStoreConditional(address, dummyReg, true, extractStoreMoFromCMo(mo)); + Load load = newRMWLoadExclusive(resultRegister, address, extractLoadMoFromCMo(mo)); + Store store = newRMWStoreConditional(address, dummyReg, true, extractStoreMoFromCMo(mo)); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(resultRegister, label); @@ -232,8 +232,8 @@ public List visitAtomicFetchOp(AtomicFetchOp e) { @Override public List visitAtomicLoad(AtomicLoad e) { String mo = e.getMo(); - Event optionalBarrierBefore = Tag.C11.MO_SC.equals(mo) ? RISCV.newRWRWFence() : null; - Event optionalBarrierAfter = Tag.C11.MO_SC.equals(mo) || Tag.C11.MO_ACQUIRE.equals(mo) ? RISCV.newRRWFence() : null; + Event optionalBarrierBefore = Tag.C11.MO_SC.equals(mo) ? newRWRWFence() : null; + Event optionalBarrierAfter = Tag.C11.MO_SC.equals(mo) || Tag.C11.MO_ACQUIRE.equals(mo) ? newRRWFence() : null; return eventSequence( optionalBarrierBefore, @@ -245,7 +245,7 @@ public List visitAtomicLoad(AtomicLoad e) { @Override public List visitAtomicStore(AtomicStore e) { String mo = e.getMo(); - Event optionalBarrierBefore = Tag.C11.MO_SC.equals(mo) || Tag.C11.MO_RELEASE.equals(mo) || useRC11Scheme ? RISCV.newRWWFence() : null; + Event optionalBarrierBefore = Tag.C11.MO_SC.equals(mo) || Tag.C11.MO_RELEASE.equals(mo) || useRC11Scheme ? newRWWFence() : null; return eventSequence( optionalBarrierBefore, @@ -256,10 +256,10 @@ public List visitAtomicStore(AtomicStore e) { @Override public List visitAtomicThreadFence(AtomicThreadFence e) { Event fence = switch (e.getMo()) { - case Tag.C11.MO_ACQUIRE -> RISCV.newRRWFence(); - case Tag.C11.MO_RELEASE -> RISCV.newRWWFence(); - case Tag.C11.MO_ACQUIRE_RELEASE -> RISCV.newTsoFence(); - case Tag.C11.MO_SC -> RISCV.newRWRWFence(); + case Tag.C11.MO_ACQUIRE -> newRRWFence(); + case Tag.C11.MO_RELEASE -> newRWWFence(); + case Tag.C11.MO_ACQUIRE_RELEASE -> newTsoFence(); + case Tag.C11.MO_SC -> newRWRWFence(); default -> null; }; @@ -274,8 +274,8 @@ public List visitAtomicXchg(AtomicXchg e) { Expression address = e.getAddress(); String mo = e.getMo(); - Load load = RISCV.newRMWLoadExclusive(resultRegister, address, extractLoadMoFromCMo(mo)); - Store store = RISCV.newRMWStoreConditional(address, e.getValue(), true, extractStoreMoFromCMo(mo)); + Load load = newRMWLoadExclusive(resultRegister, address, extractLoadMoFromCMo(mo)); + Store store = newRMWStoreConditional(address, e.getValue(), true, extractStoreMoFromCMo(mo)); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newFakeCtrlDep(resultRegister, label); @@ -297,7 +297,7 @@ public List visitAtomicXchg(AtomicXchg e) { @Override public List visitLKMMLoad(LKMMLoad e) { String mo = e.getMo(); - Event optionalMemoryBarrier = mo.equals(Tag.Linux.MO_ACQUIRE) ? RISCV.newRRWFence() : null; + Event optionalMemoryBarrier = mo.equals(Tag.Linux.MO_ACQUIRE) ? newRRWFence() : null; return eventSequence( newLoad(e.getResultRegister(), e.getAddress()), @@ -310,8 +310,8 @@ public List visitLKMMLoad(LKMMLoad e) { public List visitLKMMStore(LKMMStore e) { String mo = e.getMo(); - Event optionalMemoryBarrierBefore = mo.equals(Tag.Linux.MO_RELEASE) ? RISCV.newRWWFence() : null; - Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? RISCV.newRWRWFence() : null; + Event optionalMemoryBarrierBefore = mo.equals(Tag.Linux.MO_RELEASE) ? newRWWFence() : null; + Event optionalMemoryBarrierAfter = mo.equals(Tag.Linux.MO_MB) ? newRWRWFence() : null; return eventSequence( optionalMemoryBarrierBefore, @@ -329,23 +329,23 @@ public List visitLKMMFence(LKMMFence e) { // https://elixir.bootlin.com/linux/v5.18/source/arch/riscv/include/asm/barrier.h case Tag.Linux.MO_MB, Tag.Linux.BEFORE_ATOMIC, - Tag.Linux.AFTER_ATOMIC -> RISCV.newRWRWFence(); + Tag.Linux.AFTER_ATOMIC -> newRWRWFence(); // smp_rmb() - case Tag.Linux.MO_RMB -> RISCV.newRRFence(); + case Tag.Linux.MO_RMB -> newRRFence(); // smp_wmb() - case Tag.Linux.MO_WMB -> RISCV.newWWFence(); + case Tag.Linux.MO_WMB -> newWWFence(); // ##define smp_mb__after_spinlock() RISCV_FENCE(iorw,iorw) // https://elixir.bootlin.com/linux/v6.1/source/arch/riscv/include/asm/barrier.h#L72 // RISCV_FENCE(iorw,iorw) imposes ordering both on devices and memory // https://github.com/westerndigitalcorporation/RISC-V-Linux/blob/master/linux/arch/riscv/include/asm/barrier.h // Since the memory model says nothing about devices, we use RISCV_FENCE(rw,rw) which I think // gives the ordering we want wrt. memory - case Tag.Linux.AFTER_SPINLOCK -> RISCV.newRWRWFence(); + case Tag.Linux.AFTER_SPINLOCK -> newRWRWFence(); // #define smp_mb__after_unlock_lock() smp_mb() /* Full ordering for lock. */ // https://elixir.bootlin.com/linux/v6.1/source/include/linux/rcupdate.h#L1008 // It seem to be only used for RCU related stuff in the kernel so it makes sense // it is defined in that header file - case Tag.Linux.AFTER_UNLOCK_LOCK -> RISCV.newRWRWFence(); + case Tag.Linux.AFTER_UNLOCK_LOCK -> newRWRWFence(); // https://elixir.bootlin.com/linux/v6.1/source/include/linux/compiler.h#L86 case Tag.Linux.BARRIER -> null; default -> @@ -367,9 +367,9 @@ public List visitLKMMCmpXchg(LKMMCmpXchg e) { Label casEnd = newLabel("CAS_end"); CondJump branchOnCasCmpResult = newJump(expressions.makeNEQ(dummy, e.getExpectedValue()), casEnd); - Load load = RISCV.newRMWLoadExclusive(dummy, address, ""); // TODO: No mo on the load? + Load load = newRMWLoadExclusive(dummy, address, ""); // TODO: No mo on the load? String moStore = mo.equals(Tag.Linux.MO_MB) ? MO_REL : ""; - Store store = RISCV.newRMWStoreConditional(address, e.getStoreValue(), true, moStore); + Store store = newRMWStoreConditional(address, e.getStoreValue(), true, moStore); ExecutionStatus status = newExecutionStatusWithDependencyTracking(statusReg, store); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newJump(statusReg, label); // TODO: Do we really need a fakedep from the store? @@ -401,9 +401,9 @@ public List visitLKMMXchg(LKMMXchg e) { Register dummy = e.getFunction().newRegister(type); Register statusReg = e.getFunction().newRegister(types.getBooleanType()); String moLoad = mo.equals(Tag.Linux.MO_MB) || mo.equals(Tag.Linux.MO_ACQUIRE) ? MO_ACQ : ""; - Load load = RISCV.newRMWLoadExclusive(dummy, address, moLoad); + Load load = newRMWLoadExclusive(dummy, address, moLoad); String moStore = mo.equals(Tag.Linux.MO_MB) || mo.equals(Tag.Linux.MO_RELEASE) ? MO_ACQ_REL : ""; - Store store = RISCV.newRMWStoreConditional(address, e.getValue(), true, moStore); + Store store = newRMWStoreConditional(address, e.getValue(), true, moStore); ExecutionStatus status = newExecutionStatusWithDependencyTracking(statusReg, store); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newJump(statusReg, label); // TODO: Do we really need a fakedep from the store? @@ -432,9 +432,9 @@ public List visitLKMMOpNoReturn(LKMMOpNoReturn e) { Register statusReg = e.getFunction().newRegister(types.getBooleanType()); Expression storeValue = expressions.makeIntBinary(dummy, e.getOperator(), e.getOperand()); String moLoad = mo.equals(Tag.Linux.MO_MB) || mo.equals(Tag.Linux.MO_ACQUIRE) ? MO_ACQ : ""; - Load load = RISCV.newRMWLoadExclusive(dummy, address, moLoad); + Load load = newRMWLoadExclusive(dummy, address, moLoad); String moStore = mo.equals(Tag.Linux.MO_MB) || mo.equals(Tag.Linux.MO_RELEASE) ? MO_ACQ_REL : ""; - Store store = RISCV.newRMWStoreConditional(address, storeValue, true, moStore); + Store store = newRMWStoreConditional(address, storeValue, true, moStore); ExecutionStatus status = newExecutionStatusWithDependencyTracking(statusReg, store); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newJump(statusReg, label); // TODO: Do we really need a fakedep from the store? @@ -464,9 +464,9 @@ public List visitLKMMFetchOp(LKMMFetchOp e) { Register statusReg = e.getFunction().newRegister(types.getBooleanType()); Expression value = expressions.makeIntBinary(dummy, e.getOperator(), e.getOperand()); - Load load = RISCV.newRMWLoadExclusive(dummy, address, ""); // TODO: No mo on the load? + Load load = newRMWLoadExclusive(dummy, address, ""); // TODO: No mo on the load? String moStore = mo.equals(Tag.Linux.MO_MB) ? MO_REL : ""; - Store store = RISCV.newRMWStoreConditional(address, value, true, moStore); + Store store = newRMWStoreConditional(address, value, true, moStore); ExecutionStatus status = newExecutionStatusWithDependencyTracking(statusReg, store); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newJump(statusReg, label); // TODO: Do we really need a fakedep from the store? @@ -498,9 +498,9 @@ public List visitLKMMOpReturn(LKMMOpReturn e) { Register dummy = e.getFunction().newRegister(type); Register statusReg = e.getFunction().newRegister(types.getBooleanType()); - Load load = RISCV.newRMWLoadExclusive(dummy, address, ""); // TODO: No mo on the load? + Load load = newRMWLoadExclusive(dummy, address, ""); // TODO: No mo on the load? String moStore = mo.equals(Tag.Linux.MO_MB) ? MO_REL : ""; - Store store = RISCV.newRMWStoreConditional(address, dummy, true, moStore); + Store store = newRMWStoreConditional(address, dummy, true, moStore); ExecutionStatus status = newExecutionStatusWithDependencyTracking(statusReg, store); Label label = newLabel("FakeDep"); Event fakeCtrlDep = newJump(statusReg, label); // TODO: Do we really need a fakedep from the store? @@ -533,9 +533,9 @@ public List visitLKMMAddUnless(LKMMAddUnless e) { Register regValue = e.getFunction().newRegister(type); Expression value = expressions.makeAdd(regValue, e.getOperand()); - Load load = RISCV.newRMWLoadExclusive(regValue, address, ""); // TODO: No mo on the load? + Load load = newRMWLoadExclusive(regValue, address, ""); // TODO: No mo on the load? String moStore = mo.equals(Tag.Linux.MO_MB) ? MO_REL : ""; - Store store = RISCV.newRMWStoreConditional(address, value, true, moStore); + Store store = newRMWStoreConditional(address, value, true, moStore); // TODO: Why does this use a different fake dep (from the load) than the other RMW events (from the store)? Label label = newLabel("FakeDep"); @@ -574,8 +574,9 @@ public List visitLKMMOpAndTest(LKMMOpAndTest e) { // TODO: No mo on the load? String storeMo = mo.equals(Tag.Linux.MO_MB) ? MO_REL : ""; - Load load = RISCV.newRMWLoadExclusive(dummy, address, ""); + Load load = newRMWLoadExclusive(dummy, address, ""); Local localOp = newLocal(dummy, expressions.makeIntBinary(dummy, e.getOperator(), e.getOperand())); + //TODO Store store = newRMWStoreExclusiveWithMo(address, dummy, true, false, storeMo); Local testOp = newLocal(resultRegister, expressions.makeCast(testResult, resultRegister.getType())); Label label = newLabel("FakeDep"); @@ -602,33 +603,67 @@ public List visitLKMMLock(LKMMLock e) { // https://github.com/westerndigitalcorporation/RISC-V-Linux/blob/master/linux/arch/riscv/include/asm/spinlock.h // We replace AMO instructions with LL/SC return eventSequence( - RISCV.newRMWLoadExclusive(dummy, e.getLock(), ""), + newRMWLoadExclusive(dummy, e.getLock(), ""), newAssume(expressions.makeEQ(dummy, zero)), newRMWStoreExclusive(e.getLock(), one, true, false), - RISCV.newRRWFence() + newRRWFence() ); } @Override public List visitLKMMUnlock(LKMMUnlock e) { return eventSequence( - RISCV.newRWWFence(), + newRWWFence(), newStore(e.getAddress(), expressions.makeZero((IntegerType)e.getAccessType())) ); } private Event optionalMemoryBarrierBefore(String mo) { return switch (mo) { - case Tag.Linux.MO_RELEASE -> RISCV.newRWWFence(); + case Tag.Linux.MO_RELEASE -> newRWWFence(); default -> null; }; } private Event optionalMemoryBarrierAfter(String mo) { return switch (mo) { - case Tag.Linux.MO_MB -> RISCV.newRWRWFence(); - case Tag.Linux.MO_ACQUIRE -> RISCV.newRRWFence(); + case Tag.Linux.MO_MB -> newRWRWFence(); + case Tag.Linux.MO_ACQUIRE -> newRRWFence(); default -> null; }; } + + private Load newRMWLoadExclusive(Register value, Expression address, String mo) { + return newRMWLoadExclusiveWithMo(value, address, mo); + } + + private Store newRMWStoreConditional(Expression address, Expression value, boolean strong, String mo) { + Store store = newRMWStoreExclusiveWithMo(address, value, strong, true, mo); + store.addTags(STCOND); + return store; + } + + private Event newRRFence() { + return RISCV.newRRFence(); + } + + private Event newRRWFence() { + return RISCV.newRRWFence(); + } + + private Event newRWWFence() { + return RISCV.newRWWFence(); + } + + private Event newRWRWFence() { + return RISCV.newRWRWFence(); + } + + private Event newWWFence() { + return RISCV.newWWFence(); + } + + private Event newTsoFence() { + return RISCV.newTsoFence(); + } } \ No newline at end of file From 0385200162aacd89732009b70008f3ba9a8865cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pascal=20Maseli?= Date: Thu, 26 Mar 2026 18:53:06 +0100 Subject: [PATCH 5/8] fixup! Move newRMWLoadExclusive from EventFactory to compilers --- .../dartagnan/program/processing/compilation/VisitorRISCV.java | 1 - 1 file changed, 1 deletion(-) diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorRISCV.java b/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorRISCV.java index 9400927f11..3b748b5d24 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorRISCV.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/program/processing/compilation/VisitorRISCV.java @@ -576,7 +576,6 @@ public List visitLKMMOpAndTest(LKMMOpAndTest e) { Load load = newRMWLoadExclusive(dummy, address, ""); Local localOp = newLocal(dummy, expressions.makeIntBinary(dummy, e.getOperator(), e.getOperand())); - //TODO Store store = newRMWStoreExclusiveWithMo(address, dummy, true, false, storeMo); Local testOp = newLocal(resultRegister, expressions.makeCast(testResult, resultRegister.getType())); Label label = newLabel("FakeDep"); From ebd62db16bd17229d5a9ba80db872493e0833b30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pascal=20Maseli?= Date: Thu, 26 Mar 2026 19:06:22 +0100 Subject: [PATCH 6/8] fixup! Move newRMWLoadExclusive from EventFactory to compilers --- .../dartagnan/parsers/program/visitors/VisitorAsmRISCV.java | 4 ++-- .../parsers/program/visitors/VisitorLitmusAArch64.java | 2 +- .../dartagnan/parsers/program/visitors/VisitorLitmusPPC.java | 2 +- .../parsers/program/visitors/VisitorLitmusRISCV.java | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorAsmRISCV.java b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorAsmRISCV.java index 06e6015070..5333e2837b 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorAsmRISCV.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorAsmRISCV.java @@ -105,7 +105,7 @@ public Object visitLoadImmediate(LoadImmediateContext ctx) { public Object visitLoadExclusive(LoadExclusiveContext ctx) { Register register = (Register) ctx.register(0).accept(this); Register address = (Register) ctx.register(1).accept(this); - asmInstructions.add(EventFactory.RISCV.newRMWLoadExclusive(register, address, "")); + asmInstructions.add(EventFactory.newRMWLoadExclusive(register, address)); return null; } @@ -113,7 +113,7 @@ public Object visitLoadExclusive(LoadExclusiveContext ctx) { public Object visitLoadAcquireExclusive(LoadAcquireExclusiveContext ctx) { Register register = (Register) ctx.register(0).accept(this); Register address = (Register) ctx.register(1).accept(this); - asmInstructions.add(EventFactory.RISCV.newRMWLoadExclusive(register, address, Tag.RISCV.MO_ACQ)); + asmInstructions.add(EventFactory.newRMWLoadExclusiveWithMo(register, address, Tag.RISCV.MO_ACQ)); return null; } diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusAArch64.java b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusAArch64.java index 290b585bb2..2a514365a0 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusAArch64.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusAArch64.java @@ -232,7 +232,7 @@ public Object visitLoadExclusive(LoadExclusiveContext ctx) { final Expression address = parseAddress(ctx.address()); final String mo = inst.acquire ? MO_ACQ : ""; final int lineOfCode = ctx.getStart().getLine(); - add(EventFactory.AArch64.newRMWLoadExclusive(register, address, mo), lineOfCode); + add(EventFactory.newRMWLoadExclusiveWithMo(register, address, mo), lineOfCode); addRegister64Update(r64, register, lineOfCode); return null; } diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusPPC.java b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusPPC.java index 6a71237f58..2d187d461d 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusPPC.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusPPC.java @@ -128,7 +128,7 @@ public Object visitLwarx(LwarxContext ctx) { Register r1 = (Register) ctx.register(0).accept(this); Register ra = (Register) ctx.register(1).accept(this); Register rb = (Register) ctx.register(2).accept(this); - return append(EventFactory.Power.newRMWLoadExclusive(r1, expressions.makeAdd(ra, rb)), ctx); + return append(EventFactory.newRMWLoadExclusive(r1, expressions.makeAdd(ra, rb)), ctx); } @Override diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusRISCV.java b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusRISCV.java index fba14df007..bd67b98b9c 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusRISCV.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusRISCV.java @@ -196,7 +196,7 @@ public Object visitSw(SwContext ctx) { public Object visitLr(LrContext ctx) { Register r1 = programBuilder.getOrNewRegister(mainThread, ctx.register(0).getText(), archType); Register ra = programBuilder.getOrErrorRegister(mainThread, ctx.register(1).getText()); - return append(EventFactory.RISCV.newRMWLoadExclusive(r1, ra, getMo(ctx.moRISCV(0), ctx.moRISCV(1))), ctx); + return append(EventFactory.newRMWLoadExclusiveWithMo(r1, ra, getMo(ctx.moRISCV(0), ctx.moRISCV(1))), ctx); } @Override From c3acefb1e306cfff5ce4aba00fbdba8d85580f86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pascal=20Maseli?= Date: Thu, 26 Mar 2026 22:34:54 +0100 Subject: [PATCH 7/8] Refactor VisitorLitmusAArch64 --- .../visitors/VisitorLitmusAArch64.java | 63 ++++++++++--------- 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusAArch64.java b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusAArch64.java index 2a514365a0..c53e90a8dc 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusAArch64.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusAArch64.java @@ -241,7 +241,7 @@ public Object visitLoadExclusive(LoadExclusiveContext ctx) { public Object visitStore(StoreContext ctx) { final Register r64 = parseRegister64(ctx.rV32, ctx.rV64); final StoreInstructionContext inst = ctx.storeInstruction(); - final IntegerType type = inst.byteSize ? i8 : inst.halfWordSize ? i16 : ctx.rV64 == null ? i32 : i64; + final IntegerType type = type(ctx.rV32, inst.halfWordSize, inst.byteSize); final Expression value = expressions.makeIntegerCast(r64, type, false); final Expression address = parseAddress(ctx.address()); final String mo = ctx.storeInstruction().release ? MO_REL : ""; @@ -267,7 +267,7 @@ public Object visitStorePair(StorePairContext ctx) { public Object visitStoreExclusive(StoreExclusiveContext ctx) { final Register r64 = parseRegister64(ctx.rV32, ctx.rV64); final StoreExclusiveInstructionContext inst = ctx.storeExclusiveInstruction(); - final IntegerType type = inst.byteSize ? i8 : inst.halfWordSize ? i16 : ctx.rV64 == null ? i32 : i64; + final IntegerType type = type(ctx.rV32, inst.halfWordSize, inst.byteSize); final Expression value = expressions.makeIntegerCast(r64, type, false); final Register status = parseRegister64(ctx.rS32); final Expression address = parseAddress(ctx.address()); @@ -285,7 +285,7 @@ public Object visitStoreExclusive(StoreExclusiveContext ctx) { final Register loadReg = xchg.getResultRegister(); final Expression address = xchg.getAddress(); - return Optional.of(String.format("SWP%s%s %s, %s, [%s]", acq, rel, value, loadReg, address)); + return Optional.of(String.format("SWP%s%s%s %s, %s, [%s]", acq, rel, size, value, loadReg, address)); }; @Override @@ -327,7 +327,7 @@ public Object visitSwap(SwapContext ctx) { final Register loadReg = cas.getResultRegister(); final Expression address = cas.getAddress(); - return Optional.of(String.format("CAS%s%s %s, %s, [%s]", acq, rel, loadReg, value, address)); + return Optional.of(String.format("CAS%s%s%s %s, %s, [%s]", acq, rel, size, loadReg, value, address)); }; @Override @@ -360,7 +360,6 @@ public Object visitCas(CasContext ctx) { return null; } - record LDSTAmoInfo(IntBinaryOp op, boolean isHalfSize, boolean isByteSize, boolean acquire, boolean release) {} // Used for LDXXX and STXXX instructions of shape @@ -423,6 +422,7 @@ private LDSTAmoInfo getLDSTInfoFromInstructionName(String instrName) { return Optional.of(String.format("LD%s%s%s%s %s, %s, [%s]", op, acq, rel, size, loadReg, operand, address)); }; + private static final CustomPrinting STOP_PRINTER = e -> { if (!(e instanceof RMWOp stop)) { return Optional.empty(); @@ -483,6 +483,30 @@ public Object visitLoadOp(LoadOpContext ctx) { return null; } + @Override + public Object visitStoreOp(StoreOpContext ctx) { + final String instr = ctx.storeOpInstruction().getText(); + final LDSTAmoInfo info = getLDSTInfoFromInstructionName(instr); + + final Register rs64 = parseRegister64(ctx.rS32, ctx.rS64); + final IntegerType type = type(ctx.rS32, info.isHalfSize, info.isByteSize); + Expression operand = expressions.makeCast(rs64, type, false); + if (info.op == IntBinaryOp.AND) { + // This was a CLR instruction + operand = expressions.makeIntNot(operand); + } + + final Expression address = parseAddress(ctx.address()); + final RMWOp stOp = EventFactory.Common.newRmwOp(address, info.op, operand); + if (info.release) { + stOp.addTags(MO_REL); + } + stOp.setMetadata(STOP_PRINTER); + + add(stOp, ctx.getStart().getLine()); + return null; + } + @Override public Object visitBranch(BranchContext ctx) { Label label = programBuilder.getOrCreateLabel(mainThread, ctx.label().getText()); @@ -631,6 +655,10 @@ private Register shrinkRegister(Register r64, Register32Context ctx, boolean hal } } + private IntegerType type(Register32Context ctx, boolean halfWordSize, boolean byteSize) { + return byteSize ? i8 : halfWordSize ? i16 : ctx != null ? i32 : i64; + } + private void addRegister64Update(Register r64, Register value, int lineOfCode) { checkArgument(r64.getType().equals(i64), "Unexpectedly-typed register %s", r64); if (r64 != value) { @@ -643,31 +671,6 @@ private Void add(Event event, int lineOfCode) { return null; } - @Override - public Object visitStoreOp(StoreOpContext ctx) { - final String instr = ctx.storeOpInstruction().getText(); - final LDSTAmoInfo info = getLDSTInfoFromInstructionName(instr); - - final Register rs64 = parseRegister64(ctx.rS32, ctx.rS64); - // TODO: We don't actually care about the smaller register, but only its type! - final Register rs = shrinkRegister(rs64, ctx.rS32, info.isHalfSize, info.isByteSize); - Expression operand = expressions.makeCast(rs64, rs.getType(), false); - if (info.op == IntBinaryOp.AND) { - // This was a CLR instruction - operand = expressions.makeIntNot(operand); - } - - final Expression address = parseAddress(ctx.address()); - final RMWOp stOp = EventFactory.Common.newRmwOp(address, info.op, operand); - if (info.release) { - stOp.addTags(MO_REL); - } - stOp.setMetadata(STOP_PRINTER); - - add(stOp, ctx.getStart().getLine()); - return null; - } - private static String getArmSizeSuffix(Type type) { return switch (((IntegerType) type).getBitWidth()) { case 16 -> "H"; From b82a538db4d8ebc6d0f9075925f033b26adf0d5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pascal=20Maseli?= Date: Fri, 27 Mar 2026 10:17:12 +0100 Subject: [PATCH 8/8] fixup! Refactor VisitorLitmusAArch64 --- .../parsers/program/visitors/VisitorLitmusAArch64.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusAArch64.java b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusAArch64.java index c53e90a8dc..637da0978a 100644 --- a/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusAArch64.java +++ b/dartagnan/src/main/java/com/dat3m/dartagnan/parsers/program/visitors/VisitorLitmusAArch64.java @@ -281,6 +281,7 @@ public Object visitStoreExclusive(StoreExclusiveContext ctx) { } final String acq = e.hasTag(MO_ACQ) ? "A" : ""; final String rel = e.hasTag(MO_REL) ? "L" : ""; + final String size = getArmSizeSuffix(xchg.getAccessType()); final Expression value = xchg.getValue(); final Register loadReg = xchg.getResultRegister(); final Expression address = xchg.getAddress(); @@ -323,6 +324,7 @@ public Object visitSwap(SwapContext ctx) { } final String acq = e.hasTag(MO_ACQ) ? "A" : ""; final String rel = e.hasTag(MO_REL) ? "L" : ""; + final String size = getArmSizeSuffix(cas.getAccessType()); final Expression value = cas.getStoreValue(); final Register loadReg = cas.getResultRegister(); final Expression address = cas.getAddress();