Index: include/clang/Basic/Builtins.h =================================================================== --- include/clang/Basic/Builtins.h +++ include/clang/Basic/Builtins.h @@ -29,18 +29,19 @@ class ASTContext; class QualType; class LangOptions; - + enum LanguageID { - GNU_LANG = 0x1, // builtin requires GNU mode. - C_LANG = 0x2, // builtin for c only. - CXX_LANG = 0x4, // builtin for cplusplus only. - OBJC_LANG = 0x8, // builtin for objective-c and objective-c++ - MS_LANG = 0x10, // builtin requires MS mode. + GNU_LANG = 0x1, // builtin requires GNU mode. + C_LANG = 0x2, // builtin for c only. + CXX_LANG = 0x4, // builtin for cplusplus only. + OBJC_LANG = 0x8, // builtin for objective-c and objective-c++ + MS_LANG = 0x10, // builtin requires MS extensions. + MS_COMPAT = 0x20, // builtin requires MS compatibility mode. ALL_LANGUAGES = C_LANG | CXX_LANG | OBJC_LANG, // builtin for all languages. 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", "", MS_COMPAT) + LANGBUILTIN(__yield, "v", "", ALL_MS_LANGUAGES) LANGBUILTIN(__wfe, "v", "", ALL_MS_LANGUAGES) LANGBUILTIN(__wfi, "v", "", ALL_MS_LANGUAGES) Index: lib/Basic/Builtins.cpp =================================================================== --- lib/Basic/Builtins.cpp +++ lib/Basic/Builtins.cpp @@ -57,10 +57,13 @@ (BuiltinInfo.builtin_lang & GNU_LANG); bool MSModeUnsupported = !LangOpts.MicrosoftExt && (BuiltinInfo.builtin_lang & MS_LANG); + bool MSCompatUnsupported = !LangOpts.MSVCCompat && + (BuiltinInfo.builtin_lang & MS_COMPAT); bool ObjCUnsupported = !LangOpts.ObjC1 && BuiltinInfo.builtin_lang == OBJC_LANG; return !BuiltinsUnsupported && !MathBuiltinsUnsupported && - !GnuModeUnsupported && !MSModeUnsupported && !ObjCUnsupported; + !GnuModeUnsupported && !MSModeUnsupported && !MSCompatUnsupported && + !ObjCUnsupported; } /// InitializeBuiltins - Mark the identifiers for all the builtins with their 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,26 @@ if (auto Hint = GetValueForARMHint(BuiltinID)) return Hint; + if (BuiltinID == ARM::BI__emit) { + assert(getTarget().getTriple().isOSWindows() && + "__emit is only supported on Windows on ARM"); + assert(getTarget().getTriple().getArch() == llvm::Triple::thumb && + "Windows on ARM only supports thumb"); + + llvm::FunctionType *FTy = + llvm::FunctionType::get(VoidTy, /*Variadic=*/false); + + APSInt Value; + if (!E->getArg(0)->EvaluateAsInt(Value, CGM.getContext())) + report_fatal_error("constant value required!"); + uint64_t ZExtValue = Builder.getInt(Value)->getZExtValue(); + + llvm::InlineAsm *Emit = + InlineAsm::get(FTy, ".inst.n 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,11 @@ +// RUN: not %clang_cc1 -triple thumbv7-windows -fms-compatibility -emit-llvm -o /dev/null %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK + +void emit_error(unsigned int opcode) { + __emit(opcode); +} + +// CHECK: error: argument to '__emit' must be a constant integer +// CHECK: __emit(opcode) +// CHECK: ^ ~~~~~~ + Index: test/CodeGen/builtins-arm-msvc-compat-only.c =================================================================== --- /dev/null +++ test/CodeGen/builtins-arm-msvc-compat-only.c @@ -0,0 +1,13 @@ +// 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 +