// removeAttribute() currently does not work on Attribute::Alignment // (it fails with an assertion error), so we have to take a more // convoluted route to removing this attribute by recreating the // AttributeSet. AttributeSet RemoveAttrs(LLVMContext &Context, AttributeSet Attrs) { SmallVector<AttributeSet, 8> AttrList; for (unsigned Slot = 0; Slot < Attrs.getNumSlots(); ++Slot) { unsigned Index = Attrs.getSlotIndex(Slot); AttrBuilder AB; for (AttributeSet::iterator Attr = Attrs.begin(Slot), E = Attrs.end(Slot); Attr != E; ++Attr) { if (Attr->isEnumAttribute() && Attr->getKindAsEnum() != Attribute::ByVal && Attr->getKindAsEnum() != Attribute::StructRet) { AB.addAttribute(*Attr); } // IR semantics require that ByVal implies NoAlias. However, IR // semantics do not require StructRet to imply NoAlias. For // example, a global variable address can be passed as a // StructRet argument, although Clang does not do so and Clang // explicitly adds NoAlias to StructRet arguments. if (Attr->isEnumAttribute() && Attr->getKindAsEnum() == Attribute::ByVal) { AB.addAttribute(Attribute::get(Context, Attribute::NoAlias)); } } AttrList.push_back(AttributeSet::get(Context, Index, AB)); } return AttributeSet::get(Context, AttrList); }
// Most attributes are just hints which can safely be removed. A few // attributes can break programs if removed, so check all attributes // before removing them, in case LLVM adds new attributes. static void CheckAttributes(AttributeSet Attrs) { for (unsigned Slot = 0; Slot < Attrs.getNumSlots(); ++Slot) { for (AttributeSet::iterator Attr = Attrs.begin(Slot), E = Attrs.end(Slot); Attr != E; ++Attr) { if (!Attr->isEnumAttribute()) { continue; } switch (Attr->getKindAsEnum()) { // The following attributes can affect calling conventions. // Rather than complaining, we just strip these out. // ExpandSmallArguments should have rendered SExt/ZExt // meaningless since the function arguments will be at least // 32-bit. case Attribute::InReg: case Attribute::SExt: case Attribute::ZExt: // These attributes influence ABI decisions that should not be // visible to PNaCl pexes. case Attribute::NonLazyBind: // Only relevant to dynamic linking. case Attribute::NoRedZone: case Attribute::StackAlignment: // The following attributes are just hints, which can be // safely removed. case Attribute::AlwaysInline: case Attribute::InlineHint: case Attribute::MinSize: case Attribute::NoAlias: case Attribute::NoBuiltin: case Attribute::NoCapture: case Attribute::NoDuplicate: case Attribute::NoImplicitFloat: case Attribute::NoInline: case Attribute::NoReturn: case Attribute::OptimizeForSize: case Attribute::ReadNone: case Attribute::ReadOnly: // PNaCl does not support -fstack-protector in the translator. case Attribute::StackProtect: case Attribute::StackProtectReq: case Attribute::StackProtectStrong: // PNaCl does not support ASan in the translator. case Attribute::SanitizeAddress: case Attribute::SanitizeThread: case Attribute::SanitizeMemory: // The Language References cites setjmp() as an example of a // function which returns twice, and says ReturnsTwice is // necessary to disable optimizations such as tail calls. // However, in the PNaCl ABI, setjmp() is an intrinsic, and // user-defined functions are not allowed to return twice. case Attribute::ReturnsTwice: // NoUnwind is not a hint if it causes unwind info to be // omitted, since this will prevent C++ exceptions from // propagating. In the future, when PNaCl supports zero-cost // C++ exception handling using unwind info, we might allow // NoUnwind and UWTable. Alternatively, we might continue to // disallow them, and just generate unwind info for all // functions. case Attribute::NoUnwind: case Attribute::UWTable: break; case Attribute::ByVal: case Attribute::StructRet: case Attribute::Alignment: Attrs.dump(); report_fatal_error( "Attribute should already have been removed by ExpandByVal"); case Attribute::Naked: case Attribute::Nest: Attrs.dump(); report_fatal_error("Unsupported attribute"); default: Attrs.dump(); report_fatal_error("Unrecognized attribute"); } } } }