mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-14 14:24:05 +00:00
Introducing nocapture, a parameter attribute for pointers to indicate that the
callee will not introduce any new aliases of that pointer. The attributes had all bits allocated already, so I decided to collapse alignment. Alignment was previously stored as a 16-bit integer from bits 16 to 32 of the attribute, but it was required to be a power of 2. Now it's stored in log2 encoded form in five bits from 16 to 21. That gives us 11 more bits of space. You may have already noticed that you only need four bits to encode a 16-bit power of two, so why five bits? Because the AsmParser accepted 32-bit alignments, even though we couldn't store them (they were silently discarded). Now we can store them in memory, but not in the bitcode. The bitcode format was already storing these as 64-bit VBR integers. So, the bitcode format stays the same, keeping the alignment values stored as 16 bit raw values. There's some hideous code in the reader and writer that deals with this, waiting to be ripped out the moment we run out of bits again and have to replace the parameter attributes table encoding. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@61019 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -192,11 +192,11 @@ and returns MustAlias, MayAlias, or NoAlias as appropriate.
|
|||||||
|
|
||||||
<div class="doc_text">
|
<div class="doc_text">
|
||||||
<p>The NoAlias response is used when the two pointers refer to distinct objects,
|
<p>The NoAlias response is used when the two pointers refer to distinct objects,
|
||||||
even regardless of whether the pointers compare equal. For example, freed
|
regardless of whether the pointers compare equal. For example, freed pointers
|
||||||
pointers don't alias any pointers that were allocated afterwards. As a
|
don't alias any pointers that were allocated afterwards. As a degenerate case,
|
||||||
degenerate case, pointers returned by malloc(0) have no bytes for an object,
|
pointers returned by malloc(0) have no bytes for an object, and are considered
|
||||||
and are considered NoAlias even when malloc returns the same pointer. The same
|
NoAlias even when malloc returns the same pointer. The same rule applies to
|
||||||
rule applies to NULL pointers.</p>
|
NULL pointers.</p>
|
||||||
|
|
||||||
<p>The MayAlias response is used whenever the two pointers might refer to the
|
<p>The MayAlias response is used whenever the two pointers might refer to the
|
||||||
same object. If the two memory objects overlap, but do not start at the same
|
same object. If the two memory objects overlap, but do not start at the same
|
||||||
|
@ -894,9 +894,15 @@ declare signext i8 @returns_signed_char()
|
|||||||
parameter. The caller is responsible for ensuring that this is the
|
parameter. The caller is responsible for ensuring that this is the
|
||||||
case. On a function return value, <tt>noalias</tt> additionally indicates
|
case. On a function return value, <tt>noalias</tt> additionally indicates
|
||||||
that the pointer does not alias any other pointers visible to the
|
that the pointer does not alias any other pointers visible to the
|
||||||
caller. Note that this applies only to pointers that can be used to actually
|
caller. For further details, please see the discussion of the NoAlias
|
||||||
load/store a value: NULL, unique pointers from malloc(0), and freed pointers
|
response in
|
||||||
are considered to not alias anything.</dd>
|
<a href="http://llvm.org/docs/AliasAnalysis.html#MustMayNo">alias
|
||||||
|
analysis</a>.</dd>
|
||||||
|
|
||||||
|
<dt><tt>nocapture</tt></dt>
|
||||||
|
<dd>This indicates that the callee does not make any copies of the pointer
|
||||||
|
that outlive the callee itself. This is not a valid attribute for return
|
||||||
|
values.</dd>
|
||||||
|
|
||||||
<dt><tt>nest</tt></dt>
|
<dt><tt>nest</tt></dt>
|
||||||
<dd>This indicates that the pointer parameter can be excised using the
|
<dd>This indicates that the pointer parameter can be excised using the
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#ifndef LLVM_ATTRIBUTES_H
|
#ifndef LLVM_ATTRIBUTES_H
|
||||||
#define LLVM_ATTRIBUTES_H
|
#define LLVM_ATTRIBUTES_H
|
||||||
|
|
||||||
|
#include "llvm/Support/MathExtras.h"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@ -23,7 +24,7 @@ class Type;
|
|||||||
|
|
||||||
/// Attributes - A bitset of attributes.
|
/// Attributes - A bitset of attributes.
|
||||||
typedef unsigned Attributes;
|
typedef unsigned Attributes;
|
||||||
|
|
||||||
namespace Attribute {
|
namespace Attribute {
|
||||||
|
|
||||||
/// Function parameters and results can have attributes to indicate how they
|
/// Function parameters and results can have attributes to indicate how they
|
||||||
@ -44,16 +45,17 @@ const Attributes ByVal = 1<<7; ///< Pass structure by value
|
|||||||
const Attributes Nest = 1<<8; ///< Nested function static chain
|
const Attributes Nest = 1<<8; ///< Nested function static chain
|
||||||
const Attributes ReadNone = 1<<9; ///< Function does not access memory
|
const Attributes ReadNone = 1<<9; ///< Function does not access memory
|
||||||
const Attributes ReadOnly = 1<<10; ///< Function only reads from memory
|
const Attributes ReadOnly = 1<<10; ///< Function only reads from memory
|
||||||
const Attributes NoInline = 1<<11; // inline=never
|
const Attributes NoInline = 1<<11; ///< inline=never
|
||||||
const Attributes AlwaysInline = 1<<12; // inline=always
|
const Attributes AlwaysInline = 1<<12; ///< inline=always
|
||||||
const Attributes OptimizeForSize = 1<<13; // opt_size
|
const Attributes OptimizeForSize = 1<<13; ///< opt_size
|
||||||
const Attributes StackProtect = 1<<14; // Stack protection.
|
const Attributes StackProtect = 1<<14; ///< Stack protection.
|
||||||
const Attributes StackProtectReq = 1<<15; // Stack protection required.
|
const Attributes StackProtectReq = 1<<15; ///< Stack protection required.
|
||||||
const Attributes Alignment = 0xffff<<16; ///< Alignment of parameter (16 bits)
|
const Attributes Alignment = 31<<16; ///< Alignment of parameter (5 bits)
|
||||||
// 0 = unknown, else in clear (not log)
|
// stored as log2 of alignment.
|
||||||
|
const Attributes NoCapture = 1<<21; ///< Function creates no aliases of pointer
|
||||||
|
|
||||||
/// @brief Attributes that only apply to function parameters.
|
/// @brief Attributes that only apply to function parameters.
|
||||||
const Attributes ParameterOnly = ByVal | Nest | StructRet;
|
const Attributes ParameterOnly = ByVal | Nest | StructRet | NoCapture;
|
||||||
|
|
||||||
/// @brief Attributes that only apply to function.
|
/// @brief Attributes that only apply to function.
|
||||||
const Attributes FunctionOnly = NoReturn | NoUnwind | ReadNone | ReadOnly |
|
const Attributes FunctionOnly = NoReturn | NoUnwind | ReadNone | ReadOnly |
|
||||||
@ -64,7 +66,7 @@ const Attributes VarArgsIncompatible = StructRet;
|
|||||||
|
|
||||||
/// @brief Attributes that are mutually incompatible.
|
/// @brief Attributes that are mutually incompatible.
|
||||||
const Attributes MutuallyIncompatible[4] = {
|
const Attributes MutuallyIncompatible[4] = {
|
||||||
ByVal | InReg | Nest | StructRet,
|
ByVal | InReg | Nest | StructRet,
|
||||||
ZExt | SExt,
|
ZExt | SExt,
|
||||||
ReadNone | ReadOnly,
|
ReadNone | ReadOnly,
|
||||||
NoInline | AlwaysInline
|
NoInline | AlwaysInline
|
||||||
@ -76,7 +78,8 @@ Attributes typeIncompatible(const Type *Ty);
|
|||||||
/// This turns an int alignment (a power of 2, normally) into the
|
/// This turns an int alignment (a power of 2, normally) into the
|
||||||
/// form used internally in Attributes.
|
/// form used internally in Attributes.
|
||||||
inline Attributes constructAlignmentFromInt(unsigned i) {
|
inline Attributes constructAlignmentFromInt(unsigned i) {
|
||||||
return (i << 16);
|
assert(isPowerOf2_32(i) && "Alignment must be a power of two.");
|
||||||
|
return Log2_32(i) << 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The set of Attributes set in Attributes is converted to a
|
/// The set of Attributes set in Attributes is converted to a
|
||||||
|
@ -491,6 +491,7 @@ int LLLexer::LexIdentifier() {
|
|||||||
KEYWORD("nounwind", NOUNWIND);
|
KEYWORD("nounwind", NOUNWIND);
|
||||||
KEYWORD("noreturn", NORETURN);
|
KEYWORD("noreturn", NORETURN);
|
||||||
KEYWORD("noalias", NOALIAS);
|
KEYWORD("noalias", NOALIAS);
|
||||||
|
KEYWORD("nocapture", NOCAPTURE);
|
||||||
KEYWORD("byval", BYVAL);
|
KEYWORD("byval", BYVAL);
|
||||||
KEYWORD("nest", NEST);
|
KEYWORD("nest", NEST);
|
||||||
KEYWORD("readnone", READNONE);
|
KEYWORD("readnone", READNONE);
|
||||||
|
@ -1136,8 +1136,8 @@ Module *llvm::RunVMAsmParser(llvm::MemoryBuffer *MB) {
|
|||||||
%token <OtherOpVal> EXTRACTVALUE INSERTVALUE
|
%token <OtherOpVal> EXTRACTVALUE INSERTVALUE
|
||||||
|
|
||||||
// Function Attributes
|
// Function Attributes
|
||||||
%token SIGNEXT ZEROEXT NORETURN INREG SRET NOUNWIND NOALIAS BYVAL NEST
|
%token SIGNEXT ZEROEXT NORETURN INREG SRET NOUNWIND NOALIAS NOCAPTURE BYVAL
|
||||||
%token READNONE READONLY GC OPTSIZE NOINLINE ALWAYSINLINE SSP SSPREQ
|
%token READNONE READONLY GC OPTSIZE NOINLINE ALWAYSINLINE SSP SSPREQ NEST
|
||||||
|
|
||||||
// Visibility Styles
|
// Visibility Styles
|
||||||
%token DEFAULT HIDDEN PROTECTED
|
%token DEFAULT HIDDEN PROTECTED
|
||||||
@ -1265,15 +1265,16 @@ OptCallingConv : /*empty*/ { $$ = CallingConv::C; } |
|
|||||||
CHECK_FOR_ERROR
|
CHECK_FOR_ERROR
|
||||||
};
|
};
|
||||||
|
|
||||||
Attribute : ZEROEXT { $$ = Attribute::ZExt; }
|
Attribute : ZEROEXT { $$ = Attribute::ZExt; }
|
||||||
| ZEXT { $$ = Attribute::ZExt; }
|
| ZEXT { $$ = Attribute::ZExt; }
|
||||||
| SIGNEXT { $$ = Attribute::SExt; }
|
| SIGNEXT { $$ = Attribute::SExt; }
|
||||||
| SEXT { $$ = Attribute::SExt; }
|
| SEXT { $$ = Attribute::SExt; }
|
||||||
| INREG { $$ = Attribute::InReg; }
|
| INREG { $$ = Attribute::InReg; }
|
||||||
| SRET { $$ = Attribute::StructRet; }
|
| SRET { $$ = Attribute::StructRet; }
|
||||||
| NOALIAS { $$ = Attribute::NoAlias; }
|
| NOALIAS { $$ = Attribute::NoAlias; }
|
||||||
| BYVAL { $$ = Attribute::ByVal; }
|
| NOCAPTURE { $$ = Attribute::NoCapture; }
|
||||||
| NEST { $$ = Attribute::Nest; }
|
| BYVAL { $$ = Attribute::ByVal; }
|
||||||
|
| NEST { $$ = Attribute::Nest; }
|
||||||
| ALIGN EUINT64VAL { $$ =
|
| ALIGN EUINT64VAL { $$ =
|
||||||
Attribute::constructAlignmentFromInt($2); }
|
Attribute::constructAlignmentFromInt($2); }
|
||||||
;
|
;
|
||||||
|
@ -362,6 +362,20 @@ bool BitcodeReader::ParseAttributeBlock() {
|
|||||||
Attributes RetAttribute = Attribute::None;
|
Attributes RetAttribute = Attribute::None;
|
||||||
Attributes FnAttribute = Attribute::None;
|
Attributes FnAttribute = Attribute::None;
|
||||||
for (unsigned i = 0, e = Record.size(); i != e; i += 2) {
|
for (unsigned i = 0, e = Record.size(); i != e; i += 2) {
|
||||||
|
// FIXME: remove in LLVM 3.0
|
||||||
|
// The alignment is stored as a 16-bit raw value from bits 31--16.
|
||||||
|
// We shift the bits above 31 down by 11 bits.
|
||||||
|
|
||||||
|
unsigned Alignment = (Record[i+1] & (0xffffull << 16)) >> 16;
|
||||||
|
if (Alignment && !isPowerOf2_32(Alignment))
|
||||||
|
return Error("Alignment is not a power of two.");
|
||||||
|
|
||||||
|
Attributes ReconstitutedAttr = Record[i+1] & 0xffff;
|
||||||
|
if (Alignment)
|
||||||
|
ReconstitutedAttr |= Attribute::constructAlignmentFromInt(Alignment);
|
||||||
|
ReconstitutedAttr |= (Record[i+1] & (0xffffull << 32)) >> 11;
|
||||||
|
Record[i+1] = ReconstitutedAttr;
|
||||||
|
|
||||||
if (Record[i] == 0)
|
if (Record[i] == 0)
|
||||||
RetAttribute = Record[i+1];
|
RetAttribute = Record[i+1];
|
||||||
else if (Record[i] == ~0U)
|
else if (Record[i] == ~0U)
|
||||||
|
@ -122,7 +122,16 @@ static void WriteAttributeTable(const ValueEnumerator &VE,
|
|||||||
for (unsigned i = 0, e = A.getNumSlots(); i != e; ++i) {
|
for (unsigned i = 0, e = A.getNumSlots(); i != e; ++i) {
|
||||||
const AttributeWithIndex &PAWI = A.getSlot(i);
|
const AttributeWithIndex &PAWI = A.getSlot(i);
|
||||||
Record.push_back(PAWI.Index);
|
Record.push_back(PAWI.Index);
|
||||||
Record.push_back(PAWI.Attrs);
|
|
||||||
|
// FIXME: remove in LLVM 3.0
|
||||||
|
// Store the alignment in the bitcode as a 16-bit raw value instead of a
|
||||||
|
// 5-bit log2 encoded value. Shift the bits above the alignment up by
|
||||||
|
// 11 bits.
|
||||||
|
uint64_t FauxAttr = PAWI.Attrs & 0xffff;
|
||||||
|
FauxAttr |= (1ull<<16)<<((PAWI.Attrs & Attribute::Alignment) >> 16);
|
||||||
|
FauxAttr |= (PAWI.Attrs & (0x3FFull << 21)) << 11;
|
||||||
|
|
||||||
|
Record.push_back(FauxAttr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream.EmitRecord(bitc::PARAMATTR_CODE_ENTRY, Record);
|
Stream.EmitRecord(bitc::PARAMATTR_CODE_ENTRY, Record);
|
||||||
|
@ -37,6 +37,8 @@ std::string Attribute::getAsString(Attributes Attrs) {
|
|||||||
Result += "inreg ";
|
Result += "inreg ";
|
||||||
if (Attrs & Attribute::NoAlias)
|
if (Attrs & Attribute::NoAlias)
|
||||||
Result += "noalias ";
|
Result += "noalias ";
|
||||||
|
if (Attrs & Attribute::NoCapture)
|
||||||
|
Result += "nocapture ";
|
||||||
if (Attrs & Attribute::StructRet)
|
if (Attrs & Attribute::StructRet)
|
||||||
Result += "sret ";
|
Result += "sret ";
|
||||||
if (Attrs & Attribute::ByVal)
|
if (Attrs & Attribute::ByVal)
|
||||||
@ -59,10 +61,11 @@ std::string Attribute::getAsString(Attributes Attrs) {
|
|||||||
Result += "sspreq ";
|
Result += "sspreq ";
|
||||||
if (Attrs & Attribute::Alignment) {
|
if (Attrs & Attribute::Alignment) {
|
||||||
Result += "align ";
|
Result += "align ";
|
||||||
Result += utostr((Attrs & Attribute::Alignment) >> 16);
|
Result += utostr(1ull << ((Attrs & Attribute::Alignment)>>16));
|
||||||
Result += " ";
|
Result += " ";
|
||||||
}
|
}
|
||||||
// Trim the trailing space.
|
// Trim the trailing space.
|
||||||
|
assert(!Result.empty() && "Unknown attribute!");
|
||||||
Result.erase(Result.end()-1);
|
Result.erase(Result.end()-1);
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
@ -76,7 +79,7 @@ Attributes Attribute::typeIncompatible(const Type *Ty) {
|
|||||||
|
|
||||||
if (!isa<PointerType>(Ty))
|
if (!isa<PointerType>(Ty))
|
||||||
// Attributes that only apply to pointers.
|
// Attributes that only apply to pointers.
|
||||||
Incompatible |= ByVal | Nest | NoAlias | StructRet;
|
Incompatible |= ByVal | Nest | NoAlias | StructRet | NoCapture;
|
||||||
|
|
||||||
return Incompatible;
|
return Incompatible;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user