clang: lib/CodeGen/Targets/XCore.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
10#include "TargetInfo.h"
11
12using namespace clang;
14
15
16
17
18
19namespace {
20
21
22
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79class TypeStringCache {
80 enum Status {NonRecursive, Recursive, Incomplete, IncompleteUsed};
81 struct Entry {
82 std::string Str;
83 enum Status State;
84 std::string Swapped;
85
86 };
87 std::map<const IdentifierInfo *, struct Entry> Map;
88 unsigned IncompleteCount;
89 unsigned IncompleteUsedCount;
90public:
91 TypeStringCache() : IncompleteCount(0), IncompleteUsedCount(0) {}
92 void addIncomplete(const IdentifierInfo *ID, std::string StubEnc);
94 void addIfComplete(const IdentifierInfo *ID, StringRef Str,
95 bool IsRecursive);
97};
98
99
100
101class FieldEncoding {
102 bool HasName;
103 std::string Enc;
104public:
105 FieldEncoding(bool b, SmallStringEnc &e) : HasName(b), Enc(e.c_str()) {}
106 StringRef str() { return Enc; }
107 bool operator<(const FieldEncoding &rhs) const {
108 if (HasName != rhs.HasName) return HasName;
109 return Enc < rhs.Enc;
110 }
111};
112
114public:
118};
119
121 mutable TypeStringCache TSC;
122 void emitTargetMD(const Decl *D, llvm::GlobalValue *GV,
124
125public:
129 const llvm::MapVector<GlobalDecl, StringRef>
130 &MangledDeclNames) const override;
131};
132
133}
134
135
136
140
141
145
146
148 CharUnits TypeAlign = getContext().getTypeAlignInChars(Ty);
149 llvm::Type *ArgTy = CGT.ConvertType(Ty);
152 llvm::Type *ArgPtrTy = llvm::PointerType::getUnqual(ArgTy);
153
160 llvm_unreachable("Unsupported ABI kind for va_arg");
162 Val = Address(llvm::UndefValue::get(ArgPtrTy), ArgTy, TypeAlign);
164 break;
170 ArgSize = ArgSize.alignTo(SlotSize);
171 break;
175 Val = Address(Builder.CreateLoad(Val), ArgTy, TypeAlign);
176 ArgSize = SlotSize;
177 break;
178 }
179
180
181 if (!ArgSize.isZero()) {
182 Address APN = Builder.CreateConstInBoundsByteGEP(AP, ArgSize);
183 Builder.CreateStore(APN.emitRawPointer(CGF), VAListAddr);
184 }
185
187}
188
189
190
191
192
193
194void TypeStringCache::addIncomplete(const IdentifierInfo *ID,
195 std::string StubEnc) {
196 if (!ID)
197 return;
199 assert( (E.Str.empty() || E.State == Recursive) &&
200 "Incorrectly use of addIncomplete");
201 assert(!StubEnc.empty() && "Passing an empty string to addIncomplete()");
203 E.Str.swap(StubEnc);
205 ++IncompleteCount;
206}
207
208
209
210
211
212bool TypeStringCache::removeIncomplete(const IdentifierInfo *ID) {
213 if (!ID)
214 return false;
215 auto I = Map.find(ID);
216 assert(I != Map.end() && "Entry not present");
217 Entry &E = I->second;
219 E.State == IncompleteUsed) &&
220 "Entry must be an incomplete type");
221 bool IsRecursive = false;
222 if (E.State == IncompleteUsed) {
223
224 IsRecursive = true;
225 --IncompleteUsedCount;
226 }
227 if (E.Swapped.empty())
228 Map.erase(I);
229 else {
230
232 E.Swapped.clear();
233 E.State = Recursive;
234 }
235 --IncompleteCount;
236 return IsRecursive;
237}
238
239
240
241void TypeStringCache::addIfComplete(const IdentifierInfo *ID, StringRef Str,
242 bool IsRecursive) {
243 if (!ID || IncompleteUsedCount)
244 return;
246 if (IsRecursive && .Str.empty()) {
247 assert(E.State==Recursive && E.Str.size() == Str.size() &&
248 "This is not the same Recursive entry");
249
250
251
252 return;
253 }
254 assert(E.Str.empty() && "Entry already present");
255 E.Str = Str.str();
256 E.State = IsRecursive? Recursive : NonRecursive;
257}
258
259
260
261
262StringRef TypeStringCache::lookupStr(const IdentifierInfo *ID) {
263 if (!ID)
264 return StringRef();
265 auto I = Map.find(ID);
266 if (I == Map.end())
267 return StringRef();
268 Entry &E = I->second;
269 if (E.State == Recursive && IncompleteCount)
270 return StringRef();
271
273
274 E.State = IncompleteUsed;
275 ++IncompleteUsedCount;
276 }
277 return E.Str;
278}
279
280
281
282
283
284
285
286
287
288
289
290
291
294 TypeStringCache &TSC);
295
296
297void XCoreTargetCodeGenInfo::emitTargetMD(
298 const Decl *D, llvm::GlobalValue *GV,
300 SmallStringEnc Enc;
302 llvm::LLVMContext &Ctx = CGM.getModule().getContext();
303 llvm::Metadata *MDVals[] = {llvm::ConstantAsMetadata::get(GV),
304 llvm::MDString::get(Ctx, Enc.str())};
305 llvm::NamedMDNode *MD =
306 CGM.getModule().getOrInsertNamedMetadata("xcore.typestrings");
307 MD->addOperand(llvm::MDNode::get(Ctx, MDVals));
308 }
309}
310
311void XCoreTargetCodeGenInfo::emitTargetMetadata(
313 const llvm::MapVector<GlobalDecl, StringRef> &MangledDeclNames) const {
314
315
316
317 for (unsigned I = 0; I != MangledDeclNames.size(); ++I) {
318 auto Val = *(MangledDeclNames.begin() + I);
319 llvm::GlobalValue *GV = CGM.GetGlobalValue(Val.second);
320 if (GV) {
321 const Decl *D = Val.first.getDecl()->getMostRecentDecl();
322 emitTargetMD(D, GV, CGM);
323 }
324 }
325}
326
329 TypeStringCache &TSC);
330
331
332
333
337 TypeStringCache &TSC) {
338 for (const auto *Field : RD->fields()) {
339 SmallStringEnc Enc;
340 Enc += "m(";
341 Enc += Field->getName();
342 Enc += "){";
343 if (Field->isBitField()) {
344 Enc += "b(";
345 llvm::raw_svector_ostream OS(Enc);
346 OS << Field->getBitWidthValue();
347 Enc += ':';
348 }
349 if ((Enc, Field->getType(), CGM, TSC))
350 return false;
351 if (Field->isBitField())
352 Enc += ')';
353 Enc += '}';
354 FE.emplace_back(!Field->getName().empty(), Enc);
355 }
356 return true;
357}
358
359
360
361
365
366 StringRef TypeString = TSC.lookupStr(ID);
367 if (!TypeString.empty()) {
368 Enc += TypeString;
369 return true;
370 }
371
372
373 size_t Start = Enc.size();
375 Enc += '(';
376 if (ID)
377 Enc += ID->getName();
378 Enc += "){";
379
380
381 bool IsRecursive = false;
384
385
386
388 std::string StubEnc(Enc.substr(Start).str());
389 StubEnc += '}';
390 TSC.addIncomplete(ID, std::move(StubEnc));
392 (void) TSC.removeIncomplete(ID);
393 return false;
394 }
395 IsRecursive = TSC.removeIncomplete(ID);
396
397
399 llvm::sort(FE);
400
401 unsigned E = FE.size();
402 for (unsigned I = 0; I != E; ++I) {
403 if (I)
404 Enc += ',';
405 Enc += FE[I].str();
406 }
407 }
408 Enc += '}';
409 TSC.addIfComplete(ID, Enc.substr(Start), IsRecursive);
410 return true;
411}
412
413
415 TypeStringCache &TSC,
417
418 StringRef TypeString = TSC.lookupStr(ID);
419 if (!TypeString.empty()) {
420 Enc += TypeString;
421 return true;
422 }
423
424 size_t Start = Enc.size();
425 Enc += "e(";
426 if (ID)
427 Enc += ID->getName();
428 Enc += "){";
429
430
433 for (auto I = ED->enumerator_begin(), E = ED->enumerator_end(); I != E;
434 ++I) {
435 SmallStringEnc EnumEnc;
436 EnumEnc += "m(";
437 EnumEnc += I->getName();
438 EnumEnc += "){";
439 I->getInitVal().toString(EnumEnc);
440 EnumEnc += '}';
441 FE.push_back(FieldEncoding(!I->getName().empty(), EnumEnc));
442 }
443 llvm::sort(FE);
444 unsigned E = FE.size();
445 for (unsigned I = 0; I != E; ++I) {
446 if (I)
447 Enc += ',';
448 Enc += FE[I].str();
449 }
450 }
451 Enc += '}';
452 TSC.addIfComplete(ID, Enc.substr(Start), false);
453 return true;
454}
455
456
457
459
460 static const char *const Table[]={"","c:","r:","cr:","v:","cv:","rv:","crv:"};
461 int Lookup = 0;
463 Lookup += 1<<0;
465 Lookup += 1<<1;
467 Lookup += 1<<2;
468 Enc += Table[Lookup];
469}
470
471
473 const char *EncType;
475 case BuiltinType::Void:
476 EncType = "0";
477 break;
478 case BuiltinType::Bool:
479 EncType = "b";
480 break;
481 case BuiltinType::Char_U:
482 EncType = "uc";
483 break;
484 case BuiltinType::UChar:
485 EncType = "uc";
486 break;
487 case BuiltinType::SChar:
488 EncType = "sc";
489 break;
490 case BuiltinType::UShort:
491 EncType = "us";
492 break;
493 case BuiltinType::Short:
494 EncType = "ss";
495 break;
496 case BuiltinType::UInt:
497 EncType = "ui";
498 break;
499 case BuiltinType::Int:
500 EncType = "si";
501 break;
502 case BuiltinType::ULong:
503 EncType = "ul";
504 break;
505 case BuiltinType::Long:
506 EncType = "sl";
507 break;
508 case BuiltinType::ULongLong:
509 EncType = "ull";
510 break;
511 case BuiltinType::LongLong:
512 EncType = "sll";
513 break;
514 case BuiltinType::Float:
515 EncType = "ft";
516 break;
517 case BuiltinType::Double:
518 EncType = "d";
519 break;
520 case BuiltinType::LongDouble:
521 EncType = "ld";
522 break;
523 default:
524 return false;
525 }
526 Enc += EncType;
527 return true;
528}
529
530
533 TypeStringCache &TSC) {
534 Enc += "p(";
536 return false;
537 Enc += ')';
538 return true;
539}
540
541
545 TypeStringCache &TSC, StringRef NoSizeEnc) {
547 return false;
548 Enc += "a(";
549 if (const ConstantArrayType *CAT = dyn_cast(AT))
550 CAT->getSize().toStringUnsigned(Enc);
551 else
552 Enc += NoSizeEnc;
553 Enc += ':';
554
557 return false;
558 Enc += ')';
559 return true;
560}
561
562
563
566 TypeStringCache &TSC) {
567 Enc += "f{";
569 return false;
570 Enc += "}(";
572
573 auto I = FPT->param_type_begin();
574 auto E = FPT->param_type_end();
575 if (I != E) {
576 do {
578 return false;
579 ++I;
580 if (I != E)
581 Enc += ',';
582 } while (I != E);
583 if (FPT->isVariadic())
584 Enc += ",va";
585 } else {
586 if (FPT->isVariadic())
587 Enc += "va";
588 else
589 Enc += '0';
590 }
591 }
592 Enc += ')';
593 return true;
594}
595
596
597
600 TypeStringCache &TSC) {
601
603
605
606
608
610
613
616
619
622
625
628
629 return false;
630}
631
634 TypeStringCache &TSC) {
635 if ()
636 return false;
637
638 if (const FunctionDecl *FD = dyn_cast(D)) {
640 return false;
641 return appendType(Enc, FD->getType(), CGM, TSC);
642 }
643
644 if (const VarDecl *VD = dyn_cast(D)) {
646 return false;
647 QualType QT = VD->getType().getCanonicalType();
649
650
651
653 }
654 return appendType(Enc, QT, CGM, TSC);
655 }
656 return false;
657}
658
659std::unique_ptr
661 return std::make_unique(CGM.getTypes());
662}
static bool appendRecordType(SmallStringEnc &Enc, const RecordType *RT, const CodeGen::CodeGenModule &CGM, TypeStringCache &TSC, const IdentifierInfo *ID)
Appends structure and union types to Enc and adds encoding to cache.
static bool appendBuiltinType(SmallStringEnc &Enc, const BuiltinType *BT)
Appends built-in types to Enc.
static bool extractFieldType(SmallVectorImpl< FieldEncoding > &FE, const RecordDecl *RD, const CodeGen::CodeGenModule &CGM, TypeStringCache &TSC)
Helper function for appendRecordType().
static bool appendPointerType(SmallStringEnc &Enc, const PointerType *PT, const CodeGen::CodeGenModule &CGM, TypeStringCache &TSC)
Appends a pointer encoding to Enc before calling appendType for the pointee.
static bool appendFunctionType(SmallStringEnc &Enc, const FunctionType *FT, const CodeGen::CodeGenModule &CGM, TypeStringCache &TSC)
Appends a function encoding to Enc, calling appendType for the return type and the arguments.
static bool getTypeString(SmallStringEnc &Enc, const Decl *D, const CodeGen::CodeGenModule &CGM, TypeStringCache &TSC)
The XCore ABI includes a type information section that communicates symbol type information to the li...
static void appendQualifier(SmallStringEnc &Enc, QualType QT)
Appends type's qualifier to Enc.
static bool appendType(SmallStringEnc &Enc, QualType QType, const CodeGen::CodeGenModule &CGM, TypeStringCache &TSC)
Handles the type's qualifier before dispatching a call to handle specific type encodings.
static bool appendEnumType(SmallStringEnc &Enc, const EnumType *ET, TypeStringCache &TSC, const IdentifierInfo *ID)
Appends enum types to Enc and adds the encoding to the cache.
static bool appendArrayType(SmallStringEnc &Enc, QualType QT, const ArrayType *AT, const CodeGen::CodeGenModule &CGM, TypeStringCache &TSC, StringRef NoSizeEnc)
Appends array encoding to Enc before calling appendType for the element.
static CharUnits getTypeAllocSize(CodeGenModule &CGM, llvm::Type *type)
Represents an array type, per C99 6.7.5.2 - Array Declarators.
ArraySizeModifier getSizeModifier() const
QualType getElementType() const
This class is used for builtin types like 'int'.
CharUnits - This is an opaque type for sizes expressed in character units.
bool isZero() const
isZero - Test whether the quantity equals zero.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
CharUnits alignTo(const CharUnits &Align) const
alignTo - Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is ...
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
ABIArgInfo - Helper class to encapsulate information about how a specific C type should be passed to ...
void setCoerceToType(llvm::Type *T)
@ Extend
Extend - Valid only for integer argument types.
@ Ignore
Ignore - Ignore the argument (treat as void).
@ IndirectAliased
IndirectAliased - Similar to Indirect, but the pointer may be to an object that is otherwise referenc...
@ Expand
Expand - Only valid for aggregate argument types.
@ InAlloca
InAlloca - Pass the argument directly using the LLVM inalloca attribute.
@ Indirect
Indirect - Pass the argument indirectly via a hidden pointer with the specified alignment (0 indicate...
@ CoerceAndExpand
CoerceAndExpand - Only valid for aggregate argument types.
@ Direct
Direct - Pass the argument directly using the normal converted LLVM type, or by coercing to another s...
llvm::Type * getCoerceToType() const
bool canHaveCoerceToType() const
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
RValue EmitLoadOfAnyValue(LValue V, AggValueSlot Slot=AggValueSlot::ignored(), SourceLocation Loc={})
Like EmitLoadOfLValue but also handles complex and aggregate types.
This class organizes the cross-function state that is used while generating LLVM code.
llvm::Module & getModule() const
CodeGenTypes & getTypes()
llvm::GlobalValue * GetGlobalValue(StringRef Ref)
This class organizes the cross-module state that is used while lowering AST types to LLVM types.
DefaultABIInfo - The default implementation for ABI specific details.
RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty, AggValueSlot Slot) const override
EmitVAArg - Emit the target dependent code to load a value of.
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
TargetCodeGenInfo - This class organizes various target-specific codegeneration issues,...
virtual void emitTargetMetadata(CodeGen::CodeGenModule &CGM, const llvm::MapVector< GlobalDecl, StringRef > &MangledDeclNames) const
emitTargetMetadata - Provides a convenient hook to handle extra target-specific metadata for the give...
Represents the canonical version of C arrays with a specified constant size.
Decl - This represents one declaration (or definition), e.g.
EnumDecl * getDefinition() const
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of enums.
EnumDecl * getDecl() const
Represents a function declaration or definition.
Represents a prototype with parameter type info, e.g.
FunctionType - C99 6.7.5.3 - Function Declarators.
QualType getReturnType() const
One of these records is kept for each identifier that is lexed.
PointerType - C99 6.7.5.1 - Pointer Declarators.
QualType getPointeeType() const
A (possibly-)qualified type.
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
bool isRestrictQualified() const
Determine whether this type is restrict-qualified.
const IdentifierInfo * getBaseTypeIdentifier() const
Retrieves a pointer to the name of the base type.
QualType getCanonicalType() const
bool isConstQualified() const
Determine whether this type is const-qualified.
Represents a struct/union/class.
field_range fields() const
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
RecordDecl * getDecl() const
const RecordType * getAsUnionType() const
NOTE: getAs*ArrayType are methods on ASTContext.
const RecordType * getAsStructureType() const
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
const T * getAs() const
Member-template getAs'.
Represents a variable declaration or definition.
ABIArgInfo classifyArgumentType(CodeGenModule &CGM, CanQualType type)
Classify the rules for how to pass a particular type.
llvm::Type * getVAListElementType(CodeGenFunction &CGF)
std::unique_ptr< TargetCodeGenInfo > createXCoreTargetCodeGenInfo(CodeGenModule &CGM)
The JSON file list parser is used to communicate input to InstallAPI.
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
@ Incomplete
Template argument deduction did not deduce a value for every template parameter.