Skip to content

Commit 06248fa

Browse files
luxufancuviper
luxufan
authored andcommitted
[RISCV] Support '.option arch' directive
The proposal of '.option arch' directive is riscv-non-isa/riscv-asm-manual#67 Note: For '.option arch, +/-' directive, version number is not yet supported. Reviewed By: luismarques, craig.topper Differential Revision: https://reviews.llvm.org/D123515
1 parent 0050e04 commit 06248fa

File tree

7 files changed

+395
-35
lines changed

7 files changed

+395
-35
lines changed

llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp

+159-34
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,12 @@ class RISCVAsmParser : public MCTargetAsmParser {
179179
bool parseDirectiveInsn(SMLoc L);
180180
bool parseDirectiveVariantCC();
181181

182+
/// Helper to reset target features for a new arch string. It
183+
/// also records the new arch string that is expanded by RISCVISAInfo
184+
/// and reports error for invalid arch string.
185+
bool resetToArch(StringRef Arch, SMLoc Loc, std::string &Result,
186+
bool FromOptionDirective);
187+
182188
void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
183189
if (!(getSTI().getFeatureBits()[Feature])) {
184190
MCSubtargetInfo &STI = copySTI();
@@ -2039,6 +2045,49 @@ bool RISCVAsmParser::ParseDirective(AsmToken DirectiveID) {
20392045
return true;
20402046
}
20412047

2048+
bool RISCVAsmParser::resetToArch(StringRef Arch, SMLoc Loc, std::string &Result,
2049+
bool FromOptionDirective) {
2050+
for (auto Feature : RISCVFeatureKV)
2051+
if (llvm::RISCVISAInfo::isSupportedExtensionFeature(Feature.Key))
2052+
clearFeatureBits(Feature.Value, Feature.Key);
2053+
2054+
auto ParseResult = llvm::RISCVISAInfo::parseArchString(
2055+
Arch, /*EnableExperimentalExtension=*/true,
2056+
/*ExperimentalExtensionVersionCheck=*/true);
2057+
if (!ParseResult) {
2058+
std::string Buffer;
2059+
raw_string_ostream OutputErrMsg(Buffer);
2060+
handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
2061+
OutputErrMsg << "invalid arch name '" << Arch << "', "
2062+
<< ErrMsg.getMessage();
2063+
});
2064+
2065+
return Error(Loc, OutputErrMsg.str());
2066+
}
2067+
auto &ISAInfo = *ParseResult;
2068+
2069+
for (auto Feature : RISCVFeatureKV)
2070+
if (ISAInfo->hasExtension(Feature.Key))
2071+
setFeatureBits(Feature.Value, Feature.Key);
2072+
2073+
if (FromOptionDirective) {
2074+
if (ISAInfo->getXLen() == 32 && isRV64())
2075+
return Error(Loc, "bad arch string switching from rv64 to rv32");
2076+
else if (ISAInfo->getXLen() == 64 && !isRV64())
2077+
return Error(Loc, "bad arch string switching from rv32 to rv64");
2078+
}
2079+
2080+
if (ISAInfo->getXLen() == 32)
2081+
clearFeatureBits(RISCV::Feature64Bit, "64bit");
2082+
else if (ISAInfo->getXLen() == 64)
2083+
setFeatureBits(RISCV::Feature64Bit, "64bit");
2084+
else
2085+
return Error(Loc, "bad arch string " + Arch);
2086+
2087+
Result = ISAInfo->toString();
2088+
return false;
2089+
}
2090+
20422091
bool RISCVAsmParser::parseDirectiveOption() {
20432092
MCAsmParser &Parser = getParser();
20442093
// Get the option token.
@@ -2071,6 +2120,109 @@ bool RISCVAsmParser::parseDirectiveOption() {
20712120
return false;
20722121
}
20732122

2123+
if (Option == "arch") {
2124+
2125+
Parser.parseComma();
2126+
2127+
bool PrefixEmitted = false;
2128+
bool IsExtensionList = false;
2129+
while (true) {
2130+
bool IsAdd;
2131+
if (Parser.getTok().is(AsmToken::Plus)) {
2132+
IsAdd = true;
2133+
IsExtensionList = true;
2134+
} else if (Parser.getTok().is(AsmToken::Minus)) {
2135+
IsAdd = false;
2136+
IsExtensionList = true;
2137+
} else {
2138+
SMLoc ArchLoc = Parser.getTok().getLoc();
2139+
2140+
if (IsExtensionList)
2141+
return Error(ArchLoc, "unexpected token, expected + or -");
2142+
2143+
StringRef Arch;
2144+
if (Parser.getTok().is(AsmToken::Identifier))
2145+
Arch = Parser.getTok().getString();
2146+
else
2147+
return Error(ArchLoc,
2148+
"unexpected token, expected identifier");
2149+
2150+
std::string Result;
2151+
if (resetToArch(Arch, ArchLoc, Result, true))
2152+
return true;
2153+
2154+
getTargetStreamer().emitDirectiveOptionArchFullArch(Result,
2155+
PrefixEmitted);
2156+
2157+
Parser.Lex();
2158+
2159+
return Parser.parseToken(AsmToken::EndOfStatement,
2160+
"unexpected token, expected end of statement");
2161+
}
2162+
2163+
Parser.Lex();
2164+
2165+
if (Parser.getTok().isNot(AsmToken::Identifier))
2166+
return Error(Parser.getTok().getLoc(),
2167+
"unexpected token, expected identifier");
2168+
2169+
StringRef ExtStr = Parser.getTok().getString();
2170+
2171+
ArrayRef<SubtargetFeatureKV> KVArray(RISCVFeatureKV);
2172+
auto Ext = llvm::lower_bound(KVArray, ExtStr);
2173+
if (Ext == KVArray.end() || StringRef(Ext->Key) != ExtStr ||
2174+
!RISCVISAInfo::isSupportedExtension(ExtStr)) {
2175+
if (isDigit(ExtStr.back()))
2176+
return Error(
2177+
Parser.getTok().getLoc(),
2178+
"Extension version number parsing not currently implemented");
2179+
return Error(Parser.getTok().getLoc(), "unknown extension feature");
2180+
}
2181+
2182+
SMLoc Loc = Parser.getTok().getLoc();
2183+
2184+
Parser.Lex(); // Eat arch string
2185+
bool HasComma = getTok().is(AsmToken::Comma);
2186+
if (IsAdd) {
2187+
setFeatureBits(Ext->Value, Ext->Key);
2188+
auto ParseResult = RISCVFeatures::parseFeatureBits(isRV64(), STI->getFeatureBits());
2189+
if (!ParseResult) {
2190+
std::string Buffer;
2191+
raw_string_ostream OutputErrMsg(Buffer);
2192+
handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
2193+
OutputErrMsg << ErrMsg.getMessage();
2194+
});
2195+
2196+
return Error(Loc, OutputErrMsg.str());
2197+
}
2198+
getTargetStreamer().emitDirectiveOptionArchPlus(Ext->Key, PrefixEmitted,
2199+
HasComma);
2200+
} else {
2201+
// It is invalid to disable an extension that there are other enabled
2202+
// extensions depend on it.
2203+
// TODO: Make use of RISCVISAInfo to handle this
2204+
for (auto Feature : KVArray) {
2205+
if (getSTI().hasFeature(Feature.Value) &&
2206+
Feature.Implies.test(Ext->Value))
2207+
return Error(Loc,
2208+
Twine("Can't disable ") + Ext->Key + " extension, " +
2209+
Feature.Key + " extension requires " + Ext->Key +
2210+
" extension be enabled");
2211+
}
2212+
2213+
clearFeatureBits(Ext->Value, Ext->Key);
2214+
getTargetStreamer().emitDirectiveOptionArchMinus(
2215+
Ext->Key, PrefixEmitted, HasComma);
2216+
}
2217+
2218+
if (!HasComma)
2219+
return Parser.parseToken(AsmToken::EndOfStatement,
2220+
"unexpected token, expected end of statement");
2221+
// Eat comma
2222+
Parser.Lex();
2223+
}
2224+
}
2225+
20742226
if (Option == "rvc") {
20752227
if (Parser.parseEOL())
20762228
return true;
@@ -2127,9 +2279,9 @@ bool RISCVAsmParser::parseDirectiveOption() {
21272279
}
21282280

21292281
// Unknown option.
2130-
Warning(Parser.getTok().getLoc(),
2131-
"unknown option, expected 'push', 'pop', 'rvc', 'norvc', 'relax' or "
2132-
"'norelax'");
2282+
Warning(Parser.getTok().getLoc(), "unknown option, expected 'push', 'pop', "
2283+
"'rvc', 'norvc', 'arch', 'relax' or "
2284+
"'norelax'");
21332285
Parser.eatToEndOfStatement();
21342286
return false;
21352287
}
@@ -2204,39 +2356,12 @@ bool RISCVAsmParser::parseDirectiveAttribute() {
22042356
else if (Tag != RISCVAttrs::ARCH)
22052357
getTargetStreamer().emitTextAttribute(Tag, StringValue);
22062358
else {
2207-
StringRef Arch = StringValue;
2208-
for (auto Feature : RISCVFeatureKV)
2209-
if (llvm::RISCVISAInfo::isSupportedExtensionFeature(Feature.Key))
2210-
clearFeatureBits(Feature.Value, Feature.Key);
2211-
2212-
auto ParseResult = llvm::RISCVISAInfo::parseArchString(
2213-
StringValue, /*EnableExperimentalExtension=*/true,
2214-
/*ExperimentalExtensionVersionCheck=*/true);
2215-
if (!ParseResult) {
2216-
std::string Buffer;
2217-
raw_string_ostream OutputErrMsg(Buffer);
2218-
handleAllErrors(ParseResult.takeError(), [&](llvm::StringError &ErrMsg) {
2219-
OutputErrMsg << "invalid arch name '" << Arch << "', "
2220-
<< ErrMsg.getMessage();
2221-
});
2222-
2223-
return Error(ValueExprLoc, OutputErrMsg.str());
2224-
}
2225-
auto &ISAInfo = *ParseResult;
2226-
2227-
for (auto Feature : RISCVFeatureKV)
2228-
if (ISAInfo->hasExtension(Feature.Key))
2229-
setFeatureBits(Feature.Value, Feature.Key);
2230-
2231-
if (ISAInfo->getXLen() == 32)
2232-
clearFeatureBits(RISCV::Feature64Bit, "64bit");
2233-
else if (ISAInfo->getXLen() == 64)
2234-
setFeatureBits(RISCV::Feature64Bit, "64bit");
2235-
else
2236-
return Error(ValueExprLoc, "bad arch string " + Arch);
2359+
std::string Result;
2360+
if (resetToArch(StringValue, ValueExprLoc, Result, false))
2361+
return true;
22372362

22382363
// Then emit the arch string.
2239-
getTargetStreamer().emitTextAttribute(Tag, ISAInfo->toString());
2364+
getTargetStreamer().emitTextAttribute(Tag, Result);
22402365
}
22412366

22422367
return false;

llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp

+44
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,14 @@ void RISCVTargetStreamer::emitDirectiveOptionNoRVC() {}
3434
void RISCVTargetStreamer::emitDirectiveOptionRelax() {}
3535
void RISCVTargetStreamer::emitDirectiveOptionNoRelax() {}
3636
void RISCVTargetStreamer::emitDirectiveVariantCC(MCSymbol &Symbol) {}
37+
void RISCVTargetStreamer::emitDirectiveOptionArchFullArch(StringRef Value,
38+
bool &hasDotOption) {}
39+
void RISCVTargetStreamer::emitDirectiveOptionArchPlus(StringRef Value,
40+
bool &hasDotOption,
41+
bool EmitComma) {}
42+
void RISCVTargetStreamer::emitDirectiveOptionArchMinus(StringRef Value,
43+
bool &hasDotOption,
44+
bool EmitComma) {}
3745
void RISCVTargetStreamer::emitAttribute(unsigned Attribute, unsigned Value) {}
3846
void RISCVTargetStreamer::finishAttributeSection() {}
3947
void RISCVTargetStreamer::emitTextAttribute(unsigned Attribute,
@@ -116,4 +124,40 @@ void RISCVTargetAsmStreamer::emitIntTextAttribute(unsigned Attribute,
116124
unsigned IntValue,
117125
StringRef StringValue) {}
118126

127+
static void emitDirectiveOptionArchPrefix(formatted_raw_ostream &OS,
128+
bool &PrefixEmitted) {
129+
if (!PrefixEmitted) {
130+
OS << "\t .option\tarch,\t";
131+
PrefixEmitted = true;
132+
}
133+
}
134+
135+
static void emitCommaOrNextLine(formatted_raw_ostream &OS, bool EmitComma) {
136+
if (EmitComma)
137+
OS << ", ";
138+
else
139+
OS << "\n";
140+
}
141+
142+
void RISCVTargetAsmStreamer::emitDirectiveOptionArchFullArch(
143+
StringRef Value, bool &PrefixEmitted) {
144+
emitDirectiveOptionArchPrefix(OS, PrefixEmitted);
145+
OS << Value;
146+
emitCommaOrNextLine(OS, false);
147+
}
148+
void RISCVTargetAsmStreamer::emitDirectiveOptionArchPlus(StringRef Value,
149+
bool &PrefixEmitted,
150+
bool EmitComma) {
151+
emitDirectiveOptionArchPrefix(OS, PrefixEmitted);
152+
OS << "+" << Value;
153+
emitCommaOrNextLine(OS, EmitComma);
154+
}
155+
void RISCVTargetAsmStreamer::emitDirectiveOptionArchMinus(StringRef Value,
156+
bool &PrefixEmitted,
157+
bool EmitComma) {
158+
emitDirectiveOptionArchPrefix(OS, PrefixEmitted);
159+
OS << "-" << Value;
160+
emitCommaOrNextLine(OS, EmitComma);
161+
}
162+
119163
void RISCVTargetAsmStreamer::finishAttributeSection() {}

llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.h

+13
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ class RISCVTargetStreamer : public MCTargetStreamer {
3434
virtual void emitDirectiveOptionRelax();
3535
virtual void emitDirectiveOptionNoRelax();
3636
virtual void emitDirectiveVariantCC(MCSymbol &Symbol);
37+
virtual void emitDirectiveOptionArchFullArch(StringRef Value,
38+
bool &PrefixEmitted);
39+
virtual void emitDirectiveOptionArchPlus(StringRef Value, bool &PrefixEmitted,
40+
bool EmitComma);
41+
virtual void emitDirectiveOptionArchMinus(StringRef Value,
42+
bool &PrefixEmitted,
43+
bool EmitComma);
3744
virtual void emitAttribute(unsigned Attribute, unsigned Value);
3845
virtual void finishAttributeSection();
3946
virtual void emitTextAttribute(unsigned Attribute, StringRef String);
@@ -67,6 +74,12 @@ class RISCVTargetAsmStreamer : public RISCVTargetStreamer {
6774
void emitDirectiveOptionRelax() override;
6875
void emitDirectiveOptionNoRelax() override;
6976
void emitDirectiveVariantCC(MCSymbol &Symbol) override;
77+
void emitDirectiveOptionArchFullArch(StringRef Value,
78+
bool &PrefixEmitted) override;
79+
void emitDirectiveOptionArchPlus(StringRef Value, bool &PrefixEmitted,
80+
bool EmitComma) override;
81+
void emitDirectiveOptionArchMinus(StringRef Value, bool &PrefixEmitted,
82+
bool EmitComma) override;
7083
};
7184

7285
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
; RUN: llc -mtriple=riscv64 < %s -o - | FileCheck --check-prefixes=CHECK-ATTRIBUTES %s
2+
; RUN: llc -mtriple=riscv64 < %s -filetype=obj | llvm-readelf -h - \
3+
; RUN: | FileCheck --check-prefixes=CHECK-EFLAGS %s
4+
5+
; CHECK-ATTRIBUTES: .attribute 5, "rv64i2p1"
6+
; CHECK-EFLAGS: Flags: 0x0
7+
define void @test() {
8+
tail call void asm ".option arch, +c", ""()
9+
ret void
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# RUN: llvm-mc -triple=riscv64 -filetype=obj %s -o - | llvm-readelf -h - \
2+
# RUN: | FileCheck --check-prefixes=CHECK %s
3+
4+
# CHECK: Flags: 0x0
5+
.option arch, +c

0 commit comments

Comments
 (0)