diff options
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/lib/CodeGen/CGBuiltin.cpp | 104 | ||||
| -rw-r--r-- | clang/test/CodeGen/ms-setjmp.c | 12 | 
2 files changed, 67 insertions, 49 deletions
| diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 5829396b0fe..a09fa7aae5e 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -643,6 +643,52 @@ static RValue EmitBitTestIntrinsic(CodeGenFunction &CGF, unsigned BuiltinID,        ShiftedByte, llvm::ConstantInt::get(CGF.Int8Ty, 1), "bittest.res"));  } +namespace { +enum class MSVCSetJmpKind { +  _setjmpex, +  _setjmp3, +  _setjmp +}; +} + +/// MSVC handles setjmp a bit differently on different platforms. On every +/// architecture except 32-bit x86, the frame address is passed. On x86, extra +/// parameters can be passed as variadic arguments, but we always pass none. +static RValue EmitMSVCRTSetJmp(CodeGenFunction &CGF, MSVCSetJmpKind SJKind, +                               const CallExpr *E) { +  llvm::Value *Arg1 = nullptr; +  llvm::Type *Arg1Ty = nullptr; +  StringRef Name; +  bool IsVarArg = false; +  if (SJKind == MSVCSetJmpKind::_setjmp3) { +    Name = "_setjmp3"; +    Arg1Ty = CGF.Int32Ty; +    Arg1 = llvm::ConstantInt::get(CGF.IntTy, 0); +    IsVarArg = true; +  } else { +    Name = SJKind == MSVCSetJmpKind::_setjmp ? "_setjmp" : "_setjmpex"; +    Arg1Ty = CGF.Int8PtrTy; +    Arg1 = CGF.Builder.CreateCall(CGF.CGM.getIntrinsic(Intrinsic::frameaddress), +                                  llvm::ConstantInt::get(CGF.Int32Ty, 0)); +  } + +  // Mark the call site and declaration with ReturnsTwice. +  llvm::Type *ArgTypes[2] = {CGF.Int8PtrTy, Arg1Ty}; +  llvm::AttributeList ReturnsTwiceAttr = llvm::AttributeList::get( +      CGF.getLLVMContext(), llvm::AttributeList::FunctionIndex, +      llvm::Attribute::ReturnsTwice); +  llvm::Constant *SetJmpFn = CGF.CGM.CreateRuntimeFunction( +      llvm::FunctionType::get(CGF.IntTy, ArgTypes, IsVarArg), Name, +      ReturnsTwiceAttr, /*Local=*/true); + +  llvm::Value *Buf = CGF.Builder.CreateBitOrPointerCast( +      CGF.EmitScalarExpr(E->getArg(0)), CGF.Int8PtrTy); +  llvm::Value *Args[] = {Buf, Arg1}; +  llvm::CallSite CS = CGF.EmitRuntimeCallOrInvoke(SetJmpFn, Args); +  CS.setAttributes(ReturnsTwiceAttr); +  return RValue::get(CS.getInstruction()); +} +  // Many of MSVC builtins are on both x64 and ARM; to avoid repeating code, we  // handle them here.  enum class CodeGenFunction::MSVCIntrin { @@ -2957,59 +3003,19 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,    case Builtin::BI__abnormal_termination:    case Builtin::BI_abnormal_termination:      return RValue::get(EmitSEHAbnormalTermination()); -  case Builtin::BI_setjmpex: { -    if (getTarget().getTriple().isOSMSVCRT()) { -      llvm::Type *ArgTypes[] = {Int8PtrTy, Int8PtrTy}; -      llvm::AttributeList ReturnsTwiceAttr = llvm::AttributeList::get( -          getLLVMContext(), llvm::AttributeList::FunctionIndex, -          llvm::Attribute::ReturnsTwice); -      llvm::Constant *SetJmpEx = CGM.CreateRuntimeFunction( -          llvm::FunctionType::get(IntTy, ArgTypes, /*isVarArg=*/false), -          "_setjmpex", ReturnsTwiceAttr, /*Local=*/true); -      llvm::Value *Buf = Builder.CreateBitOrPointerCast( -          EmitScalarExpr(E->getArg(0)), Int8PtrTy); -      llvm::Value *FrameAddr = -          Builder.CreateCall(CGM.getIntrinsic(Intrinsic::frameaddress), -                             ConstantInt::get(Int32Ty, 0)); -      llvm::Value *Args[] = {Buf, FrameAddr}; -      llvm::CallSite CS = EmitRuntimeCallOrInvoke(SetJmpEx, Args); -      CS.setAttributes(ReturnsTwiceAttr); -      return RValue::get(CS.getInstruction()); -    } +  case Builtin::BI_setjmpex: +    if (getTarget().getTriple().isOSMSVCRT()) +      return EmitMSVCRTSetJmp(*this, MSVCSetJmpKind::_setjmpex, E);      break; -  } -  case Builtin::BI_setjmp: { +  case Builtin::BI_setjmp:      if (getTarget().getTriple().isOSMSVCRT()) { -      llvm::AttributeList ReturnsTwiceAttr = llvm::AttributeList::get( -          getLLVMContext(), llvm::AttributeList::FunctionIndex, -          llvm::Attribute::ReturnsTwice); -      llvm::Value *Buf = Builder.CreateBitOrPointerCast( -          EmitScalarExpr(E->getArg(0)), Int8PtrTy); -      llvm::CallSite CS; -      if (getTarget().getTriple().getArch() == llvm::Triple::x86) { -        llvm::Type *ArgTypes[] = {Int8PtrTy, IntTy}; -        llvm::Constant *SetJmp3 = CGM.CreateRuntimeFunction( -            llvm::FunctionType::get(IntTy, ArgTypes, /*isVarArg=*/true), -            "_setjmp3", ReturnsTwiceAttr, /*Local=*/true); -        llvm::Value *Count = ConstantInt::get(IntTy, 0); -        llvm::Value *Args[] = {Buf, Count}; -        CS = EmitRuntimeCallOrInvoke(SetJmp3, Args); -      } else { -        llvm::Type *ArgTypes[] = {Int8PtrTy, Int8PtrTy}; -        llvm::Constant *SetJmp = CGM.CreateRuntimeFunction( -            llvm::FunctionType::get(IntTy, ArgTypes, /*isVarArg=*/false), -            "_setjmp", ReturnsTwiceAttr, /*Local=*/true); -        llvm::Value *FrameAddr = -            Builder.CreateCall(CGM.getIntrinsic(Intrinsic::frameaddress), -                               ConstantInt::get(Int32Ty, 0)); -        llvm::Value *Args[] = {Buf, FrameAddr}; -        CS = EmitRuntimeCallOrInvoke(SetJmp, Args); -      } -      CS.setAttributes(ReturnsTwiceAttr); -      return RValue::get(CS.getInstruction()); +      if (getTarget().getTriple().getArch() == llvm::Triple::x86) +        return EmitMSVCRTSetJmp(*this, MSVCSetJmpKind::_setjmp3, E); +      else if (getTarget().getTriple().getArch() == llvm::Triple::aarch64) +        return EmitMSVCRTSetJmp(*this, MSVCSetJmpKind::_setjmpex, E); +      return EmitMSVCRTSetJmp(*this, MSVCSetJmpKind::_setjmp, E);      }      break; -  }    case Builtin::BI__GetExceptionInfo: {      if (llvm::GlobalVariable *GV = diff --git a/clang/test/CodeGen/ms-setjmp.c b/clang/test/CodeGen/ms-setjmp.c index b9c67eb3040..d92f4d00ff5 100644 --- a/clang/test/CodeGen/ms-setjmp.c +++ b/clang/test/CodeGen/ms-setjmp.c @@ -1,7 +1,9 @@  // RUN: %clang_cc1 -fms-extensions -DDECLARE_SETJMP -triple i686-windows-msvc   -emit-llvm %s -o - | FileCheck --check-prefix=I386 %s  // RUN: %clang_cc1 -fms-extensions -DDECLARE_SETJMP -triple x86_64-windows-msvc -emit-llvm %s -o - | FileCheck --check-prefix=X64 %s +// RUN: %clang_cc1 -fms-extensions -DDECLARE_SETJMP -triple aarch64-windows-msvc -emit-llvm %s -o - | FileCheck --check-prefix=AARCH64 %s  // RUN: %clang_cc1 -fms-extensions -triple i686-windows-msvc   -emit-llvm %s -o - | FileCheck --check-prefix=I386 %s  // RUN: %clang_cc1 -fms-extensions -triple x86_64-windows-msvc -emit-llvm %s -o - | FileCheck --check-prefix=X64 %s +// RUN: %clang_cc1 -fms-extensions -triple aarch64-windows-msvc -emit-llvm %s -o - | FileCheck --check-prefix=AARCH64 %s  typedef char jmp_buf[1];  #ifdef DECLARE_SETJMP @@ -21,6 +23,11 @@ int test_setjmp() {    // X64:       %[[addr:.*]] = call i8* @llvm.frameaddress(i32 0)    // X64:       %[[call:.*]] = call i32 @_setjmp(i8* getelementptr inbounds ([1 x i8], [1 x i8]* @jb, i32 0, i32 0), i8* %[[addr]])    // X64-NEXT:  ret i32 %[[call]] + +  // AARCH64-LABEL: define dso_local i32 @test_setjmp +  // AARCH64:       %[[addr:.*]] = call i8* @llvm.frameaddress(i32 0) +  // AARCH64:       %[[call:.*]] = call i32 @_setjmpex(i8* getelementptr inbounds ([1 x i8], [1 x i8]* @jb, i32 0, i32 0), i8* %[[addr]]) +  // AARCH64-NEXT:  ret i32 %[[call]]  }  int test_setjmpex() { @@ -29,4 +36,9 @@ int test_setjmpex() {    // X64:       %[[addr:.*]] = call i8* @llvm.frameaddress(i32 0)    // X64:       %[[call:.*]] = call i32 @_setjmpex(i8* getelementptr inbounds ([1 x i8], [1 x i8]* @jb, i32 0, i32 0), i8* %[[addr]])    // X64-NEXT:  ret i32 %[[call]] + +  // AARCH64-LABEL: define dso_local i32 @test_setjmpex +  // AARCH64:       %[[addr:.*]] = call i8* @llvm.frameaddress(i32 0) +  // AARCH64:       %[[call:.*]] = call i32 @_setjmpex(i8* getelementptr inbounds ([1 x i8], [1 x i8]* @jb, i32 0, i32 0), i8* %[[addr]]) +  // AARCH64-NEXT:  ret i32 %[[call]]  } | 

