diff --git a/Test/LLVM/varargs.mlir b/Test/LLVM/varargs.mlir new file mode 100644 index 000000000..10a333fe7 --- /dev/null +++ b/Test/LLVM/varargs.mlir @@ -0,0 +1,22 @@ +// RUN: VEIR_ROUNDTRIP +// RUN: MLIR_ROUNDTRIP + +"builtin.module"() ({ + "llvm.func"() <{function_type = !llvm.func, linkage = #llvm.linkage, sym_name = "sum"}> ({ + ^bb0(%n: i32): + %one = "llvm.mlir.constant"() <{value = 1 : i64}> : () -> i64 + %list = "llvm.alloca"(%one) <{alignment = 8 : i64, elem_type = !llvm.ptr}> : (i64) -> !llvm.ptr + "llvm.intr.vastart"(%list) : (!llvm.ptr) -> () + %i = "llvm.va_arg"(%list) : (!llvm.ptr) -> i32 + %f = "llvm.va_arg"(%list) : (!llvm.ptr) -> f64 + %p = "llvm.va_arg"(%list) : (!llvm.ptr) -> !llvm.ptr + "llvm.intr.vaend"(%list) : (!llvm.ptr) -> () + "llvm.return"(%i) : (i32) -> () + }) : () -> () +}) : () -> () + +// CHECK: "llvm.intr.vastart"(%{{[a-z0-9_]+}}) : (!llvm.ptr) -> () +// CHECK: "llvm.va_arg"(%{{[a-z0-9_]+}}) : (!llvm.ptr) -> i32 +// CHECK: "llvm.va_arg"(%{{[a-z0-9_]+}}) : (!llvm.ptr) -> f64 +// CHECK: "llvm.va_arg"(%{{[a-z0-9_]+}}) : (!llvm.ptr) -> !llvm.ptr +// CHECK: "llvm.intr.vaend"(%{{[a-z0-9_]+}}) : (!llvm.ptr) -> () diff --git a/Test/Verifier/llvm_va_arg_index_result.mlir b/Test/Verifier/llvm_va_arg_index_result.mlir new file mode 100644 index 000000000..12b29b6e8 --- /dev/null +++ b/Test/Verifier/llvm_va_arg_index_result.mlir @@ -0,0 +1,12 @@ +// RUN: not veir-opt %s 2>&1 | filecheck %s +// RUN: MLIR_INVALID + +"builtin.module"() ({ + "llvm.func"() <{function_type = !llvm.func, linkage = #llvm.linkage, sym_name = "f"}> ({ + ^bb0(%p: !llvm.ptr): + %r = "llvm.va_arg"(%p) : (!llvm.ptr) -> index + "llvm.return"() : () -> () + }) : () -> () +}) : () -> () + +// CHECK: llvm.va_arg: result 0 must be an LLVM dialect-compatible type, but got index diff --git a/Test/Verifier/llvm_vastart_non_pointer_operand.mlir b/Test/Verifier/llvm_vastart_non_pointer_operand.mlir new file mode 100644 index 000000000..edd844e9a --- /dev/null +++ b/Test/Verifier/llvm_vastart_non_pointer_operand.mlir @@ -0,0 +1,12 @@ +// RUN: not veir-opt %s 2>&1 | filecheck %s +// RUN: MLIR_INVALID + +"builtin.module"() ({ + "llvm.func"() <{function_type = !llvm.func, linkage = #llvm.linkage, sym_name = "f"}> ({ + ^bb0(%x: i64): + "llvm.intr.vastart"(%x) : (i64) -> () + "llvm.return"() : () -> () + }) : () -> () +}) : () -> () + +// CHECK: llvm.intr.vastart: Expected operand 0 to have !llvm.ptr type diff --git a/Veir/Dialects/LLVM/OpInfo.lean b/Veir/Dialects/LLVM/OpInfo.lean index e1c2fd083..52c4f43e3 100644 --- a/Veir/Dialects/LLVM/OpInfo.lean +++ b/Veir/Dialects/LLVM/OpInfo.lean @@ -32,6 +32,9 @@ inductive Llvm where | intr__cttz | intr__lifetime__start | intr__lifetime__end +| intr__vastart +| intr__vaend +| va_arg | intr__memset | intr__memcpy | intr__memmove @@ -456,6 +459,7 @@ def Llvm.propagatesPoison : Llvm → Bool | .mlir__addressof | .select | .br | .cond_br | .switch | .unreachable | .alloca | .load | .store | .intr__lifetime__start | .intr__lifetime__end | .intr__assume + | .intr__vastart | .intr__vaend | .va_arg | .intr__memset | .intr__memcpy | .intr__memmove | .getelementptr | .insertvalue | .call | .call_intrinsic | .return | .func | .module_flags @@ -689,6 +693,15 @@ def Llvm.verifyLocalInvariants {OpInfo : Type} [IsOpCode OpInfo] let .llvmPointerType _ := operandType.val | throw "Expected operand 0 to have !llvm.ptr type" pure () + | .intr__vastart | .intr__vaend | .va_arg => do + op.checkIsNonNullIntegerType ctx opIn + op.verifyLLVMCompatibleTypes ctx opIn + let results := if opType = .va_arg then 1 else 0 + op.verifyPlainOpCounts ctx opIn 1 results + let operandType := (op.getOperand! ctx.raw 0).getType! ctx.raw + let .llvmPointerType _ := operandType.val + | throw "Expected operand 0 to have !llvm.ptr type" + pure () | .intr__assume => do op.checkIsNonNullIntegerType ctx opIn let props := op.getProperties! ctx.raw Llvm.intr__assume