LLVM学习笔记(19)

3.4.2.5.2. 有匹配模式的Instruction

对有模式的Instruction定义,第一步也是先生成CodeGenInstruction实例。接着把这个实例,连同记录了其匹配模式的DagInit列表,交给下面的方法来解析。目的也是生成DAGInstruction实例,但这里因为指令定义有匹配模式,处理起来复杂很多。

2903  const DAGInstruction &CodeGenDAGPatterns::parseInstructionPattern(

2904      CodeGenInstruction &CGI, ListInit *Pat, DAGInstMap &DAGInsts) {

2905 

2906    assert(!DAGInsts.count(CGI.TheDef) && "Instruction already parsed!");

2907 

2908    // Parse the instruction.

2909    TreePattern *I = new TreePattern(CGI.TheDef, Pat, true, *this);

2910    // Inline pattern fragments into it.

2911    I->InlinePatternFragments();

2912 

2913    // Infer as many types as possible.  If we cannot infer all of them, we can

2914    // never do anything with this instruction pattern: report it to the user.

2915    if (!I->InferAllTypes())

2916      I->error("Could not infer all types in pattern!");

2917

2918    // InstInputs - Keep track of all of the inputs of the instruction, along

2919    // with the record they are declared as.

2920    std::map<std::string, TreePatternNode*> InstInputs;

2921 

2922    // InstResults - Keep track of all the virtual registers that are 'set'

2923    // in the instruction, including what reg class they are.

2924    std::map<std::string, TreePatternNode*> InstResults;

2925 

2926    std::vector<Record*> InstImpResults;

2927 

2928    // Verify that the top-level forms in the instruction are of void type, and

2929    // fill in the InstResults map.

2930    for (unsigned j = 0, e = I->getNumTrees(); j != e; ++j) {

2931      TreePatternNode *Pat = I->getTree(j);

2932      if (Pat->getNumTypes() != 0)

2933        I->error("Top-level forms in instruction pattern should have"

2934                 " void types");

2935 

2936      // Find inputs and outputs, and verify the structure of the uses/defs.

2937      FindPatternInputsAndOutputs(I, Pat, InstInputs, InstResults,

2938                                  InstImpResults);

2939    }

第一步解析这个模式,生成对应的TreePattern树,接着进行内联展开与类型推导。前面看TreePatternNode::ApplyTypeConstraints()方法时,我们跳过了模式操作符是Instruction部分,现在我们仍然要跳过它,因为当前的Instruction还未解析完,它是不可能作为当前模式操作符的。

接下来就要找出该模式的输入、输出以及隐含输出了,并把它们分别保存入相应的容器中。

2604  void CodeGenDAGPatterns::

2605  FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat,

2606                              std::map<std::string, TreePatternNode*> &InstInputs,

2607                              std::map<std::string, TreePatternNode*>&InstResults,

2608                              std::vector<Record*> &InstImpResults) {

2609    if (Pat->isLeaf()) {

2610      bool isUse = HandleUse(I, Pat, InstInputs);

2611      if (!isUse && Pat->getTransformFn())

2612        I->error("Cannot specify a transform function for a non-input value!");

2613      return;

2614    }

2615 

2616    if (Pat->getOperator()->getName() == "implicit") {

2617      for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i) {

2618        TreePatternNode *Dest = Pat->getChild(i);

2619        if (!Dest->isLeaf())

2620          I->error("implicitly defined value should be a register!");

2621 

2622        DefInit *Val = dyn_cast<DefInit>(Dest->getLeafValue());

2623        if (!Val || !Val->getDef()->isSubClassOf("Register"))

2624          I->error("implicitly defined value should be a register!");

2625        InstImpResults.push_back(Val->getDef());

2626      }

2627      return;

2628    }

2629 

2630    if (Pat->getOperator()->getName() != "set") {

2631      // If this is not a set, verify that the children nodes are not void typed,

2632      // and recurse.

2633      for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i) {

2634        if (Pat->getChild(i)->getNumTypes() == 0)

2635          I->error("Cannot have void nodes inside of patterns!");

2636        FindPatternInputsAndOutputs(I, Pat->getChild(i), InstInputs, InstResults,

2637                                    InstImpResults);

2638      }

2639 

2640      // If this is a non-leaf node with no children, treat it basically as if

2641      // it were a leaf.  This handles nodes like (imm).

2642      bool isUse = HandleUse(I, Pat, InstInputs);

2643 

2644      if (!isUse && Pat->getTransformFn())

2645        I->error("Cannot specify a transform function for a non-input value!");

2646      return;

2647    }

2648 

2649    // Otherwise, this is a set, validate and collect instruction results.

2650    if (Pat->getNumChildren() == 0)

2651      I->error("set requires operands!");

2652 

2653    if (Pat->getTransformFn())

2654      I->error("Cannot specify a transform function on a set node!");

2655 

2656    // Check the set destinations.

2657    unsigned NumDests = Pat->getNumChildren()-1;

2658    for (unsigned i = 0; i != NumDests; ++i) {

2659      TreePatternNode *Dest = Pat->getChild(i);

2660      if (!Dest->isLeaf())

2661        I->error("set destination should be a register!");

2662 

2663      DefInit *Val = dyn_cast<DefInit>(Dest->getLeafValue());

2664      if (!Val) {

2665        I->error("set destination should be a register!");

2666        continue;

2667      }

2668 

2669      if (Val->getDef()->isSubClassOf("RegisterClass") ||

2670          Val->getDef()->isSubClassOf("ValueType") ||

2671          Val->getDef()->isSubClassOf("RegisterOperand") ||

2672         Val->getDef()->isSubClassOf("PointerLikeRegClass")) {

2673        if (Dest->getName().empty())

2674          I->error("set destination must have a name!");

2675        if (InstResults.count(Dest->getName()))

2676          I->error("cannot set '" + Dest->getName() +"' multiple times");

2677        InstResults[Dest->getName()] = Dest;

2678      } else if (Val->getDef()->isSubClassOf("Register")) {

2679        InstImpResults.push_back(Val->getDef());

2680      } else {

2681        I->error("set destination should be a register!");

2682      }

2683    }

2684 

2685    // Verify and collect info from the computation.

2686    FindPatternInputsAndOutputs(I, Pat->getChild(NumDests),

2687                                InstInputs, InstResults, InstImpResults);

2688  }

一般情况下模式中给出的操作数都应视为输入操作数,除了以Implicit及set作为操作符的dag。Implicit的操作数必须是Register对象,并且这代表隐含结果。Set则要复杂些,首先set最后的操作数是源操作数,其他操作数都是目标操作数,set的作用是将源操作数设置给目标操作数。目标操作数是有限制的,首先它们必须是set这棵TreePattern树的叶子节点。其次,它们的类型必须是RegisterClass、ValueType、RegisterOperand、PointerLikeRegClass或Register之一,而且前四者都必须是具名的。另外,Register类型的目标操作数被视为隐含结果。Set的源操作数则要复杂一些,因此在2686行通过FindPatternInputsAndOutputs()递归来处理。

非set节点(2630行条件)可以有复杂的源操作数,因此也由FindPatternInputsAndOutputs()递归处理(2636行)。另外,输入操作数需要被记录到容器InstInputs里,HandleUse()方法执行这个操作,并进行一些合法性检查。

2554  static bool HandleUse(TreePattern *I, TreePatternNode *Pat,

2555                        std::map<std::string, TreePatternNode*> &InstInputs) {

2556    // No name -> not interesting.

2557    if (Pat->getName().empty()) {

2558      if (Pat->isLeaf()) {

2559        DefInit *DI = dyn_cast<DefInit>(Pat->getLeafValue());

2560        if (DI && (DI->getDef()->isSubClassOf("RegisterClass") ||

2561                   DI->getDef()->isSubClassOf("RegisterOperand")))

2562          I->error("Input " + DI->getDef()->getName() + " must be named!");

2563      }

2564      return false;

2565    }

2566 

2567    Record *Rec;

2568    if (Pat->isLeaf()) {

2569      DefInit *DI = dyn_cast<DefInit>(Pat->getLeafValue());

2570      if (!DI) I->error("Input $" + Pat->getName() + " must be an identifier!");

2571      Rec = DI->getDef();

2572    } else {

2573      Rec = Pat->getOperator();

2574    }

2575 

2576    // SRCVALUE nodes are ignored.

2577    if (Rec->getName() == "srcvalue")

2578      return false;

2579 

2580    TreePatternNode *&Slot = InstInputs[Pat->getName()];

2581    if (!Slot) {

2582      Slot = Pat;

2583      return true;

2584    }

2585    Record *SlotRec;

2586    if (Slot->isLeaf()) {

2587      SlotRec = cast<DefInit>(Slot->getLeafValue())->getDef();

2588    } else {

2589      assert(Slot->getNumChildren() == 0 && "can't be a use with children!");

2590      SlotRec = Slot->getOperator();

2591    }

2592 

2593    // Ensure that the inputs agree if we've already seen this input.

2594    if (Rec != SlotRec)

2595      I->error("All $" + Pat->getName() + " inputs must agree with each other");

2596    if (Slot->getExtTypes() != Pat->getExtTypes())

2597      I->error("All $" + Pat->getName() + " inputs must agree with each other");

2598    return true;

2599  }

Srcvalue类型是不在考虑范围内的,不过LLVM似乎已经不再使用它了。如果同名操作数已经在InstInputs里,必须确保它们是一样的。在2580行输入操作数被保存入InstInputs容器。

回到CodeGenDAGPatterns::parseInstructionPattern(),2953行的CGI.Operands.size()给出了输入、输出操作数的总数,在CGI.Operands中输出操作数在前(参考CGIOperandList的构造函数)。

CodeGenDAGPatterns::parseInstructionPattern(续)

2941    // Now that we have inputs and outputs of the pattern, inspect the operands

2942    // list for the instruction.  This determines the order that operands are

2943    // added to the machine instruction the node corresponds to.

2944    unsigned NumResults = InstResults.size();

2945 

2946    // Parse the operands list from the (ops) list, validating it.

2947    assert(I->getArgList().empty() && "Args list should still be empty here!");

2948 

2949    // Check that all of the results occur first in the list.

2950    std::vector<Record*> Results;

2951    SmallVector<TreePatternNode *, 2> ResNodes;

2952    for (unsigned i = 0; i != NumResults; ++i) {

2953      if (i == CGI.Operands.size())

2954        I->error("'" + InstResults.begin()->first +

2955                 "' set but does not appear in operand list!");

2956      const std::string &OpName = CGI.Operands[i].Name;

2957 

2958      // Check that it exists in InstResults.

2959      TreePatternNode *RNode = InstResults[OpName];

2960      if (!RNode)

2961        I->error("Operand $" + OpName + " does not exist in operand list!");

2962 

2963      ResNodes.push_back(RNode);

2964 

2965      Record *R = cast<DefInit>(RNode->getLeafValue())->getDef();

2966      if (!R)

2967        I->error("Operand $" + OpName + " should be a set destination: all "

2968                 "outputs must occur before inputs in operand list!");

2969 

2970      if (!checkOperandClass(CGI.Operands[i], R))

2971        I->error("Operand $" + OpName + " class mismatch!");

2972 

2973      // Remember the return type.

2974      Results.push_back(CGI.Operands[i].Rec);

2975 

2976      // Okay, this one checks out.

2977      InstResults.erase(OpName);

2978    }

2952行循环遍历输出操作数,调用checkOperandClass()方法检查操作数的Record对象与CGIOperandList::OperandInfo实例是否一致。在OperandInfo构造函数里,OperandInfo对象中保存了对应操作数的Record实例,即下面2888行的OI.Rec。而参数Leaf则是来自指令定义中的结果操作数。原则上两者必须是相同的,除非Leaf是ValueType或ComplexPattern类型。参考指令定义的例子一节的例子bmi_andn。在这个例子里可以发现对其中一个操作数$src2,OI.Rec是X86MemOperand(Operand对象),Leaf是addr(ComplexPattern对象)。

2886  static bool checkOperandClass(CGIOperandList::OperandInfo &OI,

2887                                Record *Leaf) {

2888    if (OI.Rec == Leaf)

2889      return true;

2890 

2891    // Allow direct value types to be used in instruction set patterns.

2892    // The type will be checked later.

2893    if (Leaf->isSubClassOf("ValueType"))

2894      return true;

2895 

2896    // Patterns can also be ComplexPattern instances.

2897    if (Leaf->isSubClassOf("ComplexPattern"))

2898      return true;

2899 

2900    return false;

2901  }

注意2977行的erase,完成2952行循环后,InstResults应该是空的。2985行的Operands容器将只包含输入操作数的Record对象。因此,2984行定义的容器ResultNodeOperands包含的将是输出操作数,它将用作代表结果的模式树的操作数。

CodeGenDAGPatterns::parseInstructionPattern(续)

2980    // Loop over the inputs next.  Make a copy of InstInputs so we can destroy

2981    // the copy while we're checking the inputs.

2982    std::map<std::string, TreePatternNode*> InstInputsCheck(InstInputs);

2983 

2984    std::vector<TreePatternNode*> ResultNodeOperands;

2985    std::vector<Record*> Operands;

2986    for (unsigned i = NumResults, e = CGI.Operands.size(); i != e; ++i) {

2987      CGIOperandList::OperandInfo &Op = CGI.Operands[i];

2988      const std::string &OpName = Op.Name;

2989      if (OpName.empty())

2990        I->error("Operand #" + utostr(i) + " in operands list has no name!");

2991 

2992      if (!InstInputsCheck.count(OpName)) {

2993        // If this is an operand with a DefaultOps set filled in, we can ignore

2994        // this.  When we codegen it, we will do so as always executed.

2995        if (Op.Rec->isSubClassOf("OperandWithDefaultOps")) {

2996          // Does it have a non-empty DefaultOps field?  If so, ignore this

2997          // operand.

2998          if (!getDefaultOperand(Op.Rec).DefaultOps.empty())

2999            continue;

3000        }

3001        I->error("Operand $" + OpName +

3002                 " does not appear in the instruction pattern");

3003      }

3004      TreePatternNode *InVal = InstInputsCheck[OpName];

3005      InstInputsCheck.erase(OpName);   // It occurred, remove from map.

3006 

3007     if (InVal->isLeaf() && isa<DefInit>(InVal->getLeafValue())) {

3008        Record *InRec = static_cast<DefInit*>(InVal->getLeafValue())->getDef();

3009        if (!checkOperandClass(Op, InRec))

3010          I->error("Operand $" + OpName + "'s register class disagrees"

3011                   " between the operand and pattern");

3012      }

3013      Operands.push_back(Op.Rec);

3014 

3015      // Construct the result for the dest-pattern operand list.

3016      TreePatternNode *OpNode = InVal->clone();

3017 

3018      // No predicate is useful on the result.

3019      OpNode->clearPredicateFns();

3020 

3021      // Promote the xform function to be an explicit node if set.

3022      if (Record *Xform = OpNode->getTransformFn()) {

3023        OpNode->setTransformFn(nullptr);

3024        std::vector<TreePatternNode*> Children;

3025        Children.push_back(OpNode);

3026        OpNode = new TreePatternNode(Xform, Children, OpNode->getNumTypes());

3027      }

3028 

3029      ResultNodeOperands.push_back(OpNode);

3030    }

3016行克隆了输入操作数的TreePatternNode,如果其中有转换方法,还要将代表转换方法的SDNodeXForm节点作为这棵TreePattern树的根。这些克隆节点保存在ResultNodeOperands容器里。

下面3036行生成代表指令结果的树节点——ResultPattern,Instruction定义的Record对象为根,ResultNodeOperands作为孩子。在3053行构建一个TreePattern对象(注意,IsInput参数为false)来封装ResultPattern,目的在于调用TreePattern的InferAllTypes()方法,确认指令模式树中的具名操作数集合与这个TreePattern对象中的具名操作数一致。

CodeGenDAGPatterns::parseInstructionPattern(续)

3032    if (!InstInputsCheck.empty())

3033      I->error("Input operand $" + InstInputsCheck.begin()->first +

3034               " occurs in pattern but not in operands list!");

3035 

3036    TreePatternNode *ResultPattern =

3037      new TreePatternNode(I->getRecord(), ResultNodeOperands,

3038                          GetNumNodeResults(I->getRecord(), *this));

3039    // Copy fully inferred output node types to instruction result pattern.

3040    for (unsigned i = 0; i != NumResults; ++i) {

3041      assert(ResNodes[i]->getNumTypes() == 1 && "FIXME: Unhandled");

3042      ResultPattern->setType(i, ResNodes[i]->getExtType(0));

3043    }

3044 

3045    // Create and insert the instruction.

3046    // FIXME: InstImpResults should not be part of DAGInstruction.

3047    DAGInstruction TheInst(I, Results, Operands, InstImpResults);

3048    DAGInsts.insert(std::make_pair(I->getRecord(), TheInst));

3049 

3050    // Use a temporary tree pattern to infer all types and make sure that the

3051    // constructed result is correct.  This depends on the instruction already

3052    // being inserted into the DAGInsts map.

3053    TreePattern Temp(I->getRecord(), ResultPattern, false, *this);

3054    Temp.InferAllTypes(&I->getNamedNodesMap());

3055 

3056    DAGInstruction &TheInsertedInst = DAGInsts.find(I->getRecord())->second;

3057    TheInsertedInst.setResultPattern(Temp.getOnlyTree());

3058 

3059    return TheInsertedInst;

3060  }

这里注意看一下3047行DAGInstruction的构建。参数I是指令的匹配模式TreePattern对象,Results是输出操作数,Operands是输入操作数,InstImpResults是隐含的输出结果。在3057行代表结果的模式树被设置为这个DAGInstruction实例的ResultPattern。

V7.0的处理

V7.0的处理稍有出入。首先在3491行在栈上创建当前指令匹配模式的TreePattern实例,而不是v3.6.1那样在堆上。另外,它也不着急着将这个TreePattern进行内联以及类型推导。

3485  void CodeGenDAGPatterns::parseInstructionPattern(

3486      CodeGenInstruction &CGI, ListInit *Pat, DAGInstMap &DAGInsts) {

3487 

3488    assert(!DAGInsts.count(CGI.TheDef) && "Instruction already parsed!");

3489 

3490    // Parse the instruction.

3491    TreePattern I(CGI.TheDef, Pat, true, *this);

3492 

3493    // InstInputs - Keep track of all of the inputs of the instruction, along

3494    // with the record they are declared as.

3495    std::map<std::string, TreePatternNodePtr> InstInputs;

3496 

3497    // InstResults - Keep track of all the virtual registers that are 'set'

3498    // in the instruction, including what reg class they are.

3499    std::map<std::string, TreePatternNodePtr> InstResults;

3500 

3501    std::vector<Record*> InstImpResults;

3502 

3503    // Verify that the top-level forms in the instruction are of void type, and

3504    // fill in the InstResults map.

3505    SmallString<32> TypesString;

3506    for (unsigned j = 0, e = I.getNumTrees(); j != e; ++j) {

3507      TypesString.clear();

3508      TreePatternNodePtr Pat = I.getTree(j);

3509      if (Pat->getNumTypes() != 0) {

3510        raw_svector_ostream OS(TypesString);

3511        for (unsigned k = 0, ke = Pat->getNumTypes(); k != ke; ++k) {

3512          if (k > 0)

3513            OS << ", ";

3514          Pat->getExtType(k).writeToStream(OS);

3515        }

3516        I.error("Top-level forms in instruction pattern should have"

3517                 " void types, has types " +

3518                 OS.str());

3519      }

3520 

3521      // Find inputs and outputs, and verify the structure of the uses/defs.

3522      FindPatternInputsAndOutputs(I, Pat, InstInputs, InstResults,

3523                                  InstImpResults);

3524    }

前面看到在TreePattern构造函数里,会按匹配模式解析dag对象。Instruction定义的Pattern域里每个dag对象将解析为一个TreePatternNode实例保存在Trees容器中。指令是没有类型的,因此3506行循环遍历这些TreePatternNode实例,检查是否有违规。

对具名模式,CodeGenDAGPatterns::FindPatternInputsAndOutputs()一进来就进行展开与类型推导,如果有多棵模式树,3189TreePatterngetOnlyTree()方法会引发断言。这是v3.6.1没有做的检查。

3176  void CodeGenDAGPatterns::FindPatternInputsAndOutputs(

3177      TreePattern &I, TreePatternNodePtr Pat,

3178      std::map<std::string, TreePatternNodePtr> &InstInputs,

3179      std::map<std::string, TreePatternNodePtr> &InstResults,

3180      std::vector<Record *> &InstImpResults) {

3181 

3182    // The instruction pattern still has unresolved fragments.  For *named*

3183    // nodes we must resolve those here.  This may not result in multiple

3184    // alternatives.

3185    if (!Pat->getName().empty()) {

3186      TreePattern SrcPattern(I.getRecord(), Pat, true, *this);

3187      SrcPattern.InlinePatternFragments();

3188      SrcPattern.InferAllTypes();

3189      Pat = SrcPattern.getOnlyTree();

3190    }

3191 

3192    if (Pat->isLeaf()) {

3193      bool isUse = HandleUse(I, Pat, InstInputs);

3194      if (!isUse && Pat->getTransformFn())

3195        I.error("Cannot specify a transform function for a non-input value!");

3196      return;

3197    }

3198 

3199    if (Pat->getOperator()->getName() == "implicit") {

3200      for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i) {

3201        TreePatternNode *Dest = Pat->getChild(i);

3202        if (!Dest->isLeaf())

3203          I.error("implicitly defined value should be a register!");

3204 

3205        DefInit *Val = dyn_cast<DefInit>(Dest->getLeafValue());

3206        if (!Val || !Val->getDef()->isSubClassOf("Register"))

3207          I.error("implicitly defined value should be a register!");

3208        InstImpResults.push_back(Val->getDef());

3209      }

3210      return;

3211    }

3212 

3213    if (Pat->getOperator()->getName() != "set") {

3214      // If this is not a set, verify that the children nodes are not void typed,

3215      // and recurse.

3216      for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i) {

3217        if (Pat->getChild(i)->getNumTypes() == 0)

3218          I.error("Cannot have void nodes inside of patterns!");

3219        FindPatternInputsAndOutputs(I, Pat->getChildShared(i), InstInputs,

3220                                    InstResults, InstImpResults);

3221      }

3222 

3223      // If this is a non-leaf node with no children, treat it basically as if

3224      // it were a leaf.  This handles nodes like (imm).

3225      bool isUse = HandleUse(I, Pat, InstInputs);

3226 

3227      if (!isUse && Pat->getTransformFn())

3228        I.error("Cannot specify a transform function for a non-input value!");

3229      return;

3230    }

3231 

3232    // Otherwise, this is a set, validate and collect instruction results.

3233    if (Pat->getNumChildren() == 0)

3234      I.error("set requires operands!");

3235 

3236    if (Pat->getTransformFn())

3237      I.error("Cannot specify a transform function on a set node!");

3238 

3239    // Check the set destinations.

3240    unsigned NumDests = Pat->getNumChildren()-1;

3241    for (unsigned i = 0; i != NumDests; ++i) {

3242      TreePatternNodePtr Dest = Pat->getChildShared(i);

3243      // For set destinations we also must resolve fragments here.

3244      TreePattern DestPattern(I.getRecord(), Dest, false, *this);

3245      DestPattern.InlinePatternFragments();

3246      DestPattern.InferAllTypes();

3247      Dest = DestPattern.getOnlyTree();

3248 

3249      if (!Dest->isLeaf())

3250        I.error("set destination should be a register!");

3251 

3252      DefInit *Val = dyn_cast<DefInit>(Dest->getLeafValue());

3253      if (!Val) {

3254        I.error("set destination should be a register!");

3255        continue;

3256      }

3257 

3258      if (Val->getDef()->isSubClassOf("RegisterClass") ||

3259          Val->getDef()->isSubClassOf("ValueType") ||

3260          Val->getDef()->isSubClassOf("RegisterOperand") ||

3261          Val->getDef()->isSubClassOf("PointerLikeRegClass")) {

3262        if (Dest->getName().empty())

3263          I.error("set destination must have a name!");

3264        if (InstResults.count(Dest->getName()))

3265          I.error("cannot set '" + Dest->getName() + "' multiple times");

3266        InstResults[Dest->getName()] = Dest;

3267      } else if (Val->getDef()->isSubClassOf("Register")) {

3268        InstImpResults.push_back(Val->getDef());

3269      } else {

3270        I.error("set destination should be a register!");

3271      }

3272    }

3273 

3274    // Verify and collect info from the computation.

3275    FindPatternInputsAndOutputs(I, Pat->getChildShared(NumDests), InstInputs,

3276                                InstResults, InstImpResults);

3277  }

叶子节点很可能是操作数,因此调用HandleUse()来处理它。V7.0HandleUse()v3.6.1基本相同。首先,只处理具名节点。其次,RegisterClassRegisterOperand类型节点是不允许匿名的。对满足条件的节点(参数Pat),加入参数InstInputs容器中,以名字作为索引。同名对象的多次加入是允许的,但它们必须来自相同的定义(对非叶子节点,这个定义是对应dag的操作符),而且存在一致的类型。

Dag通常是匿名的,它们由3199行以下的代码处理。除了implicit的操作数以及set最后一个以外的操作数,其他操作数都视为输入操作数。这里对可以作为输出操作数类型的检查与v3.6.1无异。不过,也是在处理输出操作数前,才进行内联与类型推导,并确保只生成一棵树(3242~3247行)。

CodeGenDAGPatterns::parseInstructionPattern(续)

3526    // Now that we have inputs and outputs of the pattern, inspect the operands

3527    // list for the instruction.  This determines the order that operands are

3528    // added to the machine instruction the node corresponds to.

3529    unsigned NumResults = InstResults.size();

3530 

3531    // Parse the operands list from the (ops) list, validating it.

3532    assert(I.getArgList().empty() && "Args list should still be empty here!");

3533 

3534    // Check that all of the results occur first in the list.

3535    std::vector<Record*> Results;

3536    SmallVector<TreePatternNodePtr, 2> ResNodes;

3537    for (unsigned i = 0; i != NumResults; ++i) {

3538      if (i == CGI.Operands.size())

3539        I.error("'" + InstResults.begin()->first +

3540                 "' set but does not appear in operand list!");

3541      const std::string &OpName = CGI.Operands[i].Name;

3542 

3543      // Check that it exists in InstResults.

3544      TreePatternNodePtr RNode = InstResults[OpName];

3545      if (!RNode)

3546        I.error("Operand $" + OpName + " does not exist in operand list!");

3547 

3548 

3549      Record *R = cast<DefInit>(RNode->getLeafValue())->getDef();

3550      ResNodes.push_back(std::move(RNode));

3551      if (!R)

3552        I.error("Operand $" + OpName + " should be a set destination: all "

3553                 "outputs must occur before inputs in operand list!");

3554 

3555      if (!checkOperandClass(CGI.Operands[i], R))

3556        I.error("Operand $" + OpName + " class mismatch!");

3557 

3558      // Remember the return type.

3559      Results.push_back(CGI.Operands[i].Rec);

3560 

3561      // Okay, this one checks out.

3562      InstResults.erase(OpName);

3563    }

3564 

3565    // Loop over the inputs next.

3566    std::vector<TreePatternNodePtr> ResultNodeOperands;

3567    std::vector<Record*> Operands;

3568    for (unsigned i = NumResults, e = CGI.Operands.size(); i != e; ++i) {

3569      CGIOperandList::OperandInfo &Op = CGI.Operands[i];

3570      const std::string &OpName = Op.Name;

3571      if (OpName.empty())

3572        I.error("Operand #" + Twine(i) + " in operands list has no name!");

3573 

3574      if (!InstInputs.count(OpName)) {

3575        // If this is an operand with a DefaultOps set filled in, we can ignore

3576        // this.  When we codegen it, we will do so as always executed.

3577        if (Op.Rec->isSubClassOf("OperandWithDefaultOps")) {

3578          // Does it have a non-empty DefaultOps field?  If so, ignore this

3579          // operand.

3580          if (!getDefaultOperand(Op.Rec).DefaultOps.empty())

3581            continue;

3582        }

3583        I.error("Operand $" + OpName +

3584                 " does not appear in the instruction pattern");

3585      }

3586      TreePatternNodePtr InVal = InstInputs[OpName];

3587      InstInputs.erase(OpName);   // It occurred, remove from map.

3588 

3589      if (InVal->isLeaf() && isa<DefInit>(InVal->getLeafValue())) {

3590        Record *InRec = static_cast<DefInit*>(InVal->getLeafValue())->getDef();

3591        if (!checkOperandClass(Op, InRec))

3592          I.error("Operand $" + OpName + "'s register class disagrees"

3593                   " between the operand and pattern");

3594      }

3595      Operands.push_back(Op.Rec);

3596 

3597      // Construct the result for the dest-pattern operand list.

3598      TreePatternNodePtr OpNode = InVal->clone();

3599 

3600      // No predicate is useful on the result.

3601      OpNode->clearPredicateFns();

3602 

3603      // Promote the xform function to be an explicit node if set.

3604      if (Record *Xform = OpNode->getTransformFn()) {

3605        OpNode->setTransformFn(nullptr);

3606        std::vector<TreePatternNodePtr> Children;

3607        Children.push_back(OpNode);

3608        OpNode = std::make_shared<TreePatternNode>(Xform, std::move(Children),

3609                                                   OpNode->getNumTypes());

3610      }

3611 

3612      ResultNodeOperands.push_back(std::move(OpNode));

3613    }

3614 

3615    if (!InstInputs.empty())

3616      I.error("Input operand $" + InstInputs.begin()->first +

3617              " occurs in pattern but not in operands list!");

3618 

3619    TreePatternNodePtr ResultPattern = std::make_shared<TreePatternNode>(

3620        I.getRecord(), std::move(ResultNodeOperands),

3621        GetNumNodeResults(I.getRecord(), *this));

3622    // Copy fully inferred output node types to instruction result pattern.

3623    for (unsigned i = 0; i != NumResults; ++i) {

3624      assert(ResNodes[i]->getNumTypes() == 1 && "FIXME: Unhandled");

3625      ResultPattern->setType(i, ResNodes[i]->getExtType(0));

3626    }

3627 

3628    // FIXME: Assume only the first tree is the pattern. The others are clobber

3629    // nodes.

3630    TreePatternNodePtr Pattern = I.getTree(0);

3631    TreePatternNodePtr SrcPattern;

3632    if (Pattern->getOperator()->getName() == "set") {

3633      SrcPattern = Pattern->getChild(Pattern->getNumChildren()-1)->clone();

3634    } else{

3635      // Not a set (store or something?)

3636      SrcPattern = Pattern;

3637    }

3638 

3639    // Create and insert the instruction.

3640    // FIXME: InstImpResults should not be part of DAGInstruction.

3641    Record *R = I.getRecord();

3642    DAGInsts.emplace(std::piecewise_construct, std::forward_as_tuple(R),

3643                     std::forward_as_tuple(Results, Operands, InstImpResults,

3644                                           SrcPattern, ResultPattern));

3645 

3646    LLVM_DEBUG(I.dump());

3647  }

v3.6.1一样,CodeGenDAGPatterns::parseInstructionPattern()接下来根据指令定义里声明的输入、输出操作数(Instruction定义里的OutOperandListInOperandList),检查从匹配模式得到的输入、输出操作数的个数、名字是否与定义一致(如果Instruction定义里使用了OperandWithDefaultOps类型操作数,这些操作数可以不出现在输入操作数列表中)。

注意3619ResultPattern的构建。其中的ResultNodeOperands是输入操作数,它的结果类型由输出操作数类型确定(3625行)。SrcPattern则在3630~3637行获取,如果I有多棵子树(这些子树来自Instruction定义的Pattern域),目前我们只假定第一棵树是相关的,其他树是无关的。

3642行,DAGInstsstd::map<Record*, DAGInstruction, LessRecordByID>类型容器,因此这行代码生成一个DAGInstruction实例,并与相关的Record*对象一起加入这个容器。

<think>嗯,用户想安装LLVM 19,但不知道该怎么找指南或者教程。首先,我需要回忆一下LLVM的安装方法。通常,LLVM可以通过源码编译或者预编译的二进制文件安装。用户提到的版本是19,可能指的是较新的版本,但官方稳定版可能还没到19,可能用户有特定需求或者版本号有误? 然后,用户提供的参考引用里提到了-DLLVM_ENABLE_SPHINX=On生成文档,这可能和构建文档相关,但安装的话可能需要不同的步骤。用户需要的是安装指南,可能需要分不同操作系统来考虑,比如Ubuntu、macOS或者Windows。 可能要先检查LLVM的官方网站,看看是否有官方安装说明。另外,LLVM通常提供预编译的二进制文件,用户可以直接下载。对于Linux系统,可能可以用包管理器,比如apt,但版本可能较旧。如果用户需要最新版本,可能需要添加第三方仓库或者自己编译源码。 编译源码的话,步骤可能包括下载源码、配置CMake、构建和安装。但这个过程比较复杂,特别是对于新手来说。需要确保系统依赖项安装正确,比如CMake、GCC等。另外,用户可能遇到权限问题,需要sudo权限来安装到系统目录。 还可能要考虑是否需要安装所有组件,比如clang、lldb等,或者只安装核心组件。用户的需求可能不明确,可能需要给出几种不同的安装方式,让他们根据自己的情况选择。 另外,用户提到的是版本19,但目前官方发布的最新稳定版本可能不是19,需要确认是否存在这个版本。如果不存在,可能需要用户从源码构建特定的分支或者使用开发中的版本。这时候可能需要指导他们如何检出特定的git分支或标签。 还有,用户可能遇到问题,比如依赖项缺失、编译错误等,需要提供一些常见问题的解决方法或者参考文档链接。比如,官方网站的文档或者社区论坛的支持。 综上所述,回答应该分步骤,覆盖不同操作系统,提供预编译包和源码编译两种方式,并提醒用户注意版本号和可能的依赖问题。同时,生成相关问题来帮助用户进一步了解安装后的配置和使用。</think>### 安装LLVM 19的指南 #### 1. 通过预编译二进制文件安装(推荐) 适用于Linux/macOS/Windows系统: - **步骤**: 1. 访问LLVM官方预编译包仓库:https://github.com/llvm/llvm-project/releases 2. 查找与系统匹配的版本(如`clang+llvm-19.0.0-x86_64-linux-gnu-ubuntu-22.04.tar.xz`) 3. 解压文件并添加二进制路径到环境变量: ```bash tar -xvf <下载的文件名> export PATH=$PATH:/解压路径/bin ``` #### 2. 通过包管理器安装(Linux) 适用于支持APT的Ubuntu/Debian系统: - **步骤**: ```bash # 添加LLVM官方仓库 wget -qO- https://apt.llvm.org/llvm.sh | sudo bash -s 19 # 安装核心组件 sudo apt install llvm-19 clang-19 lldb-19 ``` #### 3. 从源码编译安装 适用于需要自定义配置或调试的场景: - **步骤**: 1. 安装依赖项: ```bash sudo apt install cmake ninja-build gcc python3 ``` 2. 下载LLVM 19源码: ```bash git clone https://github.com/llvm/llvm-project.git cd llvm-project && git checkout llvmorg-19.0.0 ``` 3. 配置并编译: ```bash mkdir build && cd build cmake -G Ninja ../llvm -DLLVM_ENABLE_PROJECTS="clang;lld" ninja sudo ninja install ``` #### 验证安装 ```bash llvm-config --version # 应输出19.0.0 clang --version # 检查是否包含LLVM 19 ``` --- ### 常见问题解决 - **依赖项缺失**:根据CMake错误提示安装缺失的库(如`zlib1g-dev`) - **权限问题**:编译时使用`sudo`或指定用户目录安装路径(通过`CMAKE_INSTALL_PREFIX`配置) - **版本冲突**:若系统已安装旧版LLVM,可通过`update-alternatives`管理多版本[^1] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值