Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion clang/lib/Sema/SemaStmtAsm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -664,11 +664,16 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
SmallerValueMentioned |= OutSize < InSize;
}

// If the input is an integer register while the output is floating point,
// or vice-versa, there is no way they can work together.
bool FPTiedToInt = (InputDomain == AD_FP) ^ (OutputDomain == AD_FP);

// If the smaller value wasn't mentioned in the asm string, and if the
// output was a register, just extend the shorter one to the size of the
// larger one.
if (!SmallerValueMentioned && InputDomain != AD_Other &&
if (!SmallerValueMentioned && !FPTiedToInt && InputDomain != AD_Other &&
OutputConstraintInfos[TiedTo].allowsRegister()) {

// FIXME: GCC supports the OutSize to be 128 at maximum. Currently codegen
// crash when the size larger than the register size. So we limit it here.
if (OutTy->isStructureType() &&
Expand Down
21 changes: 21 additions & 0 deletions clang/test/Sema/asm.c
Original file line number Diff line number Diff line change
Expand Up @@ -365,3 +365,24 @@ void test19(long long x)
// FIXME: This case should be supported by codegen, but it fails now.
asm ("" : "=rm" (x): "0" (e)); // expected-error {{unsupported inline asm: input with type 'st_size128' (aka 'struct _st_size128') matching output with type 'long long'}}
}

typedef int int2 __attribute__((ext_vector_type(2)));

// GH118892
void test20(char x) {
double d;
float f;

asm ("fabs" : "=t" (d): "0" (x)); // expected-error {{unsupported inline asm: input with type 'char' matching output with type 'double'}}
asm ("fabs" : "=t" (x): "0" (d)); // expected-error {{unsupported inline asm: input with type 'double' matching output with type 'char'}}
asm ("fabs" : "=t" (f): "0" (d)); // no-error
asm ("fabs" : "=t" (d): "0" (f)); // no-error

st_size64 a;
asm ("fabs" : "=t" (d): "0" (a)); // expected-error {{unsupported inline asm: input with type 'st_size64' (aka 'struct _st_size64') matching output with type 'double'}}
asm ("fabs" : "=t" (a): "0" (d)); // expected-error {{unsupported inline asm: input with type 'double' matching output with type 'st_size64' (aka 'struct _st_size64')}}

int2 v;
asm ("fabs" : "=t" (d): "0" (v)); // expected-error {{unsupported inline asm: input with type 'int2' (vector of 2 'int' values) matching output with type 'double'}}
asm ("fabs" : "=t" (v): "0" (d)); // expected-error {{unsupported inline asm: input with type 'double' matching output with type 'int2' (vector of 2 'int' values)}}
}
Copy link
Contributor

@arsenm arsenm Dec 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test both directions. And what about other kinds of types, like vectors

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about vectors (is it std::vector)? I'll add test against structs and floats.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I mean like int2 typedef int int2 __attribute__((ext_vector_type(2)))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.

Loading