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;

198 Entry &E = Map[ID];

199 assert( (E.Str.empty() || E.State == Recursive) &&

200 "Incorrectly use of addIncomplete");

201 assert(!StubEnc.empty() && "Passing an empty string to addIncomplete()");

202 E.Swapped.swap(E.Str);

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

231 E.Swapped.swap(E.Str);

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;

245 Entry &E = Map[ID];

246 if (IsRecursive && E.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 (appendType(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 (D)

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.