Add a new function attribute, 'alignstack'. It will indicate (when the backends
authorCharles Davis <cdavis@mines.edu>
Fri, 12 Feb 2010 00:31:15 +0000 (00:31 +0000)
committerCharles Davis <cdavis@mines.edu>
Fri, 12 Feb 2010 00:31:15 +0000 (00:31 +0000)
implement support for it) that the stack should be forcibly realigned in the
prologue (and the process reversed in the epilogue).

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@95945 91177308-0d34-0410-b5e6-96231b3b80d8

docs/LangRef.html
include/llvm/Attributes.h
lib/AsmParser/LLParser.cpp
lib/AsmParser/LLParser.h
lib/VMCore/Attributes.cpp
test/Feature/alignment.ll

index fed2f80696c3cbcfb4b06dbaee8d5ae39cea1f51..9590609a872cad7dba7abd9318e8b56a9717e96f 100644 (file)
@@ -1078,6 +1078,11 @@ define void @f() optsize { ... }
 </div>
 
 <dl>
+  <dt><tt><b>alignstack(&lt;<em>n</em>&gt;)</b></tt></dt>
+  <dd>This attribute indicates that, when emitting the prologue and epilogue,
+      the backend should forcibly align the stack pointer. Specify the
+      desired alignment, which must be a power of two, in parentheses.
+
   <dt><tt><b>alwaysinline</b></tt></dt>
   <dd>This attribute indicates that the inliner should attempt to inline this
       function into callers whenever possible, ignoring any active inlining size
index 068f81fc7de22e3b98ef99b60f0cdf8ab43b31a8..126c290b5a74f9ff22300dd9300120e5e9502013 100644 (file)
@@ -60,6 +60,11 @@ const Attributes NoImplicitFloat = 1<<23; /// disable implicit floating point
 const Attributes Naked           = 1<<24; ///< Naked function
 const Attributes InlineHint      = 1<<25; ///< source said inlining was
                                           ///desirable
+const Attributes StackAlignment  = 31<<26; ///< Alignment of stack for
+                                           ///function (5 bits) stored as log2
+                                           ///of alignment with +1 bias
+                                           ///0 means unaligned (different from
+                                           ///alignstack(1))
 
 /// @brief Attributes that only apply to function parameters.
 const Attributes ParameterOnly = ByVal | Nest | StructRet | NoCapture;
@@ -68,7 +73,7 @@ const Attributes ParameterOnly = ByVal | Nest | StructRet | NoCapture;
 /// be used on return values or function parameters.
 const Attributes FunctionOnly = NoReturn | NoUnwind | ReadNone | ReadOnly |
   NoInline | AlwaysInline | OptimizeForSize | StackProtect | StackProtectReq |
-  NoRedZone | NoImplicitFloat | Naked | InlineHint;
+  NoRedZone | NoImplicitFloat | Naked | InlineHint | StackAlignment;
 
 /// @brief Parameter attributes that do not apply to vararg call arguments.
 const Attributes VarArgsIncompatible = StructRet;
@@ -105,6 +110,28 @@ inline unsigned getAlignmentFromAttrs(Attributes A) {
   return 1U << ((Align >> 16) - 1);
 }
 
+/// This turns an int stack alignment (which must be a power of 2) into
+/// the form used internally in Attributes.
+inline Attributes constructStackAlignmentFromInt(unsigned i) {
+  // Default alignment, allow the target to define how to align it.
+  if (i == 0)
+    return 0;
+
+  assert(isPowerOf2_32(i) && "Alignment must be a power of two.");
+  assert(i <= 0x40000000 && "Alignment too large.");
+  return (Log2_32(i)+1) << 26;
+}
+
+/// This returns the stack alignment field of an attribute as a byte alignment
+/// value.
+inline unsigned getStackAlignmentFromAttrs(Attributes A) {
+  Attributes StackAlign = A & Attribute::StackAlignment;
+  if (StackAlign == 0)
+    return 0;
+
+  return 1U << ((StackAlign >> 26) - 1);
+}
+
 
 /// The set of Attributes set in Attributes is converted to a
 /// string of equivalent mnemonics. This is, presumably, for writing out
