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";

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),输出的结果如下:

#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          }

62        };

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

33        const unsigned MAX_SUBTARGET_FEATURES = 64;

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      }

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

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 }, { } }

};

猜你喜欢

转载自blog.csdn.net/wuhui_gdnt/article/details/82015262