summaryrefslogtreecommitdiff
path: root/gnu/llvm/tools
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/llvm/tools')
-rw-r--r--gnu/llvm/tools/clang/include/clang/Driver/CC1Options.td247
-rw-r--r--gnu/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def163
-rw-r--r--gnu/llvm/tools/clang/lib/CodeGen/CGCall.cpp1540
-rw-r--r--gnu/llvm/tools/clang/lib/Driver/ToolChains/Clang.cpp7
-rw-r--r--gnu/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp1445
5 files changed, 2529 insertions, 873 deletions
diff --git a/gnu/llvm/tools/clang/include/clang/Driver/CC1Options.td b/gnu/llvm/tools/clang/include/clang/Driver/CC1Options.td
index 051f9033756..f19b2c3f277 100644
--- a/gnu/llvm/tools/clang/include/clang/Driver/CC1Options.td
+++ b/gnu/llvm/tools/clang/include/clang/Driver/CC1Options.td
@@ -70,7 +70,7 @@ def analyzer_opt_analyze_nested_blocks : Flag<["-"], "analyzer-opt-analyze-neste
def analyzer_display_progress : Flag<["-"], "analyzer-display-progress">,
HelpText<"Emit verbose output about the analyzer's progress">;
def analyze_function : Separate<["-"], "analyze-function">,
- HelpText<"Run analysis on specific function">;
+ HelpText<"Run analysis on specific function (for C++ include parameters in name)">;
def analyze_function_EQ : Joined<["-"], "analyze-function=">, Alias<analyze_function>;
def analyzer_eagerly_assume : Flag<["-"], "analyzer-eagerly-assume">,
HelpText<"Eagerly assume the truth/falseness of some symbolic constraints">;
@@ -99,7 +99,19 @@ def analyzer_stats : Flag<["-"], "analyzer-stats">,
HelpText<"Print internal analyzer statistics.">;
def analyzer_checker : Separate<["-"], "analyzer-checker">,
- HelpText<"Choose analyzer checkers to enable">;
+ HelpText<"Choose analyzer checkers to enable">,
+ ValuesCode<[{
+ const char *Values =
+ #define GET_CHECKERS
+ #define CHECKER(FULLNAME, CLASS, DESCFILE, HT, G, H) FULLNAME ","
+ #include "clang/StaticAnalyzer/Checkers/Checkers.inc"
+ #undef GET_CHECKERS
+ #define GET_PACKAGES
+ #define PACKAGE(FULLNAME, G, D) FULLNAME ","
+ #include "clang/StaticAnalyzer/Checkers/Checkers.inc"
+ #undef GET_PACKAGES
+ ;
+ }]>;
def analyzer_checker_EQ : Joined<["-"], "analyzer-checker=">,
Alias<analyzer_checker>;
@@ -114,6 +126,9 @@ def analyzer_disable_all_checks : Flag<["-"], "analyzer-disable-all-checks">,
def analyzer_checker_help : Flag<["-"], "analyzer-checker-help">,
HelpText<"Display the list of analyzer checkers that are available">;
+def analyzer_list_enabled_checkers : Flag<["-"], "analyzer-list-enabled-checkers">,
+ HelpText<"Display the list of enabled analyzer checkers">;
+
def analyzer_config : Separate<["-"], "analyzer-config">,
HelpText<"Choose analyzer options to enable">;
@@ -131,35 +146,47 @@ def migrator_no_finalize_removal : Flag<["-"], "no-finalize-removal">,
//===----------------------------------------------------------------------===//
let Flags = [CC1Option, CC1AsOption, NoDriverOption] in {
-
def debug_info_kind_EQ : Joined<["-"], "debug-info-kind=">;
+def debug_info_macro : Flag<["-"], "debug-info-macro">,
+ HelpText<"Emit macro debug information">;
def dwarf_version_EQ : Joined<["-"], "dwarf-version=">;
def debugger_tuning_EQ : Joined<["-"], "debugger-tuning=">;
def fdebug_compilation_dir : Separate<["-"], "fdebug-compilation-dir">,
HelpText<"The compilation directory to embed in the debug info.">;
def dwarf_debug_flags : Separate<["-"], "dwarf-debug-flags">,
HelpText<"The string to embed in the Dwarf debug flags record.">;
+def compress_debug_sections : Flag<["-", "--"], "compress-debug-sections">,
+ HelpText<"DWARF debug sections compression">;
+def compress_debug_sections_EQ : Joined<["-"], "compress-debug-sections=">,
+ HelpText<"DWARF debug sections compression type">;
def mno_exec_stack : Flag<["-"], "mnoexecstack">,
HelpText<"Mark the file as not needing an executable stack">;
def massembler_fatal_warnings : Flag<["-"], "massembler-fatal-warnings">,
HelpText<"Make assembler warnings fatal">;
-def compress_debug_sections : Flag<["-"], "compress-debug-sections">,
- HelpText<"Compress DWARF debug sections using zlib">;
+def mrelax_relocations : Flag<["--"], "mrelax-relocations">,
+ HelpText<"Use relaxable elf relocations">;
def msave_temp_labels : Flag<["-"], "msave-temp-labels">,
HelpText<"Save temporary labels in the symbol table. "
"Note this may change .s semantics and shouldn't generally be used "
"on compiler-generated code.">;
def mrelocation_model : Separate<["-"], "mrelocation-model">,
- HelpText<"The relocation model to use">;
+ HelpText<"The relocation model to use">, Values<"static,pic,ropi,rwpi,ropi-rwpi,dynamic-no-pic">;
+def fno_math_builtin : Flag<["-"], "fno-math-builtin">,
+ HelpText<"Disable implicit builtin knowledge of math functions">;
}
-def disable_llvm_optzns : Flag<["-"], "disable-llvm-optzns">,
- HelpText<"Don't run LLVM optimization passes">;
def disable_llvm_verifier : Flag<["-"], "disable-llvm-verifier">,
HelpText<"Don't run the LLVM IR verifier pass">;
def disable_llvm_passes : Flag<["-"], "disable-llvm-passes">,
HelpText<"Use together with -emit-llvm to get pristine LLVM IR from the "
"frontend by not running any LLVM passes at all">;
+def disable_llvm_optzns : Flag<["-"], "disable-llvm-optzns">,
+ Alias<disable_llvm_passes>;
+def disable_lifetimemarkers : Flag<["-"], "disable-lifetime-markers">,
+ HelpText<"Disable lifetime-markers emission even when optimizations are "
+ "enabled">;
+def disable_O0_optnone : Flag<["-"], "disable-O0-optnone">,
+ HelpText<"Disable adding the optnone attribute to functions at O0">;
def disable_red_zone : Flag<["-"], "disable-red-zone">,
HelpText<"Do not emit code that uses the red zone.">;
def dwarf_column_info : Flag<["-"], "dwarf-column-info">,
@@ -173,6 +200,12 @@ def arange_sections : Flag<["-"], "arange_sections">,
def dwarf_ext_refs : Flag<["-"], "dwarf-ext-refs">,
HelpText<"Generate debug info with external references to clang modules"
" or precompiled headers">;
+def dwarf_explicit_import : Flag<["-"], "dwarf-explicit-import">,
+ HelpText<"Generate explicit import from anonymous namespace to containing"
+ " scope">;
+def debug_forward_template_params : Flag<["-"], "debug-forward-template-params">,
+ HelpText<"Emit complete descriptions of template parameters in forward"
+ " declarations">;
def fforbid_guard_variables : Flag<["-"], "fforbid-guard-variables">,
HelpText<"Emit an error if a C++ static local initializer would need a guard variable">;
def no_implicit_float : Flag<["-"], "no-implicit-float">,
@@ -185,9 +218,14 @@ def femit_coverage_notes : Flag<["-"], "femit-coverage-notes">,
HelpText<"Emit a gcov coverage notes file when compiling.">;
def femit_coverage_data: Flag<["-"], "femit-coverage-data">,
HelpText<"Instrument the program to emit gcov coverage data when run.">;
-def coverage_file : Separate<["-"], "coverage-file">,
- HelpText<"Emit coverage data to this filename. The extension will be replaced.">;
-def coverage_file_EQ : Joined<["-"], "coverage-file=">, Alias<coverage_file>;
+def coverage_data_file : Separate<["-"], "coverage-data-file">,
+ HelpText<"Emit coverage data to this filename.">;
+def coverage_data_file_EQ : Joined<["-"], "coverage-data-file=">,
+ Alias<coverage_data_file>;
+def coverage_notes_file : Separate<["-"], "coverage-notes-file">,
+ HelpText<"Emit coverage notes to this filename.">;
+def coverage_notes_file_EQ : Joined<["-"], "coverage-notes-file=">,
+ Alias<coverage_notes_file>;
def coverage_cfg_checksum : Flag<["-"], "coverage-cfg-checksum">,
HelpText<"Emit CFG checksum for functions in .gcno files.">;
def coverage_no_function_names_in_data : Flag<["-"], "coverage-no-function-names-in-data">,
@@ -206,10 +244,12 @@ def relaxed_aliasing : Flag<["-"], "relaxed-aliasing">,
HelpText<"Turn off Type Based Alias Analysis">;
def no_struct_path_tbaa : Flag<["-"], "no-struct-path-tbaa">,
HelpText<"Turn off struct-path aware Type Based Alias Analysis">;
+def new_struct_path_tbaa : Flag<["-"], "new-struct-path-tbaa">,
+ HelpText<"Enable enhanced struct-path aware Type Based Alias Analysis">;
def masm_verbose : Flag<["-"], "masm-verbose">,
HelpText<"Generate verbose assembly output">;
def mcode_model : Separate<["-"], "mcode-model">,
- HelpText<"The code model to use">;
+ HelpText<"The code model to use">, Values<"small,kernel,medium,large">;
def mdebug_pass : Separate<["-"], "mdebug-pass">,
HelpText<"Enable additional debug output">;
def mdisable_fp_elim : Flag<["-"], "mdisable-fp-elim">,
@@ -223,8 +263,12 @@ def menable_no_nans : Flag<["-"], "menable-no-nans">,
def menable_unsafe_fp_math : Flag<["-"], "menable-unsafe-fp-math">,
HelpText<"Allow unsafe floating-point math optimizations which may decrease "
"precision">;
+def mreassociate : Flag<["-"], "mreassociate">,
+ HelpText<"Allow reassociation transformations for floating-point instructions">;
def mfloat_abi : Separate<["-"], "mfloat-abi">,
HelpText<"The float ABI to use">;
+def mtp : Separate<["-"], "mtp">,
+ HelpText<"Mode for reading thread pointer">;
def mlimit_float_precision : Separate<["-"], "mlimit-float-precision">,
HelpText<"Limit float precision to the given value">;
def split_stacks : Flag<["-"], "split-stacks">,
@@ -248,10 +292,10 @@ def vectorize_loops : Flag<["-"], "vectorize-loops">,
HelpText<"Run the Loop vectorization passes">;
def vectorize_slp : Flag<["-"], "vectorize-slp">,
HelpText<"Run the SLP vectorization passes">;
-def vectorize_slp_aggressive : Flag<["-"], "vectorize-slp-aggressive">,
- HelpText<"Run the BB vectorization passes">;
def dependent_lib : Joined<["--"], "dependent-lib=">,
HelpText<"Add dependent library">;
+def linker_option : Joined<["--"], "linker-option=">,
+ HelpText<"Add linker option">;
def fsanitize_coverage_type : Joined<["-"], "fsanitize-coverage-type=">,
HelpText<"Sanitizer coverage type">;
def fsanitize_coverage_indirect_calls
@@ -263,9 +307,54 @@ def fsanitize_coverage_trace_bb
def fsanitize_coverage_trace_cmp
: Flag<["-"], "fsanitize-coverage-trace-cmp">,
HelpText<"Enable cmp instruction tracing in sanitizer coverage">;
+def fsanitize_coverage_trace_div
+ : Flag<["-"], "fsanitize-coverage-trace-div">,
+ HelpText<"Enable div instruction tracing in sanitizer coverage">;
+def fsanitize_coverage_trace_gep
+ : Flag<["-"], "fsanitize-coverage-trace-gep">,
+ HelpText<"Enable gep instruction tracing in sanitizer coverage">;
def fsanitize_coverage_8bit_counters
: Flag<["-"], "fsanitize-coverage-8bit-counters">,
HelpText<"Enable frequency counters in sanitizer coverage">;
+def fsanitize_coverage_inline_8bit_counters
+ : Flag<["-"], "fsanitize-coverage-inline-8bit-counters">,
+ HelpText<"Enable inline 8-bit counters in sanitizer coverage">;
+def fsanitize_coverage_pc_table
+ : Flag<["-"], "fsanitize-coverage-pc-table">,
+ HelpText<"Create a table of coverage-instrumented PCs">;
+def fsanitize_coverage_trace_pc
+ : Flag<["-"], "fsanitize-coverage-trace-pc">,
+ HelpText<"Enable PC tracing in sanitizer coverage">;
+def fsanitize_coverage_trace_pc_guard
+ : Flag<["-"], "fsanitize-coverage-trace-pc-guard">,
+ HelpText<"Enable PC tracing with guard in sanitizer coverage">;
+def fsanitize_coverage_no_prune
+ : Flag<["-"], "fsanitize-coverage-no-prune">,
+ HelpText<"Disable coverage pruning (i.e. instrument all blocks/edges)">;
+def fsanitize_coverage_stack_depth
+ : Flag<["-"], "fsanitize-coverage-stack-depth">,
+ HelpText<"Enable max stack depth tracing">;
+def fprofile_instrument_EQ : Joined<["-"], "fprofile-instrument=">,
+ HelpText<"Enable PGO instrumentation. The accepted value is clang, llvm, "
+ "or none">, Values<"none,clang,llvm">;
+def fprofile_instrument_path_EQ : Joined<["-"], "fprofile-instrument-path=">,
+ HelpText<"Generate instrumented code to collect execution counts into "
+ "<file> (overridden by LLVM_PROFILE_FILE env var)">;
+def fprofile_instrument_use_path_EQ :
+ Joined<["-"], "fprofile-instrument-use-path=">,
+ HelpText<"Specify the profile path in PGO use compilation">;
+def flto_visibility_public_std:
+ Flag<["-"], "flto-visibility-public-std">,
+ HelpText<"Use public LTO visibility for classes in std and stdext namespaces">;
+def flto_unit: Flag<["-"], "flto-unit">,
+ HelpText<"Emit IR to support LTO unit features (CFI, whole program vtable opt)">;
+def fno_lto_unit: Flag<["-"], "fno-lto-unit">;
+def fthin_link_bitcode_EQ : Joined<["-"], "fthin-link-bitcode=">,
+ HelpText<"Write minimized bitcode to <file> for the ThinLTO thin link only">;
+def fdebug_pass_manager : Flag<["-"], "fdebug-pass-manager">,
+ HelpText<"Prints debug information for the new pass manager">;
+def fno_debug_pass_manager : Flag<["-"], "fno-debug-pass-manager">,
+ HelpText<"Disables debug printing for the new pass manager">;
//===----------------------------------------------------------------------===//
// Dependency Output Options
@@ -291,9 +380,9 @@ def diagnostic_serialized_file : Separate<["-"], "serialize-diagnostic-file">,
HelpText<"File for serializing diagnostics in a binary format">;
def fdiagnostics_format : Separate<["-"], "fdiagnostics-format">,
- HelpText<"Change diagnostic formatting to match IDE and command line tools">;
+ HelpText<"Change diagnostic formatting to match IDE and command line tools">, Values<"clang,msvc,msvc-fallback,vi">;
def fdiagnostics_show_category : Separate<["-"], "fdiagnostics-show-category">,
- HelpText<"Print diagnostic category">;
+ HelpText<"Print diagnostic category">, Values<"none,id,name">;
def fno_diagnostics_use_presumed_location : Flag<["-"], "fno-diagnostics-use-presumed-location">,
HelpText<"Ignore #line directives when displaying diagnostic locations">;
def ftabstop : Separate<["-"], "ftabstop">, MetaVarName<"<N>">,
@@ -308,10 +397,17 @@ def fconstexpr_backtrace_limit : Separate<["-"], "fconstexpr-backtrace-limit">,
HelpText<"Set the maximum number of entries to print in a constexpr evaluation backtrace (0 = no limit).">;
def fspell_checking_limit : Separate<["-"], "fspell-checking-limit">, MetaVarName<"<N>">,
HelpText<"Set the maximum number of times to perform spell checking on unrecognized identifiers (0 = no limit).">;
+def fcaret_diagnostics_max_lines :
+ Separate<["-"], "fcaret-diagnostics-max-lines">, MetaVarName<"<N>">,
+ HelpText<"Set the maximum number of source lines to show in a caret diagnostic">;
def fmessage_length : Separate<["-"], "fmessage-length">, MetaVarName<"<N>">,
HelpText<"Format message diagnostics so that they fit within N columns or fewer, when possible.">;
+def verify_EQ : CommaJoined<["-"], "verify=">,
+ MetaVarName<"<prefixes>">,
+ HelpText<"Verify diagnostic output using comment directives that start with"
+ " prefixes in the comma-separated sequence <prefixes>">;
def verify : Flag<["-"], "verify">,
- HelpText<"Verify diagnostic output using comment directives">;
+ HelpText<"Equivalent to -verify=expected">;
def verify_ignore_unexpected : Flag<["-"], "verify-ignore-unexpected">,
HelpText<"Ignore unexpected diagnostic messages">;
def verify_ignore_unexpected_EQ : CommaJoined<["-"], "verify-ignore-unexpected=">,
@@ -347,10 +443,14 @@ def code_completion_patterns : Flag<["-"], "code-completion-patterns">,
HelpText<"Include code patterns in code-completion results">;
def no_code_completion_globals : Flag<["-"], "no-code-completion-globals">,
HelpText<"Do not include global declarations in code-completion results.">;
+def no_code_completion_ns_level_decls : Flag<["-"], "no-code-completion-ns-level-decls">,
+ HelpText<"Do not include declarations inside namespaces (incl. global namespace) in the code-completion results.">;
def code_completion_brief_comments : Flag<["-"], "code-completion-brief-comments">,
HelpText<"Include brief documentation comments in code-completion results.">;
def disable_free : Flag<["-"], "disable-free">,
HelpText<"Disable freeing of memory on exit">;
+def discard_value_names : Flag<["-"], "discard-value-names">,
+ HelpText<"Discard value names in LLVM IR">;
def load : Separate<["-"], "load">, MetaVarName<"<dsopath>">,
HelpText<"Load the named plugin (dynamic shared object)">;
def plugin : Separate<["-"], "plugin">, MetaVarName<"<name>">,
@@ -369,9 +469,6 @@ def fno_modules_global_index : Flag<["-"], "fno-modules-global-index">,
HelpText<"Do not automatically generate or update the global module index">;
def fno_modules_error_recovery : Flag<["-"], "fno-modules-error-recovery">,
HelpText<"Do not automatically import modules for error recovery">;
-def fmodule_implementation_of : Separate<["-"], "fmodule-implementation-of">,
- MetaVarName<"<name>">,
- HelpText<"Specify the name of the module whose implementation file this is">;
def fmodule_map_file_home_is_cwd : Flag<["-"], "fmodule-map-file-home-is-cwd">,
HelpText<"Use the current working directory as the home directory of "
"module maps specified by -fmodule-map-file=<FILE>">;
@@ -389,6 +486,14 @@ def fmodules_local_submodule_visibility :
Flag<["-"], "fmodules-local-submodule-visibility">,
HelpText<"Enforce name visibility rules across submodules of the same "
"top-level module.">;
+def fmodules_codegen :
+ Flag<["-"], "fmodules-codegen">,
+ HelpText<"Generate code for uses of this module that assumes an explicit "
+ "object file will be built for the module">;
+def fmodules_debuginfo :
+ Flag<["-"], "fmodules-debuginfo">,
+ HelpText<"Generate debug info for types in an object file built from this "
+ "module and do not generate them elsewhere">;
def fmodule_format_EQ : Joined<["-"], "fmodule-format=">,
HelpText<"Select the container format for clang modules and PCH. "
"Supported options are 'raw' and 'obj'.">;
@@ -426,6 +531,8 @@ def ast_list : Flag<["-"], "ast-list">,
HelpText<"Build ASTs and print the list of declaration node qualified names">;
def ast_dump : Flag<["-"], "ast-dump">,
HelpText<"Build ASTs and then debug dump them">;
+def ast_dump_all : Flag<["-"], "ast-dump-all">,
+ HelpText<"Build ASTs and then debug dump them, forcing deserialization">;
def ast_dump_lookups : Flag<["-"], "ast-dump-lookups">,
HelpText<"Build ASTs and then debug dump their name lookup tables">;
def ast_view : Flag<["-"], "ast-view">,
@@ -434,6 +541,8 @@ def print_decl_contexts : Flag<["-"], "print-decl-contexts">,
HelpText<"Print DeclContexts and their Decls">;
def emit_module : Flag<["-"], "emit-module">,
HelpText<"Generate pre-compiled module file from a module map">;
+def emit_module_interface : Flag<["-"], "emit-module-interface">,
+ HelpText<"Generate pre-compiled module file from a C++ module interface">;
def emit_pth : Flag<["-"], "emit-pth">,
HelpText<"Generate pre-tokenized header file">;
def emit_pch : Flag<["-"], "emit-pch">,
@@ -468,8 +577,13 @@ def arcmt_modify : Flag<["-"], "arcmt-modify">,
def arcmt_migrate : Flag<["-"], "arcmt-migrate">,
HelpText<"Apply modifications and produces temporary files that conform to ARC">;
+def opt_record_file : Separate<["-"], "opt-record-file">,
+ HelpText<"File name to use for YAML optimization record output">;
+
def print_stats : Flag<["-"], "print-stats">,
HelpText<"Print performance metrics and statistics">;
+def stats_file : Joined<["-"], "stats-file=">,
+ HelpText<"Filename to write statistics to">;
def fdump_record_layouts : Flag<["-"], "fdump-record-layouts">,
HelpText<"Dump record layout information">;
def fdump_record_layouts_simple : Flag<["-"], "fdump-record-layouts-simple">,
@@ -485,7 +599,16 @@ def fixit_to_temp : Flag<["-"], "fixit-to-temporary">,
def foverride_record_layout_EQ : Joined<["-"], "foverride-record-layout=">,
HelpText<"Override record layouts with those in the given file">;
+def find_pch_source_EQ : Joined<["-"], "find-pch-source=">,
+ HelpText<"When building a pch, try to find the input file in include "
+ "directories, as if it had been included by the argument passed "
+ "to this flag.">;
+def fno_pch_timestamp : Flag<["-"], "fno-pch-timestamp">,
+ HelpText<"Disable inclusion of timestamp in precompiled headers">;
+def aligned_alloc_unavailable : Flag<["-"], "faligned-alloc-unavailable">,
+ HelpText<"Aligned allocation/deallocation functions are unavailable">;
+
//===----------------------------------------------------------------------===//
// Language Options
//===----------------------------------------------------------------------===//
@@ -501,10 +624,10 @@ def main_file_name : Separate<["-"], "main-file-name">,
def fblocks_runtime_optional : Flag<["-"], "fblocks-runtime-optional">,
HelpText<"Weakly link in the blocks runtime">;
-def fsjlj_exceptions : Flag<["-"], "fsjlj-exceptions">,
- HelpText<"Use SjLj style exceptions">;
-def fnew_ms_eh: Flag<["-"], "fnew-ms-eh">,
- HelpText<"Use the new IR representation for MS exceptions">;
+def fexternc_nounwind : Flag<["-"], "fexternc-nounwind">,
+ HelpText<"Assume all functions with C linkage do not unwind">;
+def enable_split_dwarf : Flag<["-"], "enable-split-dwarf">,
+ HelpText<"Use split dwarf/Fission">;
def split_dwarf_file : Separate<["-"], "split-dwarf-file">,
HelpText<"File name to use for split dwarf debug info output">;
def fno_wchar : Flag<["-"], "fno-wchar">,
@@ -513,21 +636,23 @@ def fconstant_string_class : Separate<["-"], "fconstant-string-class">,
MetaVarName<"<class name>">,
HelpText<"Specify the class to use for constant Objective-C string objects.">;
def fobjc_arc_cxxlib_EQ : Joined<["-"], "fobjc-arc-cxxlib=">,
- HelpText<"Objective-C++ Automatic Reference Counting standard library kind">;
+ HelpText<"Objective-C++ Automatic Reference Counting standard library kind">, Values<"libc++,libstdc++,none">;
def fobjc_runtime_has_weak : Flag<["-"], "fobjc-runtime-has-weak">,
HelpText<"The target Objective-C runtime supports ARC weak operations">;
def fobjc_dispatch_method_EQ : Joined<["-"], "fobjc-dispatch-method=">,
- HelpText<"Objective-C dispatch method to use">;
+ HelpText<"Objective-C dispatch method to use">, Values<"legacy,non-legacy,mixed">;
def disable_objc_default_synthesize_properties : Flag<["-"], "disable-objc-default-synthesize-properties">,
HelpText<"disable the default synthesis of Objective-C properties">;
def fencode_extended_block_signature : Flag<["-"], "fencode-extended-block-signature">,
HelpText<"enable extended encoding of block type signature">;
def pic_level : Separate<["-"], "pic-level">,
HelpText<"Value for __PIC__">;
-def pie_level : Separate<["-"], "pie-level">,
- HelpText<"Value for __PIE__">;
+def pic_is_pie : Flag<["-"], "pic-is-pie">,
+ HelpText<"File is for a position independent executable">;
def fno_validate_pch : Flag<["-"], "fno-validate-pch">,
HelpText<"Disable validation of precompiled headers">;
+def fallow_pch_with_errors : Flag<["-"], "fallow-pch-with-compiler-errors">,
+ HelpText<"Accept a PCH file that was created with compiler errors">;
def dump_deserialized_pch_decls : Flag<["-"], "dump-deserialized-decls">,
HelpText<"Dump declarations that are deserialized from PCH, for testing">;
def error_on_deserialized_pch_decl : Separate<["-"], "error-on-deserialized-decl">,
@@ -540,6 +665,8 @@ def stack_protector : Separate<["-"], "stack-protector">,
HelpText<"Enable stack protectors">;
def stack_protector_buffer_size : Separate<["-"], "stack-protector-buffer-size">,
HelpText<"Lower bound for a buffer to be considered for stack protection">;
+def ret_protector : Flag<["-"], "ret-protector">,
+ HelpText<"Enable Return Protectors">;
def fvisibility : Separate<["-"], "fvisibility">,
HelpText<"Default type and symbol visibility">;
def ftype_visibility : Separate<["-"], "ftype-visibility">,
@@ -584,12 +711,28 @@ def fno_rtti_data : Flag<["-"], "fno-rtti-data">,
HelpText<"Control emission of RTTI data">;
def fnative_half_type: Flag<["-"], "fnative-half-type">,
HelpText<"Use the native half type for __fp16 instead of promoting to float">;
+def fnative_half_arguments_and_returns : Flag<["-"], "fnative-half-arguments-and-returns">,
+ HelpText<"Use the native __fp16 type for arguments and returns (and skip ABI-specific lowering)">;
def fallow_half_arguments_and_returns : Flag<["-"], "fallow-half-arguments-and-returns">,
HelpText<"Allow function arguments and returns of type half">;
-
-// C++ TSes.
-def fcoroutines : Flag<["-"], "fcoroutines">,
- HelpText<"Enable support for the C++ Coroutines TS">;
+def fdefault_calling_conv_EQ : Joined<["-"], "fdefault-calling-conv=">,
+ HelpText<"Set default calling convention">, Values<"cdecl,fastcall,stdcall,vectorcall,regcall">;
+def finclude_default_header : Flag<["-"], "finclude-default-header">,
+ HelpText<"Include the default header file for OpenCL">;
+def fpreserve_vec3_type : Flag<["-"], "fpreserve-vec3-type">,
+ HelpText<"Preserve 3-component vector type">;
+def fwchar_type_EQ : Joined<["-"], "fwchar-type=">,
+ HelpText<"Select underlying type for wchar_t">, Values<"char,short,int">;
+def fsigned_wchar : Flag<["-"], "fsigned-wchar">,
+ HelpText<"Use a signed type for wchar_t">;
+def fno_signed_wchar : Flag<["-"], "fno-signed-wchar">,
+ HelpText<"Use an unsigned type for wchar_t">;
+
+// FIXME: Remove these entirely once functionality/tests have been excised.
+def fobjc_gc_only : Flag<["-"], "fobjc-gc-only">, Group<f_Group>,
+ HelpText<"Use GC exclusively for Objective-C related memory management">;
+def fobjc_gc : Flag<["-"], "fobjc-gc">, Group<f_Group>,
+ HelpText<"Enable Objective-C garbage collection">;
//===----------------------------------------------------------------------===//
// Header Search Options
@@ -599,6 +742,8 @@ def nostdsysteminc : Flag<["-"], "nostdsysteminc">,
HelpText<"Disable standard system #include directories">;
def fdisable_module_hash : Flag<["-"], "fdisable-module-hash">,
HelpText<"Disable the module hash">;
+def fmodules_hash_content : Flag<["-"], "fmodules-hash-content">,
+ HelpText<"Enable hashing the content of a module file">;
def c_isystem : JoinedOrSeparate<["-"], "c-isystem">, MetaVarName<"<directory>">,
HelpText<"Add directory to the C SYSTEM include search path">;
def objc_isystem : JoinedOrSeparate<["-"], "objc-isystem">,
@@ -639,26 +784,8 @@ def detailed_preprocessing_record : Flag<["-"], "detailed-preprocessing-record">
// OpenCL Options
//===----------------------------------------------------------------------===//
-def cl_opt_disable : Flag<["-"], "cl-opt-disable">,
- HelpText<"OpenCL only. This option disables all optimizations. The default is optimizations are enabled.">;
-def cl_strict_aliasing : Flag<["-"], "cl-strict-aliasing">,
- HelpText<"OpenCL only. This option does nothing and is for compatibility with OpenCL 1.0">;
-def cl_single_precision_constant : Flag<["-"], "cl-single-precision-constant">,
- HelpText<"OpenCL only. Treat double precision floating-point constant as single precision constant.">;
-def cl_finite_math_only : Flag<["-"], "cl-finite-math-only">,
- HelpText<"OpenCL only. Allow floating-point optimizations that assume arguments and results are not NaNs or +-Inf.">;
-def cl_kernel_arg_info : Flag<["-"], "cl-kernel-arg-info">,
- HelpText<"OpenCL only. Generate kernel argument metadata.">;
-def cl_unsafe_math_optimizations : Flag<["-"], "cl-unsafe-math-optimizations">,
- HelpText<"OpenCL only. Allow unsafe floating-point optimizations. Also implies -cl-no-signed-zeros and -cl-mad-enable">;
-def cl_fast_relaxed_math : Flag<["-"], "cl-fast-relaxed-math">,
- HelpText<"OpenCL only. Sets -cl-finite-math-only and -cl-unsafe-math-optimizations, and defines __FAST_RELAXED_MATH__">;
-def cl_mad_enable : Flag<["-"], "cl-mad-enable">,
- HelpText<"OpenCL only. Enable less precise MAD instructions to be generated.">;
-def cl_std_EQ : Joined<["-"], "cl-std=">,
- HelpText<"OpenCL language standard to compile for">;
-def cl_denorms_are_zero : Flag<["-"], "cl-denorms-are-zero">,
- HelpText<"OpenCL only. Allow denormals to be flushed to zero">;
+def cl_ext_EQ : CommaJoined<["-"], "cl-ext=">,
+ HelpText<"OpenCL only. Enable or disable OpenCL extensions. The argument is a comma-separated sequence of one or more extension names, each prefixed by '+' or '-'.">;
//===----------------------------------------------------------------------===//
// CUDA Options
@@ -666,16 +793,12 @@ def cl_denorms_are_zero : Flag<["-"], "cl-denorms-are-zero">,
def fcuda_is_device : Flag<["-"], "fcuda-is-device">,
HelpText<"Generate code for CUDA device">;
-def fcuda_allow_host_calls_from_host_device : Flag<["-"],
- "fcuda-allow-host-calls-from-host-device">,
- HelpText<"Allow host device functions to call host functions">;
-def fcuda_disable_target_call_checks : Flag<["-"],
- "fcuda-disable-target-call-checks">,
- HelpText<"Disable all cross-target (host, device, etc.) call checks in CUDA">;
def fcuda_include_gpubinary : Separate<["-"], "fcuda-include-gpubinary">,
HelpText<"Incorporate CUDA device-side binary into host object file.">;
-def fcuda_target_overloads : Flag<["-"], "fcuda-target-overloads">,
- HelpText<"Enable function overloads based on CUDA target attributes.">;
+def fcuda_allow_variadic_functions : Flag<["-"], "fcuda-allow-variadic-functions">,
+ HelpText<"Allow variadic functions in CUDA device code.">;
+def fno_cuda_host_device_constexpr : Flag<["-"], "fno-cuda-host-device-constexpr">,
+ HelpText<"Don't treat unattributed constexpr functions as __host__ __device__.">;
//===----------------------------------------------------------------------===//
// OpenMP Options
@@ -683,7 +806,7 @@ def fcuda_target_overloads : Flag<["-"], "fcuda-target-overloads">,
def fopenmp_is_device : Flag<["-"], "fopenmp-is-device">,
HelpText<"Generate code only for an OpenMP target device.">;
-def omp_host_ir_file_path : Separate<["-"], "omp-host-ir-file-path">,
+def fopenmp_host_ir_file_path : Separate<["-"], "fopenmp-host-ir-file-path">,
HelpText<"Path to the IR file produced by the frontend for the host.">;
} // let Flags = [CC1Option]
@@ -715,4 +838,6 @@ def show_inst : Flag<["-"], "show-inst">,
def dwarf_debug_producer : Separate<["-"], "dwarf-debug-producer">,
HelpText<"The string to embed in the Dwarf debug AT_producer record.">;
+def defsym : Separate<["-"], "defsym">,
+ HelpText<"Define a value for a symbol">;
} // let Flags = [CC1AsOption]
diff --git a/gnu/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def b/gnu/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def
index d9f6ab7f42d..5c4b4c3aa84 100644
--- a/gnu/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def
+++ b/gnu/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def
@@ -1,4 +1,4 @@
-//===--- CodeGenOptions.def - Code generation option database ------ C++ -*-===//
+//===--- CodeGenOptions.def - Code generation option database ----- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -29,10 +29,15 @@ CODEGENOPT(Name, Bits, Default)
#endif
CODEGENOPT(DisableIntegratedAS, 1, 0) ///< -no-integrated-as
-CODEGENOPT(CompressDebugSections, 1, 0) ///< -Wa,-compress-debug-sections
-CODEGENOPT(Autolink , 1, 1) ///< -fno-autolink
+ENUM_CODEGENOPT(CompressDebugSections, llvm::DebugCompressionType, 2,
+ llvm::DebugCompressionType::None)
+CODEGENOPT(RelaxELFRelocations, 1, 0) ///< -Wa,--mrelax-relocations
CODEGENOPT(AsmVerbose , 1, 0) ///< -dA, -fverbose-asm.
+CODEGENOPT(PreserveAsmComments, 1, 1) ///< -dA, -fno-preserve-as-comments.
+CODEGENOPT(AssumeSaneOperatorNew , 1, 1) ///< implicit __attribute__((malloc)) operator new
+CODEGENOPT(Autolink , 1, 1) ///< -fno-autolink
CODEGENOPT(ObjCAutoRefCountExceptions , 1, 0) ///< Whether ARC should be EH-safe.
+CODEGENOPT(Backchain , 1, 0) ///< -mbackchain
CODEGENOPT(CoverageExtraChecksum, 1, 0) ///< Whether we need a second checksum for functions in GCNO files.
CODEGENOPT(CoverageNoFunctionNamesInData, 1, 0) ///< Do not include function names in GCDA files.
CODEGENOPT(CoverageExitBlockBeforeBody, 1, 0) ///< Whether to emit the exit block before the body blocks in GCNO files.
@@ -43,38 +48,59 @@ CODEGENOPT(DataSections , 1, 0) ///< Set when -fdata-sections is enabled.
CODEGENOPT(UniqueSectionNames, 1, 1) ///< Set for -funique-section-names.
CODEGENOPT(DisableFPElim , 1, 0) ///< Set when -fomit-frame-pointer is enabled.
CODEGENOPT(DisableFree , 1, 0) ///< Don't free memory.
+CODEGENOPT(DiscardValueNames , 1, 0) ///< Discard Value Names from the IR (LLVMContext flag)
CODEGENOPT(DisableGCov , 1, 0) ///< Don't run the GCov pass, for testing.
-CODEGENOPT(DisableLLVMOpts , 1, 0) ///< Don't run any optimizations, for use in
- ///< getting .bc files that correspond to the
- ///< internal state before optimizations are
- ///< done.
CODEGENOPT(DisableLLVMPasses , 1, 0) ///< Don't run any LLVM IR passes to get
///< the pristine IR generated by the
///< frontend.
+CODEGENOPT(DisableLifetimeMarkers, 1, 0) ///< Don't emit any lifetime markers
+CODEGENOPT(DisableO0ImplyOptNone , 1, 0) ///< Don't annonate function with optnone at O0
+CODEGENOPT(ExperimentalNewPassManager, 1, 0) ///< Enables the new, experimental
+ ///< pass manager.
+CODEGENOPT(DebugPassManager, 1, 0) ///< Prints debug information for the new
+ ///< pass manager.
CODEGENOPT(DisableRedZone , 1, 0) ///< Set when -mno-red-zone is enabled.
CODEGENOPT(DisableTailCalls , 1, 0) ///< Do not emit tail calls.
CODEGENOPT(EmitDeclMetadata , 1, 0) ///< Emit special metadata indicating what
- ///< Decl* various IR entities came from.
+ ///< Decl* various IR entities came from.
///< Only useful when running CodeGen as a
///< subroutine.
CODEGENOPT(EmitGcovArcs , 1, 0) ///< Emit coverage data files, aka. GCDA.
CODEGENOPT(EmitGcovNotes , 1, 0) ///< Emit coverage "notes" files, aka GCNO.
CODEGENOPT(EmitOpenCLArgMetadata , 1, 0) ///< Emit OpenCL kernel arg metadata.
CODEGENOPT(EmulatedTLS , 1, 0) ///< Set when -femulated-tls is enabled.
-/// \brief FP_CONTRACT mode (on/off/fast).
-ENUM_CODEGENOPT(FPContractMode, FPContractModeKind, 2, FPC_On)
+/// \brief Embed Bitcode mode (off/all/bitcode/marker).
+ENUM_CODEGENOPT(EmbedBitcode, EmbedBitcodeKind, 2, Embed_Off)
CODEGENOPT(ForbidGuardVariables , 1, 0) ///< Issue errors if C++ guard variables
///< are required.
CODEGENOPT(FunctionSections , 1, 0) ///< Set when -ffunction-sections is enabled.
CODEGENOPT(InstrumentFunctions , 1, 0) ///< Set when -finstrument-functions is
///< enabled.
+CODEGENOPT(InstrumentFunctionsAfterInlining , 1, 0) ///< Set when
+ ///< -finstrument-functions-after-inlining is enabled.
+CODEGENOPT(InstrumentFunctionEntryBare , 1, 0) ///< Set when
+ ///< -finstrument-function-entry-bare is enabled.
+
+CODEGENOPT(XRayInstrumentFunctions , 1, 0) ///< Set when -fxray-instrument is
+ ///< enabled.
+
+///< Set when -fxray-always-emit-customevents is enabled.
+CODEGENOPT(XRayAlwaysEmitCustomEvents , 1, 0)
+
+///< Set the minimum number of instructions in a function to determine selective
+///< XRay instrumentation.
+VALUE_CODEGENOPT(XRayInstructionThreshold , 32, 200)
+
CODEGENOPT(InstrumentForProfiling , 1, 0) ///< Set when -pg is enabled.
+CODEGENOPT(CallFEntry , 1, 0) ///< Set when -mfentry is enabled.
CODEGENOPT(LessPreciseFPMAD , 1, 0) ///< Enable less precise MAD instructions to
///< be generated.
CODEGENOPT(PrepareForLTO , 1, 0) ///< Set when -flto is enabled on the
///< compile step.
-CODEGENOPT(EmitFunctionSummary, 1, 0) ///< Set when -flto=thin is enabled on the
- ///< compile step.
+CODEGENOPT(EmitSummaryIndex, 1, 0) ///< Set when -flto=thin is enabled on the
+ ///< compile step.
+CODEGENOPT(LTOUnit, 1, 0) ///< Emit IR to support LTO unit features (CFI, whole
+ ///< program vtable opt).
CODEGENOPT(IncrementalLinkerCompatible, 1, 0) ///< Emit an object file which can
///< be used with an incremental
///< linker.
@@ -91,20 +117,28 @@ CODEGENOPT(EnableSegmentedStacks , 1, 0) ///< Set when -fsplit-stack is enabled.
CODEGENOPT(NoImplicitFloat , 1, 0) ///< Set when -mno-implicit-float is enabled.
CODEGENOPT(NoInfsFPMath , 1, 0) ///< Assume FP arguments, results not +-Inf.
CODEGENOPT(NoSignedZeros , 1, 0) ///< Allow ignoring the signedness of FP zero
+CODEGENOPT(Reassociate , 1, 0) ///< Allow reassociation of FP math ops
CODEGENOPT(ReciprocalMath , 1, 0) ///< Allow FP divisions to be reassociated.
-CODEGENOPT(NoInline , 1, 0) ///< Set when -fno-inline is enabled.
- ///< Disables use of the inline keyword.
+CODEGENOPT(NoTrappingMath , 1, 0) ///< Set when -fno-trapping-math is enabled.
CODEGENOPT(NoNaNsFPMath , 1, 0) ///< Assume FP arguments, results not NaN.
+CODEGENOPT(FlushDenorm , 1, 0) ///< Allow FP denorm numbers to be flushed to zero
+CODEGENOPT(CorrectlyRoundedDivSqrt, 1, 0) ///< -cl-fp32-correctly-rounded-divide-sqrt
CODEGENOPT(NoZeroInitializedInBSS , 1, 0) ///< -fno-zero-initialized-in-bss.
/// \brief Method of Objective-C dispatch to use.
-ENUM_CODEGENOPT(ObjCDispatchMethod, ObjCDispatchMethodKind, 2, Legacy)
+ENUM_CODEGENOPT(ObjCDispatchMethod, ObjCDispatchMethodKind, 2, Legacy)
CODEGENOPT(OmitLeafFramePointer , 1, 0) ///< Set when -momit-leaf-frame-pointer is
///< enabled.
+
+/// A version of Clang that we should attempt to be ABI-compatible with.
+ENUM_CODEGENOPT(ClangABICompat, ClangABI, 4, ClangABI::Latest)
+
VALUE_CODEGENOPT(OptimizationLevel, 2, 0) ///< The -O[0-3] option specified.
VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is specified.
-CODEGENOPT(ProfileInstrGenerate , 1, 0) ///< Instrument code to generate
- ///< execution counts to use with PGO.
+/// \brief Choose profile instrumenation kind or no instrumentation.
+ENUM_CODEGENOPT(ProfileInstr, ProfileInstrKind, 2, ProfileNone)
+/// \brief Choose profile kind for PGO use compilation.
+ENUM_CODEGENOPT(ProfileUse, ProfileInstrKind, 2, ProfileNone)
CODEGENOPT(CoverageMapping , 1, 0) ///< Generate coverage mapping regions to
///< enable code coverage analysis.
CODEGENOPT(DumpCoverageMapping , 1, 0) ///< Dump the generated coverage mapping
@@ -116,14 +150,21 @@ ENUM_CODEGENOPT(StructReturnConvention, StructReturnConventionKind, 2, SRCK_Defa
CODEGENOPT(RelaxAll , 1, 0) ///< Relax all machine code instructions.
CODEGENOPT(RelaxedAliasing , 1, 0) ///< Set when -fno-strict-aliasing is enabled.
CODEGENOPT(StructPathTBAA , 1, 0) ///< Whether or not to use struct-path TBAA.
+CODEGENOPT(NewStructPathTBAA , 1, 0) ///< Whether or not to use enhanced struct-path TBAA.
CODEGENOPT(SaveTempLabels , 1, 0) ///< Save temporary labels.
-CODEGENOPT(SanitizeAddressZeroBaseShadow , 1, 0) ///< Map shadow memory at zero
- ///< offset in AddressSanitizer.
+CODEGENOPT(SanitizeAddressUseAfterScope , 1, 0) ///< Enable use-after-scope detection
+ ///< in AddressSanitizer
+CODEGENOPT(SanitizeAddressGlobalsDeadStripping, 1, 0) ///< Enable linker dead stripping
+ ///< of globals in AddressSanitizer
CODEGENOPT(SanitizeMemoryTrackOrigins, 2, 0) ///< Enable tracking origins in
///< MemorySanitizer
CODEGENOPT(SanitizeMemoryUseAfterDtor, 1, 0) ///< Enable use-after-delete detection
///< in MemorySanitizer
CODEGENOPT(SanitizeCfiCrossDso, 1, 0) ///< Enable cross-dso support in CFI.
+CODEGENOPT(SanitizeMinimalRuntime, 1, 0) ///< Use "_minimal" sanitizer runtime for
+ ///< diagnostics.
+CODEGENOPT(SanitizeCfiICallGeneralizePointers, 1, 0) ///< Generalize pointer types in
+ ///< CFI icall function signatures
CODEGENOPT(SanitizeCoverageType, 2, 0) ///< Type of sanitizer coverage
///< instrumentation.
CODEGENOPT(SanitizeCoverageIndirectCalls, 1, 0) ///< Enable sanitizer coverage
@@ -132,22 +173,35 @@ CODEGENOPT(SanitizeCoverageTraceBB, 1, 0) ///< Enable basic block tracing in
///< in sanitizer coverage.
CODEGENOPT(SanitizeCoverageTraceCmp, 1, 0) ///< Enable cmp instruction tracing
///< in sanitizer coverage.
+CODEGENOPT(SanitizeCoverageTraceDiv, 1, 0) ///< Enable div instruction tracing
+ ///< in sanitizer coverage.
+CODEGENOPT(SanitizeCoverageTraceGep, 1, 0) ///< Enable GEP instruction tracing
+ ///< in sanitizer coverage.
CODEGENOPT(SanitizeCoverage8bitCounters, 1, 0) ///< Use 8-bit frequency counters
///< in sanitizer coverage.
+CODEGENOPT(SanitizeCoverageTracePC, 1, 0) ///< Enable PC tracing
+ ///< in sanitizer coverage.
+CODEGENOPT(SanitizeCoverageTracePCGuard, 1, 0) ///< Enable PC tracing with guard
+ ///< in sanitizer coverage.
+CODEGENOPT(SanitizeCoverageInline8bitCounters, 1, 0) ///< Use inline 8bit counters.
+CODEGENOPT(SanitizeCoveragePCTable, 1, 0) ///< Create a PC Table.
+CODEGENOPT(SanitizeCoverageNoPrune, 1, 0) ///< Disable coverage pruning.
+CODEGENOPT(SanitizeCoverageStackDepth, 1, 0) ///< Enable max stack depth tracing
+CODEGENOPT(SanitizeStats , 1, 0) ///< Collect statistics for sanitizers.
CODEGENOPT(SimplifyLibCalls , 1, 1) ///< Set when -fbuiltin is enabled.
CODEGENOPT(SoftFloat , 1, 0) ///< -soft-float.
+CODEGENOPT(FineGrainedBitfieldAccesses, 1, 0) ///< Enable fine-grained bitfield accesses.
CODEGENOPT(StrictEnums , 1, 0) ///< Optimize based on strict enum definition.
CODEGENOPT(StrictVTablePointers, 1, 0) ///< Optimize based on the strict vtable pointers
CODEGENOPT(TimePasses , 1, 0) ///< Set when -ftime-report is enabled.
-CODEGENOPT(UnitAtATime , 1, 1) ///< Unused. For mirroring GCC optimization
- ///< selection.
CODEGENOPT(UnrollLoops , 1, 0) ///< Control whether loops are unrolled.
CODEGENOPT(RerollLoops , 1, 0) ///< Control whether loops are rerolled.
+CODEGENOPT(NoUseJumpTables , 1, 0) ///< Set when -fno-jump-tables is enabled.
CODEGENOPT(UnsafeFPMath , 1, 0) ///< Allow unsafe floating point optzns.
CODEGENOPT(UnwindTables , 1, 0) ///< Emit unwind tables.
-CODEGENOPT(VectorizeBB , 1, 0) ///< Run basic block vectorizer.
CODEGENOPT(VectorizeLoop , 1, 0) ///< Run loop vectorizer.
CODEGENOPT(VectorizeSLP , 1, 0) ///< Run SLP vectorizer.
+CODEGENOPT(ProfileSampleAccurate, 1, 0) ///< Sample profile is accurate.
/// Attempt to use register sized accesses to bit-fields in structures, when
/// possible.
@@ -160,7 +214,7 @@ CODEGENOPT(StackRealignment , 1, 0) ///< Control whether to force stack
///< realignment.
CODEGENOPT(UseInitArray , 1, 0) ///< Control whether to use .init_array or
///< .ctors.
-VALUE_CODEGENOPT(StackAlignment , 32, 0) ///< Overrides default stack
+VALUE_CODEGENOPT(StackAlignment , 32, 0) ///< Overrides default stack
///< alignment, if not 0.
VALUE_CODEGENOPT(StackProbeSize , 32, 4096) ///< Overrides default stack
///< probe size, even if 0.
@@ -170,12 +224,27 @@ CODEGENOPT(DebugColumnInfo, 1, 0) ///< Whether or not to use column information
CODEGENOPT(DebugTypeExtRefs, 1, 0) ///< Whether or not debug info should contain
///< external references to a PCH or module.
-CODEGENOPT(DebugExplicitImport, 1, 0) ///< Whether or not debug info should
- ///< contain explicit imports for
+CODEGENOPT(DebugExplicitImport, 1, 0) ///< Whether or not debug info should
+ ///< contain explicit imports for
///< anonymous namespaces
+CODEGENOPT(EnableSplitDwarf, 1, 0) ///< Whether to enable split DWARF
+CODEGENOPT(SplitDwarfInlining, 1, 1) ///< Whether to include inlining info in the
+ ///< skeleton CU to allow for symbolication
+ ///< of inline stack frames without .dwo files.
+CODEGENOPT(DebugFwdTemplateParams, 1, 0) ///< Whether to emit complete
+ ///< template parameter descriptions in
+ ///< forward declarations (versus just
+ ///< including them in the name).
CODEGENOPT(EmitLLVMUseLists, 1, 0) ///< Control whether to serialize use-lists.
+CODEGENOPT(WholeProgramVTables, 1, 0) ///< Whether to apply whole-program
+ /// vtable optimization.
+
+/// Whether to use public LTO visibility for entities in std and stdext
+/// namespaces. This is enabled by clang-cl's /MT and /MTd flags.
+CODEGENOPT(LTOVisibilityPublicStd, 1, 0)
+
/// The user specified number of registers to be used for integral arguments,
/// or 0 if unspecified.
VALUE_CODEGENOPT(NumRegisterParameters, 32, 0)
@@ -183,11 +252,18 @@ VALUE_CODEGENOPT(NumRegisterParameters, 32, 0)
/// The lower bound for a buffer to be considered for stack protection.
VALUE_CODEGENOPT(SSPBufferSize, 32, 0)
+/// Whether to use return protectors
+CODEGENOPT(ReturnProtector, 1, 0)
+
/// The kind of generated debug info.
-ENUM_CODEGENOPT(DebugInfo, DebugInfoKind, 3, NoDebugInfo)
+ENUM_CODEGENOPT(DebugInfo, codegenoptions::DebugInfoKind, 3, codegenoptions::NoDebugInfo)
+
+/// Whether to generate macro debug info.
+CODEGENOPT(MacroDebugInfo, 1, 0)
/// Tune the debug info for this debugger.
-ENUM_CODEGENOPT(DebuggerTuning, DebuggerKind, 2, DebuggerKindDefault)
+ENUM_CODEGENOPT(DebuggerTuning, llvm::DebuggerKind, 2,
+ llvm::DebuggerKind::Default)
/// Dwarf version. Version zero indicates to LLVM that no DWARF should be
/// emitted.
@@ -198,14 +274,43 @@ VALUE_CODEGENOPT(DwarfVersion, 3, 0)
CODEGENOPT(EmitCodeView, 1, 0)
/// The kind of inlining to perform.
-ENUM_CODEGENOPT(Inlining, InliningMethod, 2, NoInlining)
+ENUM_CODEGENOPT(Inlining, InliningMethod, 2, NormalInlining)
// Vector functions library to use.
-ENUM_CODEGENOPT(VecLib, VectorLibrary, 1, NoLibrary)
+ENUM_CODEGENOPT(VecLib, VectorLibrary, 2, NoLibrary)
/// The default TLS model to use.
ENUM_CODEGENOPT(DefaultTLSModel, TLSModel, 2, GeneralDynamicTLSModel)
+/// Number of path components to strip when emitting checks. (0 == full
+/// filename)
+VALUE_CODEGENOPT(EmitCheckPathComponentsToStrip, 32, 0)
+
+/// Whether to report the hotness of the code region for optimization remarks.
+CODEGENOPT(DiagnosticsWithHotness, 1, 0)
+
+/// The minimum hotness value a diagnostic needs in order to be included in
+/// optimization diagnostics.
+VALUE_CODEGENOPT(DiagnosticsHotnessThreshold, 32, 0)
+
+/// Whether copy relocations support is available when building as PIE.
+CODEGENOPT(PIECopyRelocations, 1, 0)
+
+/// Whether we should use the undefined behaviour optimization for control flow
+/// paths that reach the end of a function without executing a required return.
+CODEGENOPT(StrictReturn, 1, 1)
+
+/// Whether emit extra debug info for sample pgo profile collection.
+CODEGENOPT(DebugInfoForProfiling, 1, 0)
+
+/// Whether 3-component vector type is preserved.
+CODEGENOPT(PreserveVec3Type, 1, 0)
+
+/// Whether to emit .debug_gnu_pubnames section instead of .debug_pubnames.
+CODEGENOPT(GnuPubnames, 1, 0)
+
+CODEGENOPT(NoPLT, 1, 0)
+
#undef CODEGENOPT
#undef ENUM_CODEGENOPT
#undef VALUE_CODEGENOPT
diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGCall.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGCall.cpp
index 935985049c0..de67ee39c14 100644
--- a/gnu/llvm/tools/clang/lib/CodeGen/CGCall.cpp
+++ b/gnu/llvm/tools/clang/lib/CodeGen/CGCall.cpp
@@ -14,6 +14,7 @@
#include "CGCall.h"
#include "ABIInfo.h"
+#include "CGBlocks.h"
#include "CGCXXABI.h"
#include "CGCleanup.h"
#include "CodeGenFunction.h"
@@ -25,9 +26,12 @@
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/CGFunctionInfo.h"
+#include "clang/CodeGen/SwiftCallingConv.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/Attributes.h"
+#include "llvm/IR/CallingConv.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/InlineAsm.h"
@@ -39,13 +43,14 @@ using namespace CodeGen;
/***/
-static unsigned ClangCallConvToLLVMCallConv(CallingConv CC) {
+unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) {
switch (CC) {
default: return llvm::CallingConv::C;
case CC_X86StdCall: return llvm::CallingConv::X86_StdCall;
case CC_X86FastCall: return llvm::CallingConv::X86_FastCall;
+ case CC_X86RegCall: return llvm::CallingConv::X86_RegCall;
case CC_X86ThisCall: return llvm::CallingConv::X86_ThisCall;
- case CC_X86_64Win64: return llvm::CallingConv::X86_64_Win64;
+ case CC_Win64: return llvm::CallingConv::Win64;
case CC_X86_64SysV: return llvm::CallingConv::X86_64_SysV;
case CC_AAPCS: return llvm::CallingConv::ARM_AAPCS;
case CC_AAPCS_VFP: return llvm::CallingConv::ARM_AAPCS_VFP;
@@ -55,7 +60,10 @@ static unsigned ClangCallConvToLLVMCallConv(CallingConv CC) {
// TODO: Add support for __vectorcall to LLVM.
case CC_X86VectorCall: return llvm::CallingConv::X86_VectorCall;
case CC_SpirFunction: return llvm::CallingConv::SPIR_FUNC;
- case CC_SpirKernel: return llvm::CallingConv::SPIR_KERNEL;
+ case CC_OpenCLKernel: return CGM.getTargetCodeGenInfo().getOpenCLKernelCallingConv();
+ case CC_PreserveMost: return llvm::CallingConv::PreserveMost;
+ case CC_PreserveAll: return llvm::CallingConv::PreserveAll;
+ case CC_Swift: return llvm::CallingConv::Swift;
}
}
@@ -90,32 +98,67 @@ CodeGenTypes::arrangeFreeFunctionType(CanQual<FunctionNoProtoType> FTNP) {
return arrangeLLVMFunctionInfo(FTNP->getReturnType().getUnqualifiedType(),
/*instanceMethod=*/false,
/*chainCall=*/false, None,
- FTNP->getExtInfo(), RequiredArgs(0));
+ FTNP->getExtInfo(), {}, RequiredArgs(0));
}
-/// Adds the formal paramaters in FPT to the given prefix. If any parameter in
+static void addExtParameterInfosForCall(
+ llvm::SmallVectorImpl<FunctionProtoType::ExtParameterInfo> &paramInfos,
+ const FunctionProtoType *proto,
+ unsigned prefixArgs,
+ unsigned totalArgs) {
+ assert(proto->hasExtParameterInfos());
+ assert(paramInfos.size() <= prefixArgs);
+ assert(proto->getNumParams() + prefixArgs <= totalArgs);
+
+ paramInfos.reserve(totalArgs);
+
+ // Add default infos for any prefix args that don't already have infos.
+ paramInfos.resize(prefixArgs);
+
+ // Add infos for the prototype.
+ for (const auto &ParamInfo : proto->getExtParameterInfos()) {
+ paramInfos.push_back(ParamInfo);
+ // pass_object_size params have no parameter info.
+ if (ParamInfo.hasPassObjectSize())
+ paramInfos.emplace_back();
+ }
+
+ assert(paramInfos.size() <= totalArgs &&
+ "Did we forget to insert pass_object_size args?");
+ // Add default infos for the variadic and/or suffix arguments.
+ paramInfos.resize(totalArgs);
+}
+
+/// Adds the formal parameters in FPT to the given prefix. If any parameter in
/// FPT has pass_object_size attrs, then we'll add parameters for those, too.
static void appendParameterTypes(const CodeGenTypes &CGT,
SmallVectorImpl<CanQualType> &prefix,
- const CanQual<FunctionProtoType> &FPT,
- const FunctionDecl *FD) {
- // Fast path: unknown target.
- if (FD == nullptr) {
+ SmallVectorImpl<FunctionProtoType::ExtParameterInfo> &paramInfos,
+ CanQual<FunctionProtoType> FPT) {
+ // Fast path: don't touch param info if we don't need to.
+ if (!FPT->hasExtParameterInfos()) {
+ assert(paramInfos.empty() &&
+ "We have paramInfos, but the prototype doesn't?");
prefix.append(FPT->param_type_begin(), FPT->param_type_end());
return;
}
- // In the vast majority cases, we'll have precisely FPT->getNumParams()
+ unsigned PrefixSize = prefix.size();
+ // In the vast majority of cases, we'll have precisely FPT->getNumParams()
// parameters; the only thing that can change this is the presence of
// pass_object_size. So, we preallocate for the common case.
prefix.reserve(prefix.size() + FPT->getNumParams());
- assert(FD->getNumParams() == FPT->getNumParams());
+ auto ExtInfos = FPT->getExtParameterInfos();
+ assert(ExtInfos.size() == FPT->getNumParams());
for (unsigned I = 0, E = FPT->getNumParams(); I != E; ++I) {
prefix.push_back(FPT->getParamType(I));
- if (FD->getParamDecl(I)->hasAttr<PassObjectSizeAttr>())
+ if (ExtInfos[I].hasPassObjectSize())
prefix.push_back(CGT.getContext().getSizeType());
}
+
+ addExtParameterInfosForCall(paramInfos, FPT.getTypePtr(), PrefixSize,
+ prefix.size());
}
/// Arrange the LLVM function layout for a value of the given function
@@ -125,13 +168,17 @@ arrangeLLVMFunctionInfo(CodeGenTypes &CGT, bool instanceMethod,
SmallVectorImpl<CanQualType> &prefix,
CanQual<FunctionProtoType> FTP,
const FunctionDecl *FD) {
- RequiredArgs required = RequiredArgs::forPrototypePlus(FTP, prefix.size());
+ SmallVector<FunctionProtoType::ExtParameterInfo, 16> paramInfos;
+ RequiredArgs Required =
+ RequiredArgs::forPrototypePlus(FTP, prefix.size(), FD);
// FIXME: Kill copy.
- appendParameterTypes(CGT, prefix, FTP, FD);
+ appendParameterTypes(CGT, prefix, paramInfos, FTP);
CanQualType resultType = FTP->getReturnType().getUnqualifiedType();
+
return CGT.arrangeLLVMFunctionInfo(resultType, instanceMethod,
/*chainCall=*/false, prefix,
- FTP->getExtInfo(), required);
+ FTP->getExtInfo(), paramInfos,
+ Required);
}
/// Arrange the argument and result information for a value of the
@@ -152,6 +199,9 @@ static CallingConv getCallingConventionForDecl(const Decl *D, bool IsWindows) {
if (D->hasAttr<FastCallAttr>())
return CC_X86FastCall;
+ if (D->hasAttr<RegCallAttr>())
+ return CC_X86RegCall;
+
if (D->hasAttr<ThisCallAttr>())
return CC_X86ThisCall;
@@ -168,11 +218,17 @@ static CallingConv getCallingConventionForDecl(const Decl *D, bool IsWindows) {
return CC_IntelOclBicc;
if (D->hasAttr<MSABIAttr>())
- return IsWindows ? CC_C : CC_X86_64Win64;
+ return IsWindows ? CC_C : CC_Win64;
if (D->hasAttr<SysVABIAttr>())
return IsWindows ? CC_X86_64SysV : CC_C;
+ if (D->hasAttr<PreserveMostAttr>())
+ return CC_PreserveMost;
+
+ if (D->hasAttr<PreserveAllAttr>())
+ return CC_PreserveAll;
+
return CC_C;
}
@@ -219,16 +275,33 @@ CodeGenTypes::arrangeCXXMethodDeclaration(const CXXMethodDecl *MD) {
return arrangeFreeFunctionType(prototype, MD);
}
+bool CodeGenTypes::inheritingCtorHasParams(
+ const InheritedConstructor &Inherited, CXXCtorType Type) {
+ // Parameters are unnecessary if we're constructing a base class subobject
+ // and the inherited constructor lives in a virtual base.
+ return Type == Ctor_Complete ||
+ !Inherited.getShadowDecl()->constructsVirtualBase() ||
+ !Target.getCXXABI().hasConstructorVariants();
+ }
+
const CGFunctionInfo &
CodeGenTypes::arrangeCXXStructorDeclaration(const CXXMethodDecl *MD,
StructorType Type) {
SmallVector<CanQualType, 16> argTypes;
+ SmallVector<FunctionProtoType::ExtParameterInfo, 16> paramInfos;
argTypes.push_back(GetThisType(Context, MD->getParent()));
+ bool PassParams = true;
+
GlobalDecl GD;
if (auto *CD = dyn_cast<CXXConstructorDecl>(MD)) {
GD = GlobalDecl(CD, toCXXCtorType(Type));
+
+ // A base class inheriting constructor doesn't get forwarded arguments
+ // needed to construct a virtual base (or base class thereof).
+ if (auto Inherited = CD->getInheritedConstructor())
+ PassParams = inheritingCtorHasParams(Inherited, toCXXCtorType(Type));
} else {
auto *DD = dyn_cast<CXXDestructorDecl>(MD);
GD = GlobalDecl(DD, toCXXDtorType(Type));
@@ -237,12 +310,24 @@ CodeGenTypes::arrangeCXXStructorDeclaration(const CXXMethodDecl *MD,
CanQual<FunctionProtoType> FTP = GetFormalType(MD);
// Add the formal parameters.
- appendParameterTypes(*this, argTypes, FTP, MD);
-
- TheCXXABI.buildStructorSignature(MD, Type, argTypes);
+ if (PassParams)
+ appendParameterTypes(*this, argTypes, paramInfos, FTP);
+
+ CGCXXABI::AddedStructorArgs AddedArgs =
+ TheCXXABI.buildStructorSignature(MD, Type, argTypes);
+ if (!paramInfos.empty()) {
+ // Note: prefix implies after the first param.
+ if (AddedArgs.Prefix)
+ paramInfos.insert(paramInfos.begin() + 1, AddedArgs.Prefix,
+ FunctionProtoType::ExtParameterInfo{});
+ if (AddedArgs.Suffix)
+ paramInfos.append(AddedArgs.Suffix,
+ FunctionProtoType::ExtParameterInfo{});
+ }
RequiredArgs required =
- (MD->isVariadic() ? RequiredArgs(argTypes.size()) : RequiredArgs::All);
+ (PassParams && MD->isVariadic() ? RequiredArgs(argTypes.size())
+ : RequiredArgs::All);
FunctionType::ExtInfo extInfo = FTP->getExtInfo();
CanQualType resultType = TheCXXABI.HasThisReturn(GD)
@@ -252,22 +337,61 @@ CodeGenTypes::arrangeCXXStructorDeclaration(const CXXMethodDecl *MD,
: Context.VoidTy;
return arrangeLLVMFunctionInfo(resultType, /*instanceMethod=*/true,
/*chainCall=*/false, argTypes, extInfo,
- required);
+ paramInfos, required);
+}
+
+static SmallVector<CanQualType, 16>
+getArgTypesForCall(ASTContext &ctx, const CallArgList &args) {
+ SmallVector<CanQualType, 16> argTypes;
+ for (auto &arg : args)
+ argTypes.push_back(ctx.getCanonicalParamType(arg.Ty));
+ return argTypes;
+}
+
+static SmallVector<CanQualType, 16>
+getArgTypesForDeclaration(ASTContext &ctx, const FunctionArgList &args) {
+ SmallVector<CanQualType, 16> argTypes;
+ for (auto &arg : args)
+ argTypes.push_back(ctx.getCanonicalParamType(arg->getType()));
+ return argTypes;
+}
+
+static llvm::SmallVector<FunctionProtoType::ExtParameterInfo, 16>
+getExtParameterInfosForCall(const FunctionProtoType *proto,
+ unsigned prefixArgs, unsigned totalArgs) {
+ llvm::SmallVector<FunctionProtoType::ExtParameterInfo, 16> result;
+ if (proto->hasExtParameterInfos()) {
+ addExtParameterInfosForCall(result, proto, prefixArgs, totalArgs);
+ }
+ return result;
}
/// Arrange a call to a C++ method, passing the given arguments.
+///
+/// ExtraPrefixArgs is the number of ABI-specific args passed after the `this`
+/// parameter.
+/// ExtraSuffixArgs is the number of ABI-specific args passed at the end of
+/// args.
+/// PassProtoArgs indicates whether `args` has args for the parameters in the
+/// given CXXConstructorDecl.
const CGFunctionInfo &
CodeGenTypes::arrangeCXXConstructorCall(const CallArgList &args,
const CXXConstructorDecl *D,
CXXCtorType CtorKind,
- unsigned ExtraArgs) {
+ unsigned ExtraPrefixArgs,
+ unsigned ExtraSuffixArgs,
+ bool PassProtoArgs) {
// FIXME: Kill copy.
SmallVector<CanQualType, 16> ArgTypes;
for (const auto &Arg : args)
ArgTypes.push_back(Context.getCanonicalParamType(Arg.Ty));
+ // +1 for implicit this, which should always be args[0].
+ unsigned TotalPrefixArgs = 1 + ExtraPrefixArgs;
+
CanQual<FunctionProtoType> FPT = GetFormalType(D);
- RequiredArgs Required = RequiredArgs::forPrototypePlus(FPT, 1 + ExtraArgs);
+ RequiredArgs Required =
+ RequiredArgs::forPrototypePlus(FPT, TotalPrefixArgs + ExtraSuffixArgs, D);
GlobalDecl GD(D, CtorKind);
CanQualType ResultType = TheCXXABI.HasThisReturn(GD)
? ArgTypes.front()
@@ -276,9 +400,17 @@ CodeGenTypes::arrangeCXXConstructorCall(const CallArgList &args,
: Context.VoidTy;
FunctionType::ExtInfo Info = FPT->getExtInfo();
+ llvm::SmallVector<FunctionProtoType::ExtParameterInfo, 16> ParamInfos;
+ // If the prototype args are elided, we should only have ABI-specific args,
+ // which never have param info.
+ if (PassProtoArgs && FPT->hasExtParameterInfos()) {
+ // ABI-specific suffix arguments are treated the same as variadic arguments.
+ addExtParameterInfosForCall(ParamInfos, FPT.getTypePtr(), TotalPrefixArgs,
+ ArgTypes.size());
+ }
return arrangeLLVMFunctionInfo(ResultType, /*instanceMethod=*/true,
/*chainCall=*/false, ArgTypes, Info,
- Required);
+ ParamInfos, Required);
}
/// Arrange the argument and result information for the declaration or
@@ -295,15 +427,13 @@ CodeGenTypes::arrangeFunctionDeclaration(const FunctionDecl *FD) {
// When declaring a function without a prototype, always use a
// non-variadic type.
- if (isa<FunctionNoProtoType>(FTy)) {
- CanQual<FunctionNoProtoType> noProto = FTy.getAs<FunctionNoProtoType>();
+ if (CanQual<FunctionNoProtoType> noProto = FTy.getAs<FunctionNoProtoType>()) {
return arrangeLLVMFunctionInfo(
noProto->getReturnType(), /*instanceMethod=*/false,
- /*chainCall=*/false, None, noProto->getExtInfo(), RequiredArgs::All);
+ /*chainCall=*/false, None, noProto->getExtInfo(), {},RequiredArgs::All);
}
- assert(isa<FunctionProtoType>(FTy));
- return arrangeFreeFunctionType(FTy.getAs<FunctionProtoType>(), FD);
+ return arrangeFreeFunctionType(FTy.castAs<FunctionProtoType>(), FD);
}
/// Arrange the argument and result information for the declaration or
@@ -325,11 +455,15 @@ const CGFunctionInfo &
CodeGenTypes::arrangeObjCMessageSendSignature(const ObjCMethodDecl *MD,
QualType receiverType) {
SmallVector<CanQualType, 16> argTys;
+ SmallVector<FunctionProtoType::ExtParameterInfo, 4> extParamInfos(2);
argTys.push_back(Context.getCanonicalParamType(receiverType));
argTys.push_back(Context.getCanonicalParamType(Context.getObjCSelType()));
// FIXME: Kill copy?
- for (const auto *I : MD->params()) {
+ for (const auto *I : MD->parameters()) {
argTys.push_back(Context.getCanonicalParamType(I->getType()));
+ auto extParamInfo = FunctionProtoType::ExtParameterInfo().withIsNoEscape(
+ I->hasAttr<NoEscapeAttr>());
+ extParamInfos.push_back(extParamInfo);
}
FunctionType::ExtInfo einfo;
@@ -345,7 +479,18 @@ CodeGenTypes::arrangeObjCMessageSendSignature(const ObjCMethodDecl *MD,
return arrangeLLVMFunctionInfo(
GetReturnType(MD->getReturnType()), /*instanceMethod=*/false,
- /*chainCall=*/false, argTys, einfo, required);
+ /*chainCall=*/false, argTys, einfo, extParamInfos, required);
+}
+
+const CGFunctionInfo &
+CodeGenTypes::arrangeUnprototypedObjCMessageSend(QualType returnType,
+ const CallArgList &args) {
+ auto argTypes = getArgTypesForCall(Context, args);
+ FunctionType::ExtInfo einfo;
+
+ return arrangeLLVMFunctionInfo(
+ GetReturnType(returnType), /*instanceMethod=*/false,
+ /*chainCall=*/false, argTypes, einfo, {}, RequiredArgs::All);
}
const CGFunctionInfo &
@@ -374,7 +519,7 @@ CodeGenTypes::arrangeMSMemberPointerThunk(const CXXMethodDecl *MD) {
CanQualType ArgTys[] = { GetThisType(Context, MD->getParent()) };
return arrangeLLVMFunctionInfo(Context.VoidTy, /*instanceMethod=*/false,
/*chainCall=*/false, ArgTys,
- FTP->getExtInfo(), RequiredArgs(1));
+ FTP->getExtInfo(), {}, RequiredArgs(1));
}
const CGFunctionInfo &
@@ -394,7 +539,8 @@ CodeGenTypes::arrangeMSCtorClosure(const CXXConstructorDecl *CD,
/*IsVariadic=*/false, /*IsCXXMethod=*/true);
return arrangeLLVMFunctionInfo(Context.VoidTy, /*instanceMethod=*/true,
/*chainCall=*/false, ArgTys,
- FunctionType::ExtInfo(CC), RequiredArgs::All);
+ FunctionType::ExtInfo(CC), {},
+ RequiredArgs::All);
}
/// Arrange a call as unto a free function, except possibly with an
@@ -408,6 +554,8 @@ arrangeFreeFunctionLikeCall(CodeGenTypes &CGT,
bool chainCall) {
assert(args.size() >= numExtraRequiredArgs);
+ llvm::SmallVector<FunctionProtoType::ExtParameterInfo, 16> paramInfos;
+
// In most cases, there are no optional arguments.
RequiredArgs required = RequiredArgs::All;
@@ -417,6 +565,10 @@ arrangeFreeFunctionLikeCall(CodeGenTypes &CGT,
if (proto->isVariadic())
required = RequiredArgs(proto->getNumParams() + numExtraRequiredArgs);
+ if (proto->hasExtParameterInfos())
+ addExtParameterInfosForCall(paramInfos, proto, numExtraRequiredArgs,
+ args.size());
+
// If we don't have a prototype at all, but we're supposed to
// explicitly use the variadic convention for unprototyped calls,
// treat all of the arguments as required but preserve the nominal
@@ -433,7 +585,8 @@ arrangeFreeFunctionLikeCall(CodeGenTypes &CGT,
argTypes.push_back(CGT.getContext().getCanonicalParamType(arg.Ty));
return CGT.arrangeLLVMFunctionInfo(GetReturnType(fnType->getReturnType()),
/*instanceMethod=*/false, chainCall,
- argTypes, fnType->getExtInfo(), required);
+ argTypes, fnType->getExtInfo(), paramInfos,
+ required);
}
/// Figure out the rules for calling a function with the given formal
@@ -448,7 +601,7 @@ CodeGenTypes::arrangeFreeFunctionCall(const CallArgList &args,
chainCall ? 1 : 0, chainCall);
}
-/// A block function call is essentially a free-function call with an
+/// A block function is essentially a free function with an
/// extra implicit argument.
const CGFunctionInfo &
CodeGenTypes::arrangeBlockFunctionCall(const CallArgList &args,
@@ -458,54 +611,110 @@ CodeGenTypes::arrangeBlockFunctionCall(const CallArgList &args,
}
const CGFunctionInfo &
-CodeGenTypes::arrangeFreeFunctionCall(QualType resultType,
- const CallArgList &args,
- FunctionType::ExtInfo info,
- RequiredArgs required) {
+CodeGenTypes::arrangeBlockFunctionDeclaration(const FunctionProtoType *proto,
+ const FunctionArgList &params) {
+ auto paramInfos = getExtParameterInfosForCall(proto, 1, params.size());
+ auto argTypes = getArgTypesForDeclaration(Context, params);
+
+ return arrangeLLVMFunctionInfo(
+ GetReturnType(proto->getReturnType()),
+ /*instanceMethod*/ false, /*chainCall*/ false, argTypes,
+ proto->getExtInfo(), paramInfos,
+ RequiredArgs::forPrototypePlus(proto, 1, nullptr));
+}
+
+const CGFunctionInfo &
+CodeGenTypes::arrangeBuiltinFunctionCall(QualType resultType,
+ const CallArgList &args) {
// FIXME: Kill copy.
SmallVector<CanQualType, 16> argTypes;
for (const auto &Arg : args)
argTypes.push_back(Context.getCanonicalParamType(Arg.Ty));
return arrangeLLVMFunctionInfo(
GetReturnType(resultType), /*instanceMethod=*/false,
- /*chainCall=*/false, argTypes, info, required);
+ /*chainCall=*/false, argTypes, FunctionType::ExtInfo(),
+ /*paramInfos=*/ {}, RequiredArgs::All);
}
-/// Arrange a call to a C++ method, passing the given arguments.
const CGFunctionInfo &
-CodeGenTypes::arrangeCXXMethodCall(const CallArgList &args,
- const FunctionProtoType *FPT,
- RequiredArgs required) {
- // FIXME: Kill copy.
- SmallVector<CanQualType, 16> argTypes;
- for (const auto &Arg : args)
- argTypes.push_back(Context.getCanonicalParamType(Arg.Ty));
+CodeGenTypes::arrangeBuiltinFunctionDeclaration(QualType resultType,
+ const FunctionArgList &args) {
+ auto argTypes = getArgTypesForDeclaration(Context, args);
+
+ return arrangeLLVMFunctionInfo(
+ GetReturnType(resultType), /*instanceMethod=*/false, /*chainCall=*/false,
+ argTypes, FunctionType::ExtInfo(), {}, RequiredArgs::All);
+}
- FunctionType::ExtInfo info = FPT->getExtInfo();
+const CGFunctionInfo &
+CodeGenTypes::arrangeBuiltinFunctionDeclaration(CanQualType resultType,
+ ArrayRef<CanQualType> argTypes) {
return arrangeLLVMFunctionInfo(
- GetReturnType(FPT->getReturnType()), /*instanceMethod=*/true,
- /*chainCall=*/false, argTypes, info, required);
+ resultType, /*instanceMethod=*/false, /*chainCall=*/false,
+ argTypes, FunctionType::ExtInfo(), {}, RequiredArgs::All);
}
-const CGFunctionInfo &CodeGenTypes::arrangeFreeFunctionDeclaration(
- QualType resultType, const FunctionArgList &args,
- const FunctionType::ExtInfo &info, bool isVariadic) {
+/// Arrange a call to a C++ method, passing the given arguments.
+///
+/// numPrefixArgs is the number of ABI-specific prefix arguments we have. It
+/// does not count `this`.
+const CGFunctionInfo &
+CodeGenTypes::arrangeCXXMethodCall(const CallArgList &args,
+ const FunctionProtoType *proto,
+ RequiredArgs required,
+ unsigned numPrefixArgs) {
+ assert(numPrefixArgs + 1 <= args.size() &&
+ "Emitting a call with less args than the required prefix?");
+ // Add one to account for `this`. It's a bit awkward here, but we don't count
+ // `this` in similar places elsewhere.
+ auto paramInfos =
+ getExtParameterInfosForCall(proto, numPrefixArgs + 1, args.size());
+
// FIXME: Kill copy.
- SmallVector<CanQualType, 16> argTypes;
- for (auto Arg : args)
- argTypes.push_back(Context.getCanonicalParamType(Arg->getType()));
+ auto argTypes = getArgTypesForCall(Context, args);
- RequiredArgs required =
- (isVariadic ? RequiredArgs(args.size()) : RequiredArgs::All);
+ FunctionType::ExtInfo info = proto->getExtInfo();
return arrangeLLVMFunctionInfo(
- GetReturnType(resultType), /*instanceMethod=*/false,
- /*chainCall=*/false, argTypes, info, required);
+ GetReturnType(proto->getReturnType()), /*instanceMethod=*/true,
+ /*chainCall=*/false, argTypes, info, paramInfos, required);
}
const CGFunctionInfo &CodeGenTypes::arrangeNullaryFunction() {
return arrangeLLVMFunctionInfo(
getContext().VoidTy, /*instanceMethod=*/false, /*chainCall=*/false,
- None, FunctionType::ExtInfo(), RequiredArgs::All);
+ None, FunctionType::ExtInfo(), {}, RequiredArgs::All);
+}
+
+const CGFunctionInfo &
+CodeGenTypes::arrangeCall(const CGFunctionInfo &signature,
+ const CallArgList &args) {
+ assert(signature.arg_size() <= args.size());
+ if (signature.arg_size() == args.size())
+ return signature;
+
+ SmallVector<FunctionProtoType::ExtParameterInfo, 16> paramInfos;
+ auto sigParamInfos = signature.getExtParameterInfos();
+ if (!sigParamInfos.empty()) {
+ paramInfos.append(sigParamInfos.begin(), sigParamInfos.end());
+ paramInfos.resize(args.size());
+ }
+
+ auto argTypes = getArgTypesForCall(Context, args);
+
+ assert(signature.getRequiredArgs().allowsOptionalArgs());
+ return arrangeLLVMFunctionInfo(signature.getReturnType(),
+ signature.isInstanceMethod(),
+ signature.isChainCall(),
+ argTypes,
+ signature.getExtInfo(),
+ paramInfos,
+ signature.getRequiredArgs());
+}
+
+namespace clang {
+namespace CodeGen {
+void computeSPIRKernelABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI);
+}
}
/// Arrange the argument and result information for an abstract value
@@ -517,33 +726,42 @@ CodeGenTypes::arrangeLLVMFunctionInfo(CanQualType resultType,
bool chainCall,
ArrayRef<CanQualType> argTypes,
FunctionType::ExtInfo info,
+ ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos,
RequiredArgs required) {
assert(std::all_of(argTypes.begin(), argTypes.end(),
- std::mem_fun_ref(&CanQualType::isCanonicalAsParam)));
-
- unsigned CC = ClangCallConvToLLVMCallConv(info.getCC());
+ [](CanQualType T) { return T.isCanonicalAsParam(); }));
// Lookup or create unique function info.
llvm::FoldingSetNodeID ID;
- CGFunctionInfo::Profile(ID, instanceMethod, chainCall, info, required,
- resultType, argTypes);
+ CGFunctionInfo::Profile(ID, instanceMethod, chainCall, info, paramInfos,
+ required, resultType, argTypes);
void *insertPos = nullptr;
CGFunctionInfo *FI = FunctionInfos.FindNodeOrInsertPos(ID, insertPos);
if (FI)
return *FI;
+ unsigned CC = ClangCallConvToLLVMCallConv(info.getCC());
+
// Construct the function info. We co-allocate the ArgInfos.
FI = CGFunctionInfo::create(CC, instanceMethod, chainCall, info,
- resultType, argTypes, required);
+ paramInfos, resultType, argTypes, required);
FunctionInfos.InsertNode(FI, insertPos);
bool inserted = FunctionsBeingProcessed.insert(FI).second;
(void)inserted;
assert(inserted && "Recursively being processed?");
-
+
// Compute ABI information.
- getABIInfo().computeInfo(*FI);
+ if (CC == llvm::CallingConv::SPIR_KERNEL) {
+ // Force target independent argument handling for the host visible
+ // kernel functions.
+ computeSPIRKernelABIInfo(CGM, *FI);
+ } else if (info.getCC() == CC_Swift) {
+ swiftcall::computeABIInfo(CGM, *FI);
+ } else {
+ getABIInfo().computeInfo(*FI);
+ }
// Loop over all of the computed argument and return value info. If any of
// them are direct or extend without a specified coerce type, specify the
@@ -566,11 +784,16 @@ CGFunctionInfo *CGFunctionInfo::create(unsigned llvmCC,
bool instanceMethod,
bool chainCall,
const FunctionType::ExtInfo &info,
+ ArrayRef<ExtParameterInfo> paramInfos,
CanQualType resultType,
ArrayRef<CanQualType> argTypes,
RequiredArgs required) {
- void *buffer = operator new(sizeof(CGFunctionInfo) +
- sizeof(ArgInfo) * (argTypes.size() + 1));
+ assert(paramInfos.empty() || paramInfos.size() == argTypes.size());
+
+ void *buffer =
+ operator new(totalSizeToAlloc<ArgInfo, ExtParameterInfo>(
+ argTypes.size() + 1, paramInfos.size()));
+
CGFunctionInfo *FI = new(buffer) CGFunctionInfo();
FI->CallingConvention = llvmCC;
FI->EffectiveCallingConvention = llvmCC;
@@ -579,15 +802,19 @@ CGFunctionInfo *CGFunctionInfo::create(unsigned llvmCC,
FI->ChainCall = chainCall;
FI->NoReturn = info.getNoReturn();
FI->ReturnsRetained = info.getProducesResult();
+ FI->NoCallerSavedRegs = info.getNoCallerSavedRegs();
FI->Required = required;
FI->HasRegParm = info.getHasRegParm();
FI->RegParm = info.getRegParm();
FI->ArgStruct = nullptr;
FI->ArgStructAlign = 0;
FI->NumArgs = argTypes.size();
+ FI->HasExtParameterInfos = !paramInfos.empty();
FI->getArgsBuffer()[0].type = resultType;
for (unsigned i = 0, e = argTypes.size(); i != e; ++i)
FI->getArgsBuffer()[i + 1].type = argTypes[i];
+ for (unsigned i = 0, e = paramInfos.size(); i != e; ++i)
+ FI->getExtParameterInfosBuffer()[i] = paramInfos[i];
return FI;
}
@@ -634,7 +861,8 @@ struct RecordExpansion : TypeExpansion {
RecordExpansion(SmallVector<const CXXBaseSpecifier *, 1> &&Bases,
SmallVector<const FieldDecl *, 1> &&Fields)
- : TypeExpansion(TEK_Record), Bases(Bases), Fields(Fields) {}
+ : TypeExpansion(TEK_Record), Bases(std::move(Bases)),
+ Fields(std::move(Fields)) {}
static bool classof(const TypeExpansion *TE) {
return TE->Kind == TEK_Record;
}
@@ -773,7 +1001,7 @@ static void forConstantArrayExpansion(CodeGenFunction &CGF,
}
void CodeGenFunction::ExpandTypeFromArgs(
- QualType Ty, LValue LV, SmallVectorImpl<llvm::Argument *>::iterator &AI) {
+ QualType Ty, LValue LV, SmallVectorImpl<llvm::Value *>::iterator &AI) {
assert(LV.isSimple() &&
"Unexpected non-simple lvalue during struct expansion.");
@@ -798,7 +1026,7 @@ void CodeGenFunction::ExpandTypeFromArgs(
}
for (auto FD : RExp->Fields) {
// FIXME: What are the right qualifiers here?
- LValue SubLV = EmitLValueForField(LV, FD);
+ LValue SubLV = EmitLValueForFieldInitialization(LV, FD);
ExpandTypeFromArgs(FD->getType(), SubLV, AI);
}
} else if (isa<ComplexExpansion>(Exp.get())) {
@@ -999,14 +1227,15 @@ static llvm::Value *CreateCoercedLoad(Address Src, llvm::Type *Ty,
//
// FIXME: Assert that we aren't truncating non-padding bits when have access
// to that information.
- Src = CGF.Builder.CreateBitCast(Src, llvm::PointerType::getUnqual(Ty));
+ Src = CGF.Builder.CreateBitCast(Src,
+ Ty->getPointerTo(Src.getAddressSpace()));
return CGF.Builder.CreateLoad(Src);
}
// Otherwise do coercion through memory. This is stupid, but simple.
Address Tmp = CreateTempAllocaForCoercion(CGF, Ty, Src.getAlignment());
- Address Casted = CGF.Builder.CreateBitCast(Tmp, CGF.Int8PtrTy);
- Address SrcCasted = CGF.Builder.CreateBitCast(Src, CGF.Int8PtrTy);
+ Address Casted = CGF.Builder.CreateBitCast(Tmp, CGF.AllocaInt8PtrTy);
+ Address SrcCasted = CGF.Builder.CreateBitCast(Src, CGF.AllocaInt8PtrTy);
CGF.Builder.CreateMemCpy(Casted, SrcCasted,
llvm::ConstantInt::get(CGF.IntPtrTy, SrcSize),
false);
@@ -1073,7 +1302,7 @@ static void CreateCoercedStore(llvm::Value *Src,
// If store is legal, just bitcast the src pointer.
if (SrcSize <= DstSize) {
- Dst = CGF.Builder.CreateBitCast(Dst, llvm::PointerType::getUnqual(SrcTy));
+ Dst = CGF.Builder.CreateElementBitCast(Dst, SrcTy);
BuildAggStore(CGF, Src, Dst, DstIsVolatile);
} else {
// Otherwise do coercion through memory. This is stupid, but
@@ -1087,8 +1316,8 @@ static void CreateCoercedStore(llvm::Value *Src,
// to that information.
Address Tmp = CreateTempAllocaForCoercion(CGF, SrcTy, Dst.getAlignment());
CGF.Builder.CreateStore(Src, Tmp);
- Address Casted = CGF.Builder.CreateBitCast(Tmp, CGF.Int8PtrTy);
- Address DstCasted = CGF.Builder.CreateBitCast(Dst, CGF.Int8PtrTy);
+ Address Casted = CGF.Builder.CreateBitCast(Tmp, CGF.AllocaInt8PtrTy);
+ Address DstCasted = CGF.Builder.CreateBitCast(Dst, CGF.AllocaInt8PtrTy);
CGF.Builder.CreateMemCpy(DstCasted, Casted,
llvm::ConstantInt::get(CGF.IntPtrTy, DstSize),
false);
@@ -1220,11 +1449,13 @@ void ClangToLLVMArgMapping::construct(const ASTContext &Context,
// ignore and inalloca doesn't have matching LLVM parameters.
IRArgs.NumberOfArgs = 0;
break;
- case ABIArgInfo::Expand: {
+ case ABIArgInfo::CoerceAndExpand:
+ IRArgs.NumberOfArgs = AI.getCoerceAndExpandTypeSequence().size();
+ break;
+ case ABIArgInfo::Expand:
IRArgs.NumberOfArgs = getExpansionSize(ArgType, Context);
break;
}
- }
if (IRArgs.NumberOfArgs > 0) {
IRArgs.FirstArgIndex = IRArgNo;
@@ -1323,6 +1554,10 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI) {
case ABIArgInfo::Ignore:
resultType = llvm::Type::getVoidTy(getLLVMContext());
break;
+
+ case ABIArgInfo::CoerceAndExpand:
+ resultType = retAI.getUnpaddedCoerceAndExpandType();
+ break;
}
ClangToLLVMArgMapping IRFunctionArgs(getContext(), FI, true);
@@ -1367,9 +1602,10 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI) {
case ABIArgInfo::Indirect: {
assert(NumIRArgs == 1);
- // indirect arguments are always on the stack, which is addr space #0.
+ // indirect arguments are always on the stack, which is alloca addr space.
llvm::Type *LTy = ConvertTypeForMem(it->type);
- ArgTypes[FirstIRArg] = LTy->getPointerTo();
+ ArgTypes[FirstIRArg] = LTy->getPointerTo(
+ CGM.getDataLayout().getAllocaAddrSpace());
break;
}
@@ -1390,6 +1626,15 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI) {
break;
}
+ case ABIArgInfo::CoerceAndExpand: {
+ auto ArgTypesIter = ArgTypes.begin() + FirstIRArg;
+ for (auto EltTy : ArgInfo.getCoerceAndExpandTypeSequence()) {
+ *ArgTypesIter++ = EltTy;
+ }
+ assert(ArgTypesIter == ArgTypes.begin() + FirstIRArg + NumIRArgs);
+ break;
+ }
+
case ABIArgInfo::Expand:
auto ArgTypesIter = ArgTypes.begin() + FirstIRArg;
getExpandedTypes(it->type, ArgTypesIter);
@@ -1431,15 +1676,119 @@ static void AddAttributesFromFunctionProtoType(ASTContext &Ctx,
FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
}
+void CodeGenModule::ConstructDefaultFnAttrList(StringRef Name, bool HasOptnone,
+ bool AttrOnCallSite,
+ llvm::AttrBuilder &FuncAttrs) {
+ // OptimizeNoneAttr takes precedence over -Os or -Oz. No warning needed.
+ if (!HasOptnone) {
+ if (CodeGenOpts.OptimizeSize)
+ FuncAttrs.addAttribute(llvm::Attribute::OptimizeForSize);
+ if (CodeGenOpts.OptimizeSize == 2)
+ FuncAttrs.addAttribute(llvm::Attribute::MinSize);
+ }
+
+ if (CodeGenOpts.DisableRedZone)
+ FuncAttrs.addAttribute(llvm::Attribute::NoRedZone);
+ if (CodeGenOpts.NoImplicitFloat)
+ FuncAttrs.addAttribute(llvm::Attribute::NoImplicitFloat);
+
+ if (AttrOnCallSite) {
+ // Attributes that should go on the call site only.
+ if (!CodeGenOpts.SimplifyLibCalls ||
+ CodeGenOpts.isNoBuiltinFunc(Name.data()))
+ FuncAttrs.addAttribute(llvm::Attribute::NoBuiltin);
+ if (!CodeGenOpts.TrapFuncName.empty())
+ FuncAttrs.addAttribute("trap-func-name", CodeGenOpts.TrapFuncName);
+ } else {
+ // Attributes that should go on the function, but not the call site.
+ if (!CodeGenOpts.DisableFPElim) {
+ FuncAttrs.addAttribute("no-frame-pointer-elim", "false");
+ } else if (CodeGenOpts.OmitLeafFramePointer) {
+ FuncAttrs.addAttribute("no-frame-pointer-elim", "false");
+ FuncAttrs.addAttribute("no-frame-pointer-elim-non-leaf");
+ } else {
+ FuncAttrs.addAttribute("no-frame-pointer-elim", "true");
+ FuncAttrs.addAttribute("no-frame-pointer-elim-non-leaf");
+ }
+
+ FuncAttrs.addAttribute("less-precise-fpmad",
+ llvm::toStringRef(CodeGenOpts.LessPreciseFPMAD));
+
+ if (!CodeGenOpts.FPDenormalMode.empty())
+ FuncAttrs.addAttribute("denormal-fp-math", CodeGenOpts.FPDenormalMode);
+
+ FuncAttrs.addAttribute("no-trapping-math",
+ llvm::toStringRef(CodeGenOpts.NoTrappingMath));
+
+ // TODO: Are these all needed?
+ // unsafe/inf/nan/nsz are handled by instruction-level FastMathFlags.
+ FuncAttrs.addAttribute("no-infs-fp-math",
+ llvm::toStringRef(CodeGenOpts.NoInfsFPMath));
+ FuncAttrs.addAttribute("no-nans-fp-math",
+ llvm::toStringRef(CodeGenOpts.NoNaNsFPMath));
+ FuncAttrs.addAttribute("unsafe-fp-math",
+ llvm::toStringRef(CodeGenOpts.UnsafeFPMath));
+ FuncAttrs.addAttribute("use-soft-float",
+ llvm::toStringRef(CodeGenOpts.SoftFloat));
+ FuncAttrs.addAttribute("stack-protector-buffer-size",
+ llvm::utostr(CodeGenOpts.SSPBufferSize));
+ FuncAttrs.addAttribute("no-signed-zeros-fp-math",
+ llvm::toStringRef(CodeGenOpts.NoSignedZeros));
+ FuncAttrs.addAttribute(
+ "correctly-rounded-divide-sqrt-fp-math",
+ llvm::toStringRef(CodeGenOpts.CorrectlyRoundedDivSqrt));
+
+ // TODO: Reciprocal estimate codegen options should apply to instructions?
+ const std::vector<std::string> &Recips = CodeGenOpts.Reciprocals;
+ if (!Recips.empty())
+ FuncAttrs.addAttribute("reciprocal-estimates",
+ llvm::join(Recips, ","));
+
+ if (!CodeGenOpts.PreferVectorWidth.empty() &&
+ CodeGenOpts.PreferVectorWidth != "none")
+ FuncAttrs.addAttribute("prefer-vector-width",
+ CodeGenOpts.PreferVectorWidth);
+
+ if (CodeGenOpts.StackRealignment)
+ FuncAttrs.addAttribute("stackrealign");
+ if (CodeGenOpts.Backchain)
+ FuncAttrs.addAttribute("backchain");
+ }
+
+ if (getLangOpts().assumeFunctionsAreConvergent()) {
+ // Conservatively, mark all functions and calls in CUDA and OpenCL as
+ // convergent (meaning, they may call an intrinsically convergent op, such
+ // as __syncthreads() / barrier(), and so can't have certain optimizations
+ // applied around them). LLVM will remove this attribute where it safely
+ // can.
+ FuncAttrs.addAttribute(llvm::Attribute::Convergent);
+ }
+
+ if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice) {
+ // Exceptions aren't supported in CUDA device code.
+ FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
+
+ // Respect -fcuda-flush-denormals-to-zero.
+ if (getLangOpts().CUDADeviceFlushDenormalsToZero)
+ FuncAttrs.addAttribute("nvptx-f32ftz", "true");
+ }
+}
+
+void CodeGenModule::AddDefaultFnAttrs(llvm::Function &F) {
+ llvm::AttrBuilder FuncAttrs;
+ ConstructDefaultFnAttrList(F.getName(),
+ F.hasFnAttribute(llvm::Attribute::OptimizeNone),
+ /* AttrOnCallsite = */ false, FuncAttrs);
+ F.addAttributes(llvm::AttributeList::FunctionIndex, FuncAttrs);
+}
+
void CodeGenModule::ConstructAttributeList(
StringRef Name, const CGFunctionInfo &FI, CGCalleeInfo CalleeInfo,
- AttributeListType &PAL, unsigned &CallingConv, bool AttrOnCallSite) {
+ llvm::AttributeList &AttrList, unsigned &CallingConv, bool AttrOnCallSite) {
llvm::AttrBuilder FuncAttrs;
llvm::AttrBuilder RetAttrs;
- bool HasOptnone = false;
CallingConv = FI.getEffectiveCallingConvention();
-
if (FI.isNoReturn())
FuncAttrs.addAttribute(llvm::Attribute::NoReturn);
@@ -1450,6 +1799,7 @@ void CodeGenModule::ConstructAttributeList(
const Decl *TargetDecl = CalleeInfo.getCalleeDecl();
+ bool HasOptnone = false;
// FIXME: handle sseregparm someday...
if (TargetDecl) {
if (TargetDecl->hasAttr<ReturnsTwiceAttr>())
@@ -1458,8 +1808,12 @@ void CodeGenModule::ConstructAttributeList(
FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
if (TargetDecl->hasAttr<NoReturnAttr>())
FuncAttrs.addAttribute(llvm::Attribute::NoReturn);
+ if (TargetDecl->hasAttr<ColdAttr>())
+ FuncAttrs.addAttribute(llvm::Attribute::Cold);
if (TargetDecl->hasAttr<NoDuplicateAttr>())
FuncAttrs.addAttribute(llvm::Attribute::NoDuplicate);
+ if (TargetDecl->hasAttr<ConvergentAttr>())
+ FuncAttrs.addAttribute(llvm::Attribute::Convergent);
if (const FunctionDecl *Fn = dyn_cast<FunctionDecl>(TargetDecl)) {
AddAttributesFromFunctionProtoType(
@@ -1486,78 +1840,58 @@ void CodeGenModule::ConstructAttributeList(
RetAttrs.addAttribute(llvm::Attribute::NoAlias);
if (TargetDecl->hasAttr<ReturnsNonNullAttr>())
RetAttrs.addAttribute(llvm::Attribute::NonNull);
+ if (TargetDecl->hasAttr<AnyX86NoCallerSavedRegistersAttr>())
+ FuncAttrs.addAttribute("no_caller_saved_registers");
HasOptnone = TargetDecl->hasAttr<OptimizeNoneAttr>();
+ if (auto *AllocSize = TargetDecl->getAttr<AllocSizeAttr>()) {
+ Optional<unsigned> NumElemsParam;
+ // alloc_size args are base-1, 0 means not present.
+ if (unsigned N = AllocSize->getNumElemsParam())
+ NumElemsParam = N - 1;
+ FuncAttrs.addAllocSizeAttr(AllocSize->getElemSizeParam() - 1,
+ NumElemsParam);
+ }
}
- // OptimizeNoneAttr takes precedence over -Os or -Oz. No warning needed.
- if (!HasOptnone) {
- if (CodeGenOpts.OptimizeSize)
- FuncAttrs.addAttribute(llvm::Attribute::OptimizeForSize);
- if (CodeGenOpts.OptimizeSize == 2)
- FuncAttrs.addAttribute(llvm::Attribute::MinSize);
- }
+ ConstructDefaultFnAttrList(Name, HasOptnone, AttrOnCallSite, FuncAttrs);
- if (CodeGenOpts.DisableRedZone)
- FuncAttrs.addAttribute(llvm::Attribute::NoRedZone);
- if (CodeGenOpts.NoImplicitFloat)
- FuncAttrs.addAttribute(llvm::Attribute::NoImplicitFloat);
if (CodeGenOpts.EnableSegmentedStacks &&
!(TargetDecl && TargetDecl->hasAttr<NoSplitStackAttr>()))
FuncAttrs.addAttribute("split-stack");
- if (AttrOnCallSite) {
- // Attributes that should go on the call site only.
- if (!CodeGenOpts.SimplifyLibCalls ||
- CodeGenOpts.isNoBuiltinFunc(Name.data()))
- FuncAttrs.addAttribute(llvm::Attribute::NoBuiltin);
- if (!CodeGenOpts.TrapFuncName.empty())
- FuncAttrs.addAttribute("trap-func-name", CodeGenOpts.TrapFuncName);
- } else {
- // Attributes that should go on the function, but not the call site.
- if (!CodeGenOpts.DisableFPElim) {
- FuncAttrs.addAttribute("no-frame-pointer-elim", "false");
- } else if (CodeGenOpts.OmitLeafFramePointer) {
- FuncAttrs.addAttribute("no-frame-pointer-elim", "false");
- FuncAttrs.addAttribute("no-frame-pointer-elim-non-leaf");
- } else {
- FuncAttrs.addAttribute("no-frame-pointer-elim", "true");
- FuncAttrs.addAttribute("no-frame-pointer-elim-non-leaf");
+ // Add NonLazyBind attribute to function declarations when -fno-plt
+ // is used.
+ if (TargetDecl && CodeGenOpts.NoPLT) {
+ if (auto *Fn = dyn_cast<FunctionDecl>(TargetDecl)) {
+ if (!Fn->isDefined() && !AttrOnCallSite) {
+ FuncAttrs.addAttribute(llvm::Attribute::NonLazyBind);
+ }
}
+ }
+ if (!AttrOnCallSite) {
bool DisableTailCalls =
CodeGenOpts.DisableTailCalls ||
- (TargetDecl && TargetDecl->hasAttr<DisableTailCallsAttr>());
+ (TargetDecl && (TargetDecl->hasAttr<DisableTailCallsAttr>() ||
+ TargetDecl->hasAttr<AnyX86InterruptAttr>()));
FuncAttrs.addAttribute("disable-tail-calls",
llvm::toStringRef(DisableTailCalls));
- FuncAttrs.addAttribute("less-precise-fpmad",
- llvm::toStringRef(CodeGenOpts.LessPreciseFPMAD));
- FuncAttrs.addAttribute("no-infs-fp-math",
- llvm::toStringRef(CodeGenOpts.NoInfsFPMath));
- FuncAttrs.addAttribute("no-nans-fp-math",
- llvm::toStringRef(CodeGenOpts.NoNaNsFPMath));
- FuncAttrs.addAttribute("unsafe-fp-math",
- llvm::toStringRef(CodeGenOpts.UnsafeFPMath));
- FuncAttrs.addAttribute("use-soft-float",
- llvm::toStringRef(CodeGenOpts.SoftFloat));
- FuncAttrs.addAttribute("stack-protector-buffer-size",
- llvm::utostr(CodeGenOpts.SSPBufferSize));
-
- if (CodeGenOpts.StackRealignment)
- FuncAttrs.addAttribute("stackrealign");
+ if (CodeGenOpts.ReturnProtector)
+ FuncAttrs.addAttribute("ret-protector");
// Add target-cpu and target-features attributes to functions. If
// we have a decl for the function and it has a target attribute then
// parse that and add it to the feature set.
StringRef TargetCPU = getTarget().getTargetOpts().CPU;
+ std::vector<std::string> Features;
const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl);
if (FD && FD->hasAttr<TargetAttr>()) {
llvm::StringMap<bool> FeatureMap;
getFunctionFeatureMap(FeatureMap, FD);
// Produce the canonical string for this set of features.
- std::vector<std::string> Features;
for (llvm::StringMap<bool>::const_iterator it = FeatureMap.begin(),
ie = FeatureMap.end();
it != ie; ++it)
@@ -1569,28 +1903,22 @@ void CodeGenModule::ConstructAttributeList(
// the function.
const auto *TD = FD->getAttr<TargetAttr>();
TargetAttr::ParsedTargetAttr ParsedAttr = TD->parse();
- if (ParsedAttr.second != "")
- TargetCPU = ParsedAttr.second;
- if (TargetCPU != "")
- FuncAttrs.addAttribute("target-cpu", TargetCPU);
- if (!Features.empty()) {
- std::sort(Features.begin(), Features.end());
- FuncAttrs.addAttribute(
- "target-features",
- llvm::join(Features.begin(), Features.end(), ","));
- }
+ if (ParsedAttr.Architecture != "" &&
+ getTarget().isValidCPUName(ParsedAttr.Architecture))
+ TargetCPU = ParsedAttr.Architecture;
} else {
// Otherwise just add the existing target cpu and target features to the
// function.
- std::vector<std::string> &Features = getTarget().getTargetOpts().Features;
- if (TargetCPU != "")
- FuncAttrs.addAttribute("target-cpu", TargetCPU);
- if (!Features.empty()) {
- std::sort(Features.begin(), Features.end());
- FuncAttrs.addAttribute(
- "target-features",
- llvm::join(Features.begin(), Features.end(), ","));
- }
+ Features = getTarget().getTargetOpts().Features;
+ }
+
+ if (TargetCPU != "")
+ FuncAttrs.addAttribute("target-cpu", TargetCPU);
+ if (!Features.empty()) {
+ std::sort(Features.begin(), Features.end());
+ FuncAttrs.addAttribute(
+ "target-features",
+ llvm::join(Features, ","));
}
}
@@ -1604,7 +1932,7 @@ void CodeGenModule::ConstructAttributeList(
RetAttrs.addAttribute(llvm::Attribute::SExt);
else if (RetTy->hasUnsignedIntegerRepresentation())
RetAttrs.addAttribute(llvm::Attribute::ZExt);
- // FALL THROUGH
+ LLVM_FALLTHROUGH;
case ABIArgInfo::Direct:
if (RetAI.getInReg())
RetAttrs.addAttribute(llvm::Attribute::InReg);
@@ -1620,6 +1948,9 @@ void CodeGenModule::ConstructAttributeList(
break;
}
+ case ABIArgInfo::CoerceAndExpand:
+ break;
+
case ABIArgInfo::Expand:
llvm_unreachable("Invalid ABI kind for return argument");
}
@@ -1633,28 +1964,26 @@ void CodeGenModule::ConstructAttributeList(
RetAttrs.addAttribute(llvm::Attribute::NonNull);
}
- // Attach return attributes.
- if (RetAttrs.hasAttributes()) {
- PAL.push_back(llvm::AttributeSet::get(
- getLLVMContext(), llvm::AttributeSet::ReturnIndex, RetAttrs));
- }
+ bool hasUsedSRet = false;
+ SmallVector<llvm::AttributeSet, 4> ArgAttrs(IRFunctionArgs.totalIRArgs());
// Attach attributes to sret.
if (IRFunctionArgs.hasSRetArg()) {
llvm::AttrBuilder SRETAttrs;
SRETAttrs.addAttribute(llvm::Attribute::StructRet);
+ hasUsedSRet = true;
if (RetAI.getInReg())
SRETAttrs.addAttribute(llvm::Attribute::InReg);
- PAL.push_back(llvm::AttributeSet::get(
- getLLVMContext(), IRFunctionArgs.getSRetArgNo() + 1, SRETAttrs));
+ ArgAttrs[IRFunctionArgs.getSRetArgNo()] =
+ llvm::AttributeSet::get(getLLVMContext(), SRETAttrs);
}
// Attach attributes to inalloca argument.
if (IRFunctionArgs.hasInallocaArg()) {
llvm::AttrBuilder Attrs;
Attrs.addAttribute(llvm::Attribute::InAlloca);
- PAL.push_back(llvm::AttributeSet::get(
- getLLVMContext(), IRFunctionArgs.getInallocaArgNo() + 1, Attrs));
+ ArgAttrs[IRFunctionArgs.getInallocaArgNo()] =
+ llvm::AttributeSet::get(getLLVMContext(), Attrs);
}
unsigned ArgNo = 0;
@@ -1667,10 +1996,12 @@ void CodeGenModule::ConstructAttributeList(
// Add attribute for padding argument, if necessary.
if (IRFunctionArgs.hasPaddingArg(ArgNo)) {
- if (AI.getPaddingInReg())
- PAL.push_back(llvm::AttributeSet::get(
- getLLVMContext(), IRFunctionArgs.getPaddingArgNo(ArgNo) + 1,
- llvm::Attribute::InReg));
+ if (AI.getPaddingInReg()) {
+ ArgAttrs[IRFunctionArgs.getPaddingArgNo(ArgNo)] =
+ llvm::AttributeSet::get(
+ getLLVMContext(),
+ llvm::AttrBuilder().addAttribute(llvm::Attribute::InReg));
+ }
}
// 'restrict' -> 'noalias' is done in EmitFunctionProlog when we
@@ -1686,7 +2017,7 @@ void CodeGenModule::ConstructAttributeList(
else
Attrs.addAttribute(llvm::Attribute::ZExt);
}
- // FALL THROUGH
+ LLVM_FALLTHROUGH;
case ABIArgInfo::Direct:
if (ArgNo == 0 && FI.isChainCall())
Attrs.addAttribute(llvm::Attribute::Nest);
@@ -1727,7 +2058,8 @@ void CodeGenModule::ConstructAttributeList(
}
case ABIArgInfo::Ignore:
case ABIArgInfo::Expand:
- continue;
+ case ABIArgInfo::CoerceAndExpand:
+ break;
case ABIArgInfo::InAlloca:
// inalloca disables readnone and readonly.
@@ -1745,21 +2077,57 @@ void CodeGenModule::ConstructAttributeList(
Attrs.addAttribute(llvm::Attribute::NonNull);
}
+ switch (FI.getExtParameterInfo(ArgNo).getABI()) {
+ case ParameterABI::Ordinary:
+ break;
+
+ case ParameterABI::SwiftIndirectResult: {
+ // Add 'sret' if we haven't already used it for something, but
+ // only if the result is void.
+ if (!hasUsedSRet && RetTy->isVoidType()) {
+ Attrs.addAttribute(llvm::Attribute::StructRet);
+ hasUsedSRet = true;
+ }
+
+ // Add 'noalias' in either case.
+ Attrs.addAttribute(llvm::Attribute::NoAlias);
+
+ // Add 'dereferenceable' and 'alignment'.
+ auto PTy = ParamType->getPointeeType();
+ if (!PTy->isIncompleteType() && PTy->isConstantSizeType()) {
+ auto info = getContext().getTypeInfoInChars(PTy);
+ Attrs.addDereferenceableAttr(info.first.getQuantity());
+ Attrs.addAttribute(llvm::Attribute::getWithAlignment(getLLVMContext(),
+ info.second.getQuantity()));
+ }
+ break;
+ }
+
+ case ParameterABI::SwiftErrorResult:
+ Attrs.addAttribute(llvm::Attribute::SwiftError);
+ break;
+
+ case ParameterABI::SwiftContext:
+ Attrs.addAttribute(llvm::Attribute::SwiftSelf);
+ break;
+ }
+
+ if (FI.getExtParameterInfo(ArgNo).isNoEscape())
+ Attrs.addAttribute(llvm::Attribute::NoCapture);
+
if (Attrs.hasAttributes()) {
unsigned FirstIRArg, NumIRArgs;
std::tie(FirstIRArg, NumIRArgs) = IRFunctionArgs.getIRArgs(ArgNo);
for (unsigned i = 0; i < NumIRArgs; i++)
- PAL.push_back(llvm::AttributeSet::get(getLLVMContext(),
- FirstIRArg + i + 1, Attrs));
+ ArgAttrs[FirstIRArg + i] =
+ llvm::AttributeSet::get(getLLVMContext(), Attrs);
}
}
assert(ArgNo == FI.arg_size());
- if (FuncAttrs.hasAttributes())
- PAL.push_back(llvm::
- AttributeSet::get(getLLVMContext(),
- llvm::AttributeSet::FunctionIndex,
- FuncAttrs));
+ AttrList = llvm::AttributeList::get(
+ getLLVMContext(), llvm::AttributeSet::get(getLLVMContext(), FuncAttrs),
+ llvm::AttributeSet::get(getLLVMContext(), RetAttrs), ArgAttrs);
}
/// An argument came in as a promoted argument; demote it back to its
@@ -1810,6 +2178,18 @@ static const NonNullAttr *getNonNullAttr(const Decl *FD, const ParmVarDecl *PVD,
return nullptr;
}
+namespace {
+ struct CopyBackSwiftError final : EHScopeStack::Cleanup {
+ Address Temp;
+ Address Arg;
+ CopyBackSwiftError(Address temp, Address arg) : Temp(temp), Arg(arg) {}
+ void Emit(CodeGenFunction &CGF, Flags flags) override {
+ llvm::Value *errorValue = CGF.Builder.CreateLoad(Temp);
+ CGF.Builder.CreateStore(errorValue, Arg);
+ }
+ };
+}
+
void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
llvm::Function *Fn,
const FunctionArgList &Args) {
@@ -1835,7 +2215,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
ClangToLLVMArgMapping IRFunctionArgs(CGM.getContext(), FI);
// Flattened function arguments.
- SmallVector<llvm::Argument *, 16> FnArgs;
+ SmallVector<llvm::Value *, 16> FnArgs;
FnArgs.reserve(IRFunctionArgs.totalIRArgs());
for (auto &Arg : Fn->args()) {
FnArgs.push_back(&Arg);
@@ -1856,10 +2236,9 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
// Name the struct return parameter.
if (IRFunctionArgs.hasSRetArg()) {
- auto AI = FnArgs[IRFunctionArgs.getSRetArgNo()];
+ auto AI = cast<llvm::Argument>(FnArgs[IRFunctionArgs.getSRetArgNo()]);
AI->setName("agg.result");
- AI->addAttr(llvm::AttributeSet::get(getLLVMContext(), AI->getArgNo() + 1,
- llvm::Attribute::NoAlias));
+ AI->addAttr(llvm::Attribute::NoAlias);
}
// Track if we received the parameter as a pointer (indirect, byval, or
@@ -1944,15 +2323,13 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
ArgI.getCoerceToType() == ConvertType(Ty) &&
ArgI.getDirectOffset() == 0) {
assert(NumIRArgs == 1);
- auto AI = FnArgs[FirstIRArg];
- llvm::Value *V = AI;
+ llvm::Value *V = FnArgs[FirstIRArg];
+ auto AI = cast<llvm::Argument>(V);
if (const ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(Arg)) {
if (getNonNullAttr(CurCodeDecl, PVD, PVD->getType(),
PVD->getFunctionScopeIndex()))
- AI->addAttr(llvm::AttributeSet::get(getLLVMContext(),
- AI->getArgNo() + 1,
- llvm::Attribute::NonNull));
+ AI->addAttr(llvm::Attribute::NonNull);
QualType OTy = PVD->getOriginalType();
if (const auto *ArrTy =
@@ -1969,12 +2346,9 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
llvm::AttrBuilder Attrs;
Attrs.addDereferenceableAttr(
getContext().getTypeSizeInChars(ETy).getQuantity()*ArrSize);
- AI->addAttr(llvm::AttributeSet::get(getLLVMContext(),
- AI->getArgNo() + 1, Attrs));
+ AI->addAttrs(Attrs);
} else if (getContext().getTargetAddressSpace(ETy) == 0) {
- AI->addAttr(llvm::AttributeSet::get(getLLVMContext(),
- AI->getArgNo() + 1,
- llvm::Attribute::NonNull));
+ AI->addAttr(llvm::Attribute::NonNull);
}
}
} else if (const auto *ArrTy =
@@ -1984,35 +2358,45 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
// we know that it must be nonnull.
if (ArrTy->getSizeModifier() == VariableArrayType::Static &&
!getContext().getTargetAddressSpace(ArrTy->getElementType()))
- AI->addAttr(llvm::AttributeSet::get(getLLVMContext(),
- AI->getArgNo() + 1,
- llvm::Attribute::NonNull));
+ AI->addAttr(llvm::Attribute::NonNull);
}
const auto *AVAttr = PVD->getAttr<AlignValueAttr>();
if (!AVAttr)
if (const auto *TOTy = dyn_cast<TypedefType>(OTy))
AVAttr = TOTy->getDecl()->getAttr<AlignValueAttr>();
- if (AVAttr) {
+ if (AVAttr) {
llvm::Value *AlignmentValue =
EmitScalarExpr(AVAttr->getAlignment());
llvm::ConstantInt *AlignmentCI =
cast<llvm::ConstantInt>(AlignmentValue);
- unsigned Alignment =
- std::min((unsigned) AlignmentCI->getZExtValue(),
- +llvm::Value::MaximumAlignment);
-
- llvm::AttrBuilder Attrs;
- Attrs.addAlignmentAttr(Alignment);
- AI->addAttr(llvm::AttributeSet::get(getLLVMContext(),
- AI->getArgNo() + 1, Attrs));
+ unsigned Alignment = std::min((unsigned)AlignmentCI->getZExtValue(),
+ +llvm::Value::MaximumAlignment);
+ AI->addAttrs(llvm::AttrBuilder().addAlignmentAttr(Alignment));
}
}
if (Arg->getType().isRestrictQualified())
- AI->addAttr(llvm::AttributeSet::get(getLLVMContext(),
- AI->getArgNo() + 1,
- llvm::Attribute::NoAlias));
+ AI->addAttr(llvm::Attribute::NoAlias);
+
+ // LLVM expects swifterror parameters to be used in very restricted
+ // ways. Copy the value into a less-restricted temporary.
+ if (FI.getExtParameterInfo(ArgNo).getABI()
+ == ParameterABI::SwiftErrorResult) {
+ QualType pointeeTy = Ty->getPointeeType();
+ assert(pointeeTy->isPointerType());
+ Address temp =
+ CreateMemTemp(pointeeTy, getPointerAlign(), "swifterror.temp");
+ Address arg = Address(V, getContext().getTypeAlignInChars(pointeeTy));
+ llvm::Value *incomingErrorValue = Builder.CreateLoad(arg);
+ Builder.CreateStore(incomingErrorValue, temp);
+ V = temp.getPointer();
+
+ // Push a cleanup to copy the value back at the end of the function.
+ // The convention does not guarantee that the value will be written
+ // back if the function exits with an unwind exception.
+ EHStack.pushCleanup<CopyBackSwiftError>(NormalCleanup, temp, arg);
+ }
// Ensure the argument is the correct type.
if (V->getType() != ArgI.getCoerceToType())
@@ -2021,13 +2405,6 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
if (isPromoted)
V = emitArgumentDemotion(*this, Arg, V);
- if (const CXXMethodDecl *MD =
- dyn_cast_or_null<CXXMethodDecl>(CurCodeDecl)) {
- if (MD->isVirtual() && Arg == CXXABIThisDecl)
- V = CGM.getCXXABI().
- adjustThisParameterInVirtualFunctionPrologue(*this, CurGD, V);
- }
-
// Because of merging of function types from multiple decls it is
// possible for the type of an argument to not match the corresponding
// type in the function type. Since we are codegening the callee
@@ -2058,8 +2435,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
Address AddrToStoreInto = Address::invalid();
if (SrcSize <= DstSize) {
- AddrToStoreInto =
- Builder.CreateBitCast(Ptr, llvm::PointerType::getUnqual(STy));
+ AddrToStoreInto = Builder.CreateElementBitCast(Ptr, STy);
} else {
AddrToStoreInto =
CreateTempAlloca(STy, Alloca.getAlignment(), "coerce");
@@ -2100,6 +2476,29 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
break;
}
+ case ABIArgInfo::CoerceAndExpand: {
+ // Reconstruct into a temporary.
+ Address alloca = CreateMemTemp(Ty, getContext().getDeclAlign(Arg));
+ ArgVals.push_back(ParamValue::forIndirect(alloca));
+
+ auto coercionType = ArgI.getCoerceAndExpandType();
+ alloca = Builder.CreateElementBitCast(alloca, coercionType);
+ auto layout = CGM.getDataLayout().getStructLayout(coercionType);
+
+ unsigned argIndex = FirstIRArg;
+ for (unsigned i = 0, e = coercionType->getNumElements(); i != e; ++i) {
+ llvm::Type *eltType = coercionType->getElementType(i);
+ if (ABIArgInfo::isPaddingForCoerceAndExpand(eltType))
+ continue;
+
+ auto eltAddr = Builder.CreateStructGEP(alloca, i, layout);
+ auto elt = FnArgs[argIndex++];
+ Builder.CreateStore(elt, eltAddr);
+ }
+ assert(argIndex == FirstIRArg + NumIRArgs);
+ break;
+ }
+
case ABIArgInfo::Expand: {
// If this structure was expanded into multiple arguments then
// we need to create a temporary and reconstruct it from the
@@ -2164,7 +2563,7 @@ static llvm::Value *tryEmitFusedAutoreleaseOfResult(CodeGenFunction &CGF,
// result is in a BasicBlock and is therefore an Instruction.
llvm::Instruction *generator = cast<llvm::Instruction>(result);
- SmallVector<llvm::Instruction*,4> insnsToKill;
+ SmallVector<llvm::Instruction *, 4> InstsToKill;
// Look for:
// %generator = bitcast %type1* %generator2 to %type2*
@@ -2177,7 +2576,7 @@ static llvm::Value *tryEmitFusedAutoreleaseOfResult(CodeGenFunction &CGF,
if (generator->getNextNode() != bitcast)
return nullptr;
- insnsToKill.push_back(bitcast);
+ InstsToKill.push_back(bitcast);
}
// Look for:
@@ -2210,27 +2609,26 @@ static llvm::Value *tryEmitFusedAutoreleaseOfResult(CodeGenFunction &CGF,
assert(isa<llvm::CallInst>(prev));
assert(cast<llvm::CallInst>(prev)->getCalledValue() ==
CGF.CGM.getObjCEntrypoints().retainAutoreleasedReturnValueMarker);
- insnsToKill.push_back(prev);
+ InstsToKill.push_back(prev);
}
} else {
return nullptr;
}
result = call->getArgOperand(0);
- insnsToKill.push_back(call);
+ InstsToKill.push_back(call);
// Keep killing bitcasts, for sanity. Note that we no longer care
// about precise ordering as long as there's exactly one use.
while (llvm::BitCastInst *bitcast = dyn_cast<llvm::BitCastInst>(result)) {
if (!bitcast->hasOneUse()) break;
- insnsToKill.push_back(bitcast);
+ InstsToKill.push_back(bitcast);
result = bitcast->getOperand(0);
}
// Delete all the unnecessary instructions, from latest to earliest.
- for (SmallVectorImpl<llvm::Instruction*>::iterator
- i = insnsToKill.begin(), e = insnsToKill.end(); i != e; ++i)
- (*i)->eraseFromParent();
+ for (auto *I : InstsToKill)
+ I->eraseFromParent();
// Do the fused retain/autorelease if we were asked to.
if (doRetainAutorelease)
@@ -2363,6 +2761,12 @@ static llvm::StoreInst *findDominatingStoreToReturnValue(CodeGenFunction &CGF) {
void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
bool EmitRetDbgLoc,
SourceLocation EndLoc) {
+ if (FI.isNoReturn()) {
+ // Noreturn functions don't return.
+ EmitUnreachable(EndLoc);
+ return;
+ }
+
if (CurCodeDecl && CurCodeDecl->hasAttr<NakedAttr>()) {
// Naked functions don't have epilogues.
Builder.CreateUnreachable();
@@ -2462,9 +2866,26 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
// In ARC, end functions that return a retainable type with a call
// to objc_autoreleaseReturnValue.
if (AutoreleaseResult) {
+#ifndef NDEBUG
+ // Type::isObjCRetainabletype has to be called on a QualType that hasn't
+ // been stripped of the typedefs, so we cannot use RetTy here. Get the
+ // original return type of FunctionDecl, CurCodeDecl, and BlockDecl from
+ // CurCodeDecl or BlockInfo.
+ QualType RT;
+
+ if (auto *FD = dyn_cast<FunctionDecl>(CurCodeDecl))
+ RT = FD->getReturnType();
+ else if (auto *MD = dyn_cast<ObjCMethodDecl>(CurCodeDecl))
+ RT = MD->getReturnType();
+ else if (isa<BlockDecl>(CurCodeDecl))
+ RT = BlockInfo->BlockExpression->getFunctionType()->getReturnType();
+ else
+ llvm_unreachable("Unexpected function/method type");
+
assert(getLangOpts().ObjCAutoRefCount &&
!FI.isReturnsRetained() &&
- RetTy->isObjCRetainableType());
+ RT->isObjCRetainableType());
+#endif
RV = emitAutoreleaseOfResult(*this, RV);
}
@@ -2473,25 +2894,47 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
case ABIArgInfo::Ignore:
break;
+ case ABIArgInfo::CoerceAndExpand: {
+ auto coercionType = RetAI.getCoerceAndExpandType();
+ auto layout = CGM.getDataLayout().getStructLayout(coercionType);
+
+ // Load all of the coerced elements out into results.
+ llvm::SmallVector<llvm::Value*, 4> results;
+ Address addr = Builder.CreateElementBitCast(ReturnValue, coercionType);
+ for (unsigned i = 0, e = coercionType->getNumElements(); i != e; ++i) {
+ auto coercedEltType = coercionType->getElementType(i);
+ if (ABIArgInfo::isPaddingForCoerceAndExpand(coercedEltType))
+ continue;
+
+ auto eltAddr = Builder.CreateStructGEP(addr, i, layout);
+ auto elt = Builder.CreateLoad(eltAddr);
+ results.push_back(elt);
+ }
+
+ // If we have one result, it's the single direct result type.
+ if (results.size() == 1) {
+ RV = results[0];
+
+ // Otherwise, we need to make a first-class aggregate.
+ } else {
+ // Construct a return type that lacks padding elements.
+ llvm::Type *returnType = RetAI.getUnpaddedCoerceAndExpandType();
+
+ RV = llvm::UndefValue::get(returnType);
+ for (unsigned i = 0, e = results.size(); i != e; ++i) {
+ RV = Builder.CreateInsertValue(RV, results[i], i);
+ }
+ }
+ break;
+ }
+
case ABIArgInfo::Expand:
llvm_unreachable("Invalid ABI kind for return argument");
}
llvm::Instruction *Ret;
if (RV) {
- if (CurCodeDecl && SanOpts.has(SanitizerKind::ReturnsNonnullAttribute)) {
- if (auto RetNNAttr = CurCodeDecl->getAttr<ReturnsNonNullAttr>()) {
- SanitizerScope SanScope(this);
- llvm::Value *Cond = Builder.CreateICmpNE(
- RV, llvm::Constant::getNullValue(RV->getType()));
- llvm::Constant *StaticData[] = {
- EmitCheckSourceLocation(EndLoc),
- EmitCheckSourceLocation(RetNNAttr->getLocation()),
- };
- EmitCheck(std::make_pair(Cond, SanitizerKind::ReturnsNonnullAttribute),
- "nonnull_return", StaticData, None);
- }
- }
+ EmitReturnValueCheck(RV);
Ret = Builder.CreateRet(RV);
} else {
Ret = Builder.CreateRetVoid();
@@ -2501,6 +2944,65 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
Ret->setDebugLoc(std::move(RetDbgLoc));
}
+void CodeGenFunction::EmitReturnValueCheck(llvm::Value *RV) {
+ // A current decl may not be available when emitting vtable thunks.
+ if (!CurCodeDecl)
+ return;
+
+ ReturnsNonNullAttr *RetNNAttr = nullptr;
+ if (SanOpts.has(SanitizerKind::ReturnsNonnullAttribute))
+ RetNNAttr = CurCodeDecl->getAttr<ReturnsNonNullAttr>();
+
+ if (!RetNNAttr && !requiresReturnValueNullabilityCheck())
+ return;
+
+ // Prefer the returns_nonnull attribute if it's present.
+ SourceLocation AttrLoc;
+ SanitizerMask CheckKind;
+ SanitizerHandler Handler;
+ if (RetNNAttr) {
+ assert(!requiresReturnValueNullabilityCheck() &&
+ "Cannot check nullability and the nonnull attribute");
+ AttrLoc = RetNNAttr->getLocation();
+ CheckKind = SanitizerKind::ReturnsNonnullAttribute;
+ Handler = SanitizerHandler::NonnullReturn;
+ } else {
+ if (auto *DD = dyn_cast<DeclaratorDecl>(CurCodeDecl))
+ if (auto *TSI = DD->getTypeSourceInfo())
+ if (auto FTL = TSI->getTypeLoc().castAs<FunctionTypeLoc>())
+ AttrLoc = FTL.getReturnLoc().findNullabilityLoc();
+ CheckKind = SanitizerKind::NullabilityReturn;
+ Handler = SanitizerHandler::NullabilityReturn;
+ }
+
+ SanitizerScope SanScope(this);
+
+ // Make sure the "return" source location is valid. If we're checking a
+ // nullability annotation, make sure the preconditions for the check are met.
+ llvm::BasicBlock *Check = createBasicBlock("nullcheck");
+ llvm::BasicBlock *NoCheck = createBasicBlock("no.nullcheck");
+ llvm::Value *SLocPtr = Builder.CreateLoad(ReturnLocation, "return.sloc.load");
+ llvm::Value *CanNullCheck = Builder.CreateIsNotNull(SLocPtr);
+ if (requiresReturnValueNullabilityCheck())
+ CanNullCheck =
+ Builder.CreateAnd(CanNullCheck, RetValNullabilityPrecondition);
+ Builder.CreateCondBr(CanNullCheck, Check, NoCheck);
+ EmitBlock(Check);
+
+ // Now do the null check.
+ llvm::Value *Cond = Builder.CreateIsNotNull(RV);
+ llvm::Constant *StaticData[] = {EmitCheckSourceLocation(AttrLoc)};
+ llvm::Value *DynamicData[] = {SLocPtr};
+ EmitCheck(std::make_pair(Cond, CheckKind), Handler, StaticData, DynamicData);
+
+ EmitBlock(NoCheck);
+
+#ifndef NDEBUG
+ // The return location should not be used after the check has been emitted.
+ ReturnLocation = Address::invalid();
+#endif
+}
+
static bool isInAllocaArgument(CGCXXABI &ABI, QualType type) {
const CXXRecordDecl *RD = type->getAsCXXRecordDecl();
return RD && ABI.getRecordArgABI(RD) == CGCXXABI::RAA_DirectInMemory;
@@ -2511,13 +3013,13 @@ static AggValueSlot createPlaceholderSlot(CodeGenFunction &CGF,
// FIXME: Generate IR in one pass, rather than going back and fixing up these
// placeholders.
llvm::Type *IRTy = CGF.ConvertTypeForMem(Ty);
- llvm::Value *Placeholder =
- llvm::UndefValue::get(IRTy->getPointerTo()->getPointerTo());
- Placeholder = CGF.Builder.CreateDefaultAlignedLoad(Placeholder);
+ llvm::Type *IRPtrTy = IRTy->getPointerTo();
+ llvm::Value *Placeholder = llvm::UndefValue::get(IRPtrTy->getPointerTo());
// FIXME: When we generate this IR in one pass, we shouldn't need
// this win32-specific alignment hack.
CharUnits Align = CharUnits::fromQuantity(4);
+ Placeholder = CGF.Builder.CreateAlignedLoad(IRPtrTy, Placeholder, Align);
return AggValueSlot::forAddr(Address(Placeholder, Align),
Ty.getQualifiers(),
@@ -2536,33 +3038,39 @@ void CodeGenFunction::EmitDelegateCallArg(CallArgList &args,
QualType type = param->getType();
- // For the most part, we just need to load the alloca, except:
- // 1) aggregate r-values are actually pointers to temporaries, and
- // 2) references to non-scalars are pointers directly to the aggregate.
- // I don't know why references to scalars are different here.
- if (const ReferenceType *ref = type->getAs<ReferenceType>()) {
- if (!hasScalarEvaluationKind(ref->getPointeeType()))
- return args.add(RValue::getAggregate(local), type);
-
- // Locals which are references to scalars are represented
- // with allocas holding the pointer.
- return args.add(RValue::get(Builder.CreateLoad(local)), type);
- }
-
assert(!isInAllocaArgument(CGM.getCXXABI(), type) &&
"cannot emit delegate call arguments for inalloca arguments!");
- args.add(convertTempToRValue(local, type, loc), type);
+ // GetAddrOfLocalVar returns a pointer-to-pointer for references,
+ // but the argument needs to be the original pointer.
+ if (type->isReferenceType()) {
+ args.add(RValue::get(Builder.CreateLoad(local)), type);
+
+ // In ARC, move out of consumed arguments so that the release cleanup
+ // entered by StartFunction doesn't cause an over-release. This isn't
+ // optimal -O0 code generation, but it should get cleaned up when
+ // optimization is enabled. This also assumes that delegate calls are
+ // performed exactly once for a set of arguments, but that should be safe.
+ } else if (getLangOpts().ObjCAutoRefCount &&
+ param->hasAttr<NSConsumedAttr>() &&
+ type->isObjCRetainableType()) {
+ llvm::Value *ptr = Builder.CreateLoad(local);
+ auto null =
+ llvm::ConstantPointerNull::get(cast<llvm::PointerType>(ptr->getType()));
+ Builder.CreateStore(null, local);
+ args.add(RValue::get(ptr), type);
+
+ // For the most part, we just need to load the alloca, except that
+ // aggregate r-values are actually pointers to temporaries.
+ } else {
+ args.add(convertTempToRValue(local, type, loc), type);
+ }
}
static bool isProvablyNull(llvm::Value *addr) {
return isa<llvm::ConstantPointerNull>(addr);
}
-static bool isProvablyNonNull(llvm::Value *addr) {
- return isa<llvm::AllocaInst>(addr);
-}
-
/// Emit the actual writing-back of a writeback.
static void emitWriteback(CodeGenFunction &CGF,
const CallArgList::Writeback &writeback) {
@@ -2575,7 +3083,8 @@ static void emitWriteback(CodeGenFunction &CGF,
// If the argument wasn't provably non-null, we need to null check
// before doing the store.
- bool provablyNonNull = isProvablyNonNull(srcAddr.getPointer());
+ bool provablyNonNull = llvm::isKnownNonZero(srcAddr.getPointer(),
+ CGF.CGM.getDataLayout());
if (!provablyNonNull) {
llvm::BasicBlock *writebackBB = CGF.createBasicBlock("icr.writeback");
contBB = CGF.createBasicBlock("icr.done");
@@ -2715,7 +3224,8 @@ static void emitWritebackArg(CodeGenFunction &CGF, CallArgList &args,
// If the address is *not* known to be non-null, we need to switch.
llvm::Value *finalArgument;
- bool provablyNonNull = isProvablyNonNull(srcAddr.getPointer());
+ bool provablyNonNull = llvm::isKnownNonZero(srcAddr.getPointer(),
+ CGF.CGM.getDataLayout());
if (provablyNonNull) {
finalArgument = temp.getPointer();
} else {
@@ -2786,7 +3296,7 @@ static void emitWritebackArg(CodeGenFunction &CGF, CallArgList &args,
}
void CallArgList::allocateArgumentMemory(CodeGenFunction &CGF) {
- assert(!StackBase && !StackCleanup.isValid());
+ assert(!StackBase);
// Save the stack.
llvm::Function *F = CGF.CGM.getIntrinsic(llvm::Intrinsic::stacksave);
@@ -2803,54 +3313,97 @@ void CallArgList::freeArgumentMemory(CodeGenFunction &CGF) const {
void CodeGenFunction::EmitNonNullArgCheck(RValue RV, QualType ArgType,
SourceLocation ArgLoc,
- const FunctionDecl *FD,
+ AbstractCallee AC,
unsigned ParmNum) {
- if (!SanOpts.has(SanitizerKind::NonnullAttribute) || !FD)
+ if (!AC.getDecl() || !(SanOpts.has(SanitizerKind::NonnullAttribute) ||
+ SanOpts.has(SanitizerKind::NullabilityArg)))
return;
- auto PVD = ParmNum < FD->getNumParams() ? FD->getParamDecl(ParmNum) : nullptr;
+
+ // The param decl may be missing in a variadic function.
+ auto PVD = ParmNum < AC.getNumParams() ? AC.getParamDecl(ParmNum) : nullptr;
unsigned ArgNo = PVD ? PVD->getFunctionScopeIndex() : ParmNum;
- auto NNAttr = getNonNullAttr(FD, PVD, ArgType, ArgNo);
- if (!NNAttr)
+
+ // Prefer the nonnull attribute if it's present.
+ const NonNullAttr *NNAttr = nullptr;
+ if (SanOpts.has(SanitizerKind::NonnullAttribute))
+ NNAttr = getNonNullAttr(AC.getDecl(), PVD, ArgType, ArgNo);
+
+ bool CanCheckNullability = false;
+ if (SanOpts.has(SanitizerKind::NullabilityArg) && !NNAttr && PVD) {
+ auto Nullability = PVD->getType()->getNullability(getContext());
+ CanCheckNullability = Nullability &&
+ *Nullability == NullabilityKind::NonNull &&
+ PVD->getTypeSourceInfo();
+ }
+
+ if (!NNAttr && !CanCheckNullability)
return;
+
+ SourceLocation AttrLoc;
+ SanitizerMask CheckKind;
+ SanitizerHandler Handler;
+ if (NNAttr) {
+ AttrLoc = NNAttr->getLocation();
+ CheckKind = SanitizerKind::NonnullAttribute;
+ Handler = SanitizerHandler::NonnullArg;
+ } else {
+ AttrLoc = PVD->getTypeSourceInfo()->getTypeLoc().findNullabilityLoc();
+ CheckKind = SanitizerKind::NullabilityArg;
+ Handler = SanitizerHandler::NullabilityArg;
+ }
+
SanitizerScope SanScope(this);
assert(RV.isScalar());
llvm::Value *V = RV.getScalarVal();
llvm::Value *Cond =
Builder.CreateICmpNE(V, llvm::Constant::getNullValue(V->getType()));
llvm::Constant *StaticData[] = {
- EmitCheckSourceLocation(ArgLoc),
- EmitCheckSourceLocation(NNAttr->getLocation()),
+ EmitCheckSourceLocation(ArgLoc), EmitCheckSourceLocation(AttrLoc),
llvm::ConstantInt::get(Int32Ty, ArgNo + 1),
};
- EmitCheck(std::make_pair(Cond, SanitizerKind::NonnullAttribute),
- "nonnull_arg", StaticData, None);
+ EmitCheck(std::make_pair(Cond, CheckKind), Handler, StaticData, None);
}
void CodeGenFunction::EmitCallArgs(
CallArgList &Args, ArrayRef<QualType> ArgTypes,
llvm::iterator_range<CallExpr::const_arg_iterator> ArgRange,
- const FunctionDecl *CalleeDecl, unsigned ParamsToSkip) {
+ AbstractCallee AC, unsigned ParamsToSkip, EvaluationOrder Order) {
assert((int)ArgTypes.size() == (ArgRange.end() - ArgRange.begin()));
- auto MaybeEmitImplicitObjectSize = [&](unsigned I, const Expr *Arg) {
- if (CalleeDecl == nullptr || I >= CalleeDecl->getNumParams())
+ // We *have* to evaluate arguments from right to left in the MS C++ ABI,
+ // because arguments are destroyed left to right in the callee. As a special
+ // case, there are certain language constructs that require left-to-right
+ // evaluation, and in those cases we consider the evaluation order requirement
+ // to trump the "destruction order is reverse construction order" guarantee.
+ bool LeftToRight =
+ CGM.getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee()
+ ? Order == EvaluationOrder::ForceLeftToRight
+ : Order != EvaluationOrder::ForceRightToLeft;
+
+ auto MaybeEmitImplicitObjectSize = [&](unsigned I, const Expr *Arg,
+ RValue EmittedArg) {
+ if (!AC.hasFunctionDecl() || I >= AC.getNumParams())
return;
- auto *PS = CalleeDecl->getParamDecl(I)->getAttr<PassObjectSizeAttr>();
+ auto *PS = AC.getParamDecl(I)->getAttr<PassObjectSizeAttr>();
if (PS == nullptr)
return;
const auto &Context = getContext();
auto SizeTy = Context.getSizeType();
auto T = Builder.getIntNTy(Context.getTypeSize(SizeTy));
- llvm::Value *V = evaluateOrEmitBuiltinObjectSize(Arg, PS->getType(), T);
+ assert(EmittedArg.getScalarVal() && "We emitted nothing for the arg?");
+ llvm::Value *V = evaluateOrEmitBuiltinObjectSize(Arg, PS->getType(), T,
+ EmittedArg.getScalarVal());
Args.add(RValue::get(V), SizeTy);
+ // If we're emitting args in reverse, be sure to do so with
+ // pass_object_size, as well.
+ if (!LeftToRight)
+ std::swap(Args.back(), *(&Args.back() - 1));
};
- // We *have* to evaluate arguments from right to left in the MS C++ ABI,
- // because arguments are destroyed left to right in the callee.
- if (CGM.getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee()) {
- // Insert a stack save if we're going to need any inalloca args.
- bool HasInAllocaArgs = false;
+ // Insert a stack save if we're going to need any inalloca args.
+ bool HasInAllocaArgs = false;
+ if (CGM.getTarget().getCXXABI().isMicrosoft()) {
for (ArrayRef<QualType>::iterator I = ArgTypes.begin(), E = ArgTypes.end();
I != E && !HasInAllocaArgs; ++I)
HasInAllocaArgs = isInAllocaArgument(CGM.getCXXABI(), *I);
@@ -2858,30 +3411,41 @@ void CodeGenFunction::EmitCallArgs(
assert(getTarget().getTriple().getArch() == llvm::Triple::x86);
Args.allocateArgumentMemory(*this);
}
+ }
- // Evaluate each argument.
- size_t CallArgsStart = Args.size();
- for (int I = ArgTypes.size() - 1; I >= 0; --I) {
- CallExpr::const_arg_iterator Arg = ArgRange.begin() + I;
- EmitCallArg(Args, *Arg, ArgTypes[I]);
- EmitNonNullArgCheck(Args.back().RV, ArgTypes[I], (*Arg)->getExprLoc(),
- CalleeDecl, ParamsToSkip + I);
- MaybeEmitImplicitObjectSize(I, *Arg);
- }
+ // Evaluate each argument in the appropriate order.
+ size_t CallArgsStart = Args.size();
+ for (unsigned I = 0, E = ArgTypes.size(); I != E; ++I) {
+ unsigned Idx = LeftToRight ? I : E - I - 1;
+ CallExpr::const_arg_iterator Arg = ArgRange.begin() + Idx;
+ unsigned InitialArgSize = Args.size();
+ // If *Arg is an ObjCIndirectCopyRestoreExpr, check that either the types of
+ // the argument and parameter match or the objc method is parameterized.
+ assert((!isa<ObjCIndirectCopyRestoreExpr>(*Arg) ||
+ getContext().hasSameUnqualifiedType((*Arg)->getType(),
+ ArgTypes[Idx]) ||
+ (isa<ObjCMethodDecl>(AC.getDecl()) &&
+ isObjCMethodWithTypeParams(cast<ObjCMethodDecl>(AC.getDecl())))) &&
+ "Argument and parameter types don't match");
+ EmitCallArg(Args, *Arg, ArgTypes[Idx]);
+ // In particular, we depend on it being the last arg in Args, and the
+ // objectsize bits depend on there only being one arg if !LeftToRight.
+ assert(InitialArgSize + 1 == Args.size() &&
+ "The code below depends on only adding one arg per EmitCallArg");
+ (void)InitialArgSize;
+ RValue RVArg = Args.back().RV;
+ EmitNonNullArgCheck(RVArg, ArgTypes[Idx], (*Arg)->getExprLoc(), AC,
+ ParamsToSkip + Idx);
+ // @llvm.objectsize should never have side-effects and shouldn't need
+ // destruction/cleanups, so we can safely "emit" it after its arg,
+ // regardless of right-to-leftness
+ MaybeEmitImplicitObjectSize(Idx, *Arg, RVArg);
+ }
+ if (!LeftToRight) {
// Un-reverse the arguments we just evaluated so they match up with the LLVM
// IR function.
std::reverse(Args.begin() + CallArgsStart, Args.end());
- return;
- }
-
- for (unsigned I = 0, E = ArgTypes.size(); I != E; ++I) {
- CallExpr::const_arg_iterator Arg = ArgRange.begin() + I;
- assert(Arg != ArgRange.end());
- EmitCallArg(Args, *Arg, ArgTypes[I]);
- EmitNonNullArgCheck(Args.back().RV, ArgTypes[I], (*Arg)->getExprLoc(),
- CalleeDecl, ParamsToSkip + I);
- MaybeEmitImplicitObjectSize(I, *Arg);
}
}
@@ -2923,7 +3487,6 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E,
if (const ObjCIndirectCopyRestoreExpr *CRE
= dyn_cast<ObjCIndirectCopyRestoreExpr>(E)) {
assert(getLangOpts().ObjCAutoRefCount);
- assert(getContext().hasSameType(E->getType(), type));
return emitWritebackArg(*this, args, CRE);
}
@@ -3046,24 +3609,13 @@ CodeGenFunction::EmitRuntimeCall(llvm::Value *callee,
return EmitRuntimeCall(callee, None, name);
}
-/// Emits a simple call (never an invoke) to the given runtime
-/// function.
-llvm::CallInst *
-CodeGenFunction::EmitRuntimeCall(llvm::Value *callee,
- ArrayRef<llvm::Value*> args,
- const llvm::Twine &name) {
- llvm::CallInst *call = Builder.CreateCall(callee, args, name);
- call->setCallingConv(getRuntimeCC());
- return call;
-}
-
// Calls which may throw must have operand bundles indicating which funclet
// they are nested within.
static void
-getBundlesForFunclet(llvm::Value *Callee,
- llvm::Instruction *CurrentFuncletPad,
+getBundlesForFunclet(llvm::Value *Callee, llvm::Instruction *CurrentFuncletPad,
SmallVectorImpl<llvm::OperandBundleDef> &BundleList) {
- // There is no need for a funclet operand bundle if we aren't inside a funclet.
+ // There is no need for a funclet operand bundle if we aren't inside a
+ // funclet.
if (!CurrentFuncletPad)
return;
@@ -3075,6 +3627,19 @@ getBundlesForFunclet(llvm::Value *Callee,
BundleList.emplace_back("funclet", CurrentFuncletPad);
}
+/// Emits a simple call (never an invoke) to the given runtime function.
+llvm::CallInst *
+CodeGenFunction::EmitRuntimeCall(llvm::Value *callee,
+ ArrayRef<llvm::Value*> args,
+ const llvm::Twine &name) {
+ SmallVector<llvm::OperandBundleDef, 1> BundleList;
+ getBundlesForFunclet(callee, CurrentFuncletPad, BundleList);
+
+ llvm::CallInst *call = Builder.CreateCall(callee, args, BundleList, name);
+ call->setCallingConv(getRuntimeCC());
+ return call;
+}
+
/// Emits a call or invoke to the given noreturn runtime function.
void CodeGenFunction::EmitNoreturnRuntimeCallOrInvoke(llvm::Value *callee,
ArrayRef<llvm::Value*> args) {
@@ -3098,8 +3663,7 @@ void CodeGenFunction::EmitNoreturnRuntimeCallOrInvoke(llvm::Value *callee,
}
}
-/// Emits a call or invoke instruction to the given nullary runtime
-/// function.
+/// Emits a call or invoke instruction to the given nullary runtime function.
llvm::CallSite
CodeGenFunction::EmitRuntimeCallOrInvoke(llvm::Value *callee,
const Twine &name) {
@@ -3123,13 +3687,16 @@ CodeGenFunction::EmitCallOrInvoke(llvm::Value *Callee,
ArrayRef<llvm::Value *> Args,
const Twine &Name) {
llvm::BasicBlock *InvokeDest = getInvokeDest();
+ SmallVector<llvm::OperandBundleDef, 1> BundleList;
+ getBundlesForFunclet(Callee, CurrentFuncletPad, BundleList);
llvm::Instruction *Inst;
if (!InvokeDest)
- Inst = Builder.CreateCall(Callee, Args, Name);
+ Inst = Builder.CreateCall(Callee, Args, BundleList, Name);
else {
llvm::BasicBlock *ContBB = createBasicBlock("invoke.cont");
- Inst = Builder.CreateInvoke(Callee, ContBB, InvokeDest, Args, Name);
+ Inst = Builder.CreateInvoke(Callee, ContBB, InvokeDest, Args, BundleList,
+ Name);
EmitBlock(ContBB);
}
@@ -3157,33 +3724,37 @@ void CodeGenFunction::deferPlaceholderReplacement(llvm::Instruction *Old,
}
RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
- llvm::Value *Callee,
+ const CGCallee &Callee,
ReturnValueSlot ReturnValue,
const CallArgList &CallArgs,
- CGCalleeInfo CalleeInfo,
- llvm::Instruction **callOrInvoke) {
+ llvm::Instruction **callOrInvoke,
+ SourceLocation Loc) {
// FIXME: We no longer need the types from CallArgs; lift up and simplify.
+ assert(Callee.isOrdinary());
+
// Handle struct-return functions by passing a pointer to the
// location that we would like to return into.
QualType RetTy = CallInfo.getReturnType();
const ABIArgInfo &RetAI = CallInfo.getReturnInfo();
- llvm::FunctionType *IRFuncTy =
- cast<llvm::FunctionType>(
- cast<llvm::PointerType>(Callee->getType())->getElementType());
+ llvm::FunctionType *IRFuncTy = Callee.getFunctionType();
+
+ // 1. Set up the arguments.
// If we're using inalloca, insert the allocation after the stack save.
// FIXME: Do this earlier rather than hacking it in here!
Address ArgMemory = Address::invalid();
const llvm::StructLayout *ArgMemoryLayout = nullptr;
if (llvm::StructType *ArgStruct = CallInfo.getArgStruct()) {
- ArgMemoryLayout = CGM.getDataLayout().getStructLayout(ArgStruct);
+ const llvm::DataLayout &DL = CGM.getDataLayout();
+ ArgMemoryLayout = DL.getStructLayout(ArgStruct);
llvm::Instruction *IP = CallArgs.getStackBase();
llvm::AllocaInst *AI;
if (IP) {
IP = IP->getNextNode();
- AI = new llvm::AllocaInst(ArgStruct, "argmem", IP);
+ AI = new llvm::AllocaInst(ArgStruct, DL.getAllocaAddrSpace(),
+ "argmem", IP);
} else {
AI = CreateTempAlloca(ArgStruct, "argmem");
}
@@ -3208,7 +3779,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// alloca to hold the result, unless one is given to us.
Address SRetPtr = Address::invalid();
size_t UnusedReturnSize = 0;
- if (RetAI.isIndirect() || RetAI.isInAlloca()) {
+ if (RetAI.isIndirect() || RetAI.isInAlloca() || RetAI.isCoerceAndExpand()) {
if (!ReturnValue.isNull()) {
SRetPtr = ReturnValue.getValue();
} else {
@@ -3222,12 +3793,16 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
}
if (IRFunctionArgs.hasSRetArg()) {
IRCallArgs[IRFunctionArgs.getSRetArgNo()] = SRetPtr.getPointer();
- } else {
+ } else if (RetAI.isInAlloca()) {
Address Addr = createInAllocaStructGEP(RetAI.getInAllocaFieldIndex());
Builder.CreateStore(SRetPtr.getPointer(), Addr);
}
}
+ Address swiftErrorTemp = Address::invalid();
+ Address swiftErrorArg = Address::invalid();
+
+ // Translate all of the arguments as necessary to match the IR lowering.
assert(CallInfo.arg_size() == CallArgs.size() &&
"Mismatch between function signature & arguments.");
unsigned ArgNo = 0;
@@ -3278,7 +3853,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
assert(NumIRArgs == 1);
if (RV.isScalar() || RV.isComplex()) {
// Make a temporary alloca to pass the argument.
- Address Addr = CreateMemTemp(I->Ty, ArgInfo.getIndirectAlign());
+ Address Addr = CreateMemTemp(I->Ty, ArgInfo.getIndirectAlign(),
+ "indirect-arg-temp", false);
IRCallArgs[FirstIRArg] = Addr.getPointer();
LValue argLV = MakeAddrLValue(Addr, I->Ty);
@@ -3307,7 +3883,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
< Align.getQuantity()) ||
(ArgInfo.getIndirectByVal() && (RVAddrSpace != ArgAddrSpace))) {
// Create an aligned temporary, and copy to it.
- Address AI = CreateMemTemp(I->Ty, ArgInfo.getIndirectAlign());
+ Address AI = CreateMemTemp(I->Ty, ArgInfo.getIndirectAlign(),
+ "byval-temp", false);
IRCallArgs[FirstIRArg] = AI.getPointer();
EmitAggregateCopy(AI, Addr, I->Ty, RV.isVolatileQualified());
} else {
@@ -3334,6 +3911,25 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
else
V = Builder.CreateLoad(RV.getAggregateAddress());
+ // Implement swifterror by copying into a new swifterror argument.
+ // We'll write back in the normal path out of the call.
+ if (CallInfo.getExtParameterInfo(ArgNo).getABI()
+ == ParameterABI::SwiftErrorResult) {
+ assert(!swiftErrorTemp.isValid() && "multiple swifterror args");
+
+ QualType pointeeTy = I->Ty->getPointeeType();
+ swiftErrorArg =
+ Address(V, getContext().getTypeAlignInChars(pointeeTy));
+
+ swiftErrorTemp =
+ CreateMemTemp(pointeeTy, getPointerAlign(), "swifterror.temp");
+ V = swiftErrorTemp.getPointer();
+ cast<llvm::AllocaInst>(V)->setSwiftError(true);
+
+ llvm::Value *errorValue = Builder.CreateLoad(swiftErrorArg);
+ Builder.CreateStore(errorValue, swiftErrorTemp);
+ }
+
// We might have to widen integers, but we should never truncate.
if (ArgInfo.getCoerceToType() != V->getType() &&
V->getType()->isIntegerTy())
@@ -3344,6 +3940,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
if (FirstIRArg < IRFuncTy->getNumParams() &&
V->getType() != IRFuncTy->getParamType(FirstIRArg))
V = Builder.CreateBitCast(V, IRFuncTy->getParamType(FirstIRArg));
+
IRCallArgs[FirstIRArg] = V;
break;
}
@@ -3381,7 +3978,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
Builder.CreateMemCpy(TempAlloca, Src, SrcSize);
Src = TempAlloca;
} else {
- Src = Builder.CreateBitCast(Src, llvm::PointerType::getUnqual(STy));
+ Src = Builder.CreateBitCast(Src,
+ STy->getPointerTo(Src.getAddressSpace()));
}
auto SrcLayout = CGM.getDataLayout().getStructLayout(STy);
@@ -3402,6 +4000,51 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
break;
}
+ case ABIArgInfo::CoerceAndExpand: {
+ auto coercionType = ArgInfo.getCoerceAndExpandType();
+ auto layout = CGM.getDataLayout().getStructLayout(coercionType);
+
+ llvm::Value *tempSize = nullptr;
+ Address addr = Address::invalid();
+ if (RV.isAggregate()) {
+ addr = RV.getAggregateAddress();
+ } else {
+ assert(RV.isScalar()); // complex should always just be direct
+
+ llvm::Type *scalarType = RV.getScalarVal()->getType();
+ auto scalarSize = CGM.getDataLayout().getTypeAllocSize(scalarType);
+ auto scalarAlign = CGM.getDataLayout().getPrefTypeAlignment(scalarType);
+
+ tempSize = llvm::ConstantInt::get(CGM.Int64Ty, scalarSize);
+
+ // Materialize to a temporary.
+ addr = CreateTempAlloca(RV.getScalarVal()->getType(),
+ CharUnits::fromQuantity(std::max(layout->getAlignment(),
+ scalarAlign)));
+ EmitLifetimeStart(scalarSize, addr.getPointer());
+
+ Builder.CreateStore(RV.getScalarVal(), addr);
+ }
+
+ addr = Builder.CreateElementBitCast(addr, coercionType);
+
+ unsigned IRArgPos = FirstIRArg;
+ for (unsigned i = 0, e = coercionType->getNumElements(); i != e; ++i) {
+ llvm::Type *eltType = coercionType->getElementType(i);
+ if (ABIArgInfo::isPaddingForCoerceAndExpand(eltType)) continue;
+ Address eltAddr = Builder.CreateStructGEP(addr, i, layout);
+ llvm::Value *elt = Builder.CreateLoad(eltAddr);
+ IRCallArgs[IRArgPos++] = elt;
+ }
+ assert(IRArgPos == FirstIRArg + NumIRArgs);
+
+ if (tempSize) {
+ EmitLifetimeEnd(tempSize, addr.getPointer());
+ }
+
+ break;
+ }
+
case ABIArgInfo::Expand:
unsigned IRArgPos = FirstIRArg;
ExpandTypeToArgs(I->Ty, RV, IRFuncTy, IRCallArgs, IRArgPos);
@@ -3410,6 +4053,9 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
}
}
+ llvm::Value *CalleePtr = Callee.getFunctionPointer();
+
+ // If we're using inalloca, set up that argument.
if (ArgMemory.isValid()) {
llvm::Value *Arg = ArgMemory.getPointer();
if (CallInfo.isVariadic()) {
@@ -3417,10 +4063,9 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// end up with a variadic prototype and an inalloca call site. In such
// cases, we can't do any parameter mismatch checks. Give up and bitcast
// the callee.
- unsigned CalleeAS =
- cast<llvm::PointerType>(Callee->getType())->getAddressSpace();
- Callee = Builder.CreateBitCast(
- Callee, getTypes().GetFunctionType(CallInfo)->getPointerTo(CalleeAS));
+ unsigned CalleeAS = CalleePtr->getType()->getPointerAddressSpace();
+ auto FnTy = getTypes().GetFunctionType(CallInfo)->getPointerTo(CalleeAS);
+ CalleePtr = Builder.CreateBitCast(CalleePtr, FnTy);
} else {
llvm::Type *LastParamTy =
IRFuncTy->getParamType(IRFuncTy->getNumParams() - 1);
@@ -3444,39 +4089,57 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
IRCallArgs[IRFunctionArgs.getInallocaArgNo()] = Arg;
}
- if (!CallArgs.getCleanupsToDeactivate().empty())
- deactivateArgCleanupsBeforeCall(*this, CallArgs);
+ // 2. Prepare the function pointer.
+
+ // If the callee is a bitcast of a non-variadic function to have a
+ // variadic function pointer type, check to see if we can remove the
+ // bitcast. This comes up with unprototyped functions.
+ //
+ // This makes the IR nicer, but more importantly it ensures that we
+ // can inline the function at -O0 if it is marked always_inline.
+ auto simplifyVariadicCallee = [](llvm::Value *Ptr) -> llvm::Value* {
+ llvm::FunctionType *CalleeFT =
+ cast<llvm::FunctionType>(Ptr->getType()->getPointerElementType());
+ if (!CalleeFT->isVarArg())
+ return Ptr;
+
+ llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(Ptr);
+ if (!CE || CE->getOpcode() != llvm::Instruction::BitCast)
+ return Ptr;
+
+ llvm::Function *OrigFn = dyn_cast<llvm::Function>(CE->getOperand(0));
+ if (!OrigFn)
+ return Ptr;
+
+ llvm::FunctionType *OrigFT = OrigFn->getFunctionType();
+
+ // If the original type is variadic, or if any of the component types
+ // disagree, we cannot remove the cast.
+ if (OrigFT->isVarArg() ||
+ OrigFT->getNumParams() != CalleeFT->getNumParams() ||
+ OrigFT->getReturnType() != CalleeFT->getReturnType())
+ return Ptr;
+
+ for (unsigned i = 0, e = OrigFT->getNumParams(); i != e; ++i)
+ if (OrigFT->getParamType(i) != CalleeFT->getParamType(i))
+ return Ptr;
+
+ return OrigFn;
+ };
+ CalleePtr = simplifyVariadicCallee(CalleePtr);
- // If the callee is a bitcast of a function to a varargs pointer to function
- // type, check to see if we can remove the bitcast. This handles some cases
- // with unprototyped functions.
- if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(Callee))
- if (llvm::Function *CalleeF = dyn_cast<llvm::Function>(CE->getOperand(0))) {
- llvm::PointerType *CurPT=cast<llvm::PointerType>(Callee->getType());
- llvm::FunctionType *CurFT =
- cast<llvm::FunctionType>(CurPT->getElementType());
- llvm::FunctionType *ActualFT = CalleeF->getFunctionType();
-
- if (CE->getOpcode() == llvm::Instruction::BitCast &&
- ActualFT->getReturnType() == CurFT->getReturnType() &&
- ActualFT->getNumParams() == CurFT->getNumParams() &&
- ActualFT->getNumParams() == IRCallArgs.size() &&
- (CurFT->isVarArg() || !ActualFT->isVarArg())) {
- bool ArgsMatch = true;
- for (unsigned i = 0, e = ActualFT->getNumParams(); i != e; ++i)
- if (ActualFT->getParamType(i) != CurFT->getParamType(i)) {
- ArgsMatch = false;
- break;
- }
+ // 3. Perform the actual call.
- // Strip the cast if we can get away with it. This is a nice cleanup,
- // but also allows us to inline the function at -O0 if it is marked
- // always_inline.
- if (ArgsMatch)
- Callee = CalleeF;
- }
- }
+ // Deactivate any cleanups that we're supposed to do immediately before
+ // the call.
+ if (!CallArgs.getCleanupsToDeactivate().empty())
+ deactivateArgCleanupsBeforeCall(*this, CallArgs);
+ // Assert that the arguments we computed match up. The IR verifier
+ // will catch this, but this is a common enough source of problems
+ // during IRGen changes that it's way better for debugging to catch
+ // it ourselves here.
+#ifndef NDEBUG
assert(IRCallArgs.size() == IRFuncTy->getNumParams() || IRFuncTy->isVarArg());
for (unsigned i = 0; i < IRCallArgs.size(); ++i) {
// Inalloca argument can have different type.
@@ -3486,75 +4149,117 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
if (i < IRFuncTy->getNumParams())
assert(IRCallArgs[i]->getType() == IRFuncTy->getParamType(i));
}
+#endif
+ // Compute the calling convention and attributes.
unsigned CallingConv;
- CodeGen::AttributeListType AttributeList;
- CGM.ConstructAttributeList(Callee->getName(), CallInfo, CalleeInfo,
- AttributeList, CallingConv,
+ llvm::AttributeList Attrs;
+ CGM.ConstructAttributeList(CalleePtr->getName(), CallInfo,
+ Callee.getAbstractInfo(), Attrs, CallingConv,
/*AttrOnCallSite=*/true);
- llvm::AttributeSet Attrs = llvm::AttributeSet::get(getLLVMContext(),
- AttributeList);
+ // Apply some call-site-specific attributes.
+ // TODO: work this into building the attribute set.
+
+ // Apply always_inline to all calls within flatten functions.
+ // FIXME: should this really take priority over __try, below?
+ if (CurCodeDecl && CurCodeDecl->hasAttr<FlattenAttr>() &&
+ !(Callee.getAbstractInfo().getCalleeDecl() &&
+ Callee.getAbstractInfo().getCalleeDecl()->hasAttr<NoInlineAttr>())) {
+ Attrs =
+ Attrs.addAttribute(getLLVMContext(), llvm::AttributeList::FunctionIndex,
+ llvm::Attribute::AlwaysInline);
+ }
+
+ // Disable inlining inside SEH __try blocks.
+ if (isSEHTryScope()) {
+ Attrs =
+ Attrs.addAttribute(getLLVMContext(), llvm::AttributeList::FunctionIndex,
+ llvm::Attribute::NoInline);
+ }
+
+ // Decide whether to use a call or an invoke.
bool CannotThrow;
if (currentFunctionUsesSEHTry()) {
- // SEH cares about asynchronous exceptions, everything can "throw."
+ // SEH cares about asynchronous exceptions, so everything can "throw."
CannotThrow = false;
} else if (isCleanupPadScope() &&
EHPersonality::get(*this).isMSVCXXPersonality()) {
// The MSVC++ personality will implicitly terminate the program if an
- // exception is thrown. An unwind edge cannot be reached.
+ // exception is thrown during a cleanup outside of a try/catch.
+ // We don't need to model anything in IR to get this behavior.
CannotThrow = true;
} else {
- // Otherwise, nowunind callsites will never throw.
- CannotThrow = Attrs.hasAttribute(llvm::AttributeSet::FunctionIndex,
+ // Otherwise, nounwind call sites will never throw.
+ CannotThrow = Attrs.hasAttribute(llvm::AttributeList::FunctionIndex,
llvm::Attribute::NoUnwind);
}
llvm::BasicBlock *InvokeDest = CannotThrow ? nullptr : getInvokeDest();
SmallVector<llvm::OperandBundleDef, 1> BundleList;
- getBundlesForFunclet(Callee, CurrentFuncletPad, BundleList);
+ getBundlesForFunclet(CalleePtr, CurrentFuncletPad, BundleList);
+ // Emit the actual call/invoke instruction.
llvm::CallSite CS;
if (!InvokeDest) {
- CS = Builder.CreateCall(Callee, IRCallArgs, BundleList);
+ CS = Builder.CreateCall(CalleePtr, IRCallArgs, BundleList);
} else {
llvm::BasicBlock *Cont = createBasicBlock("invoke.cont");
- CS = Builder.CreateInvoke(Callee, Cont, InvokeDest, IRCallArgs,
+ CS = Builder.CreateInvoke(CalleePtr, Cont, InvokeDest, IRCallArgs,
BundleList);
EmitBlock(Cont);
}
+ llvm::Instruction *CI = CS.getInstruction();
if (callOrInvoke)
- *callOrInvoke = CS.getInstruction();
-
- if (CurCodeDecl && CurCodeDecl->hasAttr<FlattenAttr>() &&
- !CS.hasFnAttr(llvm::Attribute::NoInline))
- Attrs =
- Attrs.addAttribute(getLLVMContext(), llvm::AttributeSet::FunctionIndex,
- llvm::Attribute::AlwaysInline);
-
- // Disable inlining inside SEH __try blocks.
- if (isSEHTryScope())
- Attrs =
- Attrs.addAttribute(getLLVMContext(), llvm::AttributeSet::FunctionIndex,
- llvm::Attribute::NoInline);
+ *callOrInvoke = CI;
+ // Apply the attributes and calling convention.
CS.setAttributes(Attrs);
CS.setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv));
+ // Apply various metadata.
+
+ if (!CI->getType()->isVoidTy())
+ CI->setName("call");
+
+ // Insert instrumentation or attach profile metadata at indirect call sites.
+ // For more details, see the comment before the definition of
+ // IPVK_IndirectCallTarget in InstrProfData.inc.
+ if (!CS.getCalledFunction())
+ PGO.valueProfile(Builder, llvm::IPVK_IndirectCallTarget,
+ CI, CalleePtr);
+
// In ObjC ARC mode with no ObjC ARC exception safety, tell the ARC
// optimizer it can aggressively ignore unwind edges.
if (CGM.getLangOpts().ObjCAutoRefCount)
- AddObjCARCExceptionMetadata(CS.getInstruction());
+ AddObjCARCExceptionMetadata(CI);
+
+ // Suppress tail calls if requested.
+ if (llvm::CallInst *Call = dyn_cast<llvm::CallInst>(CI)) {
+ const Decl *TargetDecl = Callee.getAbstractInfo().getCalleeDecl();
+ if (TargetDecl && TargetDecl->hasAttr<NotTailCalledAttr>())
+ Call->setTailCallKind(llvm::CallInst::TCK_NoTail);
+ }
+
+ // 4. Finish the call.
// If the call doesn't return, finish the basic block and clear the
- // insertion point; this allows the rest of IRgen to discard
+ // insertion point; this allows the rest of IRGen to discard
// unreachable code.
if (CS.doesNotReturn()) {
if (UnusedReturnSize)
EmitLifetimeEnd(llvm::ConstantInt::get(Int64Ty, UnusedReturnSize),
SRetPtr.getPointer());
- Builder.CreateUnreachable();
+ // Strip away the noreturn attribute to better diagnose unreachable UB.
+ if (SanOpts.has(SanitizerKind::Unreachable)) {
+ if (auto *F = CS.getCalledFunction())
+ F->removeFnAttr(llvm::Attribute::NoReturn);
+ CS.removeAttribute(llvm::AttributeList::FunctionIndex,
+ llvm::Attribute::NoReturn);
+ }
+
+ EmitUnreachable(Loc);
Builder.ClearInsertionPoint();
// FIXME: For now, emit a dummy basic block because expr emitters in
@@ -3566,12 +4271,14 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
return GetUndefRValue(RetTy);
}
- llvm::Instruction *CI = CS.getInstruction();
- if (Builder.isNamePreserving() && !CI->getType()->isVoidTy())
- CI->setName("call");
+ // Perform the swifterror writeback.
+ if (swiftErrorTemp.isValid()) {
+ llvm::Value *errorResult = Builder.CreateLoad(swiftErrorTemp);
+ Builder.CreateStore(errorResult, swiftErrorArg);
+ }
- // Emit any writebacks immediately. Arguably this should happen
- // after any return-value munging.
+ // Emit any call-associated writebacks immediately. Arguably this
+ // should happen after any return-value munging.
if (CallArgs.hasWritebacks())
emitWritebacks(*this, CallArgs);
@@ -3579,14 +4286,35 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// lexical order, so deactivate it and run it manually here.
CallArgs.freeArgumentMemory(*this);
- if (llvm::CallInst *Call = dyn_cast<llvm::CallInst>(CI)) {
- const Decl *TargetDecl = CalleeInfo.getCalleeDecl();
- if (TargetDecl && TargetDecl->hasAttr<NotTailCalledAttr>())
- Call->setTailCallKind(llvm::CallInst::TCK_NoTail);
- }
-
+ // Extract the return value.
RValue Ret = [&] {
switch (RetAI.getKind()) {
+ case ABIArgInfo::CoerceAndExpand: {
+ auto coercionType = RetAI.getCoerceAndExpandType();
+ auto layout = CGM.getDataLayout().getStructLayout(coercionType);
+
+ Address addr = SRetPtr;
+ addr = Builder.CreateElementBitCast(addr, coercionType);
+
+ assert(CI->getType() == RetAI.getUnpaddedCoerceAndExpandType());
+ bool requiresExtract = isa<llvm::StructType>(CI->getType());
+
+ unsigned unpaddedIndex = 0;
+ for (unsigned i = 0, e = coercionType->getNumElements(); i != e; ++i) {
+ llvm::Type *eltType = coercionType->getElementType(i);
+ if (ABIArgInfo::isPaddingForCoerceAndExpand(eltType)) continue;
+ Address eltAddr = Builder.CreateStructGEP(addr, i, layout);
+ llvm::Value *elt = CI;
+ if (requiresExtract)
+ elt = Builder.CreateExtractValue(elt, unpaddedIndex++);
+ else
+ assert(unpaddedIndex == 0);
+ Builder.CreateStore(elt, eltAddr);
+ }
+ // FALLTHROUGH
+ LLVM_FALLTHROUGH;
+ }
+
case ABIArgInfo::InAlloca:
case ABIArgInfo::Indirect: {
RValue ret = convertTempToRValue(SRetPtr, RetTy, SourceLocation());
@@ -3656,8 +4384,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
llvm_unreachable("Unhandled ABIArgInfo::Kind");
} ();
- const Decl *TargetDecl = CalleeInfo.getCalleeDecl();
-
+ // Emit the assume_aligned check on the return value.
+ const Decl *TargetDecl = Callee.getAbstractInfo().getCalleeDecl();
if (Ret.isScalar() && TargetDecl) {
if (const auto *AA = TargetDecl->getAttr<AssumeAlignedAttr>()) {
llvm::Value *OffsetValue = nullptr;
@@ -3668,6 +4396,10 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
llvm::ConstantInt *AlignmentCI = cast<llvm::ConstantInt>(Alignment);
EmitAlignmentAssumption(Ret.getScalarVal(), AlignmentCI->getZExtValue(),
OffsetValue);
+ } else if (const auto *AA = TargetDecl->getAttr<AllocAlignAttr>()) {
+ llvm::Value *ParamVal =
+ CallArgs[AA->getParamIndex() - 1].RV.getScalarVal();
+ EmitAlignmentAssumption(Ret.getScalarVal(), ParamVal);
}
}
diff --git a/gnu/llvm/tools/clang/lib/Driver/ToolChains/Clang.cpp b/gnu/llvm/tools/clang/lib/Driver/ToolChains/Clang.cpp
index f1137b2d928..91a656f4a48 100644
--- a/gnu/llvm/tools/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/gnu/llvm/tools/clang/lib/Driver/ToolChains/Clang.cpp
@@ -3978,6 +3978,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
else if (A->getOption().matches(options::OPT_fret_protector))
RetProtector = 1;
}
+ if (RetProtector &&
+ (getToolChain().getArch() == llvm::Triple::x86_64) &&
+ !Args.hasArg(options::OPT_fno_stack_protector) &&
+ !Args.hasArg(options::OPT_pg)) {
+ CmdArgs.push_back(Args.MakeArgString("-D_RET_PROTECTOR"));
+ CmdArgs.push_back(Args.MakeArgString(Twine("-ret-protector")));
+ }
// Translate -mstackrealign
if (Args.hasFlag(options::OPT_mstackrealign, options::OPT_mno_stackrealign,
diff --git a/gnu/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp b/gnu/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp
index 237a4470409..a637af723ab 100644
--- a/gnu/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/gnu/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/Frontend/CompilerInvocation.h"
#include "TestModuleFileExtension.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/FileManager.h"
@@ -15,11 +16,11 @@
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/Util.h"
-#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/LangStandard.h"
#include "clang/Frontend/Utils.h"
#include "clang/Lex/HeaderSearchOptions.h"
+#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/ModuleFileExtension.h"
#include "llvm/ADT/Hashing.h"
@@ -33,6 +34,7 @@
#include "llvm/Option/ArgList.h"
#include "llvm/Option/OptTable.h"
#include "llvm/Option/Option.h"
+#include "llvm/ProfileData/InstrProfReader.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
@@ -40,6 +42,7 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Target/TargetOptions.h"
+#include "llvm/Support/ScopedPrinter.h"
#include <atomic>
#include <memory>
#include <sys/stat.h>
@@ -57,12 +60,11 @@ CompilerInvocationBase::CompilerInvocationBase()
PreprocessorOpts(new PreprocessorOptions()) {}
CompilerInvocationBase::CompilerInvocationBase(const CompilerInvocationBase &X)
- : RefCountedBase<CompilerInvocation>(),
- LangOpts(new LangOptions(*X.getLangOpts())),
- TargetOpts(new TargetOptions(X.getTargetOpts())),
- DiagnosticOpts(new DiagnosticOptions(X.getDiagnosticOpts())),
- HeaderSearchOpts(new HeaderSearchOptions(X.getHeaderSearchOpts())),
- PreprocessorOpts(new PreprocessorOptions(X.getPreprocessorOpts())) {}
+ : LangOpts(new LangOptions(*X.getLangOpts())),
+ TargetOpts(new TargetOptions(X.getTargetOpts())),
+ DiagnosticOpts(new DiagnosticOptions(X.getDiagnosticOpts())),
+ HeaderSearchOpts(new HeaderSearchOptions(X.getHeaderSearchOpts())),
+ PreprocessorOpts(new PreprocessorOptions(X.getPreprocessorOpts())) {}
CompilerInvocationBase::~CompilerInvocationBase() {}
@@ -79,7 +81,7 @@ using namespace llvm::opt;
static unsigned getOptimizationLevel(ArgList &Args, InputKind IK,
DiagnosticsEngine &Diags) {
unsigned DefaultOpt = 0;
- if (IK == IK_OpenCL && !Args.hasArg(OPT_cl_opt_disable))
+ if (IK.getLanguage() == InputKind::OpenCL && !Args.hasArg(OPT_cl_opt_disable))
DefaultOpt = 2;
if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
@@ -95,6 +97,9 @@ static unsigned getOptimizationLevel(ArgList &Args, InputKind IK,
if (S == "s" || S == "z" || S.empty())
return 2;
+ if (S == "g")
+ return 1;
+
return getLastArgIntValue(Args, OPT_O, DefaultOpt, Diags);
}
@@ -235,6 +240,7 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
}
Opts.ShowCheckerHelp = Args.hasArg(OPT_analyzer_checker_help);
+ Opts.ShowEnabledCheckerList = Args.hasArg(OPT_analyzer_list_enabled_checkers);
Opts.DisableAllChecks = Args.hasArg(OPT_analyzer_disable_all_checks);
Opts.visualizeExplodedGraphWithGraphViz =
@@ -324,6 +330,17 @@ static StringRef getCodeModel(ArgList &Args, DiagnosticsEngine &Diags) {
return "default";
}
+static StringRef getRelocModel(ArgList &Args, DiagnosticsEngine &Diags) {
+ if (Arg *A = Args.getLastArg(OPT_mrelocation_model)) {
+ StringRef Value = A->getValue();
+ if (Value == "static" || Value == "pic" || Value == "ropi" ||
+ Value == "rwpi" || Value == "ropi-rwpi" || Value == "dynamic-no-pic")
+ return Value;
+ Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Value;
+ }
+ return "pic";
+}
+
/// \brief Create a new Regex instance out of the string value in \p RpassArg.
/// It returns a pointer to the newly generated Regex instance.
static std::shared_ptr<llvm::Regex>
@@ -375,6 +392,46 @@ static void parseSanitizerKinds(StringRef FlagName,
}
}
+// Set the profile kind for fprofile-instrument.
+static void setPGOInstrumentor(CodeGenOptions &Opts, ArgList &Args,
+ DiagnosticsEngine &Diags) {
+ Arg *A = Args.getLastArg(OPT_fprofile_instrument_EQ);
+ if (A == nullptr)
+ return;
+ StringRef S = A->getValue();
+ unsigned I = llvm::StringSwitch<unsigned>(S)
+ .Case("none", CodeGenOptions::ProfileNone)
+ .Case("clang", CodeGenOptions::ProfileClangInstr)
+ .Case("llvm", CodeGenOptions::ProfileIRInstr)
+ .Default(~0U);
+ if (I == ~0U) {
+ Diags.Report(diag::err_drv_invalid_pgo_instrumentor) << A->getAsString(Args)
+ << S;
+ return;
+ }
+ CodeGenOptions::ProfileInstrKind Instrumentor =
+ static_cast<CodeGenOptions::ProfileInstrKind>(I);
+ Opts.setProfileInstr(Instrumentor);
+}
+
+// Set the profile kind using fprofile-instrument-use-path.
+static void setPGOUseInstrumentor(CodeGenOptions &Opts,
+ const Twine &ProfileName) {
+ auto ReaderOrErr = llvm::IndexedInstrProfReader::create(ProfileName);
+ // In error, return silently and let Clang PGOUse report the error message.
+ if (auto E = ReaderOrErr.takeError()) {
+ llvm::consumeError(std::move(E));
+ Opts.setProfileUse(CodeGenOptions::ProfileClangInstr);
+ return;
+ }
+ std::unique_ptr<llvm::IndexedInstrProfReader> PGOReader =
+ std::move(ReaderOrErr.get());
+ if (PGOReader->isIRLevelProfile())
+ Opts.setProfileUse(CodeGenOptions::ProfileIRInstr);
+ else
+ Opts.setProfileUse(CodeGenOptions::ProfileClangInstr);
+}
+
static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
DiagnosticsEngine &Diags,
const TargetOptions &TargetOpts) {
@@ -394,19 +451,41 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
}
Opts.OptimizationLevel = OptimizationLevel;
- // We must always run at least the always inlining pass.
- Opts.setInlining(
- (Opts.OptimizationLevel > 1) ? CodeGenOptions::NormalInlining
- : CodeGenOptions::OnlyAlwaysInlining);
- // -fno-inline-functions overrides OptimizationLevel > 1.
- Opts.NoInline = Args.hasArg(OPT_fno_inline);
- Opts.setInlining(Args.hasArg(OPT_fno_inline_functions) ?
- CodeGenOptions::OnlyAlwaysInlining : Opts.getInlining());
+ // At O0 we want to fully disable inlining outside of cases marked with
+ // 'alwaysinline' that are required for correctness.
+ Opts.setInlining((Opts.OptimizationLevel == 0)
+ ? CodeGenOptions::OnlyAlwaysInlining
+ : CodeGenOptions::NormalInlining);
+ // Explicit inlining flags can disable some or all inlining even at
+ // optimization levels above zero.
+ if (Arg *InlineArg = Args.getLastArg(
+ options::OPT_finline_functions, options::OPT_finline_hint_functions,
+ options::OPT_fno_inline_functions, options::OPT_fno_inline)) {
+ if (Opts.OptimizationLevel > 0) {
+ const Option &InlineOpt = InlineArg->getOption();
+ if (InlineOpt.matches(options::OPT_finline_functions))
+ Opts.setInlining(CodeGenOptions::NormalInlining);
+ else if (InlineOpt.matches(options::OPT_finline_hint_functions))
+ Opts.setInlining(CodeGenOptions::OnlyHintInlining);
+ else
+ Opts.setInlining(CodeGenOptions::OnlyAlwaysInlining);
+ }
+ }
+
+ Opts.ExperimentalNewPassManager = Args.hasFlag(
+ OPT_fexperimental_new_pass_manager, OPT_fno_experimental_new_pass_manager,
+ /* Default */ false);
+
+ Opts.DebugPassManager =
+ Args.hasFlag(OPT_fdebug_pass_manager, OPT_fno_debug_pass_manager,
+ /* Default */ false);
if (Arg *A = Args.getLastArg(OPT_fveclib)) {
StringRef Name = A->getValue();
if (Name == "Accelerate")
Opts.setVecLib(CodeGenOptions::Accelerate);
+ else if (Name == "SVML")
+ Opts.setVecLib(CodeGenOptions::SVML);
else if (Name == "none")
Opts.setVecLib(CodeGenOptions::NoLibrary);
else
@@ -416,34 +495,40 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
if (Arg *A = Args.getLastArg(OPT_debug_info_kind_EQ)) {
unsigned Val =
llvm::StringSwitch<unsigned>(A->getValue())
- .Case("line-tables-only", CodeGenOptions::DebugLineTablesOnly)
- .Case("limited", CodeGenOptions::LimitedDebugInfo)
- .Case("standalone", CodeGenOptions::FullDebugInfo)
+ .Case("line-tables-only", codegenoptions::DebugLineTablesOnly)
+ .Case("limited", codegenoptions::LimitedDebugInfo)
+ .Case("standalone", codegenoptions::FullDebugInfo)
.Default(~0U);
if (Val == ~0U)
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args)
<< A->getValue();
else
- Opts.setDebugInfo(static_cast<CodeGenOptions::DebugInfoKind>(Val));
+ Opts.setDebugInfo(static_cast<codegenoptions::DebugInfoKind>(Val));
}
if (Arg *A = Args.getLastArg(OPT_debugger_tuning_EQ)) {
unsigned Val = llvm::StringSwitch<unsigned>(A->getValue())
- .Case("gdb", CodeGenOptions::DebuggerKindGDB)
- .Case("lldb", CodeGenOptions::DebuggerKindLLDB)
- .Case("sce", CodeGenOptions::DebuggerKindSCE)
+ .Case("gdb", unsigned(llvm::DebuggerKind::GDB))
+ .Case("lldb", unsigned(llvm::DebuggerKind::LLDB))
+ .Case("sce", unsigned(llvm::DebuggerKind::SCE))
.Default(~0U);
if (Val == ~0U)
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args)
<< A->getValue();
else
- Opts.setDebuggerTuning(static_cast<CodeGenOptions::DebuggerKind>(Val));
+ Opts.setDebuggerTuning(static_cast<llvm::DebuggerKind>(Val));
}
Opts.DwarfVersion = getLastArgIntValue(Args, OPT_dwarf_version_EQ, 0, Diags);
Opts.DebugColumnInfo = Args.hasArg(OPT_dwarf_column_info);
Opts.EmitCodeView = Args.hasArg(OPT_gcodeview);
+ Opts.MacroDebugInfo = Args.hasArg(OPT_debug_info_macro);
+ Opts.WholeProgramVTables = Args.hasArg(OPT_fwhole_program_vtables);
+ Opts.LTOVisibilityPublicStd = Args.hasArg(OPT_flto_visibility_public_std);
+ Opts.EnableSplitDwarf = Args.hasArg(OPT_enable_split_dwarf);
Opts.SplitDwarfFile = Args.getLastArgValue(OPT_split_dwarf_file);
+ Opts.SplitDwarfInlining = !Args.hasArg(OPT_fno_split_dwarf_inlining);
Opts.DebugTypeExtRefs = Args.hasArg(OPT_dwarf_ext_refs);
- Opts.DebugExplicitImport = Triple.isPS4CPU();
+ Opts.DebugExplicitImport = Args.hasArg(OPT_dwarf_explicit_import);
+ Opts.DebugFwdTemplateParams = Args.hasArg(OPT_debug_forward_template_params);
for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ))
Opts.DebugPrefixMap.insert(StringRef(Arg).split('='));
@@ -452,14 +537,20 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Args.getLastArg(OPT_emit_llvm_uselists, OPT_no_emit_llvm_uselists))
Opts.EmitLLVMUseLists = A->getOption().getID() == OPT_emit_llvm_uselists;
- Opts.DisableLLVMOpts = Args.hasArg(OPT_disable_llvm_optzns);
Opts.DisableLLVMPasses = Args.hasArg(OPT_disable_llvm_passes);
+ Opts.DisableLifetimeMarkers = Args.hasArg(OPT_disable_lifetimemarkers);
+ Opts.DisableO0ImplyOptNone = Args.hasArg(OPT_disable_O0_optnone);
Opts.DisableRedZone = Args.hasArg(OPT_disable_red_zone);
Opts.ForbidGuardVariables = Args.hasArg(OPT_fforbid_guard_variables);
Opts.UseRegisterSizedBitfieldAccess = Args.hasArg(
OPT_fuse_register_sized_bitfield_access);
Opts.RelaxedAliasing = Args.hasArg(OPT_relaxed_aliasing);
Opts.StructPathTBAA = !Args.hasArg(OPT_no_struct_path_tbaa);
+ Opts.NewStructPathTBAA = !Args.hasArg(OPT_no_struct_path_tbaa) &&
+ Args.hasArg(OPT_new_struct_path_tbaa);
+ Opts.FineGrainedBitfieldAccesses =
+ Args.hasFlag(OPT_ffine_grained_bitfield_accesses,
+ OPT_fno_fine_grained_bitfield_accesses, false);
Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags);
Opts.MergeAllConstants = !Args.hasArg(OPT_fno_merge_all_constants);
Opts.NoCommon = Args.hasArg(OPT_fno_common);
@@ -471,20 +562,57 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
getAllNoBuiltinFuncValues(Args, Opts.NoBuiltinFuncs);
Opts.UnrollLoops =
Args.hasFlag(OPT_funroll_loops, OPT_fno_unroll_loops,
- (Opts.OptimizationLevel > 1 && !Opts.OptimizeSize));
+ (Opts.OptimizationLevel > 1));
Opts.RerollLoops = Args.hasArg(OPT_freroll_loops);
Opts.DisableIntegratedAS = Args.hasArg(OPT_fno_integrated_as);
Opts.Autolink = !Args.hasArg(OPT_fno_autolink);
Opts.SampleProfileFile = Args.getLastArgValue(OPT_fprofile_sample_use_EQ);
- Opts.ProfileInstrGenerate = Args.hasArg(OPT_fprofile_instr_generate) ||
- Args.hasArg(OPT_fprofile_instr_generate_EQ);
- Opts.InstrProfileOutput = Args.getLastArgValue(OPT_fprofile_instr_generate_EQ);
- Opts.InstrProfileInput = Args.getLastArgValue(OPT_fprofile_instr_use_EQ);
+ Opts.DebugInfoForProfiling = Args.hasFlag(
+ OPT_fdebug_info_for_profiling, OPT_fno_debug_info_for_profiling, false);
+ Opts.GnuPubnames = Args.hasArg(OPT_ggnu_pubnames);
+
+ setPGOInstrumentor(Opts, Args, Diags);
+ Opts.InstrProfileOutput =
+ Args.getLastArgValue(OPT_fprofile_instrument_path_EQ);
+ Opts.ProfileInstrumentUsePath =
+ Args.getLastArgValue(OPT_fprofile_instrument_use_path_EQ);
+ if (!Opts.ProfileInstrumentUsePath.empty())
+ setPGOUseInstrumentor(Opts, Opts.ProfileInstrumentUsePath);
+
+ if (Arg *A = Args.getLastArg(OPT_fclang_abi_compat_EQ)) {
+ Opts.setClangABICompat(CodeGenOptions::ClangABI::Latest);
+
+ StringRef Ver = A->getValue();
+ std::pair<StringRef, StringRef> VerParts = Ver.split('.');
+ unsigned Major, Minor = 0;
+
+ // Check the version number is valid: either 3.x (0 <= x <= 9) or
+ // y or y.0 (4 <= y <= current version).
+ if (!VerParts.first.startswith("0") &&
+ !VerParts.first.getAsInteger(10, Major) &&
+ 3 <= Major && Major <= CLANG_VERSION_MAJOR &&
+ (Major == 3 ? VerParts.second.size() == 1 &&
+ !VerParts.second.getAsInteger(10, Minor)
+ : VerParts.first.size() == Ver.size() ||
+ VerParts.second == "0")) {
+ // Got a valid version number.
+ if (Major == 3 && Minor <= 8)
+ Opts.setClangABICompat(CodeGenOptions::ClangABI::Ver3_8);
+ else if (Major <= 4)
+ Opts.setClangABICompat(CodeGenOptions::ClangABI::Ver4);
+ } else if (Ver != "latest") {
+ Diags.Report(diag::err_drv_invalid_value)
+ << A->getAsString(Args) << A->getValue();
+ }
+ }
+
Opts.CoverageMapping =
Args.hasFlag(OPT_fcoverage_mapping, OPT_fno_coverage_mapping, false);
Opts.DumpCoverageMapping = Args.hasArg(OPT_dump_coverage_mapping);
Opts.AsmVerbose = Args.hasArg(OPT_masm_verbose);
+ Opts.PreserveAsmComments = !Args.hasArg(OPT_fno_preserve_as_comments);
+ Opts.AssumeSaneOperatorNew = !Args.hasArg(OPT_fno_assume_sane_operator_new);
Opts.ObjCAutoRefCountExceptions = Args.hasArg(OPT_fobjc_arc_exceptions);
Opts.CXAAtExit = !Args.hasArg(OPT_fno_use_cxa_atexit);
Opts.CXXCtorDtorAliases = Args.hasArg(OPT_mconstructor_aliases);
@@ -493,23 +621,12 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.DisableFPElim =
(Args.hasArg(OPT_mdisable_fp_elim) || Args.hasArg(OPT_pg));
Opts.DisableFree = Args.hasArg(OPT_disable_free);
+ Opts.DiscardValueNames = Args.hasArg(OPT_discard_value_names);
Opts.DisableTailCalls = Args.hasArg(OPT_mdisable_tail_calls);
Opts.FloatABI = Args.getLastArgValue(OPT_mfloat_abi);
- if (Arg *A = Args.getLastArg(OPT_meabi)) {
- StringRef Value = A->getValue();
- llvm::EABI EABIVersion = llvm::StringSwitch<llvm::EABI>(Value)
- .Case("default", llvm::EABI::Default)
- .Case("4", llvm::EABI::EABI4)
- .Case("5", llvm::EABI::EABI5)
- .Case("gnu", llvm::EABI::GNU)
- .Default(llvm::EABI::Unknown);
- if (EABIVersion == llvm::EABI::Unknown)
- Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args)
- << Value;
- else
- Opts.EABIVersion = Value;
- }
- Opts.LessPreciseFPMAD = Args.hasArg(OPT_cl_mad_enable);
+ Opts.LessPreciseFPMAD = Args.hasArg(OPT_cl_mad_enable) ||
+ Args.hasArg(OPT_cl_unsafe_math_optimizations) ||
+ Args.hasArg(OPT_cl_fast_relaxed_math);
Opts.LimitFloatPrecision = Args.getLastArgValue(OPT_mlimit_float_precision);
Opts.NoInfsFPMath = (Args.hasArg(OPT_menable_no_infinities) ||
Args.hasArg(OPT_cl_finite_math_only) ||
@@ -518,8 +635,17 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Args.hasArg(OPT_cl_unsafe_math_optimizations) ||
Args.hasArg(OPT_cl_finite_math_only) ||
Args.hasArg(OPT_cl_fast_relaxed_math));
- Opts.NoSignedZeros = Args.hasArg(OPT_fno_signed_zeros);
+ Opts.NoSignedZeros = (Args.hasArg(OPT_fno_signed_zeros) ||
+ Args.hasArg(OPT_cl_no_signed_zeros) ||
+ Args.hasArg(OPT_cl_unsafe_math_optimizations) ||
+ Args.hasArg(OPT_cl_fast_relaxed_math));
+ Opts.Reassociate = Args.hasArg(OPT_mreassociate);
+ Opts.FlushDenorm = Args.hasArg(OPT_cl_denorms_are_zero);
+ Opts.CorrectlyRoundedDivSqrt =
+ Args.hasArg(OPT_cl_fp32_correctly_rounded_divide_sqrt);
+ Opts.Reciprocals = Args.getAllArgValues(OPT_mrecip_EQ);
Opts.ReciprocalMath = Args.hasArg(OPT_freciprocal_math);
+ Opts.NoTrappingMath = Args.hasArg(OPT_fno_trapping_math);
Opts.NoZeroInitializedInBSS = Args.hasArg(OPT_mno_zero_initialized_in_bss);
Opts.BackendOptions = Args.getAllArgValues(OPT_backend_option);
Opts.NumRegisterParameters = getLastArgIntValue(Args, OPT_mregparm, 0, Diags);
@@ -529,17 +655,21 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.RelaxAll = Args.hasArg(OPT_mrelax_all);
Opts.IncrementalLinkerCompatible =
Args.hasArg(OPT_mincremental_linker_compatible);
+ Opts.PIECopyRelocations =
+ Args.hasArg(OPT_mpie_copy_relocations);
+ Opts.NoPLT = Args.hasArg(OPT_fno_plt);
Opts.OmitLeafFramePointer = Args.hasArg(OPT_momit_leaf_frame_pointer);
Opts.SaveTempLabels = Args.hasArg(OPT_msave_temp_labels);
Opts.NoDwarfDirectoryAsm = Args.hasArg(OPT_fno_dwarf_directory_asm);
Opts.SoftFloat = Args.hasArg(OPT_msoft_float);
Opts.StrictEnums = Args.hasArg(OPT_fstrict_enums);
+ Opts.StrictReturn = !Args.hasArg(OPT_fno_strict_return);
Opts.StrictVTablePointers = Args.hasArg(OPT_fstrict_vtable_pointers);
Opts.UnsafeFPMath = Args.hasArg(OPT_menable_unsafe_fp_math) ||
Args.hasArg(OPT_cl_unsafe_math_optimizations) ||
Args.hasArg(OPT_cl_fast_relaxed_math);
Opts.UnwindTables = Args.hasArg(OPT_munwind_tables);
- Opts.RelocationModel = Args.getLastArgValue(OPT_mrelocation_model, "pic");
+ Opts.RelocationModel = getRelocModel(Args, Diags);
Opts.ThreadModel = Args.getLastArgValue(OPT_mthread_model, "posix");
if (Opts.ThreadModel != "posix" && Opts.ThreadModel != "single")
Diags.Report(diag::err_drv_invalid_value)
@@ -557,22 +687,35 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.MergeFunctions = Args.hasArg(OPT_fmerge_functions);
+ Opts.NoUseJumpTables = Args.hasArg(OPT_fno_jump_tables);
+
+ Opts.ProfileSampleAccurate = Args.hasArg(OPT_fprofile_sample_accurate);
+
Opts.PrepareForLTO = Args.hasArg(OPT_flto, OPT_flto_EQ);
- const Arg *A = Args.getLastArg(OPT_flto, OPT_flto_EQ);
- Opts.EmitFunctionSummary = A && A->containsValue("thin");
+ Opts.EmitSummaryIndex = false;
+ if (Arg *A = Args.getLastArg(OPT_flto_EQ)) {
+ StringRef S = A->getValue();
+ if (S == "thin")
+ Opts.EmitSummaryIndex = true;
+ else if (S != "full")
+ Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << S;
+ }
+ Opts.LTOUnit = Args.hasFlag(OPT_flto_unit, OPT_fno_lto_unit, false);
if (Arg *A = Args.getLastArg(OPT_fthinlto_index_EQ)) {
- if (IK != IK_LLVM_IR)
+ if (IK.getLanguage() != InputKind::LLVM_IR)
Diags.Report(diag::err_drv_argument_only_allowed_with)
<< A->getAsString(Args) << "-x ir";
Opts.ThinLTOIndexFile = Args.getLastArgValue(OPT_fthinlto_index_EQ);
}
+ Opts.ThinLinkBitcodeFile = Args.getLastArgValue(OPT_fthin_link_bitcode_EQ);
Opts.MSVolatile = Args.hasArg(OPT_fms_volatile);
- Opts.VectorizeBB = Args.hasArg(OPT_vectorize_slp_aggressive);
Opts.VectorizeLoop = Args.hasArg(OPT_vectorize_loops);
Opts.VectorizeSLP = Args.hasArg(OPT_vectorize_slp);
+ Opts.PreferVectorWidth = Args.getLastArgValue(OPT_mprefer_vector_width_EQ);
+
Opts.MainFileName = Args.getLastArgValue(OPT_main_file_name);
Opts.VerifyModule = !Args.hasArg(OPT_disable_llvm_verifier);
@@ -580,7 +723,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.EmitGcovArcs = Args.hasArg(OPT_femit_coverage_data);
Opts.EmitGcovNotes = Args.hasArg(OPT_femit_coverage_notes);
if (Opts.EmitGcovArcs || Opts.EmitGcovNotes) {
- Opts.CoverageFile = Args.getLastArgValue(OPT_coverage_file);
+ Opts.CoverageDataFile = Args.getLastArgValue(OPT_coverage_data_file);
+ Opts.CoverageNotesFile = Args.getLastArgValue(OPT_coverage_notes_file);
Opts.CoverageExtraChecksum = Args.hasArg(OPT_coverage_cfg_checksum);
Opts.CoverageNoFunctionNamesInData =
Args.hasArg(OPT_coverage_no_function_names_in_data);
@@ -597,18 +741,89 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
}
}
}
+ // Handle -fembed-bitcode option.
+ if (Arg *A = Args.getLastArg(OPT_fembed_bitcode_EQ)) {
+ StringRef Name = A->getValue();
+ unsigned Model = llvm::StringSwitch<unsigned>(Name)
+ .Case("off", CodeGenOptions::Embed_Off)
+ .Case("all", CodeGenOptions::Embed_All)
+ .Case("bitcode", CodeGenOptions::Embed_Bitcode)
+ .Case("marker", CodeGenOptions::Embed_Marker)
+ .Default(~0U);
+ if (Model == ~0U) {
+ Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;
+ Success = false;
+ } else
+ Opts.setEmbedBitcode(
+ static_cast<CodeGenOptions::EmbedBitcodeKind>(Model));
+ }
+ // FIXME: For backend options that are not yet recorded as function
+ // attributes in the IR, keep track of them so we can embed them in a
+ // separate data section and use them when building the bitcode.
+ if (Opts.getEmbedBitcode() == CodeGenOptions::Embed_All) {
+ for (const auto &A : Args) {
+ // Do not encode output and input.
+ if (A->getOption().getID() == options::OPT_o ||
+ A->getOption().getID() == options::OPT_INPUT ||
+ A->getOption().getID() == options::OPT_x ||
+ A->getOption().getID() == options::OPT_fembed_bitcode ||
+ (A->getOption().getGroup().isValid() &&
+ A->getOption().getGroup().getID() == options::OPT_W_Group))
+ continue;
+ ArgStringList ASL;
+ A->render(Args, ASL);
+ for (const auto &arg : ASL) {
+ StringRef ArgStr(arg);
+ Opts.CmdArgs.insert(Opts.CmdArgs.end(), ArgStr.begin(), ArgStr.end());
+ // using \00 to seperate each commandline options.
+ Opts.CmdArgs.push_back('\0');
+ }
+ }
+ }
+ Opts.PreserveVec3Type = Args.hasArg(OPT_fpreserve_vec3_type);
Opts.InstrumentFunctions = Args.hasArg(OPT_finstrument_functions);
+ Opts.InstrumentFunctionsAfterInlining =
+ Args.hasArg(OPT_finstrument_functions_after_inlining);
+ Opts.InstrumentFunctionEntryBare =
+ Args.hasArg(OPT_finstrument_function_entry_bare);
+ Opts.XRayInstrumentFunctions = Args.hasArg(OPT_fxray_instrument);
+ Opts.XRayAlwaysEmitCustomEvents =
+ Args.hasArg(OPT_fxray_always_emit_customevents);
+ Opts.XRayInstructionThreshold =
+ getLastArgIntValue(Args, OPT_fxray_instruction_threshold_EQ, 200, Diags);
Opts.InstrumentForProfiling = Args.hasArg(OPT_pg);
+ Opts.CallFEntry = Args.hasArg(OPT_mfentry);
Opts.EmitOpenCLArgMetadata = Args.hasArg(OPT_cl_kernel_arg_info);
- Opts.CompressDebugSections = Args.hasArg(OPT_compress_debug_sections);
+
+ if (const Arg *A = Args.getLastArg(OPT_compress_debug_sections,
+ OPT_compress_debug_sections_EQ)) {
+ if (A->getOption().getID() == OPT_compress_debug_sections) {
+ // TODO: be more clever about the compression type auto-detection
+ Opts.setCompressDebugSections(llvm::DebugCompressionType::GNU);
+ } else {
+ auto DCT = llvm::StringSwitch<llvm::DebugCompressionType>(A->getValue())
+ .Case("none", llvm::DebugCompressionType::None)
+ .Case("zlib", llvm::DebugCompressionType::Z)
+ .Case("zlib-gnu", llvm::DebugCompressionType::GNU)
+ .Default(llvm::DebugCompressionType::None);
+ Opts.setCompressDebugSections(DCT);
+ }
+ }
+
+ Opts.RelaxELFRelocations = Args.hasArg(OPT_mrelax_relocations);
Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir);
for (auto A : Args.filtered(OPT_mlink_bitcode_file, OPT_mlink_cuda_bitcode)) {
- unsigned LinkFlags = llvm::Linker::Flags::None;
- if (A->getOption().matches(OPT_mlink_cuda_bitcode))
- LinkFlags = llvm::Linker::Flags::LinkOnlyNeeded |
- llvm::Linker::Flags::InternalizeLinkedSymbols;
- Opts.LinkBitcodeFiles.push_back(std::make_pair(LinkFlags, A->getValue()));
+ CodeGenOptions::BitcodeFileToLink F;
+ F.Filename = A->getValue();
+ if (A->getOption().matches(OPT_mlink_cuda_bitcode)) {
+ F.LinkFlags = llvm::Linker::Flags::LinkOnlyNeeded;
+ // When linking CUDA bitcode, propagate function attributes so that
+ // e.g. libdevice gets fast-math attrs if we're building with fast-math.
+ F.PropagateAttrs = true;
+ F.Internalize = true;
+ }
+ Opts.LinkBitcodeFiles.push_back(F);
}
Opts.SanitizeCoverageType =
getLastArgIntValue(Args, OPT_fsanitize_coverage_type, 0, Diags);
@@ -616,13 +831,37 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Args.hasArg(OPT_fsanitize_coverage_indirect_calls);
Opts.SanitizeCoverageTraceBB = Args.hasArg(OPT_fsanitize_coverage_trace_bb);
Opts.SanitizeCoverageTraceCmp = Args.hasArg(OPT_fsanitize_coverage_trace_cmp);
+ Opts.SanitizeCoverageTraceDiv = Args.hasArg(OPT_fsanitize_coverage_trace_div);
+ Opts.SanitizeCoverageTraceGep = Args.hasArg(OPT_fsanitize_coverage_trace_gep);
Opts.SanitizeCoverage8bitCounters =
Args.hasArg(OPT_fsanitize_coverage_8bit_counters);
+ Opts.SanitizeCoverageTracePC = Args.hasArg(OPT_fsanitize_coverage_trace_pc);
+ Opts.SanitizeCoverageTracePCGuard =
+ Args.hasArg(OPT_fsanitize_coverage_trace_pc_guard);
+ Opts.SanitizeCoverageNoPrune = Args.hasArg(OPT_fsanitize_coverage_no_prune);
+ Opts.SanitizeCoverageInline8bitCounters =
+ Args.hasArg(OPT_fsanitize_coverage_inline_8bit_counters);
+ Opts.SanitizeCoveragePCTable = Args.hasArg(OPT_fsanitize_coverage_pc_table);
+ Opts.SanitizeCoverageStackDepth =
+ Args.hasArg(OPT_fsanitize_coverage_stack_depth);
Opts.SanitizeMemoryTrackOrigins =
getLastArgIntValue(Args, OPT_fsanitize_memory_track_origins_EQ, 0, Diags);
Opts.SanitizeMemoryUseAfterDtor =
- Args.hasArg(OPT_fsanitize_memory_use_after_dtor);
+ Args.hasFlag(OPT_fsanitize_memory_use_after_dtor,
+ OPT_fno_sanitize_memory_use_after_dtor,
+ false);
+ Opts.SanitizeMinimalRuntime = Args.hasArg(OPT_fsanitize_minimal_runtime);
Opts.SanitizeCfiCrossDso = Args.hasArg(OPT_fsanitize_cfi_cross_dso);
+ Opts.SanitizeCfiICallGeneralizePointers =
+ Args.hasArg(OPT_fsanitize_cfi_icall_generalize_pointers);
+ Opts.SanitizeStats = Args.hasArg(OPT_fsanitize_stats);
+ if (Arg *A = Args.getLastArg(OPT_fsanitize_address_use_after_scope,
+ OPT_fno_sanitize_address_use_after_scope)) {
+ Opts.SanitizeAddressUseAfterScope =
+ A->getOption().getID() == OPT_fsanitize_address_use_after_scope;
+ }
+ Opts.SanitizeAddressGlobalsDeadStripping =
+ Args.hasArg(OPT_fsanitize_address_globals_dead_stripping);
Opts.SSPBufferSize =
getLastArgIntValue(Args, OPT_stack_protector_buffer_size, 8, Diags);
Opts.StackRealignment = Args.hasArg(OPT_mstackrealign);
@@ -633,6 +872,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.StackAlignment = StackAlignment;
}
+ Opts.ReturnProtector = Args.hasArg(OPT_ret_protector);
+
if (Arg *A = Args.getLastArg(OPT_mstack_probe_size)) {
StringRef Val = A->getValue();
unsigned StackProbeSize = Opts.StackProbeSize;
@@ -675,14 +916,14 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
}
}
- if (Arg *A = Args.getLastArg(OPT_ffp_contract)) {
+ if (Arg *A = Args.getLastArg(OPT_fdenormal_fp_math_EQ)) {
StringRef Val = A->getValue();
- if (Val == "fast")
- Opts.setFPContractMode(CodeGenOptions::FPC_Fast);
- else if (Val == "on")
- Opts.setFPContractMode(CodeGenOptions::FPC_On);
- else if (Val == "off")
- Opts.setFPContractMode(CodeGenOptions::FPC_Off);
+ if (Val == "ieee")
+ Opts.FPDenormalMode = "ieee";
+ else if (Val == "preserve-sign")
+ Opts.FPDenormalMode = "preserve-sign";
+ else if (Val == "positive-zero")
+ Opts.FPDenormalMode = "positive-zero";
else
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
}
@@ -697,8 +938,13 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
}
Opts.DependentLibraries = Args.getAllArgValues(OPT_dependent_lib);
+ Opts.LinkerOptions = Args.getAllArgValues(OPT_linker_option);
bool NeedLocTracking = false;
+ Opts.OptRecordFile = Args.getLastArgValue(OPT_opt_record_file);
+ if (!Opts.OptRecordFile.empty())
+ NeedLocTracking = true;
+
if (Arg *A = Args.getLastArg(OPT_Rpass_EQ)) {
Opts.OptimizationRemarkPattern =
GenerateOptimizationRemarkRegex(Diags, Args, A);
@@ -717,16 +963,32 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
NeedLocTracking = true;
}
+ Opts.DiagnosticsWithHotness =
+ Args.hasArg(options::OPT_fdiagnostics_show_hotness);
+ bool UsingSampleProfile = !Opts.SampleProfileFile.empty();
+ bool UsingProfile = UsingSampleProfile ||
+ (Opts.getProfileUse() != CodeGenOptions::ProfileNone);
+
+ if (Opts.DiagnosticsWithHotness && !UsingProfile)
+ Diags.Report(diag::warn_drv_diagnostics_hotness_requires_pgo)
+ << "-fdiagnostics-show-hotness";
+
+ Opts.DiagnosticsHotnessThreshold = getLastArgUInt64Value(
+ Args, options::OPT_fdiagnostics_hotness_threshold_EQ, 0);
+ if (Opts.DiagnosticsHotnessThreshold > 0 && !UsingProfile)
+ Diags.Report(diag::warn_drv_diagnostics_hotness_requires_pgo)
+ << "-fdiagnostics-hotness-threshold=";
+
// If the user requested to use a sample profile for PGO, then the
// backend will need to track source location information so the profile
// can be incorporated into the IR.
- if (!Opts.SampleProfileFile.empty())
+ if (UsingSampleProfile)
NeedLocTracking = true;
// If the user requested a flag that requires source locations available in
// the backend, make sure that the backend tracks source location information.
- if (NeedLocTracking && Opts.getDebugInfo() == CodeGenOptions::NoDebugInfo)
- Opts.setDebugInfo(CodeGenOptions::LocTrackingOnly);
+ if (NeedLocTracking && Opts.getDebugInfo() == codegenoptions::NoDebugInfo)
+ Opts.setDebugInfo(codegenoptions::LocTrackingOnly);
Opts.RewriteMapFiles = Args.getAllArgValues(OPT_frewrite_map_file);
@@ -742,6 +1004,11 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.CudaGpuBinaryFileNames =
Args.getAllArgValues(OPT_fcuda_include_gpubinary);
+ Opts.Backchain = Args.hasArg(OPT_mbackchain);
+
+ Opts.EmitCheckPathComponentsToStrip = getLastArgIntValue(
+ Args, OPT_fsanitize_undefined_strip_path_components_EQ, 0, Diags);
+
return Success;
}
@@ -766,13 +1033,70 @@ static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts,
// They won't be discovered by the regular preprocessor, so
// we let make / ninja to know about this implicit dependency.
Opts.ExtraDeps = Args.getAllArgValues(OPT_fdepfile_entry);
- auto ModuleFiles = Args.getAllArgValues(OPT_fmodule_file);
- Opts.ExtraDeps.insert(Opts.ExtraDeps.end(), ModuleFiles.begin(),
- ModuleFiles.end());
+ // Only the -fmodule-file=<file> form.
+ for (const Arg *A : Args.filtered(OPT_fmodule_file)) {
+ StringRef Val = A->getValue();
+ if (Val.find('=') == StringRef::npos)
+ Opts.ExtraDeps.push_back(Val);
+ }
}
-bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
+static bool parseShowColorsArgs(const ArgList &Args, bool DefaultColor) {
+ // Color diagnostics default to auto ("on" if terminal supports) in the driver
+ // but default to off in cc1, needing an explicit OPT_fdiagnostics_color.
+ // Support both clang's -f[no-]color-diagnostics and gcc's
+ // -f[no-]diagnostics-colors[=never|always|auto].
+ enum {
+ Colors_On,
+ Colors_Off,
+ Colors_Auto
+ } ShowColors = DefaultColor ? Colors_Auto : Colors_Off;
+ for (Arg *A : Args) {
+ const Option &O = A->getOption();
+ if (O.matches(options::OPT_fcolor_diagnostics) ||
+ O.matches(options::OPT_fdiagnostics_color)) {
+ ShowColors = Colors_On;
+ } else if (O.matches(options::OPT_fno_color_diagnostics) ||
+ O.matches(options::OPT_fno_diagnostics_color)) {
+ ShowColors = Colors_Off;
+ } else if (O.matches(options::OPT_fdiagnostics_color_EQ)) {
+ StringRef Value(A->getValue());
+ if (Value == "always")
+ ShowColors = Colors_On;
+ else if (Value == "never")
+ ShowColors = Colors_Off;
+ else if (Value == "auto")
+ ShowColors = Colors_Auto;
+ }
+ }
+ return ShowColors == Colors_On ||
+ (ShowColors == Colors_Auto &&
+ llvm::sys::Process::StandardErrHasColors());
+}
+
+static bool checkVerifyPrefixes(const std::vector<std::string> &VerifyPrefixes,
DiagnosticsEngine *Diags) {
+ bool Success = true;
+ for (const auto &Prefix : VerifyPrefixes) {
+ // Every prefix must start with a letter and contain only alphanumeric
+ // characters, hyphens, and underscores.
+ auto BadChar = std::find_if(Prefix.begin(), Prefix.end(),
+ [](char C){return !isAlphanumeric(C)
+ && C != '-' && C != '_';});
+ if (BadChar != Prefix.end() || !isLetter(Prefix[0])) {
+ Success = false;
+ if (Diags) {
+ Diags->Report(diag::err_drv_invalid_value) << "-verify=" << Prefix;
+ Diags->Report(diag::note_drv_verify_prefix_spelling);
+ }
+ }
+ }
+ return Success;
+}
+
+bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
+ DiagnosticsEngine *Diags,
+ bool DefaultDiagColor, bool DefaultShowOpt) {
using namespace options;
bool Success = true;
@@ -785,13 +1109,16 @@ bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
Opts.Pedantic = Args.hasArg(OPT_pedantic);
Opts.PedanticErrors = Args.hasArg(OPT_pedantic_errors);
Opts.ShowCarets = !Args.hasArg(OPT_fno_caret_diagnostics);
- Opts.ShowColors = Args.hasArg(OPT_fcolor_diagnostics);
+ Opts.ShowColors = parseShowColorsArgs(Args, DefaultDiagColor);
Opts.ShowColumn = Args.hasFlag(OPT_fshow_column,
OPT_fno_show_column,
/*Default=*/true);
Opts.ShowFixits = !Args.hasArg(OPT_fno_diagnostics_fixit_info);
Opts.ShowLocation = !Args.hasArg(OPT_fno_show_source_location);
- Opts.ShowOptionNames = Args.hasArg(OPT_fdiagnostics_show_option);
+ Opts.AbsolutePath = Args.hasArg(OPT_fdiagnostics_absolute_paths);
+ Opts.ShowOptionNames =
+ Args.hasFlag(OPT_fdiagnostics_show_option,
+ OPT_fno_diagnostics_show_option, DefaultShowOpt);
llvm::sys::Process::UseANSIEscapeCodes(Args.hasArg(OPT_fansi_escape_codes));
@@ -854,7 +1181,18 @@ bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
Opts.ShowSourceRanges = Args.hasArg(OPT_fdiagnostics_print_source_range_info);
Opts.ShowParseableFixits = Args.hasArg(OPT_fdiagnostics_parseable_fixits);
Opts.ShowPresumedLoc = !Args.hasArg(OPT_fno_diagnostics_use_presumed_location);
- Opts.VerifyDiagnostics = Args.hasArg(OPT_verify);
+ Opts.VerifyDiagnostics = Args.hasArg(OPT_verify) || Args.hasArg(OPT_verify_EQ);
+ Opts.VerifyPrefixes = Args.getAllArgValues(OPT_verify_EQ);
+ if (Args.hasArg(OPT_verify))
+ Opts.VerifyPrefixes.push_back("expected");
+ // Keep VerifyPrefixes in its original order for the sake of diagnostics, and
+ // then sort it to prepare for fast lookup using std::binary_search.
+ if (!checkVerifyPrefixes(Opts.VerifyPrefixes, Diags)) {
+ Opts.VerifyDiagnostics = false;
+ Success = false;
+ }
+ else
+ std::sort(Opts.VerifyPrefixes.begin(), Opts.VerifyPrefixes.end());
DiagnosticLevelMask DiagMask = DiagnosticLevelMask::None;
Success &= parseDiagnosticLevelMask("-verify-ignore-unexpected=",
Args.getAllArgValues(OPT_verify_ignore_unexpected_EQ),
@@ -877,6 +1215,9 @@ bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
Opts.SpellCheckingLimit = getLastArgIntValue(
Args, OPT_fspell_checking_limit,
DiagnosticOptions::DefaultSpellCheckingLimit, Diags);
+ Opts.SnippetLineLimit = getLastArgIntValue(
+ Args, OPT_fcaret_diagnostics_max_lines,
+ DiagnosticOptions::DefaultSnippetLineLimit, Diags);
Opts.TabStop = getLastArgIntValue(Args, OPT_ftabstop,
DiagnosticOptions::DefaultTabStop, Diags);
if (Opts.TabStop == 0 || Opts.TabStop > DiagnosticOptions::MaxTabStop) {
@@ -921,7 +1262,8 @@ static bool parseTestModuleFileExtensionArg(StringRef Arg,
}
static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
- DiagnosticsEngine &Diags) {
+ DiagnosticsEngine &Diags,
+ bool &IsHeaderFile) {
using namespace options;
Opts.ProgramAction = frontend::ParseSyntaxOnly;
if (const Arg *A = Args.getLastArg(OPT_Action_Group)) {
@@ -931,6 +1273,7 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
case OPT_ast_list:
Opts.ProgramAction = frontend::ASTDeclList; break;
case OPT_ast_dump:
+ case OPT_ast_dump_all:
case OPT_ast_dump_lookups:
Opts.ProgramAction = frontend::ASTDump; break;
case OPT_ast_print:
@@ -962,6 +1305,8 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
Opts.ProgramAction = frontend::FixIt; break;
case OPT_emit_module:
Opts.ProgramAction = frontend::GenerateModule; break;
+ case OPT_emit_module_interface:
+ Opts.ProgramAction = frontend::GenerateModuleInterface; break;
case OPT_emit_pch:
Opts.ProgramAction = frontend::GeneratePCH; break;
case OPT_emit_pth:
@@ -999,18 +1344,10 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
Opts.Plugins.emplace_back(A->getValue(0));
Opts.ProgramAction = frontend::PluginAction;
Opts.ActionName = A->getValue();
-
- for (const Arg *AA : Args.filtered(OPT_plugin_arg))
- if (AA->getValue(0) == Opts.ActionName)
- Opts.PluginArgs.emplace_back(AA->getValue(1));
}
-
Opts.AddPluginActions = Args.getAllArgValues(OPT_add_plugin);
- Opts.AddPluginArgs.resize(Opts.AddPluginActions.size());
- for (int i = 0, e = Opts.AddPluginActions.size(); i != e; ++i)
- for (const Arg *A : Args.filtered(OPT_plugin_arg))
- if (A->getValue(0) == Opts.AddPluginActions[i])
- Opts.AddPluginArgs[i].emplace_back(A->getValue(1));
+ for (const Arg *AA : Args.filtered(OPT_plugin_arg))
+ Opts.PluginArgs[AA->getValue(0)].emplace_back(AA->getValue(1));
for (const std::string &Arg :
Args.getAllArgValues(OPT_ftest_module_file_extension_EQ)) {
@@ -1028,8 +1365,8 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
// Add the testing module file extension.
Opts.ModuleFileExtensions.push_back(
- new TestModuleFileExtension(BlockName, MajorVersion, MinorVersion,
- Hashed, UserInfo));
+ std::make_shared<TestModuleFileExtension>(
+ BlockName, MajorVersion, MinorVersion, Hashed, UserInfo));
}
if (const Arg *A = Args.getLastArg(OPT_code_completion_at)) {
@@ -1055,14 +1392,21 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
Opts.FixAndRecompile = Args.hasArg(OPT_fixit_recompile);
Opts.FixToTemporaries = Args.hasArg(OPT_fixit_to_temp);
Opts.ASTDumpDecls = Args.hasArg(OPT_ast_dump);
+ Opts.ASTDumpAll = Args.hasArg(OPT_ast_dump_all);
Opts.ASTDumpFilter = Args.getLastArgValue(OPT_ast_dump_filter);
Opts.ASTDumpLookups = Args.hasArg(OPT_ast_dump_lookups);
Opts.UseGlobalModuleIndex = !Args.hasArg(OPT_fno_modules_global_index);
Opts.GenerateGlobalModuleIndex = Opts.UseGlobalModuleIndex;
Opts.ModuleMapFiles = Args.getAllArgValues(OPT_fmodule_map_file);
- Opts.ModuleFiles = Args.getAllArgValues(OPT_fmodule_file);
+ // Only the -fmodule-file=<file> form.
+ for (const Arg *A : Args.filtered(OPT_fmodule_file)) {
+ StringRef Val = A->getValue();
+ if (Val.find('=') == StringRef::npos)
+ Opts.ModuleFiles.push_back(Val);
+ }
Opts.ModulesEmbedFiles = Args.getAllArgValues(OPT_fmodules_embed_file_EQ);
Opts.ModulesEmbedAllFiles = Args.hasArg(OPT_fmodules_embed_all_files);
+ Opts.IncludeTimestamps = !Args.hasArg(OPT_fno_pch_timestamp);
Opts.CodeCompleteOpts.IncludeMacros
= Args.hasArg(OPT_code_completion_macros);
@@ -1070,6 +1414,8 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
= Args.hasArg(OPT_code_completion_patterns);
Opts.CodeCompleteOpts.IncludeGlobals
= !Args.hasArg(OPT_no_code_completion_globals);
+ Opts.CodeCompleteOpts.IncludeNamespaceLevelDecls
+ = !Args.hasArg(OPT_no_code_completion_ns_level_decls);
Opts.CodeCompleteOpts.IncludeBriefComments
= Args.hasArg(OPT_code_completion_brief_comments);
@@ -1077,6 +1423,8 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
= Args.getLastArgValue(OPT_foverride_record_layout_EQ);
Opts.AuxTriple =
llvm::Triple::normalize(Args.getLastArgValue(OPT_aux_triple));
+ Opts.FindPchSource = Args.getLastArgValue(OPT_find_pch_source_EQ);
+ Opts.StatsFile = Args.getLastArgValue(OPT_stats_file);
if (const Arg *A = Args.getLastArg(OPT_arcmt_check,
OPT_arcmt_modify,
@@ -1140,34 +1488,54 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
<< "ARC migration" << "ObjC migration";
}
- InputKind DashX = IK_None;
+ InputKind DashX(InputKind::Unknown);
if (const Arg *A = Args.getLastArg(OPT_x)) {
- DashX = llvm::StringSwitch<InputKind>(A->getValue())
- .Case("c", IK_C)
- .Case("cl", IK_OpenCL)
- .Case("cuda", IK_CUDA)
- .Case("c++", IK_CXX)
- .Case("objective-c", IK_ObjC)
- .Case("objective-c++", IK_ObjCXX)
- .Case("cpp-output", IK_PreprocessedC)
- .Case("assembler-with-cpp", IK_Asm)
- .Case("c++-cpp-output", IK_PreprocessedCXX)
- .Case("cuda-cpp-output", IK_PreprocessedCuda)
- .Case("objective-c-cpp-output", IK_PreprocessedObjC)
- .Case("objc-cpp-output", IK_PreprocessedObjC)
- .Case("objective-c++-cpp-output", IK_PreprocessedObjCXX)
- .Case("objc++-cpp-output", IK_PreprocessedObjCXX)
- .Case("c-header", IK_C)
- .Case("cl-header", IK_OpenCL)
- .Case("objective-c-header", IK_ObjC)
- .Case("c++-header", IK_CXX)
- .Case("objective-c++-header", IK_ObjCXX)
- .Cases("ast", "pcm", IK_AST)
- .Case("ir", IK_LLVM_IR)
- .Default(IK_None);
- if (DashX == IK_None)
+ StringRef XValue = A->getValue();
+
+ // Parse suffixes: '<lang>(-header|[-module-map][-cpp-output])'.
+ // FIXME: Supporting '<lang>-header-cpp-output' would be useful.
+ bool Preprocessed = XValue.consume_back("-cpp-output");
+ bool ModuleMap = XValue.consume_back("-module-map");
+ IsHeaderFile =
+ !Preprocessed && !ModuleMap && XValue.consume_back("-header");
+
+ // Principal languages.
+ DashX = llvm::StringSwitch<InputKind>(XValue)
+ .Case("c", InputKind::C)
+ .Case("cl", InputKind::OpenCL)
+ .Case("cuda", InputKind::CUDA)
+ .Case("c++", InputKind::CXX)
+ .Case("objective-c", InputKind::ObjC)
+ .Case("objective-c++", InputKind::ObjCXX)
+ .Case("renderscript", InputKind::RenderScript)
+ .Default(InputKind::Unknown);
+
+ // "objc[++]-cpp-output" is an acceptable synonym for
+ // "objective-c[++]-cpp-output".
+ if (DashX.isUnknown() && Preprocessed && !IsHeaderFile && !ModuleMap)
+ DashX = llvm::StringSwitch<InputKind>(XValue)
+ .Case("objc", InputKind::ObjC)
+ .Case("objc++", InputKind::ObjCXX)
+ .Default(InputKind::Unknown);
+
+ // Some special cases cannot be combined with suffixes.
+ if (DashX.isUnknown() && !Preprocessed && !ModuleMap && !IsHeaderFile)
+ DashX = llvm::StringSwitch<InputKind>(XValue)
+ .Case("cpp-output", InputKind(InputKind::C).getPreprocessed())
+ .Case("assembler-with-cpp", InputKind::Asm)
+ .Cases("ast", "pcm",
+ InputKind(InputKind::Unknown, InputKind::Precompiled))
+ .Case("ir", InputKind::LLVM_IR)
+ .Default(InputKind::Unknown);
+
+ if (DashX.isUnknown())
Diags.Report(diag::err_drv_invalid_value)
<< A->getAsString(Args) << A->getValue();
+
+ if (Preprocessed)
+ DashX = DashX.getPreprocessed();
+ if (ModuleMap)
+ DashX = DashX.withFormat(InputKind::ModuleMap);
}
// '-' is the default input if none is given.
@@ -1177,13 +1545,22 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
Inputs.push_back("-");
for (unsigned i = 0, e = Inputs.size(); i != e; ++i) {
InputKind IK = DashX;
- if (IK == IK_None) {
+ if (IK.isUnknown()) {
IK = FrontendOptions::getInputKindForExtension(
StringRef(Inputs[i]).rsplit('.').second);
+ // FIXME: Warn on this?
+ if (IK.isUnknown())
+ IK = InputKind::C;
// FIXME: Remove this hack.
if (i == 0)
DashX = IK;
}
+
+ // The -emit-module action implicitly takes a module map.
+ if (Opts.ProgramAction == frontend::GenerateModule &&
+ IK.getFormat() == InputKind::Source)
+ IK = IK.withFormat(InputKind::ModuleMap);
+
Opts.Inputs.emplace_back(std::move(Inputs[i]), IK);
}
@@ -1208,7 +1585,8 @@ std::string CompilerInvocation::GetResourcesPath(const char *Argv0,
return P.str();
}
-static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) {
+static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args,
+ const std::string &WorkingDir) {
using namespace options;
Opts.Sysroot = Args.getLastArgValue(OPT_isysroot, "/");
Opts.Verbose = Args.hasArg(OPT_v);
@@ -1218,9 +1596,31 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) {
if (const Arg *A = Args.getLastArg(OPT_stdlib_EQ))
Opts.UseLibcxx = (strcmp(A->getValue(), "libc++") == 0);
Opts.ResourceDir = Args.getLastArgValue(OPT_resource_dir);
- Opts.ModuleCachePath = Args.getLastArgValue(OPT_fmodules_cache_path);
+
+ // Canonicalize -fmodules-cache-path before storing it.
+ SmallString<128> P(Args.getLastArgValue(OPT_fmodules_cache_path));
+ if (!(P.empty() || llvm::sys::path::is_absolute(P))) {
+ if (WorkingDir.empty())
+ llvm::sys::fs::make_absolute(P);
+ else
+ llvm::sys::fs::make_absolute(WorkingDir, P);
+ }
+ llvm::sys::path::remove_dots(P);
+ Opts.ModuleCachePath = P.str();
+
Opts.ModuleUserBuildPath = Args.getLastArgValue(OPT_fmodules_user_build_path);
+ // Only the -fmodule-file=<name>=<file> form.
+ for (const Arg *A : Args.filtered(OPT_fmodule_file)) {
+ StringRef Val = A->getValue();
+ if (Val.find('=') != StringRef::npos)
+ Opts.PrebuiltModuleFiles.insert(Val.split('='));
+ }
+ for (const Arg *A : Args.filtered(OPT_fprebuilt_module_path))
+ Opts.AddPrebuiltModulePath(A->getValue());
Opts.DisableModuleHash = Args.hasArg(OPT_fdisable_module_hash);
+ Opts.ModulesHashContent = Args.hasArg(OPT_fmodules_hash_content);
+ Opts.ModulesValidateDiagnosticOptions =
+ !Args.hasArg(OPT_fmodules_disable_diagnostic_validation);
Opts.ImplicitModuleMaps = Args.hasArg(OPT_fimplicit_module_maps);
Opts.ModuleMapFileHomeIsCwd = Args.hasArg(OPT_fmodule_map_file_home_is_cwd);
Opts.ModuleCachePruneInterval =
@@ -1238,11 +1638,14 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) {
for (const Arg *A : Args.filtered(OPT_fmodules_ignore_macro)) {
StringRef MacroDef = A->getValue();
- Opts.ModulesIgnoreMacros.insert(MacroDef.split('=').first);
+ Opts.ModulesIgnoreMacros.insert(
+ llvm::CachedHashString(MacroDef.split('=').first));
}
// Add -I..., -F..., and -index-header-map options in order.
bool IsIndexHeaderMap = false;
+ bool IsSysrootSpecified =
+ Args.hasArg(OPT__sysroot_EQ) || Args.hasArg(OPT_isysroot);
for (const Arg *A : Args.filtered(OPT_I, OPT_F, OPT_index_header_map)) {
if (A->getOption().matches(OPT_index_header_map)) {
// -index-header-map applies to the next -I or -F.
@@ -1253,8 +1656,18 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) {
frontend::IncludeDirGroup Group =
IsIndexHeaderMap ? frontend::IndexHeaderMap : frontend::Angled;
- Opts.AddPath(A->getValue(), Group,
- /*IsFramework=*/A->getOption().matches(OPT_F), true);
+ bool IsFramework = A->getOption().matches(OPT_F);
+ std::string Path = A->getValue();
+
+ if (IsSysrootSpecified && !IsFramework && A->getValue()[0] == '=') {
+ SmallString<32> Buffer;
+ llvm::sys::path::append(Buffer, Opts.Sysroot,
+ llvm::StringRef(A->getValue()).substr(1));
+ Path = Buffer.str();
+ }
+
+ Opts.AddPath(Path, Group, IsFramework,
+ /*IgnoreSysroot*/ true);
IsIndexHeaderMap = false;
}
@@ -1279,6 +1692,9 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) {
!A->getOption().matches(OPT_iwithsysroot));
for (const Arg *A : Args.filtered(OPT_iframework))
Opts.AddPath(A->getValue(), frontend::System, true, true);
+ for (const Arg *A : Args.filtered(OPT_iframeworkwithsysroot))
+ Opts.AddPath(A->getValue(), frontend::System, /*IsFramework=*/true,
+ /*IgnoreSysRoot=*/false);
// Add the paths for the various language specific isystem flags.
for (const Arg *A : Args.filtered(OPT_c_isystem))
@@ -1310,45 +1726,51 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) {
}
void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
+ const llvm::Triple &T,
+ PreprocessorOptions &PPOpts,
LangStandard::Kind LangStd) {
// Set some properties which depend solely on the input kind; it would be nice
// to move these to the language standard, and have the driver resolve the
// input kind + language standard.
- if (IK == IK_Asm) {
+ //
+ // FIXME: Perhaps a better model would be for a single source file to have
+ // multiple language standards (C / C++ std, ObjC std, OpenCL std, OpenMP std)
+ // simultaneously active?
+ if (IK.getLanguage() == InputKind::Asm) {
Opts.AsmPreprocessor = 1;
- } else if (IK == IK_ObjC ||
- IK == IK_ObjCXX ||
- IK == IK_PreprocessedObjC ||
- IK == IK_PreprocessedObjCXX) {
+ } else if (IK.isObjectiveC()) {
Opts.ObjC1 = Opts.ObjC2 = 1;
}
if (LangStd == LangStandard::lang_unspecified) {
// Based on the base language, pick one.
- switch (IK) {
- case IK_None:
- case IK_AST:
- case IK_LLVM_IR:
+ switch (IK.getLanguage()) {
+ case InputKind::Unknown:
+ case InputKind::LLVM_IR:
llvm_unreachable("Invalid input kind!");
- case IK_OpenCL:
- LangStd = LangStandard::lang_opencl;
+ case InputKind::OpenCL:
+ LangStd = LangStandard::lang_opencl10;
break;
- case IK_CUDA:
- case IK_PreprocessedCuda:
+ case InputKind::CUDA:
LangStd = LangStandard::lang_cuda;
break;
- case IK_Asm:
- case IK_C:
- case IK_PreprocessedC:
- case IK_ObjC:
- case IK_PreprocessedObjC:
+ case InputKind::Asm:
+ case InputKind::C:
+ // The PS4 uses C99 as the default C standard.
+ if (T.isPS4())
+ LangStd = LangStandard::lang_gnu99;
+ else
+ LangStd = LangStandard::lang_gnu11;
+ break;
+ case InputKind::ObjC:
LangStd = LangStandard::lang_gnu11;
break;
- case IK_CXX:
- case IK_PreprocessedCXX:
- case IK_ObjCXX:
- case IK_PreprocessedObjCXX:
- LangStd = LangStandard::lang_gnucxx98;
+ case InputKind::CXX:
+ case InputKind::ObjCXX:
+ LangStd = LangStandard::lang_gnucxx14;
+ break;
+ case InputKind::RenderScript:
+ LangStd = LangStandard::lang_c99;
break;
}
}
@@ -1357,19 +1779,21 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
Opts.LineComment = Std.hasLineComments();
Opts.C99 = Std.isC99();
Opts.C11 = Std.isC11();
+ Opts.C17 = Std.isC17();
Opts.CPlusPlus = Std.isCPlusPlus();
Opts.CPlusPlus11 = Std.isCPlusPlus11();
Opts.CPlusPlus14 = Std.isCPlusPlus14();
- Opts.CPlusPlus1z = Std.isCPlusPlus1z();
+ Opts.CPlusPlus17 = Std.isCPlusPlus17();
+ Opts.CPlusPlus2a = Std.isCPlusPlus2a();
Opts.Digraphs = Std.hasDigraphs();
Opts.GNUMode = Std.isGNUMode();
- Opts.GNUInline = Std.isC89();
+ Opts.GNUInline = !Opts.C99 && !Opts.CPlusPlus;
Opts.HexFloats = Std.hasHexFloats();
Opts.ImplicitInt = Std.hasImplicitInt();
// Set OpenCL Version.
- Opts.OpenCL = LangStd == LangStandard::lang_opencl || IK == IK_OpenCL;
- if (LangStd == LangStandard::lang_opencl)
+ Opts.OpenCL = Std.isOpenCL();
+ if (LangStd == LangStandard::lang_opencl10)
Opts.OpenCLVersion = 100;
else if (LangStd == LangStandard::lang_opencl11)
Opts.OpenCLVersion = 110;
@@ -1382,14 +1806,26 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
if (Opts.OpenCL) {
Opts.AltiVec = 0;
Opts.ZVector = 0;
- Opts.CXXOperatorNames = 1;
Opts.LaxVectorConversions = 0;
- Opts.DefaultFPContract = 1;
+ Opts.setDefaultFPContractMode(LangOptions::FPC_On);
Opts.NativeHalfType = 1;
+ Opts.NativeHalfArgsAndReturns = 1;
+ // Include default header file for OpenCL.
+ if (Opts.IncludeDefaultHeader) {
+ PPOpts.Includes.push_back("opencl-c.h");
+ }
}
- Opts.CUDA = IK == IK_CUDA || IK == IK_PreprocessedCuda ||
- LangStd == LangStandard::lang_cuda;
+ Opts.CUDA = IK.getLanguage() == InputKind::CUDA;
+ if (Opts.CUDA)
+ // Set default FP_CONTRACT to FAST.
+ Opts.setDefaultFPContractMode(LangOptions::FPC_Fast);
+
+ Opts.RenderScript = IK.getLanguage() == InputKind::RenderScript;
+ if (Opts.RenderScript) {
+ Opts.NativeHalfType = 1;
+ Opts.NativeHalfArgsAndReturns = 1;
+ }
// OpenCL and C++ both have bool, true, false keywords.
Opts.Bool = Opts.OpenCL || Opts.CPlusPlus;
@@ -1403,6 +1839,8 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
Opts.GNUKeywords = Opts.GNUMode;
Opts.CXXOperatorNames = Opts.CPlusPlus;
+ Opts.AlignedAllocation = Opts.CPlusPlus17;
+
Opts.DollarIdents = !Opts.AsmPreprocessor;
}
@@ -1424,53 +1862,117 @@ static Visibility parseVisibility(Arg *arg, ArgList &args,
return DefaultVisibility;
}
+/// Check if input file kind and language standard are compatible.
+static bool IsInputCompatibleWithStandard(InputKind IK,
+ const LangStandard &S) {
+ switch (IK.getLanguage()) {
+ case InputKind::Unknown:
+ case InputKind::LLVM_IR:
+ llvm_unreachable("should not parse language flags for this input");
+
+ case InputKind::C:
+ case InputKind::ObjC:
+ case InputKind::RenderScript:
+ return S.getLanguage() == InputKind::C;
+
+ case InputKind::OpenCL:
+ return S.getLanguage() == InputKind::OpenCL;
+
+ case InputKind::CXX:
+ case InputKind::ObjCXX:
+ return S.getLanguage() == InputKind::CXX;
+
+ case InputKind::CUDA:
+ // FIXME: What -std= values should be permitted for CUDA compilations?
+ return S.getLanguage() == InputKind::CUDA ||
+ S.getLanguage() == InputKind::CXX;
+
+ case InputKind::Asm:
+ // Accept (and ignore) all -std= values.
+ // FIXME: The -std= value is not ignored; it affects the tokenization
+ // and preprocessing rules if we're preprocessing this asm input.
+ return true;
+ }
+
+ llvm_unreachable("unexpected input language");
+}
+
+/// Get language name for given input kind.
+static const StringRef GetInputKindName(InputKind IK) {
+ switch (IK.getLanguage()) {
+ case InputKind::C:
+ return "C";
+ case InputKind::ObjC:
+ return "Objective-C";
+ case InputKind::CXX:
+ return "C++";
+ case InputKind::ObjCXX:
+ return "Objective-C++";
+ case InputKind::OpenCL:
+ return "OpenCL";
+ case InputKind::CUDA:
+ return "CUDA";
+ case InputKind::RenderScript:
+ return "RenderScript";
+
+ case InputKind::Asm:
+ return "Asm";
+ case InputKind::LLVM_IR:
+ return "LLVM IR";
+
+ case InputKind::Unknown:
+ break;
+ }
+ llvm_unreachable("unknown input language");
+}
+
static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
+ const TargetOptions &TargetOpts,
+ PreprocessorOptions &PPOpts,
DiagnosticsEngine &Diags) {
// FIXME: Cleanup per-file based stuff.
LangStandard::Kind LangStd = LangStandard::lang_unspecified;
if (const Arg *A = Args.getLastArg(OPT_std_EQ)) {
LangStd = llvm::StringSwitch<LangStandard::Kind>(A->getValue())
-#define LANGSTANDARD(id, name, desc, features) \
+#define LANGSTANDARD(id, name, lang, desc, features) \
.Case(name, LangStandard::lang_##id)
+#define LANGSTANDARD_ALIAS(id, alias) \
+ .Case(alias, LangStandard::lang_##id)
#include "clang/Frontend/LangStandards.def"
.Default(LangStandard::lang_unspecified);
- if (LangStd == LangStandard::lang_unspecified)
+ if (LangStd == LangStandard::lang_unspecified) {
Diags.Report(diag::err_drv_invalid_value)
<< A->getAsString(Args) << A->getValue();
- else {
+ // Report supported standards with short description.
+ for (unsigned KindValue = 0;
+ KindValue != LangStandard::lang_unspecified;
+ ++KindValue) {
+ const LangStandard &Std = LangStandard::getLangStandardForKind(
+ static_cast<LangStandard::Kind>(KindValue));
+ if (IsInputCompatibleWithStandard(IK, Std)) {
+ auto Diag = Diags.Report(diag::note_drv_use_standard);
+ Diag << Std.getName() << Std.getDescription();
+ unsigned NumAliases = 0;
+#define LANGSTANDARD(id, name, lang, desc, features)
+#define LANGSTANDARD_ALIAS(id, alias) \
+ if (KindValue == LangStandard::lang_##id) ++NumAliases;
+#define LANGSTANDARD_ALIAS_DEPR(id, alias)
+#include "clang/Frontend/LangStandards.def"
+ Diag << NumAliases;
+#define LANGSTANDARD(id, name, lang, desc, features)
+#define LANGSTANDARD_ALIAS(id, alias) \
+ if (KindValue == LangStandard::lang_##id) Diag << alias;
+#define LANGSTANDARD_ALIAS_DEPR(id, alias)
+#include "clang/Frontend/LangStandards.def"
+ }
+ }
+ } else {
// Valid standard, check to make sure language and standard are
// compatible.
const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd);
- switch (IK) {
- case IK_C:
- case IK_ObjC:
- case IK_PreprocessedC:
- case IK_PreprocessedObjC:
- if (!(Std.isC89() || Std.isC99()))
- Diags.Report(diag::err_drv_argument_not_allowed_with)
- << A->getAsString(Args) << "C/ObjC";
- break;
- case IK_CXX:
- case IK_ObjCXX:
- case IK_PreprocessedCXX:
- case IK_PreprocessedObjCXX:
- if (!Std.isCPlusPlus())
- Diags.Report(diag::err_drv_argument_not_allowed_with)
- << A->getAsString(Args) << "C++/ObjC++";
- break;
- case IK_OpenCL:
- if (!Std.isC99())
- Diags.Report(diag::err_drv_argument_not_allowed_with)
- << A->getAsString(Args) << "OpenCL";
- break;
- case IK_CUDA:
- case IK_PreprocessedCuda:
- if (!Std.isCPlusPlus())
- Diags.Report(diag::err_drv_argument_not_allowed_with)
- << A->getAsString(Args) << "CUDA";
- break;
- default:
- break;
+ if (!IsInputCompatibleWithStandard(IK, Std)) {
+ Diags.Report(diag::err_drv_argument_not_allowed_with)
+ << A->getAsString(Args) << GetInputKindName(IK);
}
}
}
@@ -1479,22 +1981,37 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
// Override the -std option in this case.
if (const Arg *A = Args.getLastArg(OPT_cl_std_EQ)) {
LangStandard::Kind OpenCLLangStd
- = llvm::StringSwitch<LangStandard::Kind>(A->getValue())
- .Case("CL", LangStandard::lang_opencl)
- .Case("CL1.1", LangStandard::lang_opencl11)
- .Case("CL1.2", LangStandard::lang_opencl12)
- .Case("CL2.0", LangStandard::lang_opencl20)
- .Default(LangStandard::lang_unspecified);
+ = llvm::StringSwitch<LangStandard::Kind>(A->getValue())
+ .Cases("cl", "CL", LangStandard::lang_opencl10)
+ .Cases("cl1.1", "CL1.1", LangStandard::lang_opencl11)
+ .Cases("cl1.2", "CL1.2", LangStandard::lang_opencl12)
+ .Cases("cl2.0", "CL2.0", LangStandard::lang_opencl20)
+ .Default(LangStandard::lang_unspecified);
if (OpenCLLangStd == LangStandard::lang_unspecified) {
Diags.Report(diag::err_drv_invalid_value)
- << A->getAsString(Args) << A->getValue();
+ << A->getAsString(Args) << A->getValue();
}
else
LangStd = OpenCLLangStd;
}
- CompilerInvocation::setLangDefaults(Opts, IK, LangStd);
+ Opts.IncludeDefaultHeader = Args.hasArg(OPT_finclude_default_header);
+
+ llvm::Triple T(TargetOpts.Triple);
+ CompilerInvocation::setLangDefaults(Opts, IK, T, PPOpts, LangStd);
+
+ // -cl-strict-aliasing needs to emit diagnostic in the case where CL > 1.0.
+ // This option should be deprecated for CL > 1.0 because
+ // this option was added for compatibility with OpenCL 1.0.
+ if (Args.getLastArg(OPT_cl_strict_aliasing)
+ && Opts.OpenCLVersion > 100) {
+ std::string VerSpec = llvm::to_string(Opts.OpenCLVersion / 100) +
+ std::string(".") +
+ llvm::to_string((Opts.OpenCLVersion % 100) / 10);
+ Diags.Report(diag::warn_option_invalid_ocl_version)
+ << VerSpec << Args.getLastArg(OPT_cl_strict_aliasing)->getAsString(Args);
+ }
// We abuse '-f[no-]gnu-keywords' to force overriding all GNU-extension
// keywords. This behavior is provided by GCC's poorly named '-fasm' flag,
@@ -1510,14 +2027,17 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
if (Args.hasArg(OPT_fcuda_is_device))
Opts.CUDAIsDevice = 1;
- if (Args.hasArg(OPT_fcuda_allow_host_calls_from_host_device))
- Opts.CUDAAllowHostCallsFromHostDevice = 1;
+ if (Args.hasArg(OPT_fcuda_allow_variadic_functions))
+ Opts.CUDAAllowVariadicFunctions = 1;
+
+ if (Args.hasArg(OPT_fno_cuda_host_device_constexpr))
+ Opts.CUDAHostDeviceConstexpr = 0;
- if (Args.hasArg(OPT_fcuda_disable_target_call_checks))
- Opts.CUDADisableTargetCallChecks = 1;
+ if (Opts.CUDAIsDevice && Args.hasArg(OPT_fcuda_flush_denormals_to_zero))
+ Opts.CUDADeviceFlushDenormalsToZero = 1;
- if (Args.hasArg(OPT_fcuda_target_overloads))
- Opts.CUDATargetOverloads = 1;
+ if (Opts.CUDAIsDevice && Args.hasArg(OPT_fcuda_approx_transcendentals))
+ Opts.CUDADeviceApproxTranscendentals = 1;
if (Opts.ObjC1) {
if (Arg *arg = Args.getLastArg(OPT_fobjc_runtime_EQ)) {
@@ -1571,8 +2091,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
if (Args.hasArg(OPT_fgnu89_inline)) {
if (Opts.CPlusPlus)
- Diags.Report(diag::err_drv_argument_not_allowed_with) << "-fgnu89-inline"
- << "C++/ObjC++";
+ Diags.Report(diag::err_drv_argument_not_allowed_with)
+ << "-fgnu89-inline" << GetInputKindName(IK);
else
Opts.GNUInline = 1;
}
@@ -1589,9 +2109,6 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
if (Args.hasArg(OPT_fno_constant_cfstrings))
Opts.NoConstantCFStrings = 1;
- if (Args.hasArg(OPT_faltivec))
- Opts.AltiVec = 1;
-
if (Args.hasArg(OPT_fzvector))
Opts.ZVector = 1;
@@ -1641,7 +2158,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
// Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs
// is specified, or -std is set to a conforming mode.
// Trigraphs are disabled by default in c++1z onwards.
- Opts.Trigraphs = !Opts.GNUMode && !Opts.MSVCCompat && !Opts.CPlusPlus1z;
+ Opts.Trigraphs = !Opts.GNUMode && !Opts.MSVCCompat && !Opts.CPlusPlus17;
Opts.Trigraphs =
Args.hasFlag(OPT_ftrigraphs, OPT_fno_trigraphs, Opts.Trigraphs);
@@ -1661,20 +2178,42 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.Exceptions = Args.hasArg(OPT_fexceptions);
Opts.ObjCExceptions = Args.hasArg(OPT_fobjc_exceptions);
Opts.CXXExceptions = Args.hasArg(OPT_fcxx_exceptions);
- Opts.SjLjExceptions = Args.hasArg(OPT_fsjlj_exceptions);
+
+ // Handle exception personalities
+ Arg *A = Args.getLastArg(options::OPT_fsjlj_exceptions,
+ options::OPT_fseh_exceptions,
+ options::OPT_fdwarf_exceptions);
+ if (A) {
+ const Option &Opt = A->getOption();
+ Opts.SjLjExceptions = Opt.matches(options::OPT_fsjlj_exceptions);
+ Opts.SEHExceptions = Opt.matches(options::OPT_fseh_exceptions);
+ Opts.DWARFExceptions = Opt.matches(options::OPT_fdwarf_exceptions);
+ }
+
+ Opts.ExternCNoUnwind = Args.hasArg(OPT_fexternc_nounwind);
Opts.TraditionalCPP = Args.hasArg(OPT_traditional_cpp);
- Opts.RTTI = !Args.hasArg(OPT_fno_rtti);
+ Opts.RTTI = Opts.CPlusPlus && !Args.hasArg(OPT_fno_rtti);
Opts.RTTIData = Opts.RTTI && !Args.hasArg(OPT_fno_rtti_data);
- Opts.Blocks = Args.hasArg(OPT_fblocks);
+ Opts.Blocks = Args.hasArg(OPT_fblocks) || (Opts.OpenCL
+ && Opts.OpenCLVersion >= 200);
Opts.BlocksRuntimeOptional = Args.hasArg(OPT_fblocks_runtime_optional);
- Opts.Coroutines = Args.hasArg(OPT_fcoroutines);
- Opts.Modules = Args.hasArg(OPT_fmodules);
+ Opts.CoroutinesTS = Args.hasArg(OPT_fcoroutines_ts);
+
+ // Enable [[]] attributes in C++11 by default.
+ Opts.DoubleSquareBracketAttributes =
+ Args.hasFlag(OPT_fdouble_square_bracket_attributes,
+ OPT_fno_double_square_bracket_attributes, Opts.CPlusPlus11);
+
+ Opts.ModulesTS = Args.hasArg(OPT_fmodules_ts);
+ Opts.Modules = Args.hasArg(OPT_fmodules) || Opts.ModulesTS;
Opts.ModulesStrictDeclUse = Args.hasArg(OPT_fmodules_strict_decluse);
Opts.ModulesDeclUse =
Args.hasArg(OPT_fmodules_decluse) || Opts.ModulesStrictDeclUse;
Opts.ModulesLocalVisibility =
- Args.hasArg(OPT_fmodules_local_submodule_visibility);
+ Args.hasArg(OPT_fmodules_local_submodule_visibility) || Opts.ModulesTS;
+ Opts.ModulesCodegen = Args.hasArg(OPT_fmodules_codegen);
+ Opts.ModulesDebugInfo = Args.hasArg(OPT_fmodules_debuginfo);
Opts.ModulesSearchAll = Opts.Modules &&
!Args.hasArg(OPT_fno_modules_search_all) &&
Args.hasArg(OPT_fmodules_search_all);
@@ -1682,22 +2221,45 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.ImplicitModules = !Args.hasArg(OPT_fno_implicit_modules);
Opts.CharIsSigned = Opts.OpenCL || !Args.hasArg(OPT_fno_signed_char);
Opts.WChar = Opts.CPlusPlus && !Args.hasArg(OPT_fno_wchar);
- Opts.ShortWChar = Args.hasFlag(OPT_fshort_wchar, OPT_fno_short_wchar, false);
+ if (const Arg *A = Args.getLastArg(OPT_fwchar_type_EQ)) {
+ Opts.WCharSize = llvm::StringSwitch<unsigned>(A->getValue())
+ .Case("char", 1)
+ .Case("short", 2)
+ .Case("int", 4)
+ .Default(0);
+ if (Opts.WCharSize == 0)
+ Diags.Report(diag::err_fe_invalid_wchar_type) << A->getValue();
+ }
+ Opts.WCharIsSigned = Args.hasFlag(OPT_fsigned_wchar, OPT_fno_signed_wchar, true);
Opts.ShortEnums = Args.hasArg(OPT_fshort_enums);
Opts.Freestanding = Args.hasArg(OPT_ffreestanding);
Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding;
if (!Opts.NoBuiltin)
getAllNoBuiltinFuncValues(Args, Opts.NoBuiltinFuncs);
Opts.NoMathBuiltin = Args.hasArg(OPT_fno_math_builtin);
- Opts.AssumeSaneOperatorNew = !Args.hasArg(OPT_fno_assume_sane_operator_new);
+ Opts.RelaxedTemplateTemplateArgs =
+ Args.hasArg(OPT_frelaxed_template_template_args);
Opts.SizedDeallocation = Args.hasArg(OPT_fsized_deallocation);
+ Opts.AlignedAllocation =
+ Args.hasFlag(OPT_faligned_allocation, OPT_fno_aligned_allocation,
+ Opts.AlignedAllocation);
+ Opts.AlignedAllocationUnavailable =
+ Opts.AlignedAllocation && Args.hasArg(OPT_aligned_alloc_unavailable);
+ Opts.NewAlignOverride =
+ getLastArgIntValue(Args, OPT_fnew_alignment_EQ, 0, Diags);
+ if (Opts.NewAlignOverride && !llvm::isPowerOf2_32(Opts.NewAlignOverride)) {
+ Arg *A = Args.getLastArg(OPT_fnew_alignment_EQ);
+ Diags.Report(diag::err_fe_invalid_alignment) << A->getAsString(Args)
+ << A->getValue();
+ Opts.NewAlignOverride = 0;
+ }
Opts.ConceptsTS = Args.hasArg(OPT_fconcepts_ts);
Opts.HeinousExtensions = Args.hasArg(OPT_fheinous_gnu_extensions);
Opts.AccessControl = !Args.hasArg(OPT_fno_access_control);
Opts.ElideConstructors = !Args.hasArg(OPT_fno_elide_constructors);
Opts.MathErrno = !Opts.OpenCL && Args.hasArg(OPT_fmath_errno);
Opts.InstantiationDepth =
- getLastArgIntValue(Args, OPT_ftemplate_depth, 256, Diags);
+ getLastArgIntValue(Args, OPT_ftemplate_depth, 1024, Diags);
Opts.ArrowDepth =
getLastArgIntValue(Args, OPT_foperator_arrow_depth, 256, Diags);
Opts.ConstexprCallDepth =
@@ -1718,8 +2280,9 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.EmitAllDecls = Args.hasArg(OPT_femit_all_decls);
Opts.PackStruct = getLastArgIntValue(Args, OPT_fpack_struct_EQ, 0, Diags);
Opts.MaxTypeAlign = getLastArgIntValue(Args, OPT_fmax_type_align_EQ, 0, Diags);
+ Opts.AlignDouble = Args.hasArg(OPT_malign_double);
Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags);
- Opts.PIELevel = getLastArgIntValue(Args, OPT_pie_level, 0, Diags);
+ Opts.PIE = Args.hasArg(OPT_pic_is_pie);
Opts.Static = Args.hasArg(OPT_static_define);
Opts.DumpRecordLayoutsSimple = Args.hasArg(OPT_fdump_record_layouts_simple);
Opts.DumpRecordLayouts = Opts.DumpRecordLayoutsSimple
@@ -1729,7 +2292,6 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.NoBitFieldTypeAlign = Args.hasArg(OPT_fno_bitfield_type_align);
Opts.SinglePrecisionConstants = Args.hasArg(OPT_cl_single_precision_constant);
Opts.FastRelaxedMath = Args.hasArg(OPT_cl_fast_relaxed_math);
- Opts.MRTD = Args.hasArg(OPT_mrtd);
Opts.HexagonQdsp6Compat = Args.hasArg(OPT_mqdsp6_compat);
Opts.FakeAddressSpaceMap = Args.hasArg(OPT_ffake_address_space_map);
Opts.ParseUnknownAnytype = Args.hasArg(OPT_funknown_anytype);
@@ -1737,39 +2299,30 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.DebuggerCastResultToId = Args.hasArg(OPT_fdebugger_cast_result_to_id);
Opts.DebuggerObjCLiteral = Args.hasArg(OPT_fdebugger_objc_literal);
Opts.ApplePragmaPack = Args.hasArg(OPT_fapple_pragma_pack);
- Opts.CurrentModule = Args.getLastArgValue(OPT_fmodule_name);
+ Opts.CurrentModule = Args.getLastArgValue(OPT_fmodule_name_EQ);
Opts.AppExt = Args.hasArg(OPT_fapplication_extension);
- Opts.ImplementationOfModule =
- Args.getLastArgValue(OPT_fmodule_implementation_of);
Opts.ModuleFeatures = Args.getAllArgValues(OPT_fmodule_feature);
std::sort(Opts.ModuleFeatures.begin(), Opts.ModuleFeatures.end());
Opts.NativeHalfType |= Args.hasArg(OPT_fnative_half_type);
- Opts.HalfArgsAndReturns = Args.hasArg(OPT_fallow_half_arguments_and_returns);
+ Opts.NativeHalfArgsAndReturns |= Args.hasArg(OPT_fnative_half_arguments_and_returns);
+ // Enable HalfArgsAndReturns if present in Args or if NativeHalfArgsAndReturns
+ // is enabled.
+ Opts.HalfArgsAndReturns = Args.hasArg(OPT_fallow_half_arguments_and_returns)
+ | Opts.NativeHalfArgsAndReturns;
Opts.GNUAsm = !Args.hasArg(OPT_fno_gnu_inline_asm);
// __declspec is enabled by default for the PS4 by the driver, and also
// enabled for Microsoft Extensions or Borland Extensions, here.
//
// FIXME: __declspec is also currently enabled for CUDA, but isn't really a
- // CUDA extension, however it is required for supporting cuda_builtin_vars.h,
- // which uses __declspec(property). Once that has been rewritten in terms of
- // something more generic, remove the Opts.CUDA term here.
+ // CUDA extension. However, it is required for supporting
+ // __clang_cuda_builtin_vars.h, which uses __declspec(property). Once that has
+ // been rewritten in terms of something more generic, remove the Opts.CUDA
+ // term here.
Opts.DeclSpecKeyword =
Args.hasFlag(OPT_fdeclspec, OPT_fno_declspec,
(Opts.MicrosoftExt || Opts.Borland || Opts.CUDA));
- if (!Opts.CurrentModule.empty() && !Opts.ImplementationOfModule.empty() &&
- Opts.CurrentModule != Opts.ImplementationOfModule) {
- Diags.Report(diag::err_conflicting_module_names)
- << Opts.CurrentModule << Opts.ImplementationOfModule;
- }
-
- // For now, we only support local submodule visibility in C++ (because we
- // heavily depend on the ODR for merging redefinitions).
- if (Opts.ModulesLocalVisibility && !Opts.CPlusPlus)
- Diags.Report(diag::err_drv_argument_not_allowed_with)
- << "-fmodules-local-submodule-visibility" << "C";
-
if (Arg *A = Args.getLastArg(OPT_faddress_space_map_mangling_EQ)) {
switch (llvm::StringSwitch<unsigned>(A->getValue())
.Case("target", LangOptions::ASMM_Target)
@@ -1810,20 +2363,105 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.setMSPointerToMemberRepresentationMethod(InheritanceModel);
}
+ // Check for MS default calling conventions being specified.
+ if (Arg *A = Args.getLastArg(OPT_fdefault_calling_conv_EQ)) {
+ LangOptions::DefaultCallingConvention DefaultCC =
+ llvm::StringSwitch<LangOptions::DefaultCallingConvention>(A->getValue())
+ .Case("cdecl", LangOptions::DCC_CDecl)
+ .Case("fastcall", LangOptions::DCC_FastCall)
+ .Case("stdcall", LangOptions::DCC_StdCall)
+ .Case("vectorcall", LangOptions::DCC_VectorCall)
+ .Case("regcall", LangOptions::DCC_RegCall)
+ .Default(LangOptions::DCC_None);
+ if (DefaultCC == LangOptions::DCC_None)
+ Diags.Report(diag::err_drv_invalid_value)
+ << "-fdefault-calling-conv=" << A->getValue();
+
+ llvm::Triple T(TargetOpts.Triple);
+ llvm::Triple::ArchType Arch = T.getArch();
+ bool emitError = (DefaultCC == LangOptions::DCC_FastCall ||
+ DefaultCC == LangOptions::DCC_StdCall) &&
+ Arch != llvm::Triple::x86;
+ emitError |= (DefaultCC == LangOptions::DCC_VectorCall ||
+ DefaultCC == LangOptions::DCC_RegCall) &&
+ !(Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64);
+ if (emitError)
+ Diags.Report(diag::err_drv_argument_not_allowed_with)
+ << A->getSpelling() << T.getTriple();
+ else
+ Opts.setDefaultCallingConv(DefaultCC);
+ }
+
+ // -mrtd option
+ if (Arg *A = Args.getLastArg(OPT_mrtd)) {
+ if (Opts.getDefaultCallingConv() != LangOptions::DCC_None)
+ Diags.Report(diag::err_drv_argument_not_allowed_with)
+ << A->getSpelling() << "-fdefault-calling-conv";
+ else {
+ llvm::Triple T(TargetOpts.Triple);
+ if (T.getArch() != llvm::Triple::x86)
+ Diags.Report(diag::err_drv_argument_not_allowed_with)
+ << A->getSpelling() << T.getTriple();
+ else
+ Opts.setDefaultCallingConv(LangOptions::DCC_StdCall);
+ }
+ }
+
// Check if -fopenmp is specified.
- Opts.OpenMP = Args.hasArg(options::OPT_fopenmp);
+ Opts.OpenMP = Args.hasArg(options::OPT_fopenmp) ? 1 : 0;
+ // Check if -fopenmp-simd is specified.
+ Opts.OpenMPSimd = !Opts.OpenMP && Args.hasFlag(options::OPT_fopenmp_simd,
+ options::OPT_fno_openmp_simd,
+ /*Default=*/false);
Opts.OpenMPUseTLS =
Opts.OpenMP && !Args.hasArg(options::OPT_fnoopenmp_use_tls);
Opts.OpenMPIsDevice =
Opts.OpenMP && Args.hasArg(options::OPT_fopenmp_is_device);
+ if (Opts.OpenMP || Opts.OpenMPSimd) {
+ if (int Version =
+ getLastArgIntValue(Args, OPT_fopenmp_version_EQ,
+ Opts.OpenMPSimd ? 45 : Opts.OpenMP, Diags))
+ Opts.OpenMP = Version;
+ else if (Opts.OpenMPSimd)
+ Opts.OpenMP = 45;
+ // Provide diagnostic when a given target is not expected to be an OpenMP
+ // device or host.
+ if (!Opts.OpenMPIsDevice) {
+ switch (T.getArch()) {
+ default:
+ break;
+ // Add unsupported host targets here:
+ case llvm::Triple::nvptx:
+ case llvm::Triple::nvptx64:
+ Diags.Report(clang::diag::err_drv_omp_host_target_not_supported)
+ << TargetOpts.Triple;
+ break;
+ }
+ }
+ }
+
+ // Set the flag to prevent the implementation from emitting device exception
+ // handling code for those requiring so.
+ if (Opts.OpenMPIsDevice && T.isNVPTX()) {
+ Opts.Exceptions = 0;
+ Opts.CXXExceptions = 0;
+ }
+
// Get the OpenMP target triples if any.
- if (Arg *A = Args.getLastArg(options::OPT_omptargets_EQ)) {
+ if (Arg *A = Args.getLastArg(options::OPT_fopenmp_targets_EQ)) {
for (unsigned i = 0; i < A->getNumValues(); ++i) {
llvm::Triple TT(A->getValue(i));
- if (TT.getArch() == llvm::Triple::UnknownArch)
+ if (TT.getArch() == llvm::Triple::UnknownArch ||
+ !(TT.getArch() == llvm::Triple::ppc ||
+ TT.getArch() == llvm::Triple::ppc64 ||
+ TT.getArch() == llvm::Triple::ppc64le ||
+ TT.getArch() == llvm::Triple::nvptx ||
+ TT.getArch() == llvm::Triple::nvptx64 ||
+ TT.getArch() == llvm::Triple::x86 ||
+ TT.getArch() == llvm::Triple::x86_64))
Diags.Report(clang::diag::err_drv_invalid_omp_target) << A->getValue(i);
else
Opts.OMPTargetTriples.push_back(TT);
@@ -1832,7 +2470,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
// Get OpenMP host file path if any and report if a non existent file is
// found
- if (Arg *A = Args.getLastArg(options::OPT_omp_host_ir_file_path)) {
+ if (Arg *A = Args.getLastArg(options::OPT_fopenmp_host_ir_file_path)) {
Opts.OMPHostIRFile = A->getValue();
if (!llvm::sys::fs::exists(Opts.OMPHostIRFile))
Diags.Report(clang::diag::err_drv_omp_host_ir_file_not_found)
@@ -1853,7 +2491,12 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
// This is the __NO_INLINE__ define, which just depends on things like the
// optimization level and -fno-inline, not actually whether the backend has
// inlining enabled.
- Opts.NoInlineDefine = !Opt || Args.hasArg(OPT_fno_inline);
+ Opts.NoInlineDefine = !Opts.Optimize;
+ if (Arg *InlineArg = Args.getLastArg(
+ options::OPT_finline_functions, options::OPT_finline_hint_functions,
+ options::OPT_fno_inline_functions, options::OPT_fno_inline))
+ if (InlineArg->getOption().matches(options::OPT_fno_inline))
+ Opts.NoInlineDefine = true;
Opts.FastMath = Args.hasArg(OPT_ffast_math) ||
Args.hasArg(OPT_cl_fast_relaxed_math);
@@ -1864,6 +2507,18 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Args.hasArg(OPT_cl_unsafe_math_optimizations) ||
Args.hasArg(OPT_cl_fast_relaxed_math);
+ if (Arg *A = Args.getLastArg(OPT_ffp_contract)) {
+ StringRef Val = A->getValue();
+ if (Val == "fast")
+ Opts.setDefaultFPContractMode(LangOptions::FPC_Fast);
+ else if (Val == "on")
+ Opts.setDefaultFPContractMode(LangOptions::FPC_On);
+ else if (Val == "off")
+ Opts.setDefaultFPContractMode(LangOptions::FPC_Off);
+ else
+ Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
+ }
+
Opts.RetainCommentsFromSystemHeaders =
Args.hasArg(OPT_fretain_comments_from_system_headers);
@@ -1886,11 +2541,71 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.SanitizeAddressFieldPadding =
getLastArgIntValue(Args, OPT_fsanitize_address_field_padding, 0, Diags);
Opts.SanitizerBlacklistFiles = Args.getAllArgValues(OPT_fsanitize_blacklist);
+
+ // -fxray-instrument
+ Opts.XRayInstrument =
+ Args.hasFlag(OPT_fxray_instrument, OPT_fnoxray_instrument, false);
+
+ // -fxray-always-emit-customevents
+ Opts.XRayAlwaysEmitCustomEvents =
+ Args.hasFlag(OPT_fxray_always_emit_customevents,
+ OPT_fnoxray_always_emit_customevents, false);
+
+ // -fxray-{always,never}-instrument= filenames.
+ Opts.XRayAlwaysInstrumentFiles =
+ Args.getAllArgValues(OPT_fxray_always_instrument);
+ Opts.XRayNeverInstrumentFiles =
+ Args.getAllArgValues(OPT_fxray_never_instrument);
+
+ // -fallow-editor-placeholders
+ Opts.AllowEditorPlaceholders = Args.hasArg(OPT_fallow_editor_placeholders);
+}
+
+static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) {
+ switch (Action) {
+ case frontend::ASTDeclList:
+ case frontend::ASTDump:
+ case frontend::ASTPrint:
+ case frontend::ASTView:
+ case frontend::EmitAssembly:
+ case frontend::EmitBC:
+ case frontend::EmitHTML:
+ case frontend::EmitLLVM:
+ case frontend::EmitLLVMOnly:
+ case frontend::EmitCodeGenOnly:
+ case frontend::EmitObj:
+ case frontend::FixIt:
+ case frontend::GenerateModule:
+ case frontend::GenerateModuleInterface:
+ case frontend::GeneratePCH:
+ case frontend::GeneratePTH:
+ case frontend::ParseSyntaxOnly:
+ case frontend::ModuleFileInfo:
+ case frontend::VerifyPCH:
+ case frontend::PluginAction:
+ case frontend::PrintDeclContext:
+ case frontend::RewriteObjC:
+ case frontend::RewriteTest:
+ case frontend::RunAnalysis:
+ case frontend::MigrateSource:
+ return false;
+
+ case frontend::DumpRawTokens:
+ case frontend::DumpTokens:
+ case frontend::InitOnly:
+ case frontend::PrintPreamble:
+ case frontend::PrintPreprocessedInput:
+ case frontend::RewriteMacros:
+ case frontend::RunPreprocessorOnly:
+ return true;
+ }
+ llvm_unreachable("invalid frontend action");
}
static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
FileManager &FileMgr,
- DiagnosticsEngine &Diags) {
+ DiagnosticsEngine &Diags,
+ frontend::ActionKind Action) {
using namespace options;
Opts.ImplicitPCHInclude = Args.getLastArgValue(OPT_include_pch);
Opts.ImplicitPTHInclude = Args.getLastArgValue(OPT_include_pth);
@@ -1901,6 +2616,7 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
Opts.UsePredefines = !Args.hasArg(OPT_undef);
Opts.DetailedRecord = Args.hasArg(OPT_detailed_preprocessing_record);
Opts.DisablePCHValidation = Args.hasArg(OPT_fno_validate_pch);
+ Opts.AllowPCHWithCompilerErrors = Args.hasArg(OPT_fallow_pch_with_errors);
Opts.DumpDeserializedPCHDecls = Args.hasArg(OPT_dump_deserialized_pch_decls);
for (const Arg *A : Args.filtered(OPT_error_on_deserialized_pch_decl))
@@ -1939,10 +2655,6 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
for (const Arg *A : Args.filtered(OPT_chain_include))
Opts.ChainedIncludes.emplace_back(A->getValue());
- // Include 'altivec.h' if -faltivec option present
- if (Args.hasArg(OPT_faltivec))
- Opts.Includes.emplace_back("altivec.h");
-
for (const Arg *A : Args.filtered(OPT_remap_file)) {
std::pair<StringRef, StringRef> Split = StringRef(A->getValue()).split(';');
@@ -1966,6 +2678,12 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
else
Opts.ObjCXXARCStandardLibrary = (ObjCXXARCStandardLibraryKind)Library;
}
+
+ // Always avoid lexing editor placeholders when we're just running the
+ // preprocessor as we never want to emit the
+ // "editor placeholder in source file" error in PP only mode.
+ if (isStrictlyPreprocessorAction(Action))
+ Opts.LexEditorPlaceholders = false;
}
static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,
@@ -1973,65 +2691,48 @@ static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,
frontend::ActionKind Action) {
using namespace options;
- switch (Action) {
- case frontend::ASTDeclList:
- case frontend::ASTDump:
- case frontend::ASTPrint:
- case frontend::ASTView:
- case frontend::EmitAssembly:
- case frontend::EmitBC:
- case frontend::EmitHTML:
- case frontend::EmitLLVM:
- case frontend::EmitLLVMOnly:
- case frontend::EmitCodeGenOnly:
- case frontend::EmitObj:
- case frontend::FixIt:
- case frontend::GenerateModule:
- case frontend::GeneratePCH:
- case frontend::GeneratePTH:
- case frontend::ParseSyntaxOnly:
- case frontend::ModuleFileInfo:
- case frontend::VerifyPCH:
- case frontend::PluginAction:
- case frontend::PrintDeclContext:
- case frontend::RewriteObjC:
- case frontend::RewriteTest:
- case frontend::RunAnalysis:
- case frontend::MigrateSource:
- Opts.ShowCPP = 0;
- break;
-
- case frontend::DumpRawTokens:
- case frontend::DumpTokens:
- case frontend::InitOnly:
- case frontend::PrintPreamble:
- case frontend::PrintPreprocessedInput:
- case frontend::RewriteMacros:
- case frontend::RunPreprocessorOnly:
+ if (isStrictlyPreprocessorAction(Action))
Opts.ShowCPP = !Args.hasArg(OPT_dM);
- break;
- }
+ else
+ Opts.ShowCPP = 0;
Opts.ShowComments = Args.hasArg(OPT_C);
Opts.ShowLineMarkers = !Args.hasArg(OPT_P);
Opts.ShowMacroComments = Args.hasArg(OPT_CC);
Opts.ShowMacros = Args.hasArg(OPT_dM) || Args.hasArg(OPT_dD);
+ Opts.ShowIncludeDirectives = Args.hasArg(OPT_dI);
Opts.RewriteIncludes = Args.hasArg(OPT_frewrite_includes);
+ Opts.RewriteImports = Args.hasArg(OPT_frewrite_imports);
Opts.UseLineDirectives = Args.hasArg(OPT_fuse_line_directives);
}
-static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args) {
+static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args,
+ DiagnosticsEngine &Diags) {
using namespace options;
Opts.ABI = Args.getLastArgValue(OPT_target_abi);
+ if (Arg *A = Args.getLastArg(OPT_meabi)) {
+ StringRef Value = A->getValue();
+ llvm::EABI EABIVersion = llvm::StringSwitch<llvm::EABI>(Value)
+ .Case("default", llvm::EABI::Default)
+ .Case("4", llvm::EABI::EABI4)
+ .Case("5", llvm::EABI::EABI5)
+ .Case("gnu", llvm::EABI::GNU)
+ .Default(llvm::EABI::Unknown);
+ if (EABIVersion == llvm::EABI::Unknown)
+ Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args)
+ << Value;
+ else
+ Opts.EABIVersion = EABIVersion;
+ }
Opts.CPU = Args.getLastArgValue(OPT_target_cpu);
Opts.FPMath = Args.getLastArgValue(OPT_mfpmath);
Opts.FeaturesAsWritten = Args.getAllArgValues(OPT_target_feature);
Opts.LinkerVersion = Args.getLastArgValue(OPT_target_linker_version);
Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple));
- Opts.Reciprocals = Args.getAllArgValues(OPT_mrecip_EQ);
// Use the default target triple if unspecified.
if (Opts.Triple.empty())
Opts.Triple = llvm::sys::getDefaultTargetTriple();
+ Opts.OpenCLExtensionsAsWritten = Args.getAllArgValues(OPT_cl_ext_EQ);
}
bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
@@ -2041,12 +2742,13 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
bool Success = true;
// Parse the arguments.
- std::unique_ptr<OptTable> Opts(createDriverOptTable());
+ std::unique_ptr<OptTable> Opts = createDriverOptTable();
const unsigned IncludedFlagsBitmask = options::CC1Option;
unsigned MissingArgIndex, MissingArgCount;
InputArgList Args =
Opts->ParseArgs(llvm::makeArrayRef(ArgBegin, ArgEnd), MissingArgIndex,
MissingArgCount, IncludedFlagsBitmask);
+ LangOptions &LangOpts = *Res.getLangOpts();
// Check for missing argument error.
if (MissingArgCount) {
@@ -2064,91 +2766,83 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
Success &= ParseAnalyzerArgs(*Res.getAnalyzerOpts(), Args, Diags);
Success &= ParseMigratorArgs(Res.getMigratorOpts(), Args);
ParseDependencyOutputArgs(Res.getDependencyOutputOpts(), Args);
- Success &= ParseDiagnosticArgs(Res.getDiagnosticOpts(), Args, &Diags);
- ParseCommentArgs(Res.getLangOpts()->CommentOpts, Args);
+ Success &=
+ ParseDiagnosticArgs(Res.getDiagnosticOpts(), Args, &Diags,
+ false /*DefaultDiagColor*/, false /*DefaultShowOpt*/);
+ ParseCommentArgs(LangOpts.CommentOpts, Args);
ParseFileSystemArgs(Res.getFileSystemOpts(), Args);
// FIXME: We shouldn't have to pass the DashX option around here
- InputKind DashX = ParseFrontendArgs(Res.getFrontendOpts(), Args, Diags);
- ParseTargetArgs(Res.getTargetOpts(), Args);
+ InputKind DashX = ParseFrontendArgs(Res.getFrontendOpts(), Args, Diags,
+ LangOpts.IsHeaderFile);
+ ParseTargetArgs(Res.getTargetOpts(), Args, Diags);
Success &= ParseCodeGenArgs(Res.getCodeGenOpts(), Args, DashX, Diags,
Res.getTargetOpts());
- ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), Args);
- if (DashX == IK_AST || DashX == IK_LLVM_IR) {
+ ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), Args,
+ Res.getFileSystemOpts().WorkingDir);
+ if (DashX.getFormat() == InputKind::Precompiled ||
+ DashX.getLanguage() == InputKind::LLVM_IR) {
// ObjCAAutoRefCount and Sanitize LangOpts are used to setup the
// PassManager in BackendUtil.cpp. They need to be initializd no matter
// what the input type is.
if (Args.hasArg(OPT_fobjc_arc))
- Res.getLangOpts()->ObjCAutoRefCount = 1;
+ LangOpts.ObjCAutoRefCount = 1;
+ // PIClevel and PIELevel are needed during code generation and this should be
+ // set regardless of the input type.
+ LangOpts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags);
+ LangOpts.PIE = Args.hasArg(OPT_pic_is_pie);
parseSanitizerKinds("-fsanitize=", Args.getAllArgValues(OPT_fsanitize_EQ),
- Diags, Res.getLangOpts()->Sanitize);
+ Diags, LangOpts.Sanitize);
} else {
// Other LangOpts are only initialzed when the input is not AST or LLVM IR.
- ParseLangArgs(*Res.getLangOpts(), Args, DashX, Diags);
+ // FIXME: Should we really be calling this for an InputKind::Asm input?
+ ParseLangArgs(LangOpts, Args, DashX, Res.getTargetOpts(),
+ Res.getPreprocessorOpts(), Diags);
if (Res.getFrontendOpts().ProgramAction == frontend::RewriteObjC)
- Res.getLangOpts()->ObjCExceptions = 1;
+ LangOpts.ObjCExceptions = 1;
+ }
+
+ if (LangOpts.CUDA) {
+ // During CUDA device-side compilation, the aux triple is the
+ // triple used for host compilation.
+ if (LangOpts.CUDAIsDevice)
+ Res.getTargetOpts().HostTriple = Res.getFrontendOpts().AuxTriple;
}
+
+ // Set the triple of the host for OpenMP device compile.
+ if (LangOpts.OpenMPIsDevice)
+ Res.getTargetOpts().HostTriple = Res.getFrontendOpts().AuxTriple;
+
+ // FIXME: Override value name discarding when asan or msan is used because the
+ // backend passes depend on the name of the alloca in order to print out
+ // names.
+ Res.getCodeGenOpts().DiscardValueNames &=
+ !LangOpts.Sanitize.has(SanitizerKind::Address) &&
+ !LangOpts.Sanitize.has(SanitizerKind::Memory);
+
// FIXME: ParsePreprocessorArgs uses the FileManager to read the contents of
// PCH file and find the original header name. Remove the need to do that in
// ParsePreprocessorArgs and remove the FileManager
// parameters from the function and the "FileManager.h" #include.
FileManager FileMgr(Res.getFileSystemOpts());
- ParsePreprocessorArgs(Res.getPreprocessorOpts(), Args, FileMgr, Diags);
+ ParsePreprocessorArgs(Res.getPreprocessorOpts(), Args, FileMgr, Diags,
+ Res.getFrontendOpts().ProgramAction);
ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), Args,
Res.getFrontendOpts().ProgramAction);
- return Success;
-}
-
-namespace {
-
- class ModuleSignature {
- SmallVector<uint64_t, 16> Data;
- unsigned CurBit;
- uint64_t CurValue;
-
- public:
- ModuleSignature() : CurBit(0), CurValue(0) { }
-
- void add(uint64_t Value, unsigned Bits);
- void add(StringRef Value);
- void flush();
-
- llvm::APInt getAsInteger() const;
- };
-}
-void ModuleSignature::add(uint64_t Value, unsigned int NumBits) {
- CurValue |= Value << CurBit;
- if (CurBit + NumBits < 64) {
- CurBit += NumBits;
- return;
+ // Turn on -Wspir-compat for SPIR target.
+ llvm::Triple T(Res.getTargetOpts().Triple);
+ auto Arch = T.getArch();
+ if (Arch == llvm::Triple::spir || Arch == llvm::Triple::spir64) {
+ Res.getDiagnosticOpts().Warnings.push_back("spir-compat");
}
- // Add the current word.
- Data.push_back(CurValue);
-
- if (CurBit)
- CurValue = Value >> (64-CurBit);
- else
- CurValue = 0;
- CurBit = (CurBit+NumBits) & 63;
-}
-
-void ModuleSignature::flush() {
- if (CurBit == 0)
- return;
-
- Data.push_back(CurValue);
- CurBit = 0;
- CurValue = 0;
-}
-
-void ModuleSignature::add(StringRef Value) {
- for (auto &c : Value)
- add(c, 8);
-}
-
-llvm::APInt ModuleSignature::getAsInteger() const {
- return llvm::APInt(Data.size() * 64, Data);
+ // If sanitizer is enabled, disable OPT_ffine_grained_bitfield_accesses.
+ if (Res.getCodeGenOpts().FineGrainedBitfieldAccesses &&
+ !Res.getLangOpts()->Sanitize.empty()) {
+ Res.getCodeGenOpts().FineGrainedBitfieldAccesses = false;
+ Diags.Report(diag::warn_drv_fine_grained_bitfield_accesses_ignored);
+ }
+ return Success;
}
std::string CompilerInvocation::getModuleHash() const {
@@ -2195,7 +2889,8 @@ std::string CompilerInvocation::getModuleHash() const {
if (!hsOpts.ModulesIgnoreMacros.empty()) {
// Check whether we're ignoring this macro.
StringRef MacroDef = I->first;
- if (hsOpts.ModulesIgnoreMacros.count(MacroDef.split('=').first))
+ if (hsOpts.ModulesIgnoreMacros.count(
+ llvm::CachedHashString(MacroDef.split('=').first)))
continue;
}
@@ -2209,7 +2904,8 @@ std::string CompilerInvocation::getModuleHash() const {
hsOpts.UseBuiltinIncludes,
hsOpts.UseStandardSystemIncludes,
hsOpts.UseStandardCXXIncludes,
- hsOpts.UseLibcxx);
+ hsOpts.UseLibcxx,
+ hsOpts.ModulesValidateDiagnosticOptions);
code = hash_combine(code, hsOpts.ResourceDir);
// Extend the signature with the user build path.
@@ -2217,32 +2913,16 @@ std::string CompilerInvocation::getModuleHash() const {
// Extend the signature with the module file extensions.
const FrontendOptions &frontendOpts = getFrontendOpts();
- for (auto ext : frontendOpts.ModuleFileExtensions) {
+ for (const auto &ext : frontendOpts.ModuleFileExtensions) {
code = ext->hashExtension(code);
}
- // Darwin-specific hack: if we have a sysroot, use the contents and
- // modification time of
- // $sysroot/System/Library/CoreServices/SystemVersion.plist
- // as part of the module hash.
- if (!hsOpts.Sysroot.empty()) {
- SmallString<128> systemVersionFile;
- systemVersionFile += hsOpts.Sysroot;
- llvm::sys::path::append(systemVersionFile, "System");
- llvm::sys::path::append(systemVersionFile, "Library");
- llvm::sys::path::append(systemVersionFile, "CoreServices");
- llvm::sys::path::append(systemVersionFile, "SystemVersion.plist");
-
- llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> buffer =
- llvm::MemoryBuffer::getFile(systemVersionFile);
- if (buffer) {
- code = hash_combine(code, buffer.get()->getBuffer());
-
- struct stat statBuf;
- if (stat(systemVersionFile.c_str(), &statBuf) == 0)
- code = hash_combine(code, statBuf.st_mtime);
- }
- }
+ // Extend the signature with the enabled sanitizers, if at least one is
+ // enabled. Sanitizers which cannot affect AST generation aren't hashed.
+ SanitizerSet SanHash = LangOpts->Sanitize;
+ SanHash.clear(getPPTransparentSanitizers());
+ if (!SanHash.empty())
+ code = hash_combine(code, SanHash.Mask);
return llvm::APInt(64, code).toString(36, /*Signed=*/false);
}
@@ -2295,22 +2975,29 @@ void BuryPointer(const void *Ptr) {
IntrusiveRefCntPtr<vfs::FileSystem>
createVFSFromCompilerInvocation(const CompilerInvocation &CI,
DiagnosticsEngine &Diags) {
+ return createVFSFromCompilerInvocation(CI, Diags, vfs::getRealFileSystem());
+}
+
+IntrusiveRefCntPtr<vfs::FileSystem>
+createVFSFromCompilerInvocation(const CompilerInvocation &CI,
+ DiagnosticsEngine &Diags,
+ IntrusiveRefCntPtr<vfs::FileSystem> BaseFS) {
if (CI.getHeaderSearchOpts().VFSOverlayFiles.empty())
- return vfs::getRealFileSystem();
+ return BaseFS;
- IntrusiveRefCntPtr<vfs::OverlayFileSystem>
- Overlay(new vfs::OverlayFileSystem(vfs::getRealFileSystem()));
+ IntrusiveRefCntPtr<vfs::OverlayFileSystem> Overlay(
+ new vfs::OverlayFileSystem(BaseFS));
// earlier vfs files are on the bottom
for (const std::string &File : CI.getHeaderSearchOpts().VFSOverlayFiles) {
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer =
- llvm::MemoryBuffer::getFile(File);
+ BaseFS->getBufferForFile(File);
if (!Buffer) {
Diags.Report(diag::err_missing_vfs_overlay_file) << File;
return IntrusiveRefCntPtr<vfs::FileSystem>();
}
- IntrusiveRefCntPtr<vfs::FileSystem> FS =
- vfs::getVFSFromYAML(std::move(Buffer.get()), /*DiagHandler*/ nullptr);
+ IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getVFSFromYAML(
+ std::move(Buffer.get()), /*DiagHandler*/ nullptr, File);
if (!FS.get()) {
Diags.Report(diag::err_invalid_vfs_overlay) << File;
return IntrusiveRefCntPtr<vfs::FileSystem>();