Skip to content

Commit

Permalink
fixup! Add atomics support to asmjs
Browse files Browse the repository at this point in the history
  • Loading branch information
Maqrkk committed Feb 5, 2024
1 parent 5093d6d commit 3732ee2
Showing 1 changed file with 27 additions and 10 deletions.
37 changes: 27 additions & 10 deletions llvm/lib/CheerpWriter/CheerpWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4872,13 +4872,19 @@ void CheerpWriter::compileAtomicCmpXchg(const AtomicCmpXchgInst& ai, PARENT_PRIO
if (shift == 0)
shiftPrio = LOWEST;

// We need to use the compare operand twice, so we load it into the second register first.
StringRef reg2 = namegen.getName(&ai, 1);
stream << "(" << reg2 << "=";
// We end up using compileOperand on the cmpOp twice. But this is ok, since we make sure
// that a compare operand to an AtomicCmpXchg instruction is never inlineable.
compileOperand(cmpOp, BIT_OR);
stream << "|0),";
// Compare Exchange can be called even if there are no uses, because it has side effects. In
// this specific case, we do not (and cannot) assign the result to a value and do the comparison.
StringRef reg2;
if (!ai.use_empty())
{
// We need to use the compare operand twice, so we load it into the second register first.
reg2 = namegen.getName(&ai, 1);
stream << "(" << reg2 << "=";
// We end up using compileOperand on the cmpOp twice. But this is ok, since we make sure
// that a compare operand to an AtomicCmpXchg instruction is never inlineable.
compileOperand(cmpOp, BIT_OR);
stream << "|0),";
}
// Now we compile the main atomic compare exchange function.
stream << namegen.getBuiltinName(NameGenerator::Builtin::ATOMICCMPXCHG) << "(";
if (t->isIntegerTy(1) || t->isIntegerTy(8))
Expand All @@ -4894,13 +4900,24 @@ void CheerpWriter::compileAtomicCmpXchg(const AtomicCmpXchgInst& ai, PARENT_PRIO
compileRawPointer(ptrOp, shiftPrio);
if (shift != 0)
stream << ">>" << shift;
stream << "," << reg2 << "|0,";
stream << ",";
// If this instruction has uses, the compare operand has been stored in the second register
// for this instruction. Otherwise, use the compare operand directly.
if (!ai.use_empty())
stream << reg2;
else
compileOperand(cmpOp, BIT_OR);
stream << "|0,";
compileOperand(newValOp, BIT_OR);
stream << "|0)|0;" << NewLine;
stream << "|0)|0";

// Finally compile the second part of this instruction, the comparison between the loaded value
// and the compare operand (which is in the second register for this instruction).
stream << reg2 << "=(" << namegen.getName(&ai, 0) << "|0)==(" << reg2 << "|0)";
if (!ai.use_empty())
{
stream << ";" << NewLine;
stream << reg2 << "=(" << namegen.getName(&ai, 0) << "|0)==(" << reg2 << "|0)";
}
}

CheerpWriter::COMPILE_INSTRUCTION_FEEDBACK CheerpWriter::compileCallInstruction(const CallBase& ci, PARENT_PRIORITY parentPrio)
Expand Down

0 comments on commit 3732ee2

Please sign in to comment.