yonghong-song created this revision. yonghong-song added reviewers: ast, anakryiko. Herald added a subscriber: pengfei. Herald added a project: All. yonghong-song requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
For function arguments, current implementation will do needed sign/zero extension for 32/64-bit integer types in callee and 8/16-bit types in caller. This patch forced sign/zero extension to be done in callee. Alternatively, with a slightly different implementation, sign/zero extension can be done in caller. Similarly for function return value, current implementation will do needed sign/zero extension for 32/64-bit integer types in caller and 8/16-bit return values in callee. This patch forced sign/zero extension in caller. Alternatively, with a slightly different implementation, sign/zero extension can be done in callee. $ cat t.c unsigned char bar(); char foo(short a) { if (bar() != a) return a; else return a + 1; } $ clang -target bpf -O2 -g -c t.c $ llvm-objdump -S t.o ... ; char foo(short a) { 0: bf 16 00 00 00 00 00 00 r6 = r1 ; if (bar() != a) return a; else return a + 1; 1: bf 67 00 00 00 00 00 00 r7 = r6 2: 67 07 00 00 30 00 00 00 r7 <<= 48 3: c7 07 00 00 30 00 00 00 r7 s>>= 48 4: 85 10 00 00 ff ff ff ff call -1 5: bf 01 00 00 00 00 00 00 r1 = r0 6: 57 01 00 00 ff 00 00 00 r1 &= 255 7: b7 00 00 00 01 00 00 00 r0 = 1 8: 1d 71 01 00 00 00 00 00 if r1 == r7 goto +1 <LBB0_2> 9: b7 00 00 00 00 00 00 00 r0 = 0 0000000000000050 <LBB0_2>: ; if (bar() != a) return a; else return a + 1; 10: 0f 60 00 00 00 00 00 00 r0 += r6 ; } 11: 95 00 00 00 00 00 00 00 exit In the above example, 16-bit argument value has sign extension is done in callee before it is used. 8-bit return value has zero extension done in caller before the value is used. Note that we mostly care about 8-bit return value sign/zero extension in the context of bpf program calling kernel functions since for x86_64, the caller can directly access 8-bit %al register while bpf can only access 32/64-bit registers. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D131468 Files: clang/lib/CodeGen/TargetInfo.cpp Index: clang/lib/CodeGen/TargetInfo.cpp =================================================================== --- clang/lib/CodeGen/TargetInfo.cpp +++ clang/lib/CodeGen/TargetInfo.cpp @@ -11498,6 +11498,75 @@ }; } // end anonymous namespace +//===----------------------------------------------------------------------===// +// BPF ABI Implementation +//===----------------------------------------------------------------------===// + +namespace { + +class BPFABIInfo : public DefaultABIInfo { +public: + BPFABIInfo(CodeGenTypes &CGT) : DefaultABIInfo(CGT) {} + +#if 1 + ABIArgInfo classifyArgumentType(QualType Ty) const { + Ty = useFirstFieldIfTransparentUnion(Ty); + + if (isAggregateTypeForABI(Ty)) + return getNaturalAlignIndirect(Ty); + + // Treat an enum type as its underlying type. + if (const EnumType *EnumTy = Ty->getAs<EnumType>()) + Ty = EnumTy->getDecl()->getIntegerType(); + + ASTContext &Context = getContext(); + if (const auto *EIT = Ty->getAs<BitIntType>()) + if (EIT->getNumBits() > Context.getTypeSize(Context.Int128Ty)) + return getNaturalAlignIndirect(Ty); + + return ABIArgInfo::getDirect(); + } +#endif + + ABIArgInfo classifyReturnType(QualType RetTy) const { + if (RetTy->isVoidType()) + return ABIArgInfo::getIgnore(); + + if (isAggregateTypeForABI(RetTy)) + return getNaturalAlignIndirect(RetTy); + + // Treat an enum type as its underlying type. + if (const EnumType *EnumTy = RetTy->getAs<EnumType>()) + RetTy = EnumTy->getDecl()->getIntegerType(); + + ASTContext &Context = getContext(); + if (const auto *EIT = RetTy->getAs<BitIntType>()) + if (EIT->getNumBits() > Context.getTypeSize(Context.Int128Ty)) + return getNaturalAlignIndirect(RetTy); + + return ABIArgInfo::getDirect(); + } + + void computeInfo(CGFunctionInfo &FI) const override { + FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); + for (auto &I : FI.arguments()) + I.info = classifyArgumentType(I.type); + } + +}; + +class BPFTargetCodeGenInfo : public TargetCodeGenInfo { +public: + BPFTargetCodeGenInfo(CodeGenTypes &CGT) + : TargetCodeGenInfo(std::make_unique<BPFABIInfo>(CGT)) {} + + const BPFABIInfo &getABIInfo() const { + return static_cast<const BPFABIInfo&>(TargetCodeGenInfo::getABIInfo()); + } +}; + +} + //===----------------------------------------------------------------------===// // Driver code //===----------------------------------------------------------------------===// @@ -11726,6 +11795,9 @@ : hasFP64 ? 64 : 32)); } + case llvm::Triple::bpfeb: + case llvm::Triple::bpfel: + return SetCGInfo(new BPFTargetCodeGenInfo(Types)); } }
Index: clang/lib/CodeGen/TargetInfo.cpp =================================================================== --- clang/lib/CodeGen/TargetInfo.cpp +++ clang/lib/CodeGen/TargetInfo.cpp @@ -11498,6 +11498,75 @@ }; } // end anonymous namespace +//===----------------------------------------------------------------------===// +// BPF ABI Implementation +//===----------------------------------------------------------------------===// + +namespace { + +class BPFABIInfo : public DefaultABIInfo { +public: + BPFABIInfo(CodeGenTypes &CGT) : DefaultABIInfo(CGT) {} + +#if 1 + ABIArgInfo classifyArgumentType(QualType Ty) const { + Ty = useFirstFieldIfTransparentUnion(Ty); + + if (isAggregateTypeForABI(Ty)) + return getNaturalAlignIndirect(Ty); + + // Treat an enum type as its underlying type. + if (const EnumType *EnumTy = Ty->getAs<EnumType>()) + Ty = EnumTy->getDecl()->getIntegerType(); + + ASTContext &Context = getContext(); + if (const auto *EIT = Ty->getAs<BitIntType>()) + if (EIT->getNumBits() > Context.getTypeSize(Context.Int128Ty)) + return getNaturalAlignIndirect(Ty); + + return ABIArgInfo::getDirect(); + } +#endif + + ABIArgInfo classifyReturnType(QualType RetTy) const { + if (RetTy->isVoidType()) + return ABIArgInfo::getIgnore(); + + if (isAggregateTypeForABI(RetTy)) + return getNaturalAlignIndirect(RetTy); + + // Treat an enum type as its underlying type. + if (const EnumType *EnumTy = RetTy->getAs<EnumType>()) + RetTy = EnumTy->getDecl()->getIntegerType(); + + ASTContext &Context = getContext(); + if (const auto *EIT = RetTy->getAs<BitIntType>()) + if (EIT->getNumBits() > Context.getTypeSize(Context.Int128Ty)) + return getNaturalAlignIndirect(RetTy); + + return ABIArgInfo::getDirect(); + } + + void computeInfo(CGFunctionInfo &FI) const override { + FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); + for (auto &I : FI.arguments()) + I.info = classifyArgumentType(I.type); + } + +}; + +class BPFTargetCodeGenInfo : public TargetCodeGenInfo { +public: + BPFTargetCodeGenInfo(CodeGenTypes &CGT) + : TargetCodeGenInfo(std::make_unique<BPFABIInfo>(CGT)) {} + + const BPFABIInfo &getABIInfo() const { + return static_cast<const BPFABIInfo&>(TargetCodeGenInfo::getABIInfo()); + } +}; + +} + //===----------------------------------------------------------------------===// // Driver code //===----------------------------------------------------------------------===// @@ -11726,6 +11795,9 @@ : hasFP64 ? 64 : 32)); } + case llvm::Triple::bpfeb: + case llvm::Triple::bpfel: + return SetCGInfo(new BPFTargetCodeGenInfo(Types)); } }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits