Merge LLVM/Clang 3.4 into PNaCl's branch This fixes up various merge conflicts. The PNaCl branch of Clang contained various changes cherry-picked from between 3.3 and 3.4, so these no longer appear as localmods after the merge. This includes changes to: * atomics * C++ method pointers for le32 * use of pow() intrinsic BUG=https://code.google.com/p/nativeclient/issues/detail?id=3757 TEST=PNaCl toolchain trybots Review URL: https://groups.google.com/forum/#!topic/native-client-reviews/OD-h-xSTCu4
diff --git a/OWNERS b/OWNERS new file mode 100644 index 0000000..ac015a5 --- /dev/null +++ b/OWNERS
@@ -0,0 +1,8 @@ +dschuff@chromium.org +eliben@chromium.org +jfb@chromium.org +jvoung@chromium.org +kschimpf@chromium.org +mseaborn@chromium.org +sehr@chromium.org +stichnot@chromium.org
diff --git a/PRESUBMIT.py b/PRESUBMIT.py new file mode 100644 index 0000000..d81168e --- /dev/null +++ b/PRESUBMIT.py
@@ -0,0 +1,66 @@ +# Copyright (c) 2012 The Native Client Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Documentation on PRESUBMIT.py can be found at: +# http://www.chromium.org/developers/how-tos/depottools/presubmit-scripts + +EXCLUDE_PROJECT_CHECKS_DIRS = [ '.' ] + +import subprocess +def CheckGitBranch(): + p = subprocess.Popen("git branch -vv", shell=True, + stdout=subprocess.PIPE) + output, _ = p.communicate() + + lines = output.split('\n') + for line in lines: + # output format for checked-out branch should be + # * branchname hash [TrackedBranchName ... + toks = line.split() + if '*' not in toks[0]: + continue + if not 'origin/master' in toks[3]: + warning = 'Warning: your current branch:\n' + line + warning += '\nis not tracking origin/master. git cl push may silently ' + warning += 'fail to push your change. To fix this, do\n' + warning += 'git branch -u origin/master' + return warning + return None + print 'Warning: presubmit check could not determine local git branch' + return None + +def _CommonChecks(input_api, output_api): + """Checks for both upload and commit.""" + results = [] + results.extend(input_api.canned_checks.PanProjectChecks( + input_api, output_api, project_name='Native Client', + excluded_paths=tuple(EXCLUDE_PROJECT_CHECKS_DIRS))) + branch_warning = CheckGitBranch() + if branch_warning: + results.append(output_api.PresubmitPromptWarning(branch_warning)) + return results + +def CheckChangeOnUpload(input_api, output_api): + """Verifies all changes in all files. + Args: + input_api: the limited set of input modules allowed in presubmit. + output_api: the limited set of output modules allowed in presubmit. + """ + report = [] + report.extend(_CommonChecks(input_api, output_api)) + return report + +def CheckChangeOnCommit(input_api, output_api): + """Verifies all changes in all files and verifies that the + tree is open and can accept a commit. + Args: + input_api: the limited set of input modules allowed in presubmit. + output_api: the limited set of output modules allowed in presubmit. + """ + report = [] + report.extend(CheckChangeOnUpload(input_api, output_api)) + return report + +def GetPreferredTrySlaves(project, change): + return []
diff --git a/codereview.settings b/codereview.settings new file mode 100644 index 0000000..fae9103 --- /dev/null +++ b/codereview.settings
@@ -0,0 +1,12 @@ +# This file is used by gcl to get repository specific information. +CODE_REVIEW_SERVER: codereview.chromium.org +CC_LIST: native-client-reviews@googlegroups.com +VIEW_VC: +https://gerrit.chromium.org/gerrit/gitweb?p=native_client/pnacl-clang.git;a=commit;h= +STATUS: http://nativeclient-status.appspot.com/status +TRY_ON_UPLOAD: False +TRYSERVER_PROJECT: nacl +TRYSERVER_SVN_URL: svn://svn.chromium.org/chrome-try/try-nacl +PUSH_URL_CONFIG: url.ssh://gerrit.chromium.org.pushinsteadof +ORIGIN_URL_CONFIG: http://git.chromium.org +
diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index 55c6ed7..37b1237 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def
@@ -1180,6 +1180,11 @@ // Clang builtins (not available in GCC). BUILTIN(__builtin_addressof, "v*v&", "nct") +// @LOCALMOD-BEGIN +// NaCl builtins. +BUILTIN(__nacl_atomic_is_lock_free, "bzvCD*", "n") +// @LOCALMOD-END + #undef BUILTIN #undef LIBBUILTIN #undef LANGBUILTIN
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index 2578681..f1a6947 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp
@@ -633,6 +633,8 @@ this->DoubleAlign = 64; this->LongDoubleWidth = 64; this->LongDoubleAlign = 64; + this->LongLongWidth = 64; + this->LongLongAlign = 64; this->SizeType = TargetInfo::UnsignedInt; this->PtrDiffType = TargetInfo::SignedInt; this->IntPtrType = TargetInfo::SignedInt;
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 8ae0c06..8b23f0c 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp
@@ -21,6 +21,7 @@ #include "clang/Basic/TargetInfo.h" #include "clang/CodeGen/CGFunctionInfo.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/InlineAsm.h" // @LOCALMOD #include "llvm/IR/Intrinsics.h" using namespace clang; @@ -1037,7 +1038,29 @@ // any way to safely use it... but in practice, it mostly works // to use it with non-atomic loads and stores to get acquire/release // semantics. - Builder.CreateFence(llvm::SequentiallyConsistent); + // @LOCALMOD-START + // Targets can ask that ``__sync_synchronize()`` be surrounded with + // compiler fences. This should enforce ordering of more than just + // atomic memory accesses, though it won't guarantee that all + // accesses (e.g. those to non-escaping objects) won't be reordered. + llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false); + std::string AsmString; // Empty. + std::string Constraints("~{memory}"); + bool HasSideEffect = true; + if (getTargetHooks().addAsmMemoryAroundSyncSynchronize()) { + Builder.CreateCall( + llvm::InlineAsm::get(FTy, AsmString, Constraints, HasSideEffect))-> + addAttribute(llvm::AttributeSet::FunctionIndex, + llvm::Attribute::NoUnwind); + Builder.CreateFence(llvm::SequentiallyConsistent); + Builder.CreateCall( + llvm::InlineAsm::get(FTy, AsmString, Constraints, HasSideEffect))-> + addAttribute(llvm::AttributeSet::FunctionIndex, + llvm::Attribute::NoUnwind); + } else { + Builder.CreateFence(llvm::SequentiallyConsistent); + } + // @LOCALMOD-END return RValue::get(0); }
diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index 0bc51dd..1eab794 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp
@@ -1722,6 +1722,18 @@ Result->addAttribute(llvm::AttributeSet::FunctionIndex, llvm::Attribute::NoUnwind); + // @LOCALMOD-START + if (getTargetHooks().asmMemoryIsFence() && IA->isAsmMemory()) { + // Targets can ask that ``asm("":::"memory")`` be treated like + // ``__sync_synchronize()``. + Builder.CreateFence(llvm::SequentiallyConsistent); + Builder.CreateCall( + llvm::InlineAsm::get(FTy, AsmString, Constraints, HasSideEffect))-> + addAttribute(llvm::AttributeSet::FunctionIndex, + llvm::Attribute::NoUnwind); + } + // @LOCALMOD-END + // Slap the source location of the inline asm into a !srcloc metadata on the // call. FIXME: Handle metadata for MS-style inline asms. if (const GCCAsmStmt *gccAsmStmt = dyn_cast<GCCAsmStmt>(&S))
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index 1412bc2..5ecf205 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp
@@ -449,6 +449,9 @@ public: PNaClTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT) : TargetCodeGenInfo(new PNaClABIInfo(CGT)) {} + + bool addAsmMemoryAroundSyncSynchronize() const { return true; } // @LOCALMOD + bool asmMemoryIsFence() const { return true; } // @LOCALMOD }; void PNaClABIInfo::computeInfo(CGFunctionInfo &FI) const {
diff --git a/lib/CodeGen/TargetInfo.h b/lib/CodeGen/TargetInfo.h index f631f31..fdf8a16 100644 --- a/lib/CodeGen/TargetInfo.h +++ b/lib/CodeGen/TargetInfo.h
@@ -199,6 +199,28 @@ virtual void getDetectMismatchOption(llvm::StringRef Name, llvm::StringRef Value, llvm::SmallString<32> &Opt) const {} + + // @LOCALMOD-START + /// Determine whether the sequentially consistent fence generated for + /// the legacy GCC-style ``__sync_synchronize()`` builtin should be + /// surrounded by empty assembly directives which touch all of + /// memory. This allows platforms which aim for portability to + /// isolate themselves from changes in sequentially consistent + /// fence's semantics, since its intent is to represent the + /// C11/C++11 memory model which only orders atomic memory accesses. + /// This won't guarantee that all accesses (e.g. those to + /// non-escaping objects) will not be reordered. + virtual bool addAsmMemoryAroundSyncSynchronize() const { + return false; + } + + /// Determine whether a full sequentially consistent fence should be + /// emitted when ``asm("":::"memory")`` is encountered, treating it + /// like ``__sync_synchronize()``. + virtual bool asmMemoryIsFence() const { + return false; + } + // @LOCALMOD-END }; }
diff --git a/test/CodeGen/NaCl/atomics.c b/test/CodeGen/NaCl/atomics.c new file mode 100644 index 0000000..9922e93 --- /dev/null +++ b/test/CodeGen/NaCl/atomics.c
@@ -0,0 +1,64 @@ +// Test frontend handling of synchronization builtins which NaCl handles +// differently. +// Modified from test/CodeGen/Atomics.c +// RUN: %clang_cc1 -triple le32-unknown-nacl -emit-llvm %s -o - | FileCheck %s + +// CHECK: define void @test_sync_synchronize() +// CHECK-NEXT: entry: +void test_sync_synchronize (void) +{ + __sync_synchronize (); + // CHECK-NEXT: call void asm sideeffect "", "~{memory}"() + // CHECK-NEXT: fence seq_cst + // CHECK-NEXT: call void asm sideeffect "", "~{memory}"() + + // CHECK-NEXT: ret void +} + +// CHECK: define void @test_asm_memory_1() +// CHECK-NEXT: entry: +void test_asm_memory_1 (void) +{ + asm ("":::"memory"); + // CHECK-NEXT: call void asm sideeffect "", "~{memory}"() + // CHECK-NEXT: fence seq_cst + // CHECK-NEXT: call void asm sideeffect "", "~{memory}"() + + // CHECK-NEXT: ret void +} + +// CHECK: define void @test_asm_memory_2() +// CHECK-NEXT: entry: +void test_asm_memory_2 (void) +{ + asm volatile ("":::"memory"); + // CHECK-NEXT: call void asm sideeffect "", "~{memory}"() + // CHECK-NEXT: fence seq_cst + // CHECK-NEXT: call void asm sideeffect "", "~{memory}"() + + // CHECK-NEXT: ret void +} + +// CHECK: define void @test_asm_memory_3() +// CHECK-NEXT: entry: +void test_asm_memory_3 (void) +{ + __asm__ ("":::"memory"); + // CHECK-NEXT: call void asm sideeffect "", "~{memory}"() + // CHECK-NEXT: fence seq_cst + // CHECK-NEXT: call void asm sideeffect "", "~{memory}"() + + // CHECK-NEXT: ret void +} + +// CHECK: define void @test_asm_memory_4() +// CHECK-NEXT: entry: +void test_asm_memory_4 (void) +{ + __asm__ __volatile__ ("":::"memory"); + // CHECK-NEXT: call void asm sideeffect "", "~{memory}"() + // CHECK-NEXT: fence seq_cst + // CHECK-NEXT: call void asm sideeffect "", "~{memory}"() + + // CHECK-NEXT: ret void +}
diff --git a/test/CodeGen/long-double-x86-nacl.c b/test/CodeGen/long-double-x86-nacl.c deleted file mode 100644 index cec381a..0000000 --- a/test/CodeGen/long-double-x86-nacl.c +++ /dev/null
@@ -1,7 +0,0 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - -triple=i686-unknown-nacl | FileCheck %s - -long double x = 0; -int checksize[sizeof(x) == 8 ? 1 : -1]; - -// CHECK-LABEL: define void @s1(double %a) -void s1(long double a) {}
diff --git a/test/CodeGen/malign-double-x86-nacl.c b/test/CodeGen/malign-double-x86-nacl.c new file mode 100644 index 0000000..ff9084a --- /dev/null +++ b/test/CodeGen/malign-double-x86-nacl.c
@@ -0,0 +1,43 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=i686-unknown-nacl | FileCheck %s +// Check that i686-nacl essentially has -malign-double, which aligns +// double, long double, and long long to 64-bits. + +int checksize[sizeof(long double) == 8 ? 1 : -1]; +int checkalign[__alignof(long double) == 8 ? 1 : -1]; + +// CHECK: define void @s1(double %a) +void s1(long double a) {} + +struct st_ld { + char c; + long double ld; +}; +int checksize2[sizeof(struct st_ld) == 16 ? 1 : -1]; +int checkalign2[__alignof(struct st_ld) == 8 ? 1 : -1]; + +int checksize3[sizeof(double) == 8 ? 1 : -1]; +int checkalign3[__alignof(double) == 8 ? 1 : -1]; + +// CHECK: define void @s2(double %a) +void s2(double a) {} + +struct st_d { + char c; + double d; +}; +int checksize4[sizeof(struct st_d) == 16 ? 1 : -1]; +int checkalign4[__alignof(struct st_d) == 8 ? 1 : -1]; + + +int checksize5[sizeof(long long) == 8 ? 1 : -1]; +int checkalign5[__alignof(long long) == 8 ? 1 : -1]; + +// CHECK: define void @s3(i64 %a) +void s3(long long a) {} + +struct st_ll { + char c; + long long ll; +}; +int checksize6[sizeof(struct st_ll) == 16 ? 1 : -1]; +int checkalign6[__alignof(struct st_ll) == 8 ? 1 : -1];
diff --git a/test/lit.cfg b/test/lit.cfg index 19daa61..d08bf66 100644 --- a/test/lit.cfg +++ b/test/lit.cfg
@@ -14,6 +14,16 @@ # name: The name of this test suite. config.name = 'Clang' +# @LOCALMOD-START +# Msys tools like make and bash output paths like /c/dir/path. We need Windows +# drive letters. Makefile.rules has $(ECHOPATH) to try to get Windows paths but +# it doesn't work with autoconf substitutions like @FOO@=$(path) +def FixMsysPath(path): + if sys.platform == 'win32' and path and path.startswith('/'): + return path[1] + ':' + path[2:] + return path +# @LOCALMOD-END + # Tweak PATH for Win32 if platform.system() == 'Windows': # Seek sane tools in directories and set to $PATH. @@ -55,7 +65,7 @@ config.test_source_root = os.path.dirname(__file__) # test_exec_root: The root path where tests should be run. -clang_obj_root = getattr(config, 'clang_obj_root', None) +clang_obj_root = FixMsysPath(getattr(config, 'clang_obj_root', None))# @LOCALMOD if clang_obj_root is not None: config.test_exec_root = os.path.join(clang_obj_root, 'test') @@ -94,7 +104,8 @@ # Tweak the PATH to include the tools dir and the scripts dir. if clang_obj_root is not None: - llvm_tools_dir = getattr(config, 'llvm_tools_dir', None) + # @LOCALMOD + llvm_tools_dir = FixMsysPath(getattr(config, 'llvm_tools_dir', None)) if not llvm_tools_dir: lit_config.fatal('No LLVM tools dir set!') path = os.path.pathsep.join((llvm_tools_dir, config.environment['PATH']))