llvm.org GIT mirror llvm / 5d0f7af
Add a new attribute called 'jumptable' that creates jump-instruction tables for functions marked with this attribute. It includes a pass that rewrites all indirect calls to jumptable functions to pass through these tables. This also adds backend support for generating the jump-instruction tables on ARM and X86. Note that since the jumptable attribute creates a second function pointer for a function, any function marked with jumptable must also be marked with unnamed_addr. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@210280 91177308-0d34-0410-b5e6-96231b3b80d8 Tom Roeder 5 years ago
40 changed file(s) with 1109 addition(s) and 8 deletion(s). Raw diff Collapse all Expand all
10191019 inlining this function is desirable (such as the "inline" keyword in
10201020 C/C++). It is just a hint; it imposes no requirements on the
10211021 inliner.
1022 ``jumptable``
1023 This attribute indicates that the function should be added to a
1024 jump-instruction table at code-generation time, and that all address-taken
1025 references to this function should be replaced with a reference to the
1026 appropriate jump-instruction-table function pointer. Note that this creates
1027 a new pointer for the original function, which means that code that depends
1028 on function-pointer identity can break. So, any function annotated with
1029 ``jumptable`` must also be ``unnamed_addr``.
10221030 ``minsize``
10231031 This attribute suggests that optimization passes and code generator
10241032 passes make choices that keep the code size of this function as small
0 //===-- JumpInstrTableInfo.h: Info for Jump-Instruction Tables --*- C++ -*-===//
1 //
2 // This file is distributed under the University of Illinois Open Source
3 // License. See LICENSE.TXT for details.
4 //
5 //===----------------------------------------------------------------------===//
6 ///
7 /// \file
8 /// \brief Information about jump-instruction tables that have been created by
9 /// JumpInstrTables pass.
10 ///
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_ANALYSIS_JUMPINSTRTABLEINFO_H
14 #define LLVM_ANALYSIS_JUMPINSTRTABLEINFO_H
15
16 #include "llvm/ADT/DenseMap.h"
17 #include "llvm/Pass.h"
18
19 #include
20
21 namespace llvm {
22 class Function;
23 class FunctionType;
24
25 /// This class stores information about jump-instruction tables created by the
26 /// JumpInstrTables pass (in lib/CodeGen/JumpInstrTables.cpp). Each table is a
27 /// map from a function type to a vector of pairs. The first element of each
28 /// pair is the function that has the jumptable annotation. The second element
29 /// is a function that was declared by JumpInstrTables and used to replace all
30 /// address-taking sites for the original function.
31 ///
32 /// The information in this pass is used in AsmPrinter
33 /// (lib/CodeGen/AsmPrinter/AsmPrinter.cpp) to generate the required assembly
34 /// for the jump-instruction tables.
35 class JumpInstrTableInfo : public ImmutablePass {
36 public:
37 static char ID;
38
39 JumpInstrTableInfo();
40 virtual ~JumpInstrTableInfo();
41 const char *getPassName() const override {
42 return "Jump-Instruction Table Info";
43 }
44
45 typedef std::pair JumpPair;
46 typedef DenseMap > JumpTables;
47
48 /// Inserts an entry in a table, adding the table if it doesn't exist.
49 void insertEntry(FunctionType *TableFunTy, Function *Target, Function *Jump);
50
51 /// Gets the tables.
52 const JumpTables &getTables() const { return Tables; }
53
54 private:
55 JumpTables Tables;
56 };
57 }
58
59 #endif /* LLVM_ANALYSIS_JUMPINSTRTABLEINFO_H */
141141 // information and prints it with -analyze.
142142 //
143143 FunctionPass *createMemDepPrinter();
144
145 // createJumpInstrTableInfoPass - This creates a pass that stores information
146 // about the jump tables created by JumpInstrTables
147 ImmutablePass *createJumpInstrTableInfoPass();
144148 }
145149
146150 #endif
371371 ATTR_KIND_COLD = 36,
372372 ATTR_KIND_OPTIMIZE_NONE = 37,
373373 ATTR_KIND_IN_ALLOCA = 38,
374 ATTR_KIND_NON_NULL = 39
374 ATTR_KIND_NON_NULL = 39,
375 ATTR_KIND_JUMP_TABLE = 40
375376 };
376377
377378 } // End bitc namespace
200200 FunctionSections("function-sections",
201201 cl::desc("Emit functions into separate sections"),
202202 cl::init(false));
203
204 cl::opt
205 JTableType("jump-table-type",
206 cl::desc("Choose the type of Jump-Instruction Table for jumptable."),
207 cl::init(JumpTable::Single),
208 cl::values(
209 clEnumValN(JumpTable::Single, "single",
210 "Create a single table for all jumptable functions"),
211 clEnumValN(JumpTable::Arity, "arity",
212 "Create one table per number of parameters."),
213 clEnumValN(JumpTable::Simplified, "simplified",
214 "Create one table per simplified function type."),
215 clEnumValN(JumpTable::Full, "full",
216 "Create one table per unique function type."),
217 clEnumValEnd));
203218
204219 // Common utility function tightly tied to the options listed here. Initializes
205220 // a TargetOptions object with CodeGen flags and returns it.
227242 Options.FunctionSections = FunctionSections;
228243
229244 Options.MCOptions = InitMCTargetOptionsFromFlags();
245 Options.JTType = JTableType;
230246
231247 return Options;
232248 }
0 //===-- JumpInstrTables.h: Jump-Instruction Tables --------------*- C++ -*-===//
1 //
2 // This file is distributed under the University of Illinois Open Source
3 // License. See LICENSE.TXT for details.
4 //
5 //===----------------------------------------------------------------------===//
6 ///
7 /// \file
8 /// \brief An implementation of tables consisting of jump instructions
9 ///
10 //===----------------------------------------------------------------------===//
11
12 #ifndef LLVM_CODEGEN_JUMPINSTRTABLES_H
13 #define LLVM_CODEGEN_JUMPINSTRTABLES_H
14
15 #include "llvm/ADT/DenseMap.h"
16 #include "llvm/Pass.h"
17 #include "llvm/Target/TargetOptions.h"
18
19 namespace llvm {
20 class Constant;
21 class Function;
22 class FunctionType;
23 class JumpInstrTableInfo;
24 class Module;
25
26 /// A class to manage a set of jump tables indexed on function type. It looks at
27 /// each function in the module to find all the functions that have the
28 /// jumptable attribute set. For each such function, it creates a new
29 /// jump-instruction-table function and stores the mapping in the ImmutablePass
30 /// JumpInstrTableInfo.
31 ///
32 /// These special functions get lowered in AsmPrinter to assembly of the form:
33 /// .globl f
34 /// .type f,@function
35 /// .align 8,0x90
36 /// f:
37 /// jmp f_orig@PLT
38 ///
39 /// Support for an architecture depends on two functions in TargetInstrInfo:
40 /// getUnconditionalBranch, and getTrap. AsmPrinter uses these to generate the
41 /// appropriate instructions for the jump statement (an unconditional branch)
42 /// and for padding to make the table have a size that is a power of two. This
43 /// padding uses a trap instruction to ensure that calls to this area halt the
44 /// program. The default implementations of these functions call
45 /// llvm_unreachable.
46 class JumpInstrTables : public ModulePass {
47 public:
48 static char ID;
49
50 JumpInstrTables();
51 JumpInstrTables(JumpTable::JumpTableType JTT);
52 virtual ~JumpInstrTables();
53 bool runOnModule(Module &M) override;
54 const char *getPassName() const override { return "Jump-Instruction Tables"; }
55 void getAnalysisUsage(AnalysisUsage &AU) const override;
56
57 /// Creates a jump-instruction table function for the Target and adds it to
58 /// the tables.
59 Function *insertEntry(Module &M, Function *Target);
60
61 /// Checks to see if there is already a table for the given FunctionType.
62 bool hasTable(FunctionType *FunTy);
63
64 private:
65 /// The metadata used while a jump table is being built
66 struct TableMeta {
67 /// The number of this table
68 unsigned TableNum;
69
70 /// The current number of jump entries in the table.
71 unsigned Count;
72 };
73
74 typedef DenseMap JumpMap;
75
76 /// Maps the function into a subset of function types, depending on the
77 /// jump-instruction table style selected from JumpTableTypes in
78 /// JumpInstrTables.cpp. The choice of mapping determines the number of
79 /// jump-instruction tables generated by this pass. E.g., the simplest mapping
80 /// converts every function type into void f(); so, all functions end up in a
81 /// single table.
82 FunctionType *transformType(FunctionType *FunTy);
83
84 /// The current state of functions and jump entries in the table(s).
85 JumpMap Metadata;
86
87 /// The ImmutablePass that stores information about the generated tables.
88 JumpInstrTableInfo *JITI;
89
90 /// The total number of tables.
91 unsigned TableCount;
92
93 /// The type of tables to build.
94 JumpTable::JumpTableType JTType;
95 };
96
97 /// Creates a JumpInstrTables pass for the given type of jump table.
98 ModulePass *createJumpInstrTablesPass(JumpTable::JumpTableType JTT);
99 }
100
101 #endif /* LLVM_CODEGEN_JUMPINSTRTABLES_H */
587587 /// the intrinsic for later emission to the StackMap.
588588 extern char &StackMapLivenessID;
589589
590 /// createJumpInstrTables - This pass creates jump-instruction tables.
591 ModulePass *createJumpInstrTablesPass();
590592 } // End llvm namespace
591593
592594 #endif
7474 Cold, ///< Marks function as being in a cold path.
7575 InlineHint, ///< Source said inlining was desirable
7676 InReg, ///< Force argument to be passed in register
77 JumpTable, ///< Build jump-instruction tables and replace refs.
7778 MinSize, ///< Function must be optimized for size first
7879 Naked, ///< Naked function
7980 Nest, ///< Nested function static chain
145145 void initializeInstNamerPass(PassRegistry&);
146146 void initializeInternalizePassPass(PassRegistry&);
147147 void initializeIntervalPartitionPass(PassRegistry&);
148 void initializeJumpInstrTableInfoPass(PassRegistry&);
149 void initializeJumpInstrTablesPass(PassRegistry&);
148150 void initializeJumpThreadingPass(PassRegistry&);
149151 void initializeLCSSAPass(PassRegistry&);
150152 void initializeLICMPass(PassRegistry&);
8484 (void) llvm::createIndVarSimplifyPass();
8585 (void) llvm::createInstructionCombiningPass();
8686 (void) llvm::createInternalizePass();
87 (void) llvm::createJumpInstrTableInfoPass();
88 (void) llvm::createJumpInstrTablesPass();
8789 (void) llvm::createLCSSAPass();
8890 (void) llvm::createLICMPass();
8991 (void) llvm::createLazyValueInfoPass();
2828 class MDNode;
2929 class MCInst;
3030 class MCSchedModel;
31 class MCSymbolRefExpr;
3132 class SDNode;
3233 class ScheduleHazardRecognizer;
3334 class SelectionDAG;
320321 virtual void ReplaceTailWithBranchTo(MachineBasicBlock::iterator Tail,
321322 MachineBasicBlock *NewDest) const;
322323
324 /// getUnconditionalBranch - Get an instruction that performs an unconditional
325 /// branch to the given symbol.
326 virtual void
327 getUnconditionalBranch(MCInst &MI,
328 const MCSymbolRefExpr *BranchTarget) const {
329 llvm_unreachable("Target didn't implement "
330 "TargetInstrInfo::getUnconditionalBranch!");
331 }
332
333 /// getTrap - Get a machine trap instruction
334 virtual void getTrap(MCInst &MI) const {
335 llvm_unreachable("Target didn't implement TargetInstrInfo::getTrap!");
336 }
337
323338 /// isLegalToSplitMBBAt - Return true if it's legal to split the given basic
324339 /// block at the specified instruction (i.e. instruction would be the start
325340 /// of a new basic block).
3535 Fast, // Enable fusion of FP ops wherever it's profitable.
3636 Standard, // Only allow fusion of 'blessed' ops (currently just fmuladd).
3737 Strict // Never fuse FP-ops.
38 };
39 }
40
41 namespace JumpTable {
42 enum JumpTableType {
43 Single, // Use a single table for all indirect jumptable calls.
44 Arity, // Use one table per number of function parameters.
45 Simplified, // Use one table per function type, with types projected
46 // into 4 types: pointer to non-function, struct,
47 // primitive, and function pointer.
48 Full // Use one table per unique function type
3849 };
3950 }
4051
5364 CompressDebugSections(false), FunctionSections(false),
5465 DataSections(false), TrapUnreachable(false), TrapFuncName(""),
5566 FloatABIType(FloatABI::Default),
56 AllowFPOpFusion(FPOpFusion::Standard) {}
67 AllowFPOpFusion(FPOpFusion::Standard), JTType(JumpTable::Single) {}
5768
5869 /// PrintMachineCode - This flag is enabled when the -print-machineinstrs
5970 /// option is specified on the command line, and should enable debugging
203214 /// via the llvm.fma.* intrinsic) will always be honored, regardless of
204215 /// the value of this option.
205216 FPOpFusion::FPOpFusionMode AllowFPOpFusion;
217
218 /// JTType - This flag specifies the type of jump-instruction table to
219 /// create for functions that have the jumptable attribute.
220 JumpTable::JumpTableType JTType;
206221
207222 /// Machine level options.
208223 MCTargetOptions MCOptions;
165165 LLVMCold = 1ULL << 34,
166166 LLVMOptimizeNone = 1ULL << 35,
167167 LLVMInAllocaAttribute = 1ULL << 36,
168 LLVMNonNullAttribute = 1ULL << 37
168 LLVMNonNullAttribute = 1ULL << 37,
169 LLVMJumpTableAttribute = 1ULL << 38,
169170 */
170171 } LLVMAttribute;
171172
4747 initializeIVUsersPass(Registry);
4848 initializeInstCountPass(Registry);
4949 initializeIntervalPartitionPass(Registry);
50 initializeJumpInstrTableInfoPass(Registry);
5051 initializeLazyValueInfoPass(Registry);
5152 initializeLibCallAliasAnalysisPass(Registry);
5253 initializeLintPass(Registry);
2424 InstructionSimplify.cpp
2525 Interval.cpp
2626 IntervalPartition.cpp
27 JumpInstrTableInfo.cpp
2728 LazyCallGraph.cpp
2829 LazyValueInfo.cpp
2930 LibCallAliasAnalysis.cpp
0 //===-- JumpInstrTableInfo.cpp: Info for Jump-Instruction Tables ----------===//
1 //
2 // This file is distributed under the University of Illinois Open Source
3 // License. See LICENSE.TXT for details.
4 //
5 //===----------------------------------------------------------------------===//
6 ///
7 /// \file
8 /// \brief Information about jump-instruction tables that have been created by
9 /// JumpInstrTables pass.
10 ///
11 //===----------------------------------------------------------------------===//
12
13 #define DEBUG_TYPE "jiti"
14
15 #include "llvm/Analysis/JumpInstrTableInfo.h"
16 #include "llvm/Analysis/Passes.h"
17 #include "llvm/IR/Function.h"
18 #include "llvm/IR/Type.h"
19
20 using namespace llvm;
21
22 INITIALIZE_PASS(JumpInstrTableInfo, "jump-instr-table-info",
23 "Jump-Instruction Table Info", true, true)
24 char JumpInstrTableInfo::ID = 0;
25
26 ImmutablePass *llvm::createJumpInstrTableInfoPass() {
27 return new JumpInstrTableInfo();
28 }
29
30 JumpInstrTableInfo::JumpInstrTableInfo() : ImmutablePass(ID), Tables() {
31 initializeJumpInstrTableInfoPass(*PassRegistry::getPassRegistry());
32 }
33
34 JumpInstrTableInfo::~JumpInstrTableInfo() {}
35
36 void JumpInstrTableInfo::insertEntry(FunctionType *TableFunTy, Function *Target,
37 Function *Jump) {
38 Tables[TableFunTy].push_back(JumpPair(Target, Jump));
39 }
582582 KEYWORD(cold);
583583 KEYWORD(inlinehint);
584584 KEYWORD(inreg);
585 KEYWORD(jumptable);
585586 KEYWORD(minsize);
586587 KEYWORD(naked);
587588 KEYWORD(nest);
946946 case lltok::kw_builtin: B.addAttribute(Attribute::Builtin); break;
947947 case lltok::kw_cold: B.addAttribute(Attribute::Cold); break;
948948 case lltok::kw_inlinehint: B.addAttribute(Attribute::InlineHint); break;
949 case lltok::kw_jumptable: B.addAttribute(Attribute::JumpTable); break;
949950 case lltok::kw_minsize: B.addAttribute(Attribute::MinSize); break;
950951 case lltok::kw_naked: B.addAttribute(Attribute::Naked); break;
951952 case lltok::kw_nobuiltin: B.addAttribute(Attribute::NoBuiltin); break;
12091210 case lltok::kw_alwaysinline:
12101211 case lltok::kw_builtin:
12111212 case lltok::kw_inlinehint:
1213 case lltok::kw_jumptable:
12121214 case lltok::kw_minsize:
12131215 case lltok::kw_naked:
12141216 case lltok::kw_nobuiltin:
12701272 case lltok::kw_builtin:
12711273 case lltok::kw_cold:
12721274 case lltok::kw_inlinehint:
1275 case lltok::kw_jumptable:
12731276 case lltok::kw_minsize:
12741277 case lltok::kw_naked:
12751278 case lltok::kw_nobuiltin:
106106 kw_cold,
107107 kw_inlinehint,
108108 kw_inreg,
109 kw_jumptable,
109110 kw_minsize,
110111 kw_naked,
111112 kw_nest,
548548 return Attribute::InlineHint;
549549 case bitc::ATTR_KIND_IN_REG:
550550 return Attribute::InReg;
551 case bitc::ATTR_KIND_JUMP_TABLE:
552 return Attribute::JumpTable;
551553 case bitc::ATTR_KIND_MIN_SIZE:
552554 return Attribute::MinSize;
553555 case bitc::ATTR_KIND_NAKED:
176176 return bitc::ATTR_KIND_INLINE_HINT;
177177 case Attribute::InReg:
178178 return bitc::ATTR_KIND_IN_REG;
179 case Attribute::JumpTable:
180 return bitc::ATTR_KIND_JUMP_TABLE;
179181 case Attribute::MinSize:
180182 return bitc::ATTR_KIND_MIN_SIZE;
181183 case Attribute::Naked:
1717 #include "llvm/ADT/SmallString.h"
1818 #include "llvm/ADT/Statistic.h"
1919 #include "llvm/Analysis/ConstantFolding.h"
20 #include "llvm/Analysis/JumpInstrTableInfo.h"
2021 #include "llvm/CodeGen/GCMetadataPrinter.h"
2122 #include "llvm/CodeGen/MachineConstantPool.h"
2223 #include "llvm/CodeGen/MachineFrameInfo.h"
888889 EmitVisibility(Name, V, false);
889890 }
890891
892 // Get information about jump-instruction tables to print.
893 JumpInstrTableInfo *JITI = getAnalysisIfAvailable();
894
895 if (JITI && !JITI->getTables().empty()) {
896 unsigned Arch = Triple(getTargetTriple()).getArch();
897 bool IsThumb = (Arch == Triple::thumb || Arch == Triple::thumbeb);
898 MCInst TrapInst;
899 TM.getInstrInfo()->getTrap(TrapInst);
900 for (const auto &KV : JITI->getTables()) {
901 uint64_t Count = 0;
902 for (const auto &FunPair : KV.second) {
903 // Emit the function labels to make this be a function entry point.
904 MCSymbol *FunSym =
905 OutContext.GetOrCreateSymbol(FunPair.second->getName());
906 OutStreamer.EmitSymbolAttribute(FunSym, MCSA_Global);
907 // FIXME: JumpTableInstrInfo should store information about the required
908 // alignment of table entries and the size of the padding instruction.
909 EmitAlignment(3);
910 if (IsThumb)
911 OutStreamer.EmitThumbFunc(FunSym);
912 if (MAI->hasDotTypeDotSizeDirective())
913 OutStreamer.EmitSymbolAttribute(FunSym, MCSA_ELF_TypeFunction);
914 OutStreamer.EmitLabel(FunSym);
915
916 // Emit the jump instruction to transfer control to the original
917 // function.
918 MCInst JumpToFun;
919 MCSymbol *TargetSymbol =
920 OutContext.GetOrCreateSymbol(FunPair.first->getName());
921 const MCSymbolRefExpr *TargetSymRef =
922 MCSymbolRefExpr::Create(TargetSymbol, MCSymbolRefExpr::VK_PLT,
923 OutContext);
924 TM.getInstrInfo()->getUnconditionalBranch(JumpToFun, TargetSymRef);
925 OutStreamer.EmitInstruction(JumpToFun, getSubtargetInfo());
926 ++Count;
927 }
928
929 // Emit enough padding instructions to fill up to the next power of two.
930 // This assumes that the trap instruction takes 8 bytes or fewer.
931 uint64_t Remaining = NextPowerOf2(Count) - Count;
932 for (uint64_t C = 0; C < Remaining; ++C) {
933 EmitAlignment(3);
934 OutStreamer.EmitInstruction(TrapInst, getSubtargetInfo());
935 }
936
937 }
938 }
939
891940 // Emit module flags.
892941 SmallVector ModuleFlags;
893942 M.getModuleFlagsMetadata(ModuleFlags);
2626 InterferenceCache.cpp
2727 IntrinsicLowering.cpp
2828 JITCodeEmitter.cpp
29 JumpInstrTables.cpp
2930 LLVMTargetMachine.cpp
3031 LatencyPriorityQueue.cpp
3132 LexicalScopes.cpp
0 //===-- JumpInstrTables.cpp: Jump-Instruction Tables ----------------------===//
1 //
2 // This file is distributed under the University of Illinois Open Source
3 // License. See LICENSE.TXT for details.
4 //
5 //===----------------------------------------------------------------------===//
6 ///
7 /// \file
8 /// \brief An implementation of jump-instruction tables.
9 ///
10 //===----------------------------------------------------------------------===//
11
12 #define DEBUG_TYPE "jt"
13
14 #include "llvm/CodeGen/JumpInstrTables.h"
15
16 #include "llvm/ADT/Statistic.h"
17 #include "llvm/Analysis/JumpInstrTableInfo.h"
18 #include "llvm/CodeGen/Passes.h"
19 #include "llvm/IR/Attributes.h"
20 #include "llvm/IR/CallSite.h"
21 #include "llvm/IR/Constants.h"
22 #include "llvm/IR/DerivedTypes.h"
23 #include "llvm/IR/Function.h"
24 #include "llvm/IR/LLVMContext.h"
25 #include "llvm/IR/Module.h"
26 #include "llvm/IR/Operator.h"
27 #include "llvm/IR/Type.h"
28 #include "llvm/IR/Verifier.h"
29 #include "llvm/Support/CommandLine.h"
30 #include "llvm/Support/Debug.h"
31 #include "llvm/Support/raw_ostream.h"
32
33 #include
34
35 using namespace llvm;
36
37 char JumpInstrTables::ID = 0;
38
39 INITIALIZE_PASS_BEGIN(JumpInstrTables, "jump-instr-tables",
40 "Jump-Instruction Tables", true, true)
41 INITIALIZE_PASS_DEPENDENCY(JumpInstrTableInfo);
42 INITIALIZE_PASS_END(JumpInstrTables, "jump-instr-tables",
43 "Jump-Instruction Tables", true, true)
44
45 STATISTIC(NumJumpTables, "Number of indirect call tables generated");
46 STATISTIC(NumFuncsInJumpTables, "Number of functions in the jump tables");
47
48 ModulePass *llvm::createJumpInstrTablesPass() {
49 // The default implementation uses a single table for all functions.
50 return new JumpInstrTables(JumpTable::Single);
51 }
52
53 ModulePass *llvm::createJumpInstrTablesPass(JumpTable::JumpTableType JTT) {
54 return new JumpInstrTables(JTT);
55 }
56
57 namespace {
58 static const char jump_func_prefix[] = "__llvm_jump_instr_table_";
59 static const char jump_section_prefix[] = ".jump.instr.table.text.";
60
61 // Checks to see if a given CallSite is making an indirect call, including
62 // cases where the indirect call is made through a bitcast.
63 bool isIndirectCall(CallSite &CS) {
64 if (CS.getCalledFunction())
65 return false;
66
67 // Check the value to see if it is merely a bitcast of a function. In
68 // this case, it will translate to a direct function call in the resulting
69 // assembly, so we won't treat it as an indirect call here.
70 const Value *V = CS.getCalledValue();
71 if (const ConstantExpr *CE = dyn_cast(V)) {
72 return !(CE->isCast() && isa(CE->getOperand(0)));
73 }
74
75 // Otherwise, since we know it's a call, it must be an indirect call
76 return true;
77 }
78
79 // Replaces Functions and GlobalAliases with a different Value.
80 bool replaceGlobalValueIndirectUse(GlobalValue *GV, Value *V, Use *U) {
81 User *Us = U->getUser();
82 if (!Us)
83 return false;
84 if (Instruction *I = dyn_cast(Us)) {
85 CallSite CS(I);
86
87 // Don't do the replacement if this use is a direct call to this function.
88 // If the use is not the called value, then replace it.
89 if (CS && (isIndirectCall(CS) || CS.isCallee(U))) {
90 return false;
91 }
92
93 U->set(V);
94 } else if (Constant *C = dyn_cast(Us)) {
95 // Don't replace calls to bitcasts of function symbols, since they get
96 // translated to direct calls.
97 if (ConstantExpr *CE = dyn_cast(Us)) {
98 if (CE->getOpcode() == Instruction::BitCast) {
99 // This bitcast must have exactly one user.
100 if (CE->user_begin() != CE->user_end()) {
101 User *ParentUs = *CE->user_begin();
102 if (CallInst *CI = dyn_cast(ParentUs)) {
103 CallSite CS(CI);
104 Use &CEU = *CE->use_begin();
105 if (CS.isCallee(&CEU)) {
106 return false;
107 }
108 }
109 }
110 }
111 }
112
113 // GlobalAlias doesn't support replaceUsesOfWithOnConstant. And the verifier
114 // requires alias to point to a defined function. So, GlobalAlias is handled
115 // as a separate case in runOnModule.
116 if (!isa(C))
117 C->replaceUsesOfWithOnConstant(GV, V, U);
118 } else {
119 assert(false && "The Use of a Function symbol is neither an instruction nor"
120 " a constant");
121 }
122
123 return true;
124 }
125
126 // Replaces all replaceable address-taken uses of GV with a pointer to a
127 // jump-instruction table entry.
128 void replaceValueWithFunction(GlobalValue *GV, Function *F) {
129 // Go through all uses of this function and replace the uses of GV with the
130 // jump-table version of the function. Get the uses as a vector before
131 // replacing them, since replacing them changes the use list and invalidates
132 // the iterator otherwise.
133 for (Value::use_iterator I = GV->use_begin(), E = GV->use_end(); I != E;) {
134 Use &U = *I++;
135
136 // Replacement of constants replaces all instances in the constant. So, some
137 // uses might have already been handled by the time we reach them here.
138 if (U.get() == GV)
139 replaceGlobalValueIndirectUse(GV, F, &U);
140 }
141
142 return;
143 }
144 } // end anonymous namespace
145
146 JumpInstrTables::JumpInstrTables()
147 : ModulePass(ID), Metadata(), JITI(nullptr), TableCount(0),
148 JTType(JumpTable::Single) {
149 initializeJumpInstrTablesPass(*PassRegistry::getPassRegistry());
150 }
151
152 JumpInstrTables::JumpInstrTables(JumpTable::JumpTableType JTT)
153 : ModulePass(ID), Metadata(), JITI(nullptr), TableCount(0), JTType(JTT) {
154 initializeJumpInstrTablesPass(*PassRegistry::getPassRegistry());
155 }
156
157 JumpInstrTables::~JumpInstrTables() {}
158
159 void JumpInstrTables::getAnalysisUsage(AnalysisUsage &AU) const {
160 AU.addRequired();
161 }
162
163 Function *JumpInstrTables::insertEntry(Module &M, Function *Target) {
164 FunctionType *OrigFunTy = Target->getFunctionType();
165 FunctionType *FunTy = transformType(OrigFunTy);
166
167 JumpMap::iterator it = Metadata.find(FunTy);
168 if (Metadata.end() == it) {
169 struct TableMeta Meta;
170 Meta.TableNum = TableCount;
171 Meta.Count = 0;
172 Metadata[FunTy] = Meta;
173 it = Metadata.find(FunTy);
174 ++NumJumpTables;
175 ++TableCount;
176 }
177
178 it->second.Count++;
179
180 std::string NewName(jump_func_prefix);
181 NewName += (Twine(it->second.TableNum) + "_" + Twine(it->second.Count)).str();
182 Function *JumpFun =
183 Function::Create(OrigFunTy, GlobalValue::ExternalLinkage, NewName, &M);
184 // The section for this table
185 JumpFun->setSection((jump_section_prefix + Twine(it->second.TableNum)).str());
186 JITI->insertEntry(FunTy, Target, JumpFun);
187
188 ++NumFuncsInJumpTables;
189 return JumpFun;
190 }
191
192 bool JumpInstrTables::hasTable(FunctionType *FunTy) {
193 FunctionType *TransTy = transformType(FunTy);
194 return Metadata.end() != Metadata.find(TransTy);
195 }
196
197 FunctionType *JumpInstrTables::transformType(FunctionType *FunTy) {
198 // Returning nullptr forces all types into the same table, since all types map
199 // to the same type
200 Type *VoidPtrTy = Type::getInt8PtrTy(FunTy->getContext());
201
202 // Ignore the return type.
203 Type *RetTy = VoidPtrTy;
204 bool IsVarArg = FunTy->isVarArg();
205 std::vector ParamTys(FunTy->getNumParams());
206 FunctionType::param_iterator PI, PE;
207 int i = 0;
208
209 std::vector EmptyParams;
210 Type *Int32Ty = Type::getInt32Ty(FunTy->getContext());
211 FunctionType *VoidFnTy = FunctionType::get(
212 Type::getVoidTy(FunTy->getContext()), EmptyParams, false);
213 switch (JTType) {
214 case JumpTable::Single:
215
216 return FunctionType::get(RetTy, EmptyParams, false);
217 case JumpTable::Arity:
218 // Transform all types to void* so that all functions with the same arity
219 // end up in the same table.
220 for (PI = FunTy->param_begin(), PE = FunTy->param_end(); PI != PE;
221 PI++, i++) {
222 ParamTys[i] = VoidPtrTy;
223 }
224
225 return FunctionType::get(RetTy, ParamTys, IsVarArg);
226 case JumpTable::Simplified:
227 // Project all parameters types to one of 3 types: composite, integer, and
228 // function, matching the three subclasses of Type.
229 for (PI = FunTy->param_begin(), PE = FunTy->param_end(); PI != PE;
230 ++PI, ++i) {
231 assert((isa(*PI) || isa(*PI) ||
232 isa(*PI)) &&
233 "This type is not an Integer or a Composite or a Function");
234 if (isa(*PI)) {
235 ParamTys[i] = VoidPtrTy;
236 } else if (isa(*PI)) {
237 ParamTys[i] = VoidFnTy;
238 } else if (isa(*PI)) {
239 ParamTys[i] = Int32Ty;
240 }
241 }
242
243 return FunctionType::get(RetTy, ParamTys, IsVarArg);
244 case JumpTable::Full:
245 // Don't transform this type at all.
246 return FunTy;
247 }
248
249 return nullptr;
250 }
251
252 bool JumpInstrTables::runOnModule(Module &M) {
253 // Make sure the module is well-formed, especially with respect to jumptable.
254 if (verifyModule(M))
255 return false;
256
257 JITI = &getAnalysis();
258
259 // Get the set of jumptable-annotated functions.
260 DenseMap Functions;
261 for (Function &F : M) {
262 if (F.hasFnAttribute(Attribute::JumpTable)) {
263 assert(F.hasUnnamedAddr() &&
264 "Attribute 'jumptable' requires 'unnamed_addr'");
265 Functions[&F] = NULL;
266 }
267 }
268
269 // Create the jump-table functions.
270 for (auto &KV : Functions) {
271 Function *F = KV.first;
272 KV.second = insertEntry(M, F);
273 }
274
275 // GlobalAlias is a special case, because the target of an alias statement
276 // must be a defined function. So, instead of replacing a given function in
277 // the alias, we replace all uses of aliases that target jumptable functions.
278 // Note that there's no need to create these functions, since only aliases
279 // that target known jumptable functions are replaced, and there's no way to
280 // put the jumptable annotation on a global alias.
281 DenseMap Aliases;
282 for (GlobalAlias &GA : M.aliases()) {
283 Constant *Aliasee = GA.getAliasee();
284 if (Function *F = dyn_cast(Aliasee)) {
285 auto it = Functions.find(F);
286 if (it != Functions.end()) {
287 Aliases[&GA] = it->second;
288 }
289 }
290 }
291
292 // Replace each address taken function with its jump-instruction table entry.
293 for (auto &KV : Functions)
294 replaceValueWithFunction(KV.first, KV.second);
295
296 for (auto &KV : Aliases)
297 replaceValueWithFunction(KV.first, KV.second);
298
299 return !Functions.empty();
300 }
1111 //===----------------------------------------------------------------------===//
1212
1313 #include "llvm/Target/TargetMachine.h"
14
15 #include "llvm/Analysis/Passes.h"
1416 #include "llvm/CodeGen/AsmPrinter.h"
17 #include "llvm/CodeGen/JumpInstrTables.h"
1518 #include "llvm/CodeGen/MachineFunctionAnalysis.h"
1619 #include "llvm/CodeGen/MachineModuleInfo.h"
1720 #include "llvm/CodeGen/Passes.h"
1821 #include "llvm/IR/IRPrintingPasses.h"
22 #include "llvm/IR/Verifier.h"
1923 #include "llvm/MC/MCAsmInfo.h"
2024 #include "llvm/MC/MCContext.h"
2125 #include "llvm/MC/MCInstrInfo.h"
8185 bool DisableVerify,
8286 AnalysisID StartAfter,
8387 AnalysisID StopAfter) {
88
8489 // Add internal analysis passes from the target machine.
8590 TM->addAnalysisPasses(PM);
8691
135140 bool DisableVerify,
136141 AnalysisID StartAfter,
137142 AnalysisID StopAfter) {
143 // Passes to handle jumptable function annotations. These can't be handled at
144 // JIT time, so we don't add them directly to addPassesToGenerateCode.
145 PM.add(createJumpInstrTableInfoPass());
146 PM.add(createJumpInstrTablesPass(Options.JTType));
147
138148 // Add common CodeGen passes.
139149 MCContext *Context = addPassesToGenerateCode(this, PM, DisableVerify,
140150 StartAfter, StopAfter);
172172 return "inlinehint";
173173 if (hasAttribute(Attribute::InReg))
174174 return "inreg";
175 if (hasAttribute(Attribute::JumpTable))
176 return "jumptable";
175177 if (hasAttribute(Attribute::MinSize))
176178 return "minsize";
177179 if (hasAttribute(Attribute::Naked))
394396 case Attribute::OptimizeNone: return 1ULL << 42;
395397 case Attribute::InAlloca: return 1ULL << 43;
396398 case Attribute::NonNull: return 1ULL << 44;
399 case Attribute::JumpTable: return 1ULL << 45;
397400 }
398401 llvm_unreachable("Unsupported attribute type");
399402 }
734734 I->getKindAsEnum() == Attribute::Builtin ||
735735 I->getKindAsEnum() == Attribute::NoBuiltin ||
736736 I->getKindAsEnum() == Attribute::Cold ||
737 I->getKindAsEnum() == Attribute::OptimizeNone) {
737 I->getKindAsEnum() == Attribute::OptimizeNone ||
738 I->getKindAsEnum() == Attribute::JumpTable) {
738739 if (!isFunction) {
739740 CheckFailed("Attribute '" + I->getAsString() +
740741 "' only applies to functions!", V);
907908 Assert1(!Attrs.hasAttribute(AttributeSet::FunctionIndex,
908909 Attribute::MinSize),
909910 "Attributes 'minsize and optnone' are incompatible!", V);
911 }
912
913 if (Attrs.hasAttribute(AttributeSet::FunctionIndex,
914 Attribute::JumpTable)) {
915 const GlobalValue *GV = cast(V);
916 Assert1(GV->hasUnnamedAddr(),
917 "Attribute 'jumptable' requires 'unnamed_addr'", V);
918
910919 }
911920 }
912921
9595 initializeConstantMergePass(R);
9696 initializeDAHPass(R);
9797 initializeInstCombinerPass(R);
98 initializeJumpInstrTablesPass(R);
9899 initializeSimpleInlinerPass(R);
99100 initializePruneEHPass(R);
100101 initializeGlobalDCEPass(R);
3131 #include "llvm/IR/Function.h"
3232 #include "llvm/IR/GlobalValue.h"
3333 #include "llvm/MC/MCAsmInfo.h"
34 #include "llvm/MC/MCExpr.h"
3435 #include "llvm/Support/BranchProbability.h"
3536 #include "llvm/Support/CommandLine.h"
3637 #include "llvm/Support/Debug.h"
43574358 MI->addRegisterKilled(DReg, TRI, true);
43584359 }
43594360
4361 void ARMBaseInstrInfo::getUnconditionalBranch(
4362 MCInst &Branch, const MCSymbolRefExpr *BranchTarget) const {
4363 if (Subtarget.isThumb())
4364 Branch.setOpcode(ARM::tB);
4365 else if (Subtarget.isThumb2())
4366 Branch.setOpcode(ARM::t2B);
4367 else
4368 Branch.setOpcode(ARM::Bcc);
4369
4370 Branch.addOperand(MCOperand::CreateExpr(BranchTarget));
4371 Branch.addOperand(MCOperand::CreateImm(ARMCC::AL));
4372 Branch.addOperand(MCOperand::CreateReg(0));
4373 }
4374
4375 void ARMBaseInstrInfo::getTrap(MCInst &MI) const {
4376 if (Subtarget.isThumb())
4377 MI.setOpcode(ARM::tTRAP);
4378 else if (Subtarget.useNaClTrap())
4379 MI.setOpcode(ARM::TRAPNaCl);
4380 else
4381 MI.setOpcode(ARM::TRAP);
4382 }
4383
43604384 bool ARMBaseInstrInfo::hasNOP() const {
43614385 return (Subtarget.getFeatureBits() & ARM::HasV6T2Ops) != 0;
43624386 }
228228 const TargetRegisterInfo*) const override;
229229 void breakPartialRegDependency(MachineBasicBlock::iterator, unsigned,
230230 const TargetRegisterInfo *TRI) const override;
231
232 void
233 getUnconditionalBranch(MCInst &Branch,
234 const MCSymbolRefExpr *BranchTarget) const override;
235
236 void getTrap(MCInst &MI) const override;
237
231238 /// Get the number of addresses by LDM or VLDM or zero for unknown.
232239 unsigned getNumLDMAddresses(const MachineInstr *MI) const;
233240
2727 #include "llvm/IR/DerivedTypes.h"
2828 #include "llvm/IR/LLVMContext.h"
2929 #include "llvm/MC/MCAsmInfo.h"
30 #include "llvm/MC/MCExpr.h"
3031 #include "llvm/MC/MCInst.h"
3132 #include "llvm/Support/CommandLine.h"
3233 #include "llvm/Support/Debug.h"
52985299 NopInst.setOpcode(X86::NOOP);
52995300 }
53005301
5302 void X86InstrInfo::getUnconditionalBranch(
5303 MCInst &Branch, const MCSymbolRefExpr *BranchTarget) const {
5304 Branch.setOpcode(X86::JMP_4);
5305 Branch.addOperand(MCOperand::CreateExpr(BranchTarget));
5306 }
5307
5308 void X86InstrInfo::getTrap(MCInst &MI) const {
5309 MI.setOpcode(X86::TRAP);
5310 }
5311
53015312 bool X86InstrInfo::isHighLatencyDef(int opc) const {
53025313 switch (opc) {
53035314 default: return false;
395395 const SmallVectorImpl &MOs,
396396 unsigned Size, unsigned Alignment) const;
397397
398 void
399 getUnconditionalBranch(MCInst &Branch,
400 const MCSymbolRefExpr *BranchTarget) const override;
401
402 void getTrap(MCInst &MI) const override;
403
398404 bool isHighLatencyDef(int opc) const override;
399405
400406 bool hasHighOperandLatency(const InstrItineraryData *ItinData,
2929 initializeGlobalDCEPass(Registry);
3030 initializeGlobalOptPass(Registry);
3131 initializeIPCPPass(Registry);
32 initializeJumpInstrTablesPass(Registry);
3233 initializeAlwaysInlinerPass(Registry);
3334 initializeSimpleInlinerPass(Registry);
3435 initializeInternalizePassPass(Registry);
202202 ; CHECK: define void @f34()
203203 {
204204 call void @nobuiltin() nobuiltin
205 ; CHECK: call void @nobuiltin() #24
205 ; CHECK: call void @nobuiltin() #25
206206 ret void;
207207 }
208208
220220 define nonnull i8* @f37(i8* nonnull %a) {
221221 ; CHECK: define nonnull i8* @f37(i8* nonnull %a) {
222222 ret i8* %a
223 }
224
225 define void @f38() unnamed_addr jumptable {
226 ; CHECK: define void @f38() unnamed_addr #24
227 call void bitcast (void (i8*)* @f36 to void ()*)()
228 unreachable
223229 }
224230
225231 ; CHECK: attributes #0 = { noreturn }
246252 ; CHECK: attributes #21 = { sspstrong }
247253 ; CHECK: attributes #22 = { minsize }
248254 ; CHECK: attributes #23 = { noinline optnone }
249 ; CHECK: attributes #24 = { nobuiltin }
250
255 ; CHECK: attributes #24 = { jumptable }
256 ; CHECK: attributes #25 = { nobuiltin }
0 ; RUN: llc <%s -march=arm -jump-table-type=single | FileCheck --check-prefix=ARM %s
1 ; RUN: llc <%s -march=thumb -jump-table-type=single | FileCheck --check-prefix=THUMB %s
2
3 define void @indirect_fun() unnamed_addr jumptable {
4 ret void
5 }
6 define void ()* @get_fun() {
7 ret void ()* @indirect_fun
8
9 ; ARM: ldr r0, [[LABEL:.*]]
10 ; ARM: mov pc, lr
11 ; ARM: [[LABEL]]:
12 ; ARM: .long __llvm_jump_instr_table_0_1
13
14 ; THUMB: ldr r0, [[LABEL:.*]]
15 ; THUMB: bx lr
16 ; THUMB: [[LABEL]]:
17 ; THUMB: .long __llvm_jump_instr_table_0_1
18 }
19
20 ; ARM: .globl __llvm_jump_instr_table_0_1
21 ; ARM: .align 3
22 ; ARM: .type __llvm_jump_instr_table_0_1,%function
23 ; ARM: __llvm_jump_instr_table_0_1:
24 ; ARM: b indirect_fun(PLT)
25
26 ; THUMB: .globl __llvm_jump_instr_table_0_1
27 ; THUMB: .align 3
28 ; THUMB: .thumb_func
29 ; THUMB: .type __llvm_jump_instr_table_0_1,%function
30 ; THUMB: __llvm_jump_instr_table_0_1:
31 ; THUMB: b indirect_fun(PLT)
44 ; STOP: Loop Strength Reduction
55 ; STOP-NEXT: Machine Function Analysis
66
7 ; START: -machine-branch-prob -gc-lowering
7 ; START: -machine-branch-prob -jump-instr-tables -gc-lowering
88 ; START: FunctionPass Manager
99 ; START-NEXT: Lower Garbage Collection Instructions
0 ; RUN: llc <%s -jump-table-type=single | FileCheck %s
1 target triple = "x86_64-unknown-linux-gnu"
2 define i32 @f() unnamed_addr jumptable {
3 entry:
4 ret i32 0
5 }
6
7 @i = alias internal i32 ()* @f
8 @j = alias i32 ()* @f
9
10 define i32 @main(i32 %argc, i8** %argv) {
11 %temp = alloca i32 ()*, align 8
12 store i32 ()* @i, i32()** %temp, align 8
13 ; CHECK: movq $__llvm_jump_instr_table_0_1
14 %1 = load i32 ()** %temp, align 8
15 ; CHECK: movl $__llvm_jump_instr_table_0_1
16 %2 = call i32 ()* %1()
17 %3 = call i32 ()* @i()
18 ; CHECK: callq i
19 %4 = call i32 ()* @j()
20 ; CHECK: callq j
21 ret i32 %3
22 }
23
24 ; There should only be one table, even though there are two GlobalAliases,
25 ; because they both alias the same value.
26
27 ; CHECK: .globl __llvm_jump_instr_table_0_1
28 ; CHECK: .align 8, 0x90
29 ; CHECK: .type __llvm_jump_instr_table_0_1,@function
30 ; CHECK: __llvm_jump_instr_table_0_1:
31 ; CHECK: jmp f@PLT
32
0 ; RUN: llc <%s -jump-table-type=single | FileCheck %s
1 target triple = "x86_64-unknown-linux-gnu"
2 define i32 @f() unnamed_addr jumptable {
3 ret i32 0
4 }
5
6 define i32 @g(i8* %a) unnamed_addr jumptable {
7 ret i32 0
8 }
9
10 define void @h(void ()* %func) unnamed_addr jumptable {
11 ret void
12 }
13
14 define i32 @main() {
15 %g = alloca i32 (...)*, align 8
16 store i32 (...)* bitcast (i32 ()* @f to i32 (...)*), i32 (...)** %g, align 8
17 ; CHECK: movq $__llvm_jump_instr_table_0_[[ENTRY:1|2|3]], (%rsp)
18 ; CHECK: movl $__llvm_jump_instr_table_0_[[ENTRY]], %ecx
19 %1 = load i32 (...)** %g, align 8
20 %call = call i32 (...)* %1()
21 call void (void ()*)* @h(void ()* bitcast (void (void ()*)* @h to void ()*))
22 ; CHECK: movl $__llvm_jump_instr_table_0_{{1|2|3}}, %edi
23 ; CHECK: callq h
24
25 %a = call i32 (i32*)* bitcast (i32 (i8*)* @g to i32(i32*)*)(i32* null)
26 ; CHECK: callq g
27 ret i32 %a
28 }
29
30 ; CHECK: .globl __llvm_jump_instr_table_0_1
31 ; CHECK: .align 8, 0x90
32 ; CHECK: .type __llvm_jump_instr_table_0_1,@function
33 ; CHECK: __llvm_jump_instr_table_0_1:
34 ; CHECK: jmp {{f|g|h}}@PLT
35 ; CHECK: .globl __llvm_jump_instr_table_0_2
36 ; CHECK: .align 8, 0x90
37 ; CHECK: .type __llvm_jump_instr_table_0_2,@function
38 ; CHECK: __llvm_jump_instr_table_0_2:
39 ; CHECK: jmp {{f|g|h}}@PLT
40 ; CHECK: .globl __llvm_jump_instr_table_0_3
41 ; CHECK: .align 8, 0x90
42 ; CHECK: .type __llvm_jump_instr_table_0_3,@function
43 ; CHECK: __llvm_jump_instr_table_0_3:
44 ; CHECK: jmp {{f|g|h}}@PLT
45
0 ; RUN: llc <%s -jump-table-type=single | FileCheck --check-prefix=SINGLE %s
1 ; RUN: llc <%s -jump-table-type=arity | FileCheck --check-prefix=ARITY %s
2 ; RUN: llc <%s -jump-table-type=simplified | FileCheck --check-prefix=SIMPL %s
3 ; RUN: llc <%s -jump-table-type=full | FileCheck --check-prefix=FULL %s
4
5 target triple = "x86_64-unknown-linux-gnu"
6
7 %struct.fun_struct = type { i32 (...)* }
8
9 define void @indirect_fun() unnamed_addr jumptable {
10 ret void
11 }
12
13 define void @indirect_fun_match() unnamed_addr jumptable {
14 ret void
15 }
16
17 define i32 @indirect_fun_i32() unnamed_addr jumptable {
18 ret i32 0
19 }
20
21 define i32 @indirect_fun_i32_1(i32 %a) unnamed_addr jumptable {
22 ret i32 %a
23 }
24
25 define i32 @indirect_fun_i32_2(i32 %a, i32 %b) unnamed_addr jumptable {
26 ret i32 %a
27 }
28
29 define i32* @indirect_fun_i32S_2(i32* %a, i32 %b) unnamed_addr jumptable {
30 ret i32* %a
31 }
32
33 define void @indirect_fun_struct(%struct.fun_struct %fs) unnamed_addr jumptable {
34 ret void
35 }
36
37 define void @indirect_fun_fun(i32 (...)* %fun, i32 %a) unnamed_addr jumptable {
38 ret void
39 }
40
41 define i32 @indirect_fun_fun_ret(i32 (...)* %fun, i32 %a) unnamed_addr jumptable {
42 ret i32 %a
43 }
44
45 define void @indirect_fun_array([19 x i8] %a) unnamed_addr jumptable {
46 ret void
47 }
48
49 define void @indirect_fun_vec(<3 x i32> %a) unnamed_addr jumptable {
50 ret void
51 }
52
53 define void @indirect_fun_vec_2(<4 x float> %a) unnamed_addr jumptable {
54 ret void
55 }
56
57 define i32 @m(void ()* %fun) {
58 call void ()* %fun()
59 ret i32 0
60 }
61
62 define void ()* @get_fun() {
63 ret void ()* @indirect_fun
64 ; SINGLE: movl $__llvm_jump_instr_table_0_
65 ; ARITY: movl $__llvm_jump_instr_table_
66 ; SIMPL: movl $__llvm_jump_instr_table_
67 ; FULL: movl $__llvm_jump_instr_table_
68 }
69
70 define i32 @main(i32 %argc, i8** %argv) {
71 %f = call void ()* ()* @get_fun()
72 %a = call i32 @m(void ()* %f)
73 ret i32 %a
74 }
75
76 ; SINGLE-DAG: .globl __llvm_jump_instr_table_0_1
77 ; SINGLE-DAG: .align 8, 0x90
78 ; SINGLE-DAG: .type __llvm_jump_instr_table_0_1,@function
79 ; SINGLE-DAG: __llvm_jump_instr_table_0_1:
80 ; SINGLE-DAG: jmp indirect_fun_array@PLT
81 ; SINGLE-DAG: .globl __llvm_jump_instr_table_0_2
82 ; SINGLE-DAG: .align 8, 0x90
83 ; SINGLE-DAG: .type __llvm_jump_instr_table_0_2,@function
84 ; SINGLE-DAG: __llvm_jump_instr_table_0_2:
85 ; SINGLE-DAG: jmp indirect_fun_i32_2@PLT
86 ; SINGLE-DAG: .globl __llvm_jump_instr_table_0_3
87 ; SINGLE-DAG: .align 8, 0x90
88 ; SINGLE-DAG: .type __llvm_jump_instr_table_0_3,@function
89 ; SINGLE-DAG: __llvm_jump_instr_table_0_3:
90 ; SINGLE-DAG: jmp indirect_fun_vec_2@PLT
91 ; SINGLE-DAG: .globl __llvm_jump_instr_table_0_4
92 ; SINGLE-DAG: .align 8, 0x90
93 ; SINGLE-DAG: .type __llvm_jump_instr_table_0_4,@function
94 ; SINGLE-DAG: __llvm_jump_instr_table_0_4:
95 ; SINGLE-DAG: jmp indirect_fun_i32S_2@PLT
96 ; SINGLE-DAG: .globl __llvm_jump_instr_table_0_5
97 ; SINGLE-DAG: .align 8, 0x90
98 ; SINGLE-DAG: .type __llvm_jump_instr_table_0_5,@function
99 ; SINGLE-DAG: __llvm_jump_instr_table_0_5:
100 ; SINGLE-DAG: jmp indirect_fun_struct@PLT
101 ; SINGLE-DAG: .globl __llvm_jump_instr_table_0_6
102 ; SINGLE-DAG: .align 8, 0x90
103 ; SINGLE-DAG: .type __llvm_jump_instr_table_0_6,@function
104 ; SINGLE-DAG: __llvm_jump_instr_table_0_6:
105 ; SINGLE-DAG: jmp indirect_fun_i32_1@PLT
106 ; SINGLE-DAG: .globl __llvm_jump_instr_table_0_7
107 ; SINGLE-DAG: .align 8, 0x90
108 ; SINGLE-DAG: .type __llvm_jump_instr_table_0_7,@function
109 ; SINGLE-DAG: __llvm_jump_instr_table_0_7:
110 ; SINGLE-DAG: jmp indirect_fun_i32@PLT
111 ; SINGLE-DAG: .globl __llvm_jump_instr_table_0_8
112 ; SINGLE-DAG: .align 8, 0x90
113 ; SINGLE-DAG: .type __llvm_jump_instr_table_0_8,@function
114 ; SINGLE-DAG: __llvm_jump_instr_table_0_8:
115 ; SINGLE-DAG: jmp indirect_fun_fun@PLT
116 ; SINGLE-DAG: .globl __llvm_jump_instr_table_0_9
117 ; SINGLE-DAG: .align 8, 0x90
118 ; SINGLE-DAG: .type __llvm_jump_instr_table_0_9,@function
119 ; SINGLE-DAG: __llvm_jump_instr_table_0_9:
120 ; SINGLE-DAG: jmp indirect_fun_fun_ret@PLT
121 ; SINGLE-DAG: .globl __llvm_jump_instr_table_0_10
122 ; SINGLE-DAG: .align 8, 0x90
123 ; SINGLE-DAG: .type __llvm_jump_instr_table_0_10,@function
124 ; SINGLE-DAG: __llvm_jump_instr_table_0_10:
125 ; SINGLE-DAG: jmp indirect_fun@PLT
126 ; SINGLE-DAG: .globl __llvm_jump_instr_table_0_11
127 ; SINGLE-DAG: .align 8, 0x90
128 ; SINGLE-DAG: .type __llvm_jump_instr_table_0_11,@function
129 ; SINGLE-DAG: __llvm_jump_instr_table_0_11:
130 ; SINGLE-DAG: jmp indirect_fun_match@PLT
131 ; SINGLE-DAG: .globl __llvm_jump_instr_table_0_12
132 ; SINGLE-DAG: .align 8, 0x90
133 ; SINGLE-DAG: .type __llvm_jump_instr_table_0_12,@function
134 ; SINGLE-DAG: __llvm_jump_instr_table_0_12:
135 ; SINGLE-DAG: jmp indirect_fun_vec@PLT
136 ; SINGLE-DAG: .align 8, 0x90
137 ; SINGLE-DAG: ud2
138 ; SINGLE-DAG: .align 8, 0x90
139 ; SINGLE-DAG: ud2
140 ; SINGLE-DAG: .align 8, 0x90
141 ; SINGLE-DAG: ud2
142 ; SINGLE-DAG: .align 8, 0x90
143 ; SINGLE-DAG: ud2
144
145
146 ; ARITY-DAG: .globl __llvm_jump_instr_table_2_1
147 ; ARITY-DAG: .align 8, 0x90
148 ; ARITY-DAG: .type __llvm_jump_instr_table_2_1,@function
149 ; ARITY-DAG: __llvm_jump_instr_table_2_1:
150 ; ARITY-DAG: jmp indirect_fun{{.*}}@PLT
151 ; ARITY-DAG: .align 8, 0x90
152 ; ARITY-DAG: ud2
153 ; ARITY-DAG: .globl __llvm_jump_instr_table_0_1
154 ; ARITY-DAG: .align 8, 0x90
155 ; ARITY-DAG: .type __llvm_jump_instr_table_0_1,@function
156 ; ARITY-DAG: __llvm_jump_instr_table_0_1:
157 ; ARITY-DAG: jmp indirect_fun{{.*}}@PLT
158 ; ARITY-DAG: .globl __llvm_jump_instr_table_1_1
159 ; ARITY-DAG: .align 8, 0x90
160 ; ARITY-DAG: .type __llvm_jump_instr_table_1_1,@function
161 ; ARITY-DAG: __llvm_jump_instr_table_1_1:
162 ; ARITY-DAG: jmp indirect_fun{{.*}}@PLT
163
164 ; SIMPL-DAG: .globl __llvm_jump_instr_table_2_1
165 ; SIMPL-DAG: .align 8, 0x90
166 ; SIMPL-DAG: .type __llvm_jump_instr_table_2_1,@function
167 ; SIMPL-DAG: __llvm_jump_instr_table_2_1:
168 ; SIMPL-DAG: jmp indirect_fun{{.*}}@PLT
169 ; SIMPL-DAG: .align 8, 0x90
170 ; SIMPL-DAG: ud2
171 ; SIMPL-DAG: .globl __llvm_jump_instr_table_0_1
172 ; SIMPL-DAG: .align 8, 0x90
173 ; SIMPL-DAG: .type __llvm_jump_instr_table_0_1,@function
174 ; SIMPL-DAG: __llvm_jump_instr_table_0_1:
175 ; SIMPL-DAG: jmp indirect_fun{{.*}}@PLT
176 ; SIMPL-DAG: .globl __llvm_jump_instr_table_1_1
177 ; SIMPL-DAG: .align 8, 0x90
178 ; SIMPL-DAG: .type __llvm_jump_instr_table_1_1,@function
179 ; SIMPL-DAG: __llvm_jump_instr_table_1_1:
180 ; SIMPL-DAG: jmp indirect_fun{{.*}}@PLT
181 ; SIMPL-DAG: .globl __llvm_jump_instr_table_3_1
182 ; SIMPL-DAG: .align 8, 0x90
183 ; SIMPL-DAG: .type __llvm_jump_instr_table_3_1,@function
184 ; SIMPL-DAG: __llvm_jump_instr_table_3_1:
185 ; SIMPL-DAG: jmp indirect_fun{{.*}}@PLT
186 ; SIMPL-DAG: .globl __llvm_jump_instr_table_4_1
187 ; SIMPL-DAG: .align 8, 0x90
188 ; SIMPL-DAG: .type __llvm_jump_instr_table_4_1,@function
189 ; SIMPL-DAG: __llvm_jump_instr_table_4_1:
190 ; SIMPL-DAG: jmp indirect_fun{{.*}}@PLT
191
192
193 ; FULL-DAG: .globl __llvm_jump_instr_table_10_1
194 ; FULL-DAG: .align 8, 0x90
195 ; FULL-DAG: .type __llvm_jump_instr_table_10_1,@function
196 ; FULL-DAG:__llvm_jump_instr_table_10_1:
197 ; FULL-DAG: jmp indirect_fun_i32_1@PLT
198 ; FULL-DAG: .align 8, 0x90
199 ; FULL-DAG: ud2
200 ; FULL-DAG: .globl __llvm_jump_instr_table_9_1
201 ; FULL-DAG: .align 8, 0x90
202 ; FULL-DAG: .type __llvm_jump_instr_table_9_1,@function
203 ; FULL-DAG:__llvm_jump_instr_table_9_1:
204 ; FULL-DAG: jmp indirect_fun_i32_2@PLT
205 ; FULL-DAG: .align 8, 0x90
206 ; FULL-DAG: ud2
207 ; FULL-DAG: .globl __llvm_jump_instr_table_7_1
208 ; FULL-DAG: .align 8, 0x90
209 ; FULL-DAG: .type __llvm_jump_instr_table_7_1,@function
210 ; FULL-DAG:__llvm_jump_instr_table_7_1:
211 ; FULL-DAG: jmp indirect_fun_i32S_2@PLT
212 ; FULL-DAG: .align 8, 0x90
213 ; FULL-DAG: ud2
214 ; FULL-DAG: .globl __llvm_jump_instr_table_3_1
215 ; FULL-DAG: .align 8, 0x90
216 ; FULL-DAG: .type __llvm_jump_instr_table_3_1,@function
217 ; FULL-DAG:__llvm_jump_instr_table_3_1:
218 ; FULL-DAG: jmp indirect_fun_vec_2@PLT
219 ; FULL-DAG: .align 8, 0x90
220 ; FULL-DAG: ud2
221 ; FULL-DAG: .globl __llvm_jump_instr_table_2_1
222 ; FULL-DAG: .align 8, 0x90
223 ; FULL-DAG: .type __llvm_jump_instr_table_2_1,@function
224 ; FULL-DAG:__llvm_jump_instr_table_2_1:
225 ; FULL-DAG: jmp indirect_fun@PLT
226 ; FULL-DAG: .align 8, 0x90
227 ; FULL-DAG: ud2
228 ; FULL-DAG: .align 8, 0x90
229 ; FULL-DAG: ud2
230 ; FULL-DAG: .globl __llvm_jump_instr_table_8_1
231 ; FULL-DAG: .align 8, 0x90
232 ; FULL-DAG: .type __llvm_jump_instr_table_8_1,@function
233 ; FULL-DAG:__llvm_jump_instr_table_8_1:
234 ; FULL-DAG: jmp indirect_fun_i32@PLT
235 ; FULL-DAG: .align 8, 0x90
236 ; FULL-DAG: ud2
237 ; FULL-DAG: .globl __llvm_jump_instr_table_1_1
238 ; FULL-DAG: .align 8, 0x90
239 ; FULL-DAG: .type __llvm_jump_instr_table_1_1,@function
240 ; FULL-DAG:__llvm_jump_instr_table_1_1:
241 ; FULL-DAG: jmp indirect_fun_array@PLT
242 ; FULL-DAG: .align 8, 0x90
243 ; FULL-DAG: ud2
244 ; FULL-DAG: .globl __llvm_jump_instr_table_0_1
245 ; FULL-DAG: .align 8, 0x90
246 ; FULL-DAG: .type __llvm_jump_instr_table_0_1,@function
247 ; FULL-DAG:__llvm_jump_instr_table_0_1:
248 ; FULL-DAG: jmp indirect_fun_vec@PLT
249 ; FULL-DAG: .align 8, 0x90
250 ; FULL-DAG: ud2
251 ; FULL-DAG: .globl __llvm_jump_instr_table_6_1
252 ; FULL-DAG: .align 8, 0x90
253 ; FULL-DAG: .type __llvm_jump_instr_table_6_1,@function
254 ; FULL-DAG:__llvm_jump_instr_table_6_1:
255 ; FULL-DAG: jmp indirect_fun_struct@PLT
256 ; FULL-DAG: .align 8, 0x90
257 ; FULL-DAG: ud2
258 ; FULL-DAG: .globl __llvm_jump_instr_table_5_1
259 ; FULL-DAG: .align 8, 0x90
260 ; FULL-DAG: .type __llvm_jump_instr_table_5_1,@function
261 ; FULL-DAG:__llvm_jump_instr_table_5_1:
262 ; FULL-DAG: jmp indirect_fun_fun@PLT
263 ; FULL-DAG: .align 8, 0x90
264 ; FULL-DAG: ud2
265 ; FULL-DAG: .globl __llvm_jump_instr_table_4_1
266 ; FULL-DAG: .align 8, 0x90
267 ; FULL-DAG: .type __llvm_jump_instr_table_4_1,@function
268 ; FULL-DAG:__llvm_jump_instr_table_4_1:
269 ; FULL-DAG: jmp indirect_fun_fun_ret@PLT
270 ; FULL-DAG: .align 8, 0x90
271 ; FULL-DAG: ud2
0 ; RUN: not llc <%s 2>&1 | FileCheck %s
1
2 define i32 @f() jumptable {
3 ret i32 0
4 }
5
6 ; CHECK: Attribute 'jumptable' requires 'unnamed_addr'
7 ; CHECK: i32 ()* @f
8 ; CHECK: LLVM ERROR: Broken function found, compilation aborted!