llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-codegen Author: Dakkshesh (beakthoven) <details> <summary>Changes</summary> Add builtins for nop, sei, cli, sleep, wdr, swap, fmul/fmuls/fmulsu, delay_cycles, and nops. The builtins lower to their llvm.avr.* intrinsics, fmul variants use inline asm, anddelay_cycles emits inline-asm delay loops. depends on: https://github.com/llvm/llvm-project/pull/203212 TODO: **__builtin_avr_insert_bits __builtin_avr_flash_segment** --- Patch is 22.94 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/203214.diff 12 Files Affected: - (added) clang/include/clang/Basic/BuiltinsAVR.def (+39) - (modified) clang/include/clang/Basic/TargetBuiltins.h (+11-1) - (modified) clang/lib/Basic/Targets/AVR.cpp (+37-3) - (modified) clang/lib/Basic/Targets/AVR.h (+1-3) - (modified) clang/lib/CodeGen/CGBuiltin.cpp (+2) - (modified) clang/lib/CodeGen/CMakeLists.txt (+1) - (modified) clang/lib/CodeGen/CodeGenFunction.h (+1) - (added) clang/lib/CodeGen/TargetBuiltins/AVR.cpp (+247) - (modified) clang/lib/Sema/SemaChecking.cpp (+22) - (modified) clang/test/CodeGen/avr/avr-builtins.c (+91) - (added) clang/test/Preprocessor/avr-builtins.c (+13) - (added) clang/test/Sema/avr-builtins.c (+19) ``````````diff diff --git a/clang/include/clang/Basic/BuiltinsAVR.def b/clang/include/clang/Basic/BuiltinsAVR.def new file mode 100644 index 0000000000000..c0d883c39d3bc --- /dev/null +++ b/clang/include/clang/Basic/BuiltinsAVR.def @@ -0,0 +1,39 @@ +//===--- BuiltinsAVR.def - AVR Builtin function database --------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the AVR-specific builtin function database. Users of +// this file must define the BUILTIN macro to make use of this information. +// +//===----------------------------------------------------------------------===// + +// Void instructions +BUILTIN(__builtin_avr_nop, "v", "n") +BUILTIN(__builtin_avr_sei, "v", "n") +BUILTIN(__builtin_avr_cli, "v", "n") +BUILTIN(__builtin_avr_sleep, "v", "n") +BUILTIN(__builtin_avr_wdr, "v", "n") + +// Swap nibbles +BUILTIN(__builtin_avr_swap, "UcUc", "nc") + +// Fractional multiply +BUILTIN(__builtin_avr_fmul, "UiUcUc", "nc") +BUILTIN(__builtin_avr_fmuls, "SiScSc", "nc") +BUILTIN(__builtin_avr_fmulsu, "SiScUc", "nc") + +// Delay cycles +BUILTIN(__builtin_avr_delay_cycles, "vULi", "n") + +// Emit N NOP instructions +BUILTIN(__builtin_avr_nops, "vUi", "n") + +// TODO builtins +// BUILTIN(__builtin_avr_insert_bits, "UcULiUcUc", "nc") +// BUILTIN(__builtin_avr_flash_segment, "c*v", "n") + +#undef BUILTIN diff --git a/clang/include/clang/Basic/TargetBuiltins.h b/clang/include/clang/Basic/TargetBuiltins.h index 9b4613c853206..2c6d007e45ead 100644 --- a/clang/include/clang/Basic/TargetBuiltins.h +++ b/clang/include/clang/Basic/TargetBuiltins.h @@ -476,12 +476,22 @@ namespace clang { }; } + /// AVR builtins + namespace AVR { + enum { + LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1, +#define BUILTIN(ID, TYPE, ATTRS) BI##ID, +#include "clang/Basic/BuiltinsAVR.def" + LastTSBuiltin + }; + } + static constexpr uint64_t LargestBuiltinID = std::max<uint64_t>( {ARM::LastTSBuiltin, AArch64::LastTSBuiltin, BPF::LastTSBuiltin, PPC::LastTSBuiltin, NVPTX::LastTSBuiltin, AMDGPU::LastTSBuiltin, X86::LastTSBuiltin, VE::LastTSBuiltin, RISCV::LastTSBuiltin, Hexagon::LastTSBuiltin, Mips::LastTSBuiltin, XCore::LastTSBuiltin, - SystemZ::LastTSBuiltin, WebAssembly::LastTSBuiltin}); + SystemZ::LastTSBuiltin, WebAssembly::LastTSBuiltin, AVR::LastTSBuiltin}); } // end namespace clang. diff --git a/clang/lib/Basic/Targets/AVR.cpp b/clang/lib/Basic/Targets/AVR.cpp index 75144099b2bdd..a04fea33997a7 100644 --- a/clang/lib/Basic/Targets/AVR.cpp +++ b/clang/lib/Basic/Targets/AVR.cpp @@ -11,12 +11,28 @@ //===----------------------------------------------------------------------===// #include "AVR.h" +#include "clang/Basic/Builtins.h" #include "clang/Basic/MacroBuilder.h" +#include "clang/Basic/TargetBuiltins.h" #include "llvm/ADT/StringSwitch.h" using namespace clang; using namespace clang::targets; +static constexpr int NumBuiltins = AVR::LastTSBuiltin - Builtin::FirstTSBuiltin; + +static constexpr llvm::StringTable BuiltinStrings = + CLANG_BUILTIN_STR_TABLE_START +#define BUILTIN CLANG_BUILTIN_STR_TABLE +#include "clang/Basic/BuiltinsAVR.def" + ; + +static constexpr auto BuiltinInfos = Builtin::MakeInfos<NumBuiltins>({ +#define BUILTIN CLANG_BUILTIN_ENTRY +#define LIBBUILTIN CLANG_LIBBUILTIN_ENTRY +#include "clang/Basic/BuiltinsAVR.def" +}); + namespace clang { namespace targets { @@ -471,8 +487,13 @@ static bool ArchHas3BytePC(StringRef Arch) { } bool AVRTargetInfo::isValidCPUName(StringRef Name) const { - return llvm::any_of( - AVRMcus, [&](const MCUInfo &Info) { return Info.Name == Name; }); + return llvm::any_of(AVRMcus, + [&](const MCUInfo &Info) { return Info.Name == Name; }); +} + +llvm::SmallVector<Builtin::InfosShard> +AVRTargetInfo::getTargetBuiltins() const { + return {{&BuiltinStrings, BuiltinInfos}}; } void AVRTargetInfo::fillValidCPUList(SmallVectorImpl<StringRef> &Values) const { @@ -524,7 +545,7 @@ void AVRTargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__AVR_TINY__", "1"); if (DefineName.size() != 0) - Builder.defineMacro(DefineName); + Builder.defineMacro(DefineName); Builder.defineMacro("__AVR_ARCH__", Arch); @@ -564,4 +585,17 @@ void AVRTargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__flash4", "__attribute__((__address_space__(5)))"); if (NumFlashBanks >= 6) Builder.defineMacro("__flash5", "__attribute__((__address_space__(6)))"); + + // Define macros for builtins + Builder.defineMacro("__BUILTIN_AVR_NOP", "1"); + Builder.defineMacro("__BUILTIN_AVR_SEI", "1"); + Builder.defineMacro("__BUILTIN_AVR_CLI", "1"); + Builder.defineMacro("__BUILTIN_AVR_WDR", "1"); + Builder.defineMacro("__BUILTIN_AVR_SLEEP", "1"); + Builder.defineMacro("__BUILTIN_AVR_SWAP", "1"); + Builder.defineMacro("__BUILTIN_AVR_FMUL", "1"); + Builder.defineMacro("__BUILTIN_AVR_FMULS", "1"); + Builder.defineMacro("__BUILTIN_AVR_FMULSU", "1"); + Builder.defineMacro("__BUILTIN_AVR_DELAY_CYCLES", "1"); + Builder.defineMacro("__BUILTIN_AVR_NOPS", "1"); } diff --git a/clang/lib/Basic/Targets/AVR.h b/clang/lib/Basic/Targets/AVR.h index f6fed1d97c9ea..211cf90fe9fb2 100644 --- a/clang/lib/Basic/Targets/AVR.h +++ b/clang/lib/Basic/Targets/AVR.h @@ -63,9 +63,7 @@ class LLVM_LIBRARY_VISIBILITY AVRTargetInfo : public TargetInfo { void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; - llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override { - return {}; - } + llvm::SmallVector<Builtin::InfosShard> getTargetBuiltins() const override; bool allowsLargerPreferedTypeAlignment() const override { return false; } diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 682b125890fe1..509ab4245d99a 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -133,6 +133,8 @@ static Value *EmitTargetArchBuiltinExpr(CodeGenFunction *CGF, [[fallthrough]]; case llvm::Triple::spirv: return CGF->EmitSPIRVBuiltinExpr(BuiltinID, E); + case llvm::Triple::avr: + return CGF->EmitAVRBuiltinExpr(BuiltinID, E); default: return nullptr; } diff --git a/clang/lib/CodeGen/CMakeLists.txt b/clang/lib/CodeGen/CMakeLists.txt index 75b2f5826f863..479967ee0a230 100644 --- a/clang/lib/CodeGen/CMakeLists.txt +++ b/clang/lib/CodeGen/CMakeLists.txt @@ -122,6 +122,7 @@ add_clang_library(clangCodeGen SanitizerMetadata.cpp SwiftCallingConv.cpp TargetBuiltins/ARM.cpp + TargetBuiltins/AVR.cpp TargetBuiltins/AMDGPU.cpp TargetBuiltins/DirectX.cpp TargetBuiltins/Hexagon.cpp diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 6bb9f285ebcfd..e1af1d281764a 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -4965,6 +4965,7 @@ class CodeGenFunction : public CodeGenTypeCache { llvm::Value *EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, const CallExpr *E); llvm::Value *EmitHexagonBuiltinExpr(unsigned BuiltinID, const CallExpr *E); + llvm::Value *EmitAVRBuiltinExpr(unsigned BuiltinID, const CallExpr *E); llvm::Value *EmitRISCVBuiltinExpr(unsigned BuiltinID, const CallExpr *E, ReturnValueSlot ReturnValue); diff --git a/clang/lib/CodeGen/TargetBuiltins/AVR.cpp b/clang/lib/CodeGen/TargetBuiltins/AVR.cpp new file mode 100644 index 0000000000000..3f95806585206 --- /dev/null +++ b/clang/lib/CodeGen/TargetBuiltins/AVR.cpp @@ -0,0 +1,247 @@ +//===------ AVR.cpp - Emit LLVM Code for AVR builtins ---------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This contains code to emit Builtin calls as LLVM code. +// +//===----------------------------------------------------------------------===// + +#include "CGBuiltin.h" +#include "clang/Basic/TargetBuiltins.h" +#include "llvm/IR/InlineAsm.h" +#include "llvm/IR/IntrinsicsAVR.h" + +using namespace clang; +using namespace CodeGen; +using namespace llvm; + +/// Emit an inline-asm-based fractional multiply (fmul/fmuls/fmulsu). +/// All three variants share the same shape: two i8 inputs → one i16 output, +/// with the result collected from R1:R0 via movw, then R1 cleared. +static Value *EmitAVRFMulInlineAsm(CodeGenFunction &CGF, const CallExpr *E, + const char *AsmInsn) { + Value *Arg0 = CGF.EmitScalarExpr(E->getArg(0)); + Value *Arg1 = CGF.EmitScalarExpr(E->getArg(1)); + llvm::LLVMContext &Ctx = CGF.getLLVMContext(); + llvm::Type *ResTy = llvm::Type::getInt16Ty(Ctx); + llvm::Type *ArgTy = llvm::Type::getInt8Ty(Ctx); + llvm::FunctionType *FTy = + llvm::FunctionType::get(ResTy, {ArgTy, ArgTy}, false); + + // Build the asm string: "<insn> $1, $2\n\tmovw $0, r0\n\tclr r1" + std::string Asm = std::string(AsmInsn) + " $1, $2\n\tmovw $0, r0\n\tclr r1"; + llvm::InlineAsm *IA = + llvm::InlineAsm::get(FTy, Asm, "=r,a,a,~{r0},~{r1}", true); + return CGF.Builder.CreateCall(IA, {Arg0, Arg1}); +} + +/// Emit __builtin_avr_delay_cycles(N). +/// +/// Generates an optimal sequence of inline assembly delay loops and NOPs +/// to consume exactly N clock cycles. +/// +/// The decomposed N into a sum of contributions from nested loops +/// of decreasing register width, then fills the remainder with rjmp/.+0 +/// (2 cycles) and nop (1 cycle). +/// +/// Loop types: +/// 4-byte loop: ldi×4 + (subi + sbci×3 + brne) = 9 setup + 6/iter +/// 3-byte loop: ldi×3 + (subi + sbci×2 + brne) = 7 setup + 5/iter +/// 2-byte loop: ldi×2 + (sbiw + brne) = 5 setup + 4/iter +/// 1-byte loop: ldi + (dec + brne) = 3/iter (no setup overhead) +static Value *EmitAVRDelayLoops(CodeGenFunction &CGF, uint32_t Cycles) { + if (Cycles == 0) + return nullptr; + + std::string Asm; + std::string Clobbers; + unsigned ClobberIdx = 0; + unsigned LabelIdx = 1; + + auto AddClobber = [&](unsigned Reg) { + if (!Clobbers.empty()) + Clobbers += ","; + Clobbers += "~{r" + std::to_string(Reg) + "}"; + }; + + // 4-byte loop: 9 + 6*(loop_count-1) cycles + // ldi×4 + (subi + sbci×3 + brne) per iteration + if (Cycles >= 83886082u) { + uint32_t LoopCount = ((Cycles - 9) / 6) + 1; + uint32_t Used = ((LoopCount - 1) * 6) + 9; + unsigned Base = 16 + ClobberIdx; + std::string L = std::to_string(LabelIdx++); + Asm += "ldi r" + std::to_string(Base) + ", lo8(" + + std::to_string(LoopCount) + ")\n\t"; + Asm += "ldi r" + std::to_string(Base + 1) + ", hi8(" + + std::to_string(LoopCount) + ")\n\t"; + Asm += "ldi r" + std::to_string(Base + 2) + ", hlo8(" + + std::to_string(LoopCount) + ")\n\t"; + Asm += "ldi r" + std::to_string(Base + 3) + ", hhi8(" + + std::to_string(LoopCount) + ")\n\t"; + Asm += L + ": subi r" + std::to_string(Base) + ", 1\n\t"; + Asm += "sbci r" + std::to_string(Base + 1) + ", 0\n\t"; + Asm += "sbci r" + std::to_string(Base + 2) + ", 0\n\t"; + Asm += "sbci r" + std::to_string(Base + 3) + ", 0\n\t"; + Asm += "brne " + L + "b\n\t"; + AddClobber(Base); + AddClobber(Base + 1); + AddClobber(Base + 2); + AddClobber(Base + 3); + ClobberIdx += 4; + Cycles -= Used; + } + + // 3-byte loop: 7 + 5*(loop_count-1) cycles + // ldi×3 + (subi + sbci×2 + brne) per iteration + if (Cycles >= 262145u) { + uint32_t LoopCount = ((Cycles - 7) / 5) + 1; + if (LoopCount > 0xFFFFFFu) + LoopCount = 0xFFFFFFu; + uint32_t Used = ((LoopCount - 1) * 5) + 7; + unsigned Base = 16 + ClobberIdx; + std::string L = std::to_string(LabelIdx++); + Asm += "ldi r" + std::to_string(Base) + ", lo8(" + + std::to_string(LoopCount) + ")\n\t"; + Asm += "ldi r" + std::to_string(Base + 1) + ", hi8(" + + std::to_string(LoopCount) + ")\n\t"; + Asm += "ldi r" + std::to_string(Base + 2) + ", hlo8(" + + std::to_string(LoopCount) + ")\n\t"; + Asm += L + ": subi r" + std::to_string(Base) + ", 1\n\t"; + Asm += "sbci r" + std::to_string(Base + 1) + ", 0\n\t"; + Asm += "sbci r" + std::to_string(Base + 2) + ", 0\n\t"; + Asm += "brne " + L + "b\n\t"; + AddClobber(Base); + AddClobber(Base + 1); + AddClobber(Base + 2); + ClobberIdx += 3; + Cycles -= Used; + } + + // 2-byte loop: 5 + 4*(loop_count-1) cycles + // ldi×2 + (sbiw + brne) per iteration + // sbiw requires an even register in {r24, r26, r28, r30}. + if (Cycles >= 768u) { + uint32_t LoopCount = ((Cycles - 5) / 4) + 1; + if (LoopCount > 0xFFFFu) + LoopCount = 0xFFFFu; + uint32_t Used = ((LoopCount - 1) * 4) + 5; + std::string L = std::to_string(LabelIdx++); + // Use r24:r25 for sbiw (hardcoded per AVR ISA constraint). + Asm += "ldi r24, lo8(" + std::to_string(LoopCount) + ")\n\t"; + Asm += "ldi r25, hi8(" + std::to_string(LoopCount) + ")\n\t"; + Asm += L + ": sbiw r24, 1\n\t"; + Asm += "brne " + L + "b\n\t"; + AddClobber(24); + AddClobber(25); + Cycles -= Used; + } + + // 1-byte loop: 3*loop_count cycles + // ldi + (dec + brne) per iteration + if (Cycles >= 6u) { + uint32_t LoopCount = Cycles / 3; + if (LoopCount > 255u) + LoopCount = 255u; + uint32_t Used = LoopCount * 3; + unsigned Reg = 16 + ClobberIdx; + if (Reg > 31) + Reg = 31; // safety + std::string L = std::to_string(LabelIdx++); + Asm += "ldi r" + std::to_string(Reg) + ", " + std::to_string(LoopCount) + + "\n\t"; + Asm += L + ": dec r" + std::to_string(Reg) + "\n\t"; + Asm += "brne " + L + "b\n\t"; + AddClobber(Reg); + ClobberIdx++; + Cycles -= Used; + } + + // Fill remaining with rjmp .+0 (2 cycles each) + while (Cycles >= 2) { + Asm += "rjmp .+0\n\t"; + Cycles -= 2; + } + + // Final single cycle + if (Cycles == 1) { + Asm += "nop\n\t"; + } + + if (Asm.empty()) + return nullptr; + + // Remove trailing \n\t + if (Asm.size() >= 3 && Asm.substr(Asm.size() - 3) == "\n\t") + Asm.resize(Asm.size() - 3); + + llvm::LLVMContext &Ctx = CGF.getLLVMContext(); + llvm::FunctionType *FTy = + llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx), false); + llvm::InlineAsm *IA = llvm::InlineAsm::get(FTy, Asm, Clobbers, true); + return CGF.Builder.CreateCall(IA); +} + +Value *CodeGenFunction::EmitAVRBuiltinExpr(unsigned BuiltinID, + const CallExpr *E) { + switch (BuiltinID) { + default: + return nullptr; + case AVR::BI__builtin_avr_nop: + return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::avr_nop)); + case AVR::BI__builtin_avr_sei: + return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::avr_sei)); + case AVR::BI__builtin_avr_cli: + return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::avr_cli)); + case AVR::BI__builtin_avr_sleep: + return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::avr_sleep)); + case AVR::BI__builtin_avr_wdr: + return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::avr_wdr)); + case AVR::BI__builtin_avr_swap: { + Value *Arg0 = EmitScalarExpr(E->getArg(0)); + return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::avr_swap), Arg0); + } + case AVR::BI__builtin_avr_fmul: + return EmitAVRFMulInlineAsm(*this, E, "fmul"); + case AVR::BI__builtin_avr_fmuls: + return EmitAVRFMulInlineAsm(*this, E, "fmuls"); + case AVR::BI__builtin_avr_fmulsu: + return EmitAVRFMulInlineAsm(*this, E, "fmulsu"); + + case AVR::BI__builtin_avr_delay_cycles: { + // Argument is validated as a compile time constant in Sema. + Expr::EvalResult Result; + E->getArg(0)->EvaluateAsInt(Result, getContext()); + uint32_t Cycles = static_cast<uint32_t>(Result.Val.getInt().getZExtValue()); + if (Cycles == 0) { + // Nothing to emit. + llvm::FunctionType *FTy = llvm::FunctionType::get( + llvm::Type::getVoidTy(getLLVMContext()), false); + return Builder.CreateCall(llvm::InlineAsm::get(FTy, "", "", true)); + } + return EmitAVRDelayLoops(*this, Cycles); + } + + case AVR::BI__builtin_avr_nops: { + // Argument is validated as a compile-time constant in Sema. + Expr::EvalResult Result; + E->getArg(0)->EvaluateAsInt(Result, getContext()); + uint32_t N = static_cast<uint32_t>(Result.Val.getInt().getZExtValue()); + if (N == 0) { + // Nothing to emit. + llvm::FunctionType *FTy = llvm::FunctionType::get( + llvm::Type::getVoidTy(getLLVMContext()), false); + return Builder.CreateCall(llvm::InlineAsm::get(FTy, "", "", true)); + } + llvm::Function *NopFn = CGM.getIntrinsic(Intrinsic::avr_nop); + Value *Last = nullptr; + for (uint32_t I = 0; I < N; ++I) + Last = Builder.CreateCall(NopFn); + return Last; + } + } +} diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index b8a3f48a32f24..be634f64807c7 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -53,6 +53,7 @@ #include "clang/Basic/SourceManager.h" #include "clang/Basic/Specifiers.h" #include "clang/Basic/SyncScope.h" +#include "clang/Basic/TargetBuiltins.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/TypeTraits.h" #include "clang/Lex/Lexer.h" // TODO: Extract static functions to fix layering. @@ -2124,6 +2125,27 @@ bool Sema::CheckTSBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, // Some builtins don't require additional checking, so just consider these // acceptable. return false; + case llvm::Triple::avr: { + switch (BuiltinID) { + default: + return false; + case AVR::BI__builtin_avr_delay_cycles: { + llvm::APSInt Result; + if (BuiltinConstantArg(TheCall, 0, Result)) + return true; + if (Result.isNegative()) + return Diag(TheCall->getArg(0)->getBeginLoc(), + diag::err_argument_invalid_range) + << toString(Result, 10) << (unsigned)0 << (unsigned)UINT32_MAX + << TheCall->getArg(0)->getSourceRange(); + return false; + } + case AVR::BI__builtin_avr_nops: { + llvm::APSInt Result; + return BuiltinConstantArg(TheCall, 0, Result); + } + } + } case llvm::Triple::arm: case llvm::Triple::armeb: case llvm::Triple::thumb: diff --git a/clang/test/CodeGen/avr/avr-builtins.c b/clang/test/CodeGen/avr/avr-builtins.c index 7c2c424848080..fee56ccadc81e 100644 --- a/clang/test/CodeGen/avr/avr-builtins.c +++ b/clang/test/CodeGen/avr/avr-builtins.c @@ -125,3 +125,94 @@ long double powil(long double x, int y) { // CHECK: define{{.*}} float @powil // CHECK: float @llvm.powi.f32.i16(float %0, i16 %1) + +// CHECK-LABEL: define{{.*}} void @test_nop() +void test_nop(void) { + // CHECK: call{{.*}} void @llvm.avr.nop() + __builtin_avr_nop(); +} + +// CHECK-LABEL: define{{.*}} void @test_sei() +void test_sei(void) { + // CHECK: call{{.*}} void @llvm.avr.sei() + __builtin_avr_sei(); +} + +// CHECK-LABEL: define{{.*}} void @test_cli() +void test_cli(void) { + // CHECK: call{{.*}} void @llvm.avr.cli() + __builtin_avr_cli(); +} + +// CHECK-LABEL: define{{.*}} void @test_sleep() +void test_sleep(void) { + // CHECK: call{{.*}} void @llvm.avr.sleep() + __builtin_avr_sleep(); +} + +// CHECK-LABEL: define{{.*}} void @test_wdr() +void test_wdr(void) { + // CHECK: call{{.*}} void @llvm.avr.wdr() + __builtin_avr_wdr(); +} + +// CHECK-LABEL: define{{.*}} i8 @test_swap +unsigned char test_swap(unsigned char a) { + // CHECK: call{{.*}} i8 @llvm.avr.swap(i8 + return __builtin_avr_swap(a); +} + +// CHECK-LABEL: define{{.*}} i16 @test_fmul +unsigned int test_fmul(unsigned char a, unsigned char b) { + // CHECK: call{{.*}} i16 asm sideeffect "fmul $1, $2 + return __builtin_avr_fmul(a, b); +} + +// CHECK-LABEL: define{{.*}} i16 @test_fmuls +int test_fmuls(signed char a, signed char b) { + // CHECK: call{{.*}} i16 asm sideeffect ... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/203214 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
