From 86b881c63e489256e779ad7d72aa8aac17fa3d06 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Wed, 17 Dec 2014 17:52:30 +0000 Subject: [PATCH] CodeGen: implement __emit intrinsic For MSVC compatibility, add the `__emit' builtin. This is used in the Windows SDK headers, and must therefore be implemented as a builtin rather than an intrinsic. The `__emit' builtin provides a mechanism to emit a 16-bit opcode instruction into the stream. The value must be a compile time constant expression. No guarantees are made about the CPU and memory states after the execution of the instruction. Due to the unchecked nature of the builtin, only support this on Windows on ARM. llvm-svn: 224438 --- clang/include/clang/Basic/BuiltinsARM.def | 2 ++ clang/lib/CodeGen/CGBuiltin.cpp | 22 ++++++++++++++++++++++ .../test/CodeGen/builtins-arm-msvc-compat-error.c | 6 ++++++ clang/test/CodeGen/builtins-arm-msvc-compat-only.c | 19 +++++++++++++++++++ 4 files changed, 49 insertions(+) create mode 100644 clang/test/CodeGen/builtins-arm-msvc-compat-error.c create mode 100644 clang/test/CodeGen/builtins-arm-msvc-compat-only.c diff --git a/clang/include/clang/Basic/BuiltinsARM.def b/clang/include/clang/Basic/BuiltinsARM.def index 1f2f9a3..9091ad4 100644 --- a/clang/include/clang/Basic/BuiltinsARM.def +++ b/clang/include/clang/Basic/BuiltinsARM.def @@ -85,6 +85,8 @@ BUILTIN(__builtin_arm_isb, "vUi", "nc") 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) diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 155545d..fca60d5 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/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 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, 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 = 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); diff --git a/clang/test/CodeGen/builtins-arm-msvc-compat-error.c b/clang/test/CodeGen/builtins-arm-msvc-compat-error.c new file mode 100644 index 0000000..29469de --- /dev/null +++ b/clang/test/CodeGen/builtins-arm-msvc-compat-error.c @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -triple thumbv7-windows -fms-extensions -verify %s + +void emit_error(unsigned int opcode) { + __emit(opcode); // expected-error {{argument to '__emit' must be a constant integer}} +} + diff --git a/clang/test/CodeGen/builtins-arm-msvc-compat-only.c b/clang/test/CodeGen/builtins-arm-msvc-compat-only.c new file mode 100644 index 0000000..db82ca4 --- /dev/null +++ b/clang/test/CodeGen/builtins-arm-msvc-compat-only.c @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -triple thumbv7-windows -fms-extensions -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", ""() + -- 2.7.4