index 5dd65691a3d1f2449624a6bf6fffd117c72e3dbf..4dab11826bc4aa11ec031457675f7886b70ee9d6 100644 (file)
@@ -956,6 +956,14 @@ bool LLParser::ParseOptionalAttrs(unsigned &Attrs, unsigned AttrKind) {
     case lltok::kw_noimplicitfloat: Attrs |= Attribute::NoImplicitFloat; break;
     case lltok::kw_naked:           Attrs |= Attribute::Naked; break;
 
+    case lltok::kw_alignstack: {
+      unsigned Alignment;
+      if (ParseOptionalStackAlignment(Alignment))
+        return true;
+      Attrs |= Attribute::constructStackAlignmentFromInt(Alignment);
+      continue;
+    }
+
     case lltok::kw_align: {
       unsigned Alignment;
       if (ParseOptionalAlignment(Alignment))
@@ -963,6 +971,7 @@ bool LLParser::ParseOptionalAttrs(unsigned &Attrs, unsigned AttrKind) {
       Attrs |= Attribute::constructAlignmentFromInt(Alignment);
       continue;
     }
+
     }
     Lex.Lex();
   }
@@ -1131,6 +1140,25 @@ bool LLParser::ParseOptionalCommaAlign(unsigned &Alignment,
   return false;
 }
 
+/// ParseOptionalStackAlignment
+///   ::= /* empty */
+///   ::= 'alignstack' '(' 4 ')'
+bool LLParser::ParseOptionalStackAlignment(unsigned &Alignment) {
+  Alignment = 0;
+  if (!EatIfPresent(lltok::kw_alignstack))
+    return false;
+  LocTy ParenLoc = Lex.getLoc();
+  if (!EatIfPresent(lltok::lparen))
+    return Error(ParenLoc, "expected '('");
+  LocTy AlignLoc = Lex.getLoc();
+  if (ParseUInt32(Alignment)) return true;
+  ParenLoc = Lex.getLoc();
+  if (!EatIfPresent(lltok::rparen))
+    return Error(ParenLoc, "expected ')'");
+  if (!isPowerOf2_32(Alignment))
+    return Error(AlignLoc, "stack alignment is not a power of two");
+  return false;
+}
 
 /// ParseIndexList - This parses the index list for an insert/extractvalue
 /// instruction.  This sets AteExtraComma in the case where we eat an extra
index 85c07ffa8fd1039626eda418294452a01afd4273..ed7a1d7117681ddae6371b6befdb25b36c665de3 100644 (file)
@@ -169,6 +169,7 @@ namespace llvm {
     bool ParseOptionalVisibility(unsigned &Visibility);
     bool ParseOptionalCallingConv(CallingConv::ID &CC);
     bool ParseOptionalAlignment(unsigned &Alignment);
+    bool ParseOptionalStackAlignment(unsigned &Alignment);
     bool ParseInstructionMetadata(SmallVectorImpl<std::pair<unsigned,
                                                             MDNode *> > &);
     bool ParseOptionalCommaAlign(unsigned &Alignment, bool &AteExtraComma);
index a371c6f92eb45ad51c4498357965073c8ebc66b5..6fa597e9587cc3381800f51aafde23dbf290e4d0 100644 (file)
@@ -70,6 +70,11 @@ std::string Attribute::getAsString(Attributes Attrs) {
     Result += "noimplicitfloat ";
   if (Attrs & Attribute::Naked)
     Result += "naked ";
+  if (Attrs & Attribute::StackAlignment) {
+    Result += "alignstack(";
+    Result += utostr(Attribute::getStackAlignmentFromAttrs(Attrs));
+    Result += ") ";
+  }
   if (Attrs & Attribute::Alignment) {
     Result += "align ";
     Result += utostr(Attribute::getAlignmentFromAttrs(Attrs));
index 409efebe84babaa7cb7a6641e8000b652f78a2c0..ef35a1344a2fbb1eb8246f7fd57df2abe0337931 100644 (file)
@@ -19,3 +19,7 @@ define i32* @test2() {
         ret i32* %X
 }
 
+define void @test3() alignstack(16) {
+        ret void
+}
+