Index: clang/lib/Basic/Targets/AVR.h =================================================================== --- clang/lib/Basic/Targets/AVR.h +++ clang/lib/Basic/Targets/AVR.h @@ -170,6 +170,7 @@ bool isValidCPUName(StringRef Name) const override; void fillValidCPUList(SmallVectorImpl &Values) const override; bool setCPU(const std::string &Name) override; + std::optional handleAsmEscapedChar(char EscChar) const override; StringRef getABI() const override { return ABI; } protected: Index: clang/lib/Basic/Targets/AVR.cpp =================================================================== --- clang/lib/Basic/Targets/AVR.cpp +++ clang/lib/Basic/Targets/AVR.cpp @@ -428,6 +428,23 @@ return false; } +std::optional +AVRTargetInfo::handleAsmEscapedChar(char EscChar) const { + switch (EscChar) { + // "%~" represents for 'r' depends on the device has long jump/call. + case '~': + return ArchHasJMPCALL(Arch) ? std::string("") : std::string(1, 'r'); + + // "%!" represents for 'e' depends on the PC register size. + case '!': + return ArchHas3BytePC(Arch) ? std::string(1, 'e') : std::string(""); + + // This is an invalid escape character for AVR. + default: + return std::nullopt; + } +} + void AVRTargetInfo::getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { Builder.defineMacro("AVR"); Index: clang/test/CodeGen/avr/avr-inline-asm-constraints.c =================================================================== --- clang/test/CodeGen/avr/avr-inline-asm-constraints.c +++ clang/test/CodeGen/avr/avr-inline-asm-constraints.c @@ -1,5 +1,10 @@ // REQUIRES: avr-registered-target -// RUN: %clang_cc1 -triple avr-unknown-unknown -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -x c -triple avr -target-cpu at90s8515 -emit-llvm -o - %s \ +// RUN: | FileCheck --check-prefixes=CHECK,AVR25 %s +// RUN: %clang_cc1 -x c -triple avr -target-cpu atmega328 -emit-llvm -o - %s \ +// RUN: | FileCheck --check-prefixes=CHECK,AVR51 %s +// RUN: %clang_cc1 -x c -triple avr -target-cpu atmega2560 -emit-llvm -o - %s \ +// RUN: | FileCheck --check-prefixes=CHECK,AVR6 %s int data; @@ -122,3 +127,23 @@ // CHECK: call addrspace(0) i16 asm "subi r30, $0", "=ra"() asm("subi r30, %0" : "=ra"(data)); } + +void escapeChar(void) { + asm("_foo:"); + // AVR25: call addrspace(0) void asm sideeffect "rcall _foo" + // AVR51: call addrspace(0) void asm sideeffect "call _foo" + // AVR6: call addrspace(0) void asm sideeffect "call _foo" + asm("%~call _foo" ::); + // AVR25: call addrspace(0) void asm sideeffect "rjmp _foo" + // AVR51: call addrspace(0) void asm sideeffect "jmp _foo" + // AVR6: call addrspace(0) void asm sideeffect "jmp _foo" + asm("%~jmp _foo" ::); + // AVR25: call addrspace(0) void asm sideeffect "icall" + // AVR51: call addrspace(0) void asm sideeffect "icall" + // AVR6: call addrspace(0) void asm sideeffect "eicall" + asm("%!icall" ::); + // AVR25: call addrspace(0) void asm sideeffect "ijmp" + // AVR51: call addrspace(0) void asm sideeffect "ijmp" + // AVR6: call addrspace(0) void asm sideeffect "eijmp" + asm("%!ijmp" ::); +}