Alexei added may_goto insn in [1]. The asm syntax for may_goto looks
like
may_goto <label>
The instruction represents a conditional branch but the condition is
implicit. Later in bpf kernel verifier, the 'may_goto <label>' insn will
be rewritten with an explicit condition. The encoding of 'may_goto' insn
is enforced in [2] and is also implemented in this patch.
In [3], 'may_goto' insn is encoded with raw bytes. I made the following
change
```
--- a/tools/testing/selftests/bpf/bpf_experimental.h
+++ b/tools/testing/selftests/bpf/bpf_experimental.h
@@ -328,10 +328,7 @@ l_true: \
#define cond_break \
({ __label__ l_break, l_continue; \
- asm volatile goto("1:.byte 0xe5; \
- .byte 0; \
- .long ((%l[l_break] - 1b - 8) / 8) & 0xffff; \
- .short 0" \
+ asm volatile goto("may_goto %l[l_break]" \
:::: l_break); \
goto l_continue; \
l_break: break;
```
and ran the selftest with the latest llvm with this patch. All tests are
passed.
[1]
https://lore.kernel.org/bpf/20240306031929.42666-1-alexei.starovoitov@gmail.com/
[2]
https://lore.kernel.org/bpf/20240306031929.42666-2-alexei.starovoitov@gmail.com/
[3]
https://lore.kernel.org/bpf/20240306031929.42666-4-alexei.starovoitov@gmail.com/
95 lines
3.0 KiB
C++
95 lines
3.0 KiB
C++
//===--- BPF.cpp - Implement BPF target feature support -------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements BPF TargetInfo objects.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "BPF.h"
|
|
#include "Targets.h"
|
|
#include "clang/Basic/MacroBuilder.h"
|
|
#include "clang/Basic/TargetBuiltins.h"
|
|
#include "llvm/ADT/StringRef.h"
|
|
|
|
using namespace clang;
|
|
using namespace clang::targets;
|
|
|
|
static constexpr Builtin::Info BuiltinInfo[] = {
|
|
#define BUILTIN(ID, TYPE, ATTRS) \
|
|
{#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
|
|
#include "clang/Basic/BuiltinsBPF.inc"
|
|
};
|
|
|
|
void BPFTargetInfo::getTargetDefines(const LangOptions &Opts,
|
|
MacroBuilder &Builder) const {
|
|
Builder.defineMacro("__bpf__");
|
|
Builder.defineMacro("__BPF__");
|
|
|
|
std::string CPU = getTargetOpts().CPU;
|
|
if (CPU == "probe") {
|
|
Builder.defineMacro("__BPF_CPU_VERSION__", "0");
|
|
return;
|
|
}
|
|
|
|
Builder.defineMacro("__BPF_FEATURE_ADDR_SPACE_CAST");
|
|
|
|
if (CPU.empty() || CPU == "generic" || CPU == "v1") {
|
|
Builder.defineMacro("__BPF_CPU_VERSION__", "1");
|
|
return;
|
|
}
|
|
|
|
std::string CpuVerNumStr = CPU.substr(1);
|
|
Builder.defineMacro("__BPF_CPU_VERSION__", CpuVerNumStr);
|
|
Builder.defineMacro("__BPF_FEATURE_MAY_GOTO");
|
|
|
|
int CpuVerNum = std::stoi(CpuVerNumStr);
|
|
if (CpuVerNum >= 2)
|
|
Builder.defineMacro("__BPF_FEATURE_JMP_EXT");
|
|
|
|
if (CpuVerNum >= 3) {
|
|
Builder.defineMacro("__BPF_FEATURE_JMP32");
|
|
Builder.defineMacro("__BPF_FEATURE_ALU32");
|
|
}
|
|
|
|
if (CpuVerNum >= 4) {
|
|
Builder.defineMacro("__BPF_FEATURE_LDSX");
|
|
Builder.defineMacro("__BPF_FEATURE_MOVSX");
|
|
Builder.defineMacro("__BPF_FEATURE_BSWAP");
|
|
Builder.defineMacro("__BPF_FEATURE_SDIV_SMOD");
|
|
Builder.defineMacro("__BPF_FEATURE_GOTOL");
|
|
Builder.defineMacro("__BPF_FEATURE_ST");
|
|
}
|
|
}
|
|
|
|
static constexpr llvm::StringLiteral ValidCPUNames[] = {"generic", "v1", "v2",
|
|
"v3", "v4", "probe"};
|
|
|
|
bool BPFTargetInfo::isValidCPUName(StringRef Name) const {
|
|
return llvm::is_contained(ValidCPUNames, Name);
|
|
}
|
|
|
|
void BPFTargetInfo::fillValidCPUList(SmallVectorImpl<StringRef> &Values) const {
|
|
Values.append(std::begin(ValidCPUNames), std::end(ValidCPUNames));
|
|
}
|
|
|
|
ArrayRef<Builtin::Info> BPFTargetInfo::getTargetBuiltins() const {
|
|
return llvm::ArrayRef(BuiltinInfo,
|
|
clang::BPF::LastTSBuiltin - Builtin::FirstTSBuiltin);
|
|
}
|
|
|
|
bool BPFTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
|
|
DiagnosticsEngine &Diags) {
|
|
for (const auto &Feature : Features) {
|
|
if (Feature == "+alu32") {
|
|
HasAlu32 = true;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|