Index: lib/Transforms/IPO/CrossDSOCFI.cpp =================================================================== --- lib/Transforms/IPO/CrossDSOCFI.cpp +++ lib/Transforms/IPO/CrossDSOCFI.cpp @@ -110,31 +110,31 @@ LLVMContext &Ctx = M->getContext(); Constant *C = M->getOrInsertFunction( - "__cfi_check", - FunctionType::get( - Type::getVoidTy(Ctx), - {Type::getInt64Ty(Ctx), PointerType::getUnqual(Type::getInt8Ty(Ctx))}, - false)); + "__cfi_check", Type::getVoidTy(Ctx), Type::getInt64Ty(Ctx), + Type::getInt8PtrTy(Ctx), Type::getInt8PtrTy(Ctx), nullptr); Function *F = dyn_cast(C); F->setAlignment(4096); auto args = F->arg_begin(); - Argument &CallSiteTypeId = *(args++); + Value &CallSiteTypeId = *(args++); CallSiteTypeId.setName("CallSiteTypeId"); - Argument &Addr = *(args++); + Value &Addr = *(args++); Addr.setName("Addr"); + Value &CFICheckFailData = *(args++); + CFICheckFailData.setName("CFICheckFailData"); assert(args == F->arg_end()); BasicBlock *BB = BasicBlock::Create(Ctx, "entry", F); + BasicBlock *ExitBB = BasicBlock::Create(Ctx, "exit", F); - BasicBlock *TrapBB = BasicBlock::Create(Ctx, "trap", F); - IRBuilder<> IRBTrap(TrapBB); - Function *TrapFn = Intrinsic::getDeclaration(M, Intrinsic::trap); - llvm::CallInst *TrapCall = IRBTrap.CreateCall(TrapFn); - TrapCall->setDoesNotReturn(); - TrapCall->setDoesNotThrow(); - IRBTrap.CreateUnreachable(); + BasicBlock *TrapBB = BasicBlock::Create(Ctx, "fail", F); + IRBuilder<> IRBFail(TrapBB); + Constant *CFICheckFailFn = M->getOrInsertFunction( + "__cfi_check_fail", Type::getVoidTy(Ctx), Type::getInt8PtrTy(Ctx), + Type::getInt8PtrTy(Ctx), nullptr); + assert(CFICheckFailFn || "Module is missing a __cfi_check_fail function"); + IRBFail.CreateCall(CFICheckFailFn, {&CFICheckFailData, &Addr}); + IRBFail.CreateBr(ExitBB); - BasicBlock *ExitBB = BasicBlock::Create(Ctx, "exit", F); IRBuilder<> IRBExit(ExitBB); IRBExit.CreateRetVoid(); Index: test/Transforms/CrossDSOCFI/basic.ll =================================================================== --- test/Transforms/CrossDSOCFI/basic.ll +++ test/Transforms/CrossDSOCFI/basic.ll @@ -1,35 +1,35 @@ ; RUN: opt -S -cross-dso-cfi < %s | FileCheck %s -; CHECK: define void @__cfi_check(i64 %[[TYPE:.*]], i8* %[[ADDR:.*]]) align 4096 -; CHECK: switch i64 %[[TYPE]], label %[[TRAP:.*]] [ +; CHECK: define void @__cfi_check(i64 %[[TYPE:.*]], i8* %[[ADDR:.*]], i8* %[[DATA:.*]]) align 4096 +; CHECK: switch i64 %[[TYPE]], label %[[FAIL:.*]] [ ; CHECK-NEXT: i64 111, label %[[L1:.*]] ; CHECK-NEXT: i64 222, label %[[L2:.*]] ; CHECK-NEXT: i64 333, label %[[L3:.*]] ; CHECK-NEXT: i64 444, label %[[L4:.*]] ; CHECK-NEXT: {{]$}} -; CHECK: [[TRAP]]: -; CHECK-NEXT: call void @llvm.trap() -; CHECK-MEXT: unreachable - ; CHECK: [[EXIT:.*]]: ; CHECK-NEXT: ret void +; CHECK: [[FAIL]]: +; CHECK-NEXT: call void @__cfi_check_fail(i8* %[[DATA]], i8* %[[ADDR]]) +; CHECK-NEXT: br label %[[EXIT]] + ; CHECK: [[L1]]: ; CHECK-NEXT: call i1 @llvm.bitset.test(i8* %[[ADDR]], metadata i64 111) -; CHECK-NEXT: br {{.*}} label %[[EXIT]], label %[[TRAP]] +; CHECK-NEXT: br {{.*}} label %[[EXIT]], label %[[FAIL]] ; CHECK: [[L2]]: ; CHECK-NEXT: call i1 @llvm.bitset.test(i8* %[[ADDR]], metadata i64 222) -; CHECK-NEXT: br {{.*}} label %[[EXIT]], label %[[TRAP]] +; CHECK-NEXT: br {{.*}} label %[[EXIT]], label %[[FAIL]] ; CHECK: [[L3]]: ; CHECK-NEXT: call i1 @llvm.bitset.test(i8* %[[ADDR]], metadata i64 333) -; CHECK-NEXT: br {{.*}} label %[[EXIT]], label %[[TRAP]] +; CHECK-NEXT: br {{.*}} label %[[EXIT]], label %[[FAIL]] ; CHECK: [[L4]]: ; CHECK-NEXT: call i1 @llvm.bitset.test(i8* %[[ADDR]], metadata i64 444) -; CHECK-NEXT: br {{.*}} label %[[EXIT]], label %[[TRAP]] +; CHECK-NEXT: br {{.*}} label %[[EXIT]], label %[[FAIL]] target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" @@ -66,6 +66,11 @@ ret i32 5 } +define weak_odr hidden void @__cfi_check_fail(i8*, i8*) { +entry: + ret void +} + !llvm.bitsets = !{!0, !1, !2, !3, !4, !7, !8, !9, !10, !11, !12, !13, !14, !15} !llvm.module.flags = !{!17}