[llvm] a1c447d - [C API]: Add getters for inline assembly template string, constraints, and flags
Justin Bogner via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 15 21:52:22 PDT 2023
Author: Justin Bogner
Date: 2023-08-15T21:49:28-07:00
New Revision: a1c447d9ddcdc00a6da9c8147626c1013d60315d
URL: https://github.com/llvm/llvm-project/commit/a1c447d9ddcdc00a6da9c8147626c1013d60315d
DIFF: https://github.com/llvm/llvm-project/commit/a1c447d9ddcdc00a6da9c8147626c1013d60315d.diff
LOG: [C API]: Add getters for inline assembly template string, constraints, and flags
This change adds support for accessing information about inline
assembly calls through the C API, enough to be able to round-trip the
information. This partially addresses https://llvm.org/pr42692 which
points out gaps in the C API
Getters for each of the parameters to LLVMGetInlineAsm/InlineAsm::get
have been added, such that the C API now has enough surface to clone
inline assembly calls
This API currently only returns the raw constraint string via
LLVMGetInlineAsmConstraintString: it may be prudent to also expose the
parsed constraints via InlineAsm::ParseConstraints, but I wasn't sure
how that should look like. This at least exposes the information for
clients
Patch by Benji Smith. Thanks!
Differential Revision: https://reviews.llvm.org/D153185
Added:
Modified:
llvm/include/llvm-c/Core.h
llvm/lib/IR/Core.cpp
llvm/test/Bindings/llvm-c/echo.ll
llvm/tools/llvm-c-test/echo.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h
index 8f5fb152a7d72d..35c58caee786e9 100644
--- a/llvm/include/llvm-c/Core.h
+++ b/llvm/include/llvm-c/Core.h
@@ -904,12 +904,58 @@ void LLVMAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm, size_t Len);
*
* @see InlineAsm::get()
*/
-LLVMValueRef LLVMGetInlineAsm(LLVMTypeRef Ty, char *AsmString,
- size_t AsmStringSize, char *Constraints,
+LLVMValueRef LLVMGetInlineAsm(LLVMTypeRef Ty, const char *AsmString,
+ size_t AsmStringSize, const char *Constraints,
size_t ConstraintsSize, LLVMBool HasSideEffects,
LLVMBool IsAlignStack,
LLVMInlineAsmDialect Dialect, LLVMBool CanThrow);
+/**
+ * Get the template string used for an inline assembly snippet
+ *
+ */
+const char *LLVMGetInlineAsmAsmString(LLVMValueRef InlineAsmVal, size_t *Len);
+
+/**
+ * Get the raw constraint string for an inline assembly snippet
+ *
+ */
+const char *LLVMGetInlineAsmConstraintString(LLVMValueRef InlineAsmVal,
+ size_t *Len);
+
+/**
+ * Get the dialect used by the inline asm snippet
+ *
+ */
+LLVMInlineAsmDialect LLVMGetInlineAsmDialect(LLVMValueRef InlineAsmVal);
+
+/**
+ * Get the function type of the inline assembly snippet. The same type that
+ * was passed into LLVMGetInlineAsm originally
+ *
+ * @see LLVMGetInlineAsm
+ *
+ */
+LLVMTypeRef LLVMGetInlineAsmFunctionType(LLVMValueRef InlineAsmVal);
+
+/**
+ * Get if the inline asm snippet has side effects
+ *
+ */
+LLVMBool LLVMGetInlineAsmHasSideEffects(LLVMValueRef InlineAsmVal);
+
+/**
+ * Get if the inline asm snippet needs an aligned stack
+ *
+ */
+LLVMBool LLVMGetInlineAsmNeedsAlignedStack(LLVMValueRef InlineAsmVal);
+
+/**
+ * Get if the inline asm snippet may unwind the stack
+ *
+ */
+LLVMBool LLVMGetInlineAsmCanUnwind(LLVMValueRef InlineAsmVal);
+
/**
* Obtain the context to which this module is associated.
*
diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp
index 129e91b5ba3d19..207d57ecc8b24b 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -460,8 +460,8 @@ const char *LLVMGetModuleInlineAsm(LLVMModuleRef M, size_t *Len) {
return Str.c_str();
}
-LLVMValueRef LLVMGetInlineAsm(LLVMTypeRef Ty, char *AsmString,
- size_t AsmStringSize, char *Constraints,
+LLVMValueRef LLVMGetInlineAsm(LLVMTypeRef Ty, const char *AsmString,
+ size_t AsmStringSize, const char *Constraints,
size_t ConstraintsSize, LLVMBool HasSideEffects,
LLVMBool IsAlignStack,
LLVMInlineAsmDialect Dialect, LLVMBool CanThrow) {
@@ -480,6 +480,61 @@ LLVMValueRef LLVMGetInlineAsm(LLVMTypeRef Ty, char *AsmString,
HasSideEffects, IsAlignStack, AD, CanThrow));
}
+const char *LLVMGetInlineAsmAsmString(LLVMValueRef InlineAsmVal, size_t *Len) {
+
+ Value *Val = unwrap<Value>(InlineAsmVal);
+ const std::string &AsmString = cast<InlineAsm>(Val)->getAsmString();
+
+ *Len = AsmString.length();
+ return AsmString.c_str();
+}
+
+const char *LLVMGetInlineAsmConstraintString(LLVMValueRef InlineAsmVal,
+ size_t *Len) {
+ Value *Val = unwrap<Value>(InlineAsmVal);
+ const std::string &ConstraintString =
+ cast<InlineAsm>(Val)->getConstraintString();
+
+ *Len = ConstraintString.length();
+ return ConstraintString.c_str();
+}
+
+LLVMInlineAsmDialect LLVMGetInlineAsmDialect(LLVMValueRef InlineAsmVal) {
+
+ Value *Val = unwrap<Value>(InlineAsmVal);
+ InlineAsm::AsmDialect Dialect = cast<InlineAsm>(Val)->getDialect();
+
+ switch (Dialect) {
+ case InlineAsm::AD_ATT:
+ return LLVMInlineAsmDialectATT;
+ case InlineAsm::AD_Intel:
+ return LLVMInlineAsmDialectIntel;
+ }
+
+ llvm_unreachable("Unrecognized inline assembly dialect");
+ return LLVMInlineAsmDialectATT;
+}
+
+LLVMTypeRef LLVMGetInlineAsmFunctionType(LLVMValueRef InlineAsmVal) {
+ Value *Val = unwrap<Value>(InlineAsmVal);
+ return (LLVMTypeRef)cast<InlineAsm>(Val)->getFunctionType();
+}
+
+LLVMBool LLVMGetInlineAsmHasSideEffects(LLVMValueRef InlineAsmVal) {
+ Value *Val = unwrap<Value>(InlineAsmVal);
+ return cast<InlineAsm>(Val)->hasSideEffects();
+}
+
+LLVMBool LLVMGetInlineAsmNeedsAlignedStack(LLVMValueRef InlineAsmVal) {
+ Value *Val = unwrap<Value>(InlineAsmVal);
+ return cast<InlineAsm>(Val)->isAlignStack();
+}
+
+LLVMBool LLVMGetInlineAsmCanUnwind(LLVMValueRef InlineAsmVal) {
+ Value *Val = unwrap<Value>(InlineAsmVal);
+ return cast<InlineAsm>(Val)->canThrow();
+}
+
/*--.. Operations on module contexts ......................................--*/
LLVMContextRef LLVMGetModuleContext(LLVMModuleRef M) {
return wrap(&unwrap(M)->getContext());
diff --git a/llvm/test/Bindings/llvm-c/echo.ll b/llvm/test/Bindings/llvm-c/echo.ll
index 3f20fb87578547..5daa238bfb8e53 100644
--- a/llvm/test/Bindings/llvm-c/echo.ll
+++ b/llvm/test/Bindings/llvm-c/echo.ll
@@ -113,6 +113,22 @@ define i32 @notailcall() {
ret i32 %1
}
+define i32 @call_inline_asm(i32 %0) {
+ ; Test Intel syntax
+ %2 = tail call i32 asm sideeffect inteldialect "mov $0, $1", "=r,r,~{dirflag},~{fpsr},~{flags}"(i32 %0)
+ %3 = tail call i32 asm sideeffect inteldialect "lea $0, [$1+$2]", "=r,r,r,~{dirflag},~{fpsr},~{flags}"(i32 %0, i32 %2)
+ %4 = tail call i32 asm inteldialect "mov $0, $1", "=r,r,~{dirflag},~{fpsr},~{flags}"(i32 %3)
+ %5 = tail call i32 asm inteldialect unwind "mov $0, $1", "=r,r,~{dirflag},~{fpsr},~{flags}"(i32 %4)
+ %6 = tail call i32 asm alignstack inteldialect "mov $0, $1", "=r,r,~{dirflag},~{fpsr},~{flags}"(i32 %5)
+
+ ; Test AT&T syntax
+ %7 = tail call i32 asm "mov $1, $0", "=r,r,~{dirflag},~{fpsr},~{flags}"(i32 %6)
+ %8 = tail call i32 asm sideeffect "mov $1, $0", "=r,r,~{dirflag},~{fpsr},~{flags}"(i32 %7)
+ %9 = tail call i32 asm alignstack "mov $1, $0", "=r,r,~{dirflag},~{fpsr},~{flags}"(i32 %8)
+ %10 = tail call i32 asm alignstack unwind "mov $1, $0", "=r,r,~{dirflag},~{fpsr},~{flags}"(i32 %9)
+ ret i32 %10
+}
+
define i32 @cond(i32 %a, i32 %b) {
br label %br
unreachable:
diff --git a/llvm/tools/llvm-c-test/echo.cpp b/llvm/tools/llvm-c-test/echo.cpp
index 91c554510d32aa..faf9838a0069af 100644
--- a/llvm/tools/llvm-c-test/echo.cpp
+++ b/llvm/tools/llvm-c-test/echo.cpp
@@ -406,6 +406,32 @@ static LLVMValueRef clone_constant_impl(LLVMValueRef Cst, LLVMModuleRef M) {
}
}
+static LLVMValueRef clone_inline_asm(LLVMValueRef Asm, LLVMModuleRef M) {
+
+ if (!LLVMIsAInlineAsm(Asm))
+ report_fatal_error("Expected inline assembly");
+
+ size_t AsmStringSize = 0;
+ const char *AsmString = LLVMGetInlineAsmAsmString(Asm, &AsmStringSize);
+
+ size_t ConstraintStringSize = 0;
+ const char *ConstraintString =
+ LLVMGetInlineAsmConstraintString(Asm, &ConstraintStringSize);
+
+ LLVMInlineAsmDialect AsmDialect = LLVMGetInlineAsmDialect(Asm);
+
+ LLVMTypeRef AsmFunctionType = LLVMGetInlineAsmFunctionType(Asm);
+
+ LLVMBool HasSideEffects = LLVMGetInlineAsmHasSideEffects(Asm);
+ LLVMBool NeedsAlignStack = LLVMGetInlineAsmNeedsAlignedStack(Asm);
+ LLVMBool CanUnwind = LLVMGetInlineAsmCanUnwind(Asm);
+
+ return LLVMGetInlineAsm(AsmFunctionType, AsmString, AsmStringSize,
+ ConstraintString, ConstraintStringSize,
+ HasSideEffects, NeedsAlignStack, AsmDialect,
+ CanUnwind);
+}
+
struct FunCloner {
LLVMValueRef Fun;
LLVMModuleRef M;
@@ -435,6 +461,10 @@ struct FunCloner {
if (i != VMap.end())
return i->second;
+ // Inline assembly is a Value, but not an Instruction
+ if (LLVMIsAInlineAsm(Src))
+ return clone_inline_asm(Src, M);
+
if (!LLVMIsAInstruction(Src))
report_fatal_error("Expected an instruction");
More information about the llvm-commits
mailing list