capstone

Форк
0
/
0004-capstone-generate-GenDisassemblerTables.inc.patch 
471 строка · 17.3 Кб
1
From 29da4c6929679b8ac4019767ab4ebcd83c9894b4 Mon Sep 17 00:00:00 2001
2
From: mephi42 <mephi42@gmail.com>
3
Date: Tue, 7 Aug 2018 18:20:17 +0200
4
Subject: [PATCH 4/7] capstone: generate *GenDisassemblerTables.inc
5

6
---
7
 utils/TableGen/DisassemblerEmitter.cpp    |  12 +-
8
 utils/TableGen/FixedLenDecoderEmitter.cpp | 248 ++++++++++++++++++++--
9
 2 files changed, 239 insertions(+), 21 deletions(-)
10

11
diff --git a/utils/TableGen/DisassemblerEmitter.cpp b/utils/TableGen/DisassemblerEmitter.cpp
12
index b99a0a973a2..2ac6d89645c 100644
13
--- a/utils/TableGen/DisassemblerEmitter.cpp
14
+++ b/utils/TableGen/DisassemblerEmitter.cpp
15
@@ -106,6 +106,11 @@ extern void EmitFixedLenDecoder(RecordKeeper &RK, raw_ostream &OS,
16
 void EmitDisassembler(RecordKeeper &Records, raw_ostream &OS) {
17
   CodeGenTarget Target(Records);
18
   emitSourceFileHeader(" * " + Target.getName().str() + " Disassembler", OS);
19
+#ifdef CAPSTONE
20
+  OS << "/* Capstone Disassembly Engine */\n"
21
+        "/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2015 */\n"
22
+        "\n";
23
+#endif
24
 
25
   // X86 uses a custom disassembler.
26
   if (Target.getName() == "X86") {
27
@@ -150,7 +155,12 @@ void EmitDisassembler(RecordKeeper &Records, raw_ostream &OS) {
28
   }
29
 
30
   EmitFixedLenDecoder(Records, OS, Target.getName(),
31
-                      "if (", " == MCDisassembler::Fail)",
32
+                      "if (",
33
+#ifdef CAPSTONE
34
+                      " == MCDisassembler_Fail)",
35
+#else
36
+                      " == MCDisassembler::Fail)",
37
+#endif
38
                       "MCDisassembler::Success", "MCDisassembler::Fail", "");
39
 }
40
 
41
diff --git a/utils/TableGen/FixedLenDecoderEmitter.cpp b/utils/TableGen/FixedLenDecoderEmitter.cpp
42
index fcecc764d44..36845d960d8 100644
43
--- a/utils/TableGen/FixedLenDecoderEmitter.cpp
44
+++ b/utils/TableGen/FixedLenDecoderEmitter.cpp
45
@@ -730,7 +730,13 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
46
       ++I;
47
       unsigned Start = *I++;
48
       unsigned Len = *I++;
49
-      OS.indent(Indentation) << "MCD::OPC_ExtractField, " << Start << ", "
50
+      OS.indent(Indentation)
51
+#ifdef CAPSTONE
52
+        << "MCD_OPC_ExtractField"
53
+#else
54
+        << "MCD::OPC_ExtractField"
55
+#endif
56
+        << ", " << Start << ", "
57
         << Len << ",  // Inst{";
58
       if (Len > 1)
59
         OS << (Start + Len - 1) << "-";
60
@@ -739,7 +745,13 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
61
     }
62
     case MCD::OPC_FilterValue: {
63
       ++I;
64
-      OS.indent(Indentation) << "MCD::OPC_FilterValue, ";
65
+      OS.indent(Indentation)
66
+#ifdef CAPSTONE
67
+        << "MCD_OPC_FilterValue"
68
+#else
69
+        << "MCD::OPC_FilterValue"
70
+#endif
71
+        << ", ";
72
       // The filter value is ULEB128 encoded.
73
       while (*I >= 128)
74
         OS << (unsigned)*I++ << ", ";
75
@@ -759,7 +771,13 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
76
       ++I;
77
       unsigned Start = *I++;
78
       unsigned Len = *I++;
79
-      OS.indent(Indentation) << "MCD::OPC_CheckField, " << Start << ", "
80
+      OS.indent(Indentation)
81
+#ifdef CAPSTONE
82
+        << "MCD_OPC_CheckField"
83
+#else
84
+        << "MCD::OPC_CheckField"
85
+#endif
86
+        << ", " << Start << ", "
87
         << Len << ", ";// << Val << ", " << NumToSkip << ",\n";
88
       // ULEB128 encoded field value.
89
       for (; *I >= 128; ++I)
90
@@ -777,7 +795,13 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
91
     }
92
     case MCD::OPC_CheckPredicate: {
93
       ++I;
94
-      OS.indent(Indentation) << "MCD::OPC_CheckPredicate, ";
95
+      OS.indent(Indentation)
96
+#ifdef CAPSTONE
97
+        << "MCD_OPC_CheckPredicate"
98
+#else
99
+        << "MCD::OPC_CheckPredicate"
100
+#endif
101
+        << ", ";
102
       for (; *I >= 128; ++I)
103
         OS << (unsigned)*I << ", ";
104
       OS << (unsigned)*I++ << ", ";
105
@@ -803,7 +827,13 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
106
                && "ULEB128 value too large!");
107
       // Decode the Opcode value.
108
       unsigned Opc = decodeULEB128(Buffer);
109
-      OS.indent(Indentation) << "MCD::OPC_" << (IsTry ? "Try" : "")
110
+      OS.indent(Indentation)
111
+#ifdef CAPSTONE
112
+        << "MCD_OPC_"
113
+#else
114
+        << "MCD::OPC_"
115
+#endif
116
+        << (IsTry ? "Try" : "")
117
         << "Decode, ";
118
       for (p = Buffer; *p >= 128; ++p)
119
         OS << (unsigned)*p << ", ";
120
@@ -837,7 +867,12 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
121
     }
