Index: include/clang/Basic/BuiltinsARM.def =================================================================== --- include/clang/Basic/BuiltinsARM.def +++ include/clang/Basic/BuiltinsARM.def @@ -65,4 +65,8 @@ BUILTIN(__builtin_arm_dmb, "vUi", "nc") BUILTIN(__builtin_arm_dsb, "vUi", "nc") +// MSVC +BUILTIN(__emit, "vUiC", "") +BUILTIN(__yield, "v", "") + #undef BUILTIN 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; @@ -4326,6 +4328,37 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { + if (BuiltinID == ARM::BI__emit) { + llvm::FunctionType *FTy = + llvm::FunctionType::get(VoidTy, /*Variadic=*/false); + + llvm::APSInt Value; + if (!E->getArg(0)->EvaluateAsInt(Value, CGM.getContext())) + report_fatal_error("constant value required!"); + uint64_t ZExtValue = Builder.getInt(Value)->getZExtValue(); + + std::string inst; + switch (getTarget().getTriple().getArch()) { + default: llvm_unreachable("invalid architecture"); + case llvm::Triple::arm: + inst = ".inst"; + break; + case llvm::Triple::thumb: + inst = ".inst.n"; + break; + } + + llvm::InlineAsm *Emit = + llvm::InlineAsm::get(FTy, inst + " 0x" + llvm::utohexstr(ZExtValue), + "", /*SideEffects=*/true); + return Builder.CreateCall(Emit); + } + + if (BuiltinID == ARM::BI__yield) { + Function *F = CGM.getIntrinsic(Intrinsic::arm_hint); + return Builder.CreateCall(F, llvm::ConstantInt::get(Int32Ty, 1)); + } + if (BuiltinID == ARM::BI__clear_cache) { assert(E->getNumArgs() == 2 && "__clear_cache takes 2 arguments"); const FunctionDecl *FD = E->getDirectCallee(); Index: test/CodeGen/builtins-arm-microsoft.c =================================================================== --- /dev/null +++ test/CodeGen/builtins-arm-microsoft.c @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -triple thumbv7-windows -emit-llvm -o - %s \ +// RUN: | FileCheck %s -check-prefix CHECK-THUMB + +// RUN: %clang_cc1 -triple armv7-eabi -emit-llvm -o - %s \ +// RUN: | FileCheck %s -check-prefix CHECK-ARM + +// REQUIRES: arm-registered-target + +void test_emit_intrinsic() { + __emit(0xdefe); +} + +// CHECK-THUMB: define arm_aapcscc void @test_emit_intrinsic() {{.*}} { +// CHECK-THUMB: entry: +// CHECK-THUMB: call void asm sideeffect ".inst.n 0xDEFE", ""() +// CHECK-THUMB: ret void +// CHECK-THUMB: } + +void test_yield_intrinsic() { + __yield(); +} + +// CHECK-ARM: define void @test_yield_intrinsic() {{.*}} { +// CHECK-ARM: entry: +// CHECK-ARM: call void @llvm.arm.hint(i32 1) +// CHECK-ARM: ret void +// CHECK-ARM: } + +// CHECK-THUMB: define arm_aapcscc void @test_yield_intrinsic() {{.*}} { +// CHECK-THUMB: entry: +// CHECK-THUMB: call void @llvm.arm.hint(i32 1) +// CHECK-THUMB: ret void +// CHECK-THUMB: } +