package sema
import (
"reflect"
"testing"
"github.com/marzeq/qk/parser"
"github.com/marzeq/qk/types"
)
func TestInlineAsmTemplateOperands(t *testing.T) {
got := inlineAsmTemplateOperands("add $2, ${0:q}; $$literal; use ${12}")
want := []int{2, 0, 12}
if !reflect.DeepEqual(got, want) {
t.Fatalf("operands: got %v, want %v", got, want)
}
}
func TestInlineAsmTiedOutput(t *testing.T) {
if index, ok := inlineAsmTiedOutput("12"); !ok || index != 12 {
t.Fatalf("valid tie: index=%d ok=%v", index, ok)
}
for _, invalid := range []string{"", "r", "1r", "-1"} {
if _, ok := inlineAsmTiedOutput(invalid); ok {
t.Fatalf("accepted invalid tie %q", invalid)
}
}
}
func TestInlineAsmCommonConstraintCompatibility(t *testing.T) {
for _, test := range []struct {
constraint string
type_ types.Type
want bool
}{
{"r", types.PrimitiveI32, true},
{"r", types.PointerType{Base: types.PrimitiveU8}, true},
{"r", types.PrimitiveF64, false},
{"f", types.PrimitiveF32, true},
{"f", types.PrimitiveU64, false},
{"i", types.PrimitiveI32, true},
{"x", types.PrimitiveF32, true}, // target-specific: defer to LLVM
} {
if got := inlineAsmConstraintAcceptsType(test.constraint, test.type_); got != test.want {
t.Errorf("constraint %q with %v: got %v, want %v", test.constraint, test.type_, got, test.want)
}
}
}
func TestInlineAsmIntegerConstant(t *testing.T) {
if !inlineAsmIntegerConstant(&parser.IntegerLiteralNode{}) || inlineAsmIntegerConstant(&parser.IdentifierNode{}) {
t.Fatal("integer constant classification is incorrect")
}
}
func TestInlineAsmClobberNames(t *testing.T) {
for _, valid := range []string{"memory", "cc", "xmm0", "flags-register"} {
if !inlineAsmClobberName(valid) {
t.Errorf("rejected valid clobber %q", valid)
}
}
for _, invalid := range []string{"", "~{cc}", "xmm 0", "cc,flags"} {
if inlineAsmClobberName(invalid) {
t.Errorf("accepted invalid clobber %q", invalid)
}
}
}