122
     case MCD::OPC_SoftFail: {
123
       ++I;
124
-      OS.indent(Indentation) << "MCD::OPC_SoftFail";
125
+      OS.indent(Indentation)
126
+#ifdef CAPSTONE
127
+        << "MCD_OPC_SoftFail";
128
+#else
129
+        << "MCD::OPC_SoftFail";
130
+#endif
131
       // Positive mask
132
       uint64_t Value = 0;
133
       unsigned Shift = 0;
134
@@ -869,7 +904,13 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
135
     }
136
     case MCD::OPC_Fail: {
137
       ++I;
138
-      OS.indent(Indentation) << "MCD::OPC_Fail,\n";
139
+      OS.indent(Indentation)
140
+#ifdef CAPSTONE
141
+        << "MCD_OPC_Fail"
142
+#else
143
+        << "MCD::OPC_Fail"
144
+#endif
145
+        << ",\n";
146
       break;
147
     }
148
     }
149
@@ -884,23 +925,46 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
150
 void FixedLenDecoderEmitter::
151
 emitPredicateFunction(formatted_raw_ostream &OS, PredicateSet &Predicates,
152
                       unsigned Indentation) const {
153
+#ifdef CAPSTONE
154
+  OS.indent(Indentation) << "static bool getbool(uint64_t b)\n";
155
+  OS.indent(Indentation) << "{\n";
156
+  OS.indent(Indentation) << "\treturn b != 0;\n";
157
+  OS.indent(Indentation) << "}\n\n";
158
+#endif
159
+
160
   // The predicate function is just a big switch statement based on the
161
   // input predicate index.
162
   OS.indent(Indentation) << "static bool checkDecoderPredicate(unsigned Idx, "
163
+#ifdef CAPSTONE
164
+    << "uint64_t Bits)\n{\n";
165
+#else
166
     << "const FeatureBitset& Bits) {\n";
167
+#endif
168
   Indentation += 2;
169
   if (!Predicates.empty()) {
170
     OS.indent(Indentation) << "switch (Idx) {\n";
171
-    OS.indent(Indentation) << "default: llvm_unreachable(\"Invalid index!\");\n";
172
+    OS.indent(Indentation) << "default: "
173
+#ifdef CAPSTONE
174
+      << "// "
175
+#endif
176
+      << "llvm_unreachable(\"Invalid index!\");\n";
177
     unsigned Index = 0;
178
     for (const auto &Predicate : Predicates) {
179
       OS.indent(Indentation) << "case " << Index++ << ":\n";
180
-      OS.indent(Indentation+2) << "return (" << Predicate << ");\n";
181
+      OS.indent(Indentation+2) << "return "
182
+#ifdef CAPSTONE
183
+        << "getbool"
184
+#endif
185
+        << "(" << Predicate << ");\n";
186
     }
187
     OS.indent(Indentation) << "}\n";
188
   } else {
189
     // No case statement to emit
190
-    OS.indent(Indentation) << "llvm_unreachable(\"Invalid index!\");\n";
191
+    OS.indent(Indentation)
192
+#ifdef CAPSTONE
193
+      << "// "
194
+#endif
195
+      << "llvm_unreachable(\"Invalid index!\");\n";
196
   }
197
   Indentation -= 2;
198
   OS.indent(Indentation) << "}\n\n";
199
@@ -911,23 +975,39 @@ emitDecoderFunction(formatted_raw_ostream &OS, DecoderSet &Decoders,
200
                     unsigned Indentation) const {
201
   // The decoder function is just a big switch statement based on the
202
   // input decoder index.
203
+#ifdef CAPSTONE
204
+#define EDF_EOL " \\\n"
205
+  OS.indent(Indentation) << "#define DecodeToMCInst(fname,fieldname, InsnType) \\\n";
206
+  OS.indent(Indentation) << "static DecodeStatus fname(DecodeStatus S, unsigned Idx, InsnType insn, MCInst *MI, \\\n";
207
+  OS.indent(Indentation) << "                uint64_t Address, const void *Decoder) \\\n";
208
+  OS.indent(Indentation) << "{ \\\n";
209
+#else
210
+#define EDF_EOL "\n"
211
   OS.indent(Indentation) << "template<typename InsnType>\n";
212
   OS.indent(Indentation) << "static DecodeStatus decodeToMCInst(DecodeStatus S,"
213
     << " unsigned Idx, InsnType insn, MCInst &MI,\n";
214
   OS.indent(Indentation) << "                                   uint64_t "
215
     << "Address, const void *Decoder, bool &DecodeComplete) {\n";
216
+#endif
217
   Indentation += 2;
218
+#ifndef CAPSTONE
219
   OS.indent(Indentation) << "DecodeComplete = true;\n";
220
-  OS.indent(Indentation) << "InsnType tmp;\n";
221
-  OS.indent(Indentation) << "switch (Idx) {\n";
222
-  OS.indent(Indentation) << "default: llvm_unreachable(\"Invalid index!\");\n";
223
+#endif
224
+  OS.indent(Indentation) << "InsnType tmp;" EDF_EOL;
225
+  OS.indent(Indentation) << "switch (Idx) {" EDF_EOL;
226
+  OS.indent(Indentation) << "default:"
227
+#ifndef CAPSTONE
228
+    << " llvm_unreachable(\"Invalid index!\");\n";
229
+#else
230
+    << " \\\n";
231
+#endif
232
   unsigned Index = 0;
233
   for (const auto &Decoder : Decoders) {
234
-    OS.indent(Indentation) << "case " << Index++ << ":\n";
235
+    OS.indent(Indentation) << "case " << Index++ << ":" EDF_EOL;
236
     OS << Decoder;
237
-    OS.indent(Indentation+2) << "return S;\n";
238
+    OS.indent(Indentation+2) << "return S;" EDF_EOL;
239
   }
240
-  OS.indent(Indentation) << "}\n";
241
+  OS.indent(Indentation) << "}" EDF_EOL;
242
   Indentation -= 2;
243
   OS.indent(Indentation) << "}\n\n";
244
 }
245
@@ -1054,16 +1134,21 @@ void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation,
246
   const std::string &Decoder = OpInfo.Decoder;
247
 
248
   if (OpInfo.numFields() != 1)
249
-    o.indent(Indentation) << "tmp = 0;\n";
250
+    o.indent(Indentation) << "tmp = 0;" EDF_EOL;
251
 
252
   for (const EncodingField &EF : OpInfo) {
253
     o.indent(Indentation) << "tmp ";
254
     if (OpInfo.numFields() != 1) o << '|';
255
-    o << "= fieldFromInstruction"
256
+    o << "= "
257
+#ifdef CAPSTONE
258
+      << "fieldname"
259
+#else
260
+      << "fieldFromInstruction"
261
+#endif
262
       << "(insn, " << EF.Base << ", " << EF.Width << ')';
263
     if (OpInfo.numFields() != 1 || EF.Offset != 0)
264
       o << " << " << EF.Offset;
265
-    o << ";\n";
266
+    o << ";" EDF_EOL;
267
   }
268
 
269
   if (Decoder != "") {
270
@@ -1071,8 +1156,12 @@ void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation,
271
     o.indent(Indentation) << Emitter->GuardPrefix << Decoder
272
       << "(MI, tmp, Address, Decoder)"
273
       << Emitter->GuardPostfix
274
+#ifdef CAPSTONE
275
+      << " return MCDisassembler_Fail; \\\n";
276
+#else
277
       << " { " << (OpHasCompleteDecoder ? "" : "DecodeComplete = false; ")
278
       << "return MCDisassembler::Fail; }\n";
279
+#endif
280
   } else {
281
     OpHasCompleteDecoder = true;
282
     o.indent(Indentation) << "MI.addOperand(MCOperand::createImm(tmp));\n";
283
@@ -1091,7 +1180,13 @@ void FilterChooser::emitDecoder(raw_ostream &OS, unsigned Indentation,
284
         << "(MI, insn, Address, Decoder)"
285
         << Emitter->GuardPostfix
286
         << " { " << (HasCompleteDecoder ? "" : "DecodeComplete = false; ")
287
-        << "return MCDisassembler::Fail; }\n";
288
+        << "return "
289
+#ifdef CAPSTONE
290
+        << "MCDisassembler_Fail"
291
+#else
292
+        << "MCDisassembler::Fail"
293
+#endif
294
+        << "; }\n";
295
       break;
296
     }
297
 
298
@@ -1129,10 +1224,19 @@ unsigned FilterChooser::getDecoderIndex(DecoderSet &Decoders,
299
 static void emitSinglePredicateMatch(raw_ostream &o, StringRef str,
300
                                      const std::string &PredicateNamespace) {
301
   if (str[0] == '!')
302
+#ifdef CAPSTONE
303
+    o << "~(Bits & " << PredicateNamespace << "_"
304
+      << str.slice(1,str.size()) << ")";
305
+#else
306
     o << "!Bits[" << PredicateNamespace << "::"
307
       << str.slice(1,str.size()) << "]";
308
+#endif
309
   else
310
+#ifdef CAPSTONE
311
+    o << "(Bits & " << PredicateNamespace << "_" << str << ")";
312
+#else
313
     o << "Bits[" << PredicateNamespace << "::" << str << "]";
314
+#endif
315
 }
316
 
317
 bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation,
318
@@ -2047,6 +2151,17 @@ static bool populateInstruction(CodeGenTarget &Target,
319
 // fieldFromInstruction().
320
 static void emitFieldFromInstruction(formatted_raw_ostream &OS) {
321
   OS << "// Helper function for extracting fields from encoded instructions.\n"
322
+#ifdef CAPSTONE
323
+     << "#define FieldFromInstruction(fname, InsnType) \\\n"
324
+     << "static InsnType fname(InsnType insn, unsigned startBit, unsigned numBits) \\\n"
325
+     << "{ \\\n"
326
+     << "  InsnType fieldMask; \\\n"
327
+     << "  if (numBits == sizeof(InsnType)*8) \\\n"
328
+     << "    fieldMask = (InsnType)(-1LL); \\\n"
329
+     << "  else \\\n"
330
+     << "    fieldMask = (((InsnType)1 << numBits) - 1) << startBit; \\\n"
331
+     << "  return (insn & fieldMask) >> startBit; \\\n"
332
+#else
333
      << "template<typename InsnType>\n"
334
    << "static InsnType fieldFromInstruction(InsnType insn, unsigned startBit,\n"
335
      << "                                     unsigned numBits) {\n"
336
@@ -2058,12 +2173,92 @@ static void emitFieldFromInstruction(formatted_raw_ostream &OS) {
337
      << "    else\n"
338
      << "      fieldMask = (((InsnType)1 << numBits) - 1) << startBit;\n"
339
      << "    return (insn & fieldMask) >> startBit;\n"
340
+#endif
341
      << "}\n\n";
342
 }
343
 
344
 // emitDecodeInstruction - Emit the templated helper function
345
 // decodeInstruction().
346
 static void emitDecodeInstruction(formatted_raw_ostream &OS) {
347
+#ifdef CAPSTONE
348
+  OS << "#define DecodeInstruction(fname, fieldname, decoder, InsnType) \\\n"
349
+     << "static DecodeStatus fname(const uint8_t DecodeTable[], MCInst *MI, \\\n"
350
+     << "           InsnType insn, uint64_t Address, const MCRegisterInfo *MRI, int feature) \\\n"
351
+     << "{ \\\n"
352
+     << "  uint64_t Bits = getFeatureBits(feature); \\\n"
353
+     << "  const uint8_t *Ptr = DecodeTable; \\\n"
354
+     << "  uint32_t CurFieldValue = 0, ExpectedValue; \\\n"
355
+     << "  DecodeStatus S = MCDisassembler_Success; \\\n"
356
+     << "  unsigned Start, Len, NumToSkip, PIdx, Opc, DecodeIdx; \\\n"
357
+     << "  InsnType Val, FieldValue, PositiveMask, NegativeMask; \\\n"
358
+     << "  bool Pred, Fail; \\\n"
359
+     << "  for (;;) { \\\n"
360
+     << "    switch (*Ptr) { \\\n"
361
+     << "    default: \\\n"
362
+     << "      return MCDisassembler_Fail; \\\n"
363
+     << "    case MCD_OPC_ExtractField: { \\\n"
364
+     << "      Start = *++Ptr; \\\n"
365
+     << "      Len = *++Ptr; \\\n"
366
+     << "      ++Ptr; \\\n"
367
+     << "      CurFieldValue = (uint32_t)fieldname(insn, Start, Len); \\\n"
368
+     << "      break; \\\n"
369
+     << "    } \\\n"
370
+     << "    case MCD_OPC_FilterValue: { \\\n"
371
+     << "      Val = (InsnType)decodeULEB128(++Ptr, &Len); \\\n"
372
+     << "      Ptr += Len; \\\n"
373
+     << "      NumToSkip = *Ptr++; \\\n"
374
+     << "      NumToSkip |= (*Ptr++) << 8; \\\n"
375
+     << "      if (Val != CurFieldValue) \\\n"
376
+     << "        Ptr += NumToSkip; \\\n"
377
+     << "      break; \\\n"
378
+     << "    } \\\n"
379
+     << "    case MCD_OPC_CheckField: { \\\n"
380
+     << "      Start = *++Ptr; \\\n"
381
+     << "      Len = *++Ptr; \\\n"
382
+     << "      FieldValue = fieldname(insn, Start, Len); \\\n"
383
+     << "      ExpectedValue = (uint32_t)decodeULEB128(++Ptr, &Len); \\\n"
384
+     << "      Ptr += Len; \\\n"
385
+     << "      NumToSkip = *Ptr++; \\\n"
386
+     << "      NumToSkip |= (*Ptr++) << 8; \\\n"
387
+     << "      if (ExpectedValue != FieldValue) \\\n"
388
+     << "        Ptr += NumToSkip; \\\n"
389
+     << "      break; \\\n"
390
+     << "    } \\\n"
391
+     << "    case MCD_OPC_CheckPredicate: { \\\n"
392
+     << "      PIdx = (uint32_t)decodeULEB128(++Ptr, &Len); \\\n"
393
+     << "      Ptr += Len; \\\n"
394
+     << "      NumToSkip = *Ptr++; \\\n"
395
+     << "      NumToSkip |= (*Ptr++) << 8; \\\n"
396
+     << "      Pred = checkDecoderPredicate(PIdx, Bits); \\\n"
397
+     << "      if (!Pred) \\\n"
398
+     << "        Ptr += NumToSkip; \\\n"
399
+     << "      (void)Pred; \\\n"
400
+     << "      break; \\\n"
401
+     << "    } \\\n"
402
+     << "    case MCD_OPC_Decode: { \\\n"
403
+     << "      Opc = (unsigned)decodeULEB128(++Ptr, &Len); \\\n"
404
+     << "      Ptr += Len; \\\n"
405
+     << "      DecodeIdx = (unsigned)decodeULEB128(Ptr, &Len); \\\n"
406
+     << "      Ptr += Len; \\\n"
407
+     << "      MCInst_setOpcode(MI, Opc); \\\n"
408
+     << "      return decoder(S, DecodeIdx, insn, MI, Address, MRI); \\\n"
409
+     << "    } \\\n"
410
+     << "    case MCD_OPC_SoftFail: { \\\n"
411
+     << "      PositiveMask = (InsnType)decodeULEB128(++Ptr, &Len); \\\n"
412
+     << "      Ptr += Len; \\\n"
413
+     << "      NegativeMask = (InsnType)decodeULEB128(Ptr, &Len); \\\n"
414
+     << "      Ptr += Len; \\\n"
415
+     << "      Fail = (insn & PositiveMask) || (~insn & NegativeMask); \\\n"
416
+     << "      if (Fail) \\\n"
417
+     << "        S = MCDisassembler_SoftFail; \\\n"
418
+     << "      break; \\\n"
419
+     << "    } \\\n"
420
+     << "    case MCD_OPC_Fail: { \\\n"
421
+     << "      return MCDisassembler_Fail; \\\n"
422
+     << "    } \\\n"
423
+     << "    } \\\n"
424
+     << "  } \\\n"
425
+#else
426
   OS << "template<typename InsnType>\n"
427
      << "static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], "
428
         "MCInst &MI,\n"
429
@@ -2240,12 +2435,18 @@ static void emitDecodeInstruction(formatted_raw_ostream &OS) {
430
      << "  }\n"
431
      << "  llvm_unreachable(\"bogosity detected in disassembler state "
432
         "machine!\");\n"
433
+#endif
434
      << "}\n\n";
435
 }
436
 
437
 // Emits disassembler code for instruction decoding.
438
 void FixedLenDecoderEmitter::run(raw_ostream &o) {
439
   formatted_raw_ostream OS(o);
440
+#ifdef CAPSTONE
441
+  OS << "#include \"../../MCInst.h\"\n";
442
+  OS << "#include \"../../LEB128.h\"\n";
443
+  OS << "\n";
444
+#else
445
   OS << "#include \"llvm/MC/MCInst.h\"\n";
446
   OS << "#include \"llvm/Support/Debug.h\"\n";
447
   OS << "#include \"llvm/Support/DataTypes.h\"\n";
448
@@ -2254,6 +2455,7 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) {
449
   OS << "#include <assert.h>\n";
450
   OS << '\n';
451
   OS << "namespace llvm {\n\n";
452
+#endif
453
 
454
   emitFieldFromInstruction(OS);
455
 
456
@@ -2322,7 +2524,13 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) {
457
   // Emit the main entry point for the decoder, decodeInstruction().
458
   emitDecodeInstruction(OS);
459
 
460
+#ifdef CAPSTONE
461
+  OS << "FieldFromInstruction(fieldFromInstruction, uint64_t)\n";
462
+  OS << "DecodeToMCInst(decodeToMCInst, fieldFromInstruction, uint64_t)\n";
463
+  OS << "DecodeInstruction(decodeInstruction, fieldFromInstruction, decodeToMCInst, uint64_t)\n";
464
+#else
465
   OS << "\n} // End llvm namespace\n";
466
+#endif
467
 }
468
 
469
 namespace llvm {
470
-- 
471
2.19.1
472

473

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.