Path: blob/main/contrib/llvm-project/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp
35290 views
//===- CodeGenIntrinsics.cpp - Intrinsic Class Wrapper --------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file defines a wrapper class for the 'Intrinsic' TableGen class.9//10//===----------------------------------------------------------------------===//1112#include "CodeGenIntrinsics.h"13#include "llvm/ADT/ArrayRef.h"14#include "llvm/ADT/STLExtras.h"15#include "llvm/ADT/Twine.h"16#include "llvm/Support/ErrorHandling.h"17#include "llvm/TableGen/Error.h"18#include "llvm/TableGen/Record.h"19#include <algorithm>20#include <cassert>21using namespace llvm;2223//===----------------------------------------------------------------------===//24// CodeGenIntrinsic Implementation25//===----------------------------------------------------------------------===//2627CodeGenIntrinsicTable::CodeGenIntrinsicTable(const RecordKeeper &RC) {28std::vector<Record *> IntrProperties =29RC.getAllDerivedDefinitions("IntrinsicProperty");3031std::vector<Record *> DefaultProperties;32for (Record *Rec : IntrProperties)33if (Rec->getValueAsBit("IsDefault"))34DefaultProperties.push_back(Rec);3536std::vector<Record *> Defs = RC.getAllDerivedDefinitions("Intrinsic");37Intrinsics.reserve(Defs.size());3839for (unsigned I = 0, e = Defs.size(); I != e; ++I)40Intrinsics.push_back(CodeGenIntrinsic(Defs[I], DefaultProperties));4142llvm::sort(Intrinsics,43[](const CodeGenIntrinsic &LHS, const CodeGenIntrinsic &RHS) {44return std::tie(LHS.TargetPrefix, LHS.Name) <45std::tie(RHS.TargetPrefix, RHS.Name);46});47Targets.push_back({"", 0, 0});48for (size_t I = 0, E = Intrinsics.size(); I < E; ++I)49if (Intrinsics[I].TargetPrefix != Targets.back().Name) {50Targets.back().Count = I - Targets.back().Offset;51Targets.push_back({Intrinsics[I].TargetPrefix, I, 0});52}53Targets.back().Count = Intrinsics.size() - Targets.back().Offset;54}5556CodeGenIntrinsic::CodeGenIntrinsic(Record *R,57ArrayRef<Record *> DefaultProperties) {58TheDef = R;59std::string DefName = std::string(R->getName());60ArrayRef<SMLoc> DefLoc = R->getLoc();61Properties = 0;62isOverloaded = false;63isCommutative = false;64canThrow = false;65isNoReturn = false;66isNoCallback = false;67isNoSync = false;68isNoFree = false;69isWillReturn = false;70isCold = false;71isNoDuplicate = false;72isNoMerge = false;73isConvergent = false;74isSpeculatable = false;75hasSideEffects = false;76isStrictFP = false;7778if (DefName.size() <= 4 || DefName.substr(0, 4) != "int_")79PrintFatalError(DefLoc,80"Intrinsic '" + DefName + "' does not start with 'int_'!");8182EnumName = DefName.substr(4);8384if (R->getValue(85"ClangBuiltinName")) // Ignore a missing ClangBuiltinName field.86ClangBuiltinName = std::string(R->getValueAsString("ClangBuiltinName"));87if (R->getValue("MSBuiltinName")) // Ignore a missing MSBuiltinName field.88MSBuiltinName = std::string(R->getValueAsString("MSBuiltinName"));8990TargetPrefix = std::string(R->getValueAsString("TargetPrefix"));91Name = std::string(R->getValueAsString("LLVMName"));9293if (Name == "") {94// If an explicit name isn't specified, derive one from the DefName.95Name = "llvm.";9697for (unsigned i = 0, e = EnumName.size(); i != e; ++i)98Name += (EnumName[i] == '_') ? '.' : EnumName[i];99} else {100// Verify it starts with "llvm.".101if (Name.size() <= 5 || Name.substr(0, 5) != "llvm.")102PrintFatalError(DefLoc, "Intrinsic '" + DefName +103"'s name does not start with 'llvm.'!");104}105106// If TargetPrefix is specified, make sure that Name starts with107// "llvm.<targetprefix>.".108if (!TargetPrefix.empty()) {109if (Name.size() < 6 + TargetPrefix.size() ||110Name.substr(5, 1 + TargetPrefix.size()) != (TargetPrefix + "."))111PrintFatalError(DefLoc, "Intrinsic '" + DefName +112"' does not start with 'llvm." +113TargetPrefix + ".'!");114}115116if (auto *Types = R->getValue("Types")) {117auto *TypeList = cast<ListInit>(Types->getValue());118isOverloaded = R->getValueAsBit("isOverloaded");119120unsigned I = 0;121for (unsigned E = R->getValueAsListInit("RetTypes")->size(); I < E; ++I)122IS.RetTys.push_back(TypeList->getElementAsRecord(I));123124for (unsigned E = TypeList->size(); I < E; ++I)125IS.ParamTys.push_back(TypeList->getElementAsRecord(I));126}127128// Parse the intrinsic properties.129ListInit *PropList = R->getValueAsListInit("IntrProperties");130for (unsigned i = 0, e = PropList->size(); i != e; ++i) {131Record *Property = PropList->getElementAsRecord(i);132assert(Property->isSubClassOf("IntrinsicProperty") &&133"Expected a property!");134135setProperty(Property);136}137138// Set default properties to true.139setDefaultProperties(R, DefaultProperties);140141// Also record the SDPatternOperator Properties.142Properties = parseSDPatternOperatorProperties(R);143144// Sort the argument attributes for later benefit.145for (auto &Attrs : ArgumentAttributes)146llvm::sort(Attrs);147}148149void CodeGenIntrinsic::setDefaultProperties(150Record *R, ArrayRef<Record *> DefaultProperties) {151// opt-out of using default attributes.152if (R->getValueAsBit("DisableDefaultAttributes"))153return;154155for (Record *Rec : DefaultProperties)156setProperty(Rec);157}158159void CodeGenIntrinsic::setProperty(Record *R) {160if (R->getName() == "IntrNoMem")161ME = MemoryEffects::none();162else if (R->getName() == "IntrReadMem") {163if (ME.onlyWritesMemory())164PrintFatalError(TheDef->getLoc(),165Twine("IntrReadMem cannot be used after IntrNoMem or "166"IntrWriteMem. Default is ReadWrite"));167ME &= MemoryEffects::readOnly();168} else if (R->getName() == "IntrWriteMem") {169if (ME.onlyReadsMemory())170PrintFatalError(TheDef->getLoc(),171Twine("IntrWriteMem cannot be used after IntrNoMem or "172"IntrReadMem. Default is ReadWrite"));173ME &= MemoryEffects::writeOnly();174} else if (R->getName() == "IntrArgMemOnly")175ME &= MemoryEffects::argMemOnly();176else if (R->getName() == "IntrInaccessibleMemOnly")177ME &= MemoryEffects::inaccessibleMemOnly();178else if (R->getName() == "IntrInaccessibleMemOrArgMemOnly")179ME &= MemoryEffects::inaccessibleOrArgMemOnly();180else if (R->getName() == "Commutative")181isCommutative = true;182else if (R->getName() == "Throws")183canThrow = true;184else if (R->getName() == "IntrNoDuplicate")185isNoDuplicate = true;186else if (R->getName() == "IntrNoMerge")187isNoMerge = true;188else if (R->getName() == "IntrConvergent")189isConvergent = true;190else if (R->getName() == "IntrNoReturn")191isNoReturn = true;192else if (R->getName() == "IntrNoCallback")193isNoCallback = true;194else if (R->getName() == "IntrNoSync")195isNoSync = true;196else if (R->getName() == "IntrNoFree")197isNoFree = true;198else if (R->getName() == "IntrWillReturn")199isWillReturn = !isNoReturn;200else if (R->getName() == "IntrCold")201isCold = true;202else if (R->getName() == "IntrSpeculatable")203isSpeculatable = true;204else if (R->getName() == "IntrHasSideEffects")205hasSideEffects = true;206else if (R->getName() == "IntrStrictFP")207isStrictFP = true;208else if (R->isSubClassOf("NoCapture")) {209unsigned ArgNo = R->getValueAsInt("ArgNo");210addArgAttribute(ArgNo, NoCapture);211} else if (R->isSubClassOf("NoAlias")) {212unsigned ArgNo = R->getValueAsInt("ArgNo");213addArgAttribute(ArgNo, NoAlias);214} else if (R->isSubClassOf("NoUndef")) {215unsigned ArgNo = R->getValueAsInt("ArgNo");216addArgAttribute(ArgNo, NoUndef);217} else if (R->isSubClassOf("NonNull")) {218unsigned ArgNo = R->getValueAsInt("ArgNo");219addArgAttribute(ArgNo, NonNull);220} else if (R->isSubClassOf("Returned")) {221unsigned ArgNo = R->getValueAsInt("ArgNo");222addArgAttribute(ArgNo, Returned);223} else if (R->isSubClassOf("ReadOnly")) {224unsigned ArgNo = R->getValueAsInt("ArgNo");225addArgAttribute(ArgNo, ReadOnly);226} else if (R->isSubClassOf("WriteOnly")) {227unsigned ArgNo = R->getValueAsInt("ArgNo");228addArgAttribute(ArgNo, WriteOnly);229} else if (R->isSubClassOf("ReadNone")) {230unsigned ArgNo = R->getValueAsInt("ArgNo");231addArgAttribute(ArgNo, ReadNone);232} else if (R->isSubClassOf("ImmArg")) {233unsigned ArgNo = R->getValueAsInt("ArgNo");234addArgAttribute(ArgNo, ImmArg);235} else if (R->isSubClassOf("Align")) {236unsigned ArgNo = R->getValueAsInt("ArgNo");237uint64_t Align = R->getValueAsInt("Align");238addArgAttribute(ArgNo, Alignment, Align);239} else if (R->isSubClassOf("Dereferenceable")) {240unsigned ArgNo = R->getValueAsInt("ArgNo");241uint64_t Bytes = R->getValueAsInt("Bytes");242addArgAttribute(ArgNo, Dereferenceable, Bytes);243} else244llvm_unreachable("Unknown property!");245}246247bool CodeGenIntrinsic::isParamAPointer(unsigned ParamIdx) const {248if (ParamIdx >= IS.ParamTys.size())249return false;250return (IS.ParamTys[ParamIdx]->isSubClassOf("LLVMQualPointerType") ||251IS.ParamTys[ParamIdx]->isSubClassOf("LLVMAnyPointerType"));252}253254bool CodeGenIntrinsic::isParamImmArg(unsigned ParamIdx) const {255// Convert argument index to attribute index starting from `FirstArgIndex`.256++ParamIdx;257if (ParamIdx >= ArgumentAttributes.size())258return false;259ArgAttribute Val{ImmArg, 0};260return std::binary_search(ArgumentAttributes[ParamIdx].begin(),261ArgumentAttributes[ParamIdx].end(), Val);262}263264void CodeGenIntrinsic::addArgAttribute(unsigned Idx, ArgAttrKind AK,265uint64_t V) {266if (Idx >= ArgumentAttributes.size())267ArgumentAttributes.resize(Idx + 1);268ArgumentAttributes[Idx].emplace_back(AK, V);269}270271272