Repository: tetratelabs/wazero
Pull request #2111 (2024-03-04 02:51:02)

wazevo(amd64): support for memory fence
cc @anuraaga 


Patch:
diff --git a/internal/engine/wazevo/backend/isa/amd64/instr.go b/internal/engine/wazevo/backend/isa/amd64/instr.go
index bed379ea..600ae2b1 100644
--- a/internal/engine/wazevo/backend/isa/amd64/instr.go
+++ b/internal/engine/wazevo/backend/isa/amd64/instr.go
@@ -258,6 +258,8 @@ func (i *instruction) String() string {
 		return fmt.Sprintf("xmmcmov%s %s, %s", cond(i.u1), i.op1.format(true), i.op2.format(true))
 	case blendvpd:
 		return fmt.Sprintf("blendvpd %s, %s, %%xmm0", i.op1.format(false), i.op2.format(false))
+	case mfence:
+		return "mfence"
 	default:
 		panic(fmt.Sprintf("BUG: %d", int(i.kind)))
 	}
@@ -754,9 +756,17 @@ const (
 	// blendvpd is https://www.felixcloutier.com/x86/blendvpd.
 	blendvpd
 
+	// mfence is https://www.felixcloutier.com/x86/mfence
+	mfence
+
 	instrMax
 )
 
+func (i *instruction) asMFence() *instruction {
+	i.kind = mfence
+	return i
+}
+
 func (i *instruction) asIdivRemSequence(execCtx, divisor, tmpGp regalloc.VReg, isDiv, signed, _64 bool) *instruction {
 	i.kind = idivRemSequence
 	i.op1 = newOperandReg(execCtx)
@@ -978,6 +988,8 @@ func (k instructionKind) String() string {
 		return "xmmCMov"
 	case idivRemSequence:
 		return "idivRemSequence"
+	case mfence:
+		return "mfence"
 	default:
 		panic("BUG")
 	}
@@ -2218,6 +2230,7 @@ var defKinds = [instrMax]defKind{
 	xmmCMov:                defKindOp2,
 	idivRemSequence:        defKindDivRem,
 	blendvpd:               defKindNone,
+	mfence:                 defKindNone,
 }
 
 // String implements fmt.Stringer.
@@ -2293,6 +2306,7 @@ var useKinds = [instrMax]useKind{
 	xmmCMov:                useKindOp1,
 	idivRemSequence:        useKindDivRem,
 	blendvpd:               useKindBlendvpd,
+	mfence:                 useKindNone,
 }
 
 func (u useKind) String() string {
diff --git a/internal/engine/wazevo/backend/isa/amd64/instr_encoding.go b/internal/engine/wazevo/backend/isa/amd64/instr_encoding.go
index 95de5e8e..2f99e8b5 100644
--- a/internal/engine/wazevo/backend/isa/amd64/instr_encoding.go
+++ b/internal/engine/wazevo/backend/isa/amd64/instr_encoding.go
@@ -1259,6 +1259,12 @@ func (i *instruction) encode(c backend.Compiler) (needsLabelResolution bool) {
 		}
 		i.encode(c)
 
+	case mfence:
+		// https://www.felixcloutier.com/x86/mfence
+		c.EmitByte(0x0f)
+		c.EmitByte(0xae)
+		c.EmitByte(0xf0)
+
 	default:
 		panic(fmt.Sprintf("TODO: %v", i.kind))
 	}
diff --git a/internal/engine/wazevo/backend/isa/amd64/machine.go b/internal/engine/wazevo/backend/isa/amd64/machine.go
index a22f29e2..29575ee0 100644
--- a/internal/engine/wazevo/backend/isa/amd64/machine.go
+++ b/internal/engine/wazevo/backend/isa/amd64/machine.go
@@ -956,6 +956,9 @@ func (m *machine) LowerInstr(instr *ssa.Instruction) {
 		}
 		m.insert(load)
 
+	case ssa.OpcodeFence:
+		m.insert(m.allocateInstr().asMFence())
+
 	default:
 		panic("TODO: lowering " + op.String())
 	}


Test patch:
diff --git a/internal/engine/wazevo/backend/isa/amd64/instr_encoding_test.go b/internal/engine/wazevo/backend/isa/amd64/instr_encoding_test.go
index b3f9ccf7..be85fa7e 100644
--- a/internal/engine/wazevo/backend/isa/amd64/instr_encoding_test.go
+++ b/internal/engine/wazevo/backend/isa/amd64/instr_encoding_test.go
@@ -4046,6 +4046,11 @@ func TestInstruction_format_encode(t *testing.T) {
 			want:       "66440f3815f9",
 			wantFormat: "blendvpd %xmm1, %xmm15, %xmm0",
 		},
+		{
+			setup:      func(i *instruction) { i.asMFence() },
+			want:       "0faef0",
+			wantFormat: "mfence",
+		},
 	} {
 		tc := tc
 		t.Run(tc.wantFormat, func(t *testing.T) {
diff --git a/internal/engine/wazevo/e2e_test.go b/internal/engine/wazevo/e2e_test.go
index ff2ec773..9807ebbe 100644
--- a/internal/engine/wazevo/e2e_test.go
+++ b/internal/engine/wazevo/e2e_test.go
@@ -842,10 +842,9 @@ func TestE2E(t *testing.T) {
 			},
 		},
 		{
-			name:      "atomic_fence",
-			m:         testcases.AtomicFence.Module,
-			features:  api.CoreFeaturesV2 | experimental.CoreFeaturesThreads,
-			skipAMD64: true,
+			name:     "atomic_fence",
+			m:        testcases.AtomicFence.Module,
+			features: api.CoreFeaturesV2 | experimental.CoreFeaturesThreads,
 			calls: []callCase{
 				{params: []uint64{}, expResults: []uint64{}},
 			},