diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp index 38b6171ede9d..fd226eac4cdd 100644 --- a/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/llvm/lib/MC/MCParser/AsmParser.cpp @@ -467,6 +467,7 @@ private: DK_CV_INLINE_LINETABLE, DK_CV_DEF_RANGE, DK_CV_STRINGTABLE, + DK_CV_STRING, DK_CV_FILECHECKSUMS, DK_CV_FILECHECKSUM_OFFSET, DK_CV_FPO_DATA, @@ -538,7 +539,7 @@ private: bool parseDirectiveStabs(); // ".cv_file", ".cv_func_id", ".cv_inline_site_id", ".cv_loc", ".cv_linetable", - // ".cv_inline_linetable", ".cv_def_range" + // ".cv_inline_linetable", ".cv_def_range", ".cv_string" bool parseDirectiveCVFile(); bool parseDirectiveCVFuncId(); bool parseDirectiveCVInlineSiteId(); @@ -546,6 +547,7 @@ private: bool parseDirectiveCVLinetable(); bool parseDirectiveCVInlineLinetable(); bool parseDirectiveCVDefRange(); + bool parseDirectiveCVString(); bool parseDirectiveCVStringTable(); bool parseDirectiveCVFileChecksums(); bool parseDirectiveCVFileChecksumOffset(); @@ -2029,6 +2031,8 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, return parseDirectiveCVInlineLinetable(); case DK_CV_DEF_RANGE: return parseDirectiveCVDefRange(); + case DK_CV_STRING: + return parseDirectiveCVString(); case DK_CV_STRINGTABLE: return parseDirectiveCVStringTable(); case DK_CV_FILECHECKSUMS: @@ -3813,6 +3817,20 @@ bool AsmParser::parseDirectiveCVDefRange() { return false; } +/// parseDirectiveCVString +/// ::= .cv_stringtable "string" +bool AsmParser::parseDirectiveCVString() { + std::string Data; + if (checkForValidSection() || parseEscapedString(Data)) + return addErrorSuffix(" in '.cv_string' directive"); + + // Put the string in the table and emit the offset. + std::pair Insertion = + getCVContext().addToStringTable(Data); + getStreamer().EmitIntValue(Insertion.second, 4); + return false; +} + /// parseDirectiveCVStringTable /// ::= .cv_stringtable bool AsmParser::parseDirectiveCVStringTable() { @@ -5238,6 +5256,7 @@ void AsmParser::initializeDirectiveKindMap() { DirectiveKindMap[".cv_inline_linetable"] = DK_CV_INLINE_LINETABLE; DirectiveKindMap[".cv_inline_site_id"] = DK_CV_INLINE_SITE_ID; DirectiveKindMap[".cv_def_range"] = DK_CV_DEF_RANGE; + DirectiveKindMap[".cv_string"] = DK_CV_STRING; DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE; DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS; DirectiveKindMap[".cv_filechecksumoffset"] = DK_CV_FILECHECKSUM_OFFSET; diff --git a/llvm/test/MC/COFF/cv-string.s b/llvm/test/MC/COFF/cv-string.s new file mode 100644 index 000000000000..b3b670c48e99 --- /dev/null +++ b/llvm/test/MC/COFF/cv-string.s @@ -0,0 +1,69 @@ +# RUN: llvm-mc -triple=i686-windows-msvc %s -filetype=obj -o %t.obj +# RUN: llvm-readobj -codeview %t.obj | FileCheck %s + +# The .cv_string directive mainly exists as a convenience for manually writing +# FPO data in assembler. Test that we can write FPO data using this directive, +# and that the string comes out in the dumper. + +# void g(int); +# void f(int x) { +# g(x+1); +# } + +# CHECK: FrameFunc [ +# CHECK-NEXT: abc = +# CHECK-NEXT: def = +# CHECK-NEXT: ghi = +# CHECK-NEXT: ] + + .text + .def @feat.00; + .scl 3; + .type 0; + .endef + .globl @feat.00 +.set @feat.00, 1 + .def _f; + .scl 2; + .type 32; + .endef + .globl _f # -- Begin function f + .p2align 4, 0x90 +_f: # @f +Lfunc_begin0: +# %bb.0: # %entry + pushl %ebp + movl %esp, %ebp + subl $8, %esp + movl 8(%ebp), %eax + movl 8(%ebp), %ecx + addl $1, %ecx + movl %ecx, (%esp) + movl %eax, -4(%ebp) # 4-byte Spill + calll _g + addl $8, %esp + popl %ebp + retl +Lfunc_end0: + # -- End function + .section .debug$S,"dr" + .p2align 2 + .long 4 # Debug section magic + + # Open coded frame data + .long 245 + .long Lfoo_fpo_end-Lfoo_fpo_begin # Subsection size +Lfoo_fpo_begin: + .long _f + .long 0 + .long Lfunc_end0-Lfunc_begin0 + .long 24 # LocalSize + .long 0 # ParamSize + .long 0 # MaxStackSize + .cv_string "abc = def = ghi = " + .short 0 # PrologSize + .short 0 # SavedRegSize + .long 0x4 # Flags +Lfoo_fpo_end: + .p2align 2 + .cv_stringtable # String table