-
Notifications
You must be signed in to change notification settings - Fork 14.2k
[clang-c] introduce queries on GCC-style inline assembly statements #143424
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-clang Author: wieDasDing (dingxiangfei2009) ChangesWe strive for exposing such information using existing stable ABIs. In doing so, queries are limited to what the original source holds or the LLVM IR These APIs opens new opportunities for Full diff: https://github.com/llvm/llvm-project/pull/143424.diff 5 Files Affected:
diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h
index e4cb4327fbaac..340d050654a69 100644
--- a/clang/include/clang-c/Index.h
+++ b/clang/include/clang-c/Index.h
@@ -36,7 +36,7 @@
#define CINDEX_VERSION_MAJOR 0
#define CINDEX_VERSION_MINOR 64
-#define CINDEX_VERSION_ENCODE(major, minor) (((major)*10000) + ((minor)*1))
+#define CINDEX_VERSION_ENCODE(major, minor) (((major) * 10000) + ((minor) * 1))
#define CINDEX_VERSION \
CINDEX_VERSION_ENCODE(CINDEX_VERSION_MAJOR, CINDEX_VERSION_MINOR)
@@ -4495,6 +4495,97 @@ CINDEX_LINKAGE CXStringSet *clang_Cursor_getCXXManglings(CXCursor);
*/
CINDEX_LINKAGE CXStringSet *clang_Cursor_getObjCManglings(CXCursor);
+/**
+ * @}
+ */
+
+/**
+ * \defgroup CINDEX_MODULE Inline Assembly introspection
+ *
+ * The functions in this group provide access to information about GCC-style
+ * inline assembly statements.
+ *
+ * @{
+ */
+
+/**
+ * Given a CXCursor_GCCAsmStmt cursor, return the assembly template string.
+ * As per LLVM IR Assembly Template language, template placeholders for
+ * inputs and outputs are either of the form $N where N is a decimal number
+ * as an index into the input-output specification,
+ * or ${N:M} where N is a decimal number also as an index into the
+ * input-output specification and M is the template argument modifier.
+ * The index N in both cases points into the the total inputs and outputs,
+ * or more specifically, into the list of outputs followed by the inputs,
+ * starting from index 0 as the first available template argument.
+ */
+
+CINDEX_LINKAGE CXString clang_Cursor_getGCCAssemblyTemplate(CXCursor);
+
+/**
+ * Given a CXCursor_GCCAsmStmt cursor, check if the assembly block has goto
+ * labels.
+ */
+
+CINDEX_LINKAGE unsigned clang_Cursor_isGCCAssemblyHasGoto(CXCursor);
+
+/**
+ * Given a CXCursor_GCCAsmStmt cursor, count the number of outputs
+ */
+
+CINDEX_LINKAGE unsigned clang_Cursor_getGCCAssemblyNumOutputs(CXCursor);
+
+/**
+ * Given a CXCursor_GCCAsmStmt cursor, count the number of inputs
+ */
+
+CINDEX_LINKAGE unsigned clang_Cursor_getGCCAssemblyNumInputs(CXCursor);
+
+/**
+ * Given a CXCursor_GCCAsmStmt cursor, get the constraint and expression cursor
+ * to the Index-th input.
+ */
+
+CINDEX_LINKAGE unsigned clang_Cursor_getGCCAssemblyInput(CXCursor Cursor,
+ unsigned Index,
+ CXString *Constraint,
+ CXCursor *Expr);
+
+/**
+ * Given a CXCursor_GCCAsmStmt cursor, get the constraint and expression cursor
+ * to the Index-th output.
+ */
+
+CINDEX_LINKAGE unsigned clang_Cursor_getGCCAssemblyOutput(CXCursor Cursor,
+ unsigned Index,
+ CXString *Constraint,
+ CXCursor *Expr);
+
+/**
+ * Given a CXCursor_GCCAsmStmt cursor, count the clobbers in it.
+ */
+
+unsigned clang_Cursor_getGCCAssemblyNumClobbers(CXCursor Cursor);
+
+/**
+ * Given a CXCursor_GCCAsmStmt cursor, get the Index-th clobber of it.
+ */
+
+CXString clang_Cursor_getGCCAssemblyClobber(CXCursor Cursor, unsigned Index);
+
+/**
+ * Given a CXCursor_GCCAsmStmt cursor, check if the inline assembly is simple.
+ */
+
+unsigned clang_Cursor_isGCCAssemblySimple(CXCursor Cursor);
+
+/**
+ * Given a CXCursor_GCCAsmStmt cursor, check if the inline assembly is
+ * `volatile`.
+ */
+
+unsigned clang_Cursor_isGCCAssemblyVolatile(CXCursor Cursor);
+
/**
* @}
*/
diff --git a/clang/test/Index/inline-assembly.c b/clang/test/Index/inline-assembly.c
new file mode 100644
index 0000000000000..1953d3d9033ff
--- /dev/null
+++ b/clang/test/Index/inline-assembly.c
@@ -0,0 +1,48 @@
+static void inline_assembly_template_regardless_of_target_machine() {
+ int tmp;
+ asm volatile (
+ "nop\n"
+ "a_value %w[v]\n"
+ "o_value %w[o]"
+ : [v] "=&r" (tmp)
+ : [o] "r" (tmp)
+ : "cc", "memory"
+ );
+}
+
+// RUN c-index-test -test-inline-assembly %s 2>&1 | FileCheck %s
+// CHECK: ===ASM TEMPLATE===
+// CHECK: nop
+// CHECK: a_value ${0:w}
+// CHECK: o_value ${1:w}
+// CHECK: ===ASM TEMPLATE END===
+// CHECK: volatile: true
+// CHECK: simple: false
+// CHECK: Output #0 Constraint (=&r): DeclRefExpr=tmp:2:9
+// CHECK: Input #0 Constraint (r): UnexposedExpr=tmp:2:9
+// CHECK: Clobber #0: cc
+// CHECK: Clobber #1: memory
+// CHECK: ===ASM END===
+
+static void inline_assembly_valid_x86_example() {
+ int tmp;
+ asm (
+ "nop\n"
+ "mov %w[o], %w[v]"
+ : [v] "=&r" (tmp)
+ : [o] "r" (tmp)
+ : "cc", "memory"
+ );
+}
+
+// CHECK: ===ASM TEMPLATE===
+// CHECK: nop
+// CHECK: mov ${1:w}, ${0:w}
+// CHECK: ===ASM TEMPLATE END===
+// CHECK: volatile: false
+// CHECK: simple: false
+// CHECK: Output #0 Constraint (=&r): DeclRefExpr=tmp:28:9
+// CHECK: Input #0 Constraint (r): UnexposedExpr=tmp:28:9
+// CHECK: Clobber #0: cc
+// CHECK: Clobber #1: memory
+// CHECK: ===ASM END===
\ No newline at end of file
diff --git a/clang/tools/c-index-test/c-index-test.c b/clang/tools/c-index-test/c-index-test.c
index 4a887cd0c1e2e..0917439898f98 100644
--- a/clang/tools/c-index-test/c-index-test.c
+++ b/clang/tools/c-index-test/c-index-test.c
@@ -1988,6 +1988,53 @@ static enum CXChildVisitResult PrintDeclAttributes(CXCursor cursor, CXCursor p,
return CXChildVisit_Continue;
}
+/******************************************************************************/
+/* Inline assembly cursor testing */
+/******************************************************************************/
+
+static enum CXChildVisitResult
+PrintGCCInlineAssembly(CXCursor cursor, CXCursor p, CXClientData d) {
+ CXString Constraint, Template, Clobber;
+ CXCursor Expr;
+ unsigned hasGoto, i, e;
+ if (clang_getCursorKind(cursor) != CXCursor_AsmStmt) {
+ return CXChildVisit_Recurse;
+ }
+ hasGoto = clang_Cursor_isGCCAssemblyHasGoto(cursor);
+ printf("===ASM TEMPLATE%s===\n", hasGoto ? " (WITH GOTO)" : "");
+ Template = clang_Cursor_getGCCAssemblyTemplate(cursor);
+ printf("%s", clang_getCString(Template));
+ clang_disposeString(Template);
+ printf("\n===ASM TEMPLATE END===\n");
+
+ printf("volatile: %s\n",
+ clang_Cursor_isGCCAssemblyVolatile(cursor) ? "true" : "false");
+ printf("simple: %s\n",
+ clang_Cursor_isGCCAssemblySimple(cursor) ? "true" : "false");
+
+ for (i = 0, e = clang_Cursor_getGCCAssemblyNumOutputs(cursor); i < e; ++i) {
+ clang_Cursor_getGCCAssemblyOutput(cursor, i, &Constraint, &Expr);
+ printf("Output #%d Constraint (%s): ", i, clang_getCString(Constraint));
+ PrintCursor(Expr, NULL);
+ printf("\n");
+ clang_disposeString(Constraint);
+ }
+ for (i = 0, e = clang_Cursor_getGCCAssemblyNumInputs(cursor); i < e; ++i) {
+ clang_Cursor_getGCCAssemblyInput(cursor, i, &Constraint, &Expr);
+ printf("Input #%d Constraint (%s): ", i, clang_getCString(Constraint));
+ PrintCursor(Expr, NULL);
+ printf("\n");
+ clang_disposeString(Constraint);
+ }
+ for (i = 0, e = clang_Cursor_getGCCAssemblyNumClobbers(cursor); i < e; ++i) {
+ Clobber = clang_Cursor_getGCCAssemblyClobber(cursor, i);
+ printf("Clobber #%d: %s\n", i, clang_getCString(Clobber));
+ clang_disposeString(Constraint);
+ }
+ printf("===ASM END===\n");
+ return CXChildVisit_Recurse;
+}
+
/******************************************************************************/
/* Target information testing. */
/******************************************************************************/
@@ -5010,6 +5057,7 @@ static void print_usage(void) {
" c-index-test -test-annotate-tokens=<range> {<args>}*\n"
" c-index-test -test-inclusion-stack-source {<args>}*\n"
" c-index-test -test-inclusion-stack-tu <AST file>\n");
+ fprintf(stderr, " c-index-test -test-inline-assembly <AST file>\n");
fprintf(stderr,
" c-index-test -test-print-linkage-source {<args>}*\n"
" c-index-test -test-print-visibility {<args>}*\n"
@@ -5167,6 +5215,10 @@ int cindextest_main(int argc, const char **argv) {
else if (argc > 2 && strstr(argv[1], "-single-symbol-sgf-for=") == argv[1])
return perform_test_single_symbol_sgf(argv[1], argc - 2, argv + 2);
+ if (argc > 2 && strstr(argv[1], "-test-inline-assembly") == argv[1])
+ return perform_test_load_source(argc - 2, argv + 2, "all",
+ PrintGCCInlineAssembly, NULL);
+
print_usage();
return 1;
}
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 3068621d9c004..3d7aa19c10645 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -2141,8 +2141,7 @@ class EnqueueVisitor : public ConstStmtVisitor<EnqueueVisitor, void>,
void VisitBlockExpr(const BlockExpr *B);
void VisitCompoundLiteralExpr(const CompoundLiteralExpr *E);
void VisitCompoundStmt(const CompoundStmt *S);
- void VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E) { /* Do nothing. */
- }
+ void VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E) { /* Do nothing. */ }
void VisitMSDependentExistsStmt(const MSDependentExistsStmt *S);
void VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *E);
void VisitCXXNewExpr(const CXXNewExpr *E);
@@ -2252,8 +2251,8 @@ class EnqueueVisitor : public ConstStmtVisitor<EnqueueVisitor, void>,
void VisitOMPMaskedTaskLoopDirective(const OMPMaskedTaskLoopDirective *D);
void
VisitOMPMasterTaskLoopSimdDirective(const OMPMasterTaskLoopSimdDirective *D);
- void VisitOMPMaskedTaskLoopSimdDirective(
- const OMPMaskedTaskLoopSimdDirective *D);
+ void
+ VisitOMPMaskedTaskLoopSimdDirective(const OMPMaskedTaskLoopSimdDirective *D);
void VisitOMPParallelMasterTaskLoopDirective(
const OMPParallelMasterTaskLoopDirective *D);
void VisitOMPParallelMaskedTaskLoopDirective(
@@ -2811,8 +2810,7 @@ void OMPClauseEnqueue::VisitOMPXDynCGroupMemClause(
void OMPClauseEnqueue::VisitOMPDoacrossClause(const OMPDoacrossClause *C) {
VisitOMPClauseList(C);
}
-void OMPClauseEnqueue::VisitOMPXAttributeClause(const OMPXAttributeClause *C) {
-}
+void OMPClauseEnqueue::VisitOMPXAttributeClause(const OMPXAttributeClause *C) {}
void OMPClauseEnqueue::VisitOMPXBareClause(const OMPXBareClause *C) {}
} // namespace
@@ -5290,7 +5288,7 @@ typedef struct _CXChildVisitResult {
int reserved;
enum CXChildVisitResult (*invoke)(struct _CXChildVisitResult *, CXCursor,
CXCursor);
-} * CXCursorVisitorBlock;
+} *CXCursorVisitorBlock;
static enum CXChildVisitResult visitWithBlock(CXCursor cursor, CXCursor parent,
CXClientData client_data) {
@@ -8648,6 +8646,119 @@ void clang_annotateTokens(CXTranslationUnit TU, CXToken *Tokens,
}
}
+//===----------------------------------------------------------------------===//
+// Operations for querying information of a GCC inline assembly block under a
+// cursor.
+//===----------------------------------------------------------------------===//
+CXString clang_Cursor_getGCCAssemblyTemplate(CXCursor Cursor) {
+ if (!clang_isStatement(Cursor.kind))
+ return cxstring::createEmpty();
+ if (auto const *Stmt = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor))) {
+ auto const &C = getCursorContext(Cursor);
+ auto AsmTemplate = Stmt->generateAsmString(C);
+ return cxstring::createDup(AsmTemplate);
+ }
+ return cxstring::createEmpty();
+}
+
+unsigned clang_Cursor_isGCCAssemblyHasGoto(CXCursor Cursor) {
+ if (!clang_isStatement(Cursor.kind))
+ return 0;
+ if (auto const *Stmt = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor))) {
+ return Stmt->isAsmGoto();
+ }
+ return 0;
+}
+
+unsigned clang_Cursor_getGCCAssemblyNumOutputs(CXCursor Cursor) {
+ if (!clang_isStatement(Cursor.kind))
+ return 0;
+ if (auto const *Stmt = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor))) {
+ return Stmt->getNumOutputs();
+ }
+ return 0;
+}
+
+unsigned clang_Cursor_getGCCAssemblyNumInputs(CXCursor Cursor) {
+ if (!clang_isStatement(Cursor.kind))
+ return 0;
+ if (auto const *Stmt = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor))) {
+ return Stmt->getNumInputs();
+ }
+ return 0;
+}
+
+unsigned clang_Cursor_getGCCAssemblyInput(CXCursor Cursor, unsigned Index,
+ CXString *Constraint,
+ CXCursor *Expr) {
+ if (!clang_isStatement(Cursor.kind) || !Constraint || !Expr)
+ return 0;
+ if (auto const *Stmt = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor));
+ Stmt && Index < Stmt->getNumInputs()) {
+ auto Constraint_ = Stmt->getInputConstraint(Index);
+ auto const *Expr_ = Stmt->getInputExpr(Index);
+ *Constraint = cxstring::createDup(Constraint_);
+ *Expr = MakeCXCursor(Expr_, getCursorDecl(Cursor),
+ cxcursor::getCursorTU(Cursor));
+ return 1;
+ }
+ return 0;
+}
+
+unsigned clang_Cursor_getGCCAssemblyOutput(CXCursor Cursor, unsigned Index,
+ CXString *Constraint,
+ CXCursor *Expr) {
+ if (!clang_isStatement(Cursor.kind) || !Constraint || !Expr)
+ return 0;
+ if (auto const *Stmt = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor));
+ Stmt && Index < Stmt->getNumOutputs()) {
+ auto Constraint_ = Stmt->getOutputConstraint(Index);
+ auto const *Expr_ = Stmt->getOutputExpr(Index);
+ *Constraint = cxstring::createDup(Constraint_);
+ *Expr = MakeCXCursor(Expr_, getCursorDecl(Cursor),
+ cxcursor::getCursorTU(Cursor));
+ return 1;
+ }
+ return 0;
+}
+
+unsigned clang_Cursor_getGCCAssemblyNumClobbers(CXCursor Cursor) {
+ if (!clang_isStatement(Cursor.kind))
+ return 0;
+ if (auto const *Stmt = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor))) {
+ return Stmt->getNumClobbers();
+ }
+ return 0;
+}
+
+CXString clang_Cursor_getGCCAssemblyClobber(CXCursor Cursor, unsigned Index) {
+ if (!clang_isStatement(Cursor.kind))
+ return cxstring::createEmpty();
+ if (auto const *Stmt = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor));
+ Stmt && Stmt->getNumClobbers()) {
+ return cxstring::createDup(Stmt->getClobber(Index));
+ }
+ return cxstring::createEmpty();
+}
+
+unsigned clang_Cursor_isGCCAssemblySimple(CXCursor Cursor) {
+ if (!clang_isStatement(Cursor.kind))
+ return 0;
+ if (auto const *Stmt = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor))) {
+ return Stmt->isSimple();
+ }
+ return 0;
+}
+
+unsigned clang_Cursor_isGCCAssemblyVolatile(CXCursor Cursor) {
+ if (!clang_isStatement(Cursor.kind))
+ return 0;
+ if (auto const *Stmt = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor))) {
+ return Stmt->isVolatile();
+ }
+ return 0;
+}
+
//===----------------------------------------------------------------------===//
// Operations for querying linkage of a cursor.
//===----------------------------------------------------------------------===//
diff --git a/clang/tools/libclang/libclang.map b/clang/tools/libclang/libclang.map
index f08d13c3da9e1..b3a12e9e9834b 100644
--- a/clang/tools/libclang/libclang.map
+++ b/clang/tools/libclang/libclang.map
@@ -441,6 +441,16 @@ LLVM_20 {
LLVM_21 {
global:
clang_getFullyQualifiedName;
+ clang_Cursor_getGCCAssemblyTemplate;
+ clang_Cursor_isGCCAssemblyHasGoto;
+ clang_Cursor_getGCCAssemblyNumOutputs;
+ clang_Cursor_getGCCAssemblyNumInputs;
+ clang_Cursor_getGCCAssemblyInput;
+ clang_Cursor_getGCCAssemblyOutput;
+ clang_Cursor_getGCCAssemblyNumClobbers;
+ clang_Cursor_getGCCAssemblyClobber;
+ clang_Cursor_isGCCAssemblySimple;
+ clang_Cursor_isGCCAssemblyVolatile;
};
# Example of how to add a new symbol version entry. If you do add a new symbol
|
4f9e599
to
78ee7fe
Compare
We strive for exposing such information using existing stable ABIs. In doing so, queries are limited to what the original source holds or the LLVM IR `asm` block would expose in connection with attributes that the queries are concerned. Signed-off-by: Xiangfei Ding <[email protected]>
78ee7fe
to
510960f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for working on this! Mostly just nits, the implementation itself looks pretty reasonable so far.
Please be sure to add a release note to clang/docs/ReleaseNotes.rst
so users know about the new functionality.
|
||
/** | ||
* Given a CXCursor_GCCAsmStmt cursor, get the constraint and expression cursor | ||
* to the Index-th input. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What kind of things does the function return via its return value?
* to the Index-th output. | ||
*/ | ||
|
||
CINDEX_LINKAGE unsigned clang_Cursor_getGCCAssemblyOutput(CXCursor Cursor, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same question here.
* Given a CXCursor_GCCAsmStmt cursor, get the Index-th clobber of it. | ||
*/ | ||
|
||
CINDEX_LINKAGE CXString clang_Cursor_getGCCAssemblyClobber(CXCursor Cursor, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does this return on error? An empty string? Something else?
* starting from index 0 as the first available template argument. | ||
*/ | ||
|
||
CINDEX_LINKAGE CXString clang_Cursor_getGCCAssemblyTemplate(CXCursor); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does this return on error?
unsigned Index); | ||
|
||
/** | ||
* Given a CXCursor_GCCAsmStmt cursor, check if the inline assembly is simple. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does it mean for assembly to be "simple"?
auto Constraint_ = Stmt->getOutputConstraint(Index); | ||
auto const *Expr_ = Stmt->getOutputExpr(Index); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here as above.
|
||
unsigned clang_Cursor_getGCCAssemblyInput(CXCursor Cursor, unsigned Index, | ||
CXString *Constraint, | ||
CXCursor *Expr) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Expr
is a type name same as Stmt
.
|
||
unsigned clang_Cursor_getGCCAssemblyOutput(CXCursor Cursor, unsigned Index, | ||
CXString *Constraint, | ||
CXCursor *Expr) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here as above.
CXString clang_Cursor_getGCCAssemblyTemplate(CXCursor Cursor) { | ||
if (!clang_isStatement(Cursor.kind)) | ||
return cxstring::createEmpty(); | ||
if (auto const *Stmt = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor))) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stmt
is a type name, better to pick a name which doesn't conflict with a type (this helps folks who have editors that don't handle conflicts with type and object names for things like autocomplete). Same issue happens in a bunch of other functions as well.
if (auto const *Stmt = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor))) { | ||
return Stmt->getNumClobbers(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (auto const *Stmt = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor))) { | |
return Stmt->getNumClobbers(); | |
} | |
if (auto const *Stmt = dyn_cast_or_null<GCCAsmStmt>(getCursorStmt(Cursor))) | |
return Stmt->getNumClobbers(); |
I'll stop commenting on this -- basically, single-line substatements don't get curly braces per our (odd) coding convention.
Discourse link
We strive for exposing such information using existing stable ABIs. In doing so, queries are limited to what the original source holds or the LLVM IR
asm
block would expose in connection with attributes that the queries are concerned.These APIs opens new opportunities for
rust-bindgen
to translate inline assemblies in reasonably cases into Rust inline assembly blocks, which would further aid better interoperability with other existing code.