llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-modules
Author: Nikita Popov (nikic)
<details>
<summary>Changes</summary>
Support specifying additional properties on module-level inline assembly. In
particular, the target features and target CPU can now be specified as follows:
module asm(target_features="+foo", target_cpu="bar")
"asm line 1"
"asm line 2"
There may be multiple module inline assembly blocks with different properties.
This is intended to fix the long standing issue where in LTO scenarios we don't
know what target features to use for parsing the module-level inline assembly.
Now they can be faithfully preserved, even when merging inline assembly from
different modules with different features.
---
Patch is 47.80 KiB, truncated to 20.00 KiB below, full version:
https://github.com/llvm/llvm-project/pull/204548.diff
54 Files Affected:
- (modified) clang/lib/CodeGen/CGObjCMac.cpp (+1-5)
- (modified) clang/lib/CodeGen/CodeGenModule.cpp (+5-1)
- (modified) clang/test/CodeGen/2006-01-23-FileScopeAsm.c (+6-5)
- (modified) clang/test/CodeGen/asm.c (+4-3)
- (modified) clang/test/CodeGen/asm_incbin.c (+2-1)
- (modified) clang/test/CodeGen/cfi-salt.c (+6-5)
- (modified) clang/test/CodeGen/kcfi.c (+4-3)
- (modified) clang/test/CodeGenCUDA/filter-decl.cu (+3-2)
- (modified) clang/test/CodeGenCXX/gnu-asm-constexpr.cpp (+2-1)
- (modified) clang/test/CodeGenObjC/category-class.m (+4-3)
- (modified) clang/test/CodeGenObjC/objc-runtime-name.m (+4-3)
- (modified) clang/test/Frontend/ast-codegen.c (+2-1)
- (modified) clang/test/Modules/codegen.test (+2-1)
- (modified) llvm/include/llvm/AsmParser/LLToken.h (+2)
- (modified) llvm/include/llvm/Bitcode/LLVMBitCodes.h (+3)
- (modified) llvm/include/llvm/IR/Module.h (+68-11)
- (modified) llvm/lib/AsmParser/LLLexer.cpp (+2)
- (modified) llvm/lib/AsmParser/LLParser.cpp (+34-3)
- (modified) llvm/lib/Bitcode/Reader/BitcodeReader.cpp (+17-1)
- (modified) llvm/lib/Bitcode/Writer/BitcodeWriter.cpp (+10-3)
- (modified) llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp (+19-6)
- (modified) llvm/lib/IR/AsmWriter.cpp (+34-13)
- (modified) llvm/lib/IR/Core.cpp (+12-1)
- (modified) llvm/lib/LTO/LTO.cpp (+2-2)
- (modified) llvm/lib/Linker/IRMover.cpp (+6-3)
- (modified) llvm/lib/Object/ModuleSymbolTable.cpp (+46-44)
- (modified) llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp (+1-1)
- (modified) llvm/lib/Transforms/IPO/ExtractGV.cpp (+1-1)
- (modified) llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp (+1-1)
- (modified) llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp (+14-12)
- (modified) llvm/lib/Transforms/Utils/SplitModule.cpp (+1-1)
- (added) llvm/test/Assembler/module-asm-invalid.ll (+25)
- (modified) llvm/test/Bitcode/compatibility-3.6.ll (+2-1)
- (modified) llvm/test/Bitcode/compatibility-3.7.ll (+2-1)
- (modified) llvm/test/Bitcode/compatibility-3.8.ll (+2-1)
- (modified) llvm/test/Bitcode/compatibility-3.9.ll (+2-1)
- (modified) llvm/test/Bitcode/compatibility-4.0.ll (+2-1)
- (modified) llvm/test/Bitcode/compatibility-5.0.ll (+2-1)
- (modified) llvm/test/Bitcode/compatibility-6.0.ll (+2-1)
- (modified) llvm/test/Bitcode/compatibility.ll (+2-1)
- (modified) llvm/test/Bitcode/highLevelStructure.3.2.ll (+2-1)
- (added) llvm/test/Bitcode/module-asm.ll (+29)
- (added) llvm/test/CodeGen/RISCV/module-asm-features.ll (+12)
- (modified) llvm/test/Instrumentation/DataFlowSanitizer/prefix-rename.ll
(+2-1)
- (added) llvm/test/LTO/RISCV/module-asm.ll (+18)
- (modified) llvm/test/LTO/X86/inline-asm-lto-discard.ll (+13-11)
- (added) llvm/test/Linker/Inputs/module-asm.ll (+2)
- (modified) llvm/test/Linker/link-arm-and-thumb-module-inline-asm.ll (+9-8)
- (added) llvm/test/Linker/module-asm.ll (+9)
- (modified) llvm/test/ThinLTO/X86/import-symver.ll (+2-1)
- (modified) llvm/test/Transforms/LowerTypeTests/export-symver.ll (+2-1)
- (modified)
llvm/test/Transforms/ThinLTOBitcodeWriter/cfi-icall-static-inline-asm.ll (+2-1)
- (modified) llvm/test/Transforms/ThinLTOBitcodeWriter/x86/module-asm.ll (+2-1)
- (modified) llvm/tools/llvm-reduce/deltas/ReduceModuleData.cpp (+1-1)
``````````diff
diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp
index 69c5e88f3c768..e518b875f44bb 100644
--- a/clang/lib/CodeGen/CGObjCMac.cpp
+++ b/clang/lib/CodeGen/CGObjCMac.cpp
@@ -6610,10 +6610,6 @@ void CGObjCMac::FinishModule() {
if ((!LazySymbols.empty() || !DefinedSymbols.empty()) &&
CGM.getTriple().isOSBinFormatMachO()) {
SmallString<256> Asm;
- Asm += CGM.getModule().getModuleInlineAsm();
- if (!Asm.empty() && Asm.back() != '\n')
- Asm += '\n';
-
llvm::raw_svector_ostream OS(Asm);
for (const auto *Sym : DefinedSymbols)
OS << "\t.objc_class_name_" << Sym->getName() << "=0\n"
@@ -6624,7 +6620,7 @@ void CGObjCMac::FinishModule() {
OS << "\t.objc_category_name_" << Category << "=0\n"
<< "\t.globl .objc_category_name_" << Category << "\n";
- CGM.getModule().setModuleInlineAsm(OS.str());
+ CGM.getModule().appendModuleInlineAsm(OS.str());
}
}
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp
b/clang/lib/CodeGen/CodeGenModule.cpp
index ddbebb1d70336..c4b01e3ea3b78 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -8042,7 +8042,11 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
if (LangOpts.SYCLIsDevice)
break;
auto *AD = cast<FileScopeAsmDecl>(D);
- getModule().appendModuleInlineAsm(AD->getAsmString());
+
+ const TargetOptions &TargetOpts = getTarget().getTargetOpts();
+ std::string Features = llvm::join(TargetOpts.Features, ",");
+ getModule().appendModuleInlineAsm(llvm::Module::GlobalAsmFragment(
+ AD->getAsmString(), Features, TargetOpts.CPU));
break;
}
diff --git a/clang/test/CodeGen/2006-01-23-FileScopeAsm.c
b/clang/test/CodeGen/2006-01-23-FileScopeAsm.c
index 877da4fc669e3..eee40654240f7 100644
--- a/clang/test/CodeGen/2006-01-23-FileScopeAsm.c
+++ b/clang/test/CodeGen/2006-01-23-FileScopeAsm.c
@@ -1,13 +1,14 @@
// UNSUPPORTED: target={{.*}}-zos{{.*}}
// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
-// CHECK: module asm "foo1"
+// CHECK: module asm(target_features="{{.*}}")
+// CHECK-NEXT: "foo1"
__asm__ ("foo1");
-// CHECK: module asm "foo2"
+// CHECK-NEXT: "foo2"
__asm__ ("foo2");
-// CHECK: module asm "foo3"
+// CHECK-NEXT: "foo3"
__asm__ ("foo3");
-// CHECK: module asm "foo4"
+// CHECK-NEXT: "foo4"
__asm__ ("foo4");
-// CHECK: module asm "foo5"
+// CHECK-NEXT: "foo5"
__asm__ ("foo5");
diff --git a/clang/test/CodeGen/asm.c b/clang/test/CodeGen/asm.c
index d7465b22fbbf6..bc54eb017ad12 100644
--- a/clang/test/CodeGen/asm.c
+++ b/clang/test/CodeGen/asm.c
@@ -2,9 +2,10 @@
// PR10415:
//
-// CHECK: module asm "foo1"
-// CHECK-NEXT: module asm "foo2"
-// CHECK-NEXT: module asm "foo3"
+// CHECK: module asm(target_features="{{.*}}")
+// CHECK-NEXT: "foo1"
+// CHECK-NEXT: "foo2"
+// CHECK-NEXT: "foo3"
__asm__ ("foo1");
__asm__ ("foo2");
__asm__ ("foo3");
diff --git a/clang/test/CodeGen/asm_incbin.c b/clang/test/CodeGen/asm_incbin.c
index 6234eea1d6738..bbc5d3af55ea2 100644
--- a/clang/test/CodeGen/asm_incbin.c
+++ b/clang/test/CodeGen/asm_incbin.c
@@ -6,4 +6,5 @@ asm(".incbin \"foo.h\"");
// RUN: cd %t
// RUN: %clang -c -emit-llvm %t/tu.c -o %t/tu.ll
// RUN: llvm-dis %t/tu.ll -o - | FileCheck %s
-// CHECK: module asm ".incbin \22foo.h\22"
+// CHECK: module asm
+// CHECK-NEXT: ".incbin \22foo.h\22"
diff --git a/clang/test/CodeGen/cfi-salt.c b/clang/test/CodeGen/cfi-salt.c
index 2a90dc31d939b..18156dc014280 100644
--- a/clang/test/CodeGen/cfi-salt.c
+++ b/clang/test/CodeGen/cfi-salt.c
@@ -26,13 +26,14 @@ typedef unsigned int (*ufn_t)(void);
typedef unsigned int (* __cfi_salt ufn_salt_t)(void);
/// Must emit __kcfi_typeid symbols for address-taken function declarations
-// CHECK: module asm ".weak __kcfi_typeid_[[F4:[a-zA-Z0-9_]+]]"
-// CHECK: module asm ".set __kcfi_typeid_[[F4]], {{[0-9]+}} /*
[[#%d,LOW_SODIUM_HASH:]] */"
-// CHECK: module asm ".weak __kcfi_typeid_[[F4_SALT:[a-zA-Z0-9_]+]]"
-// CHECK: module asm ".set __kcfi_typeid_[[F4_SALT]], {{[0-9]+}} /*
[[#%d,ASM_SALTY_HASH:]] */"
+// CHECK: module asm
+// CHECK-NEXT: ".weak __kcfi_typeid_[[F4:[a-zA-Z0-9_]+]]"
+// CHECK-NEXT: ".set __kcfi_typeid_[[F4]], {{[0-9]+}} /*
[[#%d,LOW_SODIUM_HASH:]] */"
+// CHECK-NEXT: ".weak __kcfi_typeid_[[F4_SALT:[a-zA-Z0-9_]+]]"
+// CHECK-NEXT: ".set __kcfi_typeid_[[F4_SALT]], {{[0-9]+}} /*
[[#%d,ASM_SALTY_HASH:]] */"
/// Must not __kcfi_typeid symbols for non-address-taken declarations
-// CHECK-NOT: module asm ".weak __kcfi_typeid_f6"
+// CHECK-NOT: ".weak __kcfi_typeid_f6"
int f1(void);
int f1_salt(void) __cfi_salt;
diff --git a/clang/test/CodeGen/kcfi.c b/clang/test/CodeGen/kcfi.c
index da32859dd3d88..f08cf7635fb5a 100644
--- a/clang/test/CodeGen/kcfi.c
+++ b/clang/test/CodeGen/kcfi.c
@@ -6,10 +6,11 @@
#endif
/// Must emit __kcfi_typeid symbols for address-taken function declarations
-// CHECK: module asm ".weak __kcfi_typeid_[[F4:[a-zA-Z0-9_]+]]"
-// CHECK: module asm ".set __kcfi_typeid_[[F4]], {{[0-9]+}} /* [[#%d,HASH:]]
*/"
+// CHECK: module asm
+// CHECK-NEXT: ".weak __kcfi_typeid_[[F4:[a-zA-Z0-9_]+]]"
+// CHECK-NEXT: ".set __kcfi_typeid_[[F4]], {{[0-9]+}} /* [[#%d,HASH:]] */"
/// Must not __kcfi_typeid symbols for non-address-taken declarations
-// CHECK-NOT: module asm ".weak __kcfi_typeid_{{f6|_Z2f6v}}"
+// CHECK-NOT: ".weak __kcfi_typeid_{{f6|_Z2f6v}}"
// C: @ifunc1 = ifunc i32 (i32), ptr @resolver1
// C: @ifunc2 = ifunc i64 (i64), ptr @resolver2
diff --git a/clang/test/CodeGenCUDA/filter-decl.cu
b/clang/test/CodeGenCUDA/filter-decl.cu
index 02dacd0ad8ef4..f87d62a56631e 100644
--- a/clang/test/CodeGenCUDA/filter-decl.cu
+++ b/clang/test/CodeGenCUDA/filter-decl.cu
@@ -5,8 +5,9 @@
// This has to be at the top of the file as that's where file-scope
// asm ends up.
-// CHECK-HOST: module asm "file scope asm is host only"
-// CHECK-DEVICE-NOT: module asm "file scope asm is host only"
+// CHECK-HOST: module asm
+// CHECK-HOST-NEXT: "file scope asm is host only"
+// CHECK-DEVICE-NOT: "file scope asm is host only"
__asm__("file scope asm is host only");
// CHECK-HOST: constantdata = internal global
diff --git a/clang/test/CodeGenCXX/gnu-asm-constexpr.cpp
b/clang/test/CodeGenCXX/gnu-asm-constexpr.cpp
index 175a3b7bc588c..b7e0ba389c7dd 100644
--- a/clang/test/CodeGenCXX/gnu-asm-constexpr.cpp
+++ b/clang/test/CodeGenCXX/gnu-asm-constexpr.cpp
@@ -19,7 +19,8 @@ struct string_view {
namespace GH143242 {
constexpr string_view code2 = R"(nop; nop; nop; nop)";
asm((code2));
- // CHECK: module asm "nop; nop; nop; nop"
+ // CHECK: module asm(target_features="{{.*}}")
+ // CHECK-NEXT: "nop; nop; nop; nop"
}
int func() {return 0;};
diff --git a/clang/test/CodeGenObjC/category-class.m
b/clang/test/CodeGenObjC/category-class.m
index 92fd36cbe4066..febe94ce5b9f5 100644
--- a/clang/test/CodeGenObjC/category-class.m
+++ b/clang/test/CodeGenObjC/category-class.m
@@ -1,9 +1,10 @@
// RUN: %clang_cc1 -triple i386-apple-darwin9
-fobjc-runtime=macosx-fragile-10.5 -emit-llvm -o - %s | FileCheck %s
// PR7431
-// CHECK: module asm "\09.lazy_reference .objc_class_name_A"
-// CHECK: module asm "\09.objc_category_name_A_foo=0"
-// CHECK: module asm "\09.globl .objc_category_name_A_foo"
+// CHECK: module asm
+// CHECK-NEXT: "\09.lazy_reference .objc_class_name_A"
+// CHECK-NEXT: "\09.objc_category_name_A_foo=0"
+// CHECK-NEXT: "\09.globl .objc_category_name_A_foo"
@interface A
@end
diff --git a/clang/test/CodeGenObjC/objc-runtime-name.m
b/clang/test/CodeGenObjC/objc-runtime-name.m
index c838b8c2c6f1a..a7f59caced390 100644
--- a/clang/test/CodeGenObjC/objc-runtime-name.m
+++ b/clang/test/CodeGenObjC/objc-runtime-name.m
@@ -3,9 +3,10 @@
// Check that the runtime name is emitted and used instead of the class
// identifier.
-// CHECK: module asm {{.*}}objc_class_name_XYZ=0
-// CHECK: module asm {{.*}}globl .objc_class_name_XYZ
-// CHECK: module asm {{.*}}lazy_reference .objc_class_name_XYZ
+// CHECK: module asm
+// CHECK-NEXT: {{.*}}objc_class_name_XYZ=0
+// CHECK-NEXT: {{.*}}globl .objc_class_name_XYZ
+// CHECK-NEXT: {{.*}}lazy_reference .objc_class_name_XYZ
// CHECK: @[[OBJC_CLASS_NAME:.*]] = private unnamed_addr constant [4 x i8]
c"XYZ{{.*}}, section "__TEXT,__cstring,cstring_literals",
// CHECK: = private global {{.*}} @[[OBJC_CLASS_NAME]], section
"__OBJC,__cls_refs,literal_pointers,no_dead_strip"
diff --git a/clang/test/Frontend/ast-codegen.c
b/clang/test/Frontend/ast-codegen.c
index 2e2e3d360dd17..bf35da069772d 100644
--- a/clang/test/Frontend/ast-codegen.c
+++ b/clang/test/Frontend/ast-codegen.c
@@ -2,7 +2,8 @@
// RUN: %clang -target i386-unknown-unknown -emit-ast -o %t.ast %s
// RUN: %clang -target i386-unknown-unknown -emit-llvm -S -o - %t.ast |
FileCheck %s
-// CHECK: module asm "foo"
+// CHECK: module asm(target_features="{{.*}}")
+// CHECK-NEXT: "foo"
__asm__("foo");
// CHECK: @g0 = dso_local global i32 0, align 4
diff --git a/clang/test/Modules/codegen.test b/clang/test/Modules/codegen.test
index 0af630a754805..5cc5b3c1cda2a 100644
--- a/clang/test/Modules/codegen.test
+++ b/clang/test/Modules/codegen.test
@@ -18,7 +18,8 @@ was implemented to workaround/support the initialization of
iostreams
(implemented as a namespace scope static in the header - only to be provided
when that specific header is included in the program).
-BOTH: module asm "narf"
+BOTH: module asm
+BOTH-NEXT: "narf"
FOO: $_Z2f1PKcz = comdat any
FOO: $_ZN13implicit_dtorD1Ev = comdat any
diff --git a/llvm/include/llvm/AsmParser/LLToken.h
b/llvm/include/llvm/AsmParser/LLToken.h
index d2766a05ce9ba..95d3e67ff3849 100644
--- a/llvm/include/llvm/AsmParser/LLToken.h
+++ b/llvm/include/llvm/AsmParser/LLToken.h
@@ -86,6 +86,8 @@ enum Kind {
kw_musttail,
kw_notail,
kw_target,
+ kw_target_cpu,
+ kw_target_features,
kw_triple,
kw_source_filename,
kw_unwind,
diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h
b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
index 95787c595dff7..7b05d2c161188 100644
--- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
@@ -120,6 +120,9 @@ enum ModuleCodes {
// IFUNC: [ifunc value type, addrspace, resolver val#, linkage, visibility]
MODULE_CODE_IFUNC = 18,
+
+ MODULE_CODE_ASM_TARGET_FEATURES = 19, // [strchr x N]
+ MODULE_CODE_ASM_TARGET_CPU = 20, // [strchr x N]
};
/// PARAMATTR blocks have code for defining a parameter attribute set.
diff --git a/llvm/include/llvm/IR/Module.h b/llvm/include/llvm/IR/Module.h
index 4f7e33969f16f..8a873a361ff06 100644
--- a/llvm/include/llvm/IR/Module.h
+++ b/llvm/include/llvm/IR/Module.h
@@ -169,6 +169,28 @@ class LLVM_ABI Module {
: Behavior(B), Key(K), Val(V) {}
};
+ struct GlobalAsmFragment {
+ std::string Asm;
+ std::string TargetFeatures;
+ std::string TargetCPU;
+
+ GlobalAsmFragment(StringRef Asm) : GlobalAsmFragment(Asm.str()) {}
+ GlobalAsmFragment(std::string AsmArg, std::string TargetFeatures = "",
+ std::string TargetCPU = "")
+ : Asm(std::move(AsmArg)), TargetFeatures(std::move(TargetFeatures)),
+ TargetCPU(std::move(TargetCPU)) {
+ if (!Asm.empty() && Asm.back() != '\n')
+ Asm += '\n';
+ }
+
+ bool empty() const { return Asm.empty(); }
+
+ bool hasSameProperties(const GlobalAsmFragment &Other) const {
+ return TargetFeatures == Other.TargetFeatures &&
+ TargetCPU == Other.TargetCPU;
+ }
+ };
+
/// @}
/// @name Member Variables
/// @{
@@ -180,7 +202,8 @@ class LLVM_ABI Module {
AliasListType AliasList; ///< The Aliases in the module
IFuncListType IFuncList; ///< The IFuncs in the module
NamedMDListType NamedMDList; ///< The named metadata in the module
- std::string GlobalScopeAsm; ///< Inline Asm at global scope.
+ /// Inline Asm at the global scope.
+ SmallVector<GlobalAsmFragment, 0> GlobalScopeAsm;
std::unique_ptr<ValueSymbolTable> ValSymTab; ///< Symbol table for values
ComdatSymTabType ComdatSymTab; ///< Symbol table for COMDATs
std::unique_ptr<MemoryBuffer>
@@ -287,8 +310,17 @@ class LLVM_ABI Module {
LLVMContext &getContext() const { return Context; }
/// Get any module-scope inline assembly blocks.
- /// @returns a string containing the module-scope inline assembly blocks.
- const std::string &getModuleInlineAsm() const { return GlobalScopeAsm; }
+ ArrayRef<GlobalAsmFragment> getModuleInlineAsm() const {
+ return GlobalScopeAsm;
+ }
+
+ /// Get any module-scope inline assembly blocks.
+ MutableArrayRef<GlobalAsmFragment> getModuleInlineAsm() {
+ return GlobalScopeAsm;
+ }
+
+ /// Return whether there is any module-scope inline assembly.
+ bool hasModuleInlineAsm() const { return !GlobalScopeAsm.empty(); }
/// Get a RandomNumberGenerator salted for use with this module. The
/// RNG can be seeded via -rng-seed=<uint64> and is salted with the
@@ -325,20 +357,45 @@ class LLVM_ABI Module {
/// Set the target triple.
void setTargetTriple(Triple T) { TargetTriple = std::move(T); }
+ void removeModuleInlineAsm() { GlobalScopeAsm.clear(); }
+
/// Set the module-scope inline assembly blocks.
/// A trailing newline is added if the input doesn't have one.
- void setModuleInlineAsm(StringRef Asm) {
- GlobalScopeAsm = std::string(Asm);
- if (!GlobalScopeAsm.empty() && GlobalScopeAsm.back() != '\n')
- GlobalScopeAsm += '\n';
+ void setModuleInlineAsm(GlobalAsmFragment Fragment) {
+ GlobalScopeAsm.clear();
+ appendModuleInlineAsm(std::move(Fragment));
+ }
+
+ void setModuleInlineAsm(ArrayRef<GlobalAsmFragment> Fragments) {
+ GlobalScopeAsm.clear();
+ append_range(GlobalScopeAsm, Fragments);
}
/// Append to the module-scope inline assembly blocks.
/// A trailing newline is added if the input doesn't have one.
- void appendModuleInlineAsm(StringRef Asm) {
- GlobalScopeAsm += Asm;
- if (!GlobalScopeAsm.empty() && GlobalScopeAsm.back() != '\n')
- GlobalScopeAsm += '\n';
+ void appendModuleInlineAsm(GlobalAsmFragment Fragment) {
+ if (Fragment.empty())
+ return;
+
+ if (!GlobalScopeAsm.empty() &&
+ GlobalScopeAsm.back().hasSameProperties(Fragment)) {
+ GlobalScopeAsm.back().Asm += Fragment.Asm;
+ } else {
+ GlobalScopeAsm.emplace_back(std::move(Fragment));
+ }
+ }
+
+ /// Prepend to the module-scope inline assembly blocks.
+ void prependModuleInlineAsm(GlobalAsmFragment Fragment) {
+ if (Fragment.empty())
+ return;
+
+ if (!GlobalScopeAsm.empty() &&
+ GlobalScopeAsm.front().hasSameProperties(Fragment)) {
+ GlobalScopeAsm.front().Asm.insert(0, Fragment.Asm);
+ } else {
+ GlobalScopeAsm.insert(GlobalScopeAsm.begin(), std::move(Fragment));
+ }
}
/// @}
diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp
index 069a180056488..a978867e1ad14 100644
--- a/llvm/lib/AsmParser/LLLexer.cpp
+++ b/llvm/lib/AsmParser/LLLexer.cpp
@@ -595,6 +595,8 @@ lltok::Kind LLLexer::LexIdentifier() {
KEYWORD(tail);
KEYWORD(musttail);
KEYWORD(notail);
+ KEYWORD(target_cpu);
+ KEYWORD(target_features);
KEYWORD(target);
KEYWORD(triple);
KEYWORD(source_filename);
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 75e6add0ec76f..cfd52c98d5b88 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -641,16 +641,47 @@ bool LLParser::parseTopLevelEntities() {
/// toplevelentity
/// ::= 'module' 'asm' STRINGCONSTANT
+/// ::= 'module' 'asm' '(' 'target_features' '=' STRINGCONSTANT ','
+/// 'target_cpu' '=' STRINGCONSTANT ')'
+/// STRINGCONSTANT
bool LLParser::parseModuleAsm() {
assert(Lex.getKind() == lltok::kw_module);
Lex.Lex();
std::string AsmStr;
- if (parseToken(lltok::kw_asm, "expected 'module asm'") ||
- parseStringConstant(AsmStr))
+ if (parseToken(lltok::kw_asm, "expected 'module asm'"))
return true;
- M->appendModuleInlineAsm(AsmStr);
+ std::string TargetFeatures, TargetCPU;
+ if (EatIfPresent(lltok::lparen)) {
+ while (true) {
+ if (EatIfPresent(lltok::kw_target_features)) {
+ if (parseToken(lltok::equal, "expected '='") ||
+ parseStringConstant(TargetFeatures))
+ return true;
+ } else if (EatIfPresent(lltok::kw_target_cpu)) {
+ if (parseToken(lltok::equal, "expected '='") ||
+ parseStringConstant(TargetCPU))
+ return true;
+ } else {
+ return error(Lex.getLoc(),
+ "expected one of 'target_features' or 'target_cpu'");
+ }
+ if (EatIfPresent(lltok::rparen))
+ break;
+ if (parseToken(lltok::comma, "expected ',' or ')'"))
+ return true;
+ }
+ }
+
+ do {
+ std::string AsmStrPart;
+ if (parseStringConstant(AsmStrPart))
+ return true;
+ AsmStr += AsmStrPart + "\n";
+ } while (Lex.getKind() == lltok::StringConstant);
+
+ M->appendModuleInlineAsm({AsmStr, TargetFeatures, TargetCPU});
return false;
}
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index f46d240e7ed9b..186b5b80e4a8a 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -4571,6 +4571,9 @@ Error BitcodeReader::parseModule(uint64_t ResumeBit,
// Initialize to the current module's layout string in case none is
specified.
std::string TentativeDataLayoutStr = TheModule->getDataLayoutStr();
+ // Apply to the following module asm.
+ std::string ModuleAsmTargetFeatures, ModuleAsmTargetCPU;
+
auto ResolveDataLayout = [&]() -> Error {
if (ResolvedDataLayout)
return Error::success();
@@ -4779,11 +4782,24 @@ Error BitcodeReader::parseModule(uint64_t ResumeBit,
return error("Invalid data layout record");
break;
}
+ case bitc::MODULE_CODE_ASM_TARGET_FEATURES:
+ ModuleAsmTargetFeatures.clear();
+ if (convertToString(Record, 0, ModuleAsmTargetFeatures))
+ return error("Invalid asm target features record");
+ break;
+ case bitc::MODULE_CODE_ASM_TARGET_CPU:
+ ModuleAsmTargetCPU.clear();
+ if (convertToString(Record, 0, ModuleAsmTargetCPU))
+ return error("Invalid asm target cpu record");
+ break;
case bitc::MODULE_CODE_ASM: { // ASM: [strchr x N]
std::string S;
if (convertToString(Record, 0, S))
return error("Invalid asm record");
- TheModule->setModuleInlineAsm(S);
+ TheModule->appendModuleInlineAsm(Module::GlobalAsmFragment(
+ S, ModuleAsmTargetFeatures, ModuleAsmTargetCPU));
+ ModuleAsmTargetFeatures.clear();
+ ModuleAsmTargetCPU.clear();
break;
}
case bitc::MODULE_CODE_DEPLIB: { // DEPLIB: [strchr x N]
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index f4857461ca58e..e9620763820f7 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -1546,9 +1546,16 @@ void ModuleBitcodeWriter::writeModuleInfo() {
const std::string &DL = M.getDataLayoutStr();
if (!DL.empty())
writeStringRecord(Stream, bitc::MODULE_CODE_DATALAYOUT, DL, 0 /*TODO*/);
- if (!M.getModuleInlineAsm().empty())
- writeStringRecord(Stream, bitc::MODULE_CODE_ASM, M.getModuleInlineAsm(),
- 0 /*TODO*/);
+
+ for (const Module::GlobalAsmFragment &Frag : M.getModuleInlineAsm()) {
+ if (!Frag.TargetFeatures.empty())
+ writeStringRecord(Stream, bitc::MODULE_CODE_ASM_TARGET_FEATURES,
+ Frag.TargetFeatures, 0);
+ if (!Frag.TargetCPU.empty())
+ writeStringRecord(Stream, bitc::MODULE_CODE_ASM_TARGET_CPU,
+ Frag.TargetCPU, 0);
+ writeStringRecord(Stream, bitc::MODULE_CODE_ASM, Frag.Asm, 0 /*TODO*/);
+ }
// Emit information about sections and GC, computing how many there are. Also
// compute the maximum alignment value.
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index cdb9d760606f6..97e3fcf01a08a 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -110,6 +110,7 @@
#include "llvm/MC/MCTargetOptions.h"
#include "llvm/MC/MCValue.h"
#include "llvm/MC/SectionKind.h"
+#include "llvm/MC/TargetRegistry.h"
#include "ll...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/204548
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits