LLVM学习笔记(40)

3.6. 描述目标机器的数据结构

描述目标机器的数据结构由TableGen的“-gen-subtarget”选项生成。以X86来说,生成文件是X86GenSubtargetInfo.Inc。

3.6.1. 对目标机器描述的解析

这个选项的处理入口是下面的方法:

1154  void EmitSubtarget(RecordKeeper &RK, raw_ostream &OS) {

1155    CodeGenTarget CGTarget(RK);

1156    SubtargetEmitter(RK, CGTarget).run(OS);

1157  }

SubtargetEmitter的构造函数有如下定义。

104       SubtargetEmitter(RecordKeeper &R, CodeGenTarget &TGT):

105         Records(R), SchedModels(TGT.getSchedModels()), Target(TGT.getName()) {}

SchedModels是SubtargetEmitter中类型为CodeGenSchedModels的成员,这个构造函数我们已经在前面看过了(这是一个相当复杂的过程,还好我们已经知道了,由此可见LLVM有相当好的代码重用设计)。

3.6.2. 代码生成

3.6.2.1. 处理器特征的描述

同样不出所料,SubtargetEmitter::run()方法首先输出的与此相关的枚举常量。

1409  void SubtargetEmitter::run(raw_ostream &OS) {

1410    emitSourceFileHeader("Subtarget Enumeration Source Fragment", OS);

1411 

1412    OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n";

1413    OS << "#undef GET_SUBTARGETINFO_ENUM\n";

1414 

1415    OS << "namespace llvm {\n";

1416    Enumeration(OS, "SubtargetFeature");

1417    OS << "} // End llvm namespace \n";

1418    OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n";

1419 

1420    OS << "\n#ifdef GET_SUBTARGETINFO_MC_DESC\n";

1421    OS << "#undef GET_SUBTARGETINFO_MC_DESC\n";

1422 

1423    OS << "namespace llvm {\n";

1424  #if 0

1425    OS << "namespace {\n";

1426  #endif

1427    unsigned NumFeatures = FeatureKeyValues(OS);

1428    OS << "\n";

1429    unsigned NumProcs = CPUKeyValues(OS);

1430    OS << "\n";

1431    EmitSchedModel(OS);

1432    OS << "\n";

1433  #if 0

1434    OS << "}\n";

1435  #endif

处理器所具有的特征由SubtargetFeatures派生定义来描述。因此首先需要通过下面的方法来输出标识这些特征的枚举常量。

115     void SubtargetEmitter::Enumeration(raw_ostream &OS,

116                                        const char *ClassName) {

117       // Get all records of class and sort

118       std::vector<Record*> DefList = Records.getAllDerivedDefinitions(ClassName);

119       std::sort(DefList.begin(), DefList.end(), LessRecord());

120    

121       unsigned N = DefList.size();

122       if (N == 0)

123         return;

124       if (N > MAX_SUBTARGET_FEATURES)

125         PrintFatalError("Too many subtarget features! Bump MAX_SUBTARGET_FEATURES.");

126    

127       OS << "namespace " << Target << " {\n";

128    

129       // Open enumeration. Use a 64-bit underlying type.

130       OS << "enum : uint64_t {\n";                                                                                                     <-- v7.0删除

  OS << "enum {\n";                                                                                                                       <-- v7.0增加

131    

132       // For each record

133       for (unsigned i = 0; i < N;) {

134         // Next record

135         Record *Def = DefList[i];

136    

137         // Get and emit name

138         OS << "  " << Def->getName() << " = " << i;

139         if (++i < N) OS << ",";

140    

141         OS << "\n";

142       }

143    

144       // Close enumeration and namespace

145       OS << "};\n}\n";

146     }

因为这些枚举常量将指定一个特定标志的比特位,可能出于历史原因,LLVM将这些枚举常量限定在64以下(124行的MAX_SUBTARGET_FEATURES,X86目前用到61。V7.0则用到了123,去掉了跟在enum后面uint64_t),输出的结果如下:

#ifdef GET_SUBTARGETINFO_ENUM

#undef GET_SUBTARGETINFO_ENUM

namespace llvm {

namespace X86 {

enum : uint64_t {

  Feature3DNow = 0,

  Feature3DNowA = 1,

  Feature64Bit = 2,

  FeatureADX = 3,

  …

  ProcIntelSLM = 61

};

}

} // End llvm namespace

#endif // GET_SUBTARGETINFO_ENUM

接下来需要输出描述各个处理器具有哪些特性的数据结构。首先输出的是描述特性间包含关系的SubtargetFeatureKV类型数组。SubtargetFeatureKV的定义如下:

52       struct SubtargetFeatureKV {

53         const char *Key;                      // K-V key string

54         const char *Desc;                     // Help descriptor

55         FeatureBitset Value;                  // K-V integer value

56         FeatureBitset Implies;                // K-V bit mask

57      

58         // Compare routine for std::lower_bound

59         bool operator<(StringRef S) const {

60           return StringRef(Key) < S;

61         }

 

  /// Compare routine for std::is_sorted.

  bool operator<(const SubtargetFeatureKV &Other) const {                                               <-- v7.0增加

    return StringRef(Key) < StringRef(Other.Key);

  }

62       };

其中Key用作排序的键值,Value是该实例所代表的处理器特性,Implies则是该特性所隐含的其他特性。类型FeatureBitset是这样的一个定义:

33       const unsigned MAX_SUBTARGET_FEATURES = 64;             <-- v7.0增加到192

34       class FeatureBitset: public std::bitset<MAX_SUBTARGET_FEATURES> {

35       public:

36         // Cannot inherit constructors because it's not supported by VC++..

37         FeatureBitset() : bitset() {}

38      

39         FeatureBitset(const bitset<MAX_SUBTARGET_FEATURES>& B) : bitset(B) {}

40      

41         FeatureBitset(std::initializer_list<unsigned> Init) : bitset() {

42           for (auto I = Init.begin() , E = Init.end(); I != E; ++I)

43             set(*I);

44         }

45       };

FeatureBitset保存的就是前面输出的代表各个处理器特性的枚举常量。LLVM提供这个类,是因为std::bitset不提供第三个构造函数的形式(41行),这个构造函数是下面输出X86SubTypeKV所需要的形式。

152     unsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) {

153       // Gather and sort all the features

154       std::vector<Record*> FeatureList =

155                                Records.getAllDerivedDefinitions("SubtargetFeature");

156    

157       if (FeatureList.empty())

158         return 0;

159    

160       std::sort(FeatureList.begin(), FeatureList.end(), LessRecordFieldName());

161    

162       // Begin feature table

163       OS << "// Sorted (by key) array of values for CPU features.\n"

164          << "extern const llvm::SubtargetFeatureKV " << Target

165          << "FeatureKV[] = {\n";

166    

167       // For each feature

168       unsigned NumFeatures = 0;

169       for (unsigned i = 0, N = FeatureList.size(); i < N; ++i) {

170         // Next feature

171         Record *Feature = FeatureList[i];

172    

173         const std::string &Name = Feature->getName();

174         const std::string &CommandLineName = Feature->getValueAsString("Name");

175         const std::string &Desc = Feature->getValueAsString("Desc");

176    

177         if (CommandLineName.empty()) continue;

178    

179         // Emit as { "feature", "description", { featureEnum }, { i1 , i2 , ... , in } }

180         OS << "  { "

181            << "\"" << CommandLineName << "\", "

182            << "\"" << Desc << "\", "

183            << "{ " << Target << "::" << Name << " }, ";

184    

185         const std::vector<Record*> &ImpliesList =

186           Feature->getValueAsListOfDefs("Implies");

187    

188         if (ImpliesList.empty()) {

189           OS << "{ }";

190         } else {

191           OS << "{ ";

192           for (unsigned j = 0, M = ImpliesList.size(); j < M;) {

193             OS << Target << "::" << ImpliesList[j]->getName();

194             if (++j < M) OS << ", ";

195           }

196           OS << " }";

197         }

198    

199         OS << " }";

200         ++NumFeatures;

201    

202         // Depending on 'if more in the list' emit comma

203         if ((i + 1) < N) OS << ",";

204    

205         OS << "\n";

206       }

207    

208       // End feature table

209       OS << "};\n";

210    

211       return NumFeatures;

212     }

在这些SubtargetFeatureKV对象里,Key都是这些特性的名字,这样我们得到如下的输出:

#ifdef GET_SUBTARGETINFO_MC_DESC

#undef GET_SUBTARGETINFO_MC_DESC

namespace llvm {

// Sorted (by key) array of values for CPU features.

extern const llvm::SubtargetFeatureKV X86FeatureKV[] = {

  { "16bit-mode", "16-bit mode (i8086)", { X86::Mode16Bit }, { } },

  { "32bit-mode", "32-bit mode (80386)", { X86::Mode32Bit }, { } },

  { "3dnow", "Enable 3DNow! instructions", { X86::Feature3DNow }, { X86::FeatureMMX } },

  …

  { "xop", "Enable XOP instructions", { X86::FeatureXOP }, { X86::FeatureFMA4 } }

};

接下来输出的就是描述各个处理器具有哪些特性的SubtargetFeatureKV类型数组。显然对这个数组来说,键值就应该是处理器的名字。

218   unsigned SubtargetEmitter::CPUKeyValues(raw_ostream &OS) {

219       // Gather and sort processor information

220       std::vector<Record*> ProcessorList =

221                               Records.getAllDerivedDefinitions("Processor");

222       std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName());

223    

224       // Begin processor table

225       OS << "// Sorted (by key) array of values for CPU subtype.\n"

226          << "extern const llvm::SubtargetFeatureKV " << Target

227          << "SubTypeKV[] = {\n";

228    

229       // For each processor

230       for (unsigned i = 0, N = ProcessorList.size(); i < N;) {

231         // Next processor

232         Record *Processor = ProcessorList[i];

233    

234         const std::string &Name = Processor->getValueAsString("Name");

235         const std::vector<Record*> &FeatureList =

236           Processor->getValueAsListOfDefs("Features");

237    

238         // Emit as { "cpu", "description", { f1 , f2 , ... fn } },

239         OS << "  { "

240            << "\"" << Name << "\", "

241            << "\"Select the " << Name << " processor\", ";

242    

243         if (FeatureList.empty()) {

244           OS << "{ }";

245         } else {

246           OS << "{ ";

247           for (unsigned j = 0, M = FeatureList.size(); j < M;) {

248             OS << Target << "::" << FeatureList[j]->getName();

249             if (++j < M) OS << ", ";

250           }

251           OS << " }";

252         }

253    

254         // The { } is for the "implies" section of this data structure.

255         OS << ", { } }";

256    

257         // Depending on 'if more in the list' emit comma

258         if (++i < N) OS << ",";

259    

260         OS << "\n";

261       }

262    

263       // End processor table

264       OS << "};\n";

265    

266       return ProcessorList.size();

267     }

这样,我们就得到如下的一个数组:

// Sorted (by key) array of values for CPU subtype.

extern const llvm::SubtargetFeatureKV X86SubTypeKV[] = {

  { "amdfam10", "Select the amdfam10 processor", { X86::FeatureSSE4A, X86::Feature3DNowA, X86::FeatureCMPXCHG16B, X86::FeatureLZCNT, X86::FeaturePOPCNT, X86::FeatureSlowBTMem, X86::FeatureSlowSHLD }, { } },

  { "athlon", "Select the athlon processor", { X86::Feature3DNowA, X86::FeatureSlowBTMem, X86::FeatureSlowSHLD }, { } },

  { "athlon-4", "Select the athlon-4 processor", { X86::FeatureSSE1, X86::Feature3DNowA, X86::FeatureSlowBTMem, X86::FeatureSlowSHLD }, { } },

   …

  { "yonah", "Select the yonah processor", { X86::FeatureSSE3, X86::FeatureSlowBTMem }, { } }

};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值