1 //===- SimpleTypeSerializer.cpp -----------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/DebugInfo/CodeView/SimpleTypeSerializer.h" 10 #include "llvm/DebugInfo/CodeView/CVRecord.h" 11 #include "llvm/DebugInfo/CodeView/RecordSerialization.h" 12 #include "llvm/DebugInfo/CodeView/TypeRecordMapping.h" 13 #include "llvm/Support/BinaryStreamWriter.h" 14 15 using namespace llvm; 16 using namespace llvm::codeview; 17 18 static void addPadding(BinaryStreamWriter &Writer) { 19 uint32_t Align = Writer.getOffset() % 4; 20 if (Align == 0) 21 return; 22 23 int PaddingBytes = 4 - Align; 24 while (PaddingBytes > 0) { 25 uint8_t Pad = static_cast<uint8_t>(LF_PAD0 + PaddingBytes); 26 cantFail(Writer.writeInteger(Pad)); 27 --PaddingBytes; 28 } 29 } 30 31 SimpleTypeSerializer::SimpleTypeSerializer() : ScratchBuffer(MaxRecordLength) {} 32 33 SimpleTypeSerializer::~SimpleTypeSerializer() = default; 34 35 template <typename T> 36 ArrayRef<uint8_t> SimpleTypeSerializer::serialize(T &Record) { 37 BinaryStreamWriter Writer(ScratchBuffer, support::little); 38 TypeRecordMapping Mapping(Writer); 39 40 // Write the record prefix first with a dummy length but real kind. 41 RecordPrefix DummyPrefix(uint16_t(Record.getKind())); 42 cantFail(Writer.writeObject(DummyPrefix)); 43 44 RecordPrefix *Prefix = reinterpret_cast<RecordPrefix *>(ScratchBuffer.data()); 45 CVType CVT(Prefix, sizeof(RecordPrefix)); 46 47 cantFail(Mapping.visitTypeBegin(CVT)); 48 cantFail(Mapping.visitKnownRecord(CVT, Record)); 49 cantFail(Mapping.visitTypeEnd(CVT)); 50 51 addPadding(Writer); 52 53 // Update the size and kind after serialization. 54 Prefix->RecordKind = CVT.kind(); 55 Prefix->RecordLen = Writer.getOffset() - sizeof(uint16_t); 56 57 return {ScratchBuffer.data(), static_cast<size_t>(Writer.getOffset())}; 58 } 59 60 // Explicitly instantiate the member function for each known type so that we can 61 // implement this in the cpp file. 62 #define TYPE_RECORD(EnumName, EnumVal, Name) \ 63 template ArrayRef<uint8_t> llvm::codeview::SimpleTypeSerializer::serialize( \ 64 Name##Record &Record); 65 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) 66 #define MEMBER_RECORD(EnumName, EnumVal, Name) 67 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) 68 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def" 69