// REQUIRES: bpf-registered-target
-// RUN: %clang -target bpf -emit-llvm -S -g %s -o - | FileCheck %s
+// RUN: %clang -target bpf -emit-llvm -S -g -Xclang -disable-llvm-passes %s -o - | FileCheck %s
#define __reloc__ __attribute__((preserve_access_index))
// REQUIRES: bpf-registered-target
-// RUN: %clang -target bpf -emit-llvm -S -g %s -o - | FileCheck %s
+// RUN: %clang -target bpf -emit-llvm -S -g -Xclang -disable-llvm-passes %s -o - | FileCheck %s
#define __reloc__ __attribute__((preserve_access_index))
// REQUIRES: bpf-registered-target
-// RUN: %clang -target bpf -emit-llvm -S -g %s -o - | FileCheck %s
+// RUN: %clang -target bpf -emit-llvm -S -g -Xclang -disable-llvm-passes %s -o - | FileCheck %s
#define __reloc__ __attribute__((preserve_access_index))
// REQUIRES: bpf-registered-target
-// RUN: %clang -target bpf -emit-llvm -S -g %s -o - | FileCheck %s
+// RUN: %clang -target bpf -emit-llvm -S -g -Xclang -disable-llvm-passes %s -o - | FileCheck %s
#define __reloc__ __attribute__((preserve_access_index))
// REQUIRES: bpf-registered-target
-// RUN: %clang -target bpf -emit-llvm -S -g %s -o - | FileCheck %s
+// RUN: %clang -target bpf -emit-llvm -S -g -Xclang -disable-llvm-passes %s -o - | FileCheck %s
#define __reloc__ __attribute__((preserve_access_index))
// REQUIRES: bpf-registered-target
-// RUN: %clang -target bpf -emit-llvm -S -g %s -o - | FileCheck %s
+// RUN: %clang -target bpf -emit-llvm -S -g -Xclang -disable-llvm-passes %s -o - | FileCheck %s
#define __reloc__ __attribute__((preserve_access_index))
// REQUIRES: bpf-registered-target
-// RUN: %clang -target bpf -emit-llvm -S -g %s -o - | FileCheck %s
+// RUN: %clang -target bpf -emit-llvm -S -g -Xclang -disable-llvm-passes %s -o - | FileCheck %s
#define __reloc__ __attribute__((preserve_access_index))
// REQUIRES: bpf-registered-target
-// RUN: %clang -target bpf -emit-llvm -S -g %s -o - | FileCheck %s
+// RUN: %clang -target bpf -emit-llvm -S -g -Xclang -disable-llvm-passes %s -o - | FileCheck %s
#define __reloc__ __attribute__((preserve_access_index))
-// RUN: %clang %s -target bpfeb -x c -emit-llvm -S -g -O2 -o - | FileCheck --check-prefix=CHECK %s
-// RUN: %clang %s -target bpfel -x c -emit-llvm -S -g -O2 -o - | FileCheck --check-prefix=CHECK %s
+// RUN: %clang %s -target bpfeb -x c -emit-llvm -S -g -O2 -Xclang -disable-llvm-passes -o - | FileCheck --check-prefix=CHECK %s
+// RUN: %clang %s -target bpfel -x c -emit-llvm -S -g -O2 -Xclang -disable-llvm-passes -o - | FileCheck --check-prefix=CHECK %s
struct t {
int i:1;
// REQUIRES: bpf-registered-target
-// RUN: %clang -target bpf -emit-llvm -S -g %s -o - | FileCheck %s
+// RUN: %clang -target bpf -emit-llvm -S -g -Xclang -disable-llvm-passes %s -o - | FileCheck %s
unsigned test1(int a) { return __builtin_btf_type_id(a, 0); }
unsigned test2(int a) { return __builtin_btf_type_id(&a, 0); }
// REQUIRES: bpf-registered-target
-// RUN: %clang -target bpf -emit-llvm -S -g %s -o - | FileCheck %s
+// RUN: %clang -target bpf -emit-llvm -S -g -Xclang -disable-llvm-passes %s -o - | FileCheck %s
#pragma clang attribute push (__attribute__((preserve_access_index)), apply_to = record)
typedef struct {
// REQUIRES: bpf-registered-target
-// RUN: %clang -target bpf -emit-llvm -S -g %s -o - | FileCheck %s
+// RUN: %clang -target bpf -emit-llvm -S -g -Xclang -disable-llvm-passes %s -o - | FileCheck %s
#define _(x, y) (__builtin_preserve_field_info((x), (y)))
// REQUIRES: bpf-registered-target
-// RUN: %clang -target bpf -emit-llvm -S -g %s -o - | FileCheck %s
+// RUN: %clang -target bpf -emit-llvm -S -g -Xclang -disable-llvm-passes %s -o - | FileCheck %s
#define _(x, y) (__builtin_preserve_field_info((x), (y)))
// REQUIRES: bpf-registered-target
-// RUN: %clang -target bpf -emit-llvm -S -g %s -o - | FileCheck %s
+// RUN: %clang -target bpf -emit-llvm -S -g -Xclang -disable-llvm-passes %s -o - | FileCheck %s
#define _(x, y) (__builtin_preserve_type_info((x), (y)))
// REQUIRES: bpf-registered-target
-// RUN: %clang -target bpf -emit-llvm -S -g %s -o - | FileCheck %s
+// RUN: %clang -target bpf -emit-llvm -S -g -Xclang -disable-llvm-passes %s -o - | FileCheck %s
#define _(x, y) (__builtin_preserve_enum_value((x), (y)))
def int_bpf_preserve_enum_value : GCCBuiltin<"__builtin_bpf_preserve_enum_value">,
Intrinsic<[llvm_i64_ty], [llvm_i32_ty, llvm_ptr_ty, llvm_i64_ty],
[IntrNoMem]>;
+ def int_bpf_passthrough : GCCBuiltin<"__builtin_bpf_passthrough">,
+ Intrinsic<[llvm_any_ty], [llvm_i32_ty, llvm_any_ty], [IntrNoMem]>;
}
namespace llvm {
class BPFTargetMachine;
-ModulePass *createBPFAbstractMemberAccess(BPFTargetMachine *TM);
-ModulePass *createBPFPreserveDIType();
+ModulePass *createBPFCheckAndAdjustIR();
+FunctionPass *createBPFAbstractMemberAccess(BPFTargetMachine *TM);
+FunctionPass *createBPFPreserveDIType();
FunctionPass *createBPFISelDag(BPFTargetMachine &TM);
FunctionPass *createBPFMISimplifyPatchablePass();
FunctionPass *createBPFMIPeepholePass();
FunctionPass *createBPFMIPreEmitPeepholePass();
FunctionPass *createBPFMIPreEmitCheckingPass();
+void initializeBPFCheckAndAdjustIRPass(PassRegistry&);
+
void initializeBPFAbstractMemberAccessPass(PassRegistry&);
void initializeBPFPreserveDITypePass(PassRegistry&);
void initializeBPFMISimplifyPatchablePass(PassRegistry&);
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
+#include "llvm/IR/IntrinsicsBPF.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/User.h"
namespace llvm {
constexpr StringRef BPFCoreSharedInfo::AmaAttr;
+uint32_t BPFCoreSharedInfo::SeqNum;
+
+Instruction *BPFCoreSharedInfo::insertPassThrough(Module *M, BasicBlock *BB,
+ Instruction *Input,
+ Instruction *Before) {
+ Function *Fn = Intrinsic::getDeclaration(
+ M, Intrinsic::bpf_passthrough, {Input->getType(), Input->getType()});
+ Constant *SeqNumVal = ConstantInt::get(Type::getInt32Ty(BB->getContext()),
+ BPFCoreSharedInfo::SeqNum++);
+
+ auto *NewInst = CallInst::Create(Fn, {SeqNumVal, Input});
+ BB->getInstList().insert(Before->getIterator(), NewInst);
+ return NewInst;
+}
} // namespace llvm
using namespace llvm;
namespace {
-class BPFAbstractMemberAccess final : public ModulePass {
- StringRef getPassName() const override {
- return "BPF Abstract Member Access";
- }
-
- bool runOnModule(Module &M) override;
+class BPFAbstractMemberAccess final : public FunctionPass {
+ bool runOnFunction(Function &F) override;
public:
static char ID;
// Add optional BPFTargetMachine parameter so that BPF backend can add the phase
// with target machine to find out the endianness. The default constructor (without
// parameters) is used by the pass manager for managing purposes.
- BPFAbstractMemberAccess(BPFTargetMachine *TM = nullptr) : ModulePass(ID), TM(TM) {}
+ BPFAbstractMemberAccess(BPFTargetMachine *TM = nullptr)
+ : FunctionPass(ID), TM(TM) {}
struct CallInfo {
uint32_t Kind;
};
const DataLayout *DL = nullptr;
+ Module *M = nullptr;
std::map<std::string, GlobalVariable *> GEPGlobals;
// A map to link preserve_*_access_index instrinsic calls.
// intrinsics.
std::map<CallInst *, CallInfo> BaseAICalls;
- bool doTransformation(Module &M);
+ bool doTransformation(Function &F);
void traceAICall(CallInst *Call, CallInfo &ParentInfo);
void traceBitCast(BitCastInst *BitCast, CallInst *Parent,
CallInfo &ParentInfo);
void traceGEP(GetElementPtrInst *GEP, CallInst *Parent,
CallInfo &ParentInfo);
- void collectAICallChains(Module &M, Function &F);
+ void collectAICallChains(Function &F);
bool IsPreserveDIAccessIndexCall(const CallInst *Call, CallInfo &Cinfo);
bool IsValidAIChain(const MDNode *ParentMeta, uint32_t ParentAI,
const MDNode *ChildMeta);
- bool removePreserveAccessIndexIntrinsic(Module &M);
+ bool removePreserveAccessIndexIntrinsic(Function &F);
void replaceWithGEP(std::vector<CallInst *> &CallList,
uint32_t NumOfZerosIndex, uint32_t DIIndex);
bool HasPreserveFieldInfoCall(CallInfoStack &CallStack);
MDNode *computeAccessKey(CallInst *Call, CallInfo &CInfo,
std::string &AccessKey, bool &IsInt32Ret);
uint64_t getConstant(const Value *IndexValue);
- bool transformGEPChain(Module &M, CallInst *Call, CallInfo &CInfo);
+ bool transformGEPChain(CallInst *Call, CallInfo &CInfo);
};
} // End anonymous namespace
char BPFAbstractMemberAccess::ID = 0;
INITIALIZE_PASS(BPFAbstractMemberAccess, DEBUG_TYPE,
- "abstracting struct/union member accessees", false, false)
+ "BPF Abstract Member Access", false, false)
-ModulePass *llvm::createBPFAbstractMemberAccess(BPFTargetMachine *TM) {
+FunctionPass *llvm::createBPFAbstractMemberAccess(BPFTargetMachine *TM) {
return new BPFAbstractMemberAccess(TM);
}
-bool BPFAbstractMemberAccess::runOnModule(Module &M) {
+bool BPFAbstractMemberAccess::runOnFunction(Function &F) {
LLVM_DEBUG(dbgs() << "********** Abstract Member Accesses **********\n");
+ M = F.getParent();
+ if (!M)
+ return false;
+
// Bail out if no debug info.
- if (M.debug_compile_units().empty())
+ if (M->debug_compile_units().empty())
return false;
- DL = &M.getDataLayout();
- return doTransformation(M);
+ DL = &M->getDataLayout();
+ return doTransformation(F);
}
static bool SkipDIDerivedTag(unsigned Tag, bool skipTypedef) {
}
}
-bool BPFAbstractMemberAccess::removePreserveAccessIndexIntrinsic(Module &M) {
+bool BPFAbstractMemberAccess::removePreserveAccessIndexIntrinsic(Function &F) {
std::vector<CallInst *> PreserveArrayIndexCalls;
std::vector<CallInst *> PreserveUnionIndexCalls;
std::vector<CallInst *> PreserveStructIndexCalls;
bool Found = false;
- for (Function &F : M)
- for (auto &BB : F)
- for (auto &I : BB) {
- auto *Call = dyn_cast<CallInst>(&I);
- CallInfo CInfo;
- if (!IsPreserveDIAccessIndexCall(Call, CInfo))
- continue;
-
- Found = true;
- if (CInfo.Kind == BPFPreserveArrayAI)
- PreserveArrayIndexCalls.push_back(Call);
- else if (CInfo.Kind == BPFPreserveUnionAI)
- PreserveUnionIndexCalls.push_back(Call);
- else
- PreserveStructIndexCalls.push_back(Call);
- }
+ for (auto &BB : F)
+ for (auto &I : BB) {
+ auto *Call = dyn_cast<CallInst>(&I);
+ CallInfo CInfo;
+ if (!IsPreserveDIAccessIndexCall(Call, CInfo))
+ continue;
+
+ Found = true;
+ if (CInfo.Kind == BPFPreserveArrayAI)
+ PreserveArrayIndexCalls.push_back(Call);
+ else if (CInfo.Kind == BPFPreserveUnionAI)
+ PreserveUnionIndexCalls.push_back(Call);
+ else
+ PreserveStructIndexCalls.push_back(Call);
+ }
// do the following transformation:
// . addr = preserve_array_access_index(base, dimension, index)
}
}
-void BPFAbstractMemberAccess::collectAICallChains(Module &M, Function &F) {
+void BPFAbstractMemberAccess::collectAICallChains(Function &F) {
AIChain.clear();
BaseAICalls.clear();
/// Call/Kind is the base preserve_*_access_index() call. Attempts to do
/// transformation to a chain of relocable GEPs.
-bool BPFAbstractMemberAccess::transformGEPChain(Module &M, CallInst *Call,
+bool BPFAbstractMemberAccess::transformGEPChain(CallInst *Call,
CallInfo &CInfo) {
std::string AccessKey;
MDNode *TypeMeta;
else
VarType = Type::getInt64Ty(BB->getContext()); // 64bit ptr or enum value
- GV = new GlobalVariable(M, VarType, false, GlobalVariable::ExternalLinkage,
+ GV = new GlobalVariable(*M, VarType, false, GlobalVariable::ExternalLinkage,
NULL, AccessKey);
GV->addAttribute(BPFCoreSharedInfo::AmaAttr);
GV->setMetadata(LLVMContext::MD_preserve_access_index, TypeMeta);
LDInst = new LoadInst(Type::getInt32Ty(BB->getContext()), GV, "", Call);
else
LDInst = new LoadInst(Type::getInt64Ty(BB->getContext()), GV, "", Call);
- Call->replaceAllUsesWith(LDInst);
+
+ Instruction *PassThroughInst =
+ BPFCoreSharedInfo::insertPassThrough(M, BB, LDInst, Call);
+ Call->replaceAllUsesWith(PassThroughInst);
Call->eraseFromParent();
return true;
}
// For any original GEP Call and Base %2 like
// %4 = bitcast %struct.net_device** %dev1 to i64*
// it is transformed to:
- // %6 = load sk_buff:50:$0:0:0:2:0
+ // %6 = load llvm.sk_buff:0:50$0:0:0:2:0
// %7 = bitcast %struct.sk_buff* %2 to i8*
// %8 = getelementptr i8, i8* %7, %6
// %9 = bitcast i8* %8 to i64*
auto *BCInst2 = new BitCastInst(GEP, Call->getType());
BB->getInstList().insert(Call->getIterator(), BCInst2);
- Call->replaceAllUsesWith(BCInst2);
+ // For the following code,
+ // Block0:
+ // ...
+ // if (...) goto Block1 else ...
+ // Block1:
+ // %6 = load llvm.sk_buff:0:50$0:0:0:2:0
+ // %7 = bitcast %struct.sk_buff* %2 to i8*
+ // %8 = getelementptr i8, i8* %7, %6
+ // ...
+ // goto CommonExit
+ // Block2:
+ // ...
+ // if (...) goto Block3 else ...
+ // Block3:
+ // %6 = load llvm.bpf_map:0:40$0:0:0:2:0
+ // %7 = bitcast %struct.sk_buff* %2 to i8*
+ // %8 = getelementptr i8, i8* %7, %6
+ // ...
+ // goto CommonExit
+ // CommonExit
+ // SimplifyCFG may generate:
+ // Block0:
+ // ...
+ // if (...) goto Block_Common else ...
+ // Block2:
+ // ...
+ // if (...) goto Block_Common else ...
+ // Block_Common:
+ // PHI = [llvm.sk_buff:0:50$0:0:0:2:0, llvm.bpf_map:0:40$0:0:0:2:0]
+ // %6 = load PHI
+ // %7 = bitcast %struct.sk_buff* %2 to i8*
+ // %8 = getelementptr i8, i8* %7, %6
+ // ...
+ // goto CommonExit
+ // For the above code, we cannot perform proper relocation since
+ // "load PHI" has two possible relocations.
+ //
+ // To prevent above tail merging, we use __builtin_bpf_passthrough()
+ // where one of its parameters is a seq_num. Since two
+ // __builtin_bpf_passthrough() funcs will always have different seq_num,
+ // tail merging cannot happen. The __builtin_bpf_passthrough() will be
+ // removed in the beginning of Target IR passes.
+ //
+ // This approach is also used in other places when global var
+ // representing a relocation is used.
+ Instruction *PassThroughInst =
+ BPFCoreSharedInfo::insertPassThrough(M, BB, BCInst2, Call);
+ Call->replaceAllUsesWith(PassThroughInst);
Call->eraseFromParent();
return true;
}
-bool BPFAbstractMemberAccess::doTransformation(Module &M) {
+bool BPFAbstractMemberAccess::doTransformation(Function &F) {
bool Transformed = false;
- for (Function &F : M) {
- // Collect PreserveDIAccessIndex Intrinsic call chains.
- // The call chains will be used to generate the access
- // patterns similar to GEP.
- collectAICallChains(M, F);
+ // Collect PreserveDIAccessIndex Intrinsic call chains.
+ // The call chains will be used to generate the access
+ // patterns similar to GEP.
+ collectAICallChains(F);
- for (auto &C : BaseAICalls)
- Transformed = transformGEPChain(M, C.first, C.second) || Transformed;
- }
+ for (auto &C : BaseAICalls)
+ Transformed = transformGEPChain(C.first, C.second) || Transformed;
- return removePreserveAccessIndexIntrinsic(M) || Transformed;
+ return removePreserveAccessIndexIntrinsic(F) || Transformed;
}
namespace llvm {
+class BasicBlock;
+class Instruction;
+class Module;
+
class BPFCoreSharedInfo {
public:
enum PatchableRelocKind : uint32_t {
static constexpr StringRef AmaAttr = "btf_ama";
/// The attribute attached to globals representing a type id
static constexpr StringRef TypeIdAttr = "btf_type_id";
+
+ /// llvm.bpf.passthrough builtin seq number
+ static uint32_t SeqNum;
+
+ /// Insert a bpf passthrough builtin function.
+ static Instruction *insertPassThrough(Module *M, BasicBlock *BB,
+ Instruction *Input,
+ Instruction *Before);
};
} // namespace llvm
--- /dev/null
+//===------------ BPFCheckAndAdjustIR.cpp - Check and Adjust IR -----------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Check IR and adjust IR for verifier friendly codes.
+// The following are done for IR checking:
+// - no relocation globals in PHI node.
+// The following are done for IR adjustment:
+// - remove __builtin_bpf_passthrough builtins. Target independent IR
+// optimizations are done and those builtins can be removed.
+//
+//===----------------------------------------------------------------------===//
+
+#include "BPF.h"
+#include "BPFCORE.h"
+#include "BPFTargetMachine.h"
+#include "llvm/IR/DebugInfoMetadata.h"
+#include "llvm/IR/GlobalVariable.h"
+#include "llvm/IR/Instruction.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/Type.h"
+#include "llvm/IR/User.h"
+#include "llvm/IR/Value.h"
+#include "llvm/Pass.h"
+#include "llvm/Transforms/Utils/BasicBlockUtils.h"
+
+#define DEBUG_TYPE "bpf-check-and-opt-ir"
+
+using namespace llvm;
+
+namespace {
+
+class BPFCheckAndAdjustIR final : public ModulePass {
+ bool runOnModule(Module &F) override;
+
+public:
+ static char ID;
+ BPFCheckAndAdjustIR() : ModulePass(ID) {}
+
+private:
+ void checkIR(Module &M);
+ bool adjustIR(Module &M);
+ bool removePassThroughBuiltin(Module &M);
+};
+} // End anonymous namespace
+
+char BPFCheckAndAdjustIR::ID = 0;
+INITIALIZE_PASS(BPFCheckAndAdjustIR, DEBUG_TYPE, "BPF Check And Adjust IR",
+ false, false)
+
+ModulePass *llvm::createBPFCheckAndAdjustIR() {
+ return new BPFCheckAndAdjustIR();
+}
+
+void BPFCheckAndAdjustIR::checkIR(Module &M) {
+ // Ensure relocation global won't appear in PHI node
+ // This may happen if the compiler generated the following code:
+ // B1:
+ // g1 = @llvm.skb_buff:0:1...
+ // ...
+ // goto B_COMMON
+ // B2:
+ // g2 = @llvm.skb_buff:0:2...
+ // ...
+ // goto B_COMMON
+ // B_COMMON:
+ // g = PHI(g1, g2)
+ // x = load g
+ // ...
+ // If anything likes the above "g = PHI(g1, g2)", issue a fatal error.
+ for (Function &F : M)
+ for (auto &BB : F)
+ for (auto &I : BB) {
+ PHINode *PN = dyn_cast<PHINode>(&I);
+ if (!PN || PN->use_empty())
+ continue;
+ for (int i = 0, e = PN->getNumIncomingValues(); i < e; ++i) {
+ auto *GV = dyn_cast<GlobalVariable>(PN->getIncomingValue(i));
+ if (!GV)
+ continue;
+ if (GV->hasAttribute(BPFCoreSharedInfo::AmaAttr) ||
+ GV->hasAttribute(BPFCoreSharedInfo::TypeIdAttr))
+ report_fatal_error("relocation global in PHI node");
+ }
+ }
+}
+
+bool BPFCheckAndAdjustIR::removePassThroughBuiltin(Module &M) {
+ // Remove __builtin_bpf_passthrough()'s which are used to prevent
+ // certain IR optimizations. Now major IR optimizations are done,
+ // remove them.
+ bool Changed = false;
+ CallInst *ToBeDeleted = nullptr;
+ for (Function &F : M)
+ for (auto &BB : F)
+ for (auto &I : BB) {
+ if (ToBeDeleted) {
+ ToBeDeleted->eraseFromParent();
+ ToBeDeleted = nullptr;
+ }
+
+ auto *Call = dyn_cast<CallInst>(&I);
+ if (!Call)
+ continue;
+ auto *GV = dyn_cast<GlobalValue>(Call->getCalledOperand());
+ if (!GV)
+ continue;
+ if (!GV->getName().startswith("llvm.bpf.passthrough"))
+ continue;
+ Changed = true;
+ Value *Arg = Call->getArgOperand(1);
+ Call->replaceAllUsesWith(Arg);
+ ToBeDeleted = Call;
+ }
+ return Changed;
+}
+
+bool BPFCheckAndAdjustIR::adjustIR(Module &M) {
+ return removePassThroughBuiltin(M);
+}
+
+bool BPFCheckAndAdjustIR::runOnModule(Module &M) {
+ checkIR(M);
+ return adjustIR(M);
+}
namespace {
-class BPFPreserveDIType final : public ModulePass {
- StringRef getPassName() const override {
- return "BPF Preserve DebugInfo Type";
- }
-
- bool runOnModule(Module &M) override;
+class BPFPreserveDIType final : public FunctionPass {
+ bool runOnFunction(Function &F) override;
public:
static char ID;
- BPFPreserveDIType() : ModulePass(ID) {}
+ BPFPreserveDIType() : FunctionPass(ID) {}
private:
- bool doTransformation(Module &M);
+ Module *M = nullptr;
+
+ bool doTransformation(Function &F);
};
} // End anonymous namespace
char BPFPreserveDIType::ID = 0;
-INITIALIZE_PASS(BPFPreserveDIType, DEBUG_TYPE, "preserve debuginfo type", false,
- false)
+INITIALIZE_PASS(BPFPreserveDIType, DEBUG_TYPE, "BPF Preserve Debuginfo Type",
+ false, false)
-ModulePass *llvm::createBPFPreserveDIType() { return new BPFPreserveDIType(); }
+FunctionPass *llvm::createBPFPreserveDIType() { return new BPFPreserveDIType(); }
-bool BPFPreserveDIType::runOnModule(Module &M) {
+bool BPFPreserveDIType::runOnFunction(Function &F) {
LLVM_DEBUG(dbgs() << "********** preserve debuginfo type **********\n");
+ M = F.getParent();
+ if (!M)
+ return false;
+
// Bail out if no debug info.
- if (M.debug_compile_units().empty())
+ if (M->debug_compile_units().empty())
return false;
- return doTransformation(M);
+ return doTransformation(F);
}
-bool BPFPreserveDIType::doTransformation(Module &M) {
+bool BPFPreserveDIType::doTransformation(Function &F) {
std::vector<CallInst *> PreserveDITypeCalls;
- for (auto &F : M) {
- for (auto &BB : F) {
- for (auto &I : BB) {
- auto *Call = dyn_cast<CallInst>(&I);
- if (!Call)
- continue;
-
- const auto *GV = dyn_cast<GlobalValue>(Call->getCalledOperand());
- if (!GV)
- continue;
-
- if (GV->getName().startswith("llvm.bpf.btf.type.id")) {
- if (!Call->getMetadata(LLVMContext::MD_preserve_access_index))
- report_fatal_error(
- "Missing metadata for llvm.bpf.btf.type.id intrinsic");
- PreserveDITypeCalls.push_back(Call);
- }
+ for (auto &BB : F) {
+ for (auto &I : BB) {
+ auto *Call = dyn_cast<CallInst>(&I);
+ if (!Call)
+ continue;
+
+ const auto *GV = dyn_cast<GlobalValue>(Call->getCalledOperand());
+ if (!GV)
+ continue;
+
+ if (GV->getName().startswith("llvm.bpf.btf.type.id")) {
+ if (!Call->getMetadata(LLVMContext::MD_preserve_access_index))
+ report_fatal_error(
+ "Missing metadata for llvm.bpf.btf.type.id intrinsic");
+ PreserveDITypeCalls.push_back(Call);
}
}
}
IntegerType *VarType = Type::getInt32Ty(BB->getContext());
std::string GVName = BaseName + std::to_string(Count) + "$" +
std::to_string(Reloc);
- GlobalVariable *GV =
- new GlobalVariable(M, VarType, false, GlobalVariable::ExternalLinkage,
- NULL, GVName);
+ GlobalVariable *GV = new GlobalVariable(
+ *M, VarType, false, GlobalVariable::ExternalLinkage, NULL, GVName);
GV->addAttribute(BPFCoreSharedInfo::TypeIdAttr);
GV->setMetadata(LLVMContext::MD_preserve_access_index, MD);
// Load the global variable which represents the type info.
auto *LDInst = new LoadInst(Type::getInt32Ty(BB->getContext()), GV, "",
Call);
- Call->replaceAllUsesWith(LDInst);
+ Instruction *PassThroughInst =
+ BPFCoreSharedInfo::insertPassThrough(M, BB, LDInst, Call);
+ Call->replaceAllUsesWith(PassThroughInst);
Call->eraseFromParent();
Count++;
}
PassRegistry &PR = *PassRegistry::getPassRegistry();
initializeBPFAbstractMemberAccessPass(PR);
initializeBPFPreserveDITypePass(PR);
+ initializeBPFCheckAndAdjustIRPass(PR);
initializeBPFMIPeepholePass(PR);
initializeBPFMIPeepholeTruncElimPass(PR);
}
}
void BPFTargetMachine::adjustPassManager(PassManagerBuilder &Builder) {
+ Builder.addExtension(
+ PassManagerBuilder::EP_EarlyAsPossible,
+ [&](const PassManagerBuilder &, legacy::PassManagerBase &PM) {
+ PM.add(createBPFAbstractMemberAccess(this));
+ PM.add(createBPFPreserveDIType());
+ });
+
Builder.addExtension(
PassManagerBuilder::EP_Peephole,
[&](const PassManagerBuilder &, legacy::PassManagerBase &PM) {
}
void BPFPassConfig::addIRPasses() {
- addPass(createBPFAbstractMemberAccess(&getBPFTargetMachine()));
- addPass(createBPFPreserveDIType());
-
+ addPass(createBPFCheckAndAdjustIR());
TargetPassConfig::addIRPasses();
}
add_llvm_target(BPFCodeGen
BPFAbstractMemberAccess.cpp
BPFAsmPrinter.cpp
+ BPFCheckAndAdjustIR.cpp
BPFFrameLowering.cpp
BPFInstrInfo.cpp
BPFISelDAGToDAG.cpp
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
;
; Source code:
; static int (*bpf_log)(unsigned tid, void *data, int data_size) = (void *)999;
; bpf_log(__builtin_btf_type_id(tmp__abc.f1[3], 1), &tmp__abc, sizeof(tmp__abc));
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
@tmp__abc = dso_local global { <{ i8, i8, [98 x i8] }>, i32 } { <{ i8, i8, [98 x i8] }> <{ i8 1, i8 3, [98 x i8] zeroinitializer }>, i32 0 }, align 4, !dbg !0
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
; Source code:
; struct b { int d; int e; } c;
; int f() {
; return __builtin_preserve_field_info(c.e, 0);
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%struct.b = type { i32, i32 }
--- /dev/null
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-EB,CHECK-ALU64 %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-EB,CHECK-ALU32 %s
+; Source code:
+; struct s {
+; unsigned long long f1;
+; unsigned f2;
+; unsigned f3;
+; unsigned f4;
+; unsigned char f5;
+; unsigned bf1:5,
+; bf2:1;
+; };
+; enum {FIELD_TYPE_OFFSET = 0, FIELD_TYPE_SIZE = 1, FIELD_TYPE_LSHIFT_U64 = 4,};
+; int test(struct s *arg) {
+; return __builtin_preserve_field_info(arg->bf2, FIELD_TYPE_OFFSET) +
+; __builtin_preserve_field_info(arg->bf2, FIELD_TYPE_SIZE) +
+; __builtin_preserve_field_info(arg->bf2, FIELD_TYPE_LSHIFT_U64);
+; }
+; Compilation flag:
+; clang -target bpfeb -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpfeb"
+
+%struct.s = type { i64, i32, i32, i32, i8, i8 }
+
+; Function Attrs: nounwind readnone
+define dso_local i32 @test(%struct.s* %arg) local_unnamed_addr #0 !dbg !13 {
+entry:
+ call void @llvm.dbg.value(metadata %struct.s* %arg, metadata !30, metadata !DIExpression()), !dbg !31
+ %0 = tail call i8* @llvm.preserve.struct.access.index.p0i8.p0s_struct.ss(%struct.s* %arg, i32 5, i32 6), !dbg !32, !llvm.preserve.access.index !18
+ %1 = tail call i32 @llvm.bpf.preserve.field.info.p0i8(i8* %0, i64 0), !dbg !33
+ %2 = tail call i32 @llvm.bpf.preserve.field.info.p0i8(i8* %0, i64 1), !dbg !34
+ %add = add i32 %2, %1, !dbg !35
+ %3 = tail call i32 @llvm.bpf.preserve.field.info.p0i8(i8* %0, i64 4), !dbg !36
+ %add1 = add i32 %add, %3, !dbg !37
+ ret i32 %add1, !dbg !38
+}
+
+; CHECK: r1 = 20
+; CHECK: r0 = 4
+; CHECK-ALU64: r0 += r1
+; CHECK-ALU32: w0 += w1
+; CHECK-EB: r1 = 45
+; CHECK-ALU64: r0 += r1
+; CHECK-ALU32: w0 += w1
+; CHECK: exit
+
+; CHECK: .long 1 # BTF_KIND_STRUCT(id = 2)
+
+; CHECK: .byte 115 # string offset=1
+; CHECK: .ascii ".text" # string offset=89
+; CHECK: .ascii "0:6" # string offset=95
+
+; CHECK: .long 16 # FieldReloc
+; CHECK-NEXT: .long 89 # Field reloc section string offset=89
+; CHECK-NEXT: .long 3
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
+; CHECK-NEXT: .long 2
+; CHECK-NEXT: .long 95
+; CHECK-NEXT: .long 0
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
+; CHECK-NEXT: .long 2
+; CHECK-NEXT: .long 95
+; CHECK-NEXT: .long 1
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
+; CHECK-NEXT: .long 2
+; CHECK-NEXT: .long 95
+; CHECK-NEXT: .long 4
+
+; Function Attrs: nounwind readnone
+declare i8* @llvm.preserve.struct.access.index.p0i8.p0s_struct.ss(%struct.s*, i32, i32) #1
+
+; Function Attrs: nounwind readnone
+declare i32 @llvm.bpf.preserve.field.info.p0i8(i8*, i64) #1
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.value(metadata, metadata, metadata) #2
+
+attributes #0 = { nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind readnone }
+attributes #2 = { nounwind readnone speculatable }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!9, !10, !11}
+!llvm.ident = !{!12}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 (https://github.com/llvm/llvm-project.git bc6913e314806882e2b537b5b03996800078d2ad)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
+!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/core")
+!2 = !{!3}
+!3 = !DICompositeType(tag: DW_TAG_enumeration_type, file: !1, line: 10, baseType: !4, size: 32, elements: !5)
+!4 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned)
+!5 = !{!6, !7, !8}
+!6 = !DIEnumerator(name: "FIELD_TYPE_OFFSET", value: 0, isUnsigned: true)
+!7 = !DIEnumerator(name: "FIELD_TYPE_SIZE", value: 1, isUnsigned: true)
+!8 = !DIEnumerator(name: "FIELD_TYPE_LSHIFT_U64", value: 4, isUnsigned: true)
+!9 = !{i32 2, !"Dwarf Version", i32 4}
+!10 = !{i32 2, !"Debug Info Version", i32 3}
+!11 = !{i32 1, !"wchar_size", i32 4}
+!12 = !{!"clang version 10.0.0 (https://github.com/llvm/llvm-project.git bc6913e314806882e2b537b5b03996800078d2ad)"}
+!13 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 11, type: !14, scopeLine: 11, flags: DIFlagPrototyped, isDefinition: true, isOptimized: true, unit: !0, retainedNodes: !29)
+!14 = !DISubroutineType(types: !15)
+!15 = !{!16, !17}
+!16 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!17 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !18, size: 64)
+!18 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s", file: !1, line: 1, size: 192, elements: !19)
+!19 = !{!20, !22, !23, !24, !25, !27, !28}
+!20 = !DIDerivedType(tag: DW_TAG_member, name: "f1", scope: !18, file: !1, line: 2, baseType: !21, size: 64)
+!21 = !DIBasicType(name: "long long unsigned int", size: 64, encoding: DW_ATE_unsigned)
+!22 = !DIDerivedType(tag: DW_TAG_member, name: "f2", scope: !18, file: !1, line: 3, baseType: !4, size: 32, offset: 64)
+!23 = !DIDerivedType(tag: DW_TAG_member, name: "f3", scope: !18, file: !1, line: 4, baseType: !4, size: 32, offset: 96)
+!24 = !DIDerivedType(tag: DW_TAG_member, name: "f4", scope: !18, file: !1, line: 5, baseType: !4, size: 32, offset: 128)
+!25 = !DIDerivedType(tag: DW_TAG_member, name: "f5", scope: !18, file: !1, line: 6, baseType: !26, size: 8, offset: 160)
+!26 = !DIBasicType(name: "unsigned char", size: 8, encoding: DW_ATE_unsigned_char)
+!27 = !DIDerivedType(tag: DW_TAG_member, name: "bf1", scope: !18, file: !1, line: 7, baseType: !4, size: 5, offset: 168, flags: DIFlagBitField, extraData: i64 168)
+!28 = !DIDerivedType(tag: DW_TAG_member, name: "bf2", scope: !18, file: !1, line: 8, baseType: !4, size: 1, offset: 173, flags: DIFlagBitField, extraData: i64 168)
+!29 = !{!30}
+!30 = !DILocalVariable(name: "arg", arg: 1, scope: !13, file: !1, line: 11, type: !17)
+!31 = !DILocation(line: 0, scope: !13)
+!32 = !DILocation(line: 12, column: 45, scope: !13)
+!33 = !DILocation(line: 12, column: 10, scope: !13)
+!34 = !DILocation(line: 13, column: 10, scope: !13)
+!35 = !DILocation(line: 12, column: 69, scope: !13)
+!36 = !DILocation(line: 14, column: 10, scope: !13)
+!37 = !DILocation(line: 13, column: 67, scope: !13)
+!38 = !DILocation(line: 12, column: 3, scope: !13)
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-EL,CHECK-ALU64 %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-EB,CHECK-ALU64 %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-EL,CHECK-ALU32 %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-EB,CHECK-ALU32 %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-EL,CHECK-ALU64 %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-EL,CHECK-ALU32 %s
; Source code:
; struct s {
; unsigned long long f1;
; __builtin_preserve_field_info(arg->bf2, FIELD_TYPE_LSHIFT_U64);
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%struct.s = type { i64, i32, i32, i32, i8, i8 }
ret i32 %add1, !dbg !38
}
-; CHECK: r1 = 16
-; CHECK: r0 = 8
+; CHECK: r1 = 20
+; CHECK: r0 = 4
; CHECK-ALU64: r0 += r1
; CHECK-ALU32: w0 += w1
-; CHECK-EL: r1 = 18
-; CHECK-EB: r1 = 45
+; CHECK-EL: r1 = 50
; CHECK-ALU64: r0 += r1
; CHECK-ALU32: w0 += w1
; CHECK: exit
--- /dev/null
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-EB,CHECK-ALU64 %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-EB,CHECK-ALU32 %s
+; Source code:
+; struct s {
+; char f1;
+; char bf1:6,
+; bf2:2,
+; bf3:5,
+; bf4:3;
+; };
+; enum {FIELD_TYPE_OFFSET = 0, FIELD_TYPE_SIZE = 1, FIELD_TYPE_LSHIFT_U64 = 4,};
+; int test(struct s *arg) {
+; return __builtin_preserve_field_info(arg->bf4, FIELD_TYPE_OFFSET) +
+; __builtin_preserve_field_info(arg->bf4, FIELD_TYPE_SIZE) +
+; __builtin_preserve_field_info(arg->bf4, FIELD_TYPE_LSHIFT_U64);
+; }
+; For this case, the IR type has the same starting storage offset for fields
+; bf1, bf1, bf3 and bf4 and the ABI alignment is 1 byte. So for bf4 access,
+; the starting offset has to be at the beginning of field bf3.
+; Compilation flag:
+; clang -target bpfeb -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpfeb"
+
+%struct.s = type <{ i8, i16 }>
+
+; Function Attrs: nounwind readnone
+define dso_local i32 @test(%struct.s* %arg) local_unnamed_addr #0 !dbg !13 {
+entry:
+ call void @llvm.dbg.value(metadata %struct.s* %arg, metadata !27, metadata !DIExpression()), !dbg !28
+ %0 = tail call i16* @llvm.preserve.struct.access.index.p0i16.p0s_struct.ss(%struct.s* %arg, i32 1, i32 4), !dbg !29, !llvm.preserve.access.index !18
+ %1 = tail call i32 @llvm.bpf.preserve.field.info.p0i16(i16* %0, i64 0), !dbg !30
+ %2 = tail call i32 @llvm.bpf.preserve.field.info.p0i16(i16* %0, i64 1), !dbg !31
+ %add = add i32 %2, %1, !dbg !32
+ %3 = tail call i32 @llvm.bpf.preserve.field.info.p0i16(i16* %0, i64 4), !dbg !33
+ %add1 = add i32 %add, %3, !dbg !34
+ ret i32 %add1, !dbg !35
+}
+
+; CHECK: r1 = 2
+; CHECK: r0 = 1
+; CHECK-ALU64: r0 += r1
+; CHECK-ALU32: w0 += w1
+; CHECK-EB: r1 = 61
+; CHECK-ALU64: r0 += r1
+; CHECK-ALU32: w0 += w1
+; CHECK: exit
+
+; CHECK: .long 1 # BTF_KIND_STRUCT(id = 2)
+
+; CHECK: .byte 115 # string offset=1
+; CHECK: .ascii ".text" # string offset=40
+; CHECK: .ascii "0:4" # string offset=46
+
+; CHECK: .long 16 # FieldReloc
+; CHECK-NEXT: .long 40 # Field reloc section string offset=40
+; CHECK-NEXT: .long 3
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
+; CHECK-NEXT: .long 2
+; CHECK-NEXT: .long 46
+; CHECK-NEXT: .long 0
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
+; CHECK-NEXT: .long 2
+; CHECK-NEXT: .long 46
+; CHECK-NEXT: .long 1
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
+; CHECK-NEXT: .long 2
+; CHECK-NEXT: .long 46
+; CHECK-NEXT: .long 4
+
+; Function Attrs: nounwind readnone
+declare i16* @llvm.preserve.struct.access.index.p0i16.p0s_struct.ss(%struct.s*, i32, i32) #1
+
+; Function Attrs: nounwind readnone
+declare i32 @llvm.bpf.preserve.field.info.p0i16(i16*, i64) #1
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.value(metadata, metadata, metadata) #2
+
+attributes #0 = { nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind readnone }
+attributes #2 = { nounwind readnone speculatable }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!9, !10, !11}
+!llvm.ident = !{!12}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 (https://github.com/llvm/llvm-project.git 630ca91834ecc06349cb3b4bd2982c1b85b5ad96)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
+!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/core")
+!2 = !{!3}
+!3 = !DICompositeType(tag: DW_TAG_enumeration_type, file: !1, line: 8, baseType: !4, size: 32, elements: !5)
+!4 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned)
+!5 = !{!6, !7, !8}
+!6 = !DIEnumerator(name: "FIELD_TYPE_OFFSET", value: 0, isUnsigned: true)
+!7 = !DIEnumerator(name: "FIELD_TYPE_SIZE", value: 1, isUnsigned: true)
+!8 = !DIEnumerator(name: "FIELD_TYPE_LSHIFT_U64", value: 4, isUnsigned: true)
+!9 = !{i32 2, !"Dwarf Version", i32 4}
+!10 = !{i32 2, !"Debug Info Version", i32 3}
+!11 = !{i32 1, !"wchar_size", i32 4}
+!12 = !{!"clang version 10.0.0 (https://github.com/llvm/llvm-project.git 630ca91834ecc06349cb3b4bd2982c1b85b5ad96)"}
+!13 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 9, type: !14, scopeLine: 9, flags: DIFlagPrototyped, isDefinition: true, isOptimized: true, unit: !0, retainedNodes: !26)
+!14 = !DISubroutineType(types: !15)
+!15 = !{!16, !17}
+!16 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!17 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !18, size: 64)
+!18 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s", file: !1, line: 1, size: 24, elements: !19)
+!19 = !{!20, !22, !23, !24, !25}
+!20 = !DIDerivedType(tag: DW_TAG_member, name: "f1", scope: !18, file: !1, line: 2, baseType: !21, size: 8)
+!21 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
+!22 = !DIDerivedType(tag: DW_TAG_member, name: "bf1", scope: !18, file: !1, line: 3, baseType: !21, size: 6, offset: 8, flags: DIFlagBitField, extraData: i64 8)
+!23 = !DIDerivedType(tag: DW_TAG_member, name: "bf2", scope: !18, file: !1, line: 4, baseType: !21, size: 2, offset: 14, flags: DIFlagBitField, extraData: i64 8)
+!24 = !DIDerivedType(tag: DW_TAG_member, name: "bf3", scope: !18, file: !1, line: 5, baseType: !21, size: 5, offset: 16, flags: DIFlagBitField, extraData: i64 8)
+!25 = !DIDerivedType(tag: DW_TAG_member, name: "bf4", scope: !18, file: !1, line: 6, baseType: !21, size: 3, offset: 21, flags: DIFlagBitField, extraData: i64 8)
+!26 = !{!27}
+!27 = !DILocalVariable(name: "arg", arg: 1, scope: !13, file: !1, line: 9, type: !17)
+!28 = !DILocation(line: 0, scope: !13)
+!29 = !DILocation(line: 10, column: 45, scope: !13)
+!30 = !DILocation(line: 10, column: 10, scope: !13)
+!31 = !DILocation(line: 11, column: 10, scope: !13)
+!32 = !DILocation(line: 10, column: 69, scope: !13)
+!33 = !DILocation(line: 12, column: 10, scope: !13)
+!34 = !DILocation(line: 11, column: 67, scope: !13)
+!35 = !DILocation(line: 10, column: 3, scope: !13)
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-EL,CHECK-ALU64 %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-EB,CHECK-ALU64 %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-EL,CHECK-ALU32 %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-EB,CHECK-ALU32 %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-EL,CHECK-ALU64 %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-EL,CHECK-ALU32 %s
; Source code:
; struct s {
; char f1;
; bf1, bf1, bf3 and bf4 and the ABI alignment is 1 byte. So for bf4 access,
; the starting offset has to be at the beginning of field bf3.
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%struct.s = type <{ i8, i16 }>
; CHECK-ALU64: r0 += r1
; CHECK-ALU32: w0 += w1
; CHECK-EL: r1 = 56
-; CHECK-EB: r1 = 61
; CHECK-ALU64: r0 += r1
; CHECK-ALU32: w0 += w1
; CHECK: exit
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
; Source:
; enum { FIELD_EXISTENCE = 2, };
; struct s1 { int a1; };
; return __builtin_preserve_field_info(v[0], FIELD_EXISTENCE);
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%struct.s1 = type { i32 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck %s
;
; Source code:
; #define _(x) (__builtin_preserve_access_index(x))
; int get_value(const void *addr);
; int test(struct s *arg) { return get_value(_(&arg[2].b)); }
; Compiler flag to generate IR:
-; clang -target bpf -S -O2 -g -emit-llvm test.c
+; clang -target bpf -S -O2 -g -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%struct.s = type { i32, i32 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
; Source code:
; typedef struct s1 { int a1:7; int a2:4; int a3:5; int a4:16;} __s1;
; union u1 { int b1; __s1 b2; };
; return r1 + r2 + r3 + r4;
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%union.u1 = type { i32 }
%struct.s1 = type { i32 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
; Source code:
; typedef struct s1 { int a1; char a2; } __s1;
; union u1 { int b1; __s1 b2; };
; return r1 + r2 + r3;
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%union.u1 = type { %struct.s1 }
%struct.s1 = type { i32, i8 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
; Source code:
; typedef struct s1 { int a1[10][10]; } __s1;
; union u1 { int b1; __s1 b2; };
; return r1 + r2;
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%union.u1 = type { %struct.s1 }
%struct.s1 = type { [10 x [10 x i32]] }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
; Source code:
; typedef struct s1 { int a1; int a2:4; int a3;} __s1;
; enum { FIELD_BYTE_SIZE = 1, };
; return __builtin_preserve_field_info(arg->a2, FIELD_BYTE_SIZE);
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%struct.s1 = type { i32, i8, i32 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
; Source code:
; typedef unsigned __uint;
; struct s1 { int a1; __uint a2:9; __uint a3:4; };
; return r1 + r2 + r3 + r4;
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%struct.s1 = type { i32, i16 }
%union.u1 = type { i32 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
; Source code:
; typedef unsigned __uint;
; struct s1 { int a1; __uint a2:9; __uint a3:4; };
; return r1 + r2;
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%union.u1 = type { %struct.s1 }
%struct.s1 = type { i32, i16 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
; Source code:
; typedef struct s1 { int a1[10][10]; } __s1;
; union u1 { int b1; __s1 b2; };
; return r1 + r2;
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%union.u1 = type { %struct.s1 }
%struct.s1 = type { [10 x [10 x i32]] }
--- /dev/null
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-EB,CHECK-ALU64 %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-EB,CHECK-ALU32 %s
+; Source code:
+; typedef struct s1 { int a1:7; int a2:4; int a3:5; int a4:16;} __s1;
+; union u1 { int b1; __s1 b2; };
+; enum { FIELD_LSHIFT_U64 = 4, };
+; int test(union u1 *arg) {
+; unsigned r1 = __builtin_preserve_field_info(arg->b2.a1, FIELD_LSHIFT_U64);
+; unsigned r2 = __builtin_preserve_field_info(arg->b2.a2, FIELD_LSHIFT_U64);
+; unsigned r3 = __builtin_preserve_field_info(arg->b2.a3, FIELD_LSHIFT_U64);
+; unsigned r4 = __builtin_preserve_field_info(arg->b2.a4, FIELD_LSHIFT_U64);
+; /* big endian: r1: 32, r2: 39, r3: 43, r4: 48 */
+; /* little endian: r1: 57, r2: 53, r3: 48, r4: 32 */
+; return r1 + r2 + r3 + r4;
+; }
+; Compilation flag:
+; clang -target bpfeb -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpfeb"
+
+%union.u1 = type { i32 }
+%struct.s1 = type { i32 }
+
+; Function Attrs: nounwind readnone
+define dso_local i32 @test(%union.u1* %arg) local_unnamed_addr #0 !dbg !11 {
+entry:
+ call void @llvm.dbg.value(metadata %union.u1* %arg, metadata !28, metadata !DIExpression()), !dbg !33
+ %0 = tail call %union.u1* @llvm.preserve.union.access.index.p0s_union.u1s.p0s_union.u1s(%union.u1* %arg, i32 1), !dbg !34, !llvm.preserve.access.index !16
+ %b2 = bitcast %union.u1* %0 to %struct.s1*, !dbg !34
+ %1 = tail call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s1s(%struct.s1* %b2, i32 0, i32 0), !dbg !35, !llvm.preserve.access.index !21
+ %2 = tail call i32 @llvm.bpf.preserve.field.info.p0i32(i32* %1, i64 4), !dbg !36
+ call void @llvm.dbg.value(metadata i32 %2, metadata !29, metadata !DIExpression()), !dbg !33
+ %3 = tail call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s1s(%struct.s1* %b2, i32 0, i32 1), !dbg !37, !llvm.preserve.access.index !21
+ %4 = tail call i32 @llvm.bpf.preserve.field.info.p0i32(i32* %3, i64 4), !dbg !38
+ call void @llvm.dbg.value(metadata i32 %4, metadata !30, metadata !DIExpression()), !dbg !33
+ %5 = tail call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s1s(%struct.s1* %b2, i32 0, i32 2), !dbg !39, !llvm.preserve.access.index !21
+ %6 = tail call i32 @llvm.bpf.preserve.field.info.p0i32(i32* %5, i64 4), !dbg !40
+ call void @llvm.dbg.value(metadata i32 %6, metadata !31, metadata !DIExpression()), !dbg !33
+ %7 = tail call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s1s(%struct.s1* %b2, i32 0, i32 3), !dbg !41, !llvm.preserve.access.index !21
+ %8 = tail call i32 @llvm.bpf.preserve.field.info.p0i32(i32* %7, i64 4), !dbg !42
+ call void @llvm.dbg.value(metadata i32 %8, metadata !32, metadata !DIExpression()), !dbg !33
+ %add = add i32 %4, %2, !dbg !43
+ %add4 = add i32 %add, %6, !dbg !44
+ %add5 = add i32 %add4, %8, !dbg !45
+ ret i32 %add5, !dbg !46
+}
+
+; CHECK-EB: r1 = 32
+; CHECK-EB: r0 = 39
+; CHECK-ALU64: r0 += r1
+; CHECK-ALU32: w0 += w1
+; CHECK-EB: r1 = 43
+; CHECK-ALU64: r0 += r1
+; CHECK-ALU32: w0 += w1
+; CHECK-EB: r1 = 48
+; CHECK-ALU64: r0 += r1
+; CHECK-ALU32: w0 += w1
+; CHECK: exit
+
+; CHECK: .long 1 # BTF_KIND_UNION(id = 2)
+; CHECK: .ascii "u1" # string offset=1
+; CHECK: .ascii ".text" # string offset=43
+; CHECK: .ascii "0:1:0" # string offset=49
+; CHECK: .ascii "0:1:1" # string offset=92
+; CHECK: .ascii "0:1:2" # string offset=98
+; CHECK: .ascii "0:1:3" # string offset=104
+
+; CHECK: .long 16 # FieldReloc
+; CHECK-NEXT: .long 43 # Field reloc section string offset=43
+; CHECK-NEXT: .long 4
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
+; CHECK-NEXT: .long 2
+; CHECK-NEXT: .long 49
+; CHECK-NEXT: .long 4
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
+; CHECK-NEXT: .long 2
+; CHECK-NEXT: .long 92
+; CHECK-NEXT: .long 4
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
+; CHECK-NEXT: .long 2
+; CHECK-NEXT: .long 98
+; CHECK-NEXT: .long 4
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
+; CHECK-NEXT: .long 2
+; CHECK-NEXT: .long 104
+; CHECK-NEXT: .long 4
+
+; Function Attrs: nounwind readnone
+declare %union.u1* @llvm.preserve.union.access.index.p0s_union.u1s.p0s_union.u1s(%union.u1*, i32) #1
+
+; Function Attrs: nounwind readnone
+declare i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s1s(%struct.s1*, i32, i32) #1
+
+; Function Attrs: nounwind readnone
+declare i32 @llvm.bpf.preserve.field.info.p0i32(i32*, i64) #1
+
+; Function Attrs: nounwind readnone speculatable willreturn
+declare void @llvm.dbg.value(metadata, metadata, metadata) #2
+
+attributes #0 = { nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind readnone }
+attributes #2 = { nounwind readnone speculatable willreturn }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!7, !8, !9}
+!llvm.ident = !{!10}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 (https://github.com/llvm/llvm-project.git 5635073377f153f7f2ff9b34c77af3c79885ff4a)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
+!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/core")
+!2 = !{!3}
+!3 = !DICompositeType(tag: DW_TAG_enumeration_type, file: !1, line: 3, baseType: !4, size: 32, elements: !5)
+!4 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned)
+!5 = !{!6}
+!6 = !DIEnumerator(name: "FIELD_LSHIFT_U64", value: 4, isUnsigned: true)
+!7 = !{i32 2, !"Dwarf Version", i32 4}
+!8 = !{i32 2, !"Debug Info Version", i32 3}
+!9 = !{i32 1, !"wchar_size", i32 4}
+!10 = !{!"clang version 10.0.0 (https://github.com/llvm/llvm-project.git 5635073377f153f7f2ff9b34c77af3c79885ff4a)"}
+!11 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 4, type: !12, scopeLine: 4, flags: DIFlagPrototyped, isDefinition: true, isOptimized: true, unit: !0, retainedNodes: !27)
+!12 = !DISubroutineType(types: !13)
+!13 = !{!14, !15}
+!14 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!15 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !16, size: 64)
+!16 = distinct !DICompositeType(tag: DW_TAG_union_type, name: "u1", file: !1, line: 2, size: 32, elements: !17)
+!17 = !{!18, !19}
+!18 = !DIDerivedType(tag: DW_TAG_member, name: "b1", scope: !16, file: !1, line: 2, baseType: !14, size: 32)
+!19 = !DIDerivedType(tag: DW_TAG_member, name: "b2", scope: !16, file: !1, line: 2, baseType: !20, size: 32)
+!20 = !DIDerivedType(tag: DW_TAG_typedef, name: "__s1", file: !1, line: 1, baseType: !21)
+!21 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s1", file: !1, line: 1, size: 32, elements: !22)
+!22 = !{!23, !24, !25, !26}
+!23 = !DIDerivedType(tag: DW_TAG_member, name: "a1", scope: !21, file: !1, line: 1, baseType: !14, size: 7, flags: DIFlagBitField, extraData: i64 0)
+!24 = !DIDerivedType(tag: DW_TAG_member, name: "a2", scope: !21, file: !1, line: 1, baseType: !14, size: 4, offset: 7, flags: DIFlagBitField, extraData: i64 0)
+!25 = !DIDerivedType(tag: DW_TAG_member, name: "a3", scope: !21, file: !1, line: 1, baseType: !14, size: 5, offset: 11, flags: DIFlagBitField, extraData: i64 0)
+!26 = !DIDerivedType(tag: DW_TAG_member, name: "a4", scope: !21, file: !1, line: 1, baseType: !14, size: 16, offset: 16, flags: DIFlagBitField, extraData: i64 0)
+!27 = !{!28, !29, !30, !31, !32}
+!28 = !DILocalVariable(name: "arg", arg: 1, scope: !11, file: !1, line: 4, type: !15)
+!29 = !DILocalVariable(name: "r1", scope: !11, file: !1, line: 5, type: !4)
+!30 = !DILocalVariable(name: "r2", scope: !11, file: !1, line: 6, type: !4)
+!31 = !DILocalVariable(name: "r3", scope: !11, file: !1, line: 7, type: !4)
+!32 = !DILocalVariable(name: "r4", scope: !11, file: !1, line: 8, type: !4)
+!33 = !DILocation(line: 0, scope: !11)
+!34 = !DILocation(line: 5, column: 52, scope: !11)
+!35 = !DILocation(line: 5, column: 55, scope: !11)
+!36 = !DILocation(line: 5, column: 17, scope: !11)
+!37 = !DILocation(line: 6, column: 55, scope: !11)
+!38 = !DILocation(line: 6, column: 17, scope: !11)
+!39 = !DILocation(line: 7, column: 55, scope: !11)
+!40 = !DILocation(line: 7, column: 17, scope: !11)
+!41 = !DILocation(line: 8, column: 55, scope: !11)
+!42 = !DILocation(line: 8, column: 17, scope: !11)
+!43 = !DILocation(line: 11, column: 13, scope: !11)
+!44 = !DILocation(line: 11, column: 18, scope: !11)
+!45 = !DILocation(line: 11, column: 23, scope: !11)
+!46 = !DILocation(line: 11, column: 3, scope: !11)
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-EL,CHECK-ALU64 %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-EB,CHECK-ALU64 %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-EL,CHECK-ALU32 %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-EB,CHECK-ALU32 %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-EL,CHECK-ALU64 %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-EL,CHECK-ALU32 %s
; Source code:
; typedef struct s1 { int a1:7; int a2:4; int a3:5; int a4:16;} __s1;
; union u1 { int b1; __s1 b2; };
; return r1 + r2 + r3 + r4;
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%union.u1 = type { i32 }
%struct.s1 = type { i32 }
; CHECK-EL: r1 = 57
; CHECK-EL: r0 = 53
-; CHECK-EB: r1 = 32
-; CHECK-EB: r0 = 39
; CHECK-ALU64: r0 += r1
; CHECK-ALU32: w0 += w1
; CHECK-EL: r1 = 48
-; CHECK-EB: r1 = 43
; CHECK-ALU64: r0 += r1
; CHECK-ALU32: w0 += w1
; CHECK-EL: r1 = 32
-; CHECK-EB: r1 = 48
; CHECK-ALU64: r0 += r1
; CHECK-ALU32: w0 += w1
; CHECK: exit
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
; Source code:
; typedef struct s1 { int a1; short a2; } __s1;
; union u1 { int b1; __s1 b2; };
; return r1 + r2;
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%union.u1 = type { %struct.s1 }
%struct.s1 = type { i32, i16 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
; Source code:
; typedef struct s1 { int a1:7; int a2:4; int a3:5; int a4:16;} __s1;
; union u1 { int b1; __s1 b2; };
; return r1 + r2 + r3 + r4;
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%union.u1 = type { i32 }
%struct.s1 = type { i32 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
; Source code:
; typedef struct s1 { int a1; char a2; } __s1;
; union u1 { int b1; __s1 b2; };
; return r1 + r2;
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%union.u1 = type { %struct.s1 }
%struct.s1 = type { i32, i8 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
; Source code:
; typedef struct s1 { char a1 [5][5]; } __s1;
; union u1 { int b1; __s1 b2; };
; return r1 + r2;
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%union.u1 = type { i32, [24 x i8] }
%struct.s1 = type { [5 x [5 x i8]] }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
; Source code:
; typedef unsigned __uint;
; struct s1 { int a1; __uint a2:9; __uint a3:4; };
; return r1 + r2 + r3 + r4;
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%struct.s1 = type { i32, i16 }
%union.u1 = type { i32 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
; Source code:
; enum A { AA = -1, AB = 0, }; /* signed */
; enum B { BA = 0, BB = 1, }; /* unsigned */
; return r1 + r2 + r3;
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%union.u1 = type { %struct.s1 }
%struct.s1 = type { i32, i16 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
; Source code:
; enum A { AA = -1, AB = 0, };
; enum B { BA = 0, BB = 1, };
; return r1 + r2;
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%union.u1 = type { %struct.s1 }
%struct.s1 = type { [10 x i32], [10 x [10 x i32]] }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck %s
;
; Source code:
; struct s { int a; int b; };
; int get_value(const void *addr);
; int test(struct s *arg) { return get_value(_(&arg->b)); }
; Compiler flag to generate IR:
-; clang -target bpf -S -O2 -g -emit-llvm test.c
+; clang -target bpf -S -O2 -g -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%struct.s = type { i32, i32 }
+++ /dev/null
-; RUN: opt -O2 -march=bpfeb < %s | llvm-dis | FileCheck %s
-; RUN: opt -O2 -march=bpfel < %s | llvm-dis | FileCheck %s
-;
-; Source code:
-; #define _(x) (__builtin_preserve_access_index(x))
-; int get_value(const int *arg);
-; int test(int b, int *arg) {
-; int v1 = b ? get_value(_(&arg[4])) : 0;
-; int v2 = b ? get_value(_(&arg[4])) : 0;
-; return v1 + v2;
-; }
-; Compilation flag:
-; clang -target bpf -O0 -g -S -emit-llvm -Xclang -disable-O0-optnone test.c
-
-; Function Attrs: noinline nounwind
-define dso_local i32 @test(i32 %b, i32* %arg) #0 !dbg !10 {
-entry:
- %b.addr = alloca i32, align 4
- %arg.addr = alloca i32*, align 8
- %v1 = alloca i32, align 4
- %v2 = alloca i32, align 4
- store i32 %b, i32* %b.addr, align 4
- call void @llvm.dbg.declare(metadata i32* %b.addr, metadata !13, metadata !DIExpression()), !dbg !14
- store i32* %arg, i32** %arg.addr, align 8
- call void @llvm.dbg.declare(metadata i32** %arg.addr, metadata !15, metadata !DIExpression()), !dbg !16
- call void @llvm.dbg.declare(metadata i32* %v1, metadata !17, metadata !DIExpression()), !dbg !18
- %0 = load i32, i32* %b.addr, align 4, !dbg !19
- %tobool = icmp ne i32 %0, 0, !dbg !19
- br i1 %tobool, label %cond.true, label %cond.false, !dbg !19
-
-cond.true: ; preds = %entry
- %1 = load i32*, i32** %arg.addr, align 8, !dbg !20
- %2 = call i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32* %1, i32 0, i32 4), !dbg !20, !llvm.preserve.access.index !4
- %3 = bitcast i32* %2 to i8*, !dbg !20
- %4 = bitcast i8* %3 to i32*, !dbg !20
- %call = call i32 @get_value(i32* %4), !dbg !21
- br label %cond.end, !dbg !19
-
-cond.false: ; preds = %entry
- br label %cond.end, !dbg !19
-
-cond.end: ; preds = %cond.false, %cond.true
- %cond = phi i32 [ %call, %cond.true ], [ 0, %cond.false ], !dbg !19
- store i32 %cond, i32* %v1, align 4, !dbg !18
- call void @llvm.dbg.declare(metadata i32* %v2, metadata !22, metadata !DIExpression()), !dbg !23
- %5 = load i32, i32* %b.addr, align 4, !dbg !24
- %tobool1 = icmp ne i32 %5, 0, !dbg !24
- br i1 %tobool1, label %cond.true2, label %cond.false4, !dbg !24
-
-cond.true2: ; preds = %cond.end
- %6 = load i32*, i32** %arg.addr, align 8, !dbg !25
- %7 = call i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32* %6, i32 0, i32 4), !dbg !25, !llvm.preserve.access.index !4
- %8 = bitcast i32* %7 to i8*, !dbg !25
- %9 = bitcast i8* %8 to i32*, !dbg !25
- %call3 = call i32 @get_value(i32* %9), !dbg !26
- br label %cond.end5, !dbg !24
-
-; CHECK: tail call i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32* %{{[0-9a-z]+}}, i32 0, i32 4), !dbg !{{[0-9]+}}, !llvm.preserve.access.index !{{[0-9]+}}
-; CHECK-NOT: tail call i32* @llvm.preserve.array.access.index
-
-cond.false4: ; preds = %cond.end
- br label %cond.end5, !dbg !24
-
-cond.end5: ; preds = %cond.false4, %cond.true2
- %cond6 = phi i32 [ %call3, %cond.true2 ], [ 0, %cond.false4 ], !dbg !24
- store i32 %cond6, i32* %v2, align 4, !dbg !23
- %10 = load i32, i32* %v1, align 4, !dbg !27
- %11 = load i32, i32* %v2, align 4, !dbg !28
- %add = add nsw i32 %10, %11, !dbg !29
- ret i32 %add, !dbg !30
-}
-
-; Function Attrs: nounwind readnone speculatable willreturn
-declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
-
-declare dso_local i32 @get_value(i32*) #2
-
-; Function Attrs: nounwind readnone
-declare i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32*, i32 immarg, i32 immarg) #3
-
-attributes #0 = { noinline nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
-attributes #1 = { nounwind readnone speculatable willreturn }
-attributes #2 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
-attributes #3 = { nounwind readnone }
-
-!llvm.dbg.cu = !{!0}
-!llvm.module.flags = !{!6, !7, !8}
-!llvm.ident = !{!9}
-
-!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 (https://github.com/llvm/llvm-project.git 4618b07fe2cede1b73512d1c260cf4981661f47f)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, nameTableKind: None)
-!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm/cast")
-!2 = !{}
-!3 = !{!4}
-!4 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !5, size: 64)
-!5 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-!6 = !{i32 2, !"Dwarf Version", i32 4}
-!7 = !{i32 2, !"Debug Info Version", i32 3}
-!8 = !{i32 1, !"wchar_size", i32 4}
-!9 = !{!"clang version 10.0.0 (https://github.com/llvm/llvm-project.git 4618b07fe2cede1b73512d1c260cf4981661f47f)"}
-!10 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 3, type: !11, scopeLine: 3, flags: DIFlagPrototyped, isDefinition: true, unit: !0, retainedNodes: !2)
-!11 = !DISubroutineType(types: !12)
-!12 = !{!5, !5, !4}
-!13 = !DILocalVariable(name: "b", arg: 1, scope: !10, file: !1, line: 3, type: !5)
-!14 = !DILocation(line: 3, column: 14, scope: !10)
-!15 = !DILocalVariable(name: "arg", arg: 2, scope: !10, file: !1, line: 3, type: !4)
-!16 = !DILocation(line: 3, column: 22, scope: !10)
-!17 = !DILocalVariable(name: "v1", scope: !10, file: !1, line: 4, type: !5)
-!18 = !DILocation(line: 4, column: 7, scope: !10)
-!19 = !DILocation(line: 4, column: 12, scope: !10)
-!20 = !DILocation(line: 4, column: 26, scope: !10)
-!21 = !DILocation(line: 4, column: 16, scope: !10)
-!22 = !DILocalVariable(name: "v2", scope: !10, file: !1, line: 5, type: !5)
-!23 = !DILocation(line: 5, column: 7, scope: !10)
-!24 = !DILocation(line: 5, column: 12, scope: !10)
-!25 = !DILocation(line: 5, column: 26, scope: !10)
-!26 = !DILocation(line: 5, column: 16, scope: !10)
-!27 = !DILocation(line: 6, column: 10, scope: !10)
-!28 = !DILocation(line: 6, column: 15, scope: !10)
-!29 = !DILocation(line: 6, column: 13, scope: !10)
-!30 = !DILocation(line: 6, column: 3, scope: !10)
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck %s
;
; Source:
; enum AA { VAL1 = -100, VAL2 = 0xffff8000 };
; __builtin_preserve_enum_value(*(__BB *)VAL10, 1);
; }
; Compiler flag to generate IR:
-; clang -target bpf -S -O2 -g -emit-llvm t1.c
+; clang -target bpf -S -O2 -g -emit-llvm -Xclang -disable-llvm-passes t1.c
+
+target triple = "bpf"
@0 = private unnamed_addr constant [10 x i8] c"VAL1:-100\00", align 1
@1 = private unnamed_addr constant [16 x i8] c"VAL2:4294934528\00", align 1
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck %s
;
; Source:
; enum AA { VAL = 100 };
; __builtin_preserve_type_info(*(enum AA *)0, 0);
; }
; Compiler flag to generate IR:
-; clang -target bpf -S -O2 -g -emit-llvm t1.c
+; clang -target bpf -S -O2 -g -emit-llvm -Xclang -disable-llvm-passes t1.c
+
+target triple = "bpf"
; Function Attrs: nounwind readnone
define dso_local i32 @test() local_unnamed_addr #0 !dbg !17 {
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck %s
;
; Source:
; enum AA { VAL = 100 };
; __builtin_preserve_type_info(*(enum AA *)0, 1);
; }
; Compiler flag to generate IR:
-; clang -target bpf -S -O2 -g -emit-llvm t1.c
+; clang -target bpf -S -O2 -g -emit-llvm -Xclang -disable-llvm-passes t1.c
+
+target triple = "bpf"
; Function Attrs: nounwind readnone
define dso_local i32 @test() local_unnamed_addr #0 !dbg !17 {
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck %s
;
; Source:
; enum AA { VAL = 100 };
; __builtin_preserve_type_info(a, 1);
; }
; Compiler flag to generate IR:
-; clang -target bpf -S -O2 -g -emit-llvm t1.c
+; clang -target bpf -S -O2 -g -emit-llvm -Xclang -disable-llvm-passes t1.c
+
+target triple = "bpf"
; Function Attrs: nounwind readnone
define dso_local i32 @test() local_unnamed_addr #0 !dbg !17 {
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck %s
;
; Source code:
; union u { int a; int b; };
; int get_value(const void *addr);
; int test(union u *arg) { return get_value(_(&arg->b)); }
; Compiler flag to generate IR:
-; clang -target bpf -S -O2 -g -emit-llvm test.c
+; clang -target bpf -S -O2 -g -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%union.u = type { i32 }
-; RUN: llc -march=bpfel -filetype=obj -o - %s | llvm-readelf -s - | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -filetype=obj -o - %s | llvm-readelf -s - | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfel -filetype=obj -addrsig -o - %s | llvm-readelf -s - | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -filetype=obj -addrsig -o - %s | llvm-readelf -s - | FileCheck -check-prefixes=CHECK %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=obj -o - %t1 | llvm-readelf -s - | FileCheck -check-prefixes=CHECK %s
+; RUN: llc -filetype=obj -addrsig -o - %t1 | llvm-readelf -s - | FileCheck -check-prefixes=CHECK %s
;
; Source Code:
; struct tt { int a; } __attribute__((preserve_access_index));
; return arg->a;
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm t.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes t.c
+
+target triple = "bpf"
%struct.tt = type { i32 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
; Source code:
; struct data_t {
; int d1;
; output(&data);
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%struct.info_t = type { i32, i32 }
%struct.data_t = type { i32, i32 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck %s
;
; Source code:
; struct s { int a; int b; };
; int test(struct s *arg1, struct t *arg2) {
; return get_value(_(&arg1->b), _(&arg2->d));
; }
-; clang -target bpf -S -O2 -g -emit-llvm test.c
+; clang -target bpf -S -O2 -g -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%struct.s = type { i32, i32 }
%struct.t = type { i32, i32 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
; Source code:
; struct sk_buff {
; int i;
; return dev != 0;
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%struct.sk_buff = type { i32, %struct.net_device* }
%struct.net_device = type opaque
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
; Source code:
; struct v1 {int a; int b;};
; typedef struct v1 __v1;
; return get_value(_(&cast_to_arr(&arg->d[0])[0][2].b));
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%struct.v3 = type { i8, [100 x i32] }
%struct.v1 = type { i32, i32 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
; Source code:
; struct v1 {int a; int b;};
; typedef struct v1 __v1;
; return get_value(_(&cast_to_arr(&arg->d[0])[0][2][3].b));
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%struct.v3 = type { i8, [100 x i32] }
%struct.v1 = type { i32, i32 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
; Source code:
; struct v1 { int a; int b; };
; struct v2 { int c; int d; };
; return get_value(_(&cast_to_v1(&arg->d)->b));
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%struct.v3 = type { i8, %struct.v2 }
%struct.v2 = type { i32, i32 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
; Source code:
; struct v1 { int a; int b; };
; typedef struct v1 __v1;
; return get_value(_(&cast_to_v1(&arg->d)->b));
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%struct.v3 = type { i8, %struct.v2 }
%struct.v2 = type { i32, i32 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
; Source code:
; struct v1 { int a; int b; };
; typedef struct v1 __v1;
; return get_value(_(&cast_to_v1(&arg->d[4])->b));
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%struct.v3 = type { i8, [40 x i32] }
%struct.v1 = type { i32, i32 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
; Source code:
; union v1 { int a; int b; };
; typedef union v1 __v1;
; return get_value(_(&cast_to_v1(&arg->d)->b));
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%union.v3 = type { %union.v2 }
%union.v2 = type { i32 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
; Source code:
; union v1 { int a; int b; };
; typedef union v1 __v1;
; return get_value(_(&cast_to_v1(&arg->d[4])->b));
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%union.v3 = type { [40 x i32] }
%union.v1 = type { i32 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-ALU64 %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-ALU32 %s
;
; Source Code:
; #define _(x) (__builtin_preserve_access_index(x))
; struct s {int a; int b;};
; int test(struct s *arg) { return *(const int *)_(&arg->b); }
; Compiler flag to generate IR:
-; clang -target bpf -S -O2 -g -emit-llvm test.c
+; clang -target bpf -S -O2 -g -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%struct.s = type { i32, i32 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck %s
;
; Source Code:
; #define _(x) (__builtin_preserve_access_index(x))
; struct s {int a; int b;};
; const void *test(struct s *arg) { return _(&arg->b); }
; Compiler flag to generate IR:
-; clang -target bpf -S -O2 -g -emit-llvm test.c
+; clang -target bpf -S -O2 -g -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%struct.s = type { i32, i32 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK64 %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK32 %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK64 %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK32 %s
; Source code:
; struct s {
; int a;
; return ull >> __builtin_preserve_field_info(arg->b2, FIELD_RSHIFT_U64);
; }
; Compilation flag:
-; clang -target bpfel -O2 -g -S -emit-llvm test.c
+; clang -target bpfel -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%struct.s = type { i32, i16 }
--- /dev/null
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-EB,CHECK64 %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-EB,CHECK32 %s
+; Source code:
+; struct s {
+; int a;
+; int b1:9;
+; int b2:4;
+; };
+; enum {
+; FIELD_BYTE_OFFSET = 0,
+; FIELD_BYTE_SIZE,
+; FIELD_EXISTENCE,
+; FIELD_SIGNEDNESS,
+; FIELD_LSHIFT_U64,
+; FIELD_RSHIFT_U64,
+; };
+; int field_read(struct s *arg) {
+; unsigned long long ull;
+; unsigned offset = __builtin_preserve_field_info(arg->b2, FIELD_BYTE_OFFSET);
+; unsigned size = __builtin_preserve_field_info(arg->b2, FIELD_BYTE_SIZE);
+; switch(size) {
+; case 1:
+; ull = *(unsigned char *)((void *)arg + offset); break;
+; case 2:
+; ull = *(unsigned short *)((void *)arg + offset); break;
+; case 4:
+; ull = *(unsigned int *)((void *)arg + offset); break;
+; case 8:
+; ull = *(unsigned long long *)((void *)arg + offset); break;
+; }
+; ull <<= __builtin_preserve_field_info(arg->b2, FIELD_LSHIFT_U64);
+; if (__builtin_preserve_field_info(arg->b2, FIELD_SIGNEDNESS))
+; return ((long long)ull) >>__builtin_preserve_field_info(arg->b2, FIELD_RSHIFT_U64);
+; return ull >> __builtin_preserve_field_info(arg->b2, FIELD_RSHIFT_U64);
+; }
+; Compilation flag:
+; clang -target bpfeb -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpfeb"
+
+%struct.s = type { i32, i16 }
+
+; Function Attrs: nounwind readonly
+define dso_local i32 @field_read(%struct.s* %arg) local_unnamed_addr #0 !dbg !26 {
+entry:
+ call void @llvm.dbg.value(metadata %struct.s* %arg, metadata !37, metadata !DIExpression()), !dbg !41
+ %0 = tail call i16* @llvm.preserve.struct.access.index.p0i16.p0s_struct.ss(%struct.s* %arg, i32 1, i32 2), !dbg !42, !llvm.preserve.access.index !31
+ %1 = tail call i32 @llvm.bpf.preserve.field.info.p0i16(i16* %0, i64 0), !dbg !43
+ call void @llvm.dbg.value(metadata i32 %1, metadata !39, metadata !DIExpression()), !dbg !41
+ %2 = tail call i32 @llvm.bpf.preserve.field.info.p0i16(i16* %0, i64 1), !dbg !44
+ call void @llvm.dbg.value(metadata i32 %2, metadata !40, metadata !DIExpression()), !dbg !41
+ switch i32 %2, label %sw.epilog [
+ i32 1, label %sw.bb
+ i32 2, label %sw.bb1
+ i32 4, label %sw.bb5
+ i32 8, label %sw.bb9
+ ], !dbg !45
+
+sw.bb: ; preds = %entry
+ %3 = bitcast %struct.s* %arg to i8*, !dbg !46
+ %idx.ext = zext i32 %1 to i64, !dbg !48
+ %add.ptr = getelementptr i8, i8* %3, i64 %idx.ext, !dbg !48
+ %4 = load i8, i8* %add.ptr, align 1, !dbg !49, !tbaa !50
+ %conv = zext i8 %4 to i64, !dbg !49
+ call void @llvm.dbg.value(metadata i64 %conv, metadata !38, metadata !DIExpression()), !dbg !41
+ br label %sw.epilog, !dbg !53
+
+sw.bb1: ; preds = %entry
+ %5 = bitcast %struct.s* %arg to i8*, !dbg !54
+ %idx.ext2 = zext i32 %1 to i64, !dbg !55
+ %add.ptr3 = getelementptr i8, i8* %5, i64 %idx.ext2, !dbg !55
+ %6 = bitcast i8* %add.ptr3 to i16*, !dbg !56
+ %7 = load i16, i16* %6, align 2, !dbg !57, !tbaa !58
+ %conv4 = zext i16 %7 to i64, !dbg !57
+ call void @llvm.dbg.value(metadata i64 %conv4, metadata !38, metadata !DIExpression()), !dbg !41
+ br label %sw.epilog, !dbg !60
+
+sw.bb5: ; preds = %entry
+ %8 = bitcast %struct.s* %arg to i8*, !dbg !61
+ %idx.ext6 = zext i32 %1 to i64, !dbg !62
+ %add.ptr7 = getelementptr i8, i8* %8, i64 %idx.ext6, !dbg !62
+ %9 = bitcast i8* %add.ptr7 to i32*, !dbg !63
+ %10 = load i32, i32* %9, align 4, !dbg !64, !tbaa !65
+ %conv8 = zext i32 %10 to i64, !dbg !64
+ call void @llvm.dbg.value(metadata i64 %conv8, metadata !38, metadata !DIExpression()), !dbg !41
+ br label %sw.epilog, !dbg !67
+
+sw.bb9: ; preds = %entry
+ %11 = bitcast %struct.s* %arg to i8*, !dbg !68
+ %idx.ext10 = zext i32 %1 to i64, !dbg !69
+ %add.ptr11 = getelementptr i8, i8* %11, i64 %idx.ext10, !dbg !69
+ %12 = bitcast i8* %add.ptr11 to i64*, !dbg !70
+ %13 = load i64, i64* %12, align 8, !dbg !71, !tbaa !72
+ call void @llvm.dbg.value(metadata i64 %13, metadata !38, metadata !DIExpression()), !dbg !41
+ br label %sw.epilog, !dbg !74
+
+sw.epilog: ; preds = %entry, %sw.bb9, %sw.bb5, %sw.bb1, %sw.bb
+ %ull.0 = phi i64 [ undef, %entry ], [ %13, %sw.bb9 ], [ %conv8, %sw.bb5 ], [ %conv4, %sw.bb1 ], [ %conv, %sw.bb ]
+ call void @llvm.dbg.value(metadata i64 %ull.0, metadata !38, metadata !DIExpression()), !dbg !41
+ %14 = tail call i32 @llvm.bpf.preserve.field.info.p0i16(i16* %0, i64 4), !dbg !75
+ %sh_prom = zext i32 %14 to i64, !dbg !76
+ %shl = shl i64 %ull.0, %sh_prom, !dbg !76
+ call void @llvm.dbg.value(metadata i64 %shl, metadata !38, metadata !DIExpression()), !dbg !41
+ %15 = tail call i32 @llvm.bpf.preserve.field.info.p0i16(i16* %0, i64 3), !dbg !77
+ %tobool = icmp eq i32 %15, 0, !dbg !77
+ %16 = tail call i32 @llvm.bpf.preserve.field.info.p0i16(i16* %0, i64 5), !dbg !41
+ %sh_prom12 = zext i32 %16 to i64, !dbg !41
+ %shr = ashr i64 %shl, %sh_prom12, !dbg !79
+ %shr15 = lshr i64 %shl, %sh_prom12, !dbg !79
+ %retval.0.in = select i1 %tobool, i64 %shr15, i64 %shr, !dbg !79
+ %retval.0 = trunc i64 %retval.0.in to i32, !dbg !41
+ ret i32 %retval.0, !dbg !80
+}
+
+; CHECK: r{{[0-9]+}} = 4
+; CHECK: r{{[0-9]+}} = 4
+; CHECK-EB: r{{[0-9]+}} <<= 41
+; CHECK64: r{{[0-9]+}} s>>= 60
+; CHECK64: r{{[0-9]+}} >>= 60
+; CHECK32: r{{[0-9]+}} >>= 60
+; CHECK32: r{{[0-9]+}} s>>= 60
+; CHECK: r{{[0-9]+}} = 1
+
+; CHECK: .long 1 # BTF_KIND_STRUCT(id = 2)
+; CHECK: .byte 115 # string offset=1
+; CHECK: .ascii ".text" # string offset=30
+; CHECK: .ascii "0:2" # string offset=36
+
+; CHECK: .long 16 # FieldReloc
+; CHECK-NEXT: .long 30 # Field reloc section string offset=30
+; CHECK-NEXT: .long 8
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
+; CHECK-NEXT: .long 2
+; CHECK-NEXT: .long 36
+; CHECK-NEXT: .long 1
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
+; CHECK-NEXT: .long 2
+; CHECK-NEXT: .long 36
+; CHECK-NEXT: .long 0
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
+; CHECK-NEXT: .long 2
+; CHECK-NEXT: .long 36
+; CHECK-NEXT: .long 0
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
+; CHECK-NEXT: .long 2
+; CHECK-NEXT: .long 36
+; CHECK-NEXT: .long 0
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
+; CHECK-NEXT: .long 2
+; CHECK-NEXT: .long 36
+; CHECK-NEXT: .long 4
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
+; CHECK-NEXT: .long 2
+; CHECK-NEXT: .long 36
+; CHECK-NEXT: .long 5
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
+; CHECK-NEXT: .long 2
+; CHECK-NEXT: .long 36
+; CHECK-NEXT: .long 5
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
+; CHECK-NEXT: .long 2
+; CHECK-NEXT: .long 36
+; CHECK-NEXT: .long 3
+
+; Function Attrs: nounwind readnone
+declare i16* @llvm.preserve.struct.access.index.p0i16.p0s_struct.ss(%struct.s*, i32, i32) #1
+
+; Function Attrs: nounwind readnone
+declare i32 @llvm.bpf.preserve.field.info.p0i16(i16*, i64) #1
+
+; Function Attrs: nounwind readnone speculatable willreturn
+declare void @llvm.dbg.value(metadata, metadata, metadata) #2
+
+attributes #0 = { nounwind readonly "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { nounwind readnone }
+attributes #2 = { nounwind readnone speculatable willreturn }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!22, !23, !24}
+!llvm.ident = !{!25}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 (https://github.com/llvm/llvm-project.git 923aa0ce806f7739b754167239fee2c9a15e2f31)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !12, nameTableKind: None)
+!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/core")
+!2 = !{!3}
+!3 = !DICompositeType(tag: DW_TAG_enumeration_type, file: !1, line: 6, baseType: !4, size: 32, elements: !5)
+!4 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned)
+!5 = !{!6, !7, !8, !9, !10, !11}
+!6 = !DIEnumerator(name: "FIELD_BYTE_OFFSET", value: 0, isUnsigned: true)
+!7 = !DIEnumerator(name: "FIELD_BYTE_SIZE", value: 1, isUnsigned: true)
+!8 = !DIEnumerator(name: "FIELD_EXISTENCE", value: 2, isUnsigned: true)
+!9 = !DIEnumerator(name: "FIELD_SIGNEDNESS", value: 3, isUnsigned: true)
+!10 = !DIEnumerator(name: "FIELD_LSHIFT_U64", value: 4, isUnsigned: true)
+!11 = !DIEnumerator(name: "FIELD_RSHIFT_U64", value: 5, isUnsigned: true)
+!12 = !{!13, !15, !16, !18, !19, !21}
+!13 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !14, size: 64)
+!14 = !DIBasicType(name: "unsigned char", size: 8, encoding: DW_ATE_unsigned_char)
+!15 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)
+!16 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !17, size: 64)
+!17 = !DIBasicType(name: "unsigned short", size: 16, encoding: DW_ATE_unsigned)
+!18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !4, size: 64)
+!19 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !20, size: 64)
+!20 = !DIBasicType(name: "long long unsigned int", size: 64, encoding: DW_ATE_unsigned)
+!21 = !DIBasicType(name: "long long int", size: 64, encoding: DW_ATE_signed)
+!22 = !{i32 2, !"Dwarf Version", i32 4}
+!23 = !{i32 2, !"Debug Info Version", i32 3}
+!24 = !{i32 1, !"wchar_size", i32 4}
+!25 = !{!"clang version 10.0.0 (https://github.com/llvm/llvm-project.git 923aa0ce806f7739b754167239fee2c9a15e2f31)"}
+!26 = distinct !DISubprogram(name: "field_read", scope: !1, file: !1, line: 14, type: !27, scopeLine: 14, flags: DIFlagPrototyped, isDefinition: true, isOptimized: true, unit: !0, retainedNodes: !36)
+!27 = !DISubroutineType(types: !28)
+!28 = !{!29, !30}
+!29 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!30 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !31, size: 64)
+!31 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s", file: !1, line: 1, size: 64, elements: !32)
+!32 = !{!33, !34, !35}
+!33 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !31, file: !1, line: 2, baseType: !29, size: 32)
+!34 = !DIDerivedType(tag: DW_TAG_member, name: "b1", scope: !31, file: !1, line: 3, baseType: !29, size: 9, offset: 32, flags: DIFlagBitField, extraData: i64 32)
+!35 = !DIDerivedType(tag: DW_TAG_member, name: "b2", scope: !31, file: !1, line: 4, baseType: !29, size: 4, offset: 41, flags: DIFlagBitField, extraData: i64 32)
+!36 = !{!37, !38, !39, !40}
+!37 = !DILocalVariable(name: "arg", arg: 1, scope: !26, file: !1, line: 14, type: !30)
+!38 = !DILocalVariable(name: "ull", scope: !26, file: !1, line: 15, type: !20)
+!39 = !DILocalVariable(name: "offset", scope: !26, file: !1, line: 16, type: !4)
+!40 = !DILocalVariable(name: "size", scope: !26, file: !1, line: 17, type: !4)
+!41 = !DILocation(line: 0, scope: !26)
+!42 = !DILocation(line: 16, column: 56, scope: !26)
+!43 = !DILocation(line: 16, column: 21, scope: !26)
+!44 = !DILocation(line: 17, column: 19, scope: !26)
+!45 = !DILocation(line: 18, column: 3, scope: !26)
+!46 = !DILocation(line: 20, column: 30, scope: !47)
+!47 = distinct !DILexicalBlock(scope: !26, file: !1, line: 18, column: 16)
+!48 = !DILocation(line: 20, column: 42, scope: !47)
+!49 = !DILocation(line: 20, column: 11, scope: !47)
+!50 = !{!51, !51, i64 0}
+!51 = !{!"omnipotent char", !52, i64 0}
+!52 = !{!"Simple C/C++ TBAA"}
+!53 = !DILocation(line: 20, column: 53, scope: !47)
+!54 = !DILocation(line: 22, column: 31, scope: !47)
+!55 = !DILocation(line: 22, column: 43, scope: !47)
+!56 = !DILocation(line: 22, column: 12, scope: !47)
+!57 = !DILocation(line: 22, column: 11, scope: !47)
+!58 = !{!59, !59, i64 0}
+!59 = !{!"short", !51, i64 0}
+!60 = !DILocation(line: 22, column: 54, scope: !47)
+!61 = !DILocation(line: 24, column: 29, scope: !47)
+!62 = !DILocation(line: 24, column: 41, scope: !47)
+!63 = !DILocation(line: 24, column: 12, scope: !47)
+!64 = !DILocation(line: 24, column: 11, scope: !47)
+!65 = !{!66, !66, i64 0}
+!66 = !{!"int", !51, i64 0}
+!67 = !DILocation(line: 24, column: 52, scope: !47)
+!68 = !DILocation(line: 26, column: 35, scope: !47)
+!69 = !DILocation(line: 26, column: 47, scope: !47)
+!70 = !DILocation(line: 26, column: 12, scope: !47)
+!71 = !DILocation(line: 26, column: 11, scope: !47)
+!72 = !{!73, !73, i64 0}
+!73 = !{!"long long", !51, i64 0}
+!74 = !DILocation(line: 26, column: 58, scope: !47)
+!75 = !DILocation(line: 28, column: 11, scope: !26)
+!76 = !DILocation(line: 28, column: 7, scope: !26)
+!77 = !DILocation(line: 29, column: 7, scope: !78)
+!78 = distinct !DILexicalBlock(scope: !26, file: !1, line: 29, column: 7)
+!79 = !DILocation(line: 29, column: 7, scope: !26)
+!80 = !DILocation(line: 32, column: 1, scope: !26)
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-EL,CHECK64 %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-EB,CHECK64 %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-EL,CHECK32 %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK,CHECK-EB,CHECK32 %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-EL,CHECK64 %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK,CHECK-EL,CHECK32 %s
; Source code:
; struct s {
; int a;
; return ull >> __builtin_preserve_field_info(arg->b2, FIELD_RSHIFT_U64);
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%struct.s = type { i32, i16 }
; CHECK: r{{[0-9]+}} = 4
; CHECK: r{{[0-9]+}} = 4
; CHECK-EL: r{{[0-9]+}} <<= 51
-; CHECK-EB: r{{[0-9]+}} <<= 41
; CHECK64: r{{[0-9]+}} s>>= 60
; CHECK64: r{{[0-9]+}} >>= 60
; CHECK32: r{{[0-9]+}} >>= 60
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
; Source code:
; typedef struct v3 { int a; int b; } __v3;
; #define _(x) (__builtin_preserve_access_index(x))
; return get_value(_(&g.b));
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%struct.v3 = type { i32, i32 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
; Source code:
; typedef struct v3 { int a; int b; } __v3;
; #define _(x) (__builtin_preserve_access_index(x))
; return get_value(_(&g[1][2].b));
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%struct.v3 = type { i32, i32 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
; Source code:
; typedef struct v3 { int a; int b; } __v3;
; #define _(x) (__builtin_preserve_access_index(x))
; return get_value(_(&g->b));
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%struct.v3 = type { i32, i32 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
; Source code:
; #define _(x) (__builtin_preserve_access_index(x))
; int get_value(const int *arg);
; return get_value(_(&arg[4]));
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
; Function Attrs: nounwind
define dso_local i32 @test(i32* %arg) local_unnamed_addr #0 !dbg !10 {
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
; Source code:
; struct t1 {
; int c;
; test1(ps, pt, pi);
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%struct.r1 = type { %struct.s1 }
%struct.s1 = type { %struct.t1 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
; Source code:
; typedef int __int;
; typedef struct v3 { int a; __int b[4][4]; } __v3;
; return get_value(_(&arg[1].b[2][3]));
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%struct.v3 = type { i32, [4 x [4 x i32]] }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
; Source code:
; typedef int __int;
; typedef struct v3 { int a; __int b[4][4][4]; } __v3;
; return get_value(_(&arg[1].b[2][3][2]));
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%struct.v3 = type { i32, [4 x [4 x [4 x i32]]] }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
; Source code:
; struct net_device {
; int dev_id;
; return dev_id;
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%struct.sk_buff = type { i32, %struct.net_device }
%struct.net_device = type { i32, i32 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
; Source code:
; typedef struct v3 { int a; int b; } __v3;
; #define _(x) (__builtin_preserve_access_index(x))
; return get_value(_(&arg[1]));
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%struct.v3 = type { i32, i32 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
; Source code:
; typedef struct v3 { int a; int b; } __v3;
; #define _(x) (__builtin_preserve_access_index(x))
; return get_value(_(&arg[1].b));
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%struct.v3 = type { i32, i32 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
; Source code:
; struct sk_buff {
; int i;
; return dev_id;
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%struct.sk_buff = type { i32, [10 x %struct.anon] }
%struct.anon = type { i32, i32 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
; Source code:
; struct net_device {
; int dev_id;
; return dev_id;
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%struct.sk_buff = type { i32, [10 x %struct.net_device] }
%struct.net_device = type { i32, i32 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck %s
;
; Source code:
; typedef const int arr_t[7];
; int test(s *arg) {
; return get_value(_(&arg->a[1]));
; }
-; clang -target bpf -S -O2 -g -emit-llvm test.c
+; clang -target bpf -S -O2 -g -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%struct.__s = type { [7 x i32] }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck %s
;
; Source code:
; #pragma clang attribute push (__attribute__((preserve_access_index)), apply_to = record)
;
; int test(__t *arg) { return arg->a; }
; Compiler flag to generate IR:
-; clang -target bpf -S -O2 -g -emit-llvm test.c
+; clang -target bpf -S -O2 -g -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%struct.__t = type { i32 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck %s
;
; Source code:
; typedef int _int;
; int test(s *arg) {
; return get_value(_(&arg->b));
; }
-; clang -target bpf -S -O2 -g -emit-llvm test.c
+; clang -target bpf -S -O2 -g -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%struct.__s = type { i32, i32 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck %s
;
; Source code:
; #pragma clang attribute push (__attribute__((preserve_access_index)), apply_to = record)
;
; int test(__t *arg) { return arg->a; }
; Compiler flag to generate IR:
-; clang -target bpf -S -O2 -g -emit-llvm test.c
+; clang -target bpf -S -O2 -g -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%union.__t = type { i32 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck %s
;
; Source code:
; typedef int _int;
; int test(s *arg) {
; return get_value(_(&arg->b));
; }
-; clang -target bpf -S -O2 -g -emit-llvm test.c
+; clang -target bpf -S -O2 -g -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%union.__s = type { i32 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck %s
;
; Source code:
; struct s { int a; int b; };
; int test(__arr *arg) {
; return get_value(_(&arg[1]->d.b));
; }
-; clang -target bpf -S -O2 -g -emit-llvm test.c
+; clang -target bpf -S -O2 -g -emit-llvm -Xclang -disable-llvm-passes test.c
; The offset reloc offset should be 12 from the base "arg".
+target triple = "bpf"
+
%union.u = type { %struct.s }
%struct.s = type { i32, i32 }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
-; RUN: llc -march=bpfeb -mattr=+alu32 -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck -check-prefixes=CHECK %s
; Source code:
; union sk_buff {
; int i;
; return dev_id;
; }
; Compilation flag:
-; clang -target bpf -O2 -g -S -emit-llvm test.c
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%union.sk_buff = type { %struct.anon }
%struct.anon = type { i32, %union.anon }
-; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck %s
-; RUN: llc -march=bpfel -mattr=+alu32 -filetype=asm -o - %s | FileCheck %s
+; RUN: opt -O2 %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck %s
; Source code:
; struct t {
; int a;
; return foo(param);
; }
; Compiler flag to generate IR:
-; clang -target bpf -S -O2 -g -emit-llvm test.c
+; clang -target bpf -S -O2 -g -emit-llvm -Xclang -disable-llvm-passes test.c
+
+target triple = "bpf"
%struct.t = type { i32 }