[llvm] r290384 - [cfi] Emit jump tables as a function-level inline asm.

Evgeniy Stepanov via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 22 14:22:36 PST 2016


Author: eugenis
Date: Thu Dec 22 16:22:35 2016
New Revision: 290384

URL: http://llvm.org/viewvc/llvm-project?rev=290384&view=rev
Log:
[cfi] Emit jump tables as a function-level inline asm.

Use a dummy private function with inline asm calls instead of module
level asm blocks for CFI jumptables.

The main advantage is that now jumptable codegen can be affected by
the function attributes (like target_cpu on ARM). Module level asm
gets the default subtarget based on the target triple, which is often
not good enough.

This change also uses asm constraints/arguments to reference
jumptable targets and aliases directly. We no longer do asm name
mangling in an IR pass.

Differential Revision: https://reviews.llvm.org/D28012

Modified:
    llvm/trunk/lib/Transforms/IPO/LowerTypeTests.cpp
    llvm/trunk/test/Transforms/LowerTypeTests/function-disjoint.ll
    llvm/trunk/test/Transforms/LowerTypeTests/function-ext.ll
    llvm/trunk/test/Transforms/LowerTypeTests/function-weak.ll
    llvm/trunk/test/Transforms/LowerTypeTests/function.ll
    llvm/trunk/test/Transforms/LowerTypeTests/section.ll

Modified: llvm/trunk/lib/Transforms/IPO/LowerTypeTests.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/LowerTypeTests.cpp?rev=290384&r1=290383&r2=290384&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/LowerTypeTests.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/LowerTypeTests.cpp Thu Dec 22 16:22:35 2016
@@ -23,9 +23,9 @@
 #include "llvm/IR/GlobalObject.h"
 #include "llvm/IR/GlobalVariable.h"
 #include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/InlineAsm.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/Intrinsics.h"
-#include "llvm/IR/Mangler.h"
 #include "llvm/IR/Module.h"
 #include "llvm/IR/Operator.h"
 #include "llvm/Pass.h"
