mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-27 06:35:30 +00:00
03531a4816
that return an opaque type by value, as long as you don't call it or provide a body (you can take the address of it). So it is wrong to insist that sret parameters not be an opaque*. And I guess it is really up to codegen to complain if someone tries to call such a function. I'm also removing the analogous check from byval parameters, since I don't see why we shouldn't allow them as long as no-one tries to call the function or give it a body. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@46216 91177308-0d34-0410-b5e6-96231b3b80d8
209 lines
5.9 KiB
C++
209 lines
5.9 KiB
C++
//===-- ParameterAttributes.cpp - Implement ParameterAttrs ----------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements the ParamAttrsList class and ParamAttr utilities.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/ParameterAttributes.h"
|
|
#include "llvm/DerivedTypes.h"
|
|
#include "llvm/Support/ManagedStatic.h"
|
|
|
|
using namespace llvm;
|
|
|
|
static ManagedStatic<FoldingSet<ParamAttrsList> > ParamAttrsLists;
|
|
|
|
ParamAttrsList::ParamAttrsList(const ParamAttrsVector &attrVec)
|
|
: attrs(attrVec), refCount(0) {
|
|
}
|
|
|
|
ParamAttrsList::~ParamAttrsList() {
|
|
ParamAttrsLists->RemoveNode(this);
|
|
}
|
|
|
|
uint16_t
|
|
ParamAttrsList::getParamAttrs(uint16_t Index) const {
|
|
unsigned limit = attrs.size();
|
|
for (unsigned i = 0; i < limit && attrs[i].index <= Index; ++i)
|
|
if (attrs[i].index == Index)
|
|
return attrs[i].attrs;
|
|
return ParamAttr::None;
|
|
}
|
|
|
|
bool ParamAttrsList::hasAttrSomewhere(ParameterAttributes attr) const {
|
|
for (unsigned i = 0, e = attrs.size(); i < e; ++i)
|
|
if (attrs[i].attrs & attr)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
std::string
|
|
ParamAttrsList::getParamAttrsText(uint16_t Attrs) {
|
|
std::string Result;
|
|
if (Attrs & ParamAttr::ZExt)
|
|
Result += "zeroext ";
|
|
if (Attrs & ParamAttr::SExt)
|
|
Result += "signext ";
|
|
if (Attrs & ParamAttr::NoReturn)
|
|
Result += "noreturn ";
|
|
if (Attrs & ParamAttr::NoUnwind)
|
|
Result += "nounwind ";
|
|
if (Attrs & ParamAttr::InReg)
|
|
Result += "inreg ";
|
|
if (Attrs & ParamAttr::NoAlias)
|
|
Result += "noalias ";
|
|
if (Attrs & ParamAttr::StructRet)
|
|
Result += "sret ";
|
|
if (Attrs & ParamAttr::ByVal)
|
|
Result += "byval ";
|
|
if (Attrs & ParamAttr::Nest)
|
|
Result += "nest ";
|
|
if (Attrs & ParamAttr::ReadNone)
|
|
Result += "readnone ";
|
|
if (Attrs & ParamAttr::ReadOnly)
|
|
Result += "readonly ";
|
|
return Result;
|
|
}
|
|
|
|
void ParamAttrsList::Profile(FoldingSetNodeID &ID,
|
|
const ParamAttrsVector &Attrs) {
|
|
for (unsigned i = 0; i < Attrs.size(); ++i)
|
|
ID.AddInteger(unsigned(Attrs[i].attrs) << 16 | unsigned(Attrs[i].index));
|
|
}
|
|
|
|
const ParamAttrsList *
|
|
ParamAttrsList::get(const ParamAttrsVector &attrVec) {
|
|
// If there are no attributes then return a null ParamAttrsList pointer.
|
|
if (attrVec.empty())
|
|
return 0;
|
|
|
|
#ifndef NDEBUG
|
|
for (unsigned i = 0, e = attrVec.size(); i < e; ++i) {
|
|
assert(attrVec[i].attrs != ParamAttr::None
|
|
&& "Pointless parameter attribute!");
|
|
assert((!i || attrVec[i-1].index < attrVec[i].index)
|
|
&& "Misordered ParamAttrsList!");
|
|
}
|
|
#endif
|
|
|
|
// Otherwise, build a key to look up the existing attributes.
|
|
FoldingSetNodeID ID;
|
|
ParamAttrsList::Profile(ID, attrVec);
|
|
void *InsertPos;
|
|
ParamAttrsList *PAL = ParamAttrsLists->FindNodeOrInsertPos(ID, InsertPos);
|
|
|
|
// If we didn't find any existing attributes of the same shape then
|
|
// create a new one and insert it.
|
|
if (!PAL) {
|
|
PAL = new ParamAttrsList(attrVec);
|
|
ParamAttrsLists->InsertNode(PAL, InsertPos);
|
|
}
|
|
|
|
// Return the ParamAttrsList that we found or created.
|
|
return PAL;
|
|
}
|
|
|
|
const ParamAttrsList *
|
|
ParamAttrsList::getModified(const ParamAttrsList *PAL,
|
|
const ParamAttrsVector &modVec) {
|
|
if (modVec.empty())
|
|
return PAL;
|
|
|
|
#ifndef NDEBUG
|
|
for (unsigned i = 0, e = modVec.size(); i < e; ++i)
|
|
assert((!i || modVec[i-1].index < modVec[i].index)
|
|
&& "Misordered ParamAttrsList!");
|
|
#endif
|
|
|
|
if (!PAL) {
|
|
// Strip any instances of ParamAttr::None from modVec before calling 'get'.
|
|
ParamAttrsVector newVec;
|
|
for (unsigned i = 0, e = modVec.size(); i < e; ++i)
|
|
if (modVec[i].attrs != ParamAttr::None)
|
|
newVec.push_back(modVec[i]);
|
|
return get(newVec);
|
|
}
|
|
|
|
const ParamAttrsVector &oldVec = PAL->attrs;
|
|
|
|
ParamAttrsVector newVec;
|
|
unsigned oldI = 0;
|
|
unsigned modI = 0;
|
|
unsigned oldE = oldVec.size();
|
|
unsigned modE = modVec.size();
|
|
|
|
while (oldI < oldE && modI < modE) {
|
|
uint16_t oldIndex = oldVec[oldI].index;
|
|
uint16_t modIndex = modVec[modI].index;
|
|
|
|
if (oldIndex < modIndex) {
|
|
newVec.push_back(oldVec[oldI]);
|
|
++oldI;
|
|
} else if (modIndex < oldIndex) {
|
|
if (modVec[modI].attrs != ParamAttr::None)
|
|
newVec.push_back(modVec[modI]);
|
|
++modI;
|
|
} else {
|
|
// Same index - overwrite or delete existing attributes.
|
|
if (modVec[modI].attrs != ParamAttr::None)
|
|
newVec.push_back(modVec[modI]);
|
|
++oldI;
|
|
++modI;
|
|
}
|
|
}
|
|
|
|
for (; oldI < oldE; ++oldI)
|
|
newVec.push_back(oldVec[oldI]);
|
|
for (; modI < modE; ++modI)
|
|
if (modVec[modI].attrs != ParamAttr::None)
|
|
newVec.push_back(modVec[modI]);
|
|
|
|
return get(newVec);
|
|
}
|
|
|
|
const ParamAttrsList *
|
|
ParamAttrsList::includeAttrs(const ParamAttrsList *PAL,
|
|
uint16_t idx, uint16_t attrs) {
|
|
uint16_t OldAttrs = PAL ? PAL->getParamAttrs(idx) : 0;
|
|
uint16_t NewAttrs = OldAttrs | attrs;
|
|
if (NewAttrs == OldAttrs)
|
|
return PAL;
|
|
|
|
ParamAttrsVector modVec;
|
|
modVec.push_back(ParamAttrsWithIndex::get(idx, NewAttrs));
|
|
return getModified(PAL, modVec);
|
|
}
|
|
|
|
const ParamAttrsList *
|
|
ParamAttrsList::excludeAttrs(const ParamAttrsList *PAL,
|
|
uint16_t idx, uint16_t attrs) {
|
|
uint16_t OldAttrs = PAL ? PAL->getParamAttrs(idx) : 0;
|
|
uint16_t NewAttrs = OldAttrs & ~attrs;
|
|
if (NewAttrs == OldAttrs)
|
|
return PAL;
|
|
|
|
ParamAttrsVector modVec;
|
|
modVec.push_back(ParamAttrsWithIndex::get(idx, NewAttrs));
|
|
return getModified(PAL, modVec);
|
|
}
|
|
|
|
uint16_t ParamAttr::typeIncompatible (const Type *Ty) {
|
|
uint16_t Incompatible = None;
|
|
|
|
if (!Ty->isInteger())
|
|
// Attributes that only apply to integers.
|
|
Incompatible |= SExt | ZExt;
|
|
|
|
if (!isa<PointerType>(Ty))
|
|
// Attributes that only apply to pointers.
|
|
Incompatible |= ByVal | Nest | NoAlias | StructRet;
|
|
|
|
return Incompatible;
|
|
}
|