From bce36770b7c5d9e2400216902fe2c27759079eb7 Mon Sep 17 00:00:00 2001 From: Robert Widmann Date: Mon, 14 May 2018 08:09:00 +0000 Subject: [PATCH] [LLVM-C] Add Bindings For Module Flags Summary: The first foray into merging debug info into the echo tests. - Add bindings to Module::getModuleFlagsMetadata() in the form of LLVMCopyModuleFlagsMetadata - Add the opaque type LLVMModuleFlagEntry to represent Module::ModuleFlagEntry - Add accessors for LLVMModuleFlagEntry's behavior, key, and metadata node. Reviewers: whitequark, deadalnix Reviewed By: whitequark Subscribers: aprantl, JDevlieghere, llvm-commits, harlanhaskins Differential Revision: https://reviews.llvm.org/D46792 llvm-svn: 332219 --- llvm/include/llvm-c/Core.h | 109 ++++++++++++++++++++++++++++++++++++++ llvm/include/llvm-c/Types.h | 5 ++ llvm/lib/IR/Core.cpp | 104 ++++++++++++++++++++++++++++++++++++ llvm/test/Bindings/llvm-c/echo.ll | 4 ++ llvm/tools/llvm-c-test/echo.cpp | 13 +++++ 5 files changed, 235 insertions(+) diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h index 509a2e6..a52f58e 100644 --- a/llvm/include/llvm-c/Core.h +++ b/llvm/include/llvm-c/Core.h @@ -381,6 +381,57 @@ typedef enum { LLVMInlineAsmDialectIntel } LLVMInlineAsmDialect; +typedef enum { + /** + * Emits an error if two values disagree, otherwise the resulting value is + * that of the operands. + * + * @see Module::ModFlagBehavior::Error + */ + LLVMModuleFlagBehaviorError, + /** + * Emits a warning if two values disagree. The result value will be the + * operand for the flag from the first module being linked. + * + * @see Module::ModFlagBehavior::Warning + */ + LLVMModuleFlagBehaviorWarning, + /** + * Adds a requirement that another module flag be present and have a + * specified value after linking is performed. The value must be a metadata + * pair, where the first element of the pair is the ID of the module flag + * to be restricted, and the second element of the pair is the value the + * module flag should be restricted to. This behavior can be used to + * restrict the allowable results (via triggering of an error) of linking + * IDs with the **Override** behavior. + * + * @see Module::ModFlagBehavior::Require + */ + LLVMModuleFlagBehaviorRequire, + /** + * Uses the specified value, regardless of the behavior or value of the + * other module. If both modules specify **Override**, but the values + * differ, an error will be emitted. + * + * @see Module::ModFlagBehavior::Override + */ + LLVMModuleFlagBehaviorOverride, + /** + * Appends the two values, which are required to be metadata nodes. + * + * @see Module::ModFlagBehavior::Append + */ + LLVMModuleFlagBehaviorAppend, + /** + * Appends the two values, which are required to be metadata + * nodes. However, duplicate entries in the second list are dropped + * during the append operation. + * + * @see Module::ModFlagBehavior::AppendUnique + */ + LLVMModuleFlagBehaviorAppendUnique, +} LLVMModuleFlagBehavior; + /** * Attribute index are either LLVMAttributeReturnIndex, * LLVMAttributeFunctionIndex or a parameter number from 1 to N. @@ -666,6 +717,64 @@ const char *LLVMGetTarget(LLVMModuleRef M); void LLVMSetTarget(LLVMModuleRef M, const char *Triple); /** + * Returns the module flags as an array of flag-key-value triples. The caller + * is responsible for freeing this array by calling + * \c LLVMDisposeModuleFlagsMetadata. + * + * @see Module::getModuleFlagsMetadata() + */ +LLVMModuleFlagEntry *LLVMCopyModuleFlagsMetadata(LLVMModuleRef M, size_t *Len); + +/** + * Destroys module flags metadata entries. + */ +void LLVMDisposeModuleFlagsMetadata(LLVMModuleFlagEntry *Entries); + +/** + * Returns the flag behavior for a module flag entry at a specific index. + * + * @see Module::ModuleFlagEntry::Behavior + */ +LLVMModuleFlagBehavior +LLVMModuleFlagEntriesGetFlagBehavior(LLVMModuleFlagEntry *Entries, + unsigned Index); + +/** + * Returns the key for a module flag entry at a specific index. + * + * @see Module::ModuleFlagEntry::Key + */ +const char *LLVMModuleFlagEntriesGetKey(LLVMModuleFlagEntry *Entries, + unsigned Index, size_t *Len); + +/** + * Returns the metadata for a module flag entry at a specific index. + * + * @see Module::ModuleFlagEntry::Val + */ +LLVMMetadataRef LLVMModuleFlagEntriesGetMetadata(LLVMModuleFlagEntry *Entries, + unsigned Index); + +/** + * Add a module-level flag to the module-level flags metadata if it doesn't + * already exist. + * + * @see Module::getModuleFlag() + */ +LLVMMetadataRef LLVMGetModuleFlag(LLVMModuleRef M, + const char *Key, size_t KeyLen); + +/** + * Add a module-level flag to the module-level flags metadata if it doesn't + * already exist. + * + * @see Module::addModuleFlag() + */ +void LLVMAddModuleFlag(LLVMModuleRef M, LLVMModuleFlagBehavior Behavior, + const char *Key, size_t KeyLen, + LLVMMetadataRef Val); + +/** * Dump a representation of a module to stderr. * * @see Module::dump() diff --git a/llvm/include/llvm-c/Types.h b/llvm/include/llvm-c/Types.h index 1793400..f812c41 100644 --- a/llvm/include/llvm-c/Types.h +++ b/llvm/include/llvm-c/Types.h @@ -140,6 +140,11 @@ typedef struct LLVMOpaqueDiagnosticInfo *LLVMDiagnosticInfoRef; typedef struct LLVMComdat *LLVMComdatRef; /** + * @see llvm::Module::ModuleFlagEntry + */ +typedef struct LLVMOpaqueModuleFlagEntry LLVMModuleFlagEntry; + +/** * @} */ diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp index 032b2ea..0ccf06af 100644 --- a/llvm/lib/IR/Core.cpp +++ b/llvm/lib/IR/Core.cpp @@ -266,6 +266,110 @@ void LLVMSetTarget(LLVMModuleRef M, const char *Triple) { unwrap(M)->setTargetTriple(Triple); } +/*--.. Module flags ........................................................--*/ +struct LLVMOpaqueModuleFlagEntry { + LLVMModuleFlagBehavior Behavior; + const char *Key; + size_t KeyLen; + LLVMMetadataRef Metadata; +}; + +static Module::ModFlagBehavior +map_to_llvmModFlagBehavior(LLVMModuleFlagBehavior Behavior) { + switch (Behavior) { + case LLVMModuleFlagBehaviorError: + return Module::ModFlagBehavior::Error; + case LLVMModuleFlagBehaviorWarning: + return Module::ModFlagBehavior::Warning; + case LLVMModuleFlagBehaviorRequire: + return Module::ModFlagBehavior::Require; + case LLVMModuleFlagBehaviorOverride: + return Module::ModFlagBehavior::Override; + case LLVMModuleFlagBehaviorAppend: + return Module::ModFlagBehavior::Append; + case LLVMModuleFlagBehaviorAppendUnique: + return Module::ModFlagBehavior::AppendUnique; + } +} + +static LLVMModuleFlagBehavior +map_from_llvmModFlagBehavior(Module::ModFlagBehavior Behavior) { + switch (Behavior) { + case Module::ModFlagBehavior::Error: + return LLVMModuleFlagBehaviorError; + case Module::ModFlagBehavior::Warning: + return LLVMModuleFlagBehaviorWarning; + case Module::ModFlagBehavior::Require: + return LLVMModuleFlagBehaviorRequire; + case Module::ModFlagBehavior::Override: + return LLVMModuleFlagBehaviorOverride; + case Module::ModFlagBehavior::Append: + return LLVMModuleFlagBehaviorAppend; + case Module::ModFlagBehavior::AppendUnique: + return LLVMModuleFlagBehaviorAppendUnique; + default: + llvm_unreachable("Unhandled Flag Behavior"); + } +} + +LLVMModuleFlagEntry *LLVMCopyModuleFlagsMetadata(LLVMModuleRef M, size_t *Len) { + SmallVector MFEs; + unwrap(M)->getModuleFlagsMetadata(MFEs); + + LLVMOpaqueModuleFlagEntry *Result = static_cast( + safe_malloc(MFEs.size() * sizeof(LLVMOpaqueModuleFlagEntry))); + for (unsigned i = 0; i < MFEs.size(); ++i) { + const auto &ModuleFlag = MFEs[i]; + Result[i].Behavior = map_from_llvmModFlagBehavior(ModuleFlag.Behavior); + Result[i].Key = ModuleFlag.Key->getString().data(); + Result[i].KeyLen = ModuleFlag.Key->getString().size(); + Result[i].Metadata = wrap(ModuleFlag.Val); + } + *Len = MFEs.size(); + return Result; +} + +void LLVMDisposeModuleFlagsMetadata(LLVMModuleFlagEntry *Entries) { + free(Entries); +} + +LLVMModuleFlagBehavior +LLVMModuleFlagEntriesGetFlagBehavior(LLVMModuleFlagEntry *Entries, + unsigned Index) { + LLVMOpaqueModuleFlagEntry MFE = + static_cast(Entries[Index]); + return MFE.Behavior; +} + +const char *LLVMModuleFlagEntriesGetKey(LLVMModuleFlagEntry *Entries, + unsigned Index, size_t *Len) { + LLVMOpaqueModuleFlagEntry MFE = + static_cast(Entries[Index]); + *Len = MFE.KeyLen; + return MFE.Key; +} + +LLVMMetadataRef LLVMModuleFlagEntriesGetMetadata(LLVMModuleFlagEntry *Entries, + unsigned Index) { + LLVMOpaqueModuleFlagEntry MFE = + static_cast(Entries[Index]); + return MFE.Metadata; +} + +LLVMMetadataRef LLVMGetModuleFlag(LLVMModuleRef M, + const char *Key, size_t KeyLen) { + return wrap(unwrap(M)->getModuleFlag({Key, KeyLen})); +} + +void LLVMAddModuleFlag(LLVMModuleRef M, LLVMModuleFlagBehavior Behavior, + const char *Key, size_t KeyLen, + LLVMMetadataRef Val) { + unwrap(M)->addModuleFlag(map_to_llvmModFlagBehavior(Behavior), + {Key, KeyLen}, unwrap(Val)); +} + +/*--.. Printing modules ....................................................--*/ + void LLVMDumpModule(LLVMModuleRef M) { unwrap(M)->print(errs(), nullptr, /*ShouldPreserveUseListOrder=*/false, /*IsForDebug=*/true); diff --git a/llvm/test/Bindings/llvm-c/echo.ll b/llvm/test/Bindings/llvm-c/echo.ll index 958aba0..071cbe89 100644 --- a/llvm/test/Bindings/llvm-c/echo.ll +++ b/llvm/test/Bindings/llvm-c/echo.ll @@ -159,3 +159,7 @@ cleanup: exit: ret void } + +!llvm.module.flags = !{!1} + +!1 = !{i32 2, !"Debug Info Version", i32 3} diff --git a/llvm/tools/llvm-c-test/echo.cpp b/llvm/tools/llvm-c-test/echo.cpp index 19ad5bd..fb7a4d7 100644 --- a/llvm/tools/llvm-c-test/echo.cpp +++ b/llvm/tools/llvm-c-test/echo.cpp @@ -997,6 +997,18 @@ int llvm_echo(void) { LLVMSetSourceFileName(M, SourceFileName, SourceFileLen); LLVMSetModuleIdentifier(M, ModuleName, ModuleIdentLen); + size_t SourceFlagsLen; + LLVMModuleFlagEntry *ModuleFlags = + LLVMCopyModuleFlagsMetadata(Src, &SourceFlagsLen); + for (unsigned i = 0; i < SourceFlagsLen; ++i) { + size_t EntryNameLen; + const char *EntryName = + LLVMModuleFlagEntriesGetKey(ModuleFlags, i, &EntryNameLen); + LLVMAddModuleFlag(M, LLVMModuleFlagEntriesGetFlagBehavior(ModuleFlags, i), + EntryName, EntryNameLen, + LLVMModuleFlagEntriesGetMetadata(ModuleFlags, i)); + } + LLVMSetTarget(M, LLVMGetTarget(Src)); LLVMSetModuleDataLayout(M, LLVMGetModuleDataLayout(Src)); if (strcmp(LLVMGetDataLayoutStr(M), LLVMGetDataLayoutStr(Src))) @@ -1011,6 +1023,7 @@ int llvm_echo(void) { char *Str = LLVMPrintModuleToString(M); fputs(Str, stdout); + LLVMDisposeModuleFlagsMetadata(ModuleFlags); LLVMDisposeMessage(Str); LLVMDisposeModule(Src); LLVMDisposeModule(M); -- 2.7.4