@@ -243,6 +243,7 @@ class LowerTypeTestsModule {
 
   bool LinkerSubsectionsViaSymbols;
   Triple::ArchType Arch;
+  Triple::OSType OS;
   Triple::ObjectFormatType ObjectFormat;
 
   IntegerType *Int1Ty = Type::getInt1Ty(M.getContext());
@@ -260,7 +261,6 @@ class LowerTypeTestsModule {
 
   std::vector<ByteArrayInfo> ByteArrayInfos;
 
-  Mangler Mang;
   Function *WeakInitializerFn = nullptr;
 
   BitSetInfo
@@ -281,9 +281,8 @@ class LowerTypeTestsModule {
                                        ArrayRef<GlobalTypeMember *> Globals);
   unsigned getJumpTableEntrySize();
   Type *getJumpTableEntryType();
-  void createJumpTableEntry(raw_ostream &OS, Function *Dest, unsigned Distance);
-  void createJumpTableAlias(raw_ostream &OS, Function *Dest,
-                            GlobalVariable *JumpTable, unsigned Distance);
+  void createJumpTableEntry(raw_ostream &AsmOS, raw_ostream &ConstraintOS,
+                            SmallVectorImpl<Value *> &AsmArgs, Function *Dest);
   void verifyTypeMDNode(GlobalObject *GO, MDNode *Type);
   void buildBitSetsFromFunctions(ArrayRef<Metadata *> TypeIds,
                                  ArrayRef<GlobalTypeMember *> Functions);
@@ -299,6 +298,8 @@ class LowerTypeTestsModule {
   void findGlobalVariableUsersOf(Constant *C,
                                  SmallSetVector<GlobalVariable *, 8> &Out);
 
+  void createJumpTable(Function *F, ArrayRef<GlobalTypeMember *> Functions);
+
 public:
   LowerTypeTestsModule(Module &M);
   bool lower();
@@ -691,80 +692,27 @@ unsigned LowerTypeTestsModule::getJumpTa
   }
 }
 
-static bool isValidAsmUnquotedName(StringRef Name) {
-  if (Name.empty())
-    return false;
-
-  for (char C : Name) {
-    if (!((C >= 'a' && C <= 'z') || (C >= 'A' && C <= 'Z') ||
-          (C >= '0' && C <= '9') || C == '_' || C == '$' || C == '.' ||
-          C == '@'))
-      return false;
-  }
-
-  return true;
-}
-
-// Create a constant representing a jump table entry for the target. This
-// consists of an instruction sequence containing a relative branch to Dest. The
-// constant will be laid out at address Src+(Len*Distance) where Len is the
-// target-specific jump table entry size.
-void LowerTypeTestsModule::createJumpTableEntry(raw_ostream &OS, Function *Dest,
-                                                unsigned Distance) {
-  // FIXME: replace IR Mangler with TargetLoweringObjectFile interface.
-  // A private instance of Mangler we use here can not deal with unnamed
-  // symbols, as it may create colliding labels. Thankfully(?), the use of
-  // inline asm requires us to give names to all affected functions anyway.
-  assert(Dest->hasName() && "jumptable targets can not be anonymous");
-  SmallString<16> Name;
-  Mang.getNameWithPrefix(Name, Dest, /* CannotUsePrivateLabel */ false);
-
-  if (!isValidAsmUnquotedName(Name)) {
-    // We are going to emit a function call as textual asm. Escaped strings
-    // in such expressions are not well supported.
-    report_fatal_error(
-        "CFI-ICall does not allow special characters in a function name.");
-  }
+// Create a jump table entry for the target. This consists of an instruction
+// sequence containing a relative branch to Dest. Appends inline asm text,
+// constraints and arguments to AsmOS, ConstraintOS and AsmArgs.
+void LowerTypeTestsModule::createJumpTableEntry(
+    raw_ostream &AsmOS, raw_ostream &ConstraintOS,
+    SmallVectorImpl<Value *> &AsmArgs, Function *Dest) {
+  unsigned ArgIndex = AsmArgs.size();
 
   if (Arch == Triple::x86 || Arch == Triple::x86_64) {
-    OS << "jmp " << Name << "@plt\n";
-    OS << "int3\nint3\nint3\n";
+    AsmOS << "jmp ${" << ArgIndex << ":c}@plt\n";
+    AsmOS << "int3\nint3\nint3\n";
   } else if (Arch == Triple::arm || Arch == Triple::aarch64) {
-    OS << "b " << Name << "\n";
+    AsmOS << "b $" << ArgIndex << "\n";
   } else if (Arch == Triple::thumb) {
-    OS << "b.w " << Name << "\n";
+    AsmOS << "b.w $" << ArgIndex << "\n";
   } else {
     report_fatal_error("Unsupported architecture for jump tables");
   }
-}
-
-void LowerTypeTestsModule::createJumpTableAlias(raw_ostream &OS, Function *Dest,
-                                                GlobalVariable *JumpTable,
-                                                unsigned Distance) {
-  assert(Dest->hasName() && "jumptable targets can not be anonymous");
-  SmallString<16> Name;
-  Mang.getNameWithPrefix(Name, Dest, /* CannotUsePrivateLabel */ false);
-
-  if (!isValidAsmUnquotedName(Name)) {
-    // We are going to emit a function alias as textual asm. Escaped strings
-    // in such expressions are not well supported.
-    report_fatal_error(
-        "CFI-ICall does not allow special characters in a function name.");
-  }
 
-  if (Dest->isWeakForLinker())
-    OS << ".weak " << Name << "\n";
-  else if (!Dest->hasLocalLinkage())
-    OS << ".globl " << Name << "\n";
-  OS << ".type " << Name << ", function\n";
-  if (Arch == Triple::thumb) {
-    OS << ".thumb_set " << Name << ", " << JumpTable->getName() << " + "
-       << (getJumpTableEntrySize() * Distance) << "\n";
-  } else {
-    OS << Name << " = " << JumpTable->getName() << " + "
-       << (getJumpTableEntrySize() * Distance) << "\n";
-  }
-  OS << ".size " << Name << ", " << getJumpTableEntrySize() << "\n";
+  ConstraintOS << (ArgIndex > 0 ? ",s" : "s");
+  AsmArgs.push_back(Dest);
 }
 
 Type *LowerTypeTestsModule::getJumpTableEntryType() {
@@ -844,6 +792,52 @@ void LowerTypeTestsModule::replaceWeakDe
   PlaceholderFn->eraseFromParent();
 }
 
+void LowerTypeTestsModule::createJumpTable(
+    Function *F, ArrayRef<GlobalTypeMember *> Functions) {
+  std::string AsmStr, ConstraintStr;
+  raw_string_ostream AsmOS(AsmStr), ConstraintOS(ConstraintStr);
+  SmallVector<Value *, 16> AsmArgs;
+  AsmArgs.reserve(Functions.size() * 2);
+
+  for (unsigned I = 0; I != Functions.size(); ++I)
+    createJumpTableEntry(AsmOS, ConstraintOS, AsmArgs,
+                         cast<Function>(Functions[I]->getGlobal()));
+
+  // Try to emit the jump table at the end of the text segment.
+  // Jump table must come after __cfi_check in the cross-dso mode.
+  // FIXME: this magic section name seems to do the trick.
+  F->setSection(ObjectFormat == Triple::MachO
+                    ? "__TEXT,__text,regular,pure_instructions"
+                    : ".text.cfi");
+  // Align the whole table by entry size.
+  F->setAlignment(getJumpTableEntrySize());
+  // Skip prologue.
+  // Disabled on win32 due to https://llvm.org/bugs/show_bug.cgi?id=28641#c3.
+  // Luckily, this function does not get any prologue even without the
+  // attribute.
+  if (OS != Triple::Win32)
+    F->addFnAttr(llvm::Attribute::Naked);
+  // Thumb jump table assembly needs Thumb2. The following attribute is added by
+  // Clang for -march=armv7.
+  if (Arch == Triple::thumb)
+    F->addFnAttr("target-cpu", "cortex-a8");
+
+  BasicBlock *BB = BasicBlock::Create(M.getContext(), "entry", F);
+  IRBuilder<> IRB(BB);
+
+  SmallVector<Type *, 16> ArgTypes;
+  ArgTypes.reserve(AsmArgs.size());
+  for (const auto &Arg : AsmArgs)
+    ArgTypes.push_back(Arg->getType());
+  InlineAsm *JumpTableAsm =
+      InlineAsm::get(FunctionType::get(IRB.getVoidTy(), ArgTypes, false),
+                     AsmOS.str(), ConstraintOS.str(),
+                     /*hasSideEffects=*/true);
+
+  IRB.CreateCall(JumpTableAsm, AsmArgs);
+  IRB.CreateUnreachable();
+}
+
 /// Given a disjoint set of type identifiers and functions, build a jump table
 /// for the functions, build the bit sets and lower the llvm.type.test calls.
 void LowerTypeTestsModule::buildBitSetsFromFunctionsNative(
@@ -933,88 +927,51 @@ void LowerTypeTestsModule::buildBitSetsF
   for (unsigned I = 0; I != Functions.size(); ++I)
     GlobalLayout[Functions[I]] = I * EntrySize;
 
-  // Create a constant to hold the jump table.
+  Function *JumpTableFn =
+      Function::Create(FunctionType::get(Type::getVoidTy(M.getContext()),
+                                         /* IsVarArg */ false),
+                       GlobalValue::PrivateLinkage, ".cfi.jumptable", &M);
   ArrayType *JumpTableType =
       ArrayType::get(getJumpTableEntryType(), Functions.size());
   auto JumpTable =
-      new GlobalVariable(M, JumpTableType,
-                         /*isConstant=*/true, GlobalValue::ExternalLinkage,
-                         nullptr, ".cfi.jumptable");
-  JumpTable->setVisibility(GlobalValue::HiddenVisibility);
-  lowerTypeTestCalls(TypeIds, JumpTable, GlobalLayout);
+      ConstantExpr::getPointerCast(JumpTableFn, JumpTableType->getPointerTo(0));
 
-  std::string AsmStr;
-  raw_string_ostream AsmOS(AsmStr);
+  lowerTypeTestCalls(TypeIds, JumpTable, GlobalLayout);
 
   // Build aliases pointing to offsets into the jump table, and replace
   // references to the original functions with references to the aliases.
   for (unsigned I = 0; I != Functions.size(); ++I) {
     Function *F = cast<Function>(Functions[I]->getGlobal());
 
-    // Need a name for the asm label. Normally, unnamed functions get temporary
-    // asm labels in TargetLoweringObjectFile but we don't have access to that
-    // here.
-    if (!F->hasName())
-      F->setName("unnamed");
+    Constant *CombinedGlobalElemPtr = ConstantExpr::getBitCast(
+        ConstantExpr::getInBoundsGetElementPtr(
+            JumpTableType, JumpTable,
+            ArrayRef<Constant *>{ConstantInt::get(IntPtrTy, 0),
+                                 ConstantInt::get(IntPtrTy, I)}),
+        F->getType());
     if (LinkerSubsectionsViaSymbols || F->isDeclarationForLinker()) {
-      Constant *CombinedGlobalElemPtr = ConstantExpr::getBitCast(
-          ConstantExpr::getGetElementPtr(
-              JumpTableType, JumpTable,
-              ArrayRef<Constant *>{ConstantInt::get(IntPtrTy, 0),
-                                   ConstantInt::get(IntPtrTy, I)}),
-          F->getType());
 
-      if (F->isWeakForLinker()) {
-        AsmOS << ".weak " << F->getName() << "\n";
+      if (F->isWeakForLinker())
         replaceWeakDeclarationWithJumpTablePtr(F, CombinedGlobalElemPtr);
-      } else {
+      else
         F->replaceAllUsesWith(CombinedGlobalElemPtr);
-      }
     } else {
       assert(F->getType()->getAddressSpace() == 0);
 
-      createJumpTableAlias(AsmOS, F, JumpTable, I);
-
-      Function *DeclAlias =
-          Function::Create(cast<FunctionType>(F->getValueType()),
-                           GlobalValue::ExternalLinkage, "", &M);
-      // Since the alias (DeclAlias) is actually a declaration, it can not have
-      // internal linkage. Compensate for that by giving it hidden visibility.
-      // With this we end up with a GOT relocation against a local symbol.
-      DeclAlias->setVisibility(F->hasLocalLinkage()
-                                   ? GlobalValue::HiddenVisibility
-                                   : F->getVisibility());
-      DeclAlias->takeName(F);
-      // Unnamed functions can not be added to llvm.used.
-      F->setName(DeclAlias->getName() + ".cfi");
-      F->replaceAllUsesWith(DeclAlias);
+      GlobalAlias *FAlias = GlobalAlias::create(F->getValueType(), 0,
+                                                F->getLinkage(), "",
+                                                CombinedGlobalElemPtr, &M);
+      FAlias->setVisibility(F->getVisibility());
+      FAlias->takeName(F);
+      if (FAlias->hasName())
+        F->setName(FAlias->getName() + ".cfi");
+      F->replaceAllUsesWith(FAlias);
     }
     if (!F->isDeclarationForLinker())
       F->setLinkage(GlobalValue::InternalLinkage);
   }
 
-  // Try to emit the jump table at the end of the text segment.
-  // Jump table must come after __cfi_check in the cross-dso mode.
-  // FIXME: this magic section name seems to do the trick.
-  AsmOS << ".section " << (ObjectFormat == Triple::MachO
-                               ? "__TEXT,__text,regular,pure_instructions"
-                               : ".text.cfi, \"ax\", %progbits")
-        << "\n";
-  // Align the whole table by entry size.
-  AsmOS << ".balign " << EntrySize << "\n";
-  if (Arch == Triple::thumb)
-    AsmOS << ".thumb_func\n";
-  AsmOS << JumpTable->getName() << ":\n";
-  for (unsigned I = 0; I != Functions.size(); ++I)
-    createJumpTableEntry(AsmOS, cast<Function>(Functions[I]->getGlobal()), I);
-
-  M.appendModuleInlineAsm(AsmOS.str());
-
-  SmallVector<GlobalValue *, 16> Used;
-  Used.reserve(Functions.size());
-  for (auto *F : Functions)
-    Used.push_back(F->getGlobal());
-  appendToUsed(M, Used);
+  createJumpTable(JumpTableFn, Functions);
 }
 
 /// Assign a dummy layout using an incrementing counter, tag each function
@@ -1126,6 +1083,7 @@ LowerTypeTestsModule::LowerTypeTestsModu
   Triple TargetTriple(M.getTargetTriple());
   LinkerSubsectionsViaSymbols = TargetTriple.isMacOSX();
   Arch = TargetTriple.getArch();
+  OS = TargetTriple.getOS();
   ObjectFormat = TargetTriple.getObjectFormat();
 }
 

Modified: llvm/trunk/test/Transforms/LowerTypeTests/function-disjoint.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LowerTypeTests/function-disjoint.ll?rev=290384&r1=290383&r2=290384&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/LowerTypeTests/function-disjoint.ll (original)
+++ llvm/trunk/test/Transforms/LowerTypeTests/function-disjoint.ll Thu Dec 22 16:22:35 2016
@@ -5,25 +5,8 @@
 
 target datalayout = "e-p:64:64"
 
-; X64:      module asm "f = .cfi.jumptable + 0"
-
-; X64:      module asm ".cfi.jumptable:"
-; X64-NEXT: module asm "jmp f.cfi at plt"
-; X64-NEXT: module asm "int3"
-; X64-NEXT: module asm "int3"
-; X64-NEXT: module asm "int3"
-
-; X64:      module asm "g = .cfi.jumptable.1 + 0"
-
-; X64:      module asm ".cfi.jumptable.1:"
-; X64-NEXT: module asm "jmp g.cfi at plt"
-; X64-NEXT: module asm "int3"
-; X64-NEXT: module asm "int3"
-; X64-NEXT: module asm "int3"
-
-
-; X64: @.cfi.jumptable = external hidden constant [1 x [8 x i8]]
-; X64: @.cfi.jumptable.1 = external hidden constant [1 x [8 x i8]]
+; X64: @f = alias void (), void ()* @[[JT0:.*]]
+; X64: @g = alias void (), void ()* @[[JT1:.*]]
 
 ; WASM32: private constant [0 x i8] zeroinitializer
 @0 = private unnamed_addr constant [2 x void ()*] [void ()* @f, void ()* @g], align 16
@@ -46,18 +29,21 @@ define void @g() !type !1 {
 declare i1 @llvm.type.test(i8* %ptr, metadata %bitset) nounwind readnone
 
 define i1 @foo(i8* %p) {
-  ; X64: icmp eq i64 {{.*}}, ptrtoint ([1 x [8 x i8]]* @.cfi.jumptable to i64)
+  ; X64: icmp eq i64 {{.*}}, ptrtoint (void ()* @[[JT0]] to i64)
   ; WASM32: icmp eq i64 {{.*}}, 1
   %x = call i1 @llvm.type.test(i8* %p, metadata !"typeid1")
-  ; X64: icmp eq i64 {{.*}}, ptrtoint ([1 x [8 x i8]]* @.cfi.jumptable.1 to i64)
+  ; X64: icmp eq i64 {{.*}}, ptrtoint (void ()* @[[JT1]] to i64)
   ; WASM32: icmp eq i64 {{.*}}, 2
   %y = call i1 @llvm.type.test(i8* %p, metadata !"typeid2")
   %z = add i1 %x, %y
   ret i1 %z
 }
 
-; X64: declare void @f()
-; X64: declare void @g()
+; X64: define private void @[[JT0]]() #{{.*}} section ".text.cfi" align 8 {
+; X64:   call void asm sideeffect "jmp ${0:c}@plt\0Aint3\0Aint3\0Aint3\0A", "s"(void ()* @f.cfi)
+
+; X64: define private void @[[JT1]]() #{{.*}} section ".text.cfi" align 8 {
+; X64:   call void asm sideeffect "jmp ${0:c}@plt\0Aint3\0Aint3\0Aint3\0A", "s"(void ()* @g.cfi)
 
 ; WASM32: ![[I0]] = !{i64 1}
 ; WASM32: ![[I1]] = !{i64 2}
\ No newline at end of file

Modified: llvm/trunk/test/Transforms/LowerTypeTests/function-ext.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LowerTypeTests/function-ext.ll?rev=290384&r1=290383&r2=290384&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/LowerTypeTests/function-ext.ll (original)
+++ llvm/trunk/test/Transforms/LowerTypeTests/function-ext.ll Thu Dec 22 16:22:35 2016
@@ -4,18 +4,13 @@
 ; Tests that we correctly handle external references, including the case where
 ; all functions in a bitset are external references.
 
-; X64:      module asm ".cfi.jumptable:"
-; X64-NEXT: module asm "jmp foo at plt"
-; X64-NOT:  module asm "jmp {{.*}}@plt"
-
-; X64: @.cfi.jumptable = external hidden constant [1 x [8 x i8]]
 ; WASM32: private constant [0 x i8] zeroinitializer
 
 ; WASM32: declare !type !{{[0-9]+}} void @foo()
 declare !type !0 void @foo()
 
 define i1 @bar(i8* %ptr) {
-  ; X64: icmp eq i64 {{.*}}, ptrtoint ([1 x [8 x i8]]* @.cfi.jumptable to i64)
+  ; X64: icmp eq i64 {{.*}}, ptrtoint (void ()* @[[JT:.*]] to i64)
   ; WASM32: sub i64 {{.*}}, 0
   ; WASM32: icmp ult i64 {{.*}}, 1
   %p = call i1 @llvm.type.test(i8* %ptr, metadata !"void")
@@ -27,3 +22,6 @@ declare i1 @llvm.type.test(i8* %ptr, met
 !0 = !{i64 0, !"void"}
 ; WASM-NOT: !{i64 0}
 ; WASM-NOT: !{i64 1}
+
+; X64: define private void @[[JT]]() #{{.*}} section ".text.cfi" align {{.*}} {
+; X64:   call void asm sideeffect "jmp ${0:c}@plt\0Aint3\0Aint3\0Aint3\0A", "s"(void ()* @foo)

Modified: llvm/trunk/test/Transforms/LowerTypeTests/function-weak.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LowerTypeTests/function-weak.ll?rev=290384&r1=290383&r2=290384&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/LowerTypeTests/function-weak.ll (original)
+++ llvm/trunk/test/Transforms/LowerTypeTests/function-weak.ll Thu Dec 22 16:22:35 2016
@@ -1,13 +1,11 @@
-; RUN: opt -S -lowertypetests -mtriple=i686-unknown-linux-gnu < %s | FileCheck %s
-; RUN: opt -S -lowertypetests -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s
-; RUN: opt -S -lowertypetests -mtriple=arm-unknown-linux-gnu < %s | FileCheck %s
-; RUN: opt -S -lowertypetests -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s
+; RUN: opt -S -lowertypetests -mtriple=i686-unknown-linux-gnu < %s | FileCheck --check-prefixes=CHECK,X86 %s
+; RUN: opt -S -lowertypetests -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck --check-prefixes=CHECK,X86 %s
+; RUN: opt -S -lowertypetests -mtriple=arm-unknown-linux-gnu < %s | FileCheck --check-prefixes=CHECK,ARM %s
+; RUN: opt -S -lowertypetests -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck --check-prefixes=CHECK,ARM %s
 
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-unknown-linux-gnu"
 
-; CHECK: module asm ".weak f"
-
 ; CHECK: @x = global void ()* null, align 8
 @x = global void ()* @f, align 8
 
@@ -25,7 +23,6 @@ target triple = "x86_64-unknown-linux-gn
 ; CHECK: @s = global { void ()*, void ()*, i32 } zeroinitializer, align 8
 @s = global { void ()*, void ()*, i32 } { void ()* @f, void ()* @f, i32 42 }, align 8
 
-; CHECK: @.cfi.jumptable = external hidden constant [1 x [{{.*}} x i8]]
 ; CHECK:  @llvm.global_ctors = appending global {{.*}}{ i32 0, void ()* @__cfi_global_var_init
 
 ; CHECK: declare !type !0 extern_weak void @f()
@@ -34,14 +31,14 @@ declare !type !0 extern_weak void @f()
 ; CHECK: define zeroext i1 @check_f()
 define zeroext i1 @check_f() {
 entry:
-; CHECK: ret i1 icmp ne (void ()* select (i1 icmp ne (void ()* @f, void ()* null), void ()* bitcast ({{.*}}@.cfi.jumptable to void ()*), void ()* null), void ()* null)
+; CHECK: ret i1 icmp ne (void ()* select (i1 icmp ne (void ()* @f, void ()* null), void ()* @[[JT:.*]], void ()* null), void ()* null)
   ret i1 icmp ne (void ()* @f, void ()* null)
 }
 
 ; CHECK: define void @call_f() {
 define void @call_f() {
 entry:
-; CHECK: call void select (i1 icmp ne (void ()* @f, void ()* null), void ()* bitcast ({{.*}}@.cfi.jumptable to void ()*), void ()* null)()
+; CHECK: call void select (i1 icmp ne (void ()* @f, void ()* null), void ()* @[[JT]], void ()* null)()
   call void @f()
   ret void
 }
@@ -53,15 +50,17 @@ define i1 @foo(i8* %p) {
   ret i1 %x
 }
 
+; X86: define private void @[[JT]]() #{{.*}} section ".text.cfi" align 8 {
+; ARM: define private void @[[JT]]() #{{.*}} section ".text.cfi" align 4 {
+
 ; CHECK: define internal void @__cfi_global_var_init() section ".text.startup" {
 ; CHECK-NEXT: entry:
-; CHECK-NEXT: store { void ()*, void ()*, i32 } { void ()* select (i1 icmp ne (void ()* @f, void ()* null), void ()* bitcast ({{.*}}@.cfi.jumptable to void ()*), void ()* null), void ()* select (i1 icmp ne (void ()* @f, void ()* null), void ()* bitcast ({{.*}}@.cfi.jumptable to void ()*), void ()* null), i32 42 }, { void ()*, void ()*, i32 }* @s, align 8
-; CHECK-NEXT: store void ()* bitcast (i8* getelementptr (i8, i8* bitcast (void ()* select (i1 icmp ne (void ()* @f, void ()* null), void ()* bitcast ({{.*}}@.cfi.jumptable to void ()*), void ()* null) to i8*), i64 42) to void ()*), void ()** @x4, align 8
-; CHECK-NEXT: store void ()* select (i1 icmp ne (void ()* @f, void ()* null), void ()* bitcast ({{.*}}@.cfi.jumptable to void ()*), void ()* null), void ()** @x3, align 8
-; CHECK-NEXT: store void ()* select (i1 icmp ne (void ()* @f, void ()* null), void ()* bitcast ({{.*}}@.cfi.jumptable to void ()*), void ()* null), void ()** @x2, align 8
-; CHECK-NEXT: store void ()* select (i1 icmp ne (void ()* @f, void ()* null), void ()* bitcast ({{.*}}@.cfi.jumptable to void ()*), void ()* null), void ()** @x, align 8
+; CHECK-NEXT: store { void ()*, void ()*, i32 } { void ()* select (i1 icmp ne (void ()* @f, void ()* null), void ()* @[[JT]], void ()* null), void ()* select (i1 icmp ne (void ()* @f, void ()* null), void ()* @[[JT]], void ()* null), i32 42 }, { void ()*, void ()*, i32 }* @s, align 8
+; CHECK-NEXT: store void ()* bitcast (i8* getelementptr (i8, i8* bitcast (void ()* select (i1 icmp ne (void ()* @f, void ()* null), void ()* @[[JT]], void ()* null) to i8*), i64 42) to void ()*), void ()** @x4, align 8
+; CHECK-NEXT: store void ()* select (i1 icmp ne (void ()* @f, void ()* null), void ()* @[[JT]], void ()* null), void ()** @x3, align 8
+; CHECK-NEXT: store void ()* select (i1 icmp ne (void ()* @f, void ()* null), void ()* @[[JT]], void ()* null), void ()** @x2, align 8
+; CHECK-NEXT: store void ()* select (i1 icmp ne (void ()* @f, void ()* null), void ()* @[[JT]], void ()* null), void ()** @x, align 8
 ; CHECK-NEXT: ret void
 ; CHECK-NEXT: }
 
-
 !0 = !{i32 0, !"typeid1"}

Modified: llvm/trunk/test/Transforms/LowerTypeTests/function.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LowerTypeTests/function.ll?rev=290384&r1=290383&r2=290384&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/LowerTypeTests/function.ll (original)
+++ llvm/trunk/test/Transforms/LowerTypeTests/function.ll Thu Dec 22 16:22:35 2016
@@ -1,5 +1,7 @@
-; RUN: opt -S -lowertypetests -mtriple=i686-unknown-linux-gnu < %s | FileCheck --check-prefixes=X86,NATIVE %s
-; RUN: opt -S -lowertypetests -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck --check-prefixes=X86,NATIVE %s
+; RUN: opt -S -lowertypetests -mtriple=i686-unknown-linux-gnu < %s | FileCheck --check-prefixes=X86,X86-LINUX,NATIVE %s
+; RUN: opt -S -lowertypetests -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck --check-prefixes=X86,X86-LINUX,NATIVE %s
+; RUN: opt -S -lowertypetests -mtriple=i686-pc-win32 < %s | FileCheck --check-prefixes=X86,X86-WIN32,NATIVE %s
+; RUN: opt -S -lowertypetests -mtriple=x86_64-pc-win32 < %s | FileCheck --check-prefixes=X86,X86-WIN32,NATIVE %s
 ; RUN: opt -S -lowertypetests -mtriple=arm-unknown-linux-gnu < %s | FileCheck --check-prefixes=ARM,NATIVE %s
 ; RUN: opt -S -lowertypetests -mtriple=thumb-unknown-linux-gnu < %s | FileCheck --check-prefixes=THUMB,NATIVE %s
 ; RUN: opt -S -lowertypetests -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck --check-prefixes=ARM,NATIVE %s
@@ -9,61 +11,18 @@
 
 target datalayout = "e-p:64:64"
 
-; X86:      module asm ".globl f"
-; X86-NEXT: module asm ".type f, function"
-; X86-NEXT: module asm "f = .cfi.jumptable + 0"
-; X86-NEXT: module asm ".size f, 8"
-; X86-NEXT: module asm ".type g, function"
-; X86-NEXT: module asm "g = .cfi.jumptable + 8"
-; X86-NEXT: module asm ".size g, 8"
-; X86-NEXT: module asm ".section .text.cfi, \22ax\22, %progbits"
-; X86-NEXT: module asm ".balign 8"
-; X86-NEXT: module asm ".cfi.jumptable:"
-; X86-NEXT: module asm "jmp f.cfi at plt"
-; X86-NEXT: module asm "int3"
-; X86-NEXT: module asm "int3"
-; X86-NEXT: module asm "int3"
-; X86-NEXT: module asm "jmp g.cfi at plt"
-; X86-NEXT: module asm "int3"
-; X86-NEXT: module asm "int3"
-; X86-NEXT: module asm "int3"
-
-; ARM:      module asm ".globl f"
-; ARM-NEXT: module asm ".type f, function"
-; ARM-NEXT: module asm "f = .cfi.jumptable + 0"
-; ARM-NEXT: module asm ".size f, 4"
-; ARM-NEXT: module asm ".type g, function"
-; ARM-NEXT: module asm "g = .cfi.jumptable + 4"
-; ARM-NEXT: module asm ".size g, 4"
-; ARM-NEXT: module asm ".section .text.cfi, \22ax\22, %progbits"
-; ARM-NEXT: module asm ".balign 4"
-; ARM-NEXT: module asm ".cfi.jumptable:"
-; ARM-NEXT: module asm "b f.cfi"
-; ARM-NEXT: module asm "b g.cfi"
-
-; THUMB:      module asm ".globl f"
-; THUMB-NEXT: module asm ".type f, function"
-; THUMB-NEXT: module asm ".thumb_set f, .cfi.jumptable + 0"
-; THUMB-NEXT: module asm ".size f, 4"
-; THUMB-NEXT: module asm ".type g, function"
-; THUMB-NEXT: module asm ".thumb_set g, .cfi.jumptable + 4"
-; THUMB-NEXT: module asm ".size g, 4"
-; THUMB-NEXT: module asm ".section .text.cfi, \22ax\22, %progbits"
-; THUMB-NEXT: module asm ".balign 4"
-; THUMB-NEXT: module asm ".thumb_func"
-; THUMB-NEXT: module asm ".cfi.jumptable:"
-; THUMB-NEXT: module asm "b.w f.cfi"
-; THUMB-NEXT: module asm "b.w g.cfi"
-
-
-; X86: @.cfi.jumptable = external hidden constant [2 x [8 x i8]]
-; ARM: @.cfi.jumptable = external hidden constant [2 x [4 x i8]]
-; THUMB: @.cfi.jumptable = external hidden constant [2 x [4 x i8]]
 
-; WASM32: private constant [0 x i8] zeroinitializer
+; NATIVE: @0 = private unnamed_addr constant [2 x void (...)*] [void (...)* bitcast (void ()* @f to void (...)*), void (...)* bitcast (void ()* @g to void (...)*)], align 16
 @0 = private unnamed_addr constant [2 x void (...)*] [void (...)* bitcast (void ()* @f to void (...)*), void (...)* bitcast (void ()* @g to void (...)*)], align 16
 
-; NATIVE: @llvm.used = appending global [2 x i8*] [i8* bitcast (void ()* @f.cfi to i8*), i8* bitcast (void ()* @g.cfi to i8*)], section "llvm.metadata"
+; NATIVE: private constant [0 x i8] zeroinitializer
+; WASM32: private constant [0 x i8] zeroinitializer
+
+; NATIVE: @f = alias void (), void ()* @[[JT:.*]]
+
+; X86: @g = internal alias void (), bitcast ([8 x i8]* getelementptr inbounds ([2 x [8 x i8]], [2 x [8 x i8]]* bitcast (void ()* @[[JT]] to [2 x [8 x i8]]*), i64 0, i64 1) to void ()*)
+; ARM: @g = internal alias void (), bitcast ([4 x i8]* getelementptr inbounds ([2 x [4 x i8]], [2 x [4 x i8]]* bitcast (void ()* @[[JT]] to [2 x [4 x i8]]*), i64 0, i64 1) to void ()*)
+; THUMB: @g = internal alias void (), bitcast ([4 x i8]* getelementptr inbounds ([2 x [4 x i8]], [2 x [4 x i8]]* bitcast (void ()* @[[JT]] to [2 x [4 x i8]]*), i64 0, i64 1) to void ()*)
 
 ; NATIVE: define internal void @f.cfi()
 ; WASM32: define void @f() !type !{{[0-9]+}} !wasm.index ![[I0:[0-9]+]]
@@ -82,16 +41,38 @@ define internal void @g() !type !0 {
 declare i1 @llvm.type.test(i8* %ptr, metadata %bitset) nounwind readnone
 
 define i1 @foo(i8* %p) {
-  ; X86: sub i64 {{.*}}, ptrtoint ([2 x [8 x i8]]* @.cfi.jumptable to i64)
-  ; ARM: sub i64 {{.*}}, ptrtoint ([2 x [4 x i8]]* @.cfi.jumptable to i64)
+  ; NATIVE: sub i64 {{.*}}, ptrtoint (void ()* @[[JT]] to i64)
   ; WASM32: sub i64 {{.*}}, 1
   ; WASM32: icmp ult i64 {{.*}}, 2
   %x = call i1 @llvm.type.test(i8* %p, metadata !"typeid1")
   ret i1 %x
 }
 
-; NATIVE: declare void @f()
-; NATIVE: declare hidden void @g()
+; X86-LINUX:   define private void @[[JT]]() #[[ATTR:.*]] section ".text.cfi" align 8 {
+; X86-WIN32:   define private void @[[JT]]() section ".text.cfi" align 8 {
+; ARM:   define private void @[[JT]]() #[[ATTR:.*]] section ".text.cfi" align 4 {
+; THUMB: define private void @[[JT]]() #[[ATTR:.*]] section ".text.cfi" align 4 {
+
+; X86:      jmp ${0:c}@plt
+; X86-SAME: int3
+; X86-SAME: int3
+; X86-SAME: int3
+; X86-SAME: jmp ${1:c}@plt
+; X86-SAME: int3
+; X86-SAME: int3
+; X86-SAME: int3
+
+; ARM:      b $0
+; ARM-SAME: b $1
+
+; THUMB:      b.w $0
+; THUMB-SAME: b.w $1
+
+; NATIVE-SAME: "s,s"(void ()* @f.cfi, void ()* @g.cfi)
+
+; X86-LINUX: attributes #[[ATTR]] = { {{.*}}naked
+; ARM: attributes #[[ATTR]] = { {{.*}}naked
+; THUMB: attributes #[[ATTR]] = { {{.*}}naked{{.*}}"target-cpu"="cortex-a8"
 
 ; WASM32: ![[I0]] = !{i64 1}
 ; WASM32: ![[I1]] = !{i64 2}

Modified: llvm/trunk/test/Transforms/LowerTypeTests/section.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LowerTypeTests/section.ll?rev=290384&r1=290383&r2=290384&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/LowerTypeTests/section.ll (original)
+++ llvm/trunk/test/Transforms/LowerTypeTests/section.ll Thu Dec 22 16:22:35 2016
@@ -5,10 +5,7 @@
 
 target triple = "x86_64-unknown-linux-gnu"
 
-; CHECK:      module asm ".section .text.cfi,
-; CHECK:      module asm ".cfi.jumptable:"
-; CHECK-NEXT: module asm "jmp f.cfi at plt"
-
+; CHECK: @f = alias void (), void ()* @[[JT:.*]]
 ; CHECK: define internal void @f.cfi() section "xxx"
 
 define void @f() section "xxx" !type !0 {
@@ -22,6 +19,8 @@ entry:
   ret i1 %0
 }
 
+; CHECK: define private void @[[JT]]() #{{.*}} section ".text.cfi" align {{.*}} {
+
 declare i1 @llvm.type.test(i8*, metadata) nounwind readnone
 
 !0 = !{i64 0, !"_ZTSFvE"}




More information about the llvm-commits mailing list