Index: include/llvm/IR/Attributes.h =================================================================== --- include/llvm/IR/Attributes.h +++ include/llvm/IR/Attributes.h @@ -416,6 +416,7 @@ class AttrBuilder { std::bitset Attrs; std::map TargetDepAttrs; + SmallVector NoClobberAttrs; uint64_t Alignment; uint64_t StackAlignment; uint64_t DerefBytes; Index: include/llvm/Target/TargetRegisterInfo.h =================================================================== --- include/llvm/Target/TargetRegisterInfo.h +++ include/llvm/Target/TargetRegisterInfo.h @@ -23,6 +23,7 @@ #include "llvm/MC/MCRegisterInfo.h" #include #include +#include namespace llvm { @@ -236,6 +237,8 @@ regclass_iterator RegClassBegin, RegClassEnd; // List of regclasses unsigned CoveringLanes; + typedef MCPhysReg *MCPhysRegList; + static std::map ExplicitCCNoclobbers; protected: TargetRegisterInfo(const TargetRegisterInfoDesc *ID, @@ -456,6 +459,10 @@ return nullptr; } + /// getExplicitCCNoclobberList - Return a null-terminated list of all of the + /// callee saved registers as specified for by the noclobber attribute for MF. + static const MCPhysReg *getExplicitCCNoclobberList(const MachineFunction *MF); + /// getReservedRegs - Returns a bitset indexed by physical register number /// indicating if a register is a special register that has particular uses /// and should be considered unavailable at all times, e.g. SP, RA. This is Index: lib/AsmParser/LLLexer.cpp =================================================================== --- lib/AsmParser/LLLexer.cpp +++ lib/AsmParser/LLLexer.cpp @@ -600,6 +600,7 @@ KEYWORD(cold); KEYWORD(dereferenceable); KEYWORD(hwreg); + KEYWORD(noclobber); KEYWORD(inlinehint); KEYWORD(inreg); KEYWORD(jumptable); Index: lib/AsmParser/LLParser.h =================================================================== --- lib/AsmParser/LLParser.h +++ lib/AsmParser/LLParser.h @@ -225,6 +225,7 @@ bool ParseOptionalAlignment(unsigned &Alignment); bool ParseOptionalDereferenceableBytes(uint64_t &Bytes); bool ParseOptionalHWReg(uint64_t &Reg); + bool ParseNoclobberAttrib(std::string &Regs); bool ParseScopeAndOrdering(bool isAtomic, SynchronizationScope &Scope, AtomicOrdering &Ordering); bool ParseOrdering(AtomicOrdering &Ordering); Index: lib/AsmParser/LLParser.cpp =================================================================== --- lib/AsmParser/LLParser.cpp +++ lib/AsmParser/LLParser.cpp @@ -965,7 +965,13 @@ case lltok::kw_sanitize_thread: B.addAttribute(Attribute::SanitizeThread); break; case lltok::kw_sanitize_memory: B.addAttribute(Attribute::SanitizeMemory); break; case lltok::kw_uwtable: B.addAttribute(Attribute::UWTable); break; - + case lltok::kw_noclobber: { + std::string tmp; + if (ParseNoclobberAttrib(tmp)) + HaveError |= Error(Lex.getLoc(), "malformed noclobber attribute"); + B.addAttribute("noclobber", tmp); + break; + } // Error handling. case lltok::kw_inreg: case lltok::kw_signext: @@ -1564,6 +1570,31 @@ return false; } +bool LLParser::ParseNoclobberAttrib(std::string &Regs) +{ + Lex.Lex(); + if (ParseToken(lltok::lparen, "expected '(' in noclobber attribute")) + return true; + + while (true) { + if (Lex.getKind() == lltok::rparen) { + return false; // We have found the end of the list + } + unsigned Id; + if (ParseUInt32(Id)) { + return true; + } + Regs.append(std::to_string(Id) + " "); + if (Lex.getKind() == lltok::rparen) { + continue; + } else if (Lex.getKind() == lltok::comma) { + Lex.Lex(); + } else { + return TokError("expected ')' or ',' in noclobber attribute"); + } + } +} + /// ParseOptionalCommaAlign /// ::= /// ::= ',' align 4 Index: lib/AsmParser/LLToken.h =================================================================== --- lib/AsmParser/LLToken.h +++ lib/AsmParser/LLToken.h @@ -107,6 +107,7 @@ kw_cold, kw_dereferenceable, kw_hwreg, + kw_noclobber, kw_inlinehint, kw_inreg, kw_jumptable, Index: lib/CodeGen/TargetRegisterInfo.cpp =================================================================== --- lib/CodeGen/TargetRegisterInfo.cpp +++ lib/CodeGen/TargetRegisterInfo.cpp @@ -18,6 +18,7 @@ #include "llvm/CodeGen/VirtRegMap.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/IR/Function.h" using namespace llvm; @@ -302,3 +303,38 @@ dbgs() << PrintReg(Reg, TRI, SubRegIndex) << "\n"; } #endif + +std::map TargetRegisterInfo::ExplicitCCNoclobbers; + +/// getExplicitCCNoclobberList - Return a null-terminated list of all of the +/// callee saved registers as specified for by the noclobber attribute for MF. +const MCPhysReg +*TargetRegisterInfo::getExplicitCCNoclobberList(const MachineFunction *MF) +{ + const Function *F = MF->getFunction(); + + if (!F->hasFnAttribute("noclobber")) + report_fatal_error("A function using the explicitcc calling convention " + "must have a noclobber attribute"); + std::string key = F->getFnAttribute("noclobber").getValueAsString().str(); + + MCPhysRegList &ls = ExplicitCCNoclobbers[key]; + if (ls) + return ls; + const char *str = key.c_str(); + char *end; + long v = strtol(str, &end, 10); + SmallVector NoClobbers; + NoClobbers.push_back(v); + while ((v = strtol(end, &end, 10))) { + NoClobbers.push_back(v); + } + + ls = new MCPhysReg[NoClobbers.size() + 1]; + int index = 0; + for (MCPhysReg r : NoClobbers) + ls[index++] = r; + ls[index] = 0; + return ls; +} + Index: lib/IR/Attributes.cpp =================================================================== --- lib/IR/Attributes.cpp +++ lib/IR/Attributes.cpp @@ -318,12 +318,29 @@ return Result; } - // Convert target-dependent attributes to strings of the form: - // - // "kind" - // "kind" = "value" - // - if (isStringAttribute()) { + if (isStringAttribute() && getKindAsString().equals("noclobber")) { + // The noclobber attribute masquerade as a string attribute + std::string Result; + Result += "noclobber("; + + StringRef Val = pImpl->getValueAsString(); + size_t last = 0, next = 0; + + do { + next = Val.find_first_of(' ', last); + if (last != 0 && next != StringRef::npos) + Result += ","; + Result += Val.slice(last, next); + last = next + 1; + } while (next != StringRef::npos); + Result += ")"; + return Result; + } else if (isStringAttribute()) { + // Convert target-dependent attributes to strings of the form: + // + // "kind" + // "kind" = "value" + // std::string Result; Result += (Twine('"') + getKindAsString() + Twine('"')).str();