Index: include/clang/Basic/Builtins.h =================================================================== --- include/clang/Basic/Builtins.h +++ include/clang/Basic/Builtins.h @@ -29,7 +29,7 @@ class ASTContext; class QualType; class LangOptions; - + enum LanguageID { GNU_LANG = 0x1, // builtin requires GNU mode. C_LANG = 0x2, // builtin for c only. @@ -40,7 +40,7 @@ ALL_GNU_LANGUAGES = ALL_LANGUAGES | GNU_LANG, // builtin requires GNU mode. ALL_MS_LANGUAGES = ALL_LANGUAGES | MS_LANG // builtin requires MS mode. }; - + namespace Builtin { enum ID { NotBuiltin = 0, // This is not a builtin function. Index: include/clang/Basic/BuiltinsARM.def =================================================================== --- include/clang/Basic/BuiltinsARM.def +++ include/clang/Basic/BuiltinsARM.def @@ -85,6 +85,8 @@ BUILTIN(__builtin_arm_prefetch, "vvC*UiUi", "nc") // MSVC +LANGBUILTIN(__emit, "vIUiC", "", ALL_MS_LANGUAGES) + LANGBUILTIN(__yield, "v", "", ALL_MS_LANGUAGES) LANGBUILTIN(__wfe, "v", "", ALL_MS_LANGUAGES) LANGBUILTIN(__wfi, "v", "", ALL_MS_LANGUAGES) Index: lib/CodeGen/CGBuiltin.cpp =================================================================== --- lib/CodeGen/CGBuiltin.cpp +++ lib/CodeGen/CGBuiltin.cpp @@ -20,7 +20,9 @@ #include "clang/Basic/TargetBuiltins.h" #include "clang/Basic/TargetInfo.h" #include "clang/CodeGen/CGFunctionInfo.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/InlineAsm.h" #include "llvm/IR/Intrinsics.h" using namespace clang; @@ -3165,6 +3167,27 @@ if (auto Hint = GetValueForARMHint(BuiltinID)) return Hint; + if (BuiltinID == ARM::BI__emit) { + bool IsThumb = getTarget().getTriple().getArch() == llvm::Triple::thumb; + llvm::FunctionType *FTy = + llvm::FunctionType::get(VoidTy, /*Variadic=*/false); + + APSInt Value; + if (!E->getArg(0)->EvaluateAsInt(Value, CGM.getContext())) + llvm_unreachable("Sema will ensure that the parameter is constant"); + + uint64_t ZExtValue = + Builder.getInt(Value.zextOrTrunc(IsThumb ? 16 : 32))->getZExtValue(); + + llvm::InlineAsm *Emit = + IsThumb ? InlineAsm::get(FTy, ".inst.n 0x" + utohexstr(ZExtValue), "", + /*SideEffects=*/true) + : InlineAsm::get(FTy, ".inst 0x" + utohexstr(ZExtValue), "", + /*SideEffects=*/true); + + return Builder.CreateCall(Emit); + } + if (BuiltinID == ARM::BI__builtin_arm_dbg) { Value *Option = EmitScalarExpr(E->getArg(0)); return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::arm_dbg), Option); Index: test/CodeGen/builtins-arm-msvc-compat-error.c =================================================================== --- /dev/null +++ test/CodeGen/builtins-arm-msvc-compat-error.c @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -triple thumbv7-windows -fms-compatibility -verify %s + +void emit_error(unsigned int opcode) { + __emit(opcode); // expected-error {{argument to '__emit' must be a constant integer}} +} + Index: test/CodeGen/builtins-arm-msvc-compat-only.c =================================================================== --- /dev/null +++ test/CodeGen/builtins-arm-msvc-compat-only.c @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -triple thumbv7-windows -fms-compatibility -emit-llvm -o - %s \ +// RUN: | FileCheck %s -check-prefix CHECK-MSVC +// RUN: %clang_cc1 -triple armv7-eabi -emit-llvm %s -o /dev/null 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-EABI +// REQUIRES: arm-registered-target + +void emit() { + __emit(0xdefe); +} + +// CHECK-MSVC: call void asm sideeffect ".inst.n 0xDEFE", ""() +// CHECK-EABI: warning: implicit declaration of function '__emit' is invalid in C99 + +void emit_truncated() { + __emit(0x11110000); // movs r0, r0 +} + +// CHECK-MSVC: call void asm sideeffect ".inst.n 0x0", ""() +