llvm.org GIT mirror llvm / b6c4a84
Add warning capabilities in LLVM. The patch adds a new LLVMContext::diagnose that can be used to communicate to the front-end, if any, that something of interest happened. The diagnostics are supported by a new abstraction, the DiagnosticInfo class. The base class contains the following information: - The kind of the report: What this is about. - The severity of the report: How bad this is. This patch also adds 2 classes: - DiagnosticInfoInlineAsm: For inline asm reporting. Basically, this diagnostic will be used to switch to the new diagnostic API for LLVMContext::emitError. - DiagnosticStackSize: For stack size reporting. Comes as a replacement of the hard coded warning in PEI. This patch also features dynamic diagnostic identifiers. In other words plugins can use this infrastructure for their own diagnostics (for more details, see getNextAvailablePluginDiagnosticKind). This patch introduces a new DiagnosticHandlerTy and a new DiagnosticContext in the LLVMContext that should be set by the front-end to be able to map these diagnostics in its own system. http://llvm-reviews.chandlerc.com/D2376 <rdar://problem/15515174> git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@197438 91177308-0d34-0410-b5e6-96231b3b80d8 Quentin Colombet 6 years ago
12 changed file(s) with 499 addition(s) and 9 deletion(s). Raw diff Collapse all Expand all
2626 class Instruction;
2727 class Module;
2828 class SMDiagnostic;
29 class DiagnosticInfo;
2930 template class SmallVectorImpl;
3031
3132 /// This is an important class for using LLVM in a threaded context. It
6364 typedef void (*InlineAsmDiagHandlerTy)(const SMDiagnostic&, void *Context,
6465 unsigned LocCookie);
6566
67 /// Defines the type of a diagnostic handler.
68 /// \see LLVMContext::setDiagnosticHandler.
69 /// \see LLVMContext::diagnose.
70 typedef void (*DiagnosticHandlerTy)(const DiagnosticInfo &DI, void *Context);
71
6672 /// setInlineAsmDiagnosticHandler - This method sets a handler that is invoked
6773 /// when problems with inline asm are detected by the backend. The first
6874 /// argument is a function pointer and the second is a context pointer that
8187 /// setInlineAsmDiagnosticHandler.
8288 void *getInlineAsmDiagnosticContext() const;
8389
90 /// setDiagnosticHandler - This method sets a handler that is invoked
91 /// when the backend needs to report anything to the user. The first
92 /// argument is a function pointer and the second is a context pointer that
93 /// gets passed into the DiagHandler.
94 ///
95 /// LLVMContext doesn't take ownership or interpret either of these
96 /// pointers.
97 void setDiagnosticHandler(DiagnosticHandlerTy DiagHandler,
98 void *DiagContext = 0);
99
100 /// getDiagnosticHandler - Return the diagnostic handler set by
101 /// setDiagnosticHandler.
102 DiagnosticHandlerTy getDiagnosticHandler() const;
103
104 /// getDiagnosticContext - Return the diagnostic context set by
105 /// setDiagnosticContext.
106 void *getDiagnosticContext() const;
107
108 /// diagnose - Report a message to the currently installed diagnostic handler.
109 /// This function returns, in particular in the case of error reporting
110 /// (DI.Severity == RS_Error), so the caller should leave the compilation
111 /// process in a self-consistent state, even though the generated code
112 /// need not be correct.
113 /// The diagnostic message will be implicitly prefixed with a severity
114 /// keyword according to \p DI.getSeverity(), i.e., "error: "
115 /// for RS_Error, "warning: " for RS_Warning, and "note: " for RS_Note.
116 void diagnose(const DiagnosticInfo &DI);
84117
85118 /// emitError - Emit an error message to the currently installed error handler
86119 /// with optional location information. This function returns, so code should
0 //===- llvm/Support/DiagnosticInfo.h - Diagnostic Declaration ---*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file declares the different classes involved in low level diagnostics.
10 //
11 // Diagnostics reporting is still done as part of the LLVMContext.
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_SUPPORT_DIAGNOSTICINFO_H
15 #define LLVM_SUPPORT_DIAGNOSTICINFO_H
16
17 #include "llvm/ADT/ArrayRef.h"
18 #include "llvm/Support/Casting.h"
19
20 namespace llvm {
21
22 // Forward declarations.
23 class DiagnosticPrinter;
24 class Function;
25 class Instruction;
26 class Twine;
27 class Value;
28
29 /// \brief Defines the different supported severity of a diagnostic.
30 enum DiagnosticSeverity {
31 DS_Error,
32 DS_Warning,
33 DS_Note
34 };
35
36 /// \brief Defines the different supported kind of a diagnostic.
37 /// This enum should be extended with a new ID for each added concrete subclass.
38 enum DiagnosticKind {
39 DK_InlineAsm,
40 DK_StackSize,
41 DK_FirstPluginKind
42 };
43
44 /// \brief Get the next available kind ID for a plugin diagnostic.
45 /// Each time this function is called, it returns a different number.
46 /// Therefore, a plugin that wants to "identify" its own classes
47 /// with a dynamic identifier, just have to use this method to get a new ID
48 /// and assign it to each of its classes.
49 /// The returned ID will be greater than or equal to DK_FirstPluginKind.
50 /// Thus, the plugin identifiers will not conflict with the
51 /// DiagnosticKind values.
52 int getNextAvailablePluginDiagnosticKind();
53
54 /// \brief This is the base abstract class for diagnostic reporting in
55 /// the backend.
56 /// The print method must be overloaded by the subclasses to print a
57 /// user-friendly message in the client of the backend (let us call it a
58 /// frontend).
59 class DiagnosticInfo {
60 private:
61 /// Kind defines the kind of report this is about.
62 const /* DiagnosticKind */ int Kind;
63 /// Severity gives the severity of the diagnostic.
64 const DiagnosticSeverity Severity;
65
66 public:
67 DiagnosticInfo(/* DiagnosticKind */ int Kind, DiagnosticSeverity Severity)
68 : Kind(Kind), Severity(Severity) {}
69
70 virtual ~DiagnosticInfo() {}
71
72 /* DiagnosticKind */ int getKind() const { return Kind; }
73 DiagnosticSeverity getSeverity() const { return Severity; }
74
75 /// Print using the given \p DP a user-friendly message.
76 /// This is the default message that will be printed to the user.
77 /// It is used when the frontend does not directly take advantage
78 /// of the information contained in fields of the subclasses.
79 /// The printed message must not end with '.' nor start with a severity
80 /// keyword.
81 virtual void print(DiagnosticPrinter &DP) const = 0;
82 };
83
84 /// Diagnostic information for inline asm reporting.
85 /// This is basically a message and an optional location.
86 class DiagnosticInfoInlineAsm : public DiagnosticInfo {
87 private:
88 /// Optional line information. 0 if not set.
89 unsigned LocCookie;
90 /// Message to be reported.
91 const Twine &MsgStr;
92 /// Optional origin of the problem.
93 const Instruction *Instr;
94
95 public:
96 /// \p MsgStr is the message to be reported to the frontend.
97 /// This class does not copy \p MsgStr, therefore the reference must be valid
98 /// for the whole life time of the Diagnostic.
99 DiagnosticInfoInlineAsm(const Twine &MsgStr,
100 DiagnosticSeverity Severity = DS_Error)
101 : DiagnosticInfo(DK_InlineAsm, Severity), LocCookie(0), MsgStr(MsgStr),
102 Instr(NULL) {}
103
104 /// \p LocCookie if non-zero gives the line number for this report.
105 /// \p MsgStr gives the message.
106 /// This class does not copy \p MsgStr, therefore the reference must be valid
107 /// for the whole life time of the Diagnostic.
108 DiagnosticInfoInlineAsm(unsigned LocCookie, const Twine &MsgStr,
109 DiagnosticSeverity Severity = DS_Error)
110 : DiagnosticInfo(DK_InlineAsm, Severity), LocCookie(LocCookie),
111 MsgStr(MsgStr), Instr(NULL) {}
112
113 /// \p Instr gives the original instruction that triggered the diagnostic.
114 /// \p MsgStr gives the message.
115 /// This class does not copy \p MsgStr, therefore the reference must be valid
116 /// for the whole life time of the Diagnostic.
117 /// Same for \p I.
118 DiagnosticInfoInlineAsm(const Instruction &I, const Twine &MsgStr,
119 DiagnosticSeverity Severity = DS_Error);
120
121 unsigned getLocCookie() const { return LocCookie; }
122 const Twine &getMsgStr() const { return MsgStr; }
123 const Instruction *getInstruction() const { return Instr; }
124
125 /// \see DiagnosticInfo::print.
126 virtual void print(DiagnosticPrinter &DP) const;
127
128 /// Hand rolled RTTI.
129 static bool classof(const DiagnosticInfo *DI) {
130 return DI->getKind() == DK_InlineAsm;
131 }
132 };
133
134 /// Diagnostic information for stack size reporting.
135 /// This is basically a function and a size.
136 class DiagnosticInfoStackSize : public DiagnosticInfo {
137 private:
138 /// The function that is concerned by this stack size diagnostic.
139 const Function &Fn;
140 /// The computed stack size.
141 unsigned StackSize;
142
143 public:
144 /// \p The function that is concerned by this stack size diagnostic.
145 /// \p The computed stack size.
146 DiagnosticInfoStackSize(const Function &Fn, unsigned StackSize,
147 DiagnosticSeverity Severity = DS_Warning)
148 : DiagnosticInfo(DK_StackSize, Severity), Fn(Fn), StackSize(StackSize) {}
149
150 const Function &getFunction() const { return Fn; }
151 unsigned getStackSize() const { return StackSize; }
152
153 /// \see DiagnosticInfo::print.
154 virtual void print(DiagnosticPrinter &DP) const;
155
156 /// Hand rolled RTTI.
157 static bool classof(const DiagnosticInfo *DI) {
158 return DI->getKind() == DK_StackSize;
159 }
160 };
161
162 } // End namespace llvm
163
164 #endif
0 //===- llvm/Support/DiagnosticPrinter.h - Diagnostic Printer ----*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file declares the main interface for printer backend diagnostic.
10 //
11 // Clients of the backend diagnostics should overload this interface based
12 // on their needs.
13 //===----------------------------------------------------------------------===//
14
15 #ifndef LLVM_SUPPORT_DIAGNOSTICPRINTER_H
16 #define LLVM_SUPPORT_DIAGNOSTICPRINTER_H
17
18 #include
19
20 namespace llvm {
21 // Forward declarations.
22 class raw_ostream;
23 class StringRef;
24 class Twine;
25 class Value;
26
27 /// \brief Interface for custom diagnostic printing.
28 class DiagnosticPrinter {
29 public:
30 virtual ~DiagnosticPrinter() {}
31
32 // Simple types.
33 virtual DiagnosticPrinter &operator<<(char C) = 0;
34 virtual DiagnosticPrinter &operator<<(unsigned char C) = 0;
35 virtual DiagnosticPrinter &operator<<(signed char C) = 0;
36 virtual DiagnosticPrinter &operator<<(StringRef Str) = 0;
37 virtual DiagnosticPrinter &operator<<(const char *Str) = 0;
38 virtual DiagnosticPrinter &operator<<(const std::string &Str) = 0;
39 virtual DiagnosticPrinter &operator<<(unsigned long N) = 0;
40 virtual DiagnosticPrinter &operator<<(long N) = 0;
41 virtual DiagnosticPrinter &operator<<(unsigned long long N) = 0;
42 virtual DiagnosticPrinter &operator<<(long long N) = 0;
43 virtual DiagnosticPrinter &operator<<(const void *P) = 0;
44 virtual DiagnosticPrinter &operator<<(unsigned int N) = 0;
45 virtual DiagnosticPrinter &operator<<(int N) = 0;
46 virtual DiagnosticPrinter &operator<<(double N) = 0;
47 virtual DiagnosticPrinter &operator<<(const Twine &Str) = 0;
48
49 // IR related types.
50 virtual DiagnosticPrinter &operator<<(const Value &V) = 0;
51 };
52
53 /// \brief Basic diagnostic printer that uses an underlying raw_ostream.
54 class DiagnosticPrinterRawOStream : public DiagnosticPrinter {
55 protected:
56 raw_ostream &Stream;
57
58 public:
59 DiagnosticPrinterRawOStream(raw_ostream &Stream) : Stream(Stream) {};
60
61 // Simple types.
62 virtual DiagnosticPrinter &operator<<(char C);
63 virtual DiagnosticPrinter &operator<<(unsigned char C);
64 virtual DiagnosticPrinter &operator<<(signed char C);
65 virtual DiagnosticPrinter &operator<<(StringRef Str);
66 virtual DiagnosticPrinter &operator<<(const char *Str);
67 virtual DiagnosticPrinter &operator<<(const std::string &Str);
68 virtual DiagnosticPrinter &operator<<(unsigned long N);
69 virtual DiagnosticPrinter &operator<<(long N);
70 virtual DiagnosticPrinter &operator<<(unsigned long long N);
71 virtual DiagnosticPrinter &operator<<(long long N);
72 virtual DiagnosticPrinter &operator<<(const void *P);
73 virtual DiagnosticPrinter &operator<<(unsigned int N);
74 virtual DiagnosticPrinter &operator<<(int N);
75 virtual DiagnosticPrinter &operator<<(double N);
76 virtual DiagnosticPrinter &operator<<(const Twine &Str);
77
78 // IR related types.
79 virtual DiagnosticPrinter &operator<<(const Value &V);
80 };
81 } // End namespace llvm
82
83 #endif
2929 #include "llvm/CodeGen/MachineRegisterInfo.h"
3030 #include "llvm/CodeGen/RegisterScavenging.h"
3131 #include "llvm/IR/InlineAsm.h"
32 #include "llvm/IR/LLVMContext.h"
3233 #include "llvm/Support/CommandLine.h"
3334 #include "llvm/Support/Compiler.h"
3435 #include "llvm/Support/Debug.h"
36 #include "llvm/Support/DiagnosticInfo.h"
3537 #include "llvm/Support/raw_ostream.h"
3638 #include "llvm/Target/TargetFrameLowering.h"
3739 #include "llvm/Target/TargetInstrInfo.h"
159161
160162 // Warn on stack size when we exceeds the given limit.
161163 MachineFrameInfo *MFI = Fn.getFrameInfo();
162 if (WarnStackSize.getNumOccurrences() > 0 &&
163 WarnStackSize < MFI->getStackSize())
164 errs() << "warning: Stack size limit exceeded (" << MFI->getStackSize()
165 << ") in " << Fn.getName() << ".\n";
164 uint64_t StackSize = MFI->getStackSize();
165 if (WarnStackSize.getNumOccurrences() > 0 && WarnStackSize < StackSize) {
166 DiagnosticInfoStackSize DiagStackSize(*F, StackSize);
167 F->getContext().diagnose(DiagStackSize);
168 }
166169
167170 delete RS;
168171 ReturnBlocks.clear();
1616 #include "llvm/IR/Constants.h"
1717 #include "llvm/IR/Instruction.h"
1818 #include "llvm/IR/Metadata.h"
19 #include "llvm/Support/DiagnosticInfo.h"
20 #include "llvm/Support/DiagnosticPrinter.h"
1921 #include "llvm/Support/ManagedStatic.h"
2022 #include "llvm/Support/SourceMgr.h"
2123 #include
9597 /// setInlineAsmDiagnosticHandler.
9698 void *LLVMContext::getInlineAsmDiagnosticContext() const {
9799 return pImpl->InlineAsmDiagContext;
100 }
101
102 void LLVMContext::setDiagnosticHandler(DiagnosticHandlerTy DiagnosticHandler,
103 void *DiagnosticContext) {
104 pImpl->DiagnosticHandler = DiagnosticHandler;
105 pImpl->DiagnosticContext = DiagnosticContext;
106 }
107
108 LLVMContext::DiagnosticHandlerTy LLVMContext::getDiagnosticHandler() const {
109 return pImpl->DiagnosticHandler;
110 }
111
112 void *LLVMContext::getDiagnosticContext() const {
113 return pImpl->DiagnosticContext;
98114 }
99115
100116 void LLVMContext::emitError(const Twine &ErrorStr) {
109125 LocCookie = CI->getZExtValue();
110126 }
111127 return emitError(LocCookie, ErrorStr);
128 }
129
130 void LLVMContext::diagnose(const DiagnosticInfo &DI) {
131 // If there is a report handler, use it.
132 if (pImpl->DiagnosticHandler != 0) {
133 pImpl->DiagnosticHandler(DI, pImpl->DiagnosticContext);
134 return;
135 }
136 // Otherwise, print the message with a prefix based on the severity.
137 std::string MsgStorage;
138 raw_string_ostream Stream(MsgStorage);
139 DiagnosticPrinterRawOStream DP(Stream);
140 DI.print(DP);
141 Stream.flush();
142 switch (DI.getSeverity()) {
143 case DS_Error:
144 errs() << "error: " << MsgStorage << "\n";
145 exit(1);
146 case DS_Warning:
147 errs() << "warning: " << MsgStorage << "\n";
148 break;
149 case DS_Note:
150 errs() << "note: " << MsgStorage << "\n";
151 break;
152 }
112153 }
113154
114155 void LLVMContext::emitError(unsigned LocCookie, const Twine &ErrorStr) {
3636 Int64Ty(C, 64) {
3737 InlineAsmDiagHandler = 0;
3838 InlineAsmDiagContext = 0;
39 DiagnosticHandler = 0;
40 DiagnosticContext = 0;
3941 NamedStructTypesUniqueID = 0;
4042 }
4143
237237
238238 LLVMContext::InlineAsmDiagHandlerTy InlineAsmDiagHandler;
239239 void *InlineAsmDiagContext;
240
241 typedef DenseMap
242 DenseMapAPIntKeyInfo> IntMapTy;
240
241 LLVMContext::DiagnosticHandlerTy DiagnosticHandler;
242 void *DiagnosticContext;
243
244 typedef DenseMap
245 DenseMapAPIntKeyInfo> IntMapTy;
243246 IntMapTy IntConstants;
244247
245248 typedef DenseMap
1616 Debug.cpp
1717 DeltaAlgorithm.cpp
1818 DAGDeltaAlgorithm.cpp
19 DiagnosticInfo.cpp
20 DiagnosticPrinter.cpp
1921 Dwarf.cpp
2022 ErrorHandling.cpp
2123 FileUtilities.cpp
0 //===- llvm/Support/DiagnosticInfo.cpp - Diagnostic Definitions -*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the different classes involved in low level diagnostics.
10 //
11 // Diagnostics reporting is still done as part of the LLVMContext.
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/ADT/Twine.h"
15 #include "llvm/IR/Constants.h"
16 #include "llvm/IR/Function.h"
17 #include "llvm/IR/Instruction.h"
18 #include "llvm/IR/Metadata.h"
19 #include "llvm/Support/Atomic.h"
20 #include "llvm/Support/DiagnosticInfo.h"
21 #include "llvm/Support/DiagnosticPrinter.h"
22
23 #include
24
25 using namespace llvm;
26
27 int getNextAvailablePluginDiagnosticKind() {
28 static sys::cas_flag PluginKindID = DK_FirstPluginKind;
29 return (int)sys::AtomicIncrement(&PluginKindID);
30 }
31
32 DiagnosticInfoInlineAsm::DiagnosticInfoInlineAsm(const Instruction &I,
33 const Twine &MsgStr,
34 DiagnosticSeverity Severity)
35 : DiagnosticInfo(DK_InlineAsm, Severity), LocCookie(0), MsgStr(MsgStr),
36 Instr(&I) {
37 if (const MDNode *SrcLoc = I.getMetadata("srcloc")) {
38 if (SrcLoc->getNumOperands() != 0)
39 if (const ConstantInt *CI = dyn_cast(SrcLoc->getOperand(0)))
40 LocCookie = CI->getZExtValue();
41 }
42 }
43
44 void DiagnosticInfoInlineAsm::print(DiagnosticPrinter &DP) const {
45 DP << getMsgStr();
46 if (getLocCookie())
47 DP << " at line " << getLocCookie();
48 }
49
50 void DiagnosticInfoStackSize::print(DiagnosticPrinter &DP) const {
51 DP << "stack size limit exceeded (" << getStackSize() << ") in "
52 << getFunction();
53 }
0 //===- llvm/Support/DiagnosticInfo.cpp - Diagnostic Definitions -*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the a diagnostic printer relying on raw_ostream.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "llvm/ADT/Twine.h"
14 #include "llvm/Analysis/ScalarEvolution.h"
15 #include "llvm/CodeGen/MachineInstr.h"
16 #include "llvm/IR/Value.h"
17 #include "llvm/Support/DiagnosticPrinter.h"
18 #include "llvm/Support/raw_ostream.h"
19
20 using namespace llvm;
21
22 DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(char C) {
23 Stream << C;
24 return *this;
25 }
26
27 DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(unsigned char C) {
28 Stream << C;
29 return *this;
30 }
31
32 DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(signed char C) {
33 Stream << C;
34 return *this;
35 }
36
37 DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(StringRef Str) {
38 Stream << Str;
39 return *this;
40 }
41
42 DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(const char *Str) {
43 Stream << Str;
44 return *this;
45 }
46
47 DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(
48 const std::string &Str) {
49 Stream << Str;
50 return *this;
51 }
52
53 DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(unsigned long N) {
54 Stream << N;
55 return *this;
56 }
57 DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(long N) {
58 Stream << N;
59 return *this;
60 }
61
62 DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(
63 unsigned long long N) {
64 Stream << N;
65 return *this;
66 }
67
68 DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(long long N) {
69 Stream << N;
70 return *this;
71 }
72
73 DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(const void *P) {
74 Stream << P;
75 return *this;
76 }
77
78 DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(unsigned int N) {
79 Stream << N;
80 return *this;
81 }
82
83 DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(int N) {
84 Stream << N;
85 return *this;
86 }
87
88 DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(double N) {
89 Stream << N;
90 return *this;
91 }
92
93 DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(const Twine &Str) {
94 Stream << Str.getSingleStringRef();
95 return *this;
96 }
97
98 // IR related types.
99 DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(const Value &V) {
100 Stream << V.getName();
101 return *this;
102 }
1111 ret void
1212 }
1313
14 ; CHECK: warning: Stack size limit exceeded (96) in warn.
14 ; CHECK: warning: stack size limit exceeded (96) in warn
1515 define void @warn() nounwind ssp {
1616 entry:
1717 %buffer = alloca [80 x i8], align 1
1111 ret void
1212 }
1313
14 ; CHECK: warning: Stack size limit exceeded (104) in warn.
14 ; CHECK: warning: stack size limit exceeded (104) in warn
1515 define void @warn() nounwind ssp {
1616 entry:
1717 %buffer = alloca [80 x i8], align 1