Skip to content

Commit 6245a4f

Browse files
authored
Add support for the .base64 directive (#165549)
Starting in version 15, GCC emits a `.base64` directive instead of `.string` or `.ascii` for char arrays of length `>= 3`. See [this godbolt link](https://godbolt.org/z/ebhe3oenv) for an example. This patch adds support for the .base64 directive to AsmParser.cpp, so tools like `llvm-mc` can process the output of GCC more effectively. This addresses #165499.
1 parent 7d0a208 commit 6245a4f

File tree

2 files changed

+74
-0
lines changed

2 files changed

+74
-0
lines changed

llvm/lib/MC/MCParser/AsmParser.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#include "llvm/MC/MCSymbolMachO.h"
4747
#include "llvm/MC/MCTargetOptions.h"
4848
#include "llvm/MC/MCValue.h"
49+
#include "llvm/Support/Base64.h"
4950
#include "llvm/Support/Casting.h"
5051
#include "llvm/Support/CommandLine.h"
5152
#include "llvm/Support/ErrorHandling.h"
@@ -528,6 +529,7 @@ class AsmParser : public MCAsmParser {
528529
DK_LTO_SET_CONDITIONAL,
529530
DK_CFI_MTE_TAGGED_FRAME,
530531
DK_MEMTAG,
532+
DK_BASE64,
531533
DK_END
532534
};
533535

@@ -550,6 +552,7 @@ class AsmParser : public MCAsmParser {
550552

551553
// ".ascii", ".asciz", ".string"
552554
bool parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated);
555+
bool parseDirectiveBase64(); // ".base64"
553556
bool parseDirectiveReloc(SMLoc DirectiveLoc); // ".reloc"
554557
bool parseDirectiveValue(StringRef IDVal,
555558
unsigned Size); // ".byte", ".long", ...
@@ -1951,6 +1954,8 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
19511954
case DK_ASCIZ:
19521955
case DK_STRING:
19531956
return parseDirectiveAscii(IDVal, true);
1957+
case DK_BASE64:
1958+
return parseDirectiveBase64();
19541959
case DK_BYTE:
19551960
case DK_DC_B:
19561961
return parseDirectiveValue(IDVal, 1);
@@ -3074,6 +3079,37 @@ bool AsmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
30743079
return parseMany(parseOp);
30753080
}
30763081

3082+
/// parseDirectiveBase64:
3083+
// ::= .base64 "string" (, "string" )*
3084+
bool AsmParser::parseDirectiveBase64() {
3085+
auto parseOp = [&]() -> bool {
3086+
if (checkForValidSection())
3087+
return true;
3088+
3089+
if (getTok().isNot(AsmToken::String)) {
3090+
return true;
3091+
}
3092+
3093+
std::vector<char> Decoded;
3094+
std::string const str = getTok().getStringContents().str();
3095+
if (check(str.empty(), "expected nonempty string")) {
3096+
return true;
3097+
}
3098+
3099+
llvm::Error e = decodeBase64(str, Decoded);
3100+
if (e) {
3101+
consumeError(std::move(e));
3102+
return Error(Lexer.getLoc(), "failed to base64 decode string data");
3103+
}
3104+
3105+
getStreamer().emitBytes(std::string(Decoded.begin(), Decoded.end()));
3106+
Lex();
3107+
return false;
3108+
};
3109+
3110+
return check(parseMany(parseOp), "expected string");
3111+
}
3112+
30773113
/// parseDirectiveReloc
30783114
/// ::= .reloc expression , identifier [ , expression ]
30793115
bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) {
@@ -5343,6 +5379,7 @@ void AsmParser::initializeDirectiveKindMap() {
53435379
DirectiveKindMap[".asciz"] = DK_ASCIZ;
53445380
DirectiveKindMap[".string"] = DK_STRING;
53455381
DirectiveKindMap[".byte"] = DK_BYTE;
5382+
DirectiveKindMap[".base64"] = DK_BASE64;
53465383
DirectiveKindMap[".short"] = DK_SHORT;
53475384
DirectiveKindMap[".value"] = DK_VALUE;
53485385
DirectiveKindMap[".2byte"] = DK_2BYTE;
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# RUN: llvm-mc -triple i386-unknown-unknown %s | FileCheck %s
2+
# RUN: not llvm-mc -triple i386-unknown-unknown -defsym=ERR=1 -o /dev/null %s 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR
3+
4+
.data
5+
# CHECK-LABEL: TEST0:
6+
# CHECK-NEXT: .byte 0
7+
TEST0:
8+
.base64 "AA=="
9+
10+
# CHECK-LABEL: TEST1:
11+
# CHECK-NEXT: .ascii "abcxyz"
12+
TEST1:
13+
.base64 "YWJjeHl6"
14+
15+
# CHECK-LABEL: TEST2:
16+
# CHECK-NEXT: .byte 1
17+
# CHECK-NEXT: .byte 2
18+
TEST2:
19+
.base64 "AQ=="
20+
.base64 "Ag=="
21+
22+
# CHECK-LABEL: TEST3:
23+
# CHECK-NEXT: .byte 1
24+
# CHECK-NEXT: .byte 2
25+
TEST3:
26+
.base64 "AQ==", "Ag=="
27+
28+
.ifdef ERR
29+
# CHECK-ERROR: [[#@LINE+1]]:17: error: expected string
30+
.base64 not-a-string
31+
32+
# CHECK-ERROR: [[#@LINE+1]]:17: error: failed to base64 decode string data
33+
.base64 "AA"
34+
35+
# CHECK-ERROR: [[#@LINE+1]]:17: error: expected nonempty string
36+
.base64 ""
37+
.endif

0 commit comments

Comments
 (0)