]> granicus.if.org Git - clang/commitdiff
CodeGen: implement __emit intrinsic
authorSaleem Abdulrasool <compnerd@compnerd.org>
Wed, 17 Dec 2014 17:52:30 +0000 (17:52 +0000)
committerSaleem Abdulrasool <compnerd@compnerd.org>
Wed, 17 Dec 2014 17:52:30 +0000 (17:52 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@224438 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/BuiltinsARM.def
lib/CodeGen/CGBuiltin.cpp
test/CodeGen/builtins-arm-msvc-compat-error.c [new file with mode: 0644]
test/CodeGen/builtins-arm-msvc-compat-only.c [new file with mode: 0644]

index 1f2f9a3840c32f639686d70f11bcfbe90daa8f86..9091ad4d7581cc9ccb484145be11d250d37131be 100644 (file)
@@ -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)
index 155545d4c94bfeb94a7909545708a604ab3a1b08..fca60d50c5623bad647cd7bcfbd498103d48981a 100644 (file)
@@ -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/test/CodeGen/builtins-arm-msvc-compat-error.c b/test/CodeGen/builtins-arm-msvc-compat-error.c
new file mode 100644 (file)
index 0000000..29469de
--- /dev/null
@@ -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/test/CodeGen/builtins-arm-msvc-compat-only.c b/test/CodeGen/builtins-arm-msvc-compat-only.c
new file mode 100644 (file)
index 0000000..db82ca4
--- /dev/null
@@ -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", ""()
+