From 2c1705af37983292593f45fb308f11bfdabb95ec Mon Sep 17 00:00:00 2001 From: liwentao_uiw Date: Mon, 27 Jun 2022 19:58:21 +0800 Subject: [PATCH 01/18] cherry-pick f999312872b811b550533640b92ecb234cf5c642 d5ab243c6f79f881121a80487f0879d2ab0acc41 957334382cd12ec07b46c0ddfdcc220731f6d80f 46354bac76f60e988537181b3609a8e3ac89f523 21e013303bb7d0dbb9106283af0fb966fe45af42 4cf7c6c6a44dba6d7f3c13059f966412df89fe7 302b1b97180907011aae610b9f51d4b9186c9821 a346372200e7b2b99631bd90691678d5ca03fdd1 93b09a2a5d787beda3252a8c2662d19a44527881 f9089accbac128213542703256e65ec64cba17d1 from upstream of llvm-project with ohos support modification --- clang/lib/CodeGen/CGBuilder.h | 9 +- clang/lib/CodeGen/CGBuiltin.cpp | 3 +- clang/lib/CodeGen/CGCXX.cpp | 6 +- clang/lib/CodeGen/CodeGenFunction.h | 3 +- clang/test/CodeGen/matrix-type-builtins.c | 300 +++++++++++------- .../test/CodeGenCXX/matrix-type-builtins.cpp | 22 +- clang/test/CodeGenObjC/matrix-type-builtins.m | 4 +- libcxx/include/atomic | 3 + lldb/include/lldb/Target/PathMappingList.h | 17 +- lldb/source/Core/Module.cpp | 12 +- lldb/source/Core/SourceManager.cpp | 18 +- lldb/source/Symbol/LineEntry.cpp | 8 +- lldb/source/Target/PathMappingList.cpp | 85 ++--- lldb/unittests/Target/PathMappingListTest.cpp | 28 +- llvm/cmake/config-ix.cmake | 1 + llvm/cmake/unwind.h | 1 + llvm/docs/LangRef.rst | 14 +- llvm/include/llvm/Config/config.h.cmake | 3 + llvm/include/llvm/IR/Intrinsics.td | 4 +- llvm/include/llvm/IR/MatrixBuilder.h | 4 +- llvm/lib/CodeGen/CodeGenPrepare.cpp | 6 +- .../LiveDebugValues/VarLocBasedImpl.cpp | 3 +- .../Orc/TargetProcess/RegisterEHFrames.cpp | 28 +- .../RuntimeDyld/RTDyldMemoryManager.cpp | 4 +- llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp | 17 +- .../AMDGPU/AMDGPULateCodeGenPrepare.cpp | 2 +- .../Scalar/LowerMatrixIntrinsics.cpp | 22 +- .../lib/Transforms/Utils/AMDGPUEmitPrintf.cpp | 2 +- .../MIR/X86/live-debug-values-restore.mir | 2 +- .../strided-load-double.ll | 33 +- .../strided-store-double.ll | 33 +- llvm/test/Verifier/matrix-intrinsics.ll | 44 +-- polly/lib/CodeGen/IslNodeBuilder.cpp | 16 +- polly/lib/CodeGen/LoopGenerators.cpp | 3 +- polly/lib/CodeGen/LoopGeneratorsGOMP.cpp | 4 +- polly/lib/CodeGen/LoopGeneratorsKMP.cpp | 24 +- polly/lib/CodeGen/PerfMonitor.cpp | 24 +- 37 files changed, 477 insertions(+), 335 deletions(-) diff --git a/clang/lib/CodeGen/CGBuilder.h b/clang/lib/CodeGen/CGBuilder.h index 38e96c0f4ee6..82cdd95ac7e0 100644 --- a/clang/lib/CodeGen/CGBuilder.h +++ b/clang/lib/CodeGen/CGBuilder.h @@ -66,19 +66,20 @@ public: // Note that we intentionally hide the CreateLoad APIs that don't // take an alignment. llvm::LoadInst *CreateLoad(Address Addr, const llvm::Twine &Name = "") { - return CreateAlignedLoad(Addr.getPointer(), + return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(), Addr.getAlignment().getAsAlign(), Name); } llvm::LoadInst *CreateLoad(Address Addr, const char *Name) { // This overload is required to prevent string literals from // ending up in the IsVolatile overload. - return CreateAlignedLoad(Addr.getPointer(), + return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(), Addr.getAlignment().getAsAlign(), Name); } llvm::LoadInst *CreateLoad(Address Addr, bool IsVolatile, const llvm::Twine &Name = "") { - return CreateAlignedLoad( - Addr.getPointer(), Addr.getAlignment().getAsAlign(), IsVolatile, Name); + return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(), + Addr.getAlignment().getAsAlign(), IsVolatile, + Name); } using CGBuilderBaseTy::CreateAlignedLoad; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 10e3820d9657..a62e1b0986e9 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -14473,11 +14473,12 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, break; } + llvm::Type *Ty = FixedVectorType::get(Builder.getInt64Ty(), 2); Value *InOps[9]; InOps[0] = Ops[2]; for (int i = 0; i != 8; ++i) { Value *Ptr = Builder.CreateConstGEP1_32(Ops[1], i); - InOps[i + 1] = Builder.CreateAlignedLoad(Ptr, Align(16)); + InOps[i + 1] = Builder.CreateAlignedLoad(Ty, Ptr, Align(16)); } Value *Call = Builder.CreateCall(CGM.getIntrinsic(IID), InOps); diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp index a4bd2c6d5da0..641740c37a68 100644 --- a/clang/lib/CodeGen/CGCXX.cpp +++ b/clang/lib/CodeGen/CGCXX.cpp @@ -252,8 +252,8 @@ static CGCallee BuildAppleKextVirtualCall(CodeGenFunction &CGF, "No kext in Microsoft ABI"); CodeGenModule &CGM = CGF.CGM; llvm::Value *VTable = CGM.getCXXABI().getAddrOfVTable(RD, CharUnits()); - Ty = Ty->getPointerTo()->getPointerTo(); - VTable = CGF.Builder.CreateBitCast(VTable, Ty); + Ty = Ty->getPointerTo(); + VTable = CGF.Builder.CreateBitCast(VTable, Ty->getPointerTo()); assert(VTable && "BuildVirtualCall = kext vtbl pointer is null"); uint64_t VTableIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(GD); const VTableLayout &VTLayout = CGM.getItaniumVTableContext().getVTableLayout(RD); @@ -264,7 +264,7 @@ static CGCallee BuildAppleKextVirtualCall(CodeGenFunction &CGF, llvm::Value *VFuncPtr = CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfnkxt"); llvm::Value *VFunc = CGF.Builder.CreateAlignedLoad( - VFuncPtr, llvm::Align(CGF.PointerAlignInBytes)); + Ty, VFuncPtr, llvm::Align(CGF.PointerAlignInBytes)); CGCallee Callee(GD, VFunc); return Callee; } diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 95c0b7b4d7c0..80b8818fda60 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -4775,7 +4775,8 @@ inline llvm::Value *DominatingLLVMValue::restore(CodeGenFunction &CGF, // Otherwise, it should be an alloca instruction, as set up in save(). auto alloca = cast(value.getPointer()); - return CGF.Builder.CreateAlignedLoad(alloca, alloca->getAlign()); + return CGF.Builder.CreateAlignedLoad(alloca->getAllocatedType(), alloca, + alloca->getAlign()); } } // end namespace CodeGen diff --git a/clang/test/CodeGen/matrix-type-builtins.c b/clang/test/CodeGen/matrix-type-builtins.c index 67f5c7819687..ec0be85b7151 100644 --- a/clang/test/CodeGen/matrix-type-builtins.c +++ b/clang/test/CodeGen/matrix-type-builtins.c @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -fenable-matrix -triple x86_64-apple-darwin %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s +// RUN: %clang_cc1 -fenable-matrix -triple x86_64-apple-darwin %s -emit-llvm -disable-llvm-passes -o - | FileCheck --check-prefixes=COMMON,CHECK64 %s +// RUN: %clang_cc1 -fenable-matrix -triple i386-apple-darwin %s -emit-llvm -disable-llvm-passes -o - | FileCheck --check-prefixes=COMMON,CHECK32 %s // Also check we do not crash when running some middle-end passes. Most // importantly this includes the IR verifier, to ensure we emit valid IR. @@ -15,30 +16,33 @@ typedef unsigned ux1x6_t __attribute__((matrix_type(1, 6))); typedef unsigned ux6x1_t __attribute__((matrix_type(6, 1))); void transpose_double_5x5(dx5x5_t *a) { - // CHECK-LABEL: define{{.*}} void @transpose_double_5x5( - // CHECK: [[A:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 8 - // CHECK-NEXT: [[TRANS:%.*]] = call <25 x double> @llvm.matrix.transpose.v25f64(<25 x double> [[A]], i32 5, i32 5) - // CHECK-NEXT: [[AT_ADDR:%.*]] = bitcast [25 x double]* %a_t to <25 x double>* - // CHECK-NEXT: store <25 x double> [[TRANS]], <25 x double>* [[AT_ADDR]], align 8 + // COMMON-LABEL: define{{.*}} void @transpose_double_5x5( + // CHECK32: [[A:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 4 + // CHECK64: [[A:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 8 + // COMMON-NEXT: [[TRANS:%.*]] = call <25 x double> @llvm.matrix.transpose.v25f64(<25 x double> [[A]], i32 5, i32 5) + // COMMON-NEXT: [[AT_ADDR:%.*]] = bitcast [25 x double]* %a_t to <25 x double>* + // CHECK32-NEXT: store <25 x double> [[TRANS]], <25 x double>* [[AT_ADDR]], align 4 + // CHECK64-NEXT: store <25 x double> [[TRANS]], <25 x double>* [[AT_ADDR]], align 8 + dx5x5_t a_t = __builtin_matrix_transpose(*a); } void transpose_float_3x2(fx3x2_t *a) { - // CHECK-LABEL: define{{.*}} void @transpose_float_3x2( - // CHECK: [[A:%.*]] = load <6 x float>, <6 x float>* {{.*}}, align 4 - // CHECK-NEXT: [[TRANS:%.*]] = call <6 x float> @llvm.matrix.transpose.v6f32(<6 x float> [[A]], i32 3, i32 2) - // CHECK-NEXT: [[AT_ADDR:%.*]] = bitcast [6 x float]* %a_t to <6 x float>* - // CHECK-NEXT: store <6 x float> [[TRANS]], <6 x float>* [[AT_ADDR]], align 4 + // COMMON-LABEL: define{{.*}} void @transpose_float_3x2( + // COMMON: [[A:%.*]] = load <6 x float>, <6 x float>* {{.*}}, align 4 + // COMMON-NEXT: [[TRANS:%.*]] = call <6 x float> @llvm.matrix.transpose.v6f32(<6 x float> [[A]], i32 3, i32 2) + // COMMON-NEXT: [[AT_ADDR:%.*]] = bitcast [6 x float]* %a_t to <6 x float>* + // COMMON-NEXT: store <6 x float> [[TRANS]], <6 x float>* [[AT_ADDR]], align 4 fx2x3_t a_t = __builtin_matrix_transpose(*a); } void transpose_int_20x4(ix20x4_t *a) { - // CHECK-LABEL: define{{.*}} void @transpose_int_20x4( - // CHECK: [[A:%.*]] = load <80 x i32>, <80 x i32>* {{.*}}, align 4 - // CHECK-NEXT: [[TRANS:%.*]] = call <80 x i32> @llvm.matrix.transpose.v80i32(<80 x i32> [[A]], i32 20, i32 4) - // CHECK-NEXT: [[AT_ADDR:%.*]] = bitcast [80 x i32]* %a_t to <80 x i32>* - // CHECK-NEXT: store <80 x i32> [[TRANS]], <80 x i32>* [[AT_ADDR]], align 4 + // COMMON-LABEL: define{{.*}} void @transpose_int_20x4( + // COMMON: [[A:%.*]] = load <80 x i32>, <80 x i32>* {{.*}}, align 4 + // COMMON-NEXT: [[TRANS:%.*]] = call <80 x i32> @llvm.matrix.transpose.v80i32(<80 x i32> [[A]], i32 20, i32 4) + // COMMON-NEXT: [[AT_ADDR:%.*]] = bitcast [80 x i32]* %a_t to <80 x i32>* + // COMMON-NEXT: store <80 x i32> [[TRANS]], <80 x i32>* [[AT_ADDR]], align 4 ix4x20_t a_t = __builtin_matrix_transpose(*a); } @@ -49,26 +53,28 @@ struct Foo { }; void transpose_struct_member(struct Foo *F) { - // CHECK-LABEL: define{{.*}} void @transpose_struct_member( - // CHECK: [[M:%.*]] = load <6 x i32>, <6 x i32>* {{.*}}, align 4 - // CHECK-NEXT: [[M_T:%.*]] = call <6 x i32> @llvm.matrix.transpose.v6i32(<6 x i32> [[M]], i32 1, i32 6) - // CHECK-NEXT: [[F_ADDR:%.*]] = load %struct.Foo*, %struct.Foo** %F.addr, align 8 - // CHECK-NEXT: [[OUT_PTR:%.*]] = getelementptr inbounds %struct.Foo, %struct.Foo* [[F_ADDR]], i32 0, i32 1 - // CHECK-NEXT: [[OUT_PTR_C:%.*]] = bitcast [6 x i32]* [[OUT_PTR]] to <6 x i32>* - // CHECK-NEXT: store <6 x i32> [[M_T]], <6 x i32>* [[OUT_PTR_C]], align 4 + // COMMON-LABEL: define{{.*}} void @transpose_struct_member( + // COMMON: [[M:%.*]] = load <6 x i32>, <6 x i32>* {{.*}}, align 4 + // COMMON-NEXT: [[M_T:%.*]] = call <6 x i32> @llvm.matrix.transpose.v6i32(<6 x i32> [[M]], i32 1, i32 6) + // CHECK32-NEXT: [[F_ADDR:%.*]] = load %struct.Foo*, %struct.Foo** %F.addr, align 4 + // CHECK64-NEXT: [[F_ADDR:%.*]] = load %struct.Foo*, %struct.Foo** %F.addr, align 8 + // COMMON-NEXT: [[OUT_PTR:%.*]] = getelementptr inbounds %struct.Foo, %struct.Foo* [[F_ADDR]], i32 0, i32 1 + // COMMON-NEXT: [[OUT_PTR_C:%.*]] = bitcast [6 x i32]* [[OUT_PTR]] to <6 x i32>* + // COMMON-NEXT: store <6 x i32> [[M_T]], <6 x i32>* [[OUT_PTR_C]], align 4 F->out = __builtin_matrix_transpose(F->in); } void transpose_transpose_struct_member(struct Foo *F) { - // CHECK-LABEL: define{{.*}} void @transpose_transpose_struct_member( - // CHECK: [[M:%.*]] = load <6 x i32>, <6 x i32>* {{.*}}, align 4 - // CHECK-NEXT: [[M_T:%.*]] = call <6 x i32> @llvm.matrix.transpose.v6i32(<6 x i32> [[M]], i32 1, i32 6) - // CHECK-NEXT: [[M_T2:%.*]] = call <6 x i32> @llvm.matrix.transpose.v6i32(<6 x i32> [[M_T]], i32 6, i32 1) - // CHECK-NEXT: [[F_ADDR:%.*]] = load %struct.Foo*, %struct.Foo** %F.addr, align 8 - // CHECK-NEXT: [[IN_PTR:%.*]] = getelementptr inbounds %struct.Foo, %struct.Foo* [[F_ADDR]], i32 0, i32 0 - // CHECK-NEXT: [[IN_PTR_C:%.*]] = bitcast [6 x i32]* [[IN_PTR]] to <6 x i32>* - // CHECK-NEXT: store <6 x i32> [[M_T2]], <6 x i32>* [[IN_PTR_C]], align 4 + // COMMON-LABEL: define{{.*}} void @transpose_transpose_struct_member( + // COMMON: [[M:%.*]] = load <6 x i32>, <6 x i32>* {{.*}}, align 4 + // COMMON-NEXT: [[M_T:%.*]] = call <6 x i32> @llvm.matrix.transpose.v6i32(<6 x i32> [[M]], i32 1, i32 6) + // COMMON-NEXT: [[M_T2:%.*]] = call <6 x i32> @llvm.matrix.transpose.v6i32(<6 x i32> [[M_T]], i32 6, i32 1) + // CHECK32-NEXT: [[F_ADDR:%.*]] = load %struct.Foo*, %struct.Foo** %F.addr, align 4 + // CHECK64-NEXT: [[F_ADDR:%.*]] = load %struct.Foo*, %struct.Foo** %F.addr, align 8 + // COMMON-NEXT: [[IN_PTR:%.*]] = getelementptr inbounds %struct.Foo, %struct.Foo* [[F_ADDR]], i32 0, i32 0 + // COMMON-NEXT: [[IN_PTR_C:%.*]] = bitcast [6 x i32]* [[IN_PTR]] to <6 x i32>* + // COMMON-NEXT: store <6 x i32> [[M_T2]], <6 x i32>* [[IN_PTR_C]], align 4 F->in = __builtin_matrix_transpose(__builtin_matrix_transpose(F->in)); } @@ -76,13 +82,16 @@ void transpose_transpose_struct_member(struct Foo *F) { dx5x5_t get_matrix(); void transpose_rvalue() { - // CHECK-LABEL: define{{.*}} void @transpose_rvalue() - // CHECK-NEXT: entry: - // CHECK-NEXT: [[M_T_ADDR:%.*]] = alloca [25 x double], align 8 - // CHECK-NEXT: [[CALL:%.*]] = call <25 x double> (...) @get_matrix() - // CHECK-NEXT: [[M_T:%.*]] = call <25 x double> @llvm.matrix.transpose.v25f64(<25 x double> [[CALL]], i32 5, i32 5) - // CHECK-NEXT: [[M_T_ADDR_C:%.*]] = bitcast [25 x double]* [[M_T_ADDR]] to <25 x double>* - // CHECK-NEXT: store <25 x double> [[M_T]], <25 x double>* [[M_T_ADDR_C]], align 8 + // COMMON-LABEL: define{{.*}} void @transpose_rvalue() + // COMMON-NEXT: entry: + // CHECK32-NEXT: [[M_T_ADDR:%.*]] = alloca [25 x double], align 4 + // CHECK64-NEXT: [[M_T_ADDR:%.*]] = alloca [25 x double], align 8 + // CHECK32-NEXT: [[CALL:%.*]] = call <25 x double> bitcast (<25 x double> (...)* @get_matrix to <25 x double> ()*)() + // CHECK64-NEXT: [[CALL:%.*]] = call <25 x double> (...) @get_matrix() + // COMMON-NEXT: [[M_T:%.*]] = call <25 x double> @llvm.matrix.transpose.v25f64(<25 x double> [[CALL]], i32 5, i32 5) + // COMMON-NEXT: [[M_T_ADDR_C:%.*]] = bitcast [25 x double]* [[M_T_ADDR]] to <25 x double>* + // CHECK32-NEXT: store <25 x double> [[M_T]], <25 x double>* [[M_T_ADDR_C]], align 4 + // CHECK64-NEXT: store <25 x double> [[M_T]], <25 x double>* [[M_T_ADDR_C]], align 8 dx5x5_t m_t = __builtin_matrix_transpose(get_matrix()); } @@ -90,162 +99,215 @@ void transpose_rvalue() { const dx5x5_t global_matrix; void transpose_global() { - // CHECK-LABEL: define{{.*}} void @transpose_global() - // CHECK-NEXT: entry: - // CHECK-NEXT: [[M_T_ADDR:%.*]] = alloca [25 x double], align 8 - // CHECK-NEXT: [[GLOBAL_MATRIX:%.*]] = load <25 x double>, <25 x double>* bitcast ([25 x double]* @global_matrix to <25 x double>*), align 8 - // CHECK-NEXT: [[M_T:%.*]] = call <25 x double> @llvm.matrix.transpose.v25f64(<25 x double> [[GLOBAL_MATRIX]], i32 5, i32 5) - // CHECK-NEXT: [[M_T_ADDR_C:%.*]] = bitcast [25 x double]* [[M_T_ADDR]] to <25 x double>* - // CHECK-NEXT: store <25 x double> [[M_T]], <25 x double>* [[M_T_ADDR_C]], align 8 + // COMMON-LABEL: define{{.*}} void @transpose_global() + // COMMON-NEXT: entry: + // CHECK32-NEXT: [[M_T_ADDR:%.*]] = alloca [25 x double], align 4 + // CHECK32-NEXT: [[GLOBAL_MATRIX:%.*]] = load <25 x double>, <25 x double>* bitcast ([25 x double]* @global_matrix to <25 x double>*), align 4 + // CHECK64-NEXT: [[M_T_ADDR:%.*]] = alloca [25 x double], align 8 + // CHECK64-NEXT: [[GLOBAL_MATRIX:%.*]] = load <25 x double>, <25 x double>* bitcast ([25 x double]* @global_matrix to <25 x double>*), align 8 + // COMMON-NEXT: [[M_T:%.*]] = call <25 x double> @llvm.matrix.transpose.v25f64(<25 x double> [[GLOBAL_MATRIX]], i32 5, i32 5) + // COMMON-NEXT: [[M_T_ADDR_C:%.*]] = bitcast [25 x double]* [[M_T_ADDR]] to <25 x double>* + // CHECK32-NEXT: store <25 x double> [[M_T]], <25 x double>* [[M_T_ADDR_C]], align 4 + // CHECK64-NEXT: store <25 x double> [[M_T]], <25 x double>* [[M_T_ADDR_C]], align 8 dx5x5_t m_t = __builtin_matrix_transpose(global_matrix); } void column_major_load_with_const_stride_double(double *Ptr) { - // CHECK-LABEL: define{{.*}} void @column_major_load_with_const_stride_double(double* %Ptr) - // CHECK: [[PTR:%.*]] = load double*, double** %Ptr.addr, align 8 - // CHECK-NEXT: call <25 x double> @llvm.matrix.column.major.load.v25f64(double* align 8 [[PTR]], i64 5, i1 false, i32 5, i32 5) + // COMMON-LABEL: define{{.*}} void @column_major_load_with_const_stride_double(double* %Ptr) + // CHECK32: [[PTR:%.*]] = load double*, double** %Ptr.addr, align 4 + // CHECK32-NEXT: call <25 x double> @llvm.matrix.column.major.load.v25f64.i32(double* align 4 [[PTR]], i32 5, i1 false, i32 5, i32 5) + // CHECK64: [[PTR:%.*]] = load double*, double** %Ptr.addr, align 8 + // CHECK64-NEXT: call <25 x double> @llvm.matrix.column.major.load.v25f64.i64(double* align 8 [[PTR]], i64 5, i1 false, i32 5, i32 5) dx5x5_t m_a1 = __builtin_matrix_column_major_load(Ptr, 5, 5, 5); } void column_major_load_with_const_stride2_double(double *Ptr) { - // CHECK-LABEL: define{{.*}} void @column_major_load_with_const_stride2_double(double* %Ptr) - // CHECK: [[PTR:%.*]] = load double*, double** %Ptr.addr, align 8 - // CHECK-NEXT: call <25 x double> @llvm.matrix.column.major.load.v25f64(double* align 8 [[PTR]], i64 15, i1 false, i32 5, i32 5) + // COMMON-LABEL: define{{.*}} void @column_major_load_with_const_stride2_double(double* %Ptr) + // CHECK32: [[PTR:%.*]] = load double*, double** %Ptr.addr, align 4 + // CHECK32-NEXT: call <25 x double> @llvm.matrix.column.major.load.v25f64.i32(double* align 4 [[PTR]], i32 15, i1 false, i32 5, i32 5) + // CHECK64: [[PTR:%.*]] = load double*, double** %Ptr.addr, align 8 + // CHECK64-NEXT: call <25 x double> @llvm.matrix.column.major.load.v25f64.i64(double* align 8 [[PTR]], i64 15, i1 false, i32 5, i32 5) dx5x5_t m_a2 = __builtin_matrix_column_major_load(Ptr, 5, 5, 2 * 3 + 9); } void column_major_load_with_variable_stride_ull_float(float *Ptr, unsigned long long S) { - // CHECK-LABEL: define{{.*}} void @column_major_load_with_variable_stride_ull_float(float* %Ptr, i64 %S) - // CHECK: [[S:%.*]] = load i64, i64* %S.addr, align 8 - // CHECK-NEXT: [[PTR:%.*]] = load float*, float** %Ptr.addr, align 8 - // CHECK-NEXT: call <6 x float> @llvm.matrix.column.major.load.v6f32(float* align 4 [[PTR]], i64 [[S]], i1 false, i32 2, i32 3) + // COMMON-LABEL: define{{.*}} void @column_major_load_with_variable_stride_ull_float(float* %Ptr, i64 %S) + // CHECK32: [[S:%.*]] = load i64, i64* %S.addr, align 8 + // CHECK32-NEXT: [[STRIDE_TRUNC:%.*]] = trunc i64 [[S]] to i32 + // CHECK32-NEXT: [[PTR:%.*]] = load float*, float** %Ptr.addr, align 4 + // CHECK32-NEXT: call <6 x float> @llvm.matrix.column.major.load.v6f32.i32(float* align 4 [[PTR]], i32 [[STRIDE_TRUNC]], i1 false, i32 2, i32 3) + + // CHECK64: [[S:%.*]] = load i64, i64* %S.addr, align 8 + // CHECK64-NEXT: [[PTR:%.*]] = load float*, float** %Ptr.addr, align 8 + // CHECK64-NEXT: call <6 x float> @llvm.matrix.column.major.load.v6f32.i64(float* align 4 [[PTR]], i64 [[S]], i1 false, i32 2, i32 3) fx2x3_t m_b = __builtin_matrix_column_major_load(Ptr, 2, 3, S); } void column_major_load_with_stride_math_int(int *Ptr, int S) { - // CHECK-LABEL: define{{.*}} void @column_major_load_with_stride_math_int(i32* %Ptr, i32 %S) - // CHECK: [[S:%.*]] = load i32, i32* %S.addr, align 4 - // CHECK-NEXT: [[STRIDE:%.*]] = add nsw i32 [[S]], 32 - // CHECK-NEXT: [[STRIDE_EXT:%.*]] = sext i32 [[STRIDE]] to i64 - // CHECK-NEXT: [[PTR:%.*]] = load i32*, i32** %Ptr.addr, align 8 - // CHECK-NEXT: call <80 x i32> @llvm.matrix.column.major.load.v80i32(i32* align 4 [[PTR]], i64 [[STRIDE_EXT]], i1 false, i32 4, i32 20) + // COMMON-LABEL: define{{.*}} void @column_major_load_with_stride_math_int(i32* %Ptr, i32 %S) + // COMMON: [[S:%.*]] = load i32, i32* %S.addr, align 4 + // COMMON-NEXT: [[STRIDE:%.*]] = add nsw i32 [[S]], 32 + // CHECK32-NEXT: [[PTR:%.*]] = load i32*, i32** %Ptr.addr, align 4 + // CHECK32-NEXT: call <80 x i32> @llvm.matrix.column.major.load.v80i32.i32(i32* align 4 [[PTR]], i32 [[STRIDE]], i1 false, i32 4, i32 20) + // + // CHECK64-NEXT: [[STRIDE_EXT:%.*]] = sext i32 [[STRIDE]] to i64 + // CHECK64-NEXT: [[PTR:%.*]] = load i32*, i32** %Ptr.addr, align 8 + // CHECK64-NEXT: call <80 x i32> @llvm.matrix.column.major.load.v80i32.i64(i32* align 4 [[PTR]], i64 [[STRIDE_EXT]], i1 false, i32 4, i32 20) ix4x20_t m_c = __builtin_matrix_column_major_load(Ptr, 4, 20, S + 32); } void column_major_load_with_stride_math_s_int(int *Ptr, short S) { - // CHECK-LABEL: define{{.*}} void @column_major_load_with_stride_math_s_int(i32* %Ptr, i16 signext %S) - // CHECK: [[S:%.*]] = load i16, i16* %S.addr, align 2 - // CHECK-NEXT: [[S_EXT:%.*]] = sext i16 [[S]] to i32 - // CHECK-NEXT: [[STRIDE:%.*]] = add nsw i32 [[S_EXT]], 32 - // CHECK-NEXT: [[STRIDE_EXT:%.*]] = sext i32 [[STRIDE]] to i64 - // CHECK-NEXT: [[PTR:%.*]] = load i32*, i32** %Ptr.addr, align 8 - // CHECK-NEXT: %matrix = call <80 x i32> @llvm.matrix.column.major.load.v80i32(i32* align 4 [[PTR]], i64 [[STRIDE_EXT]], i1 false, i32 4, i32 20) + // COMMON-LABEL: define{{.*}} void @column_major_load_with_stride_math_s_int(i32* %Ptr, i16 signext %S) + // COMMON: [[S:%.*]] = load i16, i16* %S.addr, align 2 + // COMMON-NEXT: [[S_EXT:%.*]] = sext i16 [[S]] to i32 + // COMMON-NEXT: [[STRIDE:%.*]] = add nsw i32 [[S_EXT]], 32 + // CHECK32-NEXT: [[PTR:%.*]] = load i32*, i32** %Ptr.addr, align 4 + // CHECK32-NEXT: %matrix = call <80 x i32> @llvm.matrix.column.major.load.v80i32.i32(i32* align 4 [[PTR]], i32 [[STRIDE]], i1 false, i32 4, i32 20) + // + // CHECK64-NEXT: [[STRIDE_EXT:%.*]] = sext i32 [[STRIDE]] to i64 + // CHECK64-NEXT: [[PTR:%.*]] = load i32*, i32** %Ptr.addr, align 8 + // CHECK64-NEXT: %matrix = call <80 x i32> @llvm.matrix.column.major.load.v80i32.i64(i32* align 4 [[PTR]], i64 [[STRIDE_EXT]], i1 false, i32 4, i32 20) ix4x20_t m_c = __builtin_matrix_column_major_load(Ptr, 4, 20, S + 32); } void column_major_load_array1(double Ptr[25]) { - // CHECK-LABEL: define{{.*}} void @column_major_load_array1(double* %Ptr) - // CHECK: [[ADDR:%.*]] = load double*, double** %Ptr.addr, align 8 - // CHECK-NEXT: call <25 x double> @llvm.matrix.column.major.load.v25f64(double* align 8 [[ADDR]], i64 5, i1 false, i32 5, i32 5) + // COMMON-LABEL: define{{.*}} void @column_major_load_array1(double* %Ptr) + // CHECK32: [[ADDR:%.*]] = load double*, double** %Ptr.addr, align 4 + // CHECK32-NEXT: call <25 x double> @llvm.matrix.column.major.load.v25f64.i32(double* align 4 [[ADDR]], i32 5, i1 false, i32 5, i32 5) + + // CHECK64: [[ADDR:%.*]] = load double*, double** %Ptr.addr, align 8 + // CHECK64-NEXT: call <25 x double> @llvm.matrix.column.major.load.v25f64.i64(double* align 8 [[ADDR]], i64 5, i1 false, i32 5, i32 5) dx5x5_t m = __builtin_matrix_column_major_load(Ptr, 5, 5, 5); } void column_major_load_array2() { - // CHECK-LABEL: define{{.*}} void @column_major_load_array2() #0 { - // CHECK-NEXT: entry: - // CHECK-NEXT: [[PTR:%.*]] = alloca [25 x double], align 16 - // CHECK: [[ARRAY_DEC:%.*]] = getelementptr inbounds [25 x double], [25 x double]* [[PTR]], i64 0, i64 0 - // CHECK-NEXT: call <25 x double> @llvm.matrix.column.major.load.v25f64(double* align 16 [[ARRAY_DEC]], i64 5, i1 false, i32 5, i32 5) + // COMMON-LABEL: define{{.*}} void @column_major_load_array2() #0 { + // COMMON-NEXT: entry: + // CHECK32-NEXT: [[PTR:%.*]] = alloca [25 x double], align 8 + // CHECK32: [[ARRAY_DEC:%.*]] = getelementptr inbounds [25 x double], [25 x double]* [[PTR]], i32 0, i32 0 + // CHECK32-NEXT: call <25 x double> @llvm.matrix.column.major.load.v25f64.i32(double* align 8 [[ARRAY_DEC]], i32 5, i1 false, i32 5, i32 5) + + // CHECK64-NEXT: [[PTR:%.*]] = alloca [25 x double], align 16 + // CHECK64: [[ARRAY_DEC:%.*]] = getelementptr inbounds [25 x double], [25 x double]* [[PTR]], i64 0, i64 0 + // CHECK64-NEXT: call <25 x double> @llvm.matrix.column.major.load.v25f64.i64(double* align 16 [[ARRAY_DEC]], i64 5, i1 false, i32 5, i32 5) double Ptr[25]; dx5x5_t m = __builtin_matrix_column_major_load(Ptr, 5, 5, 5); } void column_major_load_const(const double *Ptr) { - // CHECK-LABEL: define{{.*}} void @column_major_load_const(double* %Ptr) - // CHECK: [[PTR:%.*]] = load double*, double** %Ptr.addr, align 8 - // CHECK-NEXT: call <25 x double> @llvm.matrix.column.major.load.v25f64(double* align 8 [[PTR]], i64 5, i1 false, i32 5, i32 5) + // COMMON-LABEL: define{{.*}} void @column_major_load_const(double* %Ptr) + // CHECK32: [[PTR:%.*]] = load double*, double** %Ptr.addr, align 4 + // CHECK32-NEXT: call <25 x double> @llvm.matrix.column.major.load.v25f64.i32(double* align 4 [[PTR]], i32 5, i1 false, i32 5, i32 5) + // + // CHECK64: [[PTR:%.*]] = load double*, double** %Ptr.addr, align 8 + // CHECK64-NEXT: call <25 x double> @llvm.matrix.column.major.load.v25f64.i64(double* align 8 [[PTR]], i64 5, i1 false, i32 5, i32 5) dx5x5_t m_a1 = __builtin_matrix_column_major_load(Ptr, 5, 5, 5); } void column_major_load_volatile(volatile double *Ptr) { - // CHECK-LABEL: define{{.*}} void @column_major_load_volatile(double* %Ptr) - // CHECK: [[PTR:%.*]] = load double*, double** %Ptr.addr, align 8 - // CHECK-NEXT: call <25 x double> @llvm.matrix.column.major.load.v25f64(double* align 8 [[PTR]], i64 5, i1 true, i32 5, i32 5) + // COMMON-LABEL: define{{.*}} void @column_major_load_volatile(double* %Ptr) + // CHECK32: [[PTR:%.*]] = load double*, double** %Ptr.addr, align 4 + // CHECK32-NEXT: call <25 x double> @llvm.matrix.column.major.load.v25f64.i32(double* align 4 [[PTR]], i32 5, i1 true, i32 5, i32 5) + // + // CHECK64: [[PTR:%.*]] = load double*, double** %Ptr.addr, align 8 + // CHECK64-NEXT: call <25 x double> @llvm.matrix.column.major.load.v25f64.i64(double* align 8 [[PTR]], i64 5, i1 true, i32 5, i32 5) dx5x5_t m_a1 = __builtin_matrix_column_major_load(Ptr, 5, 5, 5); } void column_major_store_with_const_stride_double(double *Ptr) { - // CHECK-LABEL: define{{.*}} void @column_major_store_with_const_stride_double(double* %Ptr) - // CHECK: [[M:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 8 - // CHECK-NEXT: [[PTR:%.*]] = load double*, double** %Ptr.addr, align 8 - // CHECK-NEXT: call void @llvm.matrix.column.major.store.v25f64(<25 x double> [[M]], double* align 8 [[PTR]], i64 5, i1 false, i32 5, i32 5) + // COMMON-LABEL: define{{.*}} void @column_major_store_with_const_stride_double(double* %Ptr) + // CHECK32: [[M:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 4 + // CHECK32-NEXT: [[PTR:%.*]] = load double*, double** %Ptr.addr, align 4 + // CHECK32-NEXT: call void @llvm.matrix.column.major.store.v25f64.i32(<25 x double> [[M]], double* align 4 [[PTR]], i32 5, i1 false, i32 5, i32 5) + // + // CHECK64: [[M:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 8 + // CHECK64-NEXT: [[PTR:%.*]] = load double*, double** %Ptr.addr, align 8 + // CHECK64-NEXT: call void @llvm.matrix.column.major.store.v25f64.i64(<25 x double> [[M]], double* align 8 [[PTR]], i64 5, i1 false, i32 5, i32 5) dx5x5_t m; __builtin_matrix_column_major_store(m, Ptr, 5); } void column_major_store_with_const_stride2_double(double *Ptr) { - // CHECK-LABEL: define{{.*}} void @column_major_store_with_const_stride2_double(double* %Ptr) - // CHECK: [[M:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 8 - // CHECK-NEXT: [[PTR:%.*]] = load double*, double** %Ptr.addr, align 8 - // CHECK-NEXT: call void @llvm.matrix.column.major.store.v25f64(<25 x double> [[M]], double* align 8 [[PTR]], i64 15, i1 false, i32 5, i32 5) + // COMMON-LABEL: define{{.*}} void @column_major_store_with_const_stride2_double(double* %Ptr) + // CHECK32: [[M:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 4 + // CHECK32-NEXT: [[PTR:%.*]] = load double*, double** %Ptr.addr, align 4 + // CHECK32-NEXT: call void @llvm.matrix.column.major.store.v25f64.i32(<25 x double> [[M]], double* align 4 [[PTR]], i32 15, i1 false, i32 5, i32 5) + // + // CHECK64: [[M:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 8 + // CHECK64-NEXT: [[PTR:%.*]] = load double*, double** %Ptr.addr, align 8 + // CHECK64-NEXT: call void @llvm.matrix.column.major.store.v25f64.i64(<25 x double> [[M]], double* align 8 [[PTR]], i64 15, i1 false, i32 5, i32 5) // dx5x5_t m; __builtin_matrix_column_major_store(m, Ptr, 2 * 3 + 9); } void column_major_store_with_stride_math_int(int *Ptr, int S) { - // CHECK-LABEL: define{{.*}} void @column_major_store_with_stride_math_int(i32* %Ptr, i32 %S) - // CHECK: [[M:%.*]] = load <80 x i32>, <80 x i32>* {{.*}}, align 4 - // CHECK-NEXT: [[PTR:%.*]] = load i32*, i32** %Ptr.addr, align 8 - // CHECK-NEXT: [[S:%.*]] = load i32, i32* %S.addr, align 4 - // CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[S]], 32 - // CHECK-NEXT: [[IDX:%.*]] = sext i32 [[ADD]] to i64 - // CHECK-NEXT: call void @llvm.matrix.column.major.store.v80i32(<80 x i32> [[M]], i32* align 4 [[PTR]], i64 [[IDX]], i1 false, i32 4, i32 20) + // COMMON-LABEL: define{{.*}} void @column_major_store_with_stride_math_int(i32* %Ptr, i32 %S) + // COMMON: [[M:%.*]] = load <80 x i32>, <80 x i32>* {{.*}}, align 4 + // CHECK32-NEXT: [[PTR:%.*]] = load i32*, i32** %Ptr.addr, align 4 + // CHECK64-NEXT: [[PTR:%.*]] = load i32*, i32** %Ptr.addr, align 8 + // COMMON-NEXT: [[S:%.*]] = load i32, i32* %S.addr, align 4 + // COMMON-NEXT: [[ADD:%.*]] = add nsw i32 [[S]], 32 + // CHECK32-NEXT: call void @llvm.matrix.column.major.store.v80i32.i32(<80 x i32> [[M]], i32* align 4 [[PTR]], i32 [[ADD]], i1 false, i32 4, i32 20) + // + // CHECK64-NEXT: [[IDX:%.*]] = sext i32 [[ADD]] to i64 + // CHECK64-NEXT: call void @llvm.matrix.column.major.store.v80i32.i64(<80 x i32> [[M]], i32* align 4 [[PTR]], i64 [[IDX]], i1 false, i32 4, i32 20) ix4x20_t m; __builtin_matrix_column_major_store(m, Ptr, S + 32); } void column_major_store_with_stride_math_s_int(int *Ptr, short S) { - // CHECK-LABEL: define{{.*}} void @column_major_store_with_stride_math_s_int(i32* %Ptr, i16 signext %S) - // CHECK: [[M:%.*]] = load <80 x i32>, <80 x i32>* {{.*}}, align 4 - // CHECK-NEXT: [[PTR:%.*]] = load i32*, i32** %Ptr.addr, align 8 - // CHECK-NEXT: [[S:%.*]] = load i16, i16* %S.addr, align 2 - // CHECK-NEXT: [[EXT:%.*]] = sext i16 [[S]] to i32 - // CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[EXT]], 2 - // CHECK-NEXT: [[IDX:%.*]] = sext i32 [[ADD]] to i64 - // CHECK-NEXT: call void @llvm.matrix.column.major.store.v80i32(<80 x i32> [[M]], i32* align 4 [[PTR]], i64 [[IDX]], i1 false, i32 4, i32 20) + // COMMON-LABEL: define{{.*}} void @column_major_store_with_stride_math_s_int(i32* %Ptr, i16 signext %S) + // COMMON: [[M:%.*]] = load <80 x i32>, <80 x i32>* {{.*}}, align 4 + // CHECK32-NEXT: [[PTR:%.*]] = load i32*, i32** %Ptr.addr, align 4 + // CHECK64-NEXT: [[PTR:%.*]] = load i32*, i32** %Ptr.addr, align 8 + // COMMON-NEXT: [[S:%.*]] = load i16, i16* %S.addr, align 2 + // COMMON-NEXT: [[EXT:%.*]] = sext i16 [[S]] to i32 + // COMMON-NEXT: [[ADD:%.*]] = add nsw i32 [[EXT]], 2 + // CHECK32-NEXT: call void @llvm.matrix.column.major.store.v80i32.i32(<80 x i32> [[M]], i32* align 4 [[PTR]], i32 [[ADD]], i1 false, i32 4, i32 20) + // + // CHECK64-NEXT: [[IDX:%.*]] = sext i32 [[ADD]] to i64 + // CHECK64-NEXT: call void @llvm.matrix.column.major.store.v80i32.i64(<80 x i32> [[M]], i32* align 4 [[PTR]], i64 [[IDX]], i1 false, i32 4, i32 20) ix4x20_t m; __builtin_matrix_column_major_store(m, Ptr, S + 2); } void column_major_store_array1(double Ptr[25]) { - // CHECK-LABEL: define{{.*}} void @column_major_store_array1(double* %Ptr) - // CHECK: [[M:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 8 - // CHECK-NEXT: [[PTR:%.*]] = load double*, double** %Ptr.addr, align 8 - // CHECK-NEXT: call void @llvm.matrix.column.major.store.v25f64(<25 x double> [[M]], double* align 8 [[PTR]], i64 5, i1 false, i32 5, i32 5) + // COMMON-LABEL: define{{.*}} void @column_major_store_array1(double* %Ptr) + // CHECK32: [[M:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 4 + // CHECK32-NEXT: [[PTR:%.*]] = load double*, double** %Ptr.addr, align 4 + // CHECK32-NEXT: call void @llvm.matrix.column.major.store.v25f64.i32(<25 x double> [[M]], double* align 4 [[PTR]], i32 5, i1 false, i32 5, i32 5) + // + // CHECK64: [[M:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 8 + // CHECK64-NEXT: [[PTR:%.*]] = load double*, double** %Ptr.addr, align 8 + // CHECK64-NEXT: call void @llvm.matrix.column.major.store.v25f64.i64(<25 x double> [[M]], double* align 8 [[PTR]], i64 5, i1 false, i32 5, i32 5) dx5x5_t m; __builtin_matrix_column_major_store(m, Ptr, 5); } void column_major_store_array2() { - // CHECK-LABEL: define{{.*}} void @column_major_store_array2() - // CHECK: [[M:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 8 - // CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds [25 x double], [25 x double]* %Ptr, i64 0, i64 0 - // CHECK-NEXT: call void @llvm.matrix.column.major.store.v25f64(<25 x double> [[M]], double* align 16 [[PTR]], i64 5, i1 false, i32 5, i32 5) + // COMMON-LABEL: define{{.*}} void @column_major_store_array2() + // CHECK32: [[M:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 4 + // CHECK32-NEXT: [[PTR:%.*]] = getelementptr inbounds [25 x double], [25 x double]* %Ptr, i32 0, i32 0 + // CHECK32-NEXT: call void @llvm.matrix.column.major.store.v25f64.i32(<25 x double> [[M]], double* align 8 [[PTR]], i32 5, i1 false, i32 5, i32 5) + // + // CHECK64: [[M:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 8 + // CHECK64-NEXT: [[PTR:%.*]] = getelementptr inbounds [25 x double], [25 x double]* %Ptr, i64 0, i64 0 + // CHECK64-NEXT: call void @llvm.matrix.column.major.store.v25f64.i64(<25 x double> [[M]], double* align 16 [[PTR]], i64 5, i1 false, i32 5, i32 5) double Ptr[25]; dx5x5_t m; @@ -253,10 +315,14 @@ void column_major_store_array2() { } void column_major_store_volatile(volatile double *Ptr) { - // CHECK-LABEL: define{{.*}} void @column_major_store_volatile(double* %Ptr) #0 { - // CHECK: [[M:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 8 - // CHECK-NEXT: [[PTR:%.*]] = load double*, double** %Ptr.addr, align 8 - // CHECK-NEXT: call void @llvm.matrix.column.major.store.v25f64(<25 x double> [[M]], double* align 8 [[PTR]], i64 5, i1 true, i32 5, i32 5) + // COMMON-LABEL: define{{.*}} void @column_major_store_volatile(double* %Ptr) #0 { + // CHECK32: [[M:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 4 + // CHECK32-NEXT: [[PTR:%.*]] = load double*, double** %Ptr.addr, align 4 + // CHECK32-NEXT: call void @llvm.matrix.column.major.store.v25f64.i32(<25 x double> [[M]], double* align 4 [[PTR]], i32 5, i1 true, i32 5, i32 5) + // + // CHECK64: [[M:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 8 + // CHECK64-NEXT: [[PTR:%.*]] = load double*, double** %Ptr.addr, align 8 + // CHECK64-NEXT: call void @llvm.matrix.column.major.store.v25f64.i64(<25 x double> [[M]], double* align 8 [[PTR]], i64 5, i1 true, i32 5, i32 5) dx5x5_t m; __builtin_matrix_column_major_store(m, Ptr, 5); diff --git a/clang/test/CodeGenCXX/matrix-type-builtins.cpp b/clang/test/CodeGenCXX/matrix-type-builtins.cpp index 6cae343d2c24..d95774feb7c7 100644 --- a/clang/test/CodeGenCXX/matrix-type-builtins.cpp +++ b/clang/test/CodeGenCXX/matrix-type-builtins.cpp @@ -94,7 +94,7 @@ void test_column_major_load_with_stride_template_double(double *Ptr) { // CHECK-LABEL: define linkonce_odr <40 x double> @_Z29column_major_load_with_strideIdLj10ELj4ELj15EEu11matrix_typeIXT0_EXT1_ET_EPS0_(double* %Ptr) // CHECK: [[PTR:%.*]] = load double*, double** %Ptr.addr, align 8 - // CHECK-NEXT: call <40 x double> @llvm.matrix.column.major.load.v40f64(double* align 8 [[PTR]], i64 15, i1 false, i32 10, i32 4) + // CHECK-NEXT: call <40 x double> @llvm.matrix.column.major.load.v40f64.i64(double* align 8 [[PTR]], i64 15, i1 false, i32 10, i32 4) matrix_t M1 = column_major_load_with_stride(Ptr); } @@ -106,7 +106,7 @@ void test_column_major_load_with_stride_template_int(int *Ptr) { // CHECK-LABEL: define linkonce_odr <6 x i32> @_Z29column_major_load_with_strideIiLj3ELj2ELj12EEu11matrix_typeIXT0_EXT1_ET_EPS0_(i32* %Ptr) // CHECK: [[PTR:%.*]] = load i32*, i32** %Ptr.addr, align 8 - // CHECK-NEXT: call <6 x i32> @llvm.matrix.column.major.load.v6i32(i32* align 4 [[PTR]], i64 12, i1 false, i32 3, i32 2) + // CHECK-NEXT: call <6 x i32> @llvm.matrix.column.major.load.v6i32.i64(i32* align 4 [[PTR]], i64 12, i1 false, i32 3, i32 2) matrix_t M1 = column_major_load_with_stride(Ptr); } @@ -124,7 +124,7 @@ void test_column_major_load_stride_wrapper(int *Ptr, UnsignedWrapper &W) { // CHECK-NEXT: [[STRIDE:%.*]] = call i32 @_ZN15UnsignedWrappercvjEv(%struct.UnsignedWrapper* {{[^,]*}} [[W]]) // CHECK-NEXT: [[STRIDE_EXT:%.*]] = zext i32 [[STRIDE]] to i64 // CHECK-NEXT: [[PTR:%.*]] = load i32*, i32** %Ptr.addr, align 8 - // CHECK-NEXT: call <4 x i32> @llvm.matrix.column.major.load.v4i32(i32* align 4 [[PTR]], i64 [[STRIDE_EXT]], i1 false, i32 2, i32 2) + // CHECK-NEXT: call <4 x i32> @llvm.matrix.column.major.load.v4i32.i64(i32* align 4 [[PTR]], i64 [[STRIDE_EXT]], i1 false, i32 2, i32 2) matrix_t M1 = __builtin_matrix_column_major_load(Ptr, 2, 2, W); } @@ -133,7 +133,7 @@ constexpr int constexpr3() { return 3; } void test_column_major_load_constexpr_num_rows(int *Ptr) { // CHECK-LABEL: define{{.*}} void @_Z41test_column_major_load_constexpr_num_rowsPi(i32* %Ptr) // CHECK: [[PTR:%.*]] = load i32*, i32** %Ptr.addr, align 8 - // CHECK-NEXT: call <6 x i32> @llvm.matrix.column.major.load.v6i32(i32* align 4 [[PTR]], i64 3, i1 false, i32 3, i32 2) + // CHECK-NEXT: call <6 x i32> @llvm.matrix.column.major.load.v6i32.i64(i32* align 4 [[PTR]], i64 3, i1 false, i32 3, i32 2) matrix_t M1 = __builtin_matrix_column_major_load(Ptr, constexpr3(), 2, 3); } @@ -143,7 +143,7 @@ constexpr int constexpr1() { return 1; } void test_column_major_load_constexpr_num_columns(int *Ptr) { // CHECK-LABEL: define{{.*}} void @_Z44test_column_major_load_constexpr_num_columnsPi(i32* %Ptr) // CHECK: [[PTR:%.*]] = load i32*, i32** %Ptr.addr, align 8 - // CHECK-NEXT: call <2 x i32> @llvm.matrix.column.major.load.v2i32(i32* align 4 [[PTR]], i64 3, i1 false, i32 2, i32 1) + // CHECK-NEXT: call <2 x i32> @llvm.matrix.column.major.load.v2i32.i64(i32* align 4 [[PTR]], i64 3, i1 false, i32 2, i32 1) matrix_t M1 = __builtin_matrix_column_major_load(Ptr, 2, constexpr1(), 3); } @@ -153,7 +153,7 @@ constexpr int constexpr_plus1() { return N + 1; } void test_column_major_load_constexpr_num_columns_temp(int *Ptr) { // CHECK-LABEL: define{{.*}} void @_Z49test_column_major_load_constexpr_num_columns_tempPi(i32* %Ptr) // CHECK: [[PTR:%.*]] = load i32*, i32** %Ptr.addr, align 8 - // CHECK-NEXT: call <10 x i32> @llvm.matrix.column.major.load.v10i32(i32* align 4 [[PTR]], i64 3, i1 false, i32 2, i32 5) + // CHECK-NEXT: call <10 x i32> @llvm.matrix.column.major.load.v10i32.i64(i32* align 4 [[PTR]], i64 3, i1 false, i32 2, i32 5) matrix_t M1 = __builtin_matrix_column_major_load(Ptr, 2, constexpr_plus1<4>(), 3); } @@ -162,7 +162,7 @@ void test_column_major_load_constexpr_stride_constexpr(int *Ptr) { // CHECK: [[STRIDE:%.*]] = call i32 @_Z10constexpr3v() // CHECK-NEXT: [[STRIDE_EXT:%.*]] = sext i32 [[STRIDE]] to i64 // CHECK-NEXT: [[PTR:%.*]] = load i32*, i32** %Ptr.addr, align 8 - // CHECK-NEXT: call <4 x i32> @llvm.matrix.column.major.load.v4i32(i32* align 4 [[PTR]], i64 [[STRIDE_EXT]], i1 false, i32 2, i32 2) + // CHECK-NEXT: call <4 x i32> @llvm.matrix.column.major.load.v4i32.i64(i32* align 4 [[PTR]], i64 [[STRIDE_EXT]], i1 false, i32 2, i32 2) matrix_t M1 = __builtin_matrix_column_major_load(Ptr, 2, 2, constexpr3()); } @@ -200,7 +200,7 @@ void test_column_major_store_with_stride_template_double(double *Ptr) { // CHECK-LABEL: define linkonce_odr void @_Z30column_major_store_with_strideIdLj10ELj4ELj15EEvRu11matrix_typeIXT0_EXT1_ET_EPS0_([40 x double]* nonnull align 8 dereferenceable(320) %m, double* %Ptr) // CHECK: [[M:%.*]] = load <40 x double>, <40 x double>* {{.*}}, align 8 // CHECK-NEXT: [[PTR:%.*]] = load double*, double** %Ptr.addr, align 8 - // CHECK-NEXT: call void @llvm.matrix.column.major.store.v40f64(<40 x double> [[M]], double* align 8 [[PTR]], i64 15, i1 false, i32 10, i32 4) + // CHECK-NEXT: call void @llvm.matrix.column.major.store.v40f64.i64(<40 x double> [[M]], double* align 8 [[PTR]], i64 15, i1 false, i32 10, i32 4) matrix_t M1; column_major_store_with_stride(M1, Ptr); @@ -214,7 +214,7 @@ void test_column_major_store_with_stride_template_int(int *Ptr) { // CHECK-LABEL: define linkonce_odr void @_Z30column_major_store_with_strideIiLj3ELj2ELj3EEvRu11matrix_typeIXT0_EXT1_ET_EPS0_([6 x i32]* nonnull align 4 dereferenceable(24) %m, i32* %Ptr) // CHECK: [[M:%.*]] = load <6 x i32>, <6 x i32>* {{.*}}, align 4 // CHECK-NEXT: [[PTR:%.*]] = load i32*, i32** %Ptr.addr, align 8 - // CHECK-NEXT: call void @llvm.matrix.column.major.store.v6i32(<6 x i32> [[M]], i32* align 4 [[PTR]], i64 3, i1 false, i32 3, i32 2) + // CHECK-NEXT: call void @llvm.matrix.column.major.store.v6i32.i64(<6 x i32> [[M]], i32* align 4 [[PTR]], i64 3, i1 false, i32 3, i32 2) matrix_t M1; column_major_store_with_stride(M1, Ptr); @@ -227,7 +227,7 @@ void test_column_major_store_stride_wrapper(int *Ptr, UnsignedWrapper &W) { // CHECK-NEXT: [[W:%.*]] = load %struct.UnsignedWrapper*, %struct.UnsignedWrapper** %W.addr, align 8 // CHECK-NEXT: [[IDX:%.*]] = call i32 @_ZN15UnsignedWrappercvjEv(%struct.UnsignedWrapper* {{[^,]*}} [[W]]) // CHECK-NEXT: [[IDX_EXT:%.*]] = zext i32 [[IDX]] to i64 - // CHECK-NEXT: call void @llvm.matrix.column.major.store.v4i32(<4 x i32> [[M]], i32* align 4 [[PTR]], i64 [[IDX_EXT]], i1 false, i32 2, i32 2) + // CHECK-NEXT: call void @llvm.matrix.column.major.store.v4i32.i64(<4 x i32> [[M]], i32* align 4 [[PTR]], i64 [[IDX_EXT]], i1 false, i32 2, i32 2) matrix_t M1; __builtin_matrix_column_major_store(M1, Ptr, W); @@ -239,7 +239,7 @@ void test_column_major_store_constexpr_stride_constexpr(int *Ptr) { // CHECK-NEXT: [[PTR:%.*]] = load i32*, i32** %Ptr.addr, align 8 // CHECK-NEXT: [[IDX:%.*]] = call i32 @_Z10constexpr3v() // CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[IDX]] to i64 - // CHECK-NEXT: call void @llvm.matrix.column.major.store.v4i32(<4 x i32> [[M]], i32* align 4 [[PTR]], i64 [[IDX_EXT]], i1 false, i32 2, i32 2) + // CHECK-NEXT: call void @llvm.matrix.column.major.store.v4i32.i64(<4 x i32> [[M]], i32* align 4 [[PTR]], i64 [[IDX_EXT]], i1 false, i32 2, i32 2) matrix_t M; __builtin_matrix_column_major_store(M, Ptr, constexpr3()); diff --git a/clang/test/CodeGenObjC/matrix-type-builtins.m b/clang/test/CodeGenObjC/matrix-type-builtins.m index f0faaace4442..0d517dd4964a 100644 --- a/clang/test/CodeGenObjC/matrix-type-builtins.m +++ b/clang/test/CodeGenObjC/matrix-type-builtins.m @@ -56,7 +56,7 @@ void test_column_major_load(PtrValue *Ptr, IntValue *Stride) { // CHECK: [[STRIDE:%.*]] = call i32 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i32 (i8*, i8*)*) // CHECK-NEXT: [[STRIDE_EXT:%.*]] = sext i32 [[STRIDE]] to i64 // CHECK: [[PTR:%.*]] = call i32* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i32* (i8*, i8*)*) - // CHECK-NEXT: call <12 x i32> @llvm.matrix.column.major.load.v12i32(i32* align 4 [[PTR]], i64 [[STRIDE_EXT]], i1 false, i32 3, i32 4) + // CHECK-NEXT: call <12 x i32> @llvm.matrix.column.major.load.v12i32.i64(i32* align 4 [[PTR]], i64 [[STRIDE_EXT]], i1 false, i32 3, i32 4) u3x4 m = __builtin_matrix_column_major_load(Ptr.value, 3, 4, Stride.value); } @@ -67,7 +67,7 @@ void test_column_major_store(UnsignedMatrixValue *M, PtrValue *Ptr, IntValue *St // CHECK: [[PTR:%.*]] = call i32* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i32* (i8*, i8*)*) // CHECK: [[IDX:%.*]] = call i32 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i32 (i8*, i8*)*) // CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[IDX]] to i64 - // CHECK-NEXT: call void @llvm.matrix.column.major.store.v12i32(<12 x i32> [[M]], i32* align 4 [[PTR]], i64 [[IDX_EXT]], i1 false, i32 3, i32 4) + // CHECK-NEXT: call void @llvm.matrix.column.major.store.v12i32.i64(<12 x i32> [[M]], i32* align 4 [[PTR]], i64 [[IDX_EXT]], i1 false, i32 3, i32 4) __builtin_matrix_column_major_store(M.value, Ptr.value, Stride.value); } diff --git a/libcxx/include/atomic b/libcxx/include/atomic index 0fc799a24319..57d01ad2791a 100644 --- a/libcxx/include/atomic +++ b/libcxx/include/atomic @@ -2791,10 +2791,13 @@ typedef conditional<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, char>::typ typedef conditional<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, unsigned char>::type __libcpp_unsigned_lock_free; #else // No signed/unsigned lock-free types +#define _LIBCPP_NO_LOCK_FREE_TYPES #endif +#if !defined(_LIBCPP_NO_LOCK_FREE_TYPES) typedef atomic<__libcpp_signed_lock_free> atomic_signed_lock_free; typedef atomic<__libcpp_unsigned_lock_free> atomic_unsigned_lock_free; +#endif #define ATOMIC_FLAG_INIT {false} #define ATOMIC_VAR_INIT(__v) {__v} diff --git a/lldb/include/lldb/Target/PathMappingList.h b/lldb/include/lldb/Target/PathMappingList.h index 9e1e6eb26eb9..fc7b23bcfad3 100644 --- a/lldb/include/lldb/Target/PathMappingList.h +++ b/lldb/include/lldb/Target/PathMappingList.h @@ -72,13 +72,9 @@ public: /// \param[in] path /// The original source file path to try and remap. /// - /// \param[out] new_path - /// The newly remapped filespec that is may or may not exist. - /// /// \return - /// /b true if \a path was successfully located and \a new_path - /// is filled in with a new source path, \b false otherwise. - bool RemapPath(llvm::StringRef path, std::string &new_path) const; + /// The remapped filespec that may or may not exist on disk. + llvm::Optional RemapPath(llvm::StringRef path) const; bool RemapPath(const char *, std::string &) const = delete; bool ReverseRemapPath(const FileSpec &file, FileSpec &fixed) const; @@ -94,14 +90,9 @@ public: /// \param[in] orig_spec /// The original source file path to try and remap. /// - /// \param[out] new_spec - /// The newly remapped filespec that is guaranteed to exist. - /// /// \return - /// /b true if \a orig_spec was successfully located and - /// \a new_spec is filled in with an existing file spec, - /// \b false otherwise. - bool FindFile(const FileSpec &orig_spec, FileSpec &new_spec) const; + /// The newly remapped filespec that is guaranteed to exist. + llvm::Optional FindFile(const FileSpec &orig_spec) const; uint32_t FindIndexForPath(ConstString path) const; diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp index 1f9987c21658..17cfaa79e640 100644 --- a/lldb/source/Core/Module.cpp +++ b/lldb/source/Core/Module.cpp @@ -1595,13 +1595,21 @@ bool Module::MatchesModuleSpec(const ModuleSpec &module_ref) { bool Module::FindSourceFile(const FileSpec &orig_spec, FileSpec &new_spec) const { std::lock_guard guard(m_mutex); - return m_source_mappings.FindFile(orig_spec, new_spec); + if (auto remapped = m_source_mappings.FindFile(orig_spec)) { + new_spec = *remapped; + return true; + } + return false; } bool Module::RemapSourceFile(llvm::StringRef path, std::string &new_path) const { std::lock_guard guard(m_mutex); - return m_source_mappings.RemapPath(path, new_path); + if (auto remapped = m_source_mappings.RemapPath(path)) { + new_path = remapped->GetPath(); + return true; + } + return false; } void Module::RegisterXcodeSDK(llvm::StringRef sdk_name, llvm::StringRef sysroot) { diff --git a/lldb/source/Core/SourceManager.cpp b/lldb/source/Core/SourceManager.cpp index e79fcb48742d..61cf91963557 100644 --- a/lldb/source/Core/SourceManager.cpp +++ b/lldb/source/Core/SourceManager.cpp @@ -441,13 +441,17 @@ void SourceManager::File::CommonInitializer(const FileSpec &file_spec, } // Try remapping if m_file_spec does not correspond to an existing file. if (!FileSystem::Instance().Exists(m_file_spec)) { - FileSpec new_file_spec; - // Check target specific source remappings first, then fall back to - // modules objects can have individual path remappings that were - // detected when the debug info for a module was found. then - if (target->GetSourcePathMap().FindFile(m_file_spec, new_file_spec) || - target->GetImages().FindSourceFile(m_file_spec, new_file_spec)) { - m_file_spec = new_file_spec; + // Check target specific source remappings (i.e., the + // target.source-map setting), then fall back to the module + // specific remapping (i.e., the .dSYM remapping dictionary). + auto remapped = target->GetSourcePathMap().FindFile(m_file_spec); + if (!remapped) { + FileSpec new_spec; + if (target->GetImages().FindSourceFile(m_file_spec, new_spec)) + remapped = new_spec; + } + if (remapped) { + m_file_spec = *remapped; m_mod_time = FileSystem::Instance().GetModificationTime(m_file_spec); } } diff --git a/lldb/source/Symbol/LineEntry.cpp b/lldb/source/Symbol/LineEntry.cpp index a3907f4dd9c0..165ca607f4d6 100644 --- a/lldb/source/Symbol/LineEntry.cpp +++ b/lldb/source/Symbol/LineEntry.cpp @@ -253,9 +253,9 @@ AddressRange LineEntry::GetSameLineContiguousAddressRange( void LineEntry::ApplyFileMappings(lldb::TargetSP target_sp) { if (target_sp) { - // Apply any file remappings to our file - FileSpec new_file_spec; - if (target_sp->GetSourcePathMap().FindFile(original_file, new_file_spec)) - file = new_file_spec; + // Apply any file remappings to our file. + if (auto new_file_spec = + target_sp->GetSourcePathMap().FindFile(original_file)) + file = *new_file_spec; } } diff --git a/lldb/source/Target/PathMappingList.cpp b/lldb/source/Target/PathMappingList.cpp index b22673f55471..0342130a58a0 100644 --- a/lldb/source/Target/PathMappingList.cpp +++ b/lldb/source/Target/PathMappingList.cpp @@ -146,18 +146,29 @@ void PathMappingList::Clear(bool notify) { bool PathMappingList::RemapPath(ConstString path, ConstString &new_path) const { - std::string remapped; - if (RemapPath(path.GetStringRef(), remapped)) { - new_path.SetString(remapped); + if (llvm::Optional remapped = RemapPath(path.GetStringRef())) { + new_path.SetString(remapped->GetPath()); return true; } return false; } -bool PathMappingList::RemapPath(llvm::StringRef path, - std::string &new_path) const { +/// Append components to path, applying style. +static void AppendPathComponents(FileSpec &path, llvm::StringRef components, + llvm::sys::path::Style style) { + auto component = llvm::sys::path::begin(components, style); + auto e = llvm::sys::path::end(components); + while (component != e && + llvm::sys::path::is_separator(*component->data(), style)) + ++component; + for (; component != e; ++component) + path.AppendPathComponent(*component); +} + +llvm::Optional +PathMappingList::RemapPath(llvm::StringRef path) const { if (m_pairs.empty() || path.empty()) - return false; + return {}; LazyBool path_is_relative = eLazyBoolCalculate; for (const auto &it : m_pairs) { auto prefix = it.first.GetStringRef(); @@ -177,11 +188,12 @@ bool PathMappingList::RemapPath(llvm::StringRef path, continue; } FileSpec remapped(it.second.GetStringRef()); - remapped.AppendPathComponent(path); - new_path = remapped.GetPath(); - return true; + auto orig_style = FileSpec::GuessPathStyle(prefix).getValueOr( + llvm::sys::path::Style::native); + AppendPathComponents(remapped, path, orig_style); + return remapped; } - return false; + return {}; } bool PathMappingList::ReverseRemapPath(const FileSpec &file, FileSpec &fixed) const { @@ -190,56 +202,23 @@ bool PathMappingList::ReverseRemapPath(const FileSpec &file, FileSpec &fixed) co for (const auto &it : m_pairs) { if (!path_ref.consume_front(it.second.GetStringRef())) continue; - fixed.SetFile(it.first.GetStringRef(), FileSpec::Style::native); - fixed.AppendPathComponent(path_ref); + auto orig_file = it.first.GetStringRef(); + auto orig_style = FileSpec::GuessPathStyle(orig_file).getValueOr( + llvm::sys::path::Style::native); + fixed.SetFile(orig_file, orig_style); + AppendPathComponents(fixed, path_ref, orig_style); return true; } return false; } -bool PathMappingList::FindFile(const FileSpec &orig_spec, - FileSpec &new_spec) const { - if (m_pairs.empty()) - return false; - - std::string orig_path = orig_spec.GetPath(); - - if (orig_path.empty()) - return false; - - bool orig_is_relative = orig_spec.IsRelative(); - for (auto entry : m_pairs) { - llvm::StringRef orig_ref(orig_path); - llvm::StringRef prefix_ref = entry.first.GetStringRef(); - if (orig_ref.size() < prefix_ref.size()) - continue; - // We consider a relative prefix or one of just "." to - // mean "only apply to relative paths". - bool prefix_is_relative = false; - - if (prefix_ref == ".") { - prefix_is_relative = true; - // Remove the "." since it will have been removed from the - // FileSpec paths already. - prefix_ref = prefix_ref.drop_front(); - } else { - FileSpec prefix_spec(prefix_ref, FileSpec::Style::native); - prefix_is_relative = prefix_spec.IsRelative(); - } - if (prefix_is_relative != orig_is_relative) - continue; +llvm::Optional PathMappingList::FindFile(const FileSpec &orig_spec) const { + if (auto remapped = RemapPath(orig_spec.GetPath())) + if (FileSystem::Instance().Exists(*remapped)) + return remapped; - if (orig_ref.consume_front(prefix_ref)) { - new_spec.SetFile(entry.second.GetCString(), FileSpec::Style::native); - new_spec.AppendPathComponent(orig_ref); - if (FileSystem::Instance().Exists(new_spec)) - return true; - } - } - - new_spec.Clear(); - return false; + return {}; } bool PathMappingList::Replace(ConstString path, diff --git a/lldb/unittests/Target/PathMappingListTest.cpp b/lldb/unittests/Target/PathMappingListTest.cpp index 66fd97c17f62..90b6f1134a2b 100644 --- a/lldb/unittests/Target/PathMappingListTest.cpp +++ b/lldb/unittests/Target/PathMappingListTest.cpp @@ -6,9 +6,9 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/ArrayRef.h" #include "lldb/Target/PathMappingList.h" #include "lldb/Utility/FileSpec.h" +#include "llvm/ADT/ArrayRef.h" #include "gtest/gtest.h" #include @@ -19,6 +19,8 @@ struct Matches { FileSpec original; FileSpec remapped; Matches(const char *o, const char *r) : original(o), remapped(r) {} + Matches(const char *o, llvm::sys::path::Style style, const char *r) + : original(o, style), remapped(r) {} }; } // namespace @@ -112,3 +114,27 @@ TEST(PathMappingListTest, RemapRoot) { }; TestPathMappings(map, matches, fails); } + +#ifndef _WIN32 +TEST(PathMappingListTest, CrossPlatformTests) { + PathMappingList map; + map.Append(ConstString(R"(C:\old)"), ConstString("/new"), false); + Matches matches[] = { + {R"(C:\old)", llvm::sys::path::Style::windows, "/new"}, + {R"(C:\old\)", llvm::sys::path::Style::windows, "/new"}, + {R"(C:\old\foo\.)", llvm::sys::path::Style::windows, "/new/foo"}, + {R"(C:\old\foo.c)", llvm::sys::path::Style::windows, "/new/foo.c"}, + {R"(C:\old\foo.c\.)", llvm::sys::path::Style::windows, "/new/foo.c"}, + {R"(C:\old\.\foo.c)", llvm::sys::path::Style::windows, "/new/foo.c"}, + }; + ConstString fails[] = { + ConstString("/foo"), + ConstString("/"), + ConstString("foo.c"), + ConstString("./foo.c"), + ConstString("../foo.c"), + ConstString("../bar/foo.c"), + }; + TestPathMappings(map, matches, fails); +} +#endif diff --git a/llvm/cmake/config-ix.cmake b/llvm/cmake/config-ix.cmake index 818fafbce148..e9224959dd1b 100644 --- a/llvm/cmake/config-ix.cmake +++ b/llvm/cmake/config-ix.cmake @@ -210,6 +210,7 @@ endif() # Determine whether we can register EH tables. check_symbol_exists(__register_frame "${CMAKE_CURRENT_LIST_DIR}/unwind.h" HAVE_REGISTER_FRAME) check_symbol_exists(__deregister_frame "${CMAKE_CURRENT_LIST_DIR}/unwind.h" HAVE_DEREGISTER_FRAME) +check_symbol_exists(__unw_add_dynamic_fde "${CMAKE_CURRENT_LIST_DIR}/unwind.h" HAVE_UNW_ADD_DYNAMIC_FDE) check_symbol_exists(_Unwind_Backtrace "unwind.h" HAVE__UNWIND_BACKTRACE) check_symbol_exists(getpagesize unistd.h HAVE_GETPAGESIZE) diff --git a/llvm/cmake/unwind.h b/llvm/cmake/unwind.h index e7f53465f9ce..52243f2af787 100644 --- a/llvm/cmake/unwind.h +++ b/llvm/cmake/unwind.h @@ -5,3 +5,4 @@ // exist in the runtime. extern void __register_frame(const void *fde); // NOLINT extern void __deregister_frame(const void *fde); // NOLINT +extern void __unw_add_dynamic_fde(); // NOLINT diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index cd3bb0de4f34..eaabf8a0192a 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -16300,11 +16300,12 @@ Overview: The '``llvm.matrix.column.major.load.*``' intrinsics load a `` x `` matrix using a stride of ``%Stride`` to compute the start address of the -different columns. This allows for convenient loading of sub matrixes. If -```` is true, the intrinsic is considered a :ref:`volatile memory -access `. The result matrix is returned in the result vector. If the -``%Ptr`` argument is known to be aligned to some boundary, this can be -specified as an attribute on the argument. +different columns. The offset is computed using ``%Stride``'s bitwidth. This +allows for convenient loading of sub matrixes. If ```` is true, the +intrinsic is considered a :ref:`volatile memory access `. The result +matrix is returned in the result vector. If the ``%Ptr`` argument is known to +be aligned to some boundary, this can be specified as an attribute on the +argument. Arguments: """""""""" @@ -16339,7 +16340,8 @@ Overview: The '``llvm.matrix.column.major.store.*``' intrinsics store the `` x `` matrix in ``%In`` to memory using a stride of ``%Stride`` between -columns. If ```` is true, the intrinsic is considered a +columns. The offset is computed using ``%Stride``'s bitwidth. If +```` is true, the intrinsic is considered a :ref:`volatile memory access `. If the ``%Ptr`` argument is known to be aligned to some boundary, this can be diff --git a/llvm/include/llvm/Config/config.h.cmake b/llvm/include/llvm/Config/config.h.cmake index 6664ad335584..d54ea9a40c69 100644 --- a/llvm/include/llvm/Config/config.h.cmake +++ b/llvm/include/llvm/Config/config.h.cmake @@ -64,6 +64,9 @@ /* Define to 1 if we can deregister EH frames on this platform. */ #cmakedefine HAVE_DEREGISTER_FRAME ${HAVE_DEREGISTER_FRAME} +/* Define if __unw_add_dynamic_fde() is available on this platform. */ +#cmakedefine HAVE_UNW_ADD_DYNAMIC_FDE ${HAVE_UNW_ADD_DYNAMIC_FDE} + /* Define to 1 if you have the header file. */ #cmakedefine HAVE_ERRNO_H ${HAVE_ERRNO_H} diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td index 21307ed1bd91..2ea4621415b5 100644 --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -1560,7 +1560,7 @@ def int_matrix_multiply def int_matrix_column_major_load : DefaultAttrsIntrinsic<[llvm_anyvector_ty], - [LLVMPointerToElt<0>, llvm_i64_ty, llvm_i1_ty, + [LLVMPointerToElt<0>, llvm_anyint_ty, llvm_i1_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoSync, IntrWillReturn, IntrArgMemOnly, IntrReadMem, NoCapture>, ImmArg>, ImmArg>, @@ -1569,7 +1569,7 @@ def int_matrix_column_major_load def int_matrix_column_major_store : DefaultAttrsIntrinsic<[], [llvm_anyvector_ty, LLVMPointerToElt<0>, - llvm_i64_ty, llvm_i1_ty, llvm_i32_ty, llvm_i32_ty], + llvm_anyint_ty, llvm_i1_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoSync, IntrWillReturn, IntrArgMemOnly, IntrWriteMem, WriteOnly>, NoCapture>, ImmArg>, ImmArg>, ImmArg>]>; diff --git a/llvm/include/llvm/IR/MatrixBuilder.h b/llvm/include/llvm/IR/MatrixBuilder.h index 084b1d49569e..017c8c5e06b9 100644 --- a/llvm/include/llvm/IR/MatrixBuilder.h +++ b/llvm/include/llvm/IR/MatrixBuilder.h @@ -74,7 +74,7 @@ public: Value *Ops[] = {DataPtr, Stride, B.getInt1(IsVolatile), B.getInt32(Rows), B.getInt32(Columns)}; - Type *OverloadedTypes[] = {RetType}; + Type *OverloadedTypes[] = {RetType, Stride->getType()}; Function *TheFn = Intrinsic::getDeclaration( getModule(), Intrinsic::matrix_column_major_load, OverloadedTypes); @@ -97,7 +97,7 @@ public: Value *Ops[] = {Matrix, Ptr, Stride, B.getInt1(IsVolatile), B.getInt32(Rows), B.getInt32(Columns)}; - Type *OverloadedTypes[] = {Matrix->getType()}; + Type *OverloadedTypes[] = {Matrix->getType(), Stride->getType()}; Function *TheFn = Intrinsic::getDeclaration( getModule(), Intrinsic::matrix_column_major_store, OverloadedTypes); diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp index b2bc75c19709..1cbef984eab7 100644 --- a/llvm/lib/CodeGen/CodeGenPrepare.cpp +++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp @@ -633,12 +633,8 @@ void CodeGenPrepare::removeAllAssertingVHReferences(Value *V) { return; auto &GEPVector = VecI->second; - const auto &I = - llvm::find_if(GEPVector, [=](auto &Elt) { return Elt.first == GEP; }); - if (I == GEPVector.end()) - return; + llvm::erase_if(GEPVector, [=](auto &Elt) { return Elt.first == GEP; }); - GEPVector.erase(I); if (GEPVector.empty()) LargeOffsetGEPMap.erase(VecI); } diff --git a/llvm/lib/CodeGen/LiveDebugValues/VarLocBasedImpl.cpp b/llvm/lib/CodeGen/LiveDebugValues/VarLocBasedImpl.cpp index e2daa46fe6b9..78f2c642f96a 100644 --- a/llvm/lib/CodeGen/LiveDebugValues/VarLocBasedImpl.cpp +++ b/llvm/lib/CodeGen/LiveDebugValues/VarLocBasedImpl.cpp @@ -451,8 +451,9 @@ private: // on top of. FIXME: spill locations created before this pass runs // are not recognized, and not handled here. auto *TRI = MF.getSubtarget().getRegisterInfo(); + auto Deref = Indirect ? DIExpression::DerefAfter : 0; auto *SpillExpr = TRI->prependOffsetExpression( - DIExpr, DIExpression::ApplyOffset, Loc.SpillLocation.SpillOffset); + DIExpr, DIExpression::ApplyOffset | Deref, Loc.SpillLocation.SpillOffset); unsigned Base = Loc.SpillLocation.SpillBase; return BuildMI(MF, DbgLoc, IID, true, Base, Var, SpillExpr); } diff --git a/llvm/lib/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.cpp b/llvm/lib/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.cpp index aff7296cb6e3..caa91d8c4866 100644 --- a/llvm/lib/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.cpp +++ b/llvm/lib/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.cpp @@ -86,11 +86,11 @@ static Error deregisterFrameWrapper(const void *P) { } #endif -#ifdef __APPLE__ +#ifdef HAVE_UNW_ADD_DYNAMIC_FDE template -Error walkAppleEHFrameSection(const char *const SectionStart, - size_t SectionSize, HandleFDEFn HandleFDE) { +Error walkLibunwindEHFrameSection(const char *const SectionStart, + size_t SectionSize, HandleFDEFn HandleFDE) { const char *CurCFIRecord = SectionStart; const char *End = SectionStart + SectionSize; uint64_t Size = *reinterpret_cast(CurCFIRecord); @@ -124,16 +124,19 @@ Error walkAppleEHFrameSection(const char *const SectionStart, return Error::success(); } -#endif // __APPLE__ +#endif // HAVE_UNW_ADD_DYNAMIC_FDE Error registerEHFrameSection(const void *EHFrameSectionAddr, size_t EHFrameSectionSize) { -#ifdef __APPLE__ - // On Darwin __register_frame has to be called for each FDE entry. - return walkAppleEHFrameSection(static_cast(EHFrameSectionAddr), - EHFrameSectionSize, registerFrameWrapper); + /* libgcc and libunwind __register_frame behave differently. We use the + * presence of __unw_add_dynamic_fde to detect libunwind. */ +#ifdef HAVE_UNW_ADD_DYNAMIC_FDE + // With libunwind, __register_frame has to be called for each FDE entry. + return walkLibunwindEHFrameSection( + static_cast(EHFrameSectionAddr), EHFrameSectionSize, + registerFrameWrapper); #else - // On Linux __register_frame takes a single argument: + // With libgcc, __register_frame takes a single argument: // a pointer to the start of the .eh_frame section. // How can it find the end? Because crtendS.o is linked @@ -144,9 +147,10 @@ Error registerEHFrameSection(const void *EHFrameSectionAddr, Error deregisterEHFrameSection(const void *EHFrameSectionAddr, size_t EHFrameSectionSize) { -#ifdef __APPLE__ - return walkAppleEHFrameSection(static_cast(EHFrameSectionAddr), - EHFrameSectionSize, deregisterFrameWrapper); +#ifdef HAVE_UNW_ADD_DYNAMIC_FDE + return walkLibunwindEHFrameSection( + static_cast(EHFrameSectionAddr), EHFrameSectionSize, + deregisterFrameWrapper); #else return deregisterFrameWrapper(EHFrameSectionAddr); #endif diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp index b6ccd02405c1..252e20c3c38c 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp @@ -67,7 +67,9 @@ static void __deregister_frame(void *p) { } #endif -#ifdef __APPLE__ +/* libgcc and libunwind __register_frame behave differently. We use the presence + * of __unw_add_dynamic_fde to detect libunwind. */ +#ifdef HAVE_UNW_ADD_DYNAMIC_FDE static const char *processFDE(const char *Entry, bool isDeregister) { const char *P = Entry; diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp index 1f67aecb57e9..008aaf83c41d 100644 --- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp +++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp @@ -540,11 +540,12 @@ IRBuilder<>::InsertPoint OpenMPIRBuilder::createParallel( AllocaInst *PrivTIDAddr = Builder.CreateAlloca(Int32, nullptr, "tid.addr.local"); - Instruction *PrivTID = Builder.CreateLoad(PrivTIDAddr, "tid"); + Instruction *PrivTID = Builder.CreateLoad(Int32, PrivTIDAddr, "tid"); // Add some fake uses for OpenMP provided arguments. - ToBeDeleted.push_back(Builder.CreateLoad(TIDAddr, "tid.addr.use")); - Instruction *ZeroAddrUse = Builder.CreateLoad(ZeroAddr, "zero.addr.use"); + ToBeDeleted.push_back(Builder.CreateLoad(Int32, TIDAddr, "tid.addr.use")); + Instruction *ZeroAddrUse = Builder.CreateLoad(Int32, ZeroAddr, + "zero.addr.use"); ToBeDeleted.push_back(ZeroAddrUse); // ThenBB @@ -625,7 +626,7 @@ IRBuilder<>::InsertPoint OpenMPIRBuilder::createParallel( // Initialize the local TID stack location with the argument value. Builder.SetInsertPoint(PrivTID); Function::arg_iterator OutlinedAI = OutlinedFn.arg_begin(); - Builder.CreateStore(Builder.CreateLoad(OutlinedAI), PrivTIDAddr); + Builder.CreateStore(Builder.CreateLoad(Int32, OutlinedAI), PrivTIDAddr); // If no "if" clause was present we do not need the call created during // outlining, otherwise we reuse it in the serialized parallel region. @@ -743,7 +744,7 @@ IRBuilder<>::InsertPoint OpenMPIRBuilder::createParallel( // Load back next to allocations in the to-be-outlined region. Builder.restoreIP(InnerAllocaIP); - Inner = Builder.CreateLoad(Ptr); + Inner = Builder.CreateLoad(V.getType(), Ptr); } Value *ReplacementValue = nullptr; @@ -1129,8 +1130,8 @@ CanonicalLoopInfo *OpenMPIRBuilder::createStaticWorkshareLoop( Builder.CreateCall(StaticInit, {SrcLoc, ThreadNum, SchedulingType, PLastIter, PLowerBound, PUpperBound, PStride, One, Chunk}); - Value *LowerBound = Builder.CreateLoad(PLowerBound); - Value *InclusiveUpperBound = Builder.CreateLoad(PUpperBound); + Value *LowerBound = Builder.CreateLoad(IVTy, PLowerBound); + Value *InclusiveUpperBound = Builder.CreateLoad(IVTy, PUpperBound); Value *TripCountMinusOne = Builder.CreateSub(InclusiveUpperBound, LowerBound); Value *TripCount = Builder.CreateAdd(TripCountMinusOne, One); setCanonicalLoopTripCount(CLI, TripCount); @@ -1421,7 +1422,7 @@ OpenMPIRBuilder::createCopyPrivate(const LocationDescription &Loc, Value *Ident = getOrCreateIdent(SrcLocStr); Value *ThreadId = getOrCreateThreadID(Ident); - llvm::Value *DidItLD = Builder.CreateLoad(DidIt); + llvm::Value *DidItLD = Builder.CreateLoad(Builder.getInt32Ty(), DidIt); Value *Args[] = {Ident, ThreadId, BufSize, CpyBuf, CpyFn, DidItLD}; diff --git a/llvm/lib/Target/AMDGPU/AMDGPULateCodeGenPrepare.cpp b/llvm/lib/Target/AMDGPU/AMDGPULateCodeGenPrepare.cpp index 8aea33cf289d..e4aa6de10f2d 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPULateCodeGenPrepare.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPULateCodeGenPrepare.cpp @@ -168,7 +168,7 @@ bool AMDGPULateCodeGenPrepare::visitLoadInst(LoadInst &LI) { IRB.CreateConstGEP1_64(IRB.CreateBitCast(Base, Int8PtrTy), Offset - Adjust), Int32PtrTy); - LoadInst *NewLd = IRB.CreateAlignedLoad(NewPtr, Align(4)); + LoadInst *NewLd = IRB.CreateAlignedLoad(IRB.getInt32Ty(), NewPtr, Align(4)); NewLd->copyMetadata(LI); NewLd->setMetadata(LLVMContext::MD_range, nullptr); diff --git a/llvm/lib/Transforms/Scalar/LowerMatrixIntrinsics.cpp b/llvm/lib/Transforms/Scalar/LowerMatrixIntrinsics.cpp index 8e251ca940a3..9ae4fa28ed84 100644 --- a/llvm/lib/Transforms/Scalar/LowerMatrixIntrinsics.cpp +++ b/llvm/lib/Transforms/Scalar/LowerMatrixIntrinsics.cpp @@ -797,15 +797,17 @@ public: /// vectors. MatrixTy loadMatrix(Type *Ty, Value *Ptr, MaybeAlign MAlign, Value *Stride, bool IsVolatile, ShapeInfo Shape, IRBuilder<> &Builder) { - auto VType = cast(Ty); - Value *EltPtr = createElementPtr(Ptr, VType->getElementType(), Builder); + auto *VType = cast(Ty); + Type *EltTy = VType->getElementType(); + Type *VecTy = FixedVectorType::get(EltTy, Shape.getStride()); + Value *EltPtr = createElementPtr(Ptr, EltTy, Builder); MatrixTy Result; for (unsigned I = 0, E = Shape.getNumVectors(); I < E; ++I) { - Value *GEP = computeVectorAddr(EltPtr, Builder.getInt64(I), Stride, - Shape.getStride(), VType->getElementType(), - Builder); + Value *GEP = computeVectorAddr( + EltPtr, Builder.getIntN(Stride->getType()->getScalarSizeInBits(), I), + Stride, Shape.getStride(), EltTy, Builder); Value *Vector = Builder.CreateAlignedLoad( - GEP, getAlignForIndex(I, Stride, VType->getElementType(), MAlign), + VecTy, GEP, getAlignForIndex(I, Stride, EltTy, MAlign), IsVolatile, "col.load"); Result.addVector(Vector); @@ -892,9 +894,11 @@ public: auto VType = cast(Ty); Value *EltPtr = createElementPtr(Ptr, VType->getElementType(), Builder); for (auto Vec : enumerate(StoreVal.vectors())) { - Value *GEP = computeVectorAddr(EltPtr, Builder.getInt64(Vec.index()), - Stride, StoreVal.getStride(), - VType->getElementType(), Builder); + Value *GEP = computeVectorAddr( + EltPtr, + Builder.getIntN(Stride->getType()->getScalarSizeInBits(), + Vec.index()), + Stride, StoreVal.getStride(), VType->getElementType(), Builder); Builder.CreateAlignedStore(Vec.value(), GEP, getAlignForIndex(Vec.index(), Stride, VType->getElementType(), diff --git a/llvm/lib/Transforms/Utils/AMDGPUEmitPrintf.cpp b/llvm/lib/Transforms/Utils/AMDGPUEmitPrintf.cpp index ccdcf7cbce38..9210096c4f3e 100644 --- a/llvm/lib/Transforms/Utils/AMDGPUEmitPrintf.cpp +++ b/llvm/lib/Transforms/Utils/AMDGPUEmitPrintf.cpp @@ -138,7 +138,7 @@ static Value *getStrlenWithNull(IRBuilder<> &Builder, Value *Str) { PtrPhi->addIncoming(PtrNext, While); // Condition for the while loop. - auto Data = Builder.CreateLoad(PtrPhi); + auto Data = Builder.CreateLoad(Builder.getInt8Ty(), PtrPhi); auto Cmp = Builder.CreateICmpEQ(Data, CharZero); Builder.CreateCondBr(Cmp, WhileDone, While); diff --git a/llvm/test/DebugInfo/MIR/X86/live-debug-values-restore.mir b/llvm/test/DebugInfo/MIR/X86/live-debug-values-restore.mir index ded90d4a6815..9a0785053f0f 100644 --- a/llvm/test/DebugInfo/MIR/X86/live-debug-values-restore.mir +++ b/llvm/test/DebugInfo/MIR/X86/live-debug-values-restore.mir @@ -641,7 +641,7 @@ body: | # CHECK-LABEL: bb.0.entry: # CHECK: DBG_VALUE $rdi, 0, ![[TVAR]], !DIExpression() # CHECK-LABEL: bb.1.if.then: -# CHECK: DBG_VALUE $rsp, 0, ![[TVAR]], !DIExpression(DW_OP_constu, 8, DW_OP_minus) +# CHECK: DBG_VALUE $rsp, 0, ![[TVAR]], !DIExpression(DW_OP_constu, 8, DW_OP_minus, DW_OP_deref) # CHECK: INLINEASM # CHECK: DBG_VALUE ${{[a-zA-Z0-9]+}}, 0, ![[TVAR]], !DIExpression() # CHECK-LABEL: bb.2.if.end diff --git a/llvm/test/Transforms/LowerMatrixIntrinsics/strided-load-double.ll b/llvm/test/Transforms/LowerMatrixIntrinsics/strided-load-double.ll index aaf1b114cc30..61e95effc0d7 100644 --- a/llvm/test/Transforms/LowerMatrixIntrinsics/strided-load-double.ll +++ b/llvm/test/Transforms/LowerMatrixIntrinsics/strided-load-double.ll @@ -23,11 +23,11 @@ define <9 x double> @strided_load_3x3(double* %in, i64 %stride) { ; CHECK-NEXT: ret <9 x double> [[TMP2]] ; entry: - %load = call <9 x double> @llvm.matrix.column.major.load(double* %in, i64 %stride, i1 false, i32 3, i32 3) + %load = call <9 x double> @llvm.matrix.column.major.load.v9f64.i64(double* %in, i64 %stride, i1 false, i32 3, i32 3) ret <9 x double> %load } -declare <9 x double> @llvm.matrix.column.major.load(double*, i64, i1, i32, i32) +declare <9 x double> @llvm.matrix.column.major.load.v9f64.i64(double*, i64, i1, i32, i32) define <9 x double> @strided_load_9x1(double* %in, i64 %stride) { ; CHECK-LABEL: @strided_load_9x1( @@ -39,12 +39,11 @@ define <9 x double> @strided_load_9x1(double* %in, i64 %stride) { ; CHECK-NEXT: ret <9 x double> [[COL_LOAD]] ; entry: - %load = call <9 x double> @llvm.matrix.column.major.load(double* %in, i64 %stride, i1 false, i32 9, i32 1) + %load = call <9 x double> @llvm.matrix.column.major.load.v9f64.i64(double* %in, i64 %stride, i1 false, i32 9, i32 1) ret <9 x double> %load } -declare <8 x double> @llvm.matrix.column.major.load.v8f64(double*, i64, i1, i32, i32) -; CHECK: declare <8 x double> @llvm.matrix.column.major.load.v8f64(double* nocapture, i64, i1 immarg, i32 immarg, i32 immarg) [[READONLY:#[0-9]]] +declare <8 x double> @llvm.matrix.column.major.load.v8f64.i64(double*, i64, i1, i32, i32) define <8 x double> @strided_load_4x2(double* %in, i64 %stride) { ; CHECK-LABEL: @strided_load_4x2( @@ -61,9 +60,27 @@ define <8 x double> @strided_load_4x2(double* %in, i64 %stride) { ; CHECK-NEXT: ret <8 x double> [[TMP0]] ; entry: - %load = call <8 x double> @llvm.matrix.column.major.load.v8f64(double* %in, i64 %stride, i1 false, i32 4, i32 2) + %load = call <8 x double> @llvm.matrix.column.major.load.v8f64.i64(double* %in, i64 %stride, i1 false, i32 4, i32 2) ret <8 x double> %load } -; CHECK: declare <9 x double> @llvm.matrix.column.major.load.v9f64(double* nocapture, i64, i1 immarg, i32 immarg, i32 immarg) [[READONLY]] -; CHECK: attributes [[READONLY]] = { argmemonly nofree nosync nounwind readonly willreturn } +declare <8 x double> @llvm.matrix.column.major.load.v8f64.i32(double*, i32, i1, i32, i32) + +define <8 x double> @strided_load_4x2_stride_i32(double* %in, i32 %stride) { +; CHECK-LABEL: @strided_load_4x2_stride_i32( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[VEC_START:%.*]] = mul i32 0, [[STRIDE:%.*]] +; CHECK-NEXT: [[VEC_GEP:%.*]] = getelementptr double, double* [[IN:%.*]], i32 [[VEC_START]] +; CHECK-NEXT: [[VEC_CAST:%.*]] = bitcast double* [[VEC_GEP]] to <4 x double>* +; CHECK-NEXT: [[COL_LOAD:%.*]] = load <4 x double>, <4 x double>* [[VEC_CAST]], align 8 +; CHECK-NEXT: [[VEC_START1:%.*]] = mul i32 1, [[STRIDE]] +; CHECK-NEXT: [[VEC_GEP2:%.*]] = getelementptr double, double* [[IN]], i32 [[VEC_START1]] +; CHECK-NEXT: [[VEC_CAST3:%.*]] = bitcast double* [[VEC_GEP2]] to <4 x double>* +; CHECK-NEXT: [[COL_LOAD4:%.*]] = load <4 x double>, <4 x double>* [[VEC_CAST3]], align 8 +; CHECK-NEXT: [[TMP0:%.*]] = shufflevector <4 x double> [[COL_LOAD]], <4 x double> [[COL_LOAD4]], <8 x i32> +; CHECK-NEXT: ret <8 x double> [[TMP0]] +; +entry: + %load = call <8 x double> @llvm.matrix.column.major.load.v8f64.i32(double* %in, i32 %stride, i1 false, i32 4, i32 2) + ret <8 x double> %load +} diff --git a/llvm/test/Transforms/LowerMatrixIntrinsics/strided-store-double.ll b/llvm/test/Transforms/LowerMatrixIntrinsics/strided-store-double.ll index 817f989ba550..5dd1166f1c22 100644 --- a/llvm/test/Transforms/LowerMatrixIntrinsics/strided-store-double.ll +++ b/llvm/test/Transforms/LowerMatrixIntrinsics/strided-store-double.ll @@ -13,7 +13,7 @@ define void @strided_store_3x2(<6 x double> %in, double* %out) { ; CHECK-NEXT: store <3 x double> [[SPLIT1]], <3 x double>* [[VEC_CAST2]], align 8 ; CHECK-NEXT: ret void ; - call void @llvm.matrix.column.major.store.v6f64(<6 x double> %in, double* %out, i64 5, i1 false, i32 3, i32 2) + call void @llvm.matrix.column.major.store.v6f64.i64(<6 x double> %in, double* %out, i64 5, i1 false, i32 3, i32 2) ret void } @@ -31,7 +31,25 @@ define void @strided_store_3x2_nonconst_stride(<6 x double> %in, i64 %stride, do ; CHECK-NEXT: store <3 x double> [[SPLIT1]], <3 x double>* [[VEC_CAST4]], align 8 ; CHECK-NEXT: ret void ; - call void @llvm.matrix.column.major.store.v6f64(<6 x double> %in, double* %out, i64 %stride, i1 false, i32 3, i32 2) + call void @llvm.matrix.column.major.store.v6f64.i64(<6 x double> %in, double* %out, i64 %stride, i1 false, i32 3, i32 2) + ret void +} + +define void @strided_store_3x2_nonconst_i32_stride(<6 x double> %in, i32 %stride, double* %out) { +; CHECK-LABEL: @strided_store_3x2_nonconst_i32_stride( +; CHECK-NEXT: [[SPLIT:%.*]] = shufflevector <6 x double> [[IN:%.*]], <6 x double> poison, <3 x i32> +; CHECK-NEXT: [[SPLIT1:%.*]] = shufflevector <6 x double> [[IN]], <6 x double> poison, <3 x i32> +; CHECK-NEXT: [[VEC_START:%.*]] = mul i32 0, [[STRIDE:%.*]] +; CHECK-NEXT: [[VEC_GEP:%.*]] = getelementptr double, double* [[OUT:%.*]], i32 [[VEC_START]] +; CHECK-NEXT: [[VEC_CAST:%.*]] = bitcast double* [[VEC_GEP]] to <3 x double>* +; CHECK-NEXT: store <3 x double> [[SPLIT]], <3 x double>* [[VEC_CAST]], align 8 +; CHECK-NEXT: [[VEC_START2:%.*]] = mul i32 1, [[STRIDE]] +; CHECK-NEXT: [[VEC_GEP3:%.*]] = getelementptr double, double* [[OUT]], i32 [[VEC_START2]] +; CHECK-NEXT: [[VEC_CAST4:%.*]] = bitcast double* [[VEC_GEP3]] to <3 x double>* +; CHECK-NEXT: store <3 x double> [[SPLIT1]], <3 x double>* [[VEC_CAST4]], align 8 +; CHECK-NEXT: ret void +; + call void @llvm.matrix.column.major.store.v6f64.i32(<6 x double> %in, double* %out, i32 %stride, i1 false, i32 3, i32 2) ret void } @@ -58,13 +76,14 @@ define void @strided_store_2x3(<10 x double> %in, double* %out) { ; CHECK-NEXT: store <2 x double> [[SPLIT4]], <2 x double>* [[VEC_CAST11]], align 8 ; CHECK-NEXT: ret void ; - call void @llvm.matrix.column.major.store.v10f64(<10 x double> %in, double* %out, i64 4, i1 false, i32 2, i32 5) + call void @llvm.matrix.column.major.store.v10f64.i64(<10 x double> %in, double* %out, i64 4, i1 false, i32 2, i32 5) ret void } -declare void @llvm.matrix.column.major.store.v6f64(<6 x double>, double*, i64, i1, i32, i32) -declare void @llvm.matrix.column.major.store.v10f64(<10 x double>, double*, i64, i1, i32, i32) +declare void @llvm.matrix.column.major.store.v6f64.i64(<6 x double>, double*, i64, i1, i32, i32) +declare void @llvm.matrix.column.major.store.v6f64.i32(<6 x double>, double*, i32, i1, i32, i32) +declare void @llvm.matrix.column.major.store.v10f64.i64(<10 x double>, double*, i64, i1, i32, i32) -; CHECK: declare void @llvm.matrix.column.major.store.v6f64(<6 x double>, double* nocapture writeonly, i64, i1 immarg, i32 immarg, i32 immarg) #0 -; CHECK: declare void @llvm.matrix.column.major.store.v10f64(<10 x double>, double* nocapture writeonly, i64, i1 immarg, i32 immarg, i32 immarg) #0 +; CHECK: declare void @llvm.matrix.column.major.store.v6f64.i64(<6 x double>, double* nocapture writeonly, i64, i1 immarg, i32 immarg, i32 immarg) #0 +; CHECK: declare void @llvm.matrix.column.major.store.v10f64.i64(<10 x double>, double* nocapture writeonly, i64, i1 immarg, i32 immarg, i32 immarg) #0 ; CHECK: attributes #0 = { argmemonly nofree nosync nounwind willreturn writeonly } diff --git a/llvm/test/Verifier/matrix-intrinsics.ll b/llvm/test/Verifier/matrix-intrinsics.ll index 4194cfb434f2..6f90fcb5ce92 100644 --- a/llvm/test/Verifier/matrix-intrinsics.ll +++ b/llvm/test/Verifier/matrix-intrinsics.ll @@ -39,11 +39,11 @@ define <4 x float> @column.major_load(float* %m, float* %n, i32 %arg) { ; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector! ; CHECK-NEXT: immarg operand has non-immediate parameter ; CHECK-NEXT: i32 %arg -; CHECK-NEXT: %result.3 = call <6 x float> @llvm.matrix.column.major.load.v6f32(float* %n, i64 2, i1 true, i32 3, i32 %arg) - %result.0 = call <4 x float> @llvm.matrix.column.major.load.v4f32(float* %m, i64 0, i1 false, i32 0, i32 0) - %result.1 = call <4 x float> @llvm.matrix.column.major.load.v4f32(float* %m, i64 2, i1 false, i32 1, i32 2) - %result.2 = call <6 x float> @llvm.matrix.column.major.load.v6f32(float* %n, i64 2, i1 true, i32 3, i32 3) - %result.3 = call <6 x float> @llvm.matrix.column.major.load.v6f32(float* %n, i64 2, i1 true, i32 3, i32 %arg) +; CHECK-NEXT: %result.3 = call <6 x float> @llvm.matrix.column.major.load.v6f32.i64(float* %n, i64 2, i1 true, i32 3, i32 %arg) + %result.0 = call <4 x float> @llvm.matrix.column.major.load.v4f32.i64(float* %m, i64 0, i1 false, i32 0, i32 0) + %result.1 = call <4 x float> @llvm.matrix.column.major.load.v4f32.i64(float* %m, i64 2, i1 false, i32 1, i32 2) + %result.2 = call <6 x float> @llvm.matrix.column.major.load.v6f32.i64(float* %n, i64 2, i1 true, i32 3, i32 3) + %result.3 = call <6 x float> @llvm.matrix.column.major.load.v6f32.i64(float* %n, i64 2, i1 true, i32 3, i32 %arg) ret <4 x float> %result.1 } @@ -52,10 +52,10 @@ define void @column.major_store(float* %m, float* %n, i64 %arg) { ; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector! ; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector! ; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector! - call void @llvm.matrix.column.major.store.v4f32(<4 x float> zeroinitializer, float* %m, i64 0, i1 false, i32 0, i32 0) - call void @llvm.matrix.column.major.store.v4f32(<4 x float> zeroinitializer, float* %m, i64 2, i1 false, i32 1, i32 2) - call void @llvm.matrix.column.major.store.v6f32(<6 x float> zeroinitializer, float* %n, i64 2, i1 false, i32 3, i32 3) - call void @llvm.matrix.column.major.store.v6f32(<6 x float> zeroinitializer, float* %n, i64 %arg, i1 false, i32 3, i32 3) + call void @llvm.matrix.column.major.store.v4f32.i64(<4 x float> zeroinitializer, float* %m, i64 0, i1 false, i32 0, i32 0) + call void @llvm.matrix.column.major.store.v4f32.i64(<4 x float> zeroinitializer, float* %m, i64 2, i1 false, i32 1, i32 2) + call void @llvm.matrix.column.major.store.v6f32.i64(<6 x float> zeroinitializer, float* %n, i64 2, i1 false, i32 3, i32 3) + call void @llvm.matrix.column.major.store.v6f32.i64(<6 x float> zeroinitializer, float* %n, i64 %arg, i1 false, i32 3, i32 3) ret void } @@ -94,18 +94,18 @@ define <4 x float> @column.major_load_mixed_types(i32* %m, float* %n, i32 %arg) ; CHECK-NEXT: Intrinsic has incorrect argument type! ; CHECK-NEXT: <4 x float> (i32*, i64, i1, i32, i32)* @llvm.matrix.column.major.load.v4f32.pi32 ; CHECK-NEXT: Intrinsic has incorrect argument type! -; CHECK-NEXT: <4 x i32> (float*, i64, i1, i32, i32)* @llvm.matrix.column.major.load.v4i32 +; CHECK-NEXT: <4 x i32> (float*, i64, i1, i32, i32)* @llvm.matrix.column.major.load.v4i32.i64 ; %result.0 = call <4 x float> @llvm.matrix.column.major.load.v4f32.pi32(i32* %m, i64 2, i1 false, i32 2, i32 2) - %result.1 = call <4 x i32> @llvm.matrix.column.major.load.v4i32(float* %n, i64 2, i1 false, i32 2, i32 2) + %result.1 = call <4 x i32> @llvm.matrix.column.major.load.v4i32.i64(float* %n, i64 2, i1 false, i32 2, i32 2) ret <4 x float> %result.0 } define void @column.major_store_mixed_types(float* %m, i32* %n, i64 %arg) { ; -; CHECK-NEXT: Intrinsic has incorrect argument type! +; CHECK-NEXT: Intrinsic has incorrect argument type! ; CHECK-NEXT: void (<4 x i32>, float*, i64, i1, i32, i32)* @llvm.matrix.column.major.store.v4i32.vi32 -; CHECK-NEXT: Intrinsic has incorrect argument type! +; CHECK-NEXT: Intrinsic has incorrect argument type! ; CHECK-NEXT: void (<4 x float>, i32*, i64, i1, i32, i32)* @llvm.matrix.column.major.store.v4f32.pi32 ; call void @llvm.matrix.column.major.store.v4i32.vi32(<4 x i32> zeroinitializer, float* %m, i64 2, i1 false, i32 2, i32 2) @@ -125,28 +125,28 @@ define void @column.major_store_non_int_float_type(<4 x float>* %m, <4 x float>* define <4 x float> @column.major_load_stride_too_small(float* %m, i32 %arg) { ; ; CHECK-NEXT: Stride must be greater or equal than the number of rows! -; CHECK-NEXT: <4 x float> (float*, i64, i1, i32, i32)* @llvm.matrix.column.major.load.v4f32 +; CHECK-NEXT: <4 x float> (float*, i64, i1, i32, i32)* @llvm.matrix.column.major.load.v4f32.i64 ; - %result.1 = call <4 x float> @llvm.matrix.column.major.load.v4f32(float* %m, i64 1, i1 false, i32 2, i32 2) + %result.1 = call <4 x float> @llvm.matrix.column.major.load.v4f32.i64(float* %m, i64 1, i1 false, i32 2, i32 2) ret <4 x float> %result.1 } define void @column.major_store_stride_too_small(float* %m, i64 %arg) { ; ; CHECK-NEXT: Stride must be greater or equal than the number of rows! -; CHECK-NEXT: void (<4 x float>, float*, i64, i1, i32, i32)* @llvm.matrix.column.major.store.v4f32 +; CHECK-NEXT: void (<4 x float>, float*, i64, i1, i32, i32)* @llvm.matrix.column.major.store.v4f32.i64 ; - call void @llvm.matrix.column.major.store.v4f32(<4 x float> zeroinitializer, float* %m, i64 1, i1 false, i32 2, i32 2) + call void @llvm.matrix.column.major.store.v4f32.i64(<4 x float> zeroinitializer, float* %m, i64 1, i1 false, i32 2, i32 2) ret void } -declare <4 x i32> @llvm.matrix.column.major.load.v4i32(float*, i64, i1, i32, i32) +declare <4 x i32> @llvm.matrix.column.major.load.v4i32.i64(float*, i64, i1, i32, i32) declare <4 x float> @llvm.matrix.column.major.load.v4f32.pi32(i32*, i64, i1, i32, i32) -declare <4 x float> @llvm.matrix.column.major.load.v4f32(float*, i64, i1, i32, i32) -declare <6 x float> @llvm.matrix.column.major.load.v6f32(float*, i64, i1, i32, i32) +declare <4 x float> @llvm.matrix.column.major.load.v4f32.i64(float*, i64, i1, i32, i32) +declare <6 x float> @llvm.matrix.column.major.load.v6f32.i64(float*, i64, i1, i32, i32) -declare void @llvm.matrix.column.major.store.v4f32(<4 x float>, float*, i64, i1, i32, i32) -declare void @llvm.matrix.column.major.store.v6f32(<6 x float>, float*, i64, i1, i32, i32) +declare void @llvm.matrix.column.major.store.v4f32.i64(<4 x float>, float*, i64, i1, i32, i32) +declare void @llvm.matrix.column.major.store.v6f32.i64(<6 x float>, float*, i64, i1, i32, i32) declare void @llvm.matrix.column.major.store.v4i32.vi32(<4 x i32>, float*, i64, i1, i32, i32) declare void @llvm.matrix.column.major.store.v4f32.pi32(<4 x float>, i32*, i64, i1, i32, i32) declare void @llvm.matrix.column.major.store.v4f32p0.p0v4f32(<4 x float*>, <4 x float>*, i64, i1, i32, i32) diff --git a/polly/lib/CodeGen/IslNodeBuilder.cpp b/polly/lib/CodeGen/IslNodeBuilder.cpp index a329661feddf..02e663349f5a 100644 --- a/polly/lib/CodeGen/IslNodeBuilder.cpp +++ b/polly/lib/CodeGen/IslNodeBuilder.cpp @@ -1139,22 +1139,22 @@ static Value *buildFADOutermostDimensionLoad(Value *GlobalDescriptor, Builder.getInt64(0), Builder.getInt32(2)}; Value *endPtr = Builder.CreateInBoundsGEP(GlobalDescriptor, endIdx, ArrayName + "_end_ptr"); - Value *end = Builder.CreateLoad(endPtr, ArrayName + "_end"); + Type *type = cast(endPtr)->getResultElementType(); + assert(isa(type) && "expected type of end to be integral"); + + Value *end = Builder.CreateLoad(type, endPtr, ArrayName + "_end"); Value *beginIdx[4] = {Builder.getInt64(0), Builder.getInt32(3), Builder.getInt64(0), Builder.getInt32(1)}; Value *beginPtr = Builder.CreateInBoundsGEP(GlobalDescriptor, beginIdx, ArrayName + "_begin_ptr"); - Value *begin = Builder.CreateLoad(beginPtr, ArrayName + "_begin"); + Value *begin = Builder.CreateLoad(type, beginPtr, ArrayName + "_begin"); Value *size = Builder.CreateNSWSub(end, begin, ArrayName + "_end_begin_delta"); - Type *endType = dyn_cast(end->getType()); - assert(endType && "expected type of end to be integral"); - size = Builder.CreateNSWAdd(end, - ConstantInt::get(endType, 1, /* signed = */ true), - ArrayName + "_size"); + size = Builder.CreateNSWAdd( + end, ConstantInt::get(type, 1, /* signed = */ true), ArrayName + "_size"); return size; } @@ -1211,7 +1211,7 @@ Value *IslNodeBuilder::preloadUnconditionally(isl_set *AccessRange, auto Name = Ptr->getName(); auto AS = Ptr->getType()->getPointerAddressSpace(); Ptr = Builder.CreatePointerCast(Ptr, Ty->getPointerTo(AS), Name + ".cast"); - PreloadVal = Builder.CreateLoad(Ptr, Name + ".load"); + PreloadVal = Builder.CreateLoad(Ty, Ptr, Name + ".load"); if (LoadInst *PreloadInst = dyn_cast(PreloadVal)) PreloadInst->setAlignment(cast(AccInst)->getAlign()); diff --git a/polly/lib/CodeGen/LoopGenerators.cpp b/polly/lib/CodeGen/LoopGenerators.cpp index fca800dd511a..702503908702 100644 --- a/polly/lib/CodeGen/LoopGenerators.cpp +++ b/polly/lib/CodeGen/LoopGenerators.cpp @@ -245,7 +245,8 @@ void ParallelLoopGenerator::extractValuesFromStruct( SetVector OldValues, Type *Ty, Value *Struct, ValueMapT &Map) { for (unsigned i = 0; i < OldValues.size(); i++) { Value *Address = Builder.CreateStructGEP(Ty, Struct, i); - Value *NewValue = Builder.CreateLoad(Address); + Type *ElemTy = cast(Address)->getResultElementType(); + Value *NewValue = Builder.CreateLoad(ElemTy, Address); NewValue->setName("polly.subfunc.arg." + OldValues[i]->getName()); Map[OldValues[i]] = NewValue; } diff --git a/polly/lib/CodeGen/LoopGeneratorsGOMP.cpp b/polly/lib/CodeGen/LoopGeneratorsGOMP.cpp index 66ebd4dee831..294d91f2f398 100644 --- a/polly/lib/CodeGen/LoopGeneratorsGOMP.cpp +++ b/polly/lib/CodeGen/LoopGeneratorsGOMP.cpp @@ -142,8 +142,8 @@ ParallelLoopGeneratorGOMP::createSubFn(Value *Stride, AllocaInst *StructData, // Add code to load the iv bounds for this set of iterations. Builder.SetInsertPoint(PreHeaderBB); - Value *LB = Builder.CreateLoad(LBPtr, "polly.par.LB"); - Value *UB = Builder.CreateLoad(UBPtr, "polly.par.UB"); + Value *LB = Builder.CreateLoad(LongType, LBPtr, "polly.par.LB"); + Value *UB = Builder.CreateLoad(LongType, UBPtr, "polly.par.UB"); // Subtract one as the upper bound provided by OpenMP is a < comparison // whereas the codegenForSequential function creates a <= comparison. diff --git a/polly/lib/CodeGen/LoopGeneratorsKMP.cpp b/polly/lib/CodeGen/LoopGeneratorsKMP.cpp index 1fa3f89bb005..272f8ae828af 100644 --- a/polly/lib/CodeGen/LoopGeneratorsKMP.cpp +++ b/polly/lib/CodeGen/LoopGeneratorsKMP.cpp @@ -181,8 +181,8 @@ ParallelLoopGeneratorKMP::createSubFn(Value *SequentialLoopStride, Map); const auto Alignment = llvm::Align(is64BitArch() ? 8 : 4); - Value *ID = - Builder.CreateAlignedLoad(IDPtr, Alignment, "polly.par.global_tid"); + Value *ID = Builder.CreateAlignedLoad(Builder.getInt32Ty(), IDPtr, Alignment, + "polly.par.global_tid"); Builder.CreateAlignedStore(LB, LBPtr, Alignment); Builder.CreateAlignedStore(UB, UBPtr, Alignment); @@ -223,8 +223,10 @@ ParallelLoopGeneratorKMP::createSubFn(Value *SequentialLoopStride, Builder.CreateCondBr(HasIteration, PreHeaderBB, ExitBB); Builder.SetInsertPoint(PreHeaderBB); - LB = Builder.CreateAlignedLoad(LBPtr, Alignment, "polly.indvar.LB"); - UB = Builder.CreateAlignedLoad(UBPtr, Alignment, "polly.indvar.UB"); + LB = Builder.CreateAlignedLoad(LongType, LBPtr, Alignment, + "polly.indvar.LB"); + UB = Builder.CreateAlignedLoad(LongType, UBPtr, Alignment, + "polly.indvar.UB"); } break; case OMPGeneralSchedulingType::StaticChunked: @@ -234,11 +236,13 @@ ParallelLoopGeneratorKMP::createSubFn(Value *SequentialLoopStride, Builder.CreateAlignedStore(AdjustedUB, UBPtr, Alignment); createCallStaticInit(ID, IsLastPtr, LBPtr, UBPtr, StridePtr, ChunkSize); - Value *ChunkedStride = - Builder.CreateAlignedLoad(StridePtr, Alignment, "polly.kmpc.stride"); + Value *ChunkedStride = Builder.CreateAlignedLoad( + LongType, StridePtr, Alignment, "polly.kmpc.stride"); - LB = Builder.CreateAlignedLoad(LBPtr, Alignment, "polly.indvar.LB"); - UB = Builder.CreateAlignedLoad(UBPtr, Alignment, "polly.indvar.UB.temp"); + LB = Builder.CreateAlignedLoad(LongType, LBPtr, Alignment, + "polly.indvar.LB"); + UB = Builder.CreateAlignedLoad(LongType, UBPtr, Alignment, + "polly.indvar.UB.temp"); Value *UBInRange = Builder.CreateICmp(llvm::CmpInst::Predicate::ICMP_SLE, UB, AdjustedUB, @@ -252,9 +256,9 @@ ParallelLoopGeneratorKMP::createSubFn(Value *SequentialLoopStride, if (Scheduling == OMPGeneralSchedulingType::StaticChunked) { Builder.SetInsertPoint(PreHeaderBB); - LB = Builder.CreateAlignedLoad(LBPtr, Alignment, + LB = Builder.CreateAlignedLoad(LongType, LBPtr, Alignment, "polly.indvar.LB.entry"); - UB = Builder.CreateAlignedLoad(UBPtr, Alignment, + UB = Builder.CreateAlignedLoad(LongType, UBPtr, Alignment, "polly.indvar.UB.entry"); } diff --git a/polly/lib/CodeGen/PerfMonitor.cpp b/polly/lib/CodeGen/PerfMonitor.cpp index b452dc3bcc09..f6efc532364f 100644 --- a/polly/lib/CodeGen/PerfMonitor.cpp +++ b/polly/lib/CodeGen/PerfMonitor.cpp @@ -138,11 +138,12 @@ Function *PerfMonitor::insertFinalReporting() { // Measure current cycles and compute final timings. Function *RDTSCPFn = getRDTSCP(); + Type *Int64Ty = Builder.getInt64Ty(); Value *CurrentCycles = Builder.CreateExtractValue(Builder.CreateCall(RDTSCPFn), {0}); - Value *CyclesStart = Builder.CreateLoad(CyclesTotalStartPtr, true); + Value *CyclesStart = Builder.CreateLoad(Int64Ty, CyclesTotalStartPtr, true); Value *CyclesTotal = Builder.CreateSub(CurrentCycles, CyclesStart); - Value *CyclesInScops = Builder.CreateLoad(CyclesInScopsPtr, true); + Value *CyclesInScops = Builder.CreateLoad(Int64Ty, CyclesInScopsPtr, true); // Print the runtime information. RuntimeDebugBuilder::createCPUPrinter(Builder, "Polly runtime information\n"); @@ -175,11 +176,12 @@ void PerfMonitor::AppendScopReporting() { Builder.SetInsertPoint(FinalStartBB); ReturnFromFinal->eraseFromParent(); + Type *Int64Ty = Builder.getInt64Ty(); Value *CyclesInCurrentScop = - Builder.CreateLoad(this->CyclesInCurrentScopPtr, true); + Builder.CreateLoad(Int64Ty, this->CyclesInCurrentScopPtr, true); Value *TripCountForCurrentScop = - Builder.CreateLoad(this->TripCountForCurrentScopPtr, true); + Builder.CreateLoad(Int64Ty, this->TripCountForCurrentScopPtr, true); std::string EntryName, ExitName; std::tie(EntryName, ExitName) = S.getEntryExitStr(); @@ -231,7 +233,8 @@ Function *PerfMonitor::insertInitFunction(Function *FinalReporting) { // multiple times. To avoid initializations being run multiple times (and // especially to avoid that atExitFn is called more than once), we bail // out if the initializer is run more than once. - Value *HasRunBefore = Builder.CreateLoad(AlreadyInitializedPtr); + Value *HasRunBefore = + Builder.CreateLoad(Builder.getInt1Ty(), AlreadyInitializedPtr); Builder.CreateCondBr(HasRunBefore, EarlyReturn, InitBB); Builder.SetInsertPoint(EarlyReturn); Builder.CreateRetVoid(); @@ -276,20 +279,23 @@ void PerfMonitor::insertRegionEnd(Instruction *InsertBefore) { Builder.SetInsertPoint(InsertBefore); Function *RDTSCPFn = getRDTSCP(); - LoadInst *CyclesStart = Builder.CreateLoad(CyclesInScopStartPtr, true); + Type *Int64Ty = Builder.getInt64Ty(); + LoadInst *CyclesStart = + Builder.CreateLoad(Int64Ty, CyclesInScopStartPtr, true); Value *CurrentCycles = Builder.CreateExtractValue(Builder.CreateCall(RDTSCPFn), {0}); Value *CyclesInScop = Builder.CreateSub(CurrentCycles, CyclesStart); - Value *CyclesInScops = Builder.CreateLoad(CyclesInScopsPtr, true); + Value *CyclesInScops = Builder.CreateLoad(Int64Ty, CyclesInScopsPtr, true); CyclesInScops = Builder.CreateAdd(CyclesInScops, CyclesInScop); Builder.CreateStore(CyclesInScops, CyclesInScopsPtr, true); - Value *CyclesInCurrentScop = Builder.CreateLoad(CyclesInCurrentScopPtr, true); + Value *CyclesInCurrentScop = + Builder.CreateLoad(Int64Ty, CyclesInCurrentScopPtr, true); CyclesInCurrentScop = Builder.CreateAdd(CyclesInCurrentScop, CyclesInScop); Builder.CreateStore(CyclesInCurrentScop, CyclesInCurrentScopPtr, true); Value *TripCountForCurrentScop = - Builder.CreateLoad(TripCountForCurrentScopPtr, true); + Builder.CreateLoad(Int64Ty, TripCountForCurrentScopPtr, true); TripCountForCurrentScop = Builder.CreateAdd(TripCountForCurrentScop, Builder.getInt64(1)); Builder.CreateStore(TripCountForCurrentScop, TripCountForCurrentScopPtr, -- Gitee From ee84008758a383d3d3e1259c5b2b75973c8f3f7b Mon Sep 17 00:00:00 2001 From: liwentao_uiw Date: Wed, 29 Jun 2022 17:34:56 +0800 Subject: [PATCH 02/18] Spport OHOS Customized LLVM Toolchain @Leviant @Pavel @Xuyao @Chenhao Change-Id: I9cee44fe2ea65aa05af6223d982e1b379b1c9d1a --- clang/include/clang/Basic/Attr.td | 1 + clang/include/clang/Driver/Options.td | 2 + clang/include/clang/Driver/ToolChain.h | 3 +- clang/lib/Basic/TargetInfo.cpp | 3 +- clang/lib/Basic/Targets.cpp | 18 +- clang/lib/Basic/Targets/ARM.cpp | 2 +- clang/lib/Basic/Targets/OSTargets.h | 63 +++ clang/lib/Basic/Targets/X86.h | 22 + clang/lib/CodeGen/ABIInfo.h | 1 + clang/lib/CodeGen/TargetInfo.cpp | 8 +- clang/lib/Driver/CMakeLists.txt | 1 + clang/lib/Driver/Driver.cpp | 7 +- clang/lib/Driver/ToolChain.cpp | 6 + clang/lib/Driver/ToolChains/Arch/ARM.cpp | 2 + clang/lib/Driver/ToolChains/BareMetal.h | 2 +- clang/lib/Driver/ToolChains/Clang.cpp | 5 +- clang/lib/Driver/ToolChains/CommonArgs.cpp | 19 +- clang/lib/Driver/ToolChains/Gnu.cpp | 14 +- clang/lib/Driver/ToolChains/OHOS.cpp | 439 ++++++++++++++++++ clang/lib/Driver/ToolChains/OHOS.h | 103 ++++ clang/lib/Sema/SemaDecl.cpp | 3 +- .../CodeGen/aarch64-fix-cortex-a53-835769.c | 2 + clang/test/CodeGen/arm64-abi-vector.c | 1 + clang/test/CodeGen/math-builtins.c | 1 + clang/test/CodeGen/merge-functions.c | 22 + clang/test/Driver/as-fno-integrated-as.c | 3 + clang/test/Driver/fenable-merge-functions.cpp | 28 ++ clang/test/Driver/ohos.c | 245 ++++++++++ clang/test/Driver/ohos.cpp | 123 +++++ clang/test/Preprocessor/ohos.c | 11 + clang/unittests/CMakeLists.txt | 4 +- compiler-rt/CMakeLists.txt | 32 +- compiler-rt/cmake/Modules/AddCompilerRT.cmake | 6 +- .../cmake/Modules/CompilerRTUtils.cmake | 12 +- compiler-rt/cmake/base-config-ix.cmake | 3 + compiler-rt/cmake/config-ix.cmake | 47 +- compiler-rt/lib/asan/asan_allocator.h | 2 +- compiler-rt/lib/asan/asan_internal.h | 2 +- compiler-rt/lib/asan/asan_linux.cpp | 7 +- compiler-rt/lib/asan/tests/asan_test.cpp | 4 +- compiler-rt/lib/builtins/CMakeLists.txt | 7 +- compiler-rt/lib/builtins/divtf3.c | 2 +- compiler-rt/lib/builtins/fp_div_impl.inc | 2 +- compiler-rt/lib/builtins/int_util.h | 4 + compiler-rt/lib/cfi/CMakeLists.txt | 2 +- compiler-rt/lib/fuzzer/FuzzerInterceptors.cpp | 1 + compiler-rt/lib/hwasan/hwasan.cpp | 2 +- .../lib/hwasan/hwasan_dynamic_shadow.cpp | 2 +- compiler-rt/lib/interception/interception.h | 4 +- .../interception/interception_type_test.cpp | 4 +- compiler-rt/lib/lsan/lsan_common.h | 2 +- .../sanitizer_common/sanitizer_allocator.cpp | 2 +- .../sanitizer_common_interceptors.inc | 6 +- .../sanitizer_common_interceptors_ioctl.inc | 2 +- .../sanitizer_common_syscalls.inc | 4 +- .../lib/sanitizer_common/sanitizer_errno.h | 3 +- .../lib/sanitizer_common/sanitizer_flags.inc | 9 +- .../sanitizer_internal_defs.h | 4 +- .../lib/sanitizer_common/sanitizer_linux.cpp | 26 +- .../lib/sanitizer_common/sanitizer_linux.h | 2 +- .../sanitizer_linux_libcdep.cpp | 8 +- .../lib/sanitizer_common/sanitizer_platform.h | 15 +- .../sanitizer_platform_interceptors.h | 19 +- .../sanitizer_platform_limits_linux.cpp | 6 +- .../sanitizer_platform_limits_posix.cpp | 34 +- .../sanitizer_platform_limits_posix.h | 39 +- .../lib/sanitizer_common/sanitizer_posix.cpp | 4 +- .../sanitizer_posix_libcdep.cpp | 3 +- .../sanitizer_common/sanitizer_stackdepot.cpp | 3 +- .../sanitizer_common/sanitizer_stackdepot.h | 3 +- .../sanitizer_stoptheworld_linux_libcdep.cpp | 5 + .../sanitizer_symbolizer_report.cpp | 2 +- .../sanitizer_unwind_linux_libcdep.cpp | 2 +- compiler-rt/lib/scudo/scudo_flags.inc | 2 +- compiler-rt/lib/scudo/scudo_platform.h | 8 +- .../lib/ubsan/ubsan_signals_standalone.cpp | 2 +- compiler-rt/test/asan/CMakeLists.txt | 2 +- .../asan/TestCases/Linux/lit.local.cfg.py | 2 +- .../test/asan/TestCases/Linux/odr_c_test.c | 2 +- .../test/asan/TestCases/Linux/shmctl.cpp | 4 +- compiler-rt/test/asan/lit.cfg.py | 2 +- compiler-rt/test/builtins/Unit/divtf3_test.c | 5 + compiler-rt/test/lit.common.cfg.py | 72 +-- compiler-rt/test/lit.common.configured.in | 1 + .../ohos_family_commands/ohos_common.py | 45 ++ .../ohos_family_commands/ohos_compile.py | 52 +++ .../ohos_family_commands/ohos_run.py | 38 ++ libcxx/CMakeLists.txt | 14 +- libcxx/cmake/config-ix.cmake | 2 + libcxx/include/__config | 3 +- libcxx/include/__locale | 3 + libcxx/src/CMakeLists.txt | 10 +- libcxx/src/include/config_elast.h | 2 + libcxxabi/CMakeLists.txt | 13 +- libcxxabi/src/abort_message.cpp | 4 +- libunwind/CMakeLists.txt | 13 +- lld/ELF/Config.h | 2 + lld/ELF/Driver.cpp | 46 +- lld/ELF/LTO.cpp | 2 + lld/ELF/Options.td | 4 + lld/test/ELF/lto/opt-level.ll | 6 +- lldb/CMakeLists.txt | 22 +- lldb/cmake/modules/FindPythonAndSwig.cmake | 11 + lldb/cmake/modules/LLDBConfig.cmake | 2 +- lldb/include/lldb/Host/HostInfo.h | 3 + lldb/include/lldb/Host/MainLoop.h | 3 +- lldb/include/lldb/Host/ohos/HostInfoOHOS.h | 32 ++ .../include/lldb/Target/ThreadPlanStepRange.h | 1 + .../Python/lldbsuite/test/decorators.py | 3 + .../Python/lldbsuite/test/lldbplatformutil.py | 2 + .../Python/lldbsuite/test/lldbtest.py | 5 - lldb/source/Expression/IRInterpreter.cpp | 90 +++- lldb/source/Host/CMakeLists.txt | 7 +- lldb/source/Host/common/MainLoop.cpp | 8 +- lldb/source/Host/common/Socket.cpp | 2 +- lldb/source/Host/common/TCPSocket.cpp | 2 + lldb/source/Host/ohos/HostInfoOHOS.cpp | 94 ++++ lldb/source/Host/posix/DomainSocket.cpp | 2 +- lldb/source/Host/posix/HostInfoPosix.cpp | 2 +- .../Host/posix/ProcessLauncherPosixFork.cpp | 2 +- .../Clang/ClangUserExpression.cpp | 2 +- .../Clang/CppModuleConfiguration.cpp | 43 +- .../Clang/CppModuleConfiguration.h | 8 +- lldb/source/Plugins/Platform/CMakeLists.txt | 1 + .../Plugins/Platform/Linux/PlatformLinux.cpp | 2 +- .../Plugins/Platform/OHOS/CMakeLists.txt | 13 + .../Plugins/Platform/OHOS/HdcClient.cpp | 379 +++++++++++++++ lldb/source/Plugins/Platform/OHOS/HdcClient.h | 90 ++++ .../Plugins/Platform/OHOS/PlatformOHOS.cpp | 266 +++++++++++ .../Plugins/Platform/OHOS/PlatformOHOS.h | 80 ++++ .../OHOS/PlatformOHOSRemoteGDBServer.cpp | 247 ++++++++++ .../OHOS/PlatformOHOSRemoteGDBServer.h | 64 +++ lldb/source/Plugins/Process/CMakeLists.txt | 2 +- .../Linux/NativeRegisterContextLinux_arm64.h | 5 + lldb/source/Plugins/Process/Linux/Procfs.h | 2 +- .../GDBRemoteCommunicationServerCommon.cpp | 14 +- lldb/source/Target/PathMappingList.cpp | 7 +- lldb/source/Target/ThreadPlanStepInRange.cpp | 12 +- lldb/source/Target/ThreadPlanStepRange.cpp | 7 + lldb/source/Utility/ArchSpec.cpp | 4 +- .../Utility/TildeExpressionResolver.cpp | 4 +- .../API/api/command-return-object/Makefile | 1 + .../libstdcpp/list/Makefile | 2 +- .../libstdcpp/map/TestDataFormatterStdMap.py | 3 +- .../plugins/command_plugin/Makefile | 1 + lldb/test/API/lang/c/fpeval/Makefile | 3 + lldb/test/API/lang/c/fpeval/TestFPEval.py | 34 ++ lldb/test/API/lang/c/fpeval/main.c | 10 + .../TestGdbRemoteMemoryAllocation.py | 1 + .../TestPlatformProcessConnect.py | 2 +- .../TestGdbRemote_QPassSignals.py | 1 + .../thread-name/TestGdbRemoteThreadName.py | 1 + .../lldb-vscode/attach/TestVSCode_attach.py | 1 + .../runInTerminal/TestVSCode_runInTerminal.py | 1 + lldb/tools/lldb-server/CMakeLists.txt | 2 +- .../Expression/CppModuleConfigurationTest.cpp | 42 +- lldb/unittests/Target/CMakeLists.txt | 1 + lldb/unittests/Target/FindFileTest.cpp | 97 ++++ llvm-build/build.py | 0 llvm-build/env_prepare.sh | 4 +- llvm-build/mingw.py | 0 llvm-build/pack_clang_reproducers.py | 0 llvm-build/update_prebuilts_ohos.py | 0 llvm-build/windres.sh | 0 llvm/include/llvm/ADT/Triple.h | 34 +- .../llvm/BinaryFormat/MinidumpConstants.def | 1 + llvm/include/llvm/LTO/Config.h | 3 + .../LiveDebugValues/VarLocBasedImpl.cpp | 1 - llvm/lib/LTO/LTO.cpp | 2 + llvm/lib/LTO/LTOBackend.cpp | 3 + llvm/lib/Support/AArch64TargetParser.cpp | 2 +- llvm/lib/Support/ARMTargetParser.cpp | 2 +- llvm/lib/Support/Triple.cpp | 80 ++-- .../Target/AMDGPU/Utils/AMDGPUPALMetadata.cpp | 4 +- llvm/lib/Target/ARM/ARMSubtarget.h | 6 +- llvm/lib/Target/ARM/ARMTargetMachine.cpp | 3 +- .../CodeGen/AArch64/arm64-platform-reg.ll | 1 + llvm/test/Transforms/SafeStack/AArch64/abi.ll | 2 + .../Transforms/SafeStack/AArch64/abi_ssp.ll | 2 + .../SafeStack/AArch64/unreachable.ll | 2 + llvm/utils/lit/lit/llvm/config.py | 4 +- .../include/gtest/internal/gtest-port-arch.h | 3 + .../unittest/googletest/src/gtest-port.cc | 2 +- openmp/runtime/src/kmp.h | 3 +- openmp/runtime/src/kmp_i18n.cpp | 3 +- .../tasking/hidden_helper_task/depend.cpp | 4 +- .../test/tasking/hidden_helper_task/gtid.cpp | 4 +- 187 files changed, 3444 insertions(+), 352 deletions(-) create mode 100644 clang/lib/Driver/ToolChains/OHOS.cpp create mode 100644 clang/lib/Driver/ToolChains/OHOS.h create mode 100644 clang/test/CodeGen/merge-functions.c create mode 100644 clang/test/Driver/as-fno-integrated-as.c create mode 100644 clang/test/Driver/fenable-merge-functions.cpp create mode 100644 clang/test/Driver/ohos.c create mode 100644 clang/test/Driver/ohos.cpp create mode 100644 clang/test/Preprocessor/ohos.c create mode 100644 compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_common.py create mode 100644 compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_compile.py create mode 100644 compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_run.py create mode 100644 lldb/include/lldb/Host/ohos/HostInfoOHOS.h create mode 100644 lldb/source/Host/ohos/HostInfoOHOS.cpp create mode 100644 lldb/source/Plugins/Platform/OHOS/CMakeLists.txt create mode 100644 lldb/source/Plugins/Platform/OHOS/HdcClient.cpp create mode 100644 lldb/source/Plugins/Platform/OHOS/HdcClient.h create mode 100644 lldb/source/Plugins/Platform/OHOS/PlatformOHOS.cpp create mode 100644 lldb/source/Plugins/Platform/OHOS/PlatformOHOS.h create mode 100644 lldb/source/Plugins/Platform/OHOS/PlatformOHOSRemoteGDBServer.cpp create mode 100644 lldb/source/Plugins/Platform/OHOS/PlatformOHOSRemoteGDBServer.h create mode 100644 lldb/test/API/lang/c/fpeval/Makefile create mode 100644 lldb/test/API/lang/c/fpeval/TestFPEval.py create mode 100644 lldb/test/API/lang/c/fpeval/main.c create mode 100644 lldb/unittests/Target/FindFileTest.cpp mode change 100644 => 100755 llvm-build/build.py mode change 100644 => 100755 llvm-build/mingw.py mode change 100644 => 100755 llvm-build/pack_clang_reproducers.py mode change 100644 => 100755 llvm-build/update_prebuilts_ohos.py mode change 100644 => 100755 llvm-build/windres.sh diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index bfd50f6a6779..f62b547b72f5 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -840,6 +840,7 @@ def Availability : InheritableAttr { .Case("tvos_app_extension", "tvOS (App Extension)") .Case("watchos_app_extension", "watchOS (App Extension)") .Case("swift", "Swift") + .Case("ohos", "OpenHOS") .Default(llvm::StringRef()); } static llvm::StringRef getPlatformNameSourceSpelling(llvm::StringRef Platform) { diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 817798926650..9019ea8f7298 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2415,6 +2415,8 @@ def ffinite_loops: Flag<["-"], "ffinite-loops">, Group, def fno_finite_loops: Flag<["-"], "fno-finite-loops">, Group, HelpText<"Do not assume that any loop is finite.">, Flags<[CC1Option]>; +def fenable_merge_functions : Flag<["-"], "fenable-merge-functions">, Group, + HelpText<"Enables Merge Functions optimization">; def ftrigraphs : Flag<["-"], "ftrigraphs">, Group, HelpText<"Process trigraph sequences">, Flags<[CC1Option]>; def fno_trigraphs : Flag<["-"], "fno-trigraphs">, Group, diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h index 28c37a44e1eb..9ead01d68335 100644 --- a/clang/include/clang/Driver/ToolChain.h +++ b/clang/include/clang/Driver/ToolChain.h @@ -441,7 +441,8 @@ public: // Returns /lib//. This is used by runtimes (such // as OpenMP) to find arch-specific libraries. - std::string getArchSpecificLibPath() const; + // OHOS specific: make this function virtual to override in OHOS.cpp + virtual std::string getArchSpecificLibPath() const; // Returns part of above. virtual StringRef getOSLibName() const; diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp index 642ee753d224..d727d9991443 100644 --- a/clang/lib/Basic/TargetInfo.cpp +++ b/clang/lib/Basic/TargetInfo.cpp @@ -68,7 +68,8 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) { // alignment on 64-bit systems and 8-byte alignment on 32-bit systems. See // https://www.gnu.org/software/libc/manual/html_node/Malloc-Examples.html. // This alignment guarantee also applies to Windows and Android. - if (T.isGNUEnvironment() || T.isWindowsMSVCEnvironment() || T.isAndroid()) + if (T.isGNUEnvironment() || T.isWindowsMSVCEnvironment() || T.isAndroid() || + T.isOHOSFamily()) NewAlign = Triple.isArch64Bit() ? 128 : Triple.isArch32Bit() ? 64 : 0; else NewAlign = 0; // Infer from basic type alignment. diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp index 90a67d03b7b2..b0c3e9ce9c97 100644 --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -143,7 +143,12 @@ TargetInfo *AllocateTarget(const llvm::Triple &Triple, case llvm::Triple::Fuchsia: return new FuchsiaTargetInfo(Triple, Opts); case llvm::Triple::Linux: - return new LinuxTargetInfo(Triple, Opts); + switch (Triple.getEnvironment()) { + default: + return new LinuxTargetInfo(Triple, Opts); + case llvm::Triple::OpenHOS: + return new OHOSTargetInfo(Triple, Opts); + } case llvm::Triple::NetBSD: return new NetBSDTargetInfo(Triple, Opts); case llvm::Triple::OpenBSD: @@ -183,7 +188,14 @@ TargetInfo *AllocateTarget(const llvm::Triple &Triple, case llvm::Triple::CloudABI: return new CloudABITargetInfo(Triple, Opts); case llvm::Triple::Linux: - return new LinuxTargetInfo(Triple, Opts); + switch (Triple.getEnvironment()) { + default: + return new LinuxTargetInfo(Triple, Opts); + case llvm::Triple::OpenHOS: + return new OHOSTargetInfo(Triple, Opts); + } + case llvm::Triple::LiteOS: + return new OHOSTargetInfo(Triple, Opts); case llvm::Triple::FreeBSD: return new FreeBSDTargetInfo(Triple, Opts); case llvm::Triple::NetBSD: @@ -546,6 +558,8 @@ TargetInfo *AllocateTarget(const llvm::Triple &Triple, return new LinuxTargetInfo(Triple, Opts); case llvm::Triple::Android: return new AndroidX86_64TargetInfo(Triple, Opts); + case llvm::Triple::OpenHOS: + return new OHOSX86_64TargetInfo(Triple, Opts); } } case llvm::Triple::DragonFly: diff --git a/clang/lib/Basic/Targets/ARM.cpp b/clang/lib/Basic/Targets/ARM.cpp index a2c96ad12a76..cca55956b2f4 100644 --- a/clang/lib/Basic/Targets/ARM.cpp +++ b/clang/lib/Basic/Targets/ARM.cpp @@ -305,7 +305,7 @@ ARMTargetInfo::ARMTargetInfo(const llvm::Triple &Triple, default: if (IsNetBSD) setABI("apcs-gnu"); - else if (IsOpenBSD) + else if (IsOpenBSD || Triple.isOHOSFamily()) setABI("aapcs-linux"); else setABI("aapcs"); diff --git a/clang/lib/Basic/Targets/OSTargets.h b/clang/lib/Basic/Targets/OSTargets.h index 67fa1a537fea..295e68426752 100644 --- a/clang/lib/Basic/Targets/OSTargets.h +++ b/clang/lib/Basic/Targets/OSTargets.h @@ -947,6 +947,69 @@ public: : WebAssemblyOSTargetInfo(Triple, Opts) {} }; +// OHOS target +template +class LLVM_LIBRARY_VISIBILITY OHOSTargetInfo : public OSTargetInfo { +protected: + void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, + MacroBuilder &Builder) const override { + // Linux defines; list based off of gcc output + DefineStd(Builder, "unix", Opts); + + Builder.defineMacro("__ELF__"); + + // Generic OHOS target defines + if (Triple.isOHOSFamily()) { + Builder.defineMacro("__OHOS_FAMILY__", "1"); + + unsigned Maj, Min, Rev; + Triple.getEnvironmentVersion(Maj, Min, Rev); + this->PlatformName = "ohos"; + this->PlatformMinVersion = VersionTuple(Maj, Min, Rev); + if (Maj) { + Builder.defineMacro("__OHOS_Major__", Twine(Maj)); + Builder.defineMacro("__OHOS_Minor__", Twine(Min)); + Builder.defineMacro("__OHOS_Micro__", Twine(Rev)); + } + } + + if (Triple.isOpenHOS()) + Builder.defineMacro("__OHOS__"); + + if (Triple.isOSLinux()) { + DefineStd(Builder, "linux", Opts); + } else if (Triple.isOSLiteOS()) { + Builder.defineMacro("__LITEOS__"); + } + + if (Opts.POSIXThreads) + Builder.defineMacro("_REENTRANT"); + if (Opts.CPlusPlus) + Builder.defineMacro("_GNU_SOURCE"); + if (this->HasFloat128) + Builder.defineMacro("__FLOAT128__"); + } + +public: + OHOSTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : OSTargetInfo(Triple, Opts) { + this->WIntType = TargetInfo::UnsignedInt; + + switch (Triple.getArch()) { + default: + break; + case llvm::Triple::x86: + case llvm::Triple::x86_64: + this->HasFloat128 = true; + break; + } + } + + const char *getStaticInitSectionSpecifier() const override { + return ".text.startup"; + } +}; + } // namespace targets } // namespace clang #endif // LLVM_CLANG_LIB_BASIC_TARGETS_OSTARGETS_H diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h index 91a365c7d405..2b8e9bbe16b3 100644 --- a/clang/lib/Basic/Targets/X86.h +++ b/clang/lib/Basic/Targets/X86.h @@ -909,6 +909,28 @@ public: LongDoubleFormat = &llvm::APFloat::IEEEquad(); } }; + +// x86_32 OHOS target +class LLVM_LIBRARY_VISIBILITY OHOSX86_32TargetInfo + : public OHOSTargetInfo { +public: + OHOSX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : OHOSTargetInfo(Triple, Opts) { + SuitableAlign = 32; + LongDoubleWidth = 64; + LongDoubleFormat = &llvm::APFloat::IEEEdouble(); + } +}; + +// x86_64 OHOS target +class LLVM_LIBRARY_VISIBILITY OHOSX86_64TargetInfo + : public OHOSTargetInfo { +public: + OHOSX86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : OHOSTargetInfo(Triple, Opts) { + LongDoubleFormat = &llvm::APFloat::IEEEquad(); + } +}; } // namespace targets } // namespace clang #endif // LLVM_CLANG_LIB_BASIC_TARGETS_X86_H diff --git a/clang/lib/CodeGen/ABIInfo.h b/clang/lib/CodeGen/ABIInfo.h index 56f0dd4322d2..035b6e5a293c 100644 --- a/clang/lib/CodeGen/ABIInfo.h +++ b/clang/lib/CodeGen/ABIInfo.h @@ -89,6 +89,7 @@ namespace swiftcall { QualType Ty) const = 0; bool isAndroid() const; + bool isOHOSFamily() const; /// Emit the target dependent code to load a value of /// \arg Ty from the \c __builtin_ms_va_list pointed to by \arg VAListAddr. diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index bcd24292ff41..4b916b729aeb 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -223,6 +223,10 @@ const CodeGenOptions &ABIInfo::getCodeGenOpts() const { bool ABIInfo::isAndroid() const { return getTarget().getTriple().isAndroid(); } +bool ABIInfo::isOHOSFamily() const { + return getTarget().getTriple().isOHOSFamily(); +} + bool ABIInfo::isHomogeneousAggregateBaseType(QualType Ty) const { return false; } @@ -5607,7 +5611,7 @@ ABIArgInfo AArch64ABIInfo::coerceIllegalVector(QualType Ty) const { uint64_t Size = getContext().getTypeSize(Ty); // Android promotes <2 x i8> to i16, not i32 - if (isAndroid() && (Size <= 16)) { + if ((isAndroid() || isOHOSFamily()) && (Size <= 16)) { llvm::Type *ResType = llvm::Type::getInt16Ty(getVMContext()); return ABIArgInfo::getDirect(ResType); } @@ -6158,7 +6162,7 @@ public: case llvm::Triple::MuslEABIHF: return true; default: - return false; + return getTarget().getTriple().isOHOSFamily(); } } diff --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt index aeffcf0bb43a..7dca74742803 100644 --- a/clang/lib/Driver/CMakeLists.txt +++ b/clang/lib/Driver/CMakeLists.txt @@ -63,6 +63,7 @@ add_clang_library(clangDriver ToolChains/Myriad.cpp ToolChains/NaCl.cpp ToolChains/NetBSD.cpp + ToolChains/OHOS.cpp ToolChains/OpenBSD.cpp ToolChains/PS4CPU.cpp ToolChains/RISCVToolchain.cpp diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 418e1d3e8ec9..71e3df95cb1f 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -37,6 +37,7 @@ #include "ToolChains/Myriad.h" #include "ToolChains/NaCl.h" #include "ToolChains/NetBSD.h" +#include "ToolChains/OHOS.h" #include "ToolChains/OpenBSD.h" #include "ToolChains/PPCLinux.h" #include "ToolChains/PS4CPU.h" @@ -5118,7 +5119,8 @@ const ToolChain &Driver::getToolChain(const ArgList &Args, Args); else if (Target.getArch() == llvm::Triple::ve) TC = std::make_unique(*this, Target, Args); - + else if (Target.isOHOSFamily()) + TC = std::make_unique(*this, Target, Args); else TC = std::make_unique(*this, Target, Args); break; @@ -5176,6 +5178,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args, case llvm::Triple::Hurd: TC = std::make_unique(*this, Target, Args); break; + case llvm::Triple::LiteOS: + TC = std::make_unique(*this, Target, Args); + break; case llvm::Triple::ZOS: TC = std::make_unique(*this, Target, Args); break; diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index b2ddef141a75..5dc8f6720b38 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -823,7 +823,13 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args, Triple.setEnvironment(isHardFloat ? Triple::MuslEABIHF : Triple::MuslEABI); break; + case Triple::OpenHOS: + break; default: { + if (Triple.isOSLiteOS()) { + Triple.setEnvironment(Triple::OpenHOS); + break; + } arm::FloatABI DefaultABI = arm::getDefaultFloatABI(Triple); if (DefaultABI != arm::FloatABI::Invalid && isHardFloat != (DefaultABI == arm::FloatABI::Hard)) { diff --git a/clang/lib/Driver/ToolChains/Arch/ARM.cpp b/clang/lib/Driver/ToolChains/Arch/ARM.cpp index ef590db1eecd..a812bcb58873 100644 --- a/clang/lib/Driver/ToolChains/Arch/ARM.cpp +++ b/clang/lib/Driver/ToolChains/Arch/ARM.cpp @@ -211,6 +211,8 @@ arm::FloatABI arm::getDefaultFloatABI(const llvm::Triple &Triple) { return FloatABI::SoftFP; default: + if (Triple.isOHOSFamily()) + return FloatABI::Soft; switch (Triple.getEnvironment()) { case llvm::Triple::GNUEABIHF: case llvm::Triple::MuslEABIHF: diff --git a/clang/lib/Driver/ToolChains/BareMetal.h b/clang/lib/Driver/ToolChains/BareMetal.h index a6d4922a380f..c29fe67a898b 100644 --- a/clang/lib/Driver/ToolChains/BareMetal.h +++ b/clang/lib/Driver/ToolChains/BareMetal.h @@ -34,7 +34,7 @@ protected: Tool *buildLinker() const override; public: - bool useIntegratedAs() const override { return true; } + bool IsIntegratedAssemblerDefault() const override { return true; } bool isCrossCompiling() const override { return true; } bool isPICDefault() const override { return false; } bool isPIEDefault() const override { return false; } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 1976b48e0f6a..32397abf1b54 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -1702,7 +1702,7 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args, CmdArgs.push_back("-aarch64-fix-cortex-a53-835769=1"); else CmdArgs.push_back("-aarch64-fix-cortex-a53-835769=0"); - } else if (Triple.isAndroid()) { + } else if (Triple.isAndroid() || Triple.isOHOSFamily()) { // Enabled A53 errata (835769) workaround by default on android CmdArgs.push_back("-mllvm"); CmdArgs.push_back("-aarch64-fix-cortex-a53-835769=1"); @@ -5627,6 +5627,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_funroll_loops, options::OPT_fno_unroll_loops); + if (Args.hasArg(options::OPT_fenable_merge_functions)) + CmdArgs.push_back(Args.MakeArgString("-fmerge-functions")); + Args.AddLastArg(CmdArgs, options::OPT_pthread); if (Args.hasFlag(options::OPT_mspeculative_load_hardening, diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index bcaea71dca94..ce90569494c1 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -753,7 +753,7 @@ void tools::linkSanitizerRuntimeDeps(const ToolChain &TC, CmdArgs.push_back(getAsNeededOption(TC, false)); // There's no libpthread or librt on RTEMS & Android. if (TC.getTriple().getOS() != llvm::Triple::RTEMS && - !TC.getTriple().isAndroid()) { + !TC.getTriple().isAndroid() && !TC.getTriple().isOHOSFamily()) { CmdArgs.push_back("-lpthread"); if (!TC.getTriple().isOSOpenBSD()) CmdArgs.push_back("-lrt"); @@ -1132,6 +1132,18 @@ tools::ParsePICArgs(const ToolChain &ToolChain, const ArgList &Args) { } } + // OHOS-specific defaults for PIC/PIE + if (Triple.isOHOSFamily()) { + switch (Triple.getArch()) { + case llvm::Triple::aarch64: + PIC = true; // "-fpic" + break; + + default: + break; + } + } + // OpenBSD-specific defaults for PIE if (Triple.isOSOpenBSD()) { switch (ToolChain.getArch()) { @@ -1391,6 +1403,11 @@ static LibGccType getLibGccType(const Driver &D, const ArgList &Args) { static void AddUnwindLibrary(const ToolChain &TC, const Driver &D, ArgStringList &CmdArgs, const ArgList &Args) { ToolChain::UnwindLibType UNW = TC.GetUnwindLibType(Args); + if (TC.getTriple().isOHOSFamily() && UNW != ToolChain::UNW_None) { + CmdArgs.push_back("-l:libunwind.a"); + return; + } + // Targets that don't use unwind libraries. if (TC.getTriple().isAndroid() || TC.getTriple().isOSIAMCU() || TC.getTriple().isOSBinFormatWasm() || diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp index 1d8a3cdce92a..4106cd9cfa68 100644 --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -393,6 +393,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, const llvm::Triple &Triple = getToolChain().getEffectiveTriple(); const llvm::Triple::ArchType Arch = ToolChain.getArch(); + const bool isOHOSFamily = ToolChain.getTriple().isOHOSFamily(); const bool isAndroid = ToolChain.getTriple().isAndroid(); const bool IsIAMCU = ToolChain.getTriple().isOSIAMCU(); const bool IsVE = ToolChain.getTriple().isVE(); @@ -448,7 +449,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, // Most Android ARM64 targets should enable the linker fix for erratum // 843419. Only non-Cortex-A53 devices are allowed to skip this flag. - if (Arch == llvm::Triple::aarch64 && isAndroid) { + if (Arch == llvm::Triple::aarch64 && (isAndroid || isOHOSFamily)) { std::string CPU = getCPUName(Args, Triple); if (CPU.empty() || CPU == "generic" || CPU == "cortex-a53") CmdArgs.push_back("--fix-cortex-a53-843419"); @@ -456,8 +457,8 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, // Android does not allow shared text relocations. Emit a warning if the // user's code contains any. - if (isAndroid) - CmdArgs.push_back("--warn-shared-textrel"); + if (isAndroid || isOHOSFamily) + CmdArgs.push_back("--warn-shared-textrel"); ToolChain.addExtraOpts(CmdArgs); @@ -615,7 +616,8 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, AddRunTimeLibs(ToolChain, D, CmdArgs, Args); - if (WantPthread && !isAndroid) + // We don't need libpthread neither for bionic nor for musl + if (WantPthread && !isAndroid && !isOHOSFamily) CmdArgs.push_back("-lpthread"); if (Args.hasArg(options::OPT_fsplit_stack)) @@ -2074,8 +2076,8 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes( // lifetime or initialization issues. static const char *const AArch64LibDirs[] = {"/lib64", "/lib"}; static const char *const AArch64Triples[] = { - "aarch64-none-linux-gnu", "aarch64-linux-gnu", "aarch64-redhat-linux", - "aarch64-suse-linux", "aarch64-linux-android"}; + "aarch64-none-linux-gnu", "aarch64-linux-gnu", "aarch64-redhat-linux", + "aarch64-suse-linux", "aarch64-linux-android", "aarch64-linux-ohos"}; static const char *const AArch64beLibDirs[] = {"/lib"}; static const char *const AArch64beTriples[] = {"aarch64_be-none-linux-gnu", "aarch64_be-linux-gnu"}; diff --git a/clang/lib/Driver/ToolChains/OHOS.cpp b/clang/lib/Driver/ToolChains/OHOS.cpp new file mode 100644 index 000000000000..0c243a1ef723 --- /dev/null +++ b/clang/lib/Driver/ToolChains/OHOS.cpp @@ -0,0 +1,439 @@ +//===--- OHOS.cpp - OHOS ToolChain Implementations --------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "OHOS.h" +#include "Arch/ARM.h" +#include "CommonArgs.h" +#include "clang/Config/config.h" +#include "clang/Driver/Compilation.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/DriverDiagnostic.h" +#include "clang/Driver/Options.h" +#include "clang/Driver/SanitizerArgs.h" +#include "llvm/Option/ArgList.h" +#include "llvm/ProfileData/InstrProf.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/VirtualFileSystem.h" +#include "llvm/Support/ScopedPrinter.h" + +using namespace clang::driver; +using namespace clang::driver::toolchains; +using namespace clang::driver::tools; +using namespace clang; +using namespace llvm::opt; +using namespace clang::driver::tools::arm; + +using tools::addMultilibFlag; +using tools::addPathIfExists; + +static bool findOHOSMuslMultilibs(const Multilib::flags_list &Flags, + DetectedMultilibs &Result) { + MultilibSet Multilibs; + Multilibs.push_back(Multilib()); + // -mcpu=cortex-a7 + // -mfloat-abi=soft -mfloat-abi=softfp -mfloat-abi=hard + // -mfpu=neon-vfpv4 + Multilibs.push_back(Multilib("a7_soft", {}, {}, 1) + .flag("+mcpu=cortex-a7") + .flag("+mfloat-abi=soft")); + + Multilibs.push_back(Multilib("a7_softfp_neon-vfpv4", {}, {}, 1) + .flag("+mcpu=cortex-a7") + .flag("+mfloat-abi=softfp") + .flag("+mfpu=neon-vfpv4")); + + Multilibs.push_back(Multilib("a7_hard_neon-vfpv4", {}, {}, 1) + .flag("+mcpu=cortex-a7") + .flag("+mfloat-abi=hard") + .flag("+mfpu=neon-vfpv4")); + + if (Multilibs.select(Flags, Result.SelectedMultilib)) { + Result.Multilibs = Multilibs; + return true; + } + return false; +} + +static bool findOHOSMultilibs(const Driver &D, + const ToolChain &TC, + const llvm::Triple &TargetTriple, + StringRef Path, const ArgList &Args, + DetectedMultilibs &Result) { + Multilib::flags_list Flags; + bool IsA7 = false; + if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) + IsA7 = A->getValue() == StringRef("cortex-a7"); + addMultilibFlag(IsA7, "mcpu=cortex-a7", Flags); + + bool IsMFPU = false; + if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ)) + IsMFPU = A->getValue() == StringRef("neon-vfpv4"); + addMultilibFlag(IsMFPU, "mfpu=neon-vfpv4", Flags); + + tools::arm::FloatABI ARMFloatABI = getARMFloatABI(D, TargetTriple, Args); + addMultilibFlag((ARMFloatABI == tools::arm::FloatABI::Soft), + "mfloat-abi=soft", Flags); + addMultilibFlag((ARMFloatABI == tools::arm::FloatABI::SoftFP), + "mfloat-abi=softfp", Flags); + addMultilibFlag((ARMFloatABI == tools::arm::FloatABI::Hard), + "mfloat-abi=hard", Flags); + + return findOHOSMuslMultilibs(Flags, Result); +} + +std::string OHOS::getMultiarchTriple(const llvm::Triple &T) const { + // For most architectures, just use whatever we have rather than trying to be + // clever. + switch (T.getArch()) { + default: + break; + + // We use the existence of '/lib/' as a directory to detect some + // common linux triples that don't quite match the Clang triple for both + // 32-bit and 64-bit targets. Multiarch fixes its install triples to these + // regardless of what the actual target triple is. + case llvm::Triple::arm: + case llvm::Triple::thumb: + return T.isOSLiteOS() ? "arm-liteos-ohos" : "arm-linux-ohos"; + case llvm::Triple::riscv32: + return "riscv32-liteos-ohos"; + case llvm::Triple::x86: + return "i686-linux-ohos"; + case llvm::Triple::x86_64: + return "x86_64-linux-ohos"; + case llvm::Triple::aarch64: + return "aarch64-linux-ohos"; + } + return T.str(); +} + +std::string OHOS::getMultiarchTriple(const Driver &D, + const llvm::Triple &TargetTriple, + StringRef SysRoot) const { + return getMultiarchTriple(TargetTriple); +} + +static std::string makePath(const std::initializer_list &IL) { + SmallString<128> P; + for (const auto &S : IL) + llvm::sys::path::append(P, S); + return static_cast(P.str()); +} + +/// OHOS Toolchain +OHOS::OHOS(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) + : Generic_ELF(D, Triple, Args) { + std::string SysRoot = computeSysRoot(); + + // Select the correct multilib according to the given arguments. + DetectedMultilibs Result; + findOHOSMultilibs(D, *this, Triple, "", Args, Result); + Multilibs = Result.Multilibs; + SelectedMultilib = Result.SelectedMultilib; + + getFilePaths().clear(); + if (D.CCCIsCXX()) { + if (auto CXXStdlibPath = getCXXStdlibPath()) + getFilePaths().push_back(*CXXStdlibPath); + } + + std::string CandidateLibPath = getArchSpecificLibPath(); + if (getVFS().exists(CandidateLibPath)) + getFilePaths().push_back(CandidateLibPath); + + getLibraryPaths().clear(); + if (auto RuntimePath = getRuntimePath()) + getLibraryPaths().push_back(*RuntimePath); + + // OHOS sysroots contain a library directory for each supported OS + // version as well as some unversioned libraries in the usual multiarch + // directory. Support --target=aarch64-linux-ohosX.Y.Z or + // --target=aarch64-linux-ohosX.Y or --target=aarch64-linux-ohosX + unsigned Major; + unsigned Minor; + unsigned Micro; + Triple.getEnvironmentVersion(Major, Minor, Micro); + path_list &Paths = getFilePaths(); + std::string SysRootLibPath = makePath({SysRoot, "usr", "lib"}); + std::string MultiarchTriple = getMultiarchTriple(getTriple()); + addPathIfExists(D, makePath({SysRootLibPath, SelectedMultilib.gccSuffix()}), + Paths); + addPathIfExists(D, + makePath({D.Dir, "..", "lib", MultiarchTriple, + SelectedMultilib.gccSuffix()}), + Paths); + + // For compatibility with arm-liteos sysroot + // FIXME: Remove this when we'll use arm-liteos sysroot produced by build.py. + addPathIfExists( + D, + makePath({SysRootLibPath, MultiarchTriple, SelectedMultilib.gccSuffix()}), + Paths); +} + +std::string OHOS::ComputeEffectiveClangTriple(const ArgList &Args, + types::ID InputType) const { + // Don't modify this, it is impact of the toolchain and target init process. + return ComputeLLVMTriple(Args, InputType); +} + +ToolChain::RuntimeLibType OHOS::GetRuntimeLibType( + const ArgList &Args) const { + if (Arg *A = Args.getLastArg(clang::driver::options::OPT_rtlib_EQ)) { + StringRef Value = A->getValue(); + if (Value != "compiler-rt") + getDriver().Diag(clang::diag::err_drv_invalid_rtlib_name) + << A->getAsString(Args); + } + + return ToolChain::RLT_CompilerRT; +} + +ToolChain::CXXStdlibType +OHOS::GetCXXStdlibType(const ArgList &Args) const { + if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) { + StringRef Value = A->getValue(); + if (Value != "libc++") + getDriver().Diag(diag::err_drv_invalid_stdlib_name) + << A->getAsString(Args); + } + + return ToolChain::CST_Libcxx; +} + +void OHOS::AddClangSystemIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + const Driver &D = getDriver(); + const llvm::Triple &Triple = getTriple(); + std::string SysRoot = computeSysRoot(); + + if (DriverArgs.hasArg(options::OPT_nostdinc)) + return; + + if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { + SmallString<128> P(D.ResourceDir); + llvm::sys::path::append(P, "include"); + addSystemInclude(DriverArgs, CC1Args, P); + } + + if (DriverArgs.hasArg(options::OPT_nostdlibinc)) + return; + + // Check for configure-time C include directories. + StringRef CIncludeDirs(C_INCLUDE_DIRS); + if (CIncludeDirs != "") { + SmallVector dirs; + CIncludeDirs.split(dirs, ":"); + for (StringRef dir : dirs) { + StringRef Prefix = + llvm::sys::path::is_absolute(dir) ? StringRef(SysRoot) : ""; + addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir); + } + return; + } + + addExternCSystemInclude(DriverArgs, CC1Args, + SysRoot + "/usr/include/" + + getMultiarchTriple(Triple)); + addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/include"); + addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include"); +} + +void OHOS::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + if (DriverArgs.hasArg(options::OPT_nostdlibinc) || + DriverArgs.hasArg(options::OPT_nostdincxx)) + return; + + switch (GetCXXStdlibType(DriverArgs)) { + case ToolChain::CST_Libcxx: { + std::string Path = makePath({getDriver().Dir, "..", "include", + "libcxx-ohos", "include", "c++", "v1"}); + addSystemInclude(DriverArgs, CC1Args, Path); + break; + } + + default: + llvm_unreachable("invalid stdlib name"); + } +} + +void OHOS::AddCXXStdlibLibArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + switch (GetCXXStdlibType(Args)) { + case ToolChain::CST_Libcxx: + CmdArgs.push_back("-lc++"); + CmdArgs.push_back("-lc++abi"); + CmdArgs.push_back("-lunwind"); + break; + + case ToolChain::CST_Libstdcxx: + llvm_unreachable("invalid stdlib name"); + } +} + +std::string OHOS::computeSysRoot() const { + std::string SysRoot = + !getDriver().SysRoot.empty() + ? getDriver().SysRoot + : makePath({getDriver().getInstalledDir(), "..", "..", "sysroot"}); + if (!llvm::sys::fs::exists(SysRoot)) + return std::string(); + + std::string ArchRoot = makePath({SysRoot, getMultiarchTriple(getTriple())}); + return llvm::sys::fs::exists(ArchRoot) ? ArchRoot : SysRoot; +} + +Optional OHOS::getRuntimePath() const { + SmallString<128> P; + const Driver &D = getDriver(); + const llvm::Triple &Triple = getTriple(); + + // First try the triple passed to driver as --target=. + P.assign(D.ResourceDir); + llvm::sys::path::append(P, "lib", D.getTargetTriple(), SelectedMultilib.gccSuffix()); + if (getVFS().exists(P)) + return llvm::Optional(static_cast(P.str())); + + // Second try the normalized triple. + P.assign(D.ResourceDir); + llvm::sys::path::append(P, "lib", Triple.str(), SelectedMultilib.gccSuffix()); + if (getVFS().exists(P)) + return llvm::Optional(static_cast(P.str())); + + // Third try the effective triple. + P.assign(D.ResourceDir); + std::string SysRoot = computeSysRoot(); + llvm::sys::path::append(P, "lib", getMultiarchTriple(Triple), + SelectedMultilib.gccSuffix()); + if (getVFS().exists(P)) + return llvm::Optional(static_cast(P.str())); + + return None; +} + +Optional OHOS::getCXXStdlibPath() const { + const Driver &D = getDriver(); + std::string SysRoot = computeSysRoot(); + const std::string &MultiarchTriple = getMultiarchTriple(getTriple()); + + const std::string &P = makePath({D.Dir, "..", "lib", MultiarchTriple, "c++", + SelectedMultilib.gccSuffix()}); + if (getVFS().exists(P)) + return llvm::Optional(P); + + return None; +} + +std::string OHOS::getDynamicLinker(const ArgList &Args) const { + const llvm::Triple &Triple = getTriple(); + const llvm::Triple::ArchType Arch = getArch(); + + assert(Triple.isMusl()); + std::string ArchName; + bool IsArm = false; + + switch (Arch) { + case llvm::Triple::arm: + case llvm::Triple::thumb: + ArchName = "arm"; + IsArm = true; + break; + case llvm::Triple::armeb: + case llvm::Triple::thumbeb: + ArchName = "armeb"; + IsArm = true; + break; + default: + ArchName = Triple.getArchName().str(); + } + if (IsArm && + (tools::arm::getARMFloatABI(*this, Args) == tools::arm::FloatABI::Hard)) + ArchName += "hf"; + + return "/lib/ld-musl-" + ArchName + ".so.1"; +} + +std::string OHOS::getCompilerRT(const ArgList &Args, StringRef Component, + FileType Type) const { + SmallString<128> Path(getDriver().ResourceDir); + llvm::sys::path::append(Path, "lib", getMultiarchTriple(getTriple()), + SelectedMultilib.gccSuffix()); + const char *Prefix = + Type == ToolChain::FT_Object ? "" : "lib"; + const char *Suffix; + switch (Type) { + case ToolChain::FT_Object: + Suffix = ".o"; + break; + case ToolChain::FT_Static: + Suffix = ".a"; + break; + case ToolChain::FT_Shared: + Suffix = ".so"; + break; + } + llvm::sys::path::append( + Path, Prefix + Twine("clang_rt.") + Component + Suffix); + return static_cast(Path.str()); +} + +void OHOS::addExtraOpts(llvm::opt::ArgStringList &CmdArgs) const { + CmdArgs.push_back("-z"); + CmdArgs.push_back("now"); + CmdArgs.push_back("-z"); + CmdArgs.push_back("relro"); + CmdArgs.push_back("-z"); + CmdArgs.push_back("max-page-size=4096"); + CmdArgs.push_back("--hash-style=gnu"); + // FIXME: gnu or both??? + CmdArgs.push_back("--hash-style=both"); +#ifdef ENABLE_LINKER_BUILD_ID + CmdArgs.push_back("--build-id"); +#endif + CmdArgs.push_back("--enable-new-dtags"); +} + +SanitizerMask OHOS::getSupportedSanitizers() const { + SanitizerMask Res = ToolChain::getSupportedSanitizers(); + Res |= SanitizerKind::Address; + Res |= SanitizerKind::PointerCompare; + Res |= SanitizerKind::PointerSubtract; + Res |= SanitizerKind::Fuzzer; + Res |= SanitizerKind::FuzzerNoLink; + Res |= SanitizerKind::Memory; + Res |= SanitizerKind::Vptr; + Res |= SanitizerKind::SafeStack; + Res |= SanitizerKind::Scudo; + // TODO: kASAN for liteos ?? + // TODO: Support TSAN and HWASAN and update mask. + return Res; +} + +// TODO: Make a base class for Linux and OHOS and move this there. +void OHOS::addProfileRTLibs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const { + // Add linker option -u__llvm_profile_runtime to cause runtime + // initialization module to be linked in. + if (needsProfileRT(Args)) + CmdArgs.push_back(Args.MakeArgString( + Twine("-u", llvm::getInstrProfRuntimeHookVarName()))); + ToolChain::addProfileRTLibs(Args, CmdArgs); +} + +std::string OHOS::getArchSpecificLibPath() const { + llvm::Triple Triple = getTriple(); + return makePath({getDriver().ResourceDir, "lib", getMultiarchTriple(Triple)}); +} + +ToolChain::UnwindLibType OHOS::GetUnwindLibType(const llvm::opt::ArgList &Args) const { + if (const Arg *A = Args.getLastArg(options::OPT_unwindlib_EQ)) + return Generic_ELF::GetUnwindLibType(Args); + return GetDefaultUnwindLibType(); +} \ No newline at end of file diff --git a/clang/lib/Driver/ToolChains/OHOS.h b/clang/lib/Driver/ToolChains/OHOS.h new file mode 100644 index 000000000000..002ee71f7b90 --- /dev/null +++ b/clang/lib/Driver/ToolChains/OHOS.h @@ -0,0 +1,103 @@ +//===--- OHOS.h - OHOS ToolChain Implementations ----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_OHOS_H +#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_OHOS_H + +#include "Linux.h" +#include "clang/Driver/Tool.h" +#include "clang/Driver/ToolChain.h" + +namespace clang { +namespace driver { +namespace toolchains { + +class LLVM_LIBRARY_VISIBILITY OHOS : public Generic_ELF { +public: + OHOS(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args); + + bool HasNativeLLVMSupport() const override { return true; } + bool IsIntegratedAssemblerDefault() const override { return true; } + bool IsMathErrnoDefault() const override { return false; } + RuntimeLibType GetDefaultRuntimeLibType() const override { + return ToolChain::RLT_CompilerRT; + } + CXXStdlibType GetDefaultCXXStdlibType() const override { + return ToolChain::CST_Libcxx; + } + // Not add -funwind-tables by default + bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override { + return false; + } + bool isPICDefault() const override { return false; } + bool isPIEDefault() const override { return true; } + bool isPICDefaultForced() const override { return false; } + bool isNoExecStackDefault() const override { return true; } + bool useRelaxRelocations() const override { return false; } + UnwindLibType GetUnwindLibType(const llvm::opt::ArgList &Args) const override; + UnwindLibType GetDefaultUnwindLibType() const override { return UNW_CompilerRT; } + + std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args, + types::ID InputType = types::TY_INVALID) const override; + + RuntimeLibType + GetRuntimeLibType(const llvm::opt::ArgList &Args) const override; + CXXStdlibType + GetCXXStdlibType(const llvm::opt::ArgList &Args) const override; + + void + AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; + void + AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; + void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const override; + + std::string computeSysRoot() const override; + std::string getDynamicLinker(const llvm::opt::ArgList &Args) const override; + + std::string + getCompilerRT(const llvm::opt::ArgList &Args, StringRef Component, + FileType Type = ToolChain::FT_Static) const override; + + const char *getDefaultLinker() const override { + return "ld.lld"; + } + + Tool *buildLinker() const override { + return new tools::gnutools::Linker(*this); + } + Tool *buildAssembler() const override { + return new tools::gnutools::Assembler(*this); + } + + Optional getRuntimePath() const override; + Optional getCXXStdlibPath() const override; + +protected: + std::string getMultiarchTriple(const llvm::Triple &T) const; + std::string getMultiarchTriple(const Driver &D, + const llvm::Triple &TargetTriple, + StringRef SysRoot) const override; + void addExtraOpts(llvm::opt::ArgStringList &CmdArgs) const override; + SanitizerMask getSupportedSanitizers() const override; + void addProfileRTLibs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const override; + std::string getArchSpecificLibPath() const override; + +private: + Multilib SelectedMultilib; +}; + +} // end namespace toolchains +} // end namespace driver +} // end namespace clang + +#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_OHOS_H diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 1f7ab49ccdd7..66826a8b3ba7 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -14922,7 +14922,8 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { // errno in those environments even though it could set errno based on the // C standard. const llvm::Triple &Trip = Context.getTargetInfo().getTriple(); - if ((Trip.isGNUEnvironment() || Trip.isAndroid() || Trip.isOSMSVCRT()) && + if ((Trip.isGNUEnvironment() || Trip.isAndroid() || Trip.isOSMSVCRT() || + Trip.isOHOSFamily()) && !FD->hasAttr()) { switch (BuiltinID) { case Builtin::BI__builtin_fma: diff --git a/clang/test/CodeGen/aarch64-fix-cortex-a53-835769.c b/clang/test/CodeGen/aarch64-fix-cortex-a53-835769.c index c6a38b20074a..74949c91ae6c 100644 --- a/clang/test/CodeGen/aarch64-fix-cortex-a53-835769.c +++ b/clang/test/CodeGen/aarch64-fix-cortex-a53-835769.c @@ -9,6 +9,8 @@ // RUN: %clang -O3 -target aarch64-android-eabi %s -S -o- \ // RUN: | FileCheck --check-prefix=CHECK-YES --check-prefix=CHECK %s +// RUN: %clang -O3 -target aarch64-linux-ohos %s -S -o- \ +// RUN: | FileCheck --check-prefix=CHECK-YES --check-prefix=CHECK %s // RUN: %clang -O3 -target aarch64-android-eabi -mfix-cortex-a53-835769 %s -S -o- \ // RUN: | FileCheck --check-prefix=CHECK-YES --check-prefix=CHECK %s // RUN: %clang -O3 -target aarch64-android-eabi -mno-fix-cortex-a53-835769 %s -S -o- \ diff --git a/clang/test/CodeGen/arm64-abi-vector.c b/clang/test/CodeGen/arm64-abi-vector.c index da4af7a8cc82..56a1d18073e2 100644 --- a/clang/test/CodeGen/arm64-abi-vector.c +++ b/clang/test/CodeGen/arm64-abi-vector.c @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -triple arm64-apple-ios7 -target-abi darwinpcs -emit-llvm -o - %s | FileCheck %s // RUN: %clang_cc1 -triple aarch64-linux-android -emit-llvm -o - %s | FileCheck -check-prefix=ANDROID %s +// RUN: %clang_cc1 -triple aarch64-linux-ohos -emit-llvm -o - %s | FileCheck -check-prefix=ANDROID %s #include diff --git a/clang/test/CodeGen/math-builtins.c b/clang/test/CodeGen/math-builtins.c index ac2a7595e1c9..7f595e3b0b67 100644 --- a/clang/test/CodeGen/math-builtins.c +++ b/clang/test/CodeGen/math-builtins.c @@ -2,6 +2,7 @@ // RUN: %clang_cc1 -triple x86_64-unknown-unknown -w -S -o - -emit-llvm -fmath-errno %s | FileCheck %s -check-prefix=HAS_ERRNO // RUN: %clang_cc1 -triple x86_64-unknown-unknown-gnu -w -S -o - -emit-llvm -fmath-errno %s | FileCheck %s --check-prefix=HAS_ERRNO_GNU // RUN: %clang_cc1 -triple x86_64-unknown-unknown-android -w -S -o - -emit-llvm -fmath-errno %s | FileCheck %s --check-prefix=HAS_ERRNO_ANDROID +// RUN: %clang_cc1 -triple x86_64-unknown-unknown-ohos -w -S -o - -emit-llvm -fmath-errno %s | FileCheck %s --check-prefix=HAS_ERRNO_ANDROID // RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -w -S -o - -emit-llvm -fmath-errno %s | FileCheck %s --check-prefix=HAS_ERRNO_WIN // Test attributes and codegen of math builtins. diff --git a/clang/test/CodeGen/merge-functions.c b/clang/test/CodeGen/merge-functions.c new file mode 100644 index 000000000000..7e382853cc7c --- /dev/null +++ b/clang/test/CodeGen/merge-functions.c @@ -0,0 +1,22 @@ +// Check that code gen really activates function merging. In this case +// just check a trivial functions merging case. + +// RUN: %clang_cc1 -emit-llvm %s -fmerge-functions -o - | FileCheck %s + +void foo1() {} +void foo2() {} + +int main() { + + // If merge functions pass is enabled, + // then second and first calls will refer to foo1 + + // CHECK: call void @{{[^\(]*}}foo1{{[^\(]*}}() + foo1(); + + // CHECK: call void @{{[^\(]*}}foo1{{[^\(]*}}() + foo2(); + + return 0; +} + diff --git a/clang/test/Driver/as-fno-integrated-as.c b/clang/test/Driver/as-fno-integrated-as.c new file mode 100644 index 000000000000..866cc421e522 --- /dev/null +++ b/clang/test/Driver/as-fno-integrated-as.c @@ -0,0 +1,3 @@ +// Make sure that for BareMetal toolchain, we able to +// disable the use of integrated assembler. +// RUN: %clang -Werror --target="arm-none-eabi" -fno-integrated-as -c %s diff --git a/clang/test/Driver/fenable-merge-functions.cpp b/clang/test/Driver/fenable-merge-functions.cpp new file mode 100644 index 000000000000..f45cdd3b09e9 --- /dev/null +++ b/clang/test/Driver/fenable-merge-functions.cpp @@ -0,0 +1,28 @@ +// First. Check that option is passed into clangcc1 +// RUN: %clang -fenable-merge-functions -### %s 2>&1 | FileCheck %s -check-prefix=CHECK_CC1 +// CHECK_CC1: "-cc1" {{.*}} "-fmerge-functions" + +// Second. Check that code gen really activates function merging. In this case +// just check a trivial functions merging case. +// One may say, that this is an superfluous check, +// for it is covered by clang/test/CodeGen/merge-functions.c +// But it is worth keeping, because it also checks whole driver + clang interaction chain. + +// RUN: %clang -emit-llvm %s -fenable-merge-functions -c -S -o - | FileCheck %s + +void foo1() {} +void foo2() {} + +int main() { + + // If merge functions pass is enabled, + // then second and first calls will refer to foo1 + + // CHECK: call void @{{[^\(]*}}foo1{{[^\(]*}}() + foo1(); + + // CHECK: call void @{{[^\(]*}}foo1{{[^\(]*}}() + foo2(); + + return 0; +} diff --git a/clang/test/Driver/ohos.c b/clang/test/Driver/ohos.c new file mode 100644 index 000000000000..170c0da0ce06 --- /dev/null +++ b/clang/test/Driver/ohos.c @@ -0,0 +1,245 @@ +// RUN: %clang %s -### -no-canonical-prefixes --target=arm-liteos \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: --sysroot=%S/Inputs/ohos_native_tree/sysroot -fuse-ld=lld -march=armv7-a 2>&1 \ +// RUN: | FileCheck -check-prefixes=CHECK,CHECK-ARM %s +// RUN: %clang %s -### -no-canonical-prefixes --target=arm-liteos \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: --sysroot=%S/Inputs/ohos_native_tree/sysroot -fuse-ld=lld -march=armv7-a -mcpu=cortex-a7 -mfloat-abi=soft 2>&1 \ +// RUN: | FileCheck -check-prefixes=CHECK,CHECK-ARM-A7-SOFT %s +// CHECK: {{.*}}clang{{.*}}" "-cc1" +// CHECK-NOT: "--mrelax-relocations" +// CHECK-NOT: "-munwind-tables" +// CHECK: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK: "-isysroot" "[[SYSROOT:[^"]+]]" +// CHECK: "-internal-externc-isystem" "[[SYSROOT]]{{/|\\\\}}include" +// CHECK-NOT: "-fsanitize=safe-stack" +// CHECK-NOT: "-stack-protector" "2" +// CHECK-NOT: "-fno-common" +// CHECK: {{.*}}ld.lld{{.*}}" "--sysroot=[[SYSROOT]]" +// CHECK-NOT: "--sysroot=[[SYSROOT]]" +// CHECK: "-pie" +// CHECK: "-z" "noexecstack" +// CHECK-NOT: "--build-id" +// CHECK: "--hash-style=gnu" +// CHECK: "--hash-style=both" +// CHECK: "-dynamic-linker" "/lib/ld-musl-arm.so.1" +// CHECK: Scrt1.o +// CHECK: crti.o +// CHECK: clang_rt.crtbegin.o +// CHECK-ARM: "-L[[SYSROOT]]/usr/lib/arm-liteos-ohos/" +// CHECK-ARM-A7-SOFT: "-L[[SYSROOT]]/usr/lib/arm-liteos-ohos/a7_soft" +// CHECK-ARM: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}libclang_rt.builtins.a" +// CHECK-ARM-A7-SOFT: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos/a7_soft{{/|\\\\}}libclang_rt.builtins.a" +// CHECK: "-lc" +// CHECK: clang_rt.crtend.o +// CHECK: crtn.o + +// RUN: %clang %s -### --target=arm-liteos -rtlib=libgcc -fuse-ld=lld 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CHECK-RTLIB +// CHECK-RTLIB: error: invalid runtime library name in argument '-rtlib=libgcc' + +// RUN: %clang %s -### --target=arm-liteos -static -fuse-ld=lld 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CHECK-STATIC +// CHECK-STATIC: "-Bstatic" +// CHECK-STATIC-NOT: "-Bdynamic" +// CHECK-STATIC: "-l:libunwind.a" +// CHECK-STATIC: "-lc" + +// RUN: %clang %s -### --target=arm-liteos -shared -fuse-ld=lld 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CHECK-SHARED +// CHECK-SHARED-NOT: "-pie" +// CHECK-SHARED: "-shared" +// CHECK-SHARED: "-lc" +// CHECK-SHARED: "-l:libunwind.a" + +// RUN: %clang %s -### --target=arm-linux-ohos -fuse-ld=lld 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CHECK-RUNTIME +// RUN: %clang %s -### --target=aarch64-linux-ohos -fuse-ld=lld 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CHECK-RUNTIME +// CHECK-RUNTIME: "{{.*}}/libclang_rt.builtins.a" +// CHECK-RUNTIME: "-l:libunwind.a" +// CHECK-LIBM: "-lm" + +// RUN: %clang %s -### --target=arm-liteos -r -fuse-ld=lld 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CHECK-RELOCATABLE +// CHECK-RELOCATABLE-NOT: "-pie" +// CHECK-RELOCATABLE-NOT: "--build-id" +// CHECK-RELOCATABLE: "-r" + +// RUN: %clang %s -### --target=arm-liteos -nodefaultlibs -fuse-ld=lld 2>&1 \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: | FileCheck %s -check-prefix=CHECK-NODEFAULTLIBS +// CHECK-NODEFAULTLIBS: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK-NODEFAULTLIBS-NOT: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}libclang_rt.builtins.a" +// CHECK-NODEFAULTLIBS-NOT: "-lc" + +// RUN: %clang %s -### --target=arm-liteos -nostdlib -fuse-ld=lld 2>&1 \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: | FileCheck %s -check-prefix=CHECK-NOSTDLIB +// CHECK-NOSTDLIB: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK-NOSTDLIB-NOT: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}libclang_rt.builtins.a" +// CHECK-NOSTDLIB-NOT: "-lc" + +// RUN: %clang %s -### --target=arm-liteos -nolibc -fuse-ld=lld 2>&1 \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: | FileCheck %s -check-prefix=CHECK-NOLIBC +// CHECK-NOLIBC: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK-NOLIBC: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}libclang_rt.builtins.a" +// CHECK-NOLIBC-NOT: "-lc" + +// RUN: %clang %s -### --target=arm-liteos \ +// RUN: -fsanitize=safe-stack 2>&1 \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: -fuse-ld=lld \ +// RUN: | FileCheck %s -check-prefix=CHECK-SAFESTACK +// CHECK-SAFESTACK: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK-SAFESTACK: "-fsanitize=safe-stack" +// CHECK-SAFESTACK: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}libclang_rt.safestack.a" +// CHECK-SAFESTACK: "__safestack_init" + +// RUN: %clang %s -### --target=arm-liteos \ +// RUN: -fsanitize=address 2>&1 \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: -fuse-ld=lld \ +// RUN: | FileCheck %s -check-prefix=CHECK-ASAN-ARM +// CHECK-ASAN-ARM: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK-ASAN-ARM: "-fsanitize=address" +// CHECK-ASAN-ARM: "-fsanitize-address-use-after-scope" +// CHECK-ASAN-ARM: "-dynamic-linker" "/lib/ld-musl-arm.so.1" +// CHECK-ASAN-ARM: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}libclang_rt.asan.a" +// CHECK-ASAN-ARM-NOT: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}libclang_rt.asan-preinit.a" + +// RUN: %clang %s -### --target=arm-liteos \ +// RUN: -fsanitize=address -fPIC -shared 2>&1 \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: -shared-libsan \ +// RUN: -fuse-ld=lld \ +// RUN: | FileCheck %s -check-prefix=CHECK-ASAN-SHARED +// CHECK-ASAN-SHARED: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK-ASAN-SHARED: "-fsanitize=address" +// CHECK-ASAN-SHARED: "-fsanitize-address-use-after-scope" +// CHECK-ASAN-SHARED: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}libclang_rt.asan.so" +// CHECK-ASAN-SHARED-NOT: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}libclang_rt.asan-preinit.a" + +// RUN: %clang %s -### --target=arm-liteos \ +// RUN: -fsanitize=fuzzer 2>&1 \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: -fuse-ld=lld \ +// RUN: | FileCheck %s -check-prefix=CHECK-FUZZER-ARM +// CHECK-FUZZER-ARM: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK-FUZZER-ARM: "-fsanitize=fuzzer,fuzzer-no-link" +// CHECK-FUZZER-ARM: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}libclang_rt.fuzzer.a" + +// RUN: %clang %s -### --target=arm-liteos \ +// RUN: -fsanitize=scudo 2>&1 \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: -fuse-ld=lld \ +// RUN: | FileCheck %s -check-prefix=CHECK-SCUDO-ARM +// CHECK-SCUDO-ARM: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK-SCUDO-ARM: "-fsanitize=scudo" +// CHECK-SCUDO-ARM: "-pie" +// CHECK-SCUDO-ARM: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}libclang_rt.scudo.a" + +// RUN: %clang %s -### --target=arm-liteos \ +// RUN: -fsanitize=scudo -fPIC -shared 2>&1 \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: -shared-libsan \ +// RUN: -fuse-ld=lld \ +// RUN: | FileCheck %s -check-prefix=CHECK-SCUDO-SHARED +// CHECK-SCUDO-SHARED: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK-SCUDO-SHARED: "-fsanitize=scudo" +// CHECK-SCUDO-SHARED: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}libclang_rt.scudo.so" + +// RUN: %clang %s -### --target=arm-liteos \ +// RUN: -fxray-instrument -fxray-modes=xray-basic \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: -fuse-ld=lld 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CHECK-XRAY-ARM +// CHECK-XRAY-ARM: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK-XRAY-ARM: "-fxray-instrument" +// CHECK-XRAY-ARM: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}libclang_rt.xray.a" +// CHECK-XRAY-ARM: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}libclang_rt.xray-basic.a" + +// RUN: %clang %s -### --target=arm-liteos \ +// RUN: -O3 -flto -mcpu=cortex-a53 2>&1 \ +// RUN: -fuse-ld=lld \ +// RUN: | FileCheck %s -check-prefix=CHECK-LTO +// CHECK-LTO: "-plugin-opt=mcpu=cortex-a53" +// CHECK-LTO: "-plugin-opt=O3" + +// RUN: %clang %s -### --target=arm-liteos \ +// RUN: -flto=thin -flto-jobs=8 -mcpu=cortex-a7 2>&1 \ +// RUN: -fuse-ld=lld \ +// RUN: | FileCheck %s -check-prefix=CHECK-THINLTO +// CHECK-THINLTO: "-plugin-opt=mcpu=cortex-a7" +// CHECK-THINLTO: "-plugin-opt=thinlto" +// CHECK-THINLTO: "-plugin-opt=jobs=8" + +// RUN: %clang %s -### --target=arm-liteos \ +// RUN: -ccc-install-dir %S/Inputs/ohos_native_tree/llvm/bin \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: --sysroot=%S/Inputs/ohos_native_tree/sysroot \ +// RUN: -march=armv7-a -mfloat-abi=soft 2>&1\ +// RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB,CHECK-MULTILIB-SF,CHECK-MULTILIB-ARM +// RUN: %clang %s -### --target=arm-liteos \ +// RUN: -ccc-install-dir %S/Inputs/ohos_native_tree/llvm/bin \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: --sysroot=%S/Inputs/ohos_native_tree/sysroot \ +// RUN: -march=armv7-a -mcpu=cortex-a7 -mfloat-abi=soft 2>&1\ +// RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB,CHECK-MULTILIB-SF,CHECK-MULTILIB-ARM-A7-SOFT +// RUN: %clang %s -### --target=arm-liteos \ +// RUN: -ccc-install-dir %S/Inputs/ohos_native_tree/llvm/bin \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: --sysroot=%S/Inputs/ohos_native_tree/sysroot \ +// RUN: -march=armv7-a -mcpu=cortex-a7 -mfloat-abi=softfp -mfpu=neon-vfpv4 2>&1\ +// RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB,CHECK-MULTILIB-SF,CHECK-MULTILIB-ARM-A7-SOFTFP +// RUN: %clang %s -### --target=arm-liteos \ +// RUN: -ccc-install-dir %S/Inputs/ohos_native_tree/llvm/bin \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: --sysroot=%S/Inputs/ohos_native_tree/sysroot \ +// RUN: -march=armv7-a -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4 2>&1\ +// RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB,CHECK-MULTILIB-HF,CHECK-MULTILIB-ARM-A7-HARD +// CHECK-MULTILIB: {{.*}}clang{{.*}}" "-cc1" +// CHECK-MULTILIB: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK-MULTILIB: "-isysroot" "[[SYSROOT:[^"]+]]" +// CHECK-MULTILIB: {{.*}}ld.lld{{.*}}" "--sysroot=[[SYSROOT]]" +// CHECK-MULTILIB-SF: "-dynamic-linker" "/lib/ld-musl-arm.so.1" +// CHECK-MULTILIB-HF: "-dynamic-linker" "/lib/ld-musl-armhf.so.1" + +// CHECK-MULTILIB-ARM: "-L[[SYSROOT]]/usr/lib/arm-liteos-ohos/" + +// CHECK-MULTILIB-ARM-A7-SOFT: "-L[[SYSROOT]]/usr/lib/arm-liteos-ohos/a7_soft" + +// CHECK-MULTILIB-ARM-A7-SOFTFP: "-L[[SYSROOT]]/usr/lib/arm-liteos-ohos/a7_softfp_neon-vfpv4" + +// CHECK-MULTILIB-ARM-A7-HARD: "-L[[SYSROOT]]/usr/lib/arm-liteos-ohos/a7_hard_neon-vfpv4" + +// CHECK-MULTILIB-ARM: "[[RESOURCE_DIR]]/lib/arm-liteos-ohos/libclang_rt.builtins.a" +// CHECK-MULTILIB-ARM-A7-SOFT: "[[RESOURCE_DIR]]/lib/arm-liteos-ohos/a7_soft/libclang_rt.builtins.a" +// CHECK-MULTILIB-ARM-A7-SOFTFP: "[[RESOURCE_DIR]]/lib/arm-liteos-ohos/a7_softfp_neon-vfpv4/libclang_rt.builtins.a" +// CHECK-MULTILIB-ARM-A7-HARD: "[[RESOURCE_DIR]]/lib/arm-liteos-ohos/a7_hard_neon-vfpv4/libclang_rt.builtins.a" + +// RUN: %clang %s -### -no-canonical-prefixes --target=arm-linux-ohos -fprofile-instr-generate -v \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: --sysroot=%S/Inputs/ohos_native_tree/sysroot -fuse-ld=lld -march=armv7-a 2>&1 \ +// RUN: | FileCheck -check-prefixes=CHECK-PROFILE-RTLIB %s + +// CHECK-PROFILE-RTLIB: -u__llvm_profile_runtime +// CHECK-PROFILE-RTLIB: libclang_rt.profile + +// RUN: %clang %s -### -o %t.o 2>&1 \ +// RUN: --target=armv7-linux-ohos \ +// RUN: | FileCheck --check-prefix=CHECK-OHOS-WARN-SHARED-TEXTREL %s + +// CHECK-OHOS-WARN-SHARED-TEXTREL: "{{.*}}ld{{(.exe)?}}" +// CHECK-OHOS-WARN-SHARED-TEXTREL: "--warn-shared-textrel" + +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: --target=arm64-linux-ohos -pthread \ +// RUN: --gcc-toolchain="" \ +// RUN: --sysroot=%S/Inputs/ohos_native_tree/sysroot \ +// RUN: -shared \ +// RUN: | FileCheck --check-prefix=CHECK-OHOS-PTHREAD %s + +// CHECK-OHOS-PTHREAD-NOT: -lpthread + diff --git a/clang/test/Driver/ohos.cpp b/clang/test/Driver/ohos.cpp new file mode 100644 index 000000000000..d0fe244c6e78 --- /dev/null +++ b/clang/test/Driver/ohos.cpp @@ -0,0 +1,123 @@ +// RUN: %clangxx %s -### -no-canonical-prefixes --target=arm-liteos -march=armv7-a \ +// RUN: -ccc-install-dir %S/Inputs/ohos_native_tree/llvm/bin \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: --sysroot=%S/Inputs/ohos_native_tree/sysroot -fuse-ld=lld 2>&1 | FileCheck %s +// CHECK: {{.*}}clang{{.*}}" "-cc1" +// CHECK: "-triple" "armv7-unknown-liteos-ohos" +// CHECK-NOT: "-fuse-init-array" +// CHECK: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK: "-isysroot" "[[SYSROOT:[^"]+]]" +// CHECK: "-internal-isystem" "{{.*[/\\]}}include{{/|\\\\}}c++{{/|\\\\}}v1" +// CHECK: "-internal-externc-isystem" "[[SYSROOT]]{{/|\\\\}}include" +// CHECK: {{.*}}ld.lld{{.*}}" "--sysroot=[[SYSROOT]]" +// CHECK: "-pie" +// CHECK: "-z" "noexecstack" +// CHECK-NOT: "--build-id" +// CHECK: "-dynamic-linker" "/lib/ld-musl-arm.so.1" +// CHECK: Scrt1.o +// CHECK: crti.o +// CHECK: clang_rt.crtbegin.o +// CHECK: "-L{{.*[/\\]}}lib/arm-liteos-ohos/c++/" +// CHECK-NOT: "--push-state" +// CHECK-NOT: "--as-needed" +// CHECK: "-lc++" +// CHECK: "-lm" +// CHECK-NOT: "--pop-state" +// CHECK: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}libclang_rt.builtins.a" +// CHECK: "-lc" +// CHECK: clang_rt.crtend.o +// CHECK: crtn.o + +// RUN: %clangxx %s -### --target=arm-unknown-liteos -stdlib=libstdc++ \ +// RUN: -fuse-ld=lld 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CHECK-STDLIB +// CHECK-STDLIB: error: invalid library name in argument '-stdlib=libstdc++' + +// RUN: %clangxx %s -### --target=arm-unknown-liteos -static-libstdc++ \ +// RUN: -fuse-ld=lld 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CHECK-STATIC +// CHECK-STATIC-NOT: "--push-state" +// CHECK-STATIC-NOT: "--as-needed" +// CHECK-STATIC: "-Bstatic" +// CHECK-STATIC: "-lc++" +// CHECK-STATIC: "-Bdynamic" +// CHECK-STATIC: "-lm" +// CHECK-STATIC-NOT: "--pop-state" +// CHECK-STATIC: "-lc" + +// RUN: %clangxx %s -### --target=arm-unknown-liteos -static \ +// RUN: -fuse-ld=lld 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CHECK-STATIC1 +// CHECK-STATIC1-NOT: "-fuse-init-array" +// CHECK-STATIC1: "-Bstatic" +// CHECK-STATIC1: "-lc++" +// CHECK-STATIC1: "-lc++abi" +// CHECK-STATIC1: "-lunwind" +// CHECK-STATIC1: "-lm" +// CHECK-STATIC1: "-lc" + +// RUN: %clangxx %s -### --target=arm-unknown-liteos -march=armv7-a -mfloat-abi=soft -static -fPIE -fPIC -fpic -pie \ +// RUN: --sysroot=%S/Inputs/ohos_native_tree/sysroot -fuse-ld=lld 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CHECK-STATIC2 +// CHECK-STATIC2: "-isysroot" "[[SYSROOT:[^"]+]]" +// CHECK-STATIC2: {{.*}}ld.lld{{.*}}" "--sysroot=[[SYSROOT]]" +// CHECK-STATIC2: "-Bstatic" +// CHECK-STATIC2: "-lc++" +// CHECK-STATIC2: "-lc++abi" +// CHECK-STATIC2: "-lunwind" +// CHECK-STATIC2: "-lm" +// CHECK-STATIC2: "-lc" + +// RUN: %clangxx %s -### --target=arm-liteos -nostdlib++ -fuse-ld=lld 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CHECK-NOSTDLIBXX +// CHECK-NOSTDLIBXX-NOT: "-lc++" +// CHECK-NOSTDLIBXX: "-lm" +// CHECK-NOSTDLIBXX: "-lc" + +// RUN: %clangxx %s -### --target=arm-liteos \ +// RUN: -ccc-install-dir %S/Inputs/ohos_native_tree/llvm/bin \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: --sysroot=%S/Inputs/ohos_native_tree/sysroot \ +// RUN: -march=armv7-a -mfloat-abi=soft 2>&1\ +// RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB,CHECK-MULTILIB-SF,CHECK-MULTILIB-ARM +// RUN: %clangxx %s -### --target=arm-liteos \ +// RUN: -ccc-install-dir %S/Inputs/ohos_native_tree/llvm/bin \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: --sysroot=%S/Inputs/ohos_native_tree/sysroot \ +// RUN: -march=armv7-a -mcpu=cortex-a7 -mfloat-abi=soft 2>&1\ +// RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB,CHECK-MULTILIB-SF,CHECK-MULTILIB-ARM-A7-SOFT +// RUN: %clangxx %s -### --target=arm-liteos \ +// RUN: -ccc-install-dir %S/Inputs/ohos_native_tree/llvm/bin \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: --sysroot=%S/Inputs/ohos_native_tree/sysroot \ +// RUN: -march=armv7-a -mcpu=cortex-a7 -mfloat-abi=softfp -mfpu=neon-vfpv4 2>&1\ +// RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB,CHECK-MULTILIB-SF,CHECK-MULTILIB-ARM-A7-SOFTFP +// RUN: %clangxx %s -### --target=arm-liteos \ +// RUN: -ccc-install-dir %S/Inputs/ohos_native_tree/llvm/bin \ +// RUN: -resource-dir=%S/Inputs/ohos_native_tree/llvm/lib/clang/x.y.z \ +// RUN: --sysroot=%S/Inputs/ohos_native_tree/sysroot \ +// RUN: -march=armv7-a -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4 2>&1\ +// RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB,CHECK-MULTILIB-HF,CHECK-MULTILIB-ARM-A7-HARD +// CHECK-MULTILIB: {{.*}}clang{{.*}}" "-cc1" +// CHECK-MULTILIB: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK-MULTILIB: "-isysroot" "[[SYSROOT:[^"]+]]" +// CHECK-MULTILIB: {{.*}}ld.lld{{.*}}" "--sysroot=[[SYSROOT]]" +// CHECK-MULTILIB-SF: "-dynamic-linker" "/lib/ld-musl-arm.so.1" +// CHECK-MULTILIB-HF: "-dynamic-linker" "/lib/ld-musl-armhf.so.1" + +// CHECK-MULTILIB-ARM: "-L{{.*}}{{/|\\\\}}..{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}c++/" +// CHECK-MULTILIB-ARM: "-L[[SYSROOT]]/usr/lib/arm-liteos-ohos/" + +// CHECK-MULTILIB-ARM-A7-SOFT: "-L{{.*}}{{/|\\\\}}..{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}c++/a7_soft" +// CHECK-MULTILIB-ARM-A7-SOFT: "-L[[SYSROOT]]/usr/lib/arm-liteos-ohos/a7_soft" + +// CHECK-MULTILIB-ARM-A7-SOFTFP: "-L{{.*}}{{/|\\\\}}..{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}c++{{/|\\\\}}a7_softfp_neon-vfpv4" +// CHECK-MULTILIB-ARM-A7-SOFTFP: "-L[[SYSROOT]]/usr/lib/arm-liteos-ohos/a7_softfp_neon-vfpv4" + +// CHECK-MULTILIB-ARM-A7-HARD: "-L{{.*}}{{/|\\\\}}..{{/|\\\\}}lib{{/|\\\\}}arm-liteos-ohos{{/|\\\\}}c++{{/|\\\\}}a7_hard_neon-vfpv4" +// CHECK-MULTILIB-ARM-A7-HARD: "-L[[SYSROOT]]/usr/lib/arm-liteos-ohos/a7_hard_neon-vfpv4" + +// CHECK-MULTILIB-ARM: "[[RESOURCE_DIR]]/lib/arm-liteos-ohos/libclang_rt.builtins.a" +// CHECK-MULTILIB-ARM-A7-SOFT: "[[RESOURCE_DIR]]/lib/arm-liteos-ohos/a7_soft/libclang_rt.builtins.a" +// CHECK-MULTILIB-ARM-A7-SOFTFP: "[[RESOURCE_DIR]]/lib/arm-liteos-ohos/a7_softfp_neon-vfpv4/libclang_rt.builtins.a" +// CHECK-MULTILIB-ARM-A7-HARD: "[[RESOURCE_DIR]]/lib/arm-liteos-ohos/a7_hard_neon-vfpv4/libclang_rt.builtins.a" diff --git a/clang/test/Preprocessor/ohos.c b/clang/test/Preprocessor/ohos.c new file mode 100644 index 000000000000..bd1060133c4e --- /dev/null +++ b/clang/test/Preprocessor/ohos.c @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=arm-linux-ohos < /dev/null | FileCheck %s -match-full-lines -check-prefix=ARM-OHOS-CXX +// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=aarch64-linux-ohos < /dev/null | FileCheck %s -match-full-lines -check-prefix=ARM64-OHOS-CXX +// RUN: %clang_cc1 -E -dM -ffreestanding -triple=arm-linux-ohos < /dev/null | FileCheck %s -check-prefix=OHOS-DEFS + +// ARM-HOS-CXX: #define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 8U +// ARM-OHOS-CXX: #define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 8U +// ARM64-HOS-CXX: #define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 16UL +// ARM64-OHOS-CXX: #define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 16UL +// OHOS-DEFS: __OHOS_FAMILY__ +// OHOS-DEFS: __OHOS__ +// OHOS-DEFS-NOT: __OHOS__ diff --git a/clang/unittests/CMakeLists.txt b/clang/unittests/CMakeLists.txt index bb635dfff991..bcb84f1d3d7c 100644 --- a/clang/unittests/CMakeLists.txt +++ b/clang/unittests/CMakeLists.txt @@ -39,7 +39,9 @@ add_subdirectory(CodeGen) if(NOT WIN32 AND CLANG_TOOL_LIBCLANG_BUILD) add_subdirectory(libclang) endif() -add_subdirectory(DirectoryWatcher) +if (NOT APPLE) + add_subdirectory(DirectoryWatcher) +endif() add_subdirectory(Rename) add_subdirectory(Index) add_subdirectory(Serialization) diff --git a/compiler-rt/CMakeLists.txt b/compiler-rt/CMakeLists.txt index b44ad2c2118e..732e8863ed32 100644 --- a/compiler-rt/CMakeLists.txt +++ b/compiler-rt/CMakeLists.txt @@ -120,7 +120,14 @@ if ("${COMPILER_RT_DEFAULT_TARGET_TRIPLE}" MATCHES ".*android.*") string(REGEX MATCH "-target(=| +)[^ ]+android[a-z]*([0-9]+)" ANDROID_API_LEVEL "${CMAKE_C_FLAGS}") set(ANDROID_API_LEVEL ${CMAKE_MATCH_2}) endif() + +# We define OHOS for ohos targets for now +if (OHOS) + set(OHOS_FAMILY 1) +endif() + pythonize_bool(ANDROID) +pythonize_bool(OHOS_FAMILY) set(COMPILER_RT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(COMPILER_RT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) @@ -131,7 +138,7 @@ pythonize_bool(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR) # and target a UNIX-like system or Windows. # We can run tests on Android even when we are cross-compiling. if(("${CMAKE_HOST_SYSTEM}" STREQUAL "${CMAKE_SYSTEM}" AND (UNIX OR WIN32)) OR ANDROID - OR COMPILER_RT_EMULATOR) + OR COMPILER_RT_EMULATOR OR OHOS) option(COMPILER_RT_CAN_EXECUTE_TESTS "Can we execute instrumented tests" ON) else() option(COMPILER_RT_CAN_EXECUTE_TESTS "Can we execute instrumented tests" OFF) @@ -235,7 +242,7 @@ option(SANITIZER_USE_STATIC_CXX_ABI "Use static libc++abi." ${DEFAULT_SANITIZER_USE_STATIC_CXX_ABI}) set(DEFAULT_COMPILER_RT_USE_BUILTINS_LIBRARY OFF) -if (FUCHSIA) +if (FUCHSIA OR OHOS) set(DEFAULT_COMPILER_RT_USE_BUILTINS_LIBRARY ON) endif() @@ -441,24 +448,9 @@ if("${CMAKE_SYSTEM_NAME}" STREQUAL "Fuchsia") list(APPEND SANITIZER_COMMON_LINK_LIBS zircon) endif() -# TODO: COMPILER_RT_COMMON_CFLAGS and COMPILER_RT_COMMON_LINK_FLAGS are -# intended for use in non-sanitizer runtimes such as libFuzzer, profile or XRay, -# move these higher to include common flags, then derive SANITIZER_COMMON_CFLAGS -# and SANITIZER_COMMON_LINK_FLAGS from those and append sanitizer-specific flags. -set(COMPILER_RT_COMMON_CFLAGS ${SANITIZER_COMMON_CFLAGS}) -set(COMPILER_RT_COMMON_LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS}) - -# We don't use the C++ standard library, so avoid including it by mistake. -append_list_if(COMPILER_RT_HAS_NOSTDINCXX_FLAG -nostdinc++ SANITIZER_COMMON_CFLAGS) -append_list_if(COMPILER_RT_HAS_NOSTDLIBXX_FLAG -nostdlib++ SANITIZER_COMMON_LINK_FLAGS) - -# Remove -stdlib= which is unused when passing -nostdinc++... -string(REGEX MATCHALL "-stdlib=[a-zA-Z+]*" stdlib_flag "${CMAKE_CXX_FLAGS}") -string(REGEX REPLACE "-stdlib=[a-zA-Z+]*" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - -# ...we need it to build some runtimes and tests so readd it where appropriate. -list(APPEND COMPILER_RT_COMMON_CFLAGS ${stdlib_flag}) -list(APPEND COMPILER_RT_COMMON_LINK_FLAGS ${stdlib_flag}) +if (OHOS) + list(APPEND SANITIZER_COMMON_LINK_LIBS unwind) +endif() macro(append_libcxx_libs var) if (${var}_INTREE) diff --git a/compiler-rt/cmake/Modules/AddCompilerRT.cmake b/compiler-rt/cmake/Modules/AddCompilerRT.cmake index 361538a58e47..3fb062f78f70 100644 --- a/compiler-rt/cmake/Modules/AddCompilerRT.cmake +++ b/compiler-rt/cmake/Modules/AddCompilerRT.cmake @@ -239,9 +239,9 @@ function(add_compiler_rt_runtime name type) NOT name STREQUAL "clang_rt.builtins") get_compiler_rt_target(${arch} target) find_compiler_rt_library(builtins ${target} builtins_${libname}) - if(builtins_${libname} STREQUAL "NOTFOUND") - message(FATAL_ERROR "Cannot find builtins library for the target architecture") - endif() + #if(builtins_${libname} STREQUAL "NOTFOUND") + # message(FATAL_ERROR "Cannot find builtins library for the target architecture") + #endif() endif() set(sources_${libname} ${LIB_SOURCES}) format_object_libs(sources_${libname} ${arch} ${LIB_OBJECT_LIBS}) diff --git a/compiler-rt/cmake/Modules/CompilerRTUtils.cmake b/compiler-rt/cmake/Modules/CompilerRTUtils.cmake index f61d487e93a0..00bec8bdb846 100644 --- a/compiler-rt/cmake/Modules/CompilerRTUtils.cmake +++ b/compiler-rt/cmake/Modules/CompilerRTUtils.cmake @@ -378,7 +378,11 @@ endfunction() function(get_compiler_rt_install_dir arch install_dir) if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE) get_compiler_rt_target(${arch} target) - set(${install_dir} ${COMPILER_RT_INSTALL_PATH}/lib/${target} PARENT_SCOPE) + if(OHOS) + set(${install_dir} ${COMPILER_RT_INSTALL_PATH}/lib/${target}/${LLVM_TARGET_MULTILIB_SUFFIX} PARENT_SCOPE) + else() + set(${install_dir} ${COMPILER_RT_INSTALL_PATH}/lib/${target} PARENT_SCOPE) + endif() else() set(${install_dir} ${COMPILER_RT_LIBRARY_INSTALL_DIR} PARENT_SCOPE) endif() @@ -387,7 +391,11 @@ endfunction() function(get_compiler_rt_output_dir arch output_dir) if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE) get_compiler_rt_target(${arch} target) - set(${output_dir} ${COMPILER_RT_OUTPUT_DIR}/lib/${target} PARENT_SCOPE) + if(OHOS) + set(${output_dir} ${COMPILER_RT_OUTPUT_DIR}/lib/${target}/${LLVM_TARGET_MULTILIB_SUFFIX} PARENT_SCOPE) + else() + set(${output_dir} ${COMPILER_RT_OUTPUT_DIR}/lib/${target} PARENT_SCOPE) + endif() else() set(${output_dir} ${COMPILER_RT_LIBRARY_OUTPUT_DIR} PARENT_SCOPE) endif() diff --git a/compiler-rt/cmake/base-config-ix.cmake b/compiler-rt/cmake/base-config-ix.cmake index 1edab43e7c0d..61e7e0084ba3 100644 --- a/compiler-rt/cmake/base-config-ix.cmake +++ b/compiler-rt/cmake/base-config-ix.cmake @@ -165,6 +165,9 @@ macro(test_targets) # Examine compiler output to determine target architecture. detect_target_arch() set(COMPILER_RT_OS_SUFFIX "-android") + elseif(OHOS) + detect_target_arch() + set(COMPILER_RT_OS_SUFFIX "") elseif(NOT APPLE) # Supported archs for Apple platforms are generated later if(COMPILER_RT_DEFAULT_TARGET_ONLY) add_default_target_arch(${COMPILER_RT_DEFAULT_TARGET_ARCH}) diff --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake index f81b8384cbd5..347de3a08bb6 100644 --- a/compiler-rt/cmake/config-ix.cmake +++ b/compiler-rt/cmake/config-ix.cmake @@ -50,6 +50,8 @@ if (COMPILER_RT_HAS_NODEFAULTLIBS_FLAG) shell32 user32 kernel32 mingw32 ${MINGW_RUNTIME} moldname mingwex msvcrt) list(APPEND CMAKE_REQUIRED_LIBRARIES ${MINGW_LIBRARIES}) + elseif (OHOS) + list(APPEND CMAKE_REQUIRED_LIBRARIES unwind) endif() endif () @@ -128,9 +130,13 @@ check_include_files("sys/auxv.h" COMPILER_RT_HAS_AUXV) # Libraries. check_library_exists(dl dlopen "" COMPILER_RT_HAS_LIBDL) -check_library_exists(rt shm_open "" COMPILER_RT_HAS_LIBRT) +if (NOT OHOS) + check_library_exists(rt shm_open "" COMPILER_RT_HAS_LIBRT) +endif() check_library_exists(m pow "" COMPILER_RT_HAS_LIBM) -check_library_exists(pthread pthread_create "" COMPILER_RT_HAS_LIBPTHREAD) +if (NOT OHOS) + check_library_exists(pthread pthread_create "" COMPILER_RT_HAS_LIBPTHREAD) +endif() check_library_exists(execinfo backtrace "" COMPILER_RT_HAS_LIBEXECINFO) # Look for terminfo library, used in unittests that depend on LLVMSupport. @@ -159,8 +165,11 @@ check_library_exists(stdc++ __cxa_throw "" COMPILER_RT_HAS_LIBSTDCXX) check_linker_flag("-Wl,-z,text" COMPILER_RT_HAS_Z_TEXT) check_linker_flag("-fuse-ld=lld" COMPILER_RT_HAS_FUSE_LD_LLD_FLAG) -set(VERS_COMPAT_OPTION "-Wl,-z,gnu-version-script-compat") -check_linker_flag("${VERS_COMPAT_OPTION}" COMPILER_RT_HAS_GNU_VERSION_SCRIPT_COMPAT) +if (NOT OHOS) + # lld fails to link when this option is passed + set(VERS_COMPAT_OPTION "-Wl,-z,gnu-version-script-compat") + check_linker_flag("${VERS_COMPAT_OPTION}" COMPILER_RT_HAS_GNU_VERSION_SCRIPT_COMPAT) +endif() set(DUMMY_VERS ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/dummy.vers) file(WRITE ${DUMMY_VERS} "{};") @@ -312,9 +321,9 @@ if(OS_NAME MATCHES "Linux") set(ALL_FUZZER_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM64} ${S390X}) elseif (OS_NAME MATCHES "Windows") set(ALL_FUZZER_SUPPORTED_ARCH ${X86} ${X86_64}) -elseif(OS_NAME MATCHES "Android") +elseif(OS_NAME MATCHES "Android" OR OS_NAME MATCHES "OHOS") set(ALL_FUZZER_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64}) -else() +else () set(ALL_FUZZER_SUPPORTED_ARCH ${X86_64} ${ARM64}) endif() @@ -646,7 +655,7 @@ set(COMPILER_RT_SANITIZERS_TO_BUILD all CACHE STRING list_replace(COMPILER_RT_SANITIZERS_TO_BUILD all "${ALL_SANITIZERS}") if (SANITIZER_COMMON_SUPPORTED_ARCH AND NOT LLVM_USE_SANITIZER AND - (OS_NAME MATCHES "Android|Darwin|Linux|FreeBSD|NetBSD|Fuchsia|SunOS" OR + (OS_NAME MATCHES "Android|Darwin|Linux|FreeBSD|NetBSD|Fuchsia|SunOS|OHOS" OR (OS_NAME MATCHES "Windows" AND NOT CYGWIN AND (NOT MINGW OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")))) set(COMPILER_RT_HAS_SANITIZER_COMMON TRUE) @@ -666,17 +675,17 @@ else() set(COMPILER_RT_HAS_ASAN FALSE) endif() -if (OS_NAME MATCHES "Linux|FreeBSD|Windows|NetBSD|SunOS") +if (OS_NAME MATCHES "Linux|FreeBSD|Windows|NetBSD|SunOS|OHOS") set(COMPILER_RT_ASAN_HAS_STATIC_RUNTIME TRUE) -else() +else () set(COMPILER_RT_ASAN_HAS_STATIC_RUNTIME FALSE) endif() # TODO: Add builtins support. -if (CRT_SUPPORTED_ARCH AND OS_NAME MATCHES "Linux" AND NOT LLVM_USE_SANITIZER) +if (CRT_SUPPORTED_ARCH AND OS_NAME MATCHES "Linux|OHOS" AND NOT LLVM_USE_SANITIZER) set(COMPILER_RT_HAS_CRT TRUE) -else() +else () set(COMPILER_RT_HAS_CRT FALSE) endif() @@ -702,7 +711,7 @@ else() endif() if (COMPILER_RT_HAS_SANITIZER_COMMON AND HWASAN_SUPPORTED_ARCH AND - OS_NAME MATCHES "Linux|Android") + OS_NAME MATCHES "Linux|Android|OHOS") set(COMPILER_RT_HAS_HWASAN TRUE) else() set(COMPILER_RT_HAS_HWASAN FALSE) @@ -716,28 +725,28 @@ else() endif() if (PROFILE_SUPPORTED_ARCH AND NOT LLVM_USE_SANITIZER AND - OS_NAME MATCHES "Darwin|Linux|FreeBSD|Windows|Android|Fuchsia|SunOS|NetBSD|AIX") + OS_NAME MATCHES "Darwin|Linux|FreeBSD|Windows|Android|Fuchsia|SunOS|NetBSD|OHOS") set(COMPILER_RT_HAS_PROFILE TRUE) else() set(COMPILER_RT_HAS_PROFILE FALSE) endif() if (COMPILER_RT_HAS_SANITIZER_COMMON AND TSAN_SUPPORTED_ARCH AND - OS_NAME MATCHES "Darwin|Linux|FreeBSD|Android|NetBSD") + OS_NAME MATCHES "Darwin|Linux|FreeBSD|Android|NetBSD|OHOS") set(COMPILER_RT_HAS_TSAN TRUE) else() set(COMPILER_RT_HAS_TSAN FALSE) endif() if (COMPILER_RT_HAS_SANITIZER_COMMON AND UBSAN_SUPPORTED_ARCH AND - OS_NAME MATCHES "Darwin|Linux|FreeBSD|NetBSD|Windows|Android|Fuchsia|SunOS") + OS_NAME MATCHES "Darwin|Linux|FreeBSD|NetBSD|Windows|Android|Fuchsia|SunOS|OHOS") set(COMPILER_RT_HAS_UBSAN TRUE) else() set(COMPILER_RT_HAS_UBSAN FALSE) endif() if (COMPILER_RT_HAS_SANITIZER_COMMON AND UBSAN_SUPPORTED_ARCH AND - OS_NAME MATCHES "Linux|FreeBSD|NetBSD|Android|Darwin") + OS_NAME MATCHES "Linux|FreeBSD|NetBSD|Android|Darwin|OHOS") set(COMPILER_RT_HAS_UBSAN_MINIMAL TRUE) else() set(COMPILER_RT_HAS_UBSAN_MINIMAL FALSE) @@ -765,7 +774,7 @@ else() endif() if (COMPILER_RT_HAS_SANITIZER_COMMON AND SCUDO_SUPPORTED_ARCH AND - OS_NAME MATCHES "Linux|Android|Fuchsia") + OS_NAME MATCHES "Linux|Android|Fuchsia|OHOS") set(COMPILER_RT_HAS_SCUDO TRUE) else() set(COMPILER_RT_HAS_SCUDO FALSE) @@ -779,14 +788,14 @@ else() endif() if (COMPILER_RT_HAS_SANITIZER_COMMON AND FUZZER_SUPPORTED_ARCH AND - OS_NAME MATCHES "Android|Darwin|Linux|NetBSD|FreeBSD|Fuchsia|Windows") + OS_NAME MATCHES "Android|Darwin|Linux|NetBSD|FreeBSD|Fuchsia|Windows|OHOS") set(COMPILER_RT_HAS_FUZZER TRUE) else() set(COMPILER_RT_HAS_FUZZER FALSE) endif() if (COMPILER_RT_HAS_SANITIZER_COMMON AND SHADOWCALLSTACK_SUPPORTED_ARCH AND - OS_NAME MATCHES "Linux|Android") + OS_NAME MATCHES "Linux|Android|OHOS") set(COMPILER_RT_HAS_SHADOWCALLSTACK TRUE) else() set(COMPILER_RT_HAS_SHADOWCALLSTACK FALSE) diff --git a/compiler-rt/lib/asan/asan_allocator.h b/compiler-rt/lib/asan/asan_allocator.h index 2963e979b55c..a56e1ea43c22 100644 --- a/compiler-rt/lib/asan/asan_allocator.h +++ b/compiler-rt/lib/asan/asan_allocator.h @@ -128,7 +128,7 @@ typedef DefaultSizeClassMap SizeClassMap; const uptr kAllocatorSpace = ~(uptr)0; const uptr kAllocatorSize = 0x20000000000ULL; // 2T. typedef DefaultSizeClassMap SizeClassMap; -# elif defined(__aarch64__) && SANITIZER_ANDROID +#elif defined(__aarch64__) && (SANITIZER_ANDROID || SANITIZER_OHOS) // Android needs to support 39, 42 and 48 bit VMA. const uptr kAllocatorSpace = ~(uptr)0; const uptr kAllocatorSize = 0x2000000000ULL; // 128G. diff --git a/compiler-rt/lib/asan/asan_internal.h b/compiler-rt/lib/asan/asan_internal.h index cfb54927c6cf..100754da08e4 100644 --- a/compiler-rt/lib/asan/asan_internal.h +++ b/compiler-rt/lib/asan/asan_internal.h @@ -35,7 +35,7 @@ // If set, values like allocator chunk size, as well as defaults for some flags // will be changed towards less memory overhead. #ifndef ASAN_LOW_MEMORY -# if SANITIZER_IOS || SANITIZER_ANDROID || SANITIZER_RTEMS +#if SANITIZER_IOS || SANITIZER_ANDROID || SANITIZER_RTEMS || SANITIZER_OHOS # define ASAN_LOW_MEMORY 1 # else # define ASAN_LOW_MEMORY 0 diff --git a/compiler-rt/lib/asan/asan_linux.cpp b/compiler-rt/lib/asan/asan_linux.cpp index 4bcbe5d02e33..09dc9a798387 100644 --- a/compiler-rt/lib/asan/asan_linux.cpp +++ b/compiler-rt/lib/asan/asan_linux.cpp @@ -45,7 +45,8 @@ #include #endif -#if SANITIZER_ANDROID || SANITIZER_FREEBSD || SANITIZER_SOLARIS +#if SANITIZER_ANDROID || SANITIZER_FREEBSD || SANITIZER_SOLARIS || \ + SANITIZER_OHOS #include extern "C" void* _DYNAMIC; #elif SANITIZER_NETBSD @@ -121,7 +122,7 @@ void FlushUnneededASanShadowMemory(uptr p, uptr size) { ReleaseMemoryPagesToOS(MemToShadow(p), MemToShadow(p + size)); } -#if SANITIZER_ANDROID +#if SANITIZER_ANDROID || SANITIZER_OHOS // FIXME: should we do anything for Android? void AsanCheckDynamicRTPrereqs() {} void AsanCheckIncompatibleRT() {} @@ -214,7 +215,7 @@ void AsanCheckIncompatibleRT() { } #endif // SANITIZER_ANDROID -#if !SANITIZER_ANDROID +#if !SANITIZER_ANDROID && !SANITIZER_OHOS void ReadContextStack(void *context, uptr *stack, uptr *ssize) { ucontext_t *ucp = (ucontext_t*)context; *stack = (uptr)ucp->uc_stack.ss_sp; diff --git a/compiler-rt/lib/asan/tests/asan_test.cpp b/compiler-rt/lib/asan/tests/asan_test.cpp index c0b79bba48ff..25f5b5a44416 100644 --- a/compiler-rt/lib/asan/tests/asan_test.cpp +++ b/compiler-rt/lib/asan/tests/asan_test.cpp @@ -1322,7 +1322,9 @@ TEST(AddressSanitizer, LongDoubleNegativeTest) { memcpy(Ident(&c), Ident(&b), sizeof(long double)); } -#if !defined(_WIN32) +#if !defined(_WIN32) && !defined(__OHOS__) +// On OHOS/Musl sched_param is not int. +// See __interceptor_pthread_getschedparam TEST(AddressSanitizer, pthread_getschedparam) { int policy; struct sched_param param; diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt index 73b6bead8424..6088cce8f8dd 100644 --- a/compiler-rt/lib/builtins/CMakeLists.txt +++ b/compiler-rt/lib/builtins/CMakeLists.txt @@ -693,6 +693,7 @@ else () foreach (arch ${BUILTIN_SUPPORTED_ARCH}) if (CAN_TARGET_${arch}) + set(BUILTIN_CFLAGS_${arch} ${BUILTIN_CFLAGS}) # For ARM archs, exclude any VFP builtins if VFP is not supported if (${arch} MATCHES "^(arm|armhf|armv7|armv7s|armv7k|armv7m|armv7em)$") string(REPLACE ";" " " _TARGET_${arch}_CFLAGS "${TARGET_${arch}_CFLAGS}") @@ -717,13 +718,13 @@ else () # Needed for clear_cache on debug mode, due to r7's usage in inline asm. # Release mode already sets it via -O2/3, Debug mode doesn't. if (${arch} STREQUAL "armhf") - list(APPEND BUILTIN_CFLAGS -fomit-frame-pointer -DCOMPILER_RT_ARMHF_TARGET) + list(APPEND BUILTIN_CFLAGS_${arch} -fomit-frame-pointer -DCOMPILER_RT_ARMHF_TARGET) endif() # For RISCV32, we must force enable int128 for compiling long # double routines. if("${arch}" STREQUAL "riscv32") - list(APPEND BUILTIN_CFLAGS -fforce-enable-int128) + list(APPEND BUILTIN_CFLAGS_${arch} -fforce-enable-int128) endif() add_compiler_rt_runtime(clang_rt.builtins @@ -731,7 +732,7 @@ else () ARCHS ${arch} SOURCES ${${arch}_SOURCES} DEFS ${BUILTIN_DEFS} - CFLAGS ${BUILTIN_CFLAGS} + CFLAGS ${BUILTIN_CFLAGS_${arch}} PARENT_TARGET builtins) endif () endforeach () diff --git a/compiler-rt/lib/builtins/divtf3.c b/compiler-rt/lib/builtins/divtf3.c index 5bcc9a8e4aa1..809c5a4f4adb 100644 --- a/compiler-rt/lib/builtins/divtf3.c +++ b/compiler-rt/lib/builtins/divtf3.c @@ -16,7 +16,7 @@ #if defined(CRT_HAS_128BIT) && defined(CRT_LDBL_128BIT) -#define NUMBER_OF_HALF_ITERATIONS 4 +#define NUMBER_OF_HALF_ITERATIONS 5 #define NUMBER_OF_FULL_ITERATIONS 1 #include "fp_div_impl.inc" diff --git a/compiler-rt/lib/builtins/fp_div_impl.inc b/compiler-rt/lib/builtins/fp_div_impl.inc index 29bcd1920edf..b49a6fd2bd73 100644 --- a/compiler-rt/lib/builtins/fp_div_impl.inc +++ b/compiler-rt/lib/builtins/fp_div_impl.inc @@ -325,7 +325,7 @@ static __inline fp_t __divXf3__(fp_t a, fp_t b) { #define RECIPROCAL_PRECISION REP_C(10) #elif defined(DOUBLE_PRECISION) && NUMBER_OF_HALF_ITERATIONS == 3 && NUMBER_OF_FULL_ITERATIONS == 1 #define RECIPROCAL_PRECISION REP_C(220) -#elif defined(QUAD_PRECISION) && NUMBER_OF_HALF_ITERATIONS == 4 && NUMBER_OF_FULL_ITERATIONS == 1 +#elif defined(QUAD_PRECISION) && NUMBER_OF_HALF_ITERATIONS == 5 && NUMBER_OF_FULL_ITERATIONS == 1 #define RECIPROCAL_PRECISION REP_C(13922) #else #error Invalid number of iterations diff --git a/compiler-rt/lib/builtins/int_util.h b/compiler-rt/lib/builtins/int_util.h index c372c2edc637..c95c728598fb 100644 --- a/compiler-rt/lib/builtins/int_util.h +++ b/compiler-rt/lib/builtins/int_util.h @@ -40,6 +40,10 @@ NORETURN void __compilerrt_abort_impl(const char *file, int line, #define REPEAT_4_TIMES(code_to_repeat) \ REPEAT_3_TIMES(code_to_repeat) \ code_to_repeat +#define REPEAT_5_TIMES(code_to_repeat) \ + REPEAT_4_TIMES(code_to_repeat) \ + code_to_repeat + #define REPEAT_N_TIMES_(N, code_to_repeat) REPEAT_##N##_TIMES(code_to_repeat) #define REPEAT_N_TIMES(N, code_to_repeat) REPEAT_N_TIMES_(N, code_to_repeat) diff --git a/compiler-rt/lib/cfi/CMakeLists.txt b/compiler-rt/lib/cfi/CMakeLists.txt index 9a641d33ac48..1cc0b3cb6087 100644 --- a/compiler-rt/lib/cfi/CMakeLists.txt +++ b/compiler-rt/lib/cfi/CMakeLists.txt @@ -1,6 +1,6 @@ add_compiler_rt_component(cfi) -if(OS_NAME MATCHES "Linux" OR OS_NAME MATCHES "FreeBSD" OR OS_NAME MATCHES "NetBSD") +if(OS_NAME MATCHES "Linux" OR OS_NAME MATCHES "FreeBSD" OR OS_NAME MATCHES "NetBSD" OR OS_NAME MATCHES "OHOS") set(CFI_SOURCES cfi.cpp ) diff --git a/compiler-rt/lib/fuzzer/FuzzerInterceptors.cpp b/compiler-rt/lib/fuzzer/FuzzerInterceptors.cpp index b87798603fda..cb2d1e5843f9 100644 --- a/compiler-rt/lib/fuzzer/FuzzerInterceptors.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerInterceptors.cpp @@ -25,6 +25,7 @@ } #include +#include #include #include // for dlsym() diff --git a/compiler-rt/lib/hwasan/hwasan.cpp b/compiler-rt/lib/hwasan/hwasan.cpp index c5322110cb66..5d301bb90ae4 100644 --- a/compiler-rt/lib/hwasan/hwasan.cpp +++ b/compiler-rt/lib/hwasan/hwasan.cpp @@ -76,7 +76,7 @@ static void InitializeFlags() { cf.intercept_tls_get_addr = true; cf.exitcode = 99; // 8 shadow pages ~512kB, small enough to cover common stack sizes. - cf.clear_shadow_mmap_threshold = 4096 * (SANITIZER_ANDROID ? 2 : 8); + cf.clear_shadow_mmap_threshold = 4096 * ((SANITIZER_ANDROID) ? 2 : 8); // Sigtrap is used in error reporting. cf.handle_sigtrap = kHandleSignalExclusive; diff --git a/compiler-rt/lib/hwasan/hwasan_dynamic_shadow.cpp b/compiler-rt/lib/hwasan/hwasan_dynamic_shadow.cpp index 12730b29bae3..d99ff482eed1 100644 --- a/compiler-rt/lib/hwasan/hwasan_dynamic_shadow.cpp +++ b/compiler-rt/lib/hwasan/hwasan_dynamic_shadow.cpp @@ -24,7 +24,7 @@ // The code in this file needs to run in an unrelocated binary. It should not // access any external symbol, including its own non-hidden globals. -#if SANITIZER_ANDROID +#if SANITIZER_ANDROID || SANITIZER_OHOS extern "C" { INTERFACE_ATTRIBUTE void __hwasan_shadow(); diff --git a/compiler-rt/lib/interception/interception.h b/compiler-rt/lib/interception/interception.h index cb0b5284ed26..9536a3d52ce4 100644 --- a/compiler-rt/lib/interception/interception.h +++ b/compiler-rt/lib/interception/interception.h @@ -16,8 +16,8 @@ #include "sanitizer_common/sanitizer_internal_defs.h" -#if !SANITIZER_LINUX && !SANITIZER_FREEBSD && !SANITIZER_MAC && \ - !SANITIZER_NETBSD && !SANITIZER_WINDOWS && \ +#if !SANITIZER_LINUX && !SANITIZER_FREEBSD && !SANITIZER_MAC && \ + !SANITIZER_NETBSD && !SANITIZER_WINDOWS && !SANITIZER_OHOS && \ !SANITIZER_FUCHSIA && !SANITIZER_RTEMS && !SANITIZER_SOLARIS # error "Interception doesn't work on this operating system." #endif diff --git a/compiler-rt/lib/interception/interception_type_test.cpp b/compiler-rt/lib/interception/interception_type_test.cpp index a611604a700c..37f54a79b165 100644 --- a/compiler-rt/lib/interception/interception_type_test.cpp +++ b/compiler-rt/lib/interception/interception_type_test.cpp @@ -31,8 +31,8 @@ COMPILER_CHECK(sizeof(::OFF64_T) == sizeof(off64_t)); // The following are the cases when pread (and friends) is used instead of // pread64. In those cases we need OFF_T to match off_t. We don't care about the // rest (they depend on _FILE_OFFSET_BITS setting when building an application). -# if SANITIZER_ANDROID || !defined _FILE_OFFSET_BITS || \ - _FILE_OFFSET_BITS != 64 +#if SANITIZER_ANDROID || !defined _FILE_OFFSET_BITS || \ + _FILE_OFFSET_BITS != 64 || SANITIZER_OHOS COMPILER_CHECK(sizeof(::OFF_T) == sizeof(off_t)); # endif diff --git a/compiler-rt/lib/lsan/lsan_common.h b/compiler-rt/lib/lsan/lsan_common.h index b0ae6f020b63..3c65d9df225e 100644 --- a/compiler-rt/lib/lsan/lsan_common.h +++ b/compiler-rt/lib/lsan/lsan_common.h @@ -31,7 +31,7 @@ // the new architecture inside the sanitizer library. // Exclude leak-detection on arm32 for Android because `__aeabi_read_tp` // is missing. This caused a link error. -#if SANITIZER_ANDROID && (__ANDROID_API__ < 28 || defined(__arm__)) +#if (SANITIZER_ANDROID && (__ANDROID_API__ < 28 || defined(__arm__))) #define CAN_SANITIZE_LEAKS 0 #elif (SANITIZER_LINUX || SANITIZER_MAC) && (SANITIZER_WORDSIZE == 64) && \ (defined(__x86_64__) || defined(__mips64) || defined(__aarch64__) || \ diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cpp index 3157b35ffaf8..b5b14b921824 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator.cpp @@ -26,7 +26,7 @@ const char *SecondaryAllocatorName = "LargeMmapAllocator"; // ThreadSanitizer for Go uses libc malloc/free. #if defined(SANITIZER_USE_MALLOC) -# if SANITIZER_LINUX && !SANITIZER_ANDROID +#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_OHOS extern "C" void *__libc_malloc(uptr size); # if !SANITIZER_GO extern "C" void *__libc_memalign(uptr alignment, uptr size); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc index d4b9ea5f7f06..37d5dfbc8d89 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -2180,11 +2180,13 @@ INTERCEPTOR(int, clock_gettime, u32 clk_id, void *tp) { } namespace __sanitizer { extern "C" { +#if !SANITIZER_OHOS int real_clock_gettime(u32 clk_id, void *tp) { if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) return internal_clock_gettime(clk_id, tp); return REAL(clock_gettime)(clk_id, tp); } +#endif } // extern "C" } // namespace __sanitizer INTERCEPTOR(int, clock_settime, u32 clk_id, const void *tp) { @@ -2451,7 +2453,7 @@ INTERCEPTOR(int, wait3, int *status, int options, void *rusage) { } return res; } -#if SANITIZER_ANDROID +#if SANITIZER_ANDROID || SANITIZER_OHOS INTERCEPTOR(int, __wait4, int pid, int *status, int options, void *rusage) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, __wait4, pid, status, options, rusage); @@ -3750,7 +3752,7 @@ INTERCEPTOR(char *, strerror, int errnum) { // static storage. #if ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE) || \ SANITIZER_MAC || SANITIZER_ANDROID || SANITIZER_NETBSD || \ - SANITIZER_FREEBSD + SANITIZER_FREEBSD || SANITIZER_OHOS // POSIX version. Spec is not clear on whether buf is NULL-terminated. // At least on OSX, buf contents are valid even when the call fails. INTERCEPTOR(int, strerror_r, int errnum, char *buf, SIZE_T buflen) { diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc index b7da65987557..a546a45293a9 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc @@ -98,7 +98,7 @@ static void ioctl_table_fill() { _(SIOCSIFNETMASK, READ, struct_ifreq_sz); #endif -#if (SANITIZER_LINUX && !SANITIZER_ANDROID) +#if (SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_OHOS) _(SIOCGETSGCNT, WRITE, struct_sioc_sg_req_sz); _(SIOCGETVIFCNT, WRITE, struct_sioc_vif_req_sz); #endif diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc index 1b89d6e17684..e5f7af4d107a 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc @@ -2294,7 +2294,7 @@ PRE_SYSCALL(ni_syscall)() {} POST_SYSCALL(ni_syscall)(long res) {} PRE_SYSCALL(ptrace)(long request, long pid, long addr, long data) { -#if !SANITIZER_ANDROID && \ +#if !SANITIZER_ANDROID && !SANITIZER_OHOS && \ (defined(__i386) || defined(__x86_64) || defined(__mips64) || \ defined(__powerpc64__) || defined(__aarch64__) || defined(__s390__) || \ SANITIZER_RISCV64) @@ -2316,7 +2316,7 @@ PRE_SYSCALL(ptrace)(long request, long pid, long addr, long data) { } POST_SYSCALL(ptrace)(long res, long request, long pid, long addr, long data) { -#if !SANITIZER_ANDROID && \ +#if !SANITIZER_ANDROID && !SANITIZER_OHOS && \ (defined(__i386) || defined(__x86_64) || defined(__mips64) || \ defined(__powerpc64__) || defined(__aarch64__) || defined(__s390__) || \ SANITIZER_RISCV64) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_errno.h b/compiler-rt/lib/sanitizer_common/sanitizer_errno.h index 94f16b6e8735..efcc9820bd59 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_errno.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_errno.h @@ -23,8 +23,7 @@ #if SANITIZER_FREEBSD || SANITIZER_MAC # define __errno_location __error -#elif SANITIZER_ANDROID || SANITIZER_NETBSD || \ - SANITIZER_RTEMS +#elif SANITIZER_ANDROID || SANITIZER_NETBSD || SANITIZER_RTEMS # define __errno_location __errno #elif SANITIZER_SOLARIS # define __errno_location ___errno diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc b/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc index cfb5822645f1..32827da14f1b 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc @@ -60,7 +60,8 @@ COMMON_FLAG( "Mention name of executable when reporting error and " "append executable name to logs (as in \"log_path.exe_name.pid\").") COMMON_FLAG( - bool, log_to_syslog, (bool)SANITIZER_ANDROID || (bool)SANITIZER_MAC, + bool, log_to_syslog, + (bool)SANITIZER_ANDROID || (bool)SANITIZER_MAC || (bool)SANITIZER_OHOS, "Write all sanitizer output to syslog in addition to other means of " "logging.") COMMON_FLAG( @@ -230,13 +231,15 @@ COMMON_FLAG(bool, intercept_stat, true, COMMON_FLAG(bool, intercept_send, true, "If set, uses custom wrappers for send* functions " "to find more errors.") -COMMON_FLAG(bool, decorate_proc_maps, (bool)SANITIZER_ANDROID, +COMMON_FLAG(bool, decorate_proc_maps, + (bool)SANITIZER_ANDROID || (bool)SANITIZER_OHOS, "If set, decorate sanitizer mappings in /proc/self/maps with " "user-readable names") COMMON_FLAG(int, exitcode, 1, "Override the program exit status if the tool " "found an error") COMMON_FLAG( - bool, abort_on_error, (bool)SANITIZER_ANDROID || (bool)SANITIZER_MAC, + bool, abort_on_error, + (bool)SANITIZER_ANDROID || (bool)SANITIZER_MAC || (bool)SANITIZER_OHOS, "If set, the tool calls abort() instead of _exit() after printing the " "error report.") COMMON_FLAG(bool, suppress_equal_pcs, true, diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h b/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h index d8f0540037d2..16345fb954fa 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h @@ -168,8 +168,8 @@ typedef long pid_t; typedef int pid_t; #endif -#if SANITIZER_FREEBSD || SANITIZER_NETBSD || \ - SANITIZER_MAC || \ +#if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_MAC || \ + SANITIZER_OHOS || \ (SANITIZER_SOLARIS && (defined(_LP64) || _FILE_OFFSET_BITS == 64)) || \ (SANITIZER_LINUX && defined(__x86_64__)) typedef u64 OFF_T; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp index 379f6d9e294b..bef7eb5d7f52 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp @@ -49,7 +49,6 @@ #include #undef stat #endif - #include #include #include @@ -74,7 +73,7 @@ #include #endif -#if SANITIZER_LINUX && !SANITIZER_ANDROID +#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_OHOS #include #endif @@ -489,7 +488,7 @@ int TgKill(pid_t pid, tid_t tid, int sig) { } #endif -#if !SANITIZER_SOLARIS && !SANITIZER_NETBSD +#if !SANITIZER_SOLARIS && !SANITIZER_NETBSD && !SANITIZER_OHOS u64 NanoTime() { #if SANITIZER_FREEBSD timeval tv; @@ -501,10 +500,19 @@ u64 NanoTime() { return (u64)tv.tv_sec * 1000*1000*1000 + tv.tv_usec * 1000; } +#elif SANITIZER_OHOS +u64 NanoTime() { + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + return (u64)ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec; +} +#endif // !SANITIZER_SOLARIS && !SANITIZER_NETBSD + +#if !SANITIZER_SOLARIS && !SANITIZER_NETBSD && !SANITIZER_OHOS uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp) { return internal_syscall(SYSCALL(clock_gettime), clk_id, tp); } -#endif // !SANITIZER_SOLARIS && !SANITIZER_NETBSD +#endif // Like getenv, but reads env directly from /proc (on Linux) or parses the // 'environ' array (on some others) and does not use libc. This function @@ -822,7 +830,7 @@ int internal_sigaction_norestorer(int signum, const void *act, void *oldact) { // rt_sigaction, so we need to do the same (we'll need to reimplement the // restorers; for x86_64 the restorer address can be obtained from // oldact->sa_restorer upon a call to sigaction(xxx, NULL, oldact). -#if !SANITIZER_ANDROID || !SANITIZER_MIPS32 +#if (!SANITIZER_ANDROID && !SANITIZER_OHOS) || !SANITIZER_MIPS32 k_act.sa_restorer = u_act->sa_restorer; #endif } @@ -838,7 +846,7 @@ int internal_sigaction_norestorer(int signum, const void *act, void *oldact) { internal_memcpy(&u_oldact->sa_mask, &k_oldact.sa_mask, sizeof(__sanitizer_kernel_sigset_t)); u_oldact->sa_flags = k_oldact.sa_flags; -#if !SANITIZER_ANDROID || !SANITIZER_MIPS32 +#if (!SANITIZER_ANDROID && !SANITIZER_OHOS) || !SANITIZER_MIPS32 u_oldact->sa_restorer = k_oldact.sa_restorer; #endif } @@ -1004,7 +1012,7 @@ static uptr GetKernelAreaSize() { if ((segment.end >= 3 * gbyte) && segment.IsWritable()) return 0; } -#if !SANITIZER_ANDROID +#if !SANITIZER_ANDROID && !SANITIZER_OHOS // Even if nothing is mapped, top Gb may still be accessible // if we are running on 64-bit kernel. // Uname may report misleading results if personality type @@ -1765,7 +1773,7 @@ void *internal_start_thread(void *(*func)(void *arg), void *arg) { // Start the thread with signals blocked, otherwise it can steal user signals. __sanitizer_sigset_t set, old; internal_sigfillset(&set); -#if SANITIZER_LINUX && !SANITIZER_ANDROID +#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_OHOS // Glibc uses SIGSETXID signal during setuid call. If this signal is blocked // on any thread, setuid call hangs (see test/tsan/setuid.c). internal_sigdelset(&set, 33); @@ -1795,7 +1803,7 @@ struct __sanitizer_esr_context { static bool Aarch64GetESR(ucontext_t *ucontext, u64 *esr) { static const u32 kEsrMagic = 0x45535201; - u8 *aux = ucontext->uc_mcontext.__reserved; + u8 *aux = (u8 *)ucontext->uc_mcontext.__reserved; while (true) { _aarch64_ctx *ctx = (_aarch64_ctx *)aux; if (ctx->size == 0) break; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.h b/compiler-rt/lib/sanitizer_common/sanitizer_linux.h index 24902d1b6bce..4aefab43b13c 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.h @@ -116,7 +116,7 @@ inline void ReleaseMemoryPagesToOSAndZeroFill(uptr beg, uptr end) { ReleaseMemoryPagesToOS(beg, end); } -#if SANITIZER_ANDROID +#if SANITIZER_ANDROID || SANITIZER_OHOS #if defined(__aarch64__) # define __get_tls() \ diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp index f20b9001c2c2..fe9d80e0e465 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp @@ -75,7 +75,7 @@ struct __sanitizer::linux_dirent { #endif #endif -#if !SANITIZER_ANDROID +#if !SANITIZER_ANDROID && !SANITIZER_OHOS #include #include #endif @@ -803,7 +803,7 @@ void LogMessageOnPrintf(const char *str) { #endif // SANITIZER_LINUX -#if SANITIZER_LINUX && !SANITIZER_GO +#if SANITIZER_LINUX && !SANITIZER_GO && !SANITIZER_OHOS // glibc crashes when using clock_gettime from a preinit_array function as the // vDSO function pointers haven't been initialized yet. __progname is // initialized after the vDSO function pointers, so if it exists, is not null @@ -839,7 +839,11 @@ u64 MonotonicNanoTime() { // Non-Linux & Go always use the syscall. u64 MonotonicNanoTime() { timespec ts; +#if SANITIZER_OHOS + clock_gettime(CLOCK_MONOTONIC, &ts); +#else internal_clock_gettime(CLOCK_MONOTONIC, &ts); +#endif return (u64)ts.tv_sec * (1000ULL * 1000 * 1000) + ts.tv_nsec; } #endif // SANITIZER_LINUX && !SANITIZER_GO diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform.h index 96c01bad870d..8f5f59b34366 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform.h @@ -13,9 +13,9 @@ #define SANITIZER_PLATFORM_H #if !defined(__linux__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && \ - !defined(__APPLE__) && !defined(_WIN32) && \ - !defined(__Fuchsia__) && !defined(__rtems__) && \ - !(defined(__sun__) && defined(__svr4__)) + !defined(__APPLE__) && !defined(_WIN32) && !defined(__OHOS_FAMILY__) && \ + !defined(__Fuchsia__) && !defined(__rtems__) && \ + !(defined(__sun__) && defined(__svr4__)) # error "This operating system is not supported" #endif @@ -105,6 +105,12 @@ # define SANITIZER_ANDROID 0 #endif +#if defined(__OHOS__) +#define SANITIZER_OHOS 1 +#else +#define SANITIZER_OHOS 0 +#endif + #if defined(__Fuchsia__) # define SANITIZER_FUCHSIA 1 #else @@ -238,7 +244,8 @@ // For such platforms build this code with -DSANITIZER_CAN_USE_ALLOCATOR64=0 or // change the definition of SANITIZER_CAN_USE_ALLOCATOR64 here. #ifndef SANITIZER_CAN_USE_ALLOCATOR64 -# if (SANITIZER_ANDROID && defined(__aarch64__)) || SANITIZER_FUCHSIA +#if ((SANITIZER_ANDROID || SANITIZER_OHOS) && defined(__aarch64__)) || \ + SANITIZER_FUCHSIA # define SANITIZER_CAN_USE_ALLOCATOR64 1 # elif defined(__mips64) || defined(__aarch64__) # define SANITIZER_CAN_USE_ALLOCATOR64 0 diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h index 068fc9829e57..70e8a2c197fa 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -58,6 +58,12 @@ #define SI_ANDROID 0 #endif +#if SANITIZER_OHOS +#define SI_OHOS 1 +#else +#define SI_OHOS 0 +#endif + #if SANITIZER_FREEBSD #define SI_FREEBSD 1 #else @@ -271,7 +277,7 @@ #define SANITIZER_INTERCEPT_SYSINFO SI_LINUX #define SANITIZER_INTERCEPT_READDIR SI_POSIX #define SANITIZER_INTERCEPT_READDIR64 SI_LINUX_NOT_ANDROID || SI_SOLARIS32 -#if SI_LINUX_NOT_ANDROID && \ +#if SI_LINUX_NOT_ANDROID && !SI_OHOS && \ (defined(__i386) || defined(__x86_64) || defined(__mips64) || \ defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \ defined(__s390__) || SANITIZER_RISCV64) @@ -341,8 +347,9 @@ #define SANITIZER_INTERCEPT_ETHER_HOST \ (SI_FREEBSD || SI_MAC || SI_LINUX_NOT_ANDROID) #define SANITIZER_INTERCEPT_ETHER_R (SI_FREEBSD || SI_LINUX_NOT_ANDROID) -#define SANITIZER_INTERCEPT_SHMCTL \ - (((SI_FREEBSD || SI_LINUX_NOT_ANDROID) && SANITIZER_WORDSIZE == 64) || \ +#define SANITIZER_INTERCEPT_SHMCTL \ + (((SI_FREEBSD || SI_LINUX_NOT_ANDROID) && !SI_OHOS && \ + SANITIZER_WORDSIZE == 64) || \ SI_NETBSD || SI_SOLARIS) // NOLINT #define SANITIZER_INTERCEPT_RANDOM_R SI_GLIBC #define SANITIZER_INTERCEPT_PTHREAD_ATTR_GET SI_POSIX @@ -464,7 +471,7 @@ #define SANITIZER_INTERCEPT_EVENTFD_READ_WRITE SI_LINUX #define SANITIZER_INTERCEPT_STAT \ - (SI_FREEBSD || SI_MAC || SI_ANDROID || SI_NETBSD || SI_SOLARIS) + (SI_FREEBSD || SI_MAC || SI_ANDROID || SI_NETBSD || SI_SOLARIS || SI_OHOS) #define SANITIZER_INTERCEPT_LSTAT (SI_NETBSD || SI_FREEBSD) #define SANITIZER_INTERCEPT___XSTAT (!SANITIZER_INTERCEPT_STAT && SI_POSIX) #define SANITIZER_INTERCEPT___XSTAT64 SI_LINUX_NOT_ANDROID @@ -494,7 +501,7 @@ #define SANITIZER_INTERCEPT_WCSCAT SI_POSIX #define SANITIZER_INTERCEPT_WCSDUP SI_POSIX #define SANITIZER_INTERCEPT_SIGNAL_AND_SIGACTION (!SI_WINDOWS && SI_NOT_FUCHSIA) -#define SANITIZER_INTERCEPT_BSD_SIGNAL SI_ANDROID +#define SANITIZER_INTERCEPT_BSD_SIGNAL (SI_ANDROID || SI_OHOS) #define SANITIZER_INTERCEPT_ACCT (SI_NETBSD || SI_FREEBSD) #define SANITIZER_INTERCEPT_USER_FROM_UID SI_NETBSD @@ -505,7 +512,7 @@ #define SANITIZER_INTERCEPT_FACCESSAT (SI_NETBSD || SI_FREEBSD) #define SANITIZER_INTERCEPT_GETGROUPLIST SI_NETBSD #define SANITIZER_INTERCEPT_STRLCPY \ - (SI_NETBSD || SI_FREEBSD || SI_MAC || SI_ANDROID) + (SI_NETBSD || SI_FREEBSD || SI_MAC || SI_ANDROID || SI_OHOS) #define SANITIZER_INTERCEPT_NAME_TO_HANDLE_AT SI_LINUX_NOT_ANDROID #define SANITIZER_INTERCEPT_OPEN_BY_HANDLE_AT SI_LINUX_NOT_ANDROID diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_linux.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_linux.cpp index c51327e1269e..470f6ebf8d38 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_linux.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_linux.cpp @@ -59,7 +59,7 @@ using namespace __sanitizer; namespace __sanitizer { #if !SANITIZER_ANDROID - unsigned struct_statfs64_sz = sizeof(struct statfs64); +unsigned struct_statfs64_sz = sizeof(struct statfs64); #endif } // namespace __sanitizer @@ -81,7 +81,7 @@ CHECK_SIZE_AND_OFFSET(io_event, obj); CHECK_SIZE_AND_OFFSET(io_event, res); CHECK_SIZE_AND_OFFSET(io_event, res2); -#if !SANITIZER_ANDROID +#if !SANITIZER_ANDROID && !SANITIZER_OHOS COMPILER_CHECK(sizeof(struct __sanitizer_perf_event_attr) <= sizeof(struct perf_event_attr)); CHECK_SIZE_AND_OFFSET(perf_event_attr, type); @@ -90,7 +90,7 @@ CHECK_SIZE_AND_OFFSET(perf_event_attr, size); COMPILER_CHECK(iocb_cmd_pread == IOCB_CMD_PREAD); COMPILER_CHECK(iocb_cmd_pwrite == IOCB_CMD_PWRITE); -#if !SANITIZER_ANDROID +#if !SANITIZER_ANDROID && !SANITIZER_OHOS COMPILER_CHECK(iocb_cmd_preadv == IOCB_CMD_PREADV); COMPILER_CHECK(iocb_cmd_pwritev == IOCB_CMD_PWRITEV); #endif diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp index 7abaeb880bf3..c4a1b2807a84 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cpp @@ -69,7 +69,9 @@ #include #include #include +#if !SANITIZER_OHOS #include +#endif #include #include #include @@ -91,8 +93,17 @@ #if SANITIZER_LINUX # include # include + +#if SANITIZER_OHOS +// Do not include asm/sigcontext.h on behalf of asm/ptrace.h +// to avoid multiple definiton errors. +#define __ASM_SIGCONTEXT_H 1 +#include +#endif + #if defined(__mips64) || defined(__aarch64__) || defined(__arm__) || \ SANITIZER_RISCV64 + # include # ifdef __arm__ typedef struct user_fpregs elf_fpregset_t; @@ -131,6 +142,13 @@ typedef struct user_fpregs elf_fpregset_t; #if SANITIZER_ANDROID #include +#elif SANITIZER_OHOS +#include +#include +#include +#include +#include +#include #else #include #include @@ -251,7 +269,7 @@ namespace __sanitizer { unsigned struct_rlimit64_sz = sizeof(struct rlimit64); unsigned struct_statvfs64_sz = sizeof(struct statvfs64); unsigned struct_crypt_data_sz = sizeof(struct crypt_data); -#endif // SANITIZER_LINUX && !SANITIZER_ANDROID +#endif // SANITIZER_LINUX && !SANITIZER_ANDROID #if SANITIZER_LINUX && !SANITIZER_ANDROID unsigned struct_timex_sz = sizeof(struct timex); @@ -269,7 +287,6 @@ namespace __sanitizer { int e_tabsz = (int)E_TABSZ; #endif - #if SANITIZER_LINUX && !SANITIZER_ANDROID unsigned struct_shminfo_sz = sizeof(struct shminfo); unsigned struct_shm_info_sz = sizeof(struct shm_info); @@ -483,7 +500,7 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); unsigned struct_ppp_stats_sz = sizeof(struct ppp_stats); #endif // SANITIZER_GLIBC -#if !SANITIZER_ANDROID && !SANITIZER_MAC +#if !SANITIZER_ANDROID && !SANITIZER_MAC && !SANITIZER_OHOS unsigned struct_sioc_sg_req_sz = sizeof(struct sioc_sg_req); unsigned struct_sioc_vif_req_sz = sizeof(struct sioc_vif_req); #endif @@ -536,7 +553,7 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); unsigned IOCTL_TIOCSPGRP = TIOCSPGRP; unsigned IOCTL_TIOCSTI = TIOCSTI; unsigned IOCTL_TIOCSWINSZ = TIOCSWINSZ; -#if SANITIZER_LINUX && !SANITIZER_ANDROID +#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_OHOS unsigned IOCTL_SIOCGETSGCNT = SIOCGETSGCNT; unsigned IOCTL_SIOCGETVIFCNT = SIOCGETVIFCNT; #endif @@ -820,7 +837,7 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); unsigned IOCTL_VT_WAITACTIVE = VT_WAITACTIVE; #endif // SANITIZER_LINUX -#if SANITIZER_LINUX && !SANITIZER_ANDROID +#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_OHOS unsigned IOCTL_EQL_EMANCIPATE = EQL_EMANCIPATE; unsigned IOCTL_EQL_ENSLAVE = EQL_ENSLAVE; unsigned IOCTL_EQL_GETMASTRCFG = EQL_GETMASTRCFG; @@ -904,7 +921,7 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); unsigned IOCTL_TIOCSSERIAL = TIOCSSERIAL; #endif // SANITIZER_LINUX && !SANITIZER_ANDROID -#if SANITIZER_LINUX && !SANITIZER_ANDROID +#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_OHOS unsigned IOCTL_GIO_SCRNMAP = GIO_SCRNMAP; unsigned IOCTL_KDDISABIO = KDDISABIO; unsigned IOCTL_KDENABIO = KDENABIO; @@ -1072,7 +1089,8 @@ CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_mask); // didn't exist. CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_flags); #endif -#if SANITIZER_LINUX && (!SANITIZER_ANDROID || !SANITIZER_MIPS32) +#if SANITIZER_LINUX && (!SANITIZER_ANDROID || !SANITIZER_MIPS32) && \ + !SANITIZER_OHOS CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_restorer); #endif @@ -1166,7 +1184,7 @@ CHECK_TYPE_SIZE(clock_t); CHECK_TYPE_SIZE(clockid_t); #endif -#if !SANITIZER_ANDROID +#if !SANITIZER_ANDROID && !SANITIZER_OHOS CHECK_TYPE_SIZE(ifaddrs); CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_next); CHECK_SIZE_AND_OFFSET(ifaddrs, ifa_name); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h index 8a156b7fcb80..f4294a74f8e2 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h @@ -188,13 +188,15 @@ struct __sanitizer_struct_mallinfo { #endif #if SANITIZER_LINUX && !SANITIZER_ANDROID -struct __sanitizer_struct_mallinfo { - int v[10]; -}; - extern unsigned struct_ustat_sz; extern unsigned struct_rlimit64_sz; extern unsigned struct_statvfs64_sz; +#endif + +#if SANITIZER_LINUX && !SANITIZER_ANDROID +struct __sanitizer_struct_mallinfo { + int v[10]; +}; struct __sanitizer_ipc_perm { int __key; @@ -367,7 +369,7 @@ struct __sanitizer_group { char **gr_mem; }; -#if defined(__x86_64__) && !defined(_LP64) +#if SANITIZER_OHOS || (defined(__x86_64__) && !defined(_LP64)) typedef long long __sanitizer_time_t; #else typedef long __sanitizer_time_t; @@ -475,7 +477,7 @@ struct __sanitizer_dirent { unsigned short d_reclen; // more fields that we don't care about }; -#elif SANITIZER_ANDROID || defined(__x86_64__) +#elif SANITIZER_ANDROID || defined(__x86_64__) || SANITIZER_OHOS struct __sanitizer_dirent { unsigned long long d_ino; unsigned long long d_off; @@ -601,7 +603,7 @@ struct __sanitizer_sigaction { uptr sa_flags; void (*sa_restorer)(); }; -#else // !SANITIZER_ANDROID +#else // !SANITIZER_ANDROID struct __sanitizer_sigaction { #if defined(__mips__) && !SANITIZER_FREEBSD unsigned int sa_flags; @@ -779,7 +781,7 @@ struct __sanitizer_wordexp_t { uptr we_offs; }; -#if SANITIZER_LINUX && !SANITIZER_ANDROID +#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_OHOS struct __sanitizer_FILE { int _flags; char *_IO_read_ptr; @@ -803,7 +805,7 @@ typedef void __sanitizer_FILE; # define SANITIZER_HAS_STRUCT_FILE 0 #endif -#if SANITIZER_LINUX && !SANITIZER_ANDROID && \ +#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_OHOS && \ (defined(__i386) || defined(__x86_64) || defined(__mips64) || \ defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \ defined(__s390__) || SANITIZER_RISCV64) @@ -981,7 +983,7 @@ extern unsigned struct_synth_info_sz; extern unsigned struct_vt_mode_sz; #endif // SANITIZER_LINUX -#if SANITIZER_LINUX && !SANITIZER_ANDROID +#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_OHOS extern unsigned struct_ax25_parms_struct_sz; extern unsigned struct_input_keymap_entry_sz; extern unsigned struct_ipx_config_data_sz; @@ -1002,12 +1004,12 @@ extern unsigned struct_unimapinit_sz; extern const unsigned long __sanitizer_bufsiz; -#if SANITIZER_LINUX && !SANITIZER_ANDROID +#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_OHOS extern unsigned struct_audio_buf_info_sz; extern unsigned struct_ppp_stats_sz; #endif // (SANITIZER_LINUX || SANITIZER_FREEBSD) && !SANITIZER_ANDROID -#if !SANITIZER_ANDROID && !SANITIZER_MAC +#if !SANITIZER_ANDROID && !SANITIZER_MAC && !SANITIZER_OHOS extern unsigned struct_sioc_sg_req_sz; extern unsigned struct_sioc_vif_req_sz; #endif @@ -1062,7 +1064,7 @@ extern unsigned IOCTL_TIOCSETD; extern unsigned IOCTL_TIOCSPGRP; extern unsigned IOCTL_TIOCSTI; extern unsigned IOCTL_TIOCSWINSZ; -#if SANITIZER_LINUX && !SANITIZER_ANDROID +#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_OHOS extern unsigned IOCTL_SIOCGETSGCNT; extern unsigned IOCTL_SIOCGETVIFCNT; #endif @@ -1326,7 +1328,16 @@ extern unsigned IOCTL_VT_SETMODE; extern unsigned IOCTL_VT_WAITACTIVE; #endif // SANITIZER_LINUX -#if SANITIZER_LINUX && !SANITIZER_ANDROID +#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_OHOS +extern unsigned IOCTL_CYGETDEFTHRESH; +extern unsigned IOCTL_CYGETDEFTIMEOUT; +extern unsigned IOCTL_CYGETMON; +extern unsigned IOCTL_CYGETTHRESH; +extern unsigned IOCTL_CYGETTIMEOUT; +extern unsigned IOCTL_CYSETDEFTHRESH; +extern unsigned IOCTL_CYSETDEFTIMEOUT; +extern unsigned IOCTL_CYSETTHRESH; +extern unsigned IOCTL_CYSETTIMEOUT; extern unsigned IOCTL_EQL_EMANCIPATE; extern unsigned IOCTL_EQL_ENSLAVE; extern unsigned IOCTL_EQL_GETMASTRCFG; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_posix.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_posix.cpp index 2e080098283f..01860a9c1704 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_posix.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_posix.cpp @@ -341,7 +341,7 @@ bool ShouldMockFailureToOpen(const char *path) { internal_strncmp(path, "/proc/", 6) == 0; } -#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_GO +#if SANITIZER_LINUX && !SANITIZER_ANDROID && !SANITIZER_GO && !SANITIZER_OHOS int GetNamedMappingFd(const char *name, uptr size, int *flags) { if (!common_flags()->decorate_proc_maps || !name) return -1; @@ -373,7 +373,7 @@ int GetNamedMappingFd(const char *name, uptr size, int *flags) { } #endif -#if SANITIZER_ANDROID +#if SANITIZER_ANDROID || SANITIZER_OHOS #define PR_SET_VMA 0x53564d41 #define PR_SET_VMA_ANON_NAME 0 void DecorateMapping(uptr addr, uptr size, const char *name) { diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp index 12603da1750d..a5e3b4d76e2d 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp @@ -177,7 +177,8 @@ void SetAlternateSignalStack() { CHECK_EQ(0, sigaltstack(nullptr, &oldstack)); // If the alternate stack is already in place, do nothing. // Android always sets an alternate stack, but it's too small for us. - if (!SANITIZER_ANDROID && !(oldstack.ss_flags & SS_DISABLE)) return; + if (!SANITIZER_ANDROID && !(oldstack.ss_flags & SS_DISABLE)) + return; // TODO(glider): the mapped stack should have the MAP_STACK flag in the // future. It is not required by man 2 sigaltstack now (they're using // malloc()). diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp index 44a95214e38b..38af2748c9ba 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp @@ -26,7 +26,8 @@ struct StackDepotNode { u32 tag; uptr stack[1]; // [size] - static const u32 kTabSizeLog = SANITIZER_ANDROID ? 16 : 20; + static const u32 kTabSizeLog = + (SANITIZER_ANDROID || SANITIZER_OHOS) ? 16 : 20; // Lower kTabSizeLog bits are equal for all items in one bucket. // We use these bits to store the per-stack use counter. static const u32 kUseCountBits = kTabSizeLog; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.h b/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.h index 0e26c1fc37c4..3e6c0b9d4691 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.h @@ -31,7 +31,8 @@ struct StackDepotHandle { void inc_use_count_unsafe(); }; -const int kStackDepotMaxUseCount = 1U << (SANITIZER_ANDROID ? 16 : 20); +const int kStackDepotMaxUseCount = + 1U << ((SANITIZER_ANDROID || SANITIZER_OHOS) ? 16 : 20); StackDepotStats *StackDepotGetStats(); u32 StackDepotPut(StackTrace stack); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp index 53cfddcfbe0b..0735b93c9a23 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp @@ -33,6 +33,11 @@ #include // for NT_PRSTATUS #if (defined(__aarch64__) || SANITIZER_RISCV64) && !SANITIZER_ANDROID // GLIBC 2.20+ sys/user does not include asm/ptrace.h +#if SANITIZER_OHOS +// Do not include asm/sigcontext.h on behalf of asm/ptrace.h +// to avoid multiple definiton errors. +#define __ASM_SIGCONTEXT_H 1 +#endif # include #endif #include // for user_regs_struct diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cpp index c99a6ceaa562..ff72a823b960 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cpp @@ -89,7 +89,7 @@ void ReportErrorSummary(const char *error_type, const StackTrace *stack, } void ReportMmapWriteExec(int prot) { -#if SANITIZER_POSIX && (!SANITIZER_GO && !SANITIZER_ANDROID) +#if SANITIZER_POSIX && (!SANITIZER_GO && !SANITIZER_ANDROID) && !SANITIZER_OHOS if ((prot & (PROT_WRITE | PROT_EXEC)) != (PROT_WRITE | PROT_EXEC)) return; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cpp index b2628dcc4dc1..18178cd69eb5 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_unwind_linux_libcdep.cpp @@ -16,7 +16,7 @@ #include "sanitizer_common.h" #include "sanitizer_stacktrace.h" -#if SANITIZER_ANDROID +#if SANITIZER_ANDROID || SANITIZER_OHOS #include // for dlopen() #endif diff --git a/compiler-rt/lib/scudo/scudo_flags.inc b/compiler-rt/lib/scudo/scudo_flags.inc index c124738c1f3a..ce4d641b811a 100644 --- a/compiler-rt/lib/scudo/scudo_flags.inc +++ b/compiler-rt/lib/scudo/scudo_flags.inc @@ -39,7 +39,7 @@ SCUDO_FLAG(int, QuarantineChunksUpToSize, -1, // Disable the deallocation type check by default on Android, it causes too many // issues with third party libraries. SCUDO_FLAG(bool, DeallocationTypeMismatch, !SANITIZER_ANDROID, - "Report errors on malloc/delete, new/free, new/delete[], etc.") + "Report errors on malloc/delete, new/free, new/delete[], etc.") SCUDO_FLAG(bool, DeleteSizeMismatch, true, "Report errors on mismatch between size of new and delete.") diff --git a/compiler-rt/lib/scudo/scudo_platform.h b/compiler-rt/lib/scudo/scudo_platform.h index 07d4b70fc8e9..c2414ec60237 100644 --- a/compiler-rt/lib/scudo/scudo_platform.h +++ b/compiler-rt/lib/scudo/scudo_platform.h @@ -24,10 +24,10 @@ #ifndef SCUDO_TSD_EXCLUSIVE // SCUDO_TSD_EXCLUSIVE wasn't defined, use a default TSD model for the platform. -# if SANITIZER_ANDROID || SANITIZER_FUCHSIA +#if SANITIZER_ANDROID || SANITIZER_FUCHSIA // Android and Fuchsia use a pool of TSDs shared between threads. # define SCUDO_TSD_EXCLUSIVE 0 -# elif SANITIZER_LINUX && !SANITIZER_ANDROID +#elif SANITIZER_LINUX && !SANITIZER_ANDROID // Non-Android Linux use an exclusive TSD per thread. # define SCUDO_TSD_EXCLUSIVE 1 # else @@ -42,7 +42,7 @@ // Maximum number of TSDs that can be created for the Shared model. #ifndef SCUDO_SHARED_TSD_POOL_SIZE -# if SANITIZER_ANDROID +#if SANITIZER_ANDROID # define SCUDO_SHARED_TSD_POOL_SIZE 2U # else # define SCUDO_SHARED_TSD_POOL_SIZE 32U @@ -67,7 +67,7 @@ namespace __scudo { #if SANITIZER_CAN_USE_ALLOCATOR64 -# if defined(__aarch64__) && SANITIZER_ANDROID +#if defined(__aarch64__) && SANITIZER_ANDROID const uptr AllocatorSize = 0x4000000000ULL; // 256G. # elif defined(__aarch64__) const uptr AllocatorSize = 0x10000000000ULL; // 1T. diff --git a/compiler-rt/lib/ubsan/ubsan_signals_standalone.cpp b/compiler-rt/lib/ubsan/ubsan_signals_standalone.cpp index 2c91db8ca397..002e87038cfb 100644 --- a/compiler-rt/lib/ubsan/ubsan_signals_standalone.cpp +++ b/compiler-rt/lib/ubsan/ubsan_signals_standalone.cpp @@ -26,7 +26,7 @@ // debuggerd handler, but before the ART handler. // * Interceptors don't work at all when ubsan runtime is loaded late, ex. when // it is part of an APK that does not use wrap.sh method. -#if SANITIZER_FUCHSIA || SANITIZER_ANDROID +#if SANITIZER_FUCHSIA || SANITIZER_ANDROID || SANITIZER_OHOS namespace __ubsan { void InitializeDeadlySignals() {} diff --git a/compiler-rt/test/asan/CMakeLists.txt b/compiler-rt/test/asan/CMakeLists.txt index 855fac4f039f..c8b2152b373c 100644 --- a/compiler-rt/test/asan/CMakeLists.txt +++ b/compiler-rt/test/asan/CMakeLists.txt @@ -132,7 +132,7 @@ if(COMPILER_RT_INCLUDE_TESTS) ${CMAKE_CURRENT_BINARY_DIR}/Unit/dynamic/lit.site.cfg.py) endif() # FIXME: support unit test in the android test runner - if (NOT ANDROID) + if (NOT ANDROID AND NOT OHOS_FAMILY) list(APPEND ASAN_TEST_DEPS AsanUnitTests) list(APPEND ASAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/Unit) if(COMPILER_RT_ASAN_HAS_STATIC_RUNTIME) diff --git a/compiler-rt/test/asan/TestCases/Linux/lit.local.cfg.py b/compiler-rt/test/asan/TestCases/Linux/lit.local.cfg.py index 57271b8078a4..c2352c676cc5 100644 --- a/compiler-rt/test/asan/TestCases/Linux/lit.local.cfg.py +++ b/compiler-rt/test/asan/TestCases/Linux/lit.local.cfg.py @@ -5,5 +5,5 @@ def getRoot(config): root = getRoot(config) -if root.host_os not in ['Linux']: +if root.host_os not in ['Linux', 'OHOS']: config.unsupported = True diff --git a/compiler-rt/test/asan/TestCases/Linux/odr_c_test.c b/compiler-rt/test/asan/TestCases/Linux/odr_c_test.c index 9929b4a67af3..f5f234028867 100644 --- a/compiler-rt/test/asan/TestCases/Linux/odr_c_test.c +++ b/compiler-rt/test/asan/TestCases/Linux/odr_c_test.c @@ -17,7 +17,7 @@ __attribute__((aligned(8))) int x; __attribute__((aligned(1))) char y; // The gold linker puts ZZZ at the start of bss (where it is aligned) // unless we have a large alternative like Displace: -__attribute__((aligned(1))) char Displace[105]; +__attribute__((aligned(8))) char Displace[105]; __attribute__((aligned(1))) char ZZZ[100]; #elif defined(FILE2) int ZZZ = 1; diff --git a/compiler-rt/test/asan/TestCases/Linux/shmctl.cpp b/compiler-rt/test/asan/TestCases/Linux/shmctl.cpp index e1752bc894c0..8fed52092be8 100644 --- a/compiler-rt/test/asan/TestCases/Linux/shmctl.cpp +++ b/compiler-rt/test/asan/TestCases/Linux/shmctl.cpp @@ -1,5 +1,5 @@ // FIXME: https://code.google.com/p/address-sanitizer/issues/detail?id=316 -// XFAIL: android +// XFAIL: android && !ohos_family // // RUN: %clangxx_asan -O1 %s -o %t && %run %t 2>&1 // Regression test for @@ -22,6 +22,6 @@ int main() { struct shm_info shmInfo; res = shmctl(0, SHM_INFO, (struct shmid_ds *)&shmInfo); assert(res > -1); - + return 0; } diff --git a/compiler-rt/test/asan/lit.cfg.py b/compiler-rt/test/asan/lit.cfg.py index 4f56c886e92e..8be427f7ba1a 100644 --- a/compiler-rt/test/asan/lit.cfg.py +++ b/compiler-rt/test/asan/lit.cfg.py @@ -247,7 +247,7 @@ else: config.substitutions.append(('%pie', '-pie')) # Only run the tests on supported OSs. -if config.host_os not in ['Linux', 'Darwin', 'FreeBSD', 'SunOS', 'Windows', 'NetBSD']: +if config.host_os not in ['OHOS', 'Linux', 'Darwin', 'FreeBSD', 'SunOS', 'Windows', 'NetBSD']: config.unsupported = True if not config.parallelism_group: diff --git a/compiler-rt/test/builtins/Unit/divtf3_test.c b/compiler-rt/test/builtins/Unit/divtf3_test.c index 927d0b826f8f..f8b1f20e59d2 100644 --- a/compiler-rt/test/builtins/Unit/divtf3_test.c +++ b/compiler-rt/test/builtins/Unit/divtf3_test.c @@ -185,6 +185,11 @@ int main() UINT64_C(0))) return 1; + if (test__divtf3(-1L, + -0.999999999999999999999999999999999904L, + UINT64_C(0x1), + UINT64_C(0x3fff000000000000))) + return 1; #else printf("skipped\n"); diff --git a/compiler-rt/test/lit.common.cfg.py b/compiler-rt/test/lit.common.cfg.py index 30cfdbee13e2..c28b2cea07ac 100644 --- a/compiler-rt/test/lit.common.cfg.py +++ b/compiler-rt/test/lit.common.cfg.py @@ -12,6 +12,9 @@ import json import lit.formats import lit.util +def is_ohos_family_mobile(): + return config.ohos_family and config.target_arch != 'x86_64' + # Choose between lit's internal shell pipeline runner and a real shell. If # LIT_USE_INTERNAL_SHELL is in the environment, we use that as an override. use_lit_shell = os.environ.get("LIT_USE_INTERNAL_SHELL") @@ -117,10 +120,10 @@ if config.host_os == 'NetBSD': config.netbsd_nomprotect_prefix = ('sh ' + os.path.join(nb_commands_dir, 'run_nomprotect.sh')) - config.substitutions.append( ('%run_nomprotect', - config.netbsd_nomprotect_prefix) ) + config.substitutions.append(('%run_nomprotect', + config.netbsd_nomprotect_prefix)) else: - config.substitutions.append( ('%run_nomprotect', '%run') ) + config.substitutions.append(('%run_nomprotect', '%run')) # Copied from libcxx's config.py def get_lit_conf(name, default=None): @@ -136,13 +139,26 @@ emulator = get_lit_conf('emulator', None) # Allow tests to be executed on a simulator or remotely. if emulator: - config.substitutions.append( ('%run', emulator) ) - config.substitutions.append( ('%env ', "env ") ) + config.substitutions.append(('%run', emulator)) + config.substitutions.append(('%env ', "env ")) # TODO: Implement `%device_rm` to perform removal of files in the emulator. # For now just make it a no-op. lit_config.warning('%device_rm is not implemented') - config.substitutions.append( ('%device_rm', 'echo ') ) + config.substitutions.append(('%device_rm', 'echo ')) config.compile_wrapper = "" +elif is_ohos_family_mobile(): + config.available_features.add('ohos_family') + # FIXME: some tests for hos also need this now, + # probably this shouldn't be added for ohos + config.available_features.add('android') + compile_wrapper = os.path.join(config.compiler_rt_src_root, "test", "sanitizer_common", "ohos_family_commands", "ohos_compile.py") + " " + config.compile_wrapper = compile_wrapper + config.substitutions.append( ('%run', "") ) + config.substitutions.append( ('%env ', "env ") ) + # TODO: Implement `%device_rm` to perform removal of files on a device. For + # now just make it a no-op. + lit_config.warning('%device_rm is not implemented') + config.substitutions.append( ('%device_rm', 'echo ') ) elif config.host_os == 'Darwin' and config.apple_platform != "osx": # Darwin tests can be targetting macOS, a device or a simulator. All devices # are declared as "ios", even for iOS derivatives (tvOS, watchOS). Similarly, @@ -203,20 +219,20 @@ elif config.android: config.available_features.add('android') compile_wrapper = os.path.join(config.compiler_rt_src_root, "test", "sanitizer_common", "android_commands", "android_compile.py") + " " config.compile_wrapper = compile_wrapper - config.substitutions.append( ('%run', "") ) - config.substitutions.append( ('%env ', "env ") ) + config.substitutions.append(('%run', "")) + config.substitutions.append(('%env ', "env ")) else: - config.substitutions.append( ('%run', "") ) - config.substitutions.append( ('%env ', "env ") ) + config.substitutions.append(('%run', "")) + config.substitutions.append(('%env ', "env ")) # When running locally %device_rm is a no-op. - config.substitutions.append( ('%device_rm', 'echo ') ) + config.substitutions.append(('%device_rm', 'echo ')) config.compile_wrapper = "" # Define CHECK-%os to check for OS-dependent output. -config.substitutions.append( ('CHECK-%os', ("CHECK-" + config.host_os))) +config.substitutions.append(('CHECK-%os', ("CHECK-" + config.host_os))) # Define %arch to check for architecture-dependent output. -config.substitutions.append( ('%arch', (config.host_arch))) +config.substitutions.append(('%arch', (config.host_arch))) if config.host_os == 'Windows': # FIXME: This isn't quite right. Specifically, it will succeed if the program @@ -227,7 +243,7 @@ if config.host_os == 'Windows': else: config.expect_crash = "not --crash " -config.substitutions.append( ("%expect_crash ", config.expect_crash) ) +config.substitutions.append(("%expect_crash ", config.expect_crash)) target_arch = getattr(config, 'target_arch', None) if target_arch: @@ -329,12 +345,12 @@ if config.host_os == 'Darwin': for vers in min_macos_deployment_target_substitutions: flag = config.apple_platform_min_deployment_target_flag major, minor = get_macos_aligned_version(vers) - config.substitutions.append( ('%%min_macos_deployment_target=%s.%s' % vers, '{}={}.{}'.format(flag, major, minor)) ) + config.substitutions.append(('%%min_macos_deployment_target=%s.%s' % vers, '{}={}.{}'.format(flag, major, minor))) else: for vers in min_macos_deployment_target_substitutions: - config.substitutions.append( ('%%min_macos_deployment_target=%s.%s' % vers, '') ) + config.substitutions.append(('%%min_macos_deployment_target=%s.%s' % vers, '')) -if config.android: +if config.android or is_ohos_family_mobile(): env = os.environ.copy() if config.android_serial: env['ANDROID_SERIAL'] = config.android_serial @@ -345,21 +361,25 @@ if config.android: # These are needed for tests to upload/download temp files, such as # suppression-files, to device. config.substitutions.append( ('%device_rundir', "/data/local/tmp/Output") ) - config.substitutions.append( ('%push_to_device', "%s -s '%s' push " % (adb, env['ANDROID_SERIAL']) ) ) - config.substitutions.append( ('%pull_from_device', "%s -s '%s' pull " % (adb, env['ANDROID_SERIAL']) ) ) - config.substitutions.append( ('%adb_shell ', "%s -s '%s' shell " % (adb, env['ANDROID_SERIAL']) ) ) - config.substitutions.append( ('%device_rm', "%s -s '%s' shell 'rm ' " % (adb, env['ANDROID_SERIAL']) ) ) + if not config.host_os == 'OHOS': + config.substitutions.append( ('%push_to_device', "%s -s '%s' push " % (adb, env['ANDROID_SERIAL']) ) ) + config.substitutions.append( ('%pull_from_device', "%s -s '%s' pull " % (adb, env['ANDROID_SERIAL']) ) ) + config.substitutions.append( ('%adb_shell ', "%s -s '%s' shell " % (adb, env['ANDROID_SERIAL']) ) ) + config.substitutions.append( ('%device_rm', "%s -s '%s' shell 'rm ' " % (adb, env['ANDROID_SERIAL']) ) ) try: - android_api_level_str = subprocess.check_output([adb, "shell", "getprop", "ro.build.version.sdk"], env=env).rstrip() - android_api_codename = subprocess.check_output([adb, "shell", "getprop", "ro.build.version.codename"], env=env).rstrip().decode("utf-8") + android_api_level_str = subprocess.check_output( + [adb, "shell", "getprop", "ro.build.version.sdk"], env=env).rstrip() + android_api_codename = subprocess.check_output( + [adb, "shell", "getprop", "ro.build.version.codename"], env=env).rstrip().decode("utf-8") except (subprocess.CalledProcessError, OSError): lit_config.fatal("Failed to read ro.build.version.sdk (using '%s' as adb)" % adb) try: android_api_level = int(android_api_level_str) except ValueError: lit_config.fatal("Failed to read ro.build.version.sdk (using '%s' as adb): got '%s'" % (adb, android_api_level_str)) - android_api_level = min(android_api_level, int(config.android_api_level)) + if config.android_api_level: + android_api_level = min(android_api_level, int(config.android_api_level)) for required in [26, 28, 30]: if android_api_level >= required: config.available_features.add('android-%s' % required) @@ -507,7 +527,7 @@ for postfix in ["2", "1", ""]: elif config.host_os in ('FreeBSD', 'NetBSD', 'OpenBSD'): config.substitutions.append( ("%ld_flags_rpath_exe" + postfix, "-Wl,-z,origin -Wl,-rpath,\$ORIGIN -L%T -l%xdynamiclib_namespec" + postfix) ) config.substitutions.append( ("%ld_flags_rpath_so" + postfix, '') ) - elif config.host_os == 'Linux': + elif config.host_os in ['Linux', 'OHOS']: config.substitutions.append( ("%ld_flags_rpath_exe" + postfix, "-Wl,-rpath,\$ORIGIN -L%T -l%xdynamiclib_namespec" + postfix) ) config.substitutions.append( ("%ld_flags_rpath_so" + postfix, '') ) elif config.host_os == 'SunOS': @@ -546,7 +566,7 @@ if config.host_os == 'Darwin': lit_config.warning('log command found but cannot queried') else: lit_config.warning('log command not found. Some tests will be skipped.') -elif config.android: +elif config.android or is_ohos_family_mobile(): config.default_sanitizer_opts += ['abort_on_error=0'] # Allow tests to use REQUIRES=stable-runtime. For use when you cannot use XFAIL diff --git a/compiler-rt/test/lit.common.configured.in b/compiler-rt/test/lit.common.configured.in index 5653bcd90caa..957226a91888 100644 --- a/compiler-rt/test/lit.common.configured.in +++ b/compiler-rt/test/lit.common.configured.in @@ -40,6 +40,7 @@ set_default("use_thinlto", False) set_default("use_lto", config.use_thinlto) set_default("use_newpm", False) set_default("android", @ANDROID_PYBOOL@) +set_default("ohos_family", @OHOS_FAMILY_PYBOOL@) set_default("android_api_level", "@ANDROID_API_LEVEL@") set_default("android_serial", "@ANDROID_SERIAL_FOR_TESTING@") set_default("android_files_to_push", []) diff --git a/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_common.py b/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_common.py new file mode 100644 index 000000000000..da6e6b9d2fd4 --- /dev/null +++ b/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_common.py @@ -0,0 +1,45 @@ +import os, subprocess, tempfile + +HOS_TMPDIR = '/data/local/tmp/Output' +ADB = os.environ.get('ADB', 'adb') + +verbose = False +if os.environ.get('HOS_RUN_VERBOSE') == '1': + verbose = True + +def host_to_device_path(path): + rel = os.path.relpath(path, "/") + dev = os.path.join(HOS_TMPDIR, rel) + return dev + +def adb(args, attempts = 1): + if verbose: + print args + tmpname = tempfile.mktemp() + out = open(tmpname, 'w') + ret = 255 + while attempts > 0 and ret != 0: + attempts -= 1 + ret = subprocess.call([ADB] + args, stdout=out, stderr=subprocess.STDOUT) + if attempts != 0: + ret = 5 + if ret != 0: + print "adb command failed", args + print tmpname + out.close() + out = open(tmpname, 'r') + print out.read() + out.close() + os.unlink(tmpname) + return ret + +def pull_from_device(path): + tmp = tempfile.mktemp() + adb(['pull', path, tmp], 5) + text = open(tmp, 'r').read() + os.unlink(tmp) + return text + +def push_to_device(path): + dst_path = host_to_device_path(path) + adb(['push', path, dst_path], 5) diff --git a/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_compile.py b/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_compile.py new file mode 100644 index 000000000000..f7d2a89540b9 --- /dev/null +++ b/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_compile.py @@ -0,0 +1,52 @@ +#!/usr/bin/python + +import os, sys, subprocess +from hos_common import * + + +here = os.path.abspath(os.path.dirname(sys.argv[0])) +hos_run = os.path.join(here, 'hos_run.py') + +output = None +output_type = 'executable' + +args = sys.argv[1:] +append_args = [] +check_trgt = False +while args: + arg = args.pop(0) + if arg == '-shared': + output_type = 'shared' + elif arg == '-c': + output_type = 'object' + elif arg == '-o': + output = args.pop(0) + elif arg == '-target': + check_trgt = True + elif check_trgt or arg.startswith('--target='): + check_trgt = False + if arg.endswith('-linux-ohos'): + arg = arg.split('=')[-1] + dyld = 'unknown_hos_dyld' + # FIXME: Handle -mfloat-abi=hard for arm + # TODO: Support x86_64 + if arg.startswith('arm'): + dyld = 'ld-musl-arm.so.1' + elif arg.startswith('aarch64'): + dyld = 'ld-musl-aarch64.so.1' + append_args += ['-Wl,--dynamic-linker=' + os.path.join(HOS_TMPDIR, dyld)] + +if output == None: + print "No output file name!" + sys.exit(1) + +ret = subprocess.call(sys.argv[1:] + append_args) +if ret != 0: + sys.exit(ret) + +if output_type in ['executable', 'shared']: + push_to_device(output) + +if output_type == 'executable': + os.rename(output, output + '.real') + os.symlink(hos_run, output) diff --git a/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_run.py b/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_run.py new file mode 100644 index 000000000000..5bfe83ef3f56 --- /dev/null +++ b/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_run.py @@ -0,0 +1,38 @@ +#!/usr/bin/python + +import os, signal, sys, subprocess +import re +from hos_common import * + +device_binary = host_to_device_path(sys.argv[0]) + +def build_env(): + args = [] + # HOS linker ignores RPATH. Set LD_LIBRARY_PATH to Output dir. + args.append('LD_LIBRARY_PATH=%s' % (HOS_TMPDIR,)) + for (key, value) in os.environ.items(): + if key in ['ASAN_ACTIVATION_OPTIONS', 'SCUDO_OPTIONS'] or key.endswith('SAN_OPTIONS'): + args.append('%s="%s"' % (key, value)) + return ' '.join(args) + +device_env = build_env() +device_args = ' '.join(sys.argv[1:]) # FIXME: escape? +device_stdout = device_binary + '.stdout' +device_stderr = device_binary + '.stderr' +device_exitcode = device_binary + '.exitcode' +device_linker = '' + +ret = adb(['shell', 'cd %s && %s %s %s %s >%s 2>%s ; echo $? >%s' % + (HOS_TMPDIR, device_env, device_linker, device_binary, device_args, + device_stdout, device_stderr, device_exitcode)]) +if ret != 0: + sys.exit(ret) + +sys.stdout.write(pull_from_device(device_stdout)) +sys.stderr.write(pull_from_device(device_stderr)) +retcode = int(pull_from_device(device_exitcode)) +# If the device process died with a signal, do abort(). +# Not exactly the same, but good enough to fool "not --crash". +if retcode > 128: + os.kill(os.getpid(), signal.SIGABRT) +sys.exit(retcode) diff --git a/libcxx/CMakeLists.txt b/libcxx/CMakeLists.txt index cdd5495e36ab..25ce254649a9 100644 --- a/libcxx/CMakeLists.txt +++ b/libcxx/CMakeLists.txt @@ -400,9 +400,17 @@ endif () #=============================================================================== if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE) - set(LIBCXX_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}/c++) - set(LIBCXX_HEADER_DIR ${LLVM_BINARY_DIR}) - set(LIBCXX_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE}/c++) + if(OHOS) + set(LIBCXX_LIBRARY_DIR + ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}/c++/${LLVM_TARGET_MULTILIB_SUFFIX}) + set(LIBCXX_HEADER_DIR ${LLVM_BINARY_DIR}) + set(LIBCXX_INSTALL_LIBRARY_DIR + lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE}/c++/${LLVM_TARGET_MULTILIB_SUFFIX}) + else() + set(LIBCXX_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}/c++) + set(LIBCXX_HEADER_DIR ${LLVM_BINARY_DIR}) + set(LIBCXX_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE}/c++) + endif() if(LIBCXX_LIBDIR_SUBDIR) string(APPEND LIBCXX_LIBRARY_DIR /${LIBCXX_LIBDIR_SUBDIR}) string(APPEND LIBCXX_INSTALL_LIBRARY_DIR /${LIBCXX_LIBDIR_SUBDIR}) diff --git a/libcxx/cmake/config-ix.cmake b/libcxx/cmake/config-ix.cmake index 894f637f814f..991efe0c25d5 100644 --- a/libcxx/cmake/config-ix.cmake +++ b/libcxx/cmake/config-ix.cmake @@ -93,6 +93,8 @@ elseif(APPLE) set(LIBCXX_HAS_M_LIB NO) set(LIBCXX_HAS_RT_LIB NO) set(LIBCXX_HAS_ATOMIC_LIB NO) +elseif(OHOS) + set(LIBCXX_HAS_ATOMIC_LIB NO) elseif(FUCHSIA) set(LIBCXX_HAS_M_LIB NO) set(LIBCXX_HAS_PTHREAD_LIB NO) diff --git a/libcxx/include/__config b/libcxx/include/__config index a3838c89e8e1..384d59700132 100644 --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -1132,6 +1132,7 @@ extern "C" _LIBCPP_FUNC_VIS void __sanitizer_annotate_contiguous_container( defined(__CloudABI__) || \ defined(__sun__) || \ defined(__MVS__) || \ + defined(__OHOS_FAMILY__) || \ (defined(__MINGW32__) && __has_include()) # define _LIBCPP_HAS_THREAD_API_PTHREAD # elif defined(__Fuchsia__) @@ -1226,7 +1227,7 @@ extern "C" _LIBCPP_FUNC_VIS void __sanitizer_annotate_contiguous_container( # endif #endif -#if defined(__BIONIC__) || defined(__CloudABI__) || defined(__NuttX__) || \ +#if defined(__BIONIC__) || defined(__CloudABI__) || defined(__OHOS_FAMILY__) || \ defined(__Fuchsia__) || defined(__wasi__) || defined(_LIBCPP_HAS_MUSL_LIBC) || \ defined(__MVS__) || defined(__OpenBSD__) #define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE diff --git a/libcxx/include/__locale b/libcxx/include/__locale index 77e5faab2676..9d6a901898e2 100644 --- a/libcxx/include/__locale +++ b/libcxx/include/__locale @@ -43,6 +43,9 @@ #elif defined(__wasi__) // WASI libc uses musl's locales support. # include <__support/musl/xlocale.h> +#elif defined(__LITEOS__) || defined(__OHOS__) +// LiteOS libc uses musl's locales support. +# include <__support/musl/xlocale.h> #elif defined(_LIBCPP_HAS_MUSL_LIBC) # include <__support/musl/xlocale.h> #endif diff --git a/libcxx/src/CMakeLists.txt b/libcxx/src/CMakeLists.txt index 9965104cb5b2..f80c8e062526 100644 --- a/libcxx/src/CMakeLists.txt +++ b/libcxx/src/CMakeLists.txt @@ -178,11 +178,14 @@ if (LIBCXX_ENABLE_SHARED) add_library(cxx_shared SHARED ${exclude_from_all} ${LIBCXX_SOURCES} ${LIBCXX_HEADERS}) target_link_libraries(cxx_shared PUBLIC cxx-headers PRIVATE ${LIBCXX_LIBRARIES}) + if (NOT DEFINED LIBCXX_OUTPUT_NAME) + set (LIBCXX_OUTPUT_NAME "c++") + endif() set_target_properties(cxx_shared PROPERTIES COMPILE_FLAGS "${LIBCXX_COMPILE_FLAGS}" LINK_FLAGS "${LIBCXX_LINK_FLAGS}" - OUTPUT_NAME "c++" + OUTPUT_NAME "${LIBCXX_OUTPUT_NAME}" VERSION "${LIBCXX_ABI_VERSION}.0" SOVERSION "${LIBCXX_ABI_VERSION}" DEFINE_SYMBOL "" @@ -254,11 +257,14 @@ if (LIBCXX_ENABLE_STATIC) target_link_libraries(cxx_static PUBLIC cxx-headers PRIVATE ${LIBCXX_LIBRARIES}) set(CMAKE_STATIC_LIBRARY_PREFIX "lib") + if (NOT DEFINED LIBCXX_OUTPUT_STATIC_NAME) + set (LIBCXX_OUTPUT_STATIC_NAME "c++") + endif() set_target_properties(cxx_static PROPERTIES COMPILE_FLAGS "${LIBCXX_COMPILE_FLAGS}" LINK_FLAGS "${LIBCXX_LINK_FLAGS}" - OUTPUT_NAME "c++" + OUTPUT_NAME "${LIBCXX_OUTPUT_STATIC_NAME}" ) cxx_add_common_build_flags(cxx_static) cxx_set_common_defines(cxx_static) diff --git a/libcxx/src/include/config_elast.h b/libcxx/src/include/config_elast.h index 3113f9fb5cd1..91b4de27f768 100644 --- a/libcxx/src/include/config_elast.h +++ b/libcxx/src/include/config_elast.h @@ -29,6 +29,8 @@ // No _LIBCPP_ELAST needed on Fuchsia #elif defined(__wasi__) // No _LIBCPP_ELAST needed on WASI +#elif defined(__OHOS_FAMILY__) +// No _LIBCPP_ELAST needed on LiteOS #elif defined(__linux__) || defined(_LIBCPP_HAS_MUSL_LIBC) #define _LIBCPP_ELAST 4095 #elif defined(__APPLE__) diff --git a/libcxxabi/CMakeLists.txt b/libcxxabi/CMakeLists.txt index 6de2b5a2ed10..981d0c583485 100644 --- a/libcxxabi/CMakeLists.txt +++ b/libcxxabi/CMakeLists.txt @@ -179,8 +179,15 @@ set(CMAKE_MODULE_PATH ) if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE) - set(LIBCXXABI_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}/c++) - set(LIBCXXABI_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE}/c++) + if(OHOS) + set(LIBCXXABI_LIBRARY_DIR + ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}/c++/${LLVM_TARGET_MULTILIB_SUFFIX}) + set(LIBCXXABI_INSTALL_LIBRARY_DIR + lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE}/c++/${LLVM_TARGET_MULTILIB_SUFFIX}) + else() + set(LIBCXXABI_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}/c++) + set(LIBCXXABI_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE}/c++) + endif() if(LIBCXX_LIBDIR_SUBDIR) string(APPEND LIBCXXABI_LIBRARY_DIR /${LIBCXXABI_LIBDIR_SUBDIR}) string(APPEND LIBCXXABI_INSTALL_LIBRARY_DIR /${LIBCXXABI_LIBDIR_SUBDIR}) @@ -464,7 +471,7 @@ if (LIBCXXABI_BAREMETAL) add_definitions(-DLIBCXXABI_BAREMETAL) endif() -if (LIBCXXABI_HAS_COMMENT_LIB_PRAGMA) +if (LIBCXXABI_HAS_COMMENT_LIB_PRAGMA AND NOT OHOS) if (LIBCXXABI_HAS_PTHREAD_LIB) add_definitions(-D_LIBCXXABI_LINK_PTHREAD_LIB) endif() diff --git a/libcxxabi/src/abort_message.cpp b/libcxxabi/src/abort_message.cpp index ad44063facb7..e2a53cc70878 100644 --- a/libcxxabi/src/abort_message.cpp +++ b/libcxxabi/src/abort_message.cpp @@ -11,7 +11,7 @@ #include #include "abort_message.h" -#ifdef __BIONIC__ +#if defined(__BIONIC__) && !defined(__OHOS__) # include # if __ANDROID_API__ >= 21 # include @@ -52,7 +52,7 @@ void abort_message(const char* format, ...) va_end(list); CRSetCrashLogMessage(buffer); -#elif defined(__BIONIC__) +#elif defined(__BIONIC__) && !defined(__OHOS__) char* buffer; va_list list; va_start(list, format); diff --git a/libunwind/CMakeLists.txt b/libunwind/CMakeLists.txt index 570b8db90653..a9320d965207 100644 --- a/libunwind/CMakeLists.txt +++ b/libunwind/CMakeLists.txt @@ -114,8 +114,15 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}) if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE) - set(LIBUNWIND_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}/c++) - set(LIBUNWIND_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE}/c++) + if(OHOS) + set(LIBUNWIND_LIBRARY_DIR + ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}/${LLVM_TARGET_MULTILIB_SUFFIX}) + set(LIBUNWIND_INSTALL_LIBRARY_DIR + lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE}/${LLVM_TARGET_MULTILIB_SUFFIX}) + else() + set(LIBUNWIND_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}/c++) + set(LIBUNWIND_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE}/c++) + endif() if(LIBCXX_LIBDIR_SUBDIR) string(APPEND LIBUNWIND_LIBRARY_DIR /${LIBUNWIND_LIBDIR_SUBDIR}) string(APPEND LIBUNWIND_INSTALL_LIBRARY_DIR /${LIBUNWIND_LIBDIR_SUBDIR}) @@ -327,7 +334,7 @@ if (LIBUNWIND_HAS_COMMENT_LIB_PRAGMA) if (LIBUNWIND_HAS_DL_LIB) add_definitions(-D_LIBUNWIND_LINK_DL_LIB) endif() - if (LIBUNWIND_HAS_PTHREAD_LIB) + if (LIBUNWIND_HAS_PTHREAD_LIB AND NOT OHOS) add_definitions(-D_LIBUNWIND_LINK_PTHREAD_LIB) endif() endif() diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index c84b5f5bdfda..39b7ec18cc3f 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -263,6 +263,8 @@ struct Configuration { uint64_t zStackSize; unsigned ltoPartitions; unsigned ltoo; + unsigned ltos; + bool mergeFunctions; unsigned optimize; StringRef thinLTOJobs; unsigned timeTraceGranularity; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 3b2a8ba19293..a41a7d1b8dc4 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -62,6 +62,7 @@ #include "llvm/Support/raw_ostream.h" #include #include +#include using namespace llvm; using namespace llvm::ELF; @@ -925,6 +926,48 @@ static void parseClangOption(StringRef opt, const Twine &msg) { error(msg + ": " + StringRef(err).trim()); } +static std::pair parseLTOOptArg(opt::InputArgList &args, + unsigned key, + StringRef defaultValue) { + auto *a = args.getLastArg(key); + llvm::StringRef value = a ? a->getValue() : defaultValue; + + unsigned optLevel = 0; + unsigned sizeLevel = 0; + + if (value.size() != 1) { + error("invalid optimization level for LTO: " + value); + return {optLevel, sizeLevel}; + } + + char c = value[0]; + + switch (c) { + + case '0': + case '1': + case '2': + case '3': + optLevel = c - '0'; + break; + + case 's': + optLevel = 2; + sizeLevel = 1; + break; + + case 'z': + optLevel = 2; + sizeLevel = 2; + break; + + default: + error("invalid optimization level for LTO: " + value); + } + + return {optLevel, sizeLevel}; +} + // Initializes Config members by the command line options. static void readConfigs(opt::InputArgList &args) { errorHandler().verbose = args.hasArg(OPT_verbose); @@ -1002,8 +1045,9 @@ static void readConfigs(opt::InputArgList &args) { config->ltoWholeProgramVisibility = args.hasFlag(OPT_lto_whole_program_visibility, OPT_no_lto_whole_program_visibility, false); - config->ltoo = args::getInteger(args, OPT_lto_O, 2); config->ltoObjPath = args.getLastArgValue(OPT_lto_obj_path_eq); + std::tie(config->ltoo, config->ltos) = parseLTOOptArg(args, OPT_lto_O, "2"); + config->mergeFunctions = args.hasArg(OPT_lto_mf); config->ltoPartitions = args::getInteger(args, OPT_lto_partitions, 1); config->ltoPseudoProbeForProfiling = args.hasArg(OPT_lto_pseudo_probe_for_profiling); diff --git a/lld/ELF/LTO.cpp b/lld/ELF/LTO.cpp index b3d4b7dee9f8..9381509542ad 100644 --- a/lld/ELF/LTO.cpp +++ b/lld/ELF/LTO.cpp @@ -129,6 +129,8 @@ static lto::Config createConfig() { c.DisableVerify = config->disableVerify; c.DiagHandler = diagnosticHandler; c.OptLevel = config->ltoo; + c.SizeLevel = config->ltos; + c.MergeFunctions = config->mergeFunctions; c.CPU = getCPUStr(); c.MAttrs = getMAttrs(); c.CGOptLevel = args::getCGOptLevel(config->ltoo); diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td index 65ef3e824f50..e6d77f21d027 100644 --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -538,6 +538,10 @@ def lto_newpm_passes: JJ<"lto-newpm-passes=">, HelpText<"Passes to run during LTO">; def lto_O: JJ<"lto-O">, MetaVarName<"">, HelpText<"Optimization level for LTO">; +def lto_S: J<"lto-S">, MetaVarName<"">, + HelpText<"Size Optimization level for LTO, works only with -lto-O2">; +def lto_mf: F<"lto-mf">, + HelpText<"Enable Merge Functions pass for link time optimizations.">; def lto_partitions: JJ<"lto-partitions=">, HelpText<"Number of LTO codegen partitions">; def lto_cs_profile_generate: FF<"lto-cs-profile-generate">, diff --git a/lld/test/ELF/lto/opt-level.ll b/lld/test/ELF/lto/opt-level.ll index 6e0cc9ac98c5..628e4ef7126c 100644 --- a/lld/test/ELF/lto/opt-level.ll +++ b/lld/test/ELF/lto/opt-level.ll @@ -19,14 +19,14 @@ ; RUN: FileCheck --check-prefix=INVALID1 %s ; RUN: not ld.lld -o /dev/null -e main --plugin-opt=Ofoo %t.o 2>&1 | \ ; RUN: FileCheck --check-prefix=INVALID2 %s -; INVALID2: --plugin-opt=Ofoo: number expected, but got 'foo' +; INVALID2: invalid optimization level for LTO: foo ; RUN: not ld.lld -o /dev/null -e main --lto-O-1 %t.o 2>&1 | \ ; RUN: FileCheck --check-prefix=INVALIDNEGATIVE1 %s -; INVALIDNEGATIVE1: invalid optimization level for LTO: 4294967295 +; INVALIDNEGATIVE1: invalid optimization level for LTO: -1 ; RUN: not ld.lld -o /dev/null -e main --plugin-opt=O-1 %t.o 2>&1 | \ ; RUN: FileCheck --check-prefix=INVALIDNEGATIVE2 %s -; INVALIDNEGATIVE2: invalid optimization level for LTO: 4294967295 +; INVALIDNEGATIVE2: invalid optimization level for LTO: -1 target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/lldb/CMakeLists.txt b/lldb/CMakeLists.txt index b5633e21c56a..7448c99de72a 100644 --- a/lldb/CMakeLists.txt +++ b/lldb/CMakeLists.txt @@ -31,13 +31,21 @@ if (WIN32) endif() if (LLDB_ENABLE_PYTHON) - execute_process( - COMMAND ${Python3_EXECUTABLE} - -c "import distutils.sysconfig; print(distutils.sysconfig.get_python_lib(True, False, ''))" - OUTPUT_VARIABLE LLDB_PYTHON_DEFAULT_RELATIVE_PATH - OUTPUT_STRIP_TRAILING_WHITESPACE) - - file(TO_CMAKE_PATH ${LLDB_PYTHON_DEFAULT_RELATIVE_PATH} LLDB_PYTHON_DEFAULT_RELATIVE_PATH) + if (NOT CMAKE_CROSSCOMPILING) + execute_process( + COMMAND ${Python3_EXECUTABLE} + -c "import distutils.sysconfig; print(distutils.sysconfig.get_python_lib(True, False, ''))" + OUTPUT_VARIABLE LLDB_PYTHON_DEFAULT_RELATIVE_PATH + OUTPUT_STRIP_TRAILING_WHITESPACE) + + file(TO_CMAKE_PATH ${LLDB_PYTHON_DEFAULT_RELATIVE_PATH} LLDB_PYTHON_DEFAULT_RELATIVE_PATH) + else () + if ("${LLDB_PYTHON_RELATIVE_PATH}" STREQUAL "") + message(FATAL_ERROR + "Crosscompiling LLDB with Python requires manually setting + LLDB_PYTHON_RELATIVE_PATH.") + endif () + endif () set(LLDB_PYTHON_RELATIVE_PATH ${LLDB_PYTHON_DEFAULT_RELATIVE_PATH} CACHE STRING "Path where Python modules are installed, relative to install prefix") endif () diff --git a/lldb/cmake/modules/FindPythonAndSwig.cmake b/lldb/cmake/modules/FindPythonAndSwig.cmake index 3535b548c45f..562d5307e8c8 100644 --- a/lldb/cmake/modules/FindPythonAndSwig.cmake +++ b/lldb/cmake/modules/FindPythonAndSwig.cmake @@ -35,6 +35,17 @@ macro(FindPython3) endif() endmacro() +#OHOS specific: copy LLVM-10 definitions if new Python3_*** are not set +if(NOT Python3_EXECUTABLE AND PYTHON_EXECUTABLE) + set(Python3_EXECUTABLE ${PYTHON_EXECUTABLE}) +endif() +if(NOT Python3_LIBRARIES AND PYTHON_LIBRARIES) + set(Python3_LIBRARIES ${PYTHON_LIBRARIES}) +endif() +if(NOT Python3_INCLUDE_DIRS AND PYTHON_INCLUDE_DIRS) + set(Python3_INCLUDE_DIRS ${PYTHON_INCLUDE_DIRS}) +endif() + if(Python3_LIBRARIES AND Python3_INCLUDE_DIRS AND Python3_EXECUTABLE AND SWIG_EXECUTABLE) set(PYTHONANDSWIG_FOUND TRUE) else() diff --git a/lldb/cmake/modules/LLDBConfig.cmake b/lldb/cmake/modules/LLDBConfig.cmake index 2fdf1502d055..a50f6ce7c315 100644 --- a/lldb/cmake/modules/LLDBConfig.cmake +++ b/lldb/cmake/modules/LLDBConfig.cmake @@ -295,7 +295,7 @@ endif() # Figure out if lldb could use lldb-server. If so, then we'll # ensure we build lldb-server when an lldb target is being built. -if (CMAKE_SYSTEM_NAME MATCHES "Android|Darwin|FreeBSD|Linux|NetBSD|Windows") +if (CMAKE_SYSTEM_NAME MATCHES "Android|Darwin|FreeBSD|Linux|NetBSD|Windows|OHOS") set(LLDB_CAN_USE_LLDB_SERVER ON) else() set(LLDB_CAN_USE_LLDB_SERVER OFF) diff --git a/lldb/include/lldb/Host/HostInfo.h b/lldb/include/lldb/Host/HostInfo.h index b7010d69d88e..fbb5bbf1e442 100644 --- a/lldb/include/lldb/Host/HostInfo.h +++ b/lldb/include/lldb/Host/HostInfo.h @@ -39,6 +39,9 @@ #if defined(__ANDROID__) #include "lldb/Host/android/HostInfoAndroid.h" #define HOST_INFO_TYPE HostInfoAndroid +#elif defined(__OHOS_FAMILY__) +#include "lldb/Host/ohos/HostInfoOHOS.h" +#define HOST_INFO_TYPE HostInfoOHOS #else #include "lldb/Host/linux/HostInfoLinux.h" #define HOST_INFO_TYPE HostInfoLinux diff --git a/lldb/include/lldb/Host/MainLoop.h b/lldb/include/lldb/Host/MainLoop.h index 9ca5040b60a8..e26b8c8cb61b 100644 --- a/lldb/include/lldb/Host/MainLoop.h +++ b/lldb/include/lldb/Host/MainLoop.h @@ -14,7 +14,8 @@ #include "llvm/ADT/DenseMap.h" #include -#if !HAVE_PPOLL && !HAVE_SYS_EVENT_H && !defined(__ANDROID__) +#if !HAVE_PPOLL && !HAVE_SYS_EVENT_H && !defined(__ANDROID__) && \ + !defined(__OHOS_FAMILY__) #define SIGNAL_POLLING_UNSUPPORTED 1 #endif diff --git a/lldb/include/lldb/Host/ohos/HostInfoOHOS.h b/lldb/include/lldb/Host/ohos/HostInfoOHOS.h new file mode 100644 index 000000000000..e20582820145 --- /dev/null +++ b/lldb/include/lldb/Host/ohos/HostInfoOHOS.h @@ -0,0 +1,32 @@ +//===-- HostInfoOHOS.h ---------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_Host_ohos_HostInfoOHOS_h_ +#define lldb_Host_ohos_HostInfoOHOS_h_ + +#include "lldb/Host/linux/HostInfoLinux.h" + +namespace lldb_private { + +class HostInfoOHOS : public HostInfoLinux { + friend class HostInfoBase; + +public: + static FileSpec GetDefaultShell(); + static FileSpec ResolveLibraryPath(const std::string &path, + const ArchSpec &arch); + +protected: + static void ComputeHostArchitectureSupport(ArchSpec &arch_32, + ArchSpec &arch_64); + static bool ComputeTempFileBaseDirectory(FileSpec &file_spec); +}; + +} // end of namespace lldb_private + +#endif // #ifndef lldb_Host_ohos_HostInfoOHOS_h_ diff --git a/lldb/include/lldb/Target/ThreadPlanStepRange.h b/lldb/include/lldb/Target/ThreadPlanStepRange.h index 2fe885277100..36288a0d10ae 100644 --- a/lldb/include/lldb/Target/ThreadPlanStepRange.h +++ b/lldb/include/lldb/Target/ThreadPlanStepRange.h @@ -44,6 +44,7 @@ protected: bool InRange(); lldb::FrameComparison CompareCurrentFrameToStartFrame(); bool InSymbol(); + bool MaybeAArch32Or64FunctionTail(); void DumpRanges(Stream *s); Disassembler *GetDisassembler(); diff --git a/lldb/packages/Python/lldbsuite/test/decorators.py b/lldb/packages/Python/lldbsuite/test/decorators.py index ff445fa0b926..7cf1fc1e3729 100644 --- a/lldb/packages/Python/lldbsuite/test/decorators.py +++ b/lldb/packages/Python/lldbsuite/test/decorators.py @@ -641,6 +641,9 @@ def skipIfPlatform(oslist): return unittest2.skipIf(lldbplatformutil.getPlatform() in oslist, "skip on %s" % (", ".join(oslist))) +def skipOnHuaweiCI(func): + return unittest2.skipIf(lldbplatformutil.isHuawei(), "skip on Huawei CI")(func) + def skipUnlessPlatform(oslist): """Decorate the item to skip tests unless running on one of the listed platforms.""" diff --git a/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py b/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py index 94b133589dcc..d1dfcde78c44 100644 --- a/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py +++ b/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py @@ -152,6 +152,8 @@ def getPlatform(): # It still might be an unconnected remote platform. return '' +def isHuaweiCI(): + return getPlatform() == 'linux' and os.path.exists('/.dockerenv') def platformIsDarwin(): """Returns true if the OS triple for the selected platform is any valid apple OS""" diff --git a/lldb/packages/Python/lldbsuite/test/lldbtest.py b/lldb/packages/Python/lldbsuite/test/lldbtest.py index 958cadd3a7c8..964bcfdd1cff 100644 --- a/lldb/packages/Python/lldbsuite/test/lldbtest.py +++ b/lldb/packages/Python/lldbsuite/test/lldbtest.py @@ -804,11 +804,6 @@ class Base(unittest2.TestCase): for setting, value in configuration.settings: commands.append('setting set %s %s'%(setting, value)) - # Make sure that a sanitizer LLDB's environment doesn't get passed on. - if cls.platformContext and cls.platformContext.shlib_environment_var in os.environ: - commands.append('settings set target.env-vars {}='.format( - cls.platformContext.shlib_environment_var)) - # Set environment variables for the inferior. if lldbtest_config.inferior_env: commands.append('settings set target.env-vars {}'.format( diff --git a/lldb/source/Expression/IRInterpreter.cpp b/lldb/source/Expression/IRInterpreter.cpp index b87a759aadc5..f892bb3dbd9b 100644 --- a/lldb/source/Expression/IRInterpreter.cpp +++ b/lldb/source/Expression/IRInterpreter.cpp @@ -166,6 +166,18 @@ public: const Constant *constant = dyn_cast(value); if (constant) { + if (constant->getValueID() == Value::ConstantFPVal) { + if (auto *cfp = dyn_cast(constant)) { + if (cfp->getType()->isDoubleTy()) + scalar = cfp->getValueAPF().convertToDouble(); + else if (cfp->getType()->isFloatTy()) + scalar = cfp->getValueAPF().convertToFloat(); + else + return false; + return true; + } + return false; + } APInt value_apint; if (!ResolveConstantValue(value_apint, constant)) @@ -188,9 +200,18 @@ public: lldb::offset_t offset = 0; if (value_size <= 8) { - uint64_t u64value = value_extractor.GetMaxU64(&offset, value_size); - return AssignToMatchType(scalar, llvm::APInt(64, u64value), - value->getType()); + Type *ty = value->getType(); + if (ty->isDoubleTy()) { + scalar = value_extractor.GetDouble(&offset); + return true; + } else if (ty->isFloatTy()) { + scalar = value_extractor.GetFloat(&offset); + return true; + } else { + uint64_t u64value = value_extractor.GetMaxU64(&offset, value_size); + return AssignToMatchType(scalar, llvm::APInt(64, u64value), + value->getType()); + } } return false; @@ -204,11 +225,15 @@ public: return false; lldb_private::Scalar cast_scalar; - - scalar.MakeUnsigned(); - if (!AssignToMatchType(cast_scalar, scalar.UInt128(llvm::APInt()), - value->getType())) - return false; + Type *vty = value->getType(); + if (vty->isFloatTy() || vty->isDoubleTy()) { + cast_scalar = scalar; + } else { + scalar.MakeUnsigned(); + if (!AssignToMatchType(cast_scalar, scalar.UInt128(llvm::APInt()), + value->getType())) + return false; + } size_t value_byte_size = m_target_data.getTypeStoreSize(value->getType()); @@ -534,16 +559,17 @@ bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function, } break; case Instruction::GetElementPtr: break; + case Instruction::FCmp: case Instruction::ICmp: { - ICmpInst *icmp_inst = dyn_cast(&ii); + CmpInst *cmp_inst = dyn_cast(&ii); - if (!icmp_inst) { + if (!cmp_inst) { error.SetErrorToGenericError(); error.SetErrorString(interpreter_internal_error); return false; } - switch (icmp_inst->getPredicate()) { + switch (cmp_inst->getPredicate()) { default: { LLDB_LOGF(log, "Unsupported ICmp predicate: %s", PrintValue(&ii).c_str()); @@ -552,11 +578,17 @@ bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function, error.SetErrorString(unsupported_opcode_error); return false; } + case CmpInst::FCMP_OEQ: case CmpInst::ICMP_EQ: + case CmpInst::FCMP_UNE: case CmpInst::ICMP_NE: + case CmpInst::FCMP_OGT: case CmpInst::ICMP_UGT: + case CmpInst::FCMP_OGE: case CmpInst::ICMP_UGE: + case CmpInst::FCMP_OLT: case CmpInst::ICMP_ULT: + case CmpInst::FCMP_OLE: case CmpInst::ICMP_ULE: case CmpInst::ICMP_SGT: case CmpInst::ICMP_SGE: @@ -586,6 +618,11 @@ bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function, case Instruction::Xor: case Instruction::ZExt: break; + case Instruction::FAdd: + case Instruction::FSub: + case Instruction::FMul: + case Instruction::FDiv: + break; } for (unsigned oi = 0, oe = ii.getNumOperands(); oi != oe; ++oi) { @@ -701,7 +738,11 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, case Instruction::AShr: case Instruction::And: case Instruction::Or: - case Instruction::Xor: { + case Instruction::Xor: + case Instruction::FAdd: + case Instruction::FSub: + case Instruction::FMul: + case Instruction::FDiv: { const BinaryOperator *bin_op = dyn_cast(inst); if (!bin_op) { @@ -740,12 +781,15 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, default: break; case Instruction::Add: + case Instruction::FAdd: result = L + R; break; case Instruction::Mul: + case Instruction::FMul: result = L * R; break; case Instruction::Sub: + case Instruction::FSub: result = L - R; break; case Instruction::SDiv: @@ -758,6 +802,9 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, R.MakeUnsigned(); result = L / R; break; + case Instruction::FDiv: + result = L / R; + break; case Instruction::SRem: L.MakeSigned(); R.MakeSigned(); @@ -1020,10 +1067,11 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, LLDB_LOGF(log, " Poffset : %s", frame.SummarizeValue(inst).c_str()); } } break; + case Instruction::FCmp: case Instruction::ICmp: { - const ICmpInst *icmp_inst = cast(inst); + const CmpInst *cmp_inst = cast(inst); - CmpInst::Predicate predicate = icmp_inst->getPredicate(); + CmpInst::Predicate predicate = cmp_inst->getPredicate(); Value *lhs = inst->getOperand(0); Value *rhs = inst->getOperand(1); @@ -1051,9 +1099,11 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, default: return false; case CmpInst::ICMP_EQ: + case CmpInst::FCMP_OEQ: result = (L == R); break; case CmpInst::ICMP_NE: + case CmpInst::FCMP_UNE: result = (L != R); break; case CmpInst::ICMP_UGT: @@ -1066,16 +1116,28 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function, R.MakeUnsigned(); result = (L >= R); break; + case CmpInst::FCMP_OGE: + result = (L >= R); + break; + case CmpInst::FCMP_OGT: + result = (L > R); + break; case CmpInst::ICMP_ULT: L.MakeUnsigned(); R.MakeUnsigned(); result = (L < R); break; + case CmpInst::FCMP_OLT: + result = (L < R); + break; case CmpInst::ICMP_ULE: L.MakeUnsigned(); R.MakeUnsigned(); result = (L <= R); break; + case CmpInst::FCMP_OLE: + result = (L <= R); + break; case CmpInst::ICMP_SGT: L.MakeSigned(); R.MakeSigned(); diff --git a/lldb/source/Host/CMakeLists.txt b/lldb/source/Host/CMakeLists.txt index 7456cb98bfa1..1cf30c20a030 100644 --- a/lldb/source/Host/CMakeLists.txt +++ b/lldb/source/Host/CMakeLists.txt @@ -99,7 +99,7 @@ else() endif() - elseif (CMAKE_SYSTEM_NAME MATCHES "Linux|Android") + elseif (CMAKE_SYSTEM_NAME MATCHES "Linux|Android|OHOS") add_host_subdirectory(linux linux/AbstractSocket.cpp linux/Host.cpp @@ -113,6 +113,11 @@ else() android/LibcGlue.cpp ) endif() + if (CMAKE_SYSTEM_NAME MATCHES "OHOS") + add_host_subdirectory(ohos + ohos/HostInfoOHOS.cpp + ) + endif() elseif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") add_host_subdirectory(freebsd freebsd/Host.cpp diff --git a/lldb/source/Host/common/MainLoop.cpp b/lldb/source/Host/common/MainLoop.cpp index 02cabbc93550..fc8b94309b09 100644 --- a/lldb/source/Host/common/MainLoop.cpp +++ b/lldb/source/Host/common/MainLoop.cpp @@ -86,7 +86,7 @@ private: int num_events = -1; #else -#ifdef __ANDROID__ +#if defined(__ANDROID__) fd_set read_fd_set; #else std::vector read_fds; @@ -140,7 +140,7 @@ void MainLoop::RunImpl::ProcessEvents() { } #else MainLoop::RunImpl::RunImpl(MainLoop &loop) : loop(loop) { -#ifndef __ANDROID__ +#if !defined(__ANDROID__) read_fds.reserve(loop.m_read_fds.size()); #endif } @@ -162,7 +162,7 @@ sigset_t MainLoop::RunImpl::get_sigmask() { return sigmask; } -#ifdef __ANDROID__ +#if defined(__ANDROID__) Status MainLoop::RunImpl::Poll() { // ppoll(2) is not supported on older all android versions. Also, older // versions android (API <= 19) implemented pselect in a non-atomic way, as a @@ -218,7 +218,7 @@ Status MainLoop::RunImpl::Poll() { #endif void MainLoop::RunImpl::ProcessEvents() { -#ifdef __ANDROID__ +#if defined(__ANDROID__) // Collect first all readable file descriptors into a separate vector and // then iterate over it to invoke callbacks. Iterating directly over // loop.m_read_fds is not possible because the callbacks can modify the diff --git a/lldb/source/Host/common/Socket.cpp b/lldb/source/Host/common/Socket.cpp index 4bcf34a6b456..f4037da059e5 100644 --- a/lldb/source/Host/common/Socket.cpp +++ b/lldb/source/Host/common/Socket.cpp @@ -38,7 +38,7 @@ #include "lldb/Host/linux/AbstractSocket.h" #endif -#ifdef __ANDROID__ +#if defined(__ANDROID__) #include #include #include diff --git a/lldb/source/Host/common/TCPSocket.cpp b/lldb/source/Host/common/TCPSocket.cpp index ea7377edbd45..c9f4db5fae49 100644 --- a/lldb/source/Host/common/TCPSocket.cpp +++ b/lldb/source/Host/common/TCPSocket.cpp @@ -162,6 +162,8 @@ Status TCPSocket::Connect(llvm::StringRef name) { std::vector addresses = SocketAddress::GetAddressInfo( host_str.c_str(), nullptr, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP); + llvm::partition(addresses, + [](auto &sa) { return sa.GetFamily() == AF_INET; }); for (SocketAddress &address : addresses) { error = CreateSocket(address.GetFamily()); if (error.Fail()) diff --git a/lldb/source/Host/ohos/HostInfoOHOS.cpp b/lldb/source/Host/ohos/HostInfoOHOS.cpp new file mode 100644 index 000000000000..e47d26e3e938 --- /dev/null +++ b/lldb/source/Host/ohos/HostInfoOHOS.cpp @@ -0,0 +1,94 @@ +//===-- HostInfoOHOS.cpp -------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/ohos/HostInfoOHOS.h" +#include "lldb/Host/FileSystem.h" +#include "lldb/Host/linux/HostInfoLinux.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" + +using namespace lldb_private; +using namespace llvm; + +void HostInfoOHOS::ComputeHostArchitectureSupport(ArchSpec &arch_32, + ArchSpec &arch_64) { + HostInfoLinux::ComputeHostArchitectureSupport(arch_32, arch_64); + + if (arch_32.IsValid()) { + arch_32.GetTriple().setEnvironment(llvm::Triple::UnknownEnvironment); + } + if (arch_64.IsValid()) { + arch_64.GetTriple().setEnvironment(llvm::Triple::UnknownEnvironment); + } +} + +FileSpec HostInfoOHOS::GetDefaultShell() { + return FileSpec("/system/bin/sh"); +} + +FileSpec HostInfoOHOS::ResolveLibraryPath(const std::string &module_path, + const ArchSpec &arch) { + static const char *const ld_library_path_separator = ":"; + static const char *const default_lib32_path[] = {"/vendor/lib", "/system/lib", + nullptr}; + static const char *const default_lib64_path[] = {"/vendor/lib64", + "/system/lib64", nullptr}; + + if (module_path.empty() || module_path[0] == '/') { + FileSpec file_spec(module_path.c_str()); + FileSystem::Instance().Resolve(file_spec); + return file_spec; + } + + SmallVector ld_paths; + + if (const char *ld_library_path = ::getenv("LD_LIBRARY_PATH")) + StringRef(ld_library_path) + .split(ld_paths, StringRef(ld_library_path_separator), -1, false); + + const char *const *default_lib_path = nullptr; + switch (arch.GetAddressByteSize()) { + case 4: + default_lib_path = default_lib32_path; + break; + case 8: + default_lib_path = default_lib64_path; + break; + default: + assert(false && "Unknown address byte size"); + return FileSpec(); + } + + for (const char *const *it = default_lib_path; *it; ++it) + ld_paths.push_back(StringRef(*it)); + + for (const StringRef &path : ld_paths) { + FileSpec file_candidate(path.str().c_str()); + FileSystem::Instance().Resolve(file_candidate); + file_candidate.AppendPathComponent(module_path.c_str()); + + if (FileSystem::Instance().Exists(file_candidate)) + return file_candidate; + } + + return FileSpec(); +} + +bool HostInfoOHOS::ComputeTempFileBaseDirectory(FileSpec &file_spec) { + bool success = HostInfoLinux::ComputeTempFileBaseDirectory(file_spec); + + // On OHOS, there is no path which is guaranteed to be writable. If the + // user has not provided a path via an environment variable, the generic + // algorithm will deduce /tmp, which is plain wrong. In that case we have an + // invalid directory, we substitute the path with /data/local/tmp, which is + // correct at least in some cases (i.e., when running as shell user). + if (!success || !FileSystem::Instance().Exists(file_spec)) + file_spec = FileSpec("/data/local/tmp"); + + return FileSystem::Instance().Exists(file_spec); +} diff --git a/lldb/source/Host/posix/DomainSocket.cpp b/lldb/source/Host/posix/DomainSocket.cpp index 5a396906fdf6..97e8d4859e14 100644 --- a/lldb/source/Host/posix/DomainSocket.cpp +++ b/lldb/source/Host/posix/DomainSocket.cpp @@ -18,7 +18,7 @@ using namespace lldb; using namespace lldb_private; -#ifdef __ANDROID__ +#if defined(__ANDROID__) // Android does not have SUN_LEN #ifndef SUN_LEN #define SUN_LEN(ptr) \ diff --git a/lldb/source/Host/posix/HostInfoPosix.cpp b/lldb/source/Host/posix/HostInfoPosix.cpp index 7e110f07d7cf..cbfdf60a0a0a 100644 --- a/lldb/source/Host/posix/HostInfoPosix.cpp +++ b/lldb/source/Host/posix/HostInfoPosix.cpp @@ -86,7 +86,7 @@ llvm::Optional PosixUserIDResolver::DoGetUserName(id_t uid) { } llvm::Optional PosixUserIDResolver::DoGetGroupName(id_t gid) { -#ifndef __ANDROID__ +#if !defined(__ANDROID__) && !defined(__OHOS_FAMILY__) char group_buffer[PATH_MAX]; size_t group_buffer_size = sizeof(group_buffer); struct group group_info; diff --git a/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp b/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp index 35482341d3e6..de622473272a 100644 --- a/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp +++ b/lldb/source/Host/posix/ProcessLauncherPosixFork.cpp @@ -38,7 +38,7 @@ using namespace lldb; using namespace lldb_private; static void FixupEnvironment(Environment &env) { -#ifdef __ANDROID__ +#if defined(__ANDROID__) // If there is no PATH variable specified inside the environment then set the // path to /system/bin. It is required because the default path used by // execve() is wrong on android. diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp index 9be294750fa0..7e0da5663b37 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -519,7 +519,7 @@ CppModuleConfiguration GetModuleConfig(lldb::LanguageType language, // Try to create a configuration from the files. If there is no valid // configuration possible with the files, this just returns an invalid // configuration. - return CppModuleConfiguration(files); + return CppModuleConfiguration(files, target->GetArchitecture().GetTriple()); } bool ClangUserExpression::PrepareForParsing( diff --git a/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp b/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp index ffab16b1682b..7148a7c236d6 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.cpp @@ -10,6 +10,7 @@ #include "ClangHost.h" #include "lldb/Host/FileSystem.h" +#include "llvm/ADT/Triple.h" using namespace lldb_private; @@ -30,7 +31,29 @@ bool CppModuleConfiguration::SetOncePath::TrySet(llvm::StringRef path) { return false; } -bool CppModuleConfiguration::analyzeFile(const FileSpec &f) { +static std::string targetSpecificIncludePath(const llvm::Triple &triple) { + if (triple.getArchName().empty() || triple.getOSAndEnvironmentName().empty()) + return ""; + return ("/usr/include/" + triple.getArchName() + "-" + + triple.getOSAndEnvironmentName()) + .str(); +} + +static bool guessIncludePath(llvm::StringRef pathToFile, + llvm::StringRef pattern, llvm::StringRef &result) { + result = llvm::StringRef(); + if (pattern.empty()) + return false; + size_t pos = pathToFile.find(pattern); + if (pos == llvm::StringRef::npos) + return false; + + result = pathToFile.substr(0, pos + pattern.size()); + return true; +} + +bool CppModuleConfiguration::analyzeFile(const FileSpec &f, + const llvm::Triple &triple) { using namespace llvm::sys::path; // Convert to slashes to make following operations simpler. std::string dir_buffer = convert_to_slash(f.GetDirectory().GetStringRef()); @@ -46,12 +69,12 @@ bool CppModuleConfiguration::analyzeFile(const FileSpec &f) { return m_std_inc.TrySet(posix_dir); } - // Check for /usr/include. On Linux this might be /usr/include/bits, so - // we should remove that '/bits' suffix to get the actual include directory. - if (posix_dir.endswith("/usr/include/bits")) - posix_dir.consume_back("/bits"); - if (posix_dir.endswith("/usr/include")) - return m_c_inc.TrySet(posix_dir); + llvm::StringRef inc_path; + // Target specific path contains /usr/include, so we check it first + if (guessIncludePath(posix_dir, targetSpecificIncludePath(triple), inc_path)) + return m_c_target_inc.TrySet(inc_path); + if (guessIncludePath(posix_dir, "/usr/include", inc_path)) + return m_c_inc.TrySet(inc_path); // File wasn't interesting, continue analyzing. return true; @@ -92,11 +115,11 @@ bool CppModuleConfiguration::hasValidConfig() { } CppModuleConfiguration::CppModuleConfiguration( - const FileSpecList &support_files) { + const FileSpecList &support_files, const llvm::Triple &triple) { // Analyze all files we were given to build the configuration. bool error = !llvm::all_of(support_files, std::bind(&CppModuleConfiguration::analyzeFile, - this, std::placeholders::_1)); + this, std::placeholders::_1, triple)); // If we have a valid configuration at this point, set the // include directories and module list that should be used. if (!error && hasValidConfig()) { @@ -109,6 +132,8 @@ CppModuleConfiguration::CppModuleConfiguration( // This order matches the way Clang orders these directories. m_include_dirs = {m_std_inc.Get().str(), m_resource_inc, m_c_inc.Get().str()}; + if (m_c_target_inc.Valid()) + m_include_dirs.push_back(m_c_target_inc.Get().str()); m_imported_modules = {"std"}; } } diff --git a/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h b/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h index b984db43fa6d..60199005b6ba 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h @@ -44,6 +44,9 @@ class CppModuleConfiguration { SetOncePath m_std_inc; /// If valid, the include path to the C library (e.g. /usr/include). SetOncePath m_c_inc; + /// If valid, the include path to target-specific C library files + /// (e.g. /usr/include/x86_64-linux-gnu). + SetOncePath m_c_target_inc; /// The Clang resource include path for this configuration. std::string m_resource_inc; @@ -53,11 +56,12 @@ class CppModuleConfiguration { /// Analyze a given source file to build the current configuration. /// Returns false iff there was a fatal error that makes analyzing any /// further files pointless as the configuration is now invalid. - bool analyzeFile(const FileSpec &f); + bool analyzeFile(const FileSpec &f, const llvm::Triple &triple); public: /// Creates a configuration by analyzing the given list of used source files. - explicit CppModuleConfiguration(const FileSpecList &support_files); + explicit CppModuleConfiguration(const FileSpecList &support_files, + const llvm::Triple &triple); /// Creates an empty and invalid configuration. CppModuleConfiguration() {} diff --git a/lldb/source/Plugins/Platform/CMakeLists.txt b/lldb/source/Plugins/Platform/CMakeLists.txt index 5f284e517dca..8c532955a9dd 100644 --- a/lldb/source/Plugins/Platform/CMakeLists.txt +++ b/lldb/source/Plugins/Platform/CMakeLists.txt @@ -15,3 +15,4 @@ add_subdirectory(POSIX) add_subdirectory(gdb-server) add_subdirectory(Android) +add_subdirectory(OHOS) diff --git a/lldb/source/Plugins/Platform/Linux/PlatformLinux.cpp b/lldb/source/Plugins/Platform/Linux/PlatformLinux.cpp index 2cb671fd4dc3..9cdc9d5f434c 100644 --- a/lldb/source/Plugins/Platform/Linux/PlatformLinux.cpp +++ b/lldb/source/Plugins/Platform/Linux/PlatformLinux.cpp @@ -97,7 +97,7 @@ void PlatformLinux::Initialize() { PlatformPOSIX::Initialize(); if (g_initialize_count++ == 0) { -#if defined(__linux__) && !defined(__ANDROID__) +#if defined(__linux__) && !defined(__ANDROID__) && !defined(__OHOS_FAMILY__) PlatformSP default_platform_sp(new PlatformLinux(true)); default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture()); Platform::SetHostPlatform(default_platform_sp); diff --git a/lldb/source/Plugins/Platform/OHOS/CMakeLists.txt b/lldb/source/Plugins/Platform/OHOS/CMakeLists.txt new file mode 100644 index 000000000000..cc71762efe2e --- /dev/null +++ b/lldb/source/Plugins/Platform/OHOS/CMakeLists.txt @@ -0,0 +1,13 @@ +add_lldb_library(lldbPluginPlatformOHOS PLUGIN + HdcClient.cpp + PlatformOHOS.cpp + PlatformOHOSRemoteGDBServer.cpp + + LINK_LIBS + lldbCore + lldbHost + lldbPluginPlatformLinux + lldbPluginPlatformGDB + LINK_COMPONENTS + Support + ) diff --git a/lldb/source/Plugins/Platform/OHOS/HdcClient.cpp b/lldb/source/Plugins/Platform/OHOS/HdcClient.cpp new file mode 100644 index 000000000000..97fa08fb44da --- /dev/null +++ b/lldb/source/Plugins/Platform/OHOS/HdcClient.cpp @@ -0,0 +1,379 @@ +//===-- HdcClient.cpp -------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "HdcClient.h" + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/FileUtilities.h" + +#include "lldb/Host/ConnectionFileDescriptor.h" +#include "lldb/Host/FileSystem.h" +#include "lldb/Host/PosixApi.h" +#include "lldb/Utility/DataBuffer.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/DataEncoder.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/StreamString.h" +#include "lldb/Utility/Timeout.h" + +#if defined(_WIN32) +#include +#else +#include +#endif + +#include + +#include +#include +#include +#include + +// On Windows, transitive dependencies pull in , which defines a +// macro that clashes with a method name. +#ifdef SendMessage +#undef SendMessage +#endif + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::platform_ohos; +using namespace std::chrono; + +namespace { + +const seconds kReadTimeout(20); +const char *kSocketNamespaceAbstract = "localabstract"; +const char *kSocketNamespaceFileSystem = "localfilesystem"; + +Status ReadAllBytes(Connection &conn, void *buffer, size_t size, + size_t *read_ptr, ConnectionStatus *status_ptr) { + + Status error; + ConnectionStatus status; + char *read_buffer = static_cast(buffer); + + auto now = steady_clock::now(); + const auto deadline = now + kReadTimeout; + size_t total_read_bytes = 0; + while (total_read_bytes < size && now < deadline) { + auto read_bytes = + conn.Read(read_buffer + total_read_bytes, size - total_read_bytes, + duration_cast(deadline - now), status, &error); + if (status_ptr) + *status_ptr = status; + if (error.Fail()) + return error; + total_read_bytes += read_bytes; + if (read_ptr) + *read_ptr = total_read_bytes; + if (status != eConnectionStatusSuccess) + break; + now = steady_clock::now(); + } + if (total_read_bytes < size) + error = Status( + "Unable to read requested number of bytes. Connection status: %d.", + status); + return error; +} + +} // namespace + +Status HdcClient::CreateByDeviceID(const std::string &device_id, + HdcClient &hdc) { + DeviceIDList connect_devices; + auto error = hdc.GetDevices(connect_devices); + if (error.Fail()) + return error; + + std::string hdc_utid; + if (!device_id.empty()) + hdc_utid = device_id; + else if (const char *env_hdc_utid = std::getenv("HDC_UTID")) + hdc_utid = env_hdc_utid; + + if (hdc_utid.empty()) { + if (connect_devices.size() != 1) + return Status("Expected a single connected device, got instead %zu - try " + "setting 'HDC_UTID'", + connect_devices.size()); + hdc.SetDeviceID(connect_devices.front()); + } else { + auto find_it = std::find(connect_devices.begin(), connect_devices.end(), + hdc_utid); + if (find_it == connect_devices.end()) + return Status( + "Device \"%s\" not found, check HDC_UTID environment variable", + hdc_utid.c_str()); + + hdc.SetDeviceID(*find_it); + } + return error; +} + +HdcClient::HdcClient() {} + +HdcClient::HdcClient(const std::string &device_id) : m_device_id(device_id) {} + +HdcClient::~HdcClient() {} + +void HdcClient::SetDeviceID(const std::string &device_id) { + m_device_id = device_id; +} + +const std::string &HdcClient::GetDeviceID() const { return m_device_id; } + +namespace { +typedef unsigned msg_len_t; +struct ChannelHandShake { + msg_len_t size; + char banner[12]; // must first index + union { + uint32_t channelId; + char connectKey[32]; + }; +} __attribute__((packed)); +} // namespace + +Status HdcClient::Connect() { + Status error; + ChannelHandShake handshake = {}; + if (m_device_id.size() > sizeof(handshake.connectKey)) + return Status("Device id is too long: %s", m_device_id.c_str()); + m_conn.reset(new ConnectionFileDescriptor); + std::string port = "8710"; + + const char *env_port = std::getenv("OHOS_HDC_SERVER_PORT"); + if ((env_port != NULL) && (atoi(env_port) > 0)) { + port = env_port; + } + + std::string uri = "connect://localhost:" + port; + m_conn->Connect(uri.c_str(), &error); + ConnectionStatus status = eConnectionStatusError; + if (error.Success()) { + error = ReadAllBytes(&handshake, sizeof(handshake)); + if (error.Success()) { + memset(handshake.connectKey, 0, sizeof(handshake.connectKey)); + memcpy(handshake.connectKey, m_device_id.c_str(), m_device_id.size()); + m_conn->Write(&handshake, sizeof(handshake), status, &error); + } + } + return error; +} + +Status HdcClient::GetDevices(DeviceIDList &device_list) { + device_list.clear(); + + auto error = SendMessage("list targets"); + if (error.Fail()) + return error; + + std::vector in_buffer; + error = ReadMessage(in_buffer); + + llvm::StringRef response(&in_buffer[0], in_buffer.size()); + llvm::SmallVector devices; + response.split(devices, "\n", -1, false); + + for (const auto device : devices) + device_list.push_back(static_cast(device.split('\t').first)); + + // Force disconnect since ADB closes connection after host:devices response + // is sent. + m_conn.reset(); + return error; +} + +Status HdcClient::SetPortForwarding(const uint16_t local_port, + const uint16_t remote_port) { + char message[48]; + snprintf(message, sizeof(message), "fport tcp:%d tcp:%d", local_port, + remote_port); + + const auto error = SendMessage(message); + if (error.Fail()) + return error; + + return ReadResponseStatus("Forwardport result:OK"); +} + +Status +HdcClient::SetPortForwarding(const uint16_t local_port, + llvm::StringRef remote_socket_name, + const UnixSocketNamespace socket_namespace) { + char message[PATH_MAX]; + const char *sock_namespace_str = + (socket_namespace == UnixSocketNamespaceAbstract) + ? kSocketNamespaceAbstract + : kSocketNamespaceFileSystem; + snprintf(message, sizeof(message), "fport tcp:%d %s:%s", local_port, + sock_namespace_str, remote_socket_name.str().c_str()); + + const auto error = SendMessage(message); + if (error.Fail()) + return error; + + return ReadResponseStatus("Forwardport result:OK"); +} + +Status HdcClient::DeletePortForwarding(std::pair fwd) { + char message[32]; + snprintf(message, sizeof(message), "fport rm tcp:%d tcp:%d", fwd.first, + fwd.second); + + const auto error = SendMessage(message); + if (error.Fail()) + return error; + + return ReadResponseStatus(nullptr); +} + +Status HdcClient::TransferFile(const char *direction, const FileSpec &src, + const FileSpec &dst) { + llvm::SmallVector cwd; + std::error_code ec = llvm::sys::fs::current_path(cwd); + if (ec) + return Status(ec); + + std::stringstream cmd; + cmd << "file " << direction << " -cwd "; + cmd.write(cwd.data(), cwd.size()); + cmd << " " << src.GetPath() << " " << dst.GetPath(); + Status error = SendMessage(cmd.str()); + if (error.Fail()) + return error; + + return ReadResponseStatus("FileTransfer finish"); +} + +Status HdcClient::RecvFile(const FileSpec &src, const FileSpec &dst) { + return TransferFile("recv", src, dst); +} + +Status HdcClient::SendFile(const FileSpec &src, const FileSpec &dst) { + return TransferFile("send", src, dst); +} + +Status HdcClient::SendMessage(llvm::StringRef packet, const bool reconnect) { + Status error; + if (!m_conn || reconnect) { + error = Connect(); + if (error.Fail()) + return error; + } + + unsigned msg_len = packet.size() + 1; + llvm::SmallVector message(msg_len + sizeof(msg_len_t), 0); + msg_len_t len = htonl(msg_len); + memcpy(message.data(), &len, sizeof(len)); + memcpy(message.data() + sizeof(len), packet.data(), packet.size()); + + ConnectionStatus status; + m_conn->Write(message.data(), message.size(), status, &error); + if (error.Fail()) + return error; + + return error; +} + +Status HdcClient::ReadMessage(std::vector &message) { + message.clear(); + + msg_len_t packet_len; + auto error = ReadAllBytes(&packet_len, sizeof(packet_len)); + if (error.Fail()) + return error; + + packet_len = htonl(packet_len); + message.resize(packet_len, 0); + error = ReadAllBytes(&message[0], packet_len); + if (error.Fail()) + message.clear(); + + return error; +} + +Status HdcClient::ReadMessageStream(std::vector &message, + milliseconds timeout) { + auto start = steady_clock::now(); + message.clear(); + + Status error; + lldb::ConnectionStatus status = lldb::eConnectionStatusSuccess; + char buffer[1024]; + while (error.Success() && status == lldb::eConnectionStatusSuccess) { + auto end = steady_clock::now(); + auto elapsed = end - start; + if (elapsed >= timeout) + return Status("Timed out"); + + size_t n = m_conn->Read(buffer, sizeof(buffer), + duration_cast(timeout - elapsed), + status, &error); + if (n > 0) + message.insert(message.end(), &buffer[0], &buffer[n]); + } + return error; +} + +Status HdcClient::ReadResponseStatus(const char *expected) { + msg_len_t len; + ConnectionStatus conn_status; + size_t read; + + auto error = ::ReadAllBytes(*m_conn, &len, sizeof(len), &read, &conn_status); + // Special case: we expect server to close connection + if (expected == nullptr) { + if (read == 0 && conn_status == eConnectionStatusEndOfFile) + return Status(); + else if (error.Fail()) + return error; + // Something went wrong - response is not empty + // Read it and wrap to error object + } + + len = htonl(len); + llvm::SmallVector message(len + 1); + error = ReadAllBytes(message.data(), len); + if (error.Fail()) + return error; + + message[len] = 0; + if (expected == nullptr || + strncmp(message.data(), expected, strlen(expected))) + return Status("%s", message.data()); + + return error; +} + +Status HdcClient::ReadAllBytes(void *buffer, size_t size) { + return ::ReadAllBytes(*m_conn, buffer, size, nullptr, nullptr); +} + +Status HdcClient::Shell(const char *command, milliseconds timeout, + std::string *output) { + assert(command && command[0]); + std::string cmd = "shell "; + cmd += command; + Status error = SendMessage(cmd); + if (error.Fail()) + return error; + + std::vector message; + error = ReadMessageStream(message, timeout); + if (error.Fail()) + return error; + + (*output) = std::string(message.data(), message.size()); + return error; +} diff --git a/lldb/source/Plugins/Platform/OHOS/HdcClient.h b/lldb/source/Plugins/Platform/OHOS/HdcClient.h new file mode 100644 index 000000000000..64a5a324325a --- /dev/null +++ b/lldb/source/Plugins/Platform/OHOS/HdcClient.h @@ -0,0 +1,90 @@ +//===-- HdcClient.h ---------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_HdcClient_h_ +#define liblldb_HdcClient_h_ + +#include "lldb/Utility/Status.h" +#include +#include +#include +#include +#include +#include + +namespace lldb_private { + +class FileSpec; + +namespace platform_ohos { + +class HdcClient { +public: + enum UnixSocketNamespace { + UnixSocketNamespaceAbstract, + UnixSocketNamespaceFileSystem, + }; + + using DeviceIDList = std::list; + + static Status CreateByDeviceID(const std::string &device_id, HdcClient &hdc); + + HdcClient(); + explicit HdcClient(const std::string &device_id); + + ~HdcClient(); + + const std::string &GetDeviceID() const; + + Status GetDevices(DeviceIDList &device_list); + + Status SetPortForwarding(const uint16_t local_port, + const uint16_t remote_port); + + Status SetPortForwarding(const uint16_t local_port, + llvm::StringRef remote_socket_name, + const UnixSocketNamespace socket_namespace); + + Status DeletePortForwarding(std::pair fwd); + + Status RecvFile(const FileSpec &src, const FileSpec &dst); + + Status SendFile(const FileSpec &src, const FileSpec &dst); + + Status Shell(const char *command, std::chrono::milliseconds timeout, + std::string *output); + +private: + Status Connect(); + + Status TransferFile(const char *direction, const FileSpec &src, + const FileSpec &dst); + + void SetDeviceID(const std::string &device_id); + + Status SendMessage(llvm::StringRef packet, const bool reconnect = true); + + Status SendDeviceMessage(const std::string &packet); + + Status ReadMessage(std::vector &message); + + Status ReadMessageStream(std::vector &message, + std::chrono::milliseconds timeout); + + Status ReadResponseStatus(const char *expected); + + Status ReadAllBytes(void *buffer, size_t size); + + std::string m_device_id; + std::unique_ptr m_conn; +}; + +} // namespace platform_ohos +} // namespace lldb_private + +#endif // liblldb_HdcClient_h_ diff --git a/lldb/source/Plugins/Platform/OHOS/PlatformOHOS.cpp b/lldb/source/Plugins/Platform/OHOS/PlatformOHOS.cpp new file mode 100644 index 000000000000..f76e016bb6aa --- /dev/null +++ b/lldb/source/Plugins/Platform/OHOS/PlatformOHOS.cpp @@ -0,0 +1,266 @@ +//===-- PlatformOHOS.cpp -------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/Module.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Section.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Host/StringConvert.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/Scalar.h" +#include "lldb/Utility/UriParser.h" + +#include "HdcClient.h" +#include "PlatformOHOS.h" +#include "PlatformOHOSRemoteGDBServer.h" +#include "lldb/Target/Target.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::platform_ohos; +using namespace std::chrono; + +static uint32_t g_initialize_count = 0; +static const unsigned int g_ohos_default_cache_size = + 2048; // Fits inside 4k adb packet. + +LLDB_PLUGIN_DEFINE(PlatformOHOS); + +void PlatformOHOS::Initialize() { + PlatformLinux::Initialize(); + + if (g_initialize_count++ == 0) { +#if defined(__OHOS_FAMILY__) + PlatformSP default_platform_sp(new PlatformOHOS(true)); + default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture()); + Platform::SetHostPlatform(default_platform_sp); +#endif + PluginManager::RegisterPlugin( + PlatformOHOS::GetPluginNameStatic(false), + PlatformOHOS::GetPluginDescriptionStatic(false), + PlatformOHOS::CreateInstance); + } +} + +void PlatformOHOS::Terminate() { + if (g_initialize_count > 0) { + if (--g_initialize_count == 0) { + PluginManager::UnregisterPlugin(PlatformOHOS::CreateInstance); + } + } + + PlatformLinux::Terminate(); +} + +PlatformSP PlatformOHOS::CreateInstance(bool force, const ArchSpec *arch) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + if (log) { + const char *arch_name; + if (arch && arch->GetArchitectureName()) + arch_name = arch->GetArchitectureName(); + else + arch_name = ""; + + const char *triple_cstr = + arch ? arch->GetTriple().getTriple().c_str() : ""; + + log->Printf("PlatformOHOS::%s(force=%s, arch={%s,%s})", __FUNCTION__, + force ? "true" : "false", arch_name, triple_cstr); + } + + bool create = force; + if (!create && arch && arch->IsValid()) { + const llvm::Triple &triple = arch->GetTriple(); + switch (triple.getVendor()) { + case llvm::Triple::PC: + create = true; + break; + default: + break; + } + + if (create) { + switch (triple.getEnvironment()) { + case llvm::Triple::OpenHOS: + break; + default: + create = false; + break; + } + } + } + + if (create) { + if (log) + log->Printf("PlatformOHOS::%s() creating remote-ohos platform", + __FUNCTION__); + + return PlatformSP(new PlatformOHOS(false)); + } + + if (log) + log->Printf( + "PlatformOHOS::%s() aborting creation of remote-ohos platform", + __FUNCTION__); + + return PlatformSP(); +} + +PlatformOHOS::PlatformOHOS(bool is_host) : PlatformLinux(is_host) {} + +PlatformOHOS::~PlatformOHOS() {} + +ConstString PlatformOHOS::GetPluginNameStatic(bool is_host) { + if (is_host) { + static ConstString g_host_name(Platform::GetHostPlatformName()); + return g_host_name; + } else { + static ConstString g_remote_name("remote-ohos"); + return g_remote_name; + } +} + +const char *PlatformOHOS::GetPluginDescriptionStatic(bool is_host) { + if (is_host) + return "Local OpenHarmony OS user platform plug-in."; + else + return "Remote OpenHarmony OS user platform plug-in."; +} + +ConstString PlatformOHOS::GetPluginName() { + return GetPluginNameStatic(IsHost()); +} + +Status PlatformOHOS::ConnectRemote(Args &args) { + m_device_id.clear(); + + if (IsHost()) { + return Status("can't connect to the host platform '%s', always connected", + GetPluginName().GetCString()); + } + + if (!m_remote_platform_sp) + m_remote_platform_sp = PlatformSP(new PlatformOHOSRemoteGDBServer()); + + int port; + llvm::StringRef scheme, host, path; + const char *url = args.GetArgumentAtIndex(0); + if (!url) + return Status("URL is null."); + if (!UriParser::Parse(url, scheme, host, port, path)) + return Status("Invalid URL: %s", url); + if (host != "localhost") + m_device_id = static_cast(host); + + auto error = PlatformLinux::ConnectRemote(args); + if (error.Success()) { + HdcClient adb; + error = HdcClient::CreateByDeviceID(m_device_id, adb); + if (error.Fail()) + return error; + + m_device_id = adb.GetDeviceID(); + } + return error; +} + +Status PlatformOHOS::GetFile(const FileSpec &source, + const FileSpec &destination) { + if (IsHost() || !m_remote_platform_sp) + return PlatformLinux::GetFile(source, destination); + + FileSpec source_spec(source.GetPath(false), FileSpec::Style::posix); + if (source_spec.IsRelative()) + source_spec = GetRemoteWorkingDirectory().CopyByAppendingPathComponent( + source_spec.GetCString(false)); + + HdcClient hdc(m_device_id); + Status error = hdc.RecvFile(source, destination); + return error; +} + +Status PlatformOHOS::PutFile(const FileSpec &source, + const FileSpec &destination, uint32_t uid, + uint32_t gid) { + if (IsHost() || !m_remote_platform_sp) + return PlatformLinux::PutFile(source, destination, uid, gid); + + FileSpec destination_spec(destination.GetPath(false), FileSpec::Style::posix); + if (destination_spec.IsRelative()) + destination_spec = GetRemoteWorkingDirectory().CopyByAppendingPathComponent( + destination_spec.GetCString(false)); + + // TODO: Set correct uid and gid on remote file. + HdcClient hdc(m_device_id); + Status error = hdc.SendFile(source, destination_spec); + return error; +} + +const char *PlatformOHOS::GetCacheHostname() { return m_device_id.c_str(); } + +Status PlatformOHOS::DownloadModuleSlice(const FileSpec &src_file_spec, + const uint64_t src_offset, + const uint64_t src_size, + const FileSpec &dst_file_spec) { + if (src_offset != 0) + return Status("Invalid offset - %" PRIu64, src_offset); + + return GetFile(src_file_spec, dst_file_spec); +} + +Status PlatformOHOS::DisconnectRemote() { + Status error = PlatformLinux::DisconnectRemote(); + if (error.Success()) + m_device_id.clear(); + return error; +} + +uint32_t PlatformOHOS::GetDefaultMemoryCacheLineSize() { + return g_ohos_default_cache_size; +} + +uint32_t PlatformOHOS::GetSdkVersion() { + if (!IsConnected()) + return 0; + + // TBD + return 1; +} + +bool PlatformOHOS::GetRemoteOSVersion() { + m_os_version = llvm::VersionTuple(GetSdkVersion()); + return !m_os_version.empty(); +} + +llvm::StringRef +PlatformOHOS::GetLibdlFunctionDeclarations(lldb_private::Process *process) { + SymbolContextList matching_symbols; + std::vector dl_open_names = { "__dl_dlopen", "dlopen" }; + const char *dl_open_name = nullptr; + Target &target = process->GetTarget(); + for (auto name: dl_open_names) { + target.GetImages().FindFunctionSymbols(ConstString(name), + eFunctionNameTypeFull, + matching_symbols); + if (matching_symbols.GetSize()) { + dl_open_name = name; + break; + } + } + // Older platform versions have the dl function symbols mangled + if (dl_open_name == dl_open_names[0]) + return R"( + extern "C" void* dlopen(const char*, int) asm("__dl_dlopen"); + extern "C" void* dlsym(void*, const char*) asm("__dl_dlsym"); + extern "C" int dlclose(void*) asm("__dl_dlclose"); + extern "C" char* dlerror(void) asm("__dl_dlerror"); + )"; + + return PlatformPOSIX::GetLibdlFunctionDeclarations(process); +} diff --git a/lldb/source/Plugins/Platform/OHOS/PlatformOHOS.h b/lldb/source/Plugins/Platform/OHOS/PlatformOHOS.h new file mode 100644 index 000000000000..643b7ae3f75f --- /dev/null +++ b/lldb/source/Plugins/Platform/OHOS/PlatformOHOS.h @@ -0,0 +1,80 @@ +//===-- PlatformOHOS.h ---------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_PlatformOHOS_h_ +#define liblldb_PlatformOHOS_h_ + +#include +#include + +#include "Plugins/Platform/Linux/PlatformLinux.h" + +#include "HdcClient.h" + +namespace lldb_private { +namespace platform_ohos { + +class PlatformOHOS : public platform_linux::PlatformLinux { +public: + PlatformOHOS(bool is_host); + + ~PlatformOHOS() override; + + static void Initialize(); + + static void Terminate(); + + // lldb_private::PluginInterface functions + static lldb::PlatformSP CreateInstance(bool force, const ArchSpec *arch); + + static ConstString GetPluginNameStatic(bool is_host); + + static const char *GetPluginDescriptionStatic(bool is_host); + + ConstString GetPluginName() override; + + uint32_t GetPluginVersion() override { return 1; } + + // lldb_private::Platform functions + + Status ConnectRemote(Args &args) override; + + Status GetFile(const FileSpec &source, const FileSpec &destination) override; + + Status PutFile(const FileSpec &source, const FileSpec &destination, + uint32_t uid = UINT32_MAX, uint32_t gid = UINT32_MAX) override; + + uint32_t GetSdkVersion(); + + bool GetRemoteOSVersion() override; + + Status DisconnectRemote() override; + + uint32_t GetDefaultMemoryCacheLineSize() override; + +protected: + const char *GetCacheHostname() override; + + Status DownloadModuleSlice(const FileSpec &src_file_spec, + const uint64_t src_offset, const uint64_t src_size, + const FileSpec &dst_file_spec) override; + + llvm::StringRef + GetLibdlFunctionDeclarations(lldb_private::Process *process) override; + +private: + std::string m_device_id; + + PlatformOHOS(const PlatformOHOS &other) = delete; + PlatformOHOS& operator=(const PlatformOHOS &other) = delete; +}; + +} // namespace platofor_ohos +} // namespace lldb_private + +#endif // liblldb_PlatformOHOS_h_ diff --git a/lldb/source/Plugins/Platform/OHOS/PlatformOHOSRemoteGDBServer.cpp b/lldb/source/Plugins/Platform/OHOS/PlatformOHOSRemoteGDBServer.cpp new file mode 100644 index 000000000000..62dc0639afef --- /dev/null +++ b/lldb/source/Plugins/Platform/OHOS/PlatformOHOSRemoteGDBServer.cpp @@ -0,0 +1,247 @@ +//===-- PlatformOHOSRemoteGDBServer.cpp ----------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/ConnectionFileDescriptor.h" +#include "lldb/Host/common/TCPSocket.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/Status.h" +#include "lldb/Utility/UriParser.h" + +#include "PlatformOHOSRemoteGDBServer.h" + +#include + +using namespace lldb; +using namespace lldb_private; +using namespace platform_ohos; + +static const lldb::pid_t g_remote_platform_pid = + 0; // Alias for the process id of lldb-platform + +static uint16_t g_hdc_forward_port_offset = 0; + +static Status ForwardPortWithHdc( + const uint16_t local_port, const uint16_t remote_port, + llvm::StringRef remote_socket_name, + const llvm::Optional &socket_namespace, + std::string &device_id) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + + HdcClient hdc; + auto error = HdcClient::CreateByDeviceID(device_id, hdc); + if (error.Fail()) + return error; + + device_id = hdc.GetDeviceID(); + if (log) + log->Printf("Connected to OHOS device \"%s\"", device_id.c_str()); + + if (remote_port != 0) { + if (log) + log->Printf("Forwarding remote TCP port %d to local TCP port %d", + remote_port, local_port); + return hdc.SetPortForwarding(local_port, remote_port); + } + + if (log) + log->Printf("Forwarding remote socket \"%s\" to local TCP port %d", + remote_socket_name.str().c_str(), local_port); + + if (!socket_namespace) + return Status("Invalid socket namespace"); + + return hdc.SetPortForwarding(local_port, remote_socket_name, + *socket_namespace); +} + +static Status DeleteForwardPortWithHdc(std::pair ports, + const std::string &device_id) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + if (log) + log->Printf("Delete port forwarding %d -> %d, device=%s", ports.first, + ports.second, device_id.c_str()); + + HdcClient hdc(device_id); + return hdc.DeletePortForwarding(ports); +} + +static Status FindUnusedPort(uint16_t &port) { + Status error; + + if (const char *env_port = std::getenv("HDC_FORWARD_PORT_BASE_FOR_LLDB")) { + port = std::atoi(env_port) + g_hdc_forward_port_offset; + g_hdc_forward_port_offset++; + return error; + } + + std::unique_ptr tcp_socket(new TCPSocket(true, false)); + if (error.Fail()) + return error; + + error = tcp_socket->Listen("127.0.0.1:0", 1); + if (error.Success()) + port = tcp_socket->GetLocalPortNumber(); + + return error; +} + +PlatformOHOSRemoteGDBServer::PlatformOHOSRemoteGDBServer() {} + +PlatformOHOSRemoteGDBServer::~PlatformOHOSRemoteGDBServer() { + for (const auto &it : m_port_forwards) + DeleteForwardPortWithHdc(it.second, m_device_id); +} + +bool PlatformOHOSRemoteGDBServer::LaunchGDBServer(lldb::pid_t &pid, + std::string &connect_url) { + uint16_t remote_port = 0; + std::string socket_name; + if (!m_gdb_client.LaunchGDBServer("127.0.0.1", pid, remote_port, socket_name)) + return false; + + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + + auto error = + MakeConnectURL(pid, remote_port, socket_name.c_str(), connect_url); + if (error.Success() && log) + log->Printf("gdbserver connect URL: %s", connect_url.c_str()); + + return error.Success(); +} + +bool PlatformOHOSRemoteGDBServer::KillSpawnedProcess(lldb::pid_t pid) { + DeleteForwardPort(pid); + return m_gdb_client.KillSpawnedProcess(pid); +} + +Status PlatformOHOSRemoteGDBServer::ConnectRemote(Args &args) { + m_device_id.clear(); + + if (args.GetArgumentCount() != 1) + return Status( + "\"platform connect\" takes a single argument: "); + + int remote_port; + llvm::StringRef scheme, host, path; + const char *url = args.GetArgumentAtIndex(0); + if (!url) + return Status("URL is null."); + if (!UriParser::Parse(url, scheme, host, remote_port, path)) + return Status("Invalid URL: %s", url); + if (host != "localhost") + m_device_id = static_cast(host); + + m_socket_namespace.reset(); + if (scheme == ConnectionFileDescriptor::UNIX_CONNECT_SCHEME) + m_socket_namespace = HdcClient::UnixSocketNamespaceFileSystem; + else if (scheme == ConnectionFileDescriptor::UNIX_ABSTRACT_CONNECT_SCHEME) + m_socket_namespace = HdcClient::UnixSocketNamespaceAbstract; + + std::string connect_url; + auto error = + MakeConnectURL(g_remote_platform_pid, (remote_port < 0) ? 0 : remote_port, + path, connect_url); + + if (error.Fail()) + return error; + + args.ReplaceArgumentAtIndex(0, connect_url); + + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + if (log) + log->Printf("Rewritten platform connect URL: %s", connect_url.c_str()); + + error = PlatformRemoteGDBServer::ConnectRemote(args); + if (error.Fail()) + DeleteForwardPort(g_remote_platform_pid); + + return error; +} + +Status PlatformOHOSRemoteGDBServer::DisconnectRemote() { + DeleteForwardPort(g_remote_platform_pid); + g_hdc_forward_port_offset = 0; + return PlatformRemoteGDBServer::DisconnectRemote(); +} + +void PlatformOHOSRemoteGDBServer::DeleteForwardPort(lldb::pid_t pid) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + + auto it = m_port_forwards.find(pid); + if (it == m_port_forwards.end()) + return; + + const auto port = it->second; + const auto error = DeleteForwardPortWithHdc(port, m_device_id); + if (error.Fail()) { + if (log) + log->Printf("Failed to delete port forwarding (pid=%" PRIu64 + ", fwd=(%d -> %d), device=%s): %s", + pid, port.first, port.second, m_device_id.c_str(), + error.AsCString()); + } + m_port_forwards.erase(it); +} + +Status PlatformOHOSRemoteGDBServer::MakeConnectURL( + const lldb::pid_t pid, const uint16_t remote_port, + llvm::StringRef remote_socket_name, std::string &connect_url) { + static const int kAttempsNum = 5; + + Status error; + // There is a race possibility that somebody will occupy a port while we're + // in between FindUnusedPort and ForwardPortWithHdc - adding the loop to + // mitigate such problem. + for (auto i = 0; i < kAttempsNum; ++i) { + uint16_t local_port = 0; + error = FindUnusedPort(local_port); + if (error.Fail()) + return error; + + error = ForwardPortWithHdc(local_port, remote_port, remote_socket_name, + m_socket_namespace, m_device_id); + if (error.Success()) { + m_port_forwards[pid] = {local_port, remote_port}; + std::ostringstream url_str; + url_str << "connect://localhost:" << local_port; + connect_url = url_str.str(); + break; + } + } + + return error; +} + +lldb::ProcessSP PlatformOHOSRemoteGDBServer::ConnectProcess( + llvm::StringRef connect_url, llvm::StringRef plugin_name, + lldb_private::Debugger &debugger, lldb_private::Target *target, + lldb_private::Status &error) { + // We don't have the pid of the remote gdbserver when it isn't started by us + // but we still want to store the list of port forwards we set up in our port + // forward map. Generate a fake pid for these cases what won't collide with + // any other valid pid on ohos. + static lldb::pid_t s_remote_gdbserver_fake_pid = 0xffffffffffffffffULL; + + int remote_port; + llvm::StringRef scheme, host, path; + if (!UriParser::Parse(connect_url, scheme, host, remote_port, path)) { + error.SetErrorStringWithFormat("Invalid URL: %s", + connect_url.str().c_str()); + return nullptr; + } + + std::string new_connect_url; + error = MakeConnectURL(s_remote_gdbserver_fake_pid--, + (remote_port < 0) ? 0 : remote_port, path, + new_connect_url); + if (error.Fail()) + return nullptr; + + return PlatformRemoteGDBServer::ConnectProcess(new_connect_url, plugin_name, + debugger, target, error); +} diff --git a/lldb/source/Plugins/Platform/OHOS/PlatformOHOSRemoteGDBServer.h b/lldb/source/Plugins/Platform/OHOS/PlatformOHOSRemoteGDBServer.h new file mode 100644 index 000000000000..f9818589275d --- /dev/null +++ b/lldb/source/Plugins/Platform/OHOS/PlatformOHOSRemoteGDBServer.h @@ -0,0 +1,64 @@ +//===-- PlatformOHOSRemoteGDBServer.h ------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_PlatformOHOSRemoteGDBServer_h_ +#define liblldb_PlatformOHOSRemoteGDBServer_h_ + +#include +#include + +#include "Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h" + +#include "llvm/ADT/Optional.h" + +#include "HdcClient.h" + +namespace lldb_private { +namespace platform_ohos { + +class PlatformOHOSRemoteGDBServer + : public platform_gdb_server::PlatformRemoteGDBServer { +public: + PlatformOHOSRemoteGDBServer(); + + ~PlatformOHOSRemoteGDBServer() override; + + Status ConnectRemote(Args &args) override; + + Status DisconnectRemote() override; + + lldb::ProcessSP ConnectProcess(llvm::StringRef connect_url, + llvm::StringRef plugin_name, + lldb_private::Debugger &debugger, + lldb_private::Target *target, + lldb_private::Status &error) override; + +protected: + std::string m_device_id; + std::map> m_port_forwards; + llvm::Optional m_socket_namespace; + + bool LaunchGDBServer(lldb::pid_t &pid, std::string &connect_url) override; + + bool KillSpawnedProcess(lldb::pid_t pid) override; + + void DeleteForwardPort(lldb::pid_t pid); + + Status MakeConnectURL(const lldb::pid_t pid, const uint16_t remote_port, + llvm::StringRef remote_socket_name, + std::string &connect_url); + +private: + PlatformOHOSRemoteGDBServer(const PlatformOHOSRemoteGDBServer &other) = delete; + PlatformOHOSRemoteGDBServer& operator=(const PlatformOHOSRemoteGDBServer &other) = delete; +}; + +} // namespace platform_ohos +} // namespace lldb_private + +#endif // liblldb_PlatformOHOSRemoteGDBServer_h_ diff --git a/lldb/source/Plugins/Process/CMakeLists.txt b/lldb/source/Plugins/Process/CMakeLists.txt index 91f20ec22ac5..36800455ab82 100644 --- a/lldb/source/Plugins/Process/CMakeLists.txt +++ b/lldb/source/Plugins/Process/CMakeLists.txt @@ -1,4 +1,4 @@ -if (CMAKE_SYSTEM_NAME MATCHES "Linux|Android") +if (CMAKE_SYSTEM_NAME MATCHES "Linux|Android|OHOS") add_subdirectory(Linux) add_subdirectory(POSIX) elseif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h index 344eae247e91..758d08db5ade 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h @@ -14,6 +14,11 @@ #include "Plugins/Process/Linux/NativeRegisterContextLinux.h" #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h" +#if __OHOS__ +// Do not include to avoid conflicting definitions for +// aarch64-linux-ohos target +#define __ASM_SIGCONTEXT_H 1 +#endif #include namespace lldb_private { diff --git a/lldb/source/Plugins/Process/Linux/Procfs.h b/lldb/source/Plugins/Process/Linux/Procfs.h index 59dd76a2584c..3830842dae12 100644 --- a/lldb/source/Plugins/Process/Linux/Procfs.h +++ b/lldb/source/Plugins/Process/Linux/Procfs.h @@ -11,7 +11,7 @@ #include -#ifdef __ANDROID__ +#if defined(__ANDROID__) #if defined(__arm64__) || defined(__aarch64__) typedef unsigned long elf_greg_t; typedef elf_greg_t diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp index 1ca0290eda13..c13203e2b961 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp @@ -44,12 +44,15 @@ #include "lldb/Host/android/HostInfoAndroid.h" #endif +#if defined(__OHOS_FAMILY__) +#include "lldb/Host/ohos/HostInfoOHOS.h" +#endif using namespace lldb; using namespace lldb_private::process_gdb_remote; using namespace lldb_private; -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__OHOS_FAMILY__) const static uint32_t g_default_packet_timeout_sec = 20; // seconds #else const static uint32_t g_default_packet_timeout_sec = 0; // not specified @@ -183,7 +186,6 @@ GDBRemoteCommunicationServerCommon::Handle_qHostInfo( StreamString response; // $cputype:16777223;cpusubtype:3;ostype:Darwin;vendor:apple;endian:little;ptrsize:8;#00 - ArchSpec host_arch(HostInfo::GetArchitecture()); const llvm::Triple &host_triple = host_arch.GetTriple(); response.PutCString("triple:"); @@ -1277,10 +1279,12 @@ void GDBRemoteCommunicationServerCommon:: } } -FileSpec GDBRemoteCommunicationServerCommon::FindModuleFile( +FileSpec GDBRemoteCommunicationServerCommon::FindModuleFile ( const std::string &module_path, const ArchSpec &arch) { #ifdef __ANDROID__ return HostInfoAndroid::ResolveLibraryPath(module_path, arch); +#elif defined(__OHOS_FAMILY__) + return HostInfoOHOS::ResolveLibraryPath(module_path, arch); #else FileSpec file_spec(module_path); FileSystem::Instance().Resolve(file_spec); @@ -1289,10 +1293,9 @@ FileSpec GDBRemoteCommunicationServerCommon::FindModuleFile( } ModuleSpec -GDBRemoteCommunicationServerCommon::GetModuleInfo(llvm::StringRef module_path, +GDBRemoteCommunicationServerCommon::GetModuleInfo (llvm::StringRef module_path, llvm::StringRef triple) { ArchSpec arch(triple); - FileSpec req_module_path_spec(module_path); FileSystem::Instance().Resolve(req_module_path_spec); @@ -1308,6 +1311,5 @@ GDBRemoteCommunicationServerCommon::GetModuleInfo(llvm::StringRef module_path, ModuleSpec matched_module_spec; if (!module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec)) return ModuleSpec(); - return matched_module_spec; } diff --git a/lldb/source/Target/PathMappingList.cpp b/lldb/source/Target/PathMappingList.cpp index 0342130a58a0..01ee7ef707b4 100644 --- a/lldb/source/Target/PathMappingList.cpp +++ b/lldb/source/Target/PathMappingList.cpp @@ -136,7 +136,7 @@ void PathMappingList::Dump(Stream *s, int pair_index) { } } -void PathMappingList::Clear(bool notify) { +void PathMappingList::Clear (bool notify) { if (!m_pairs.empty()) ++m_mod_id; m_pairs.clear(); @@ -196,7 +196,7 @@ PathMappingList::RemapPath(llvm::StringRef path) const { return {}; } -bool PathMappingList::ReverseRemapPath(const FileSpec &file, FileSpec &fixed) const { +bool PathMappingList::ReverseRemapPath (const FileSpec &file, FileSpec &fixed) const { std::string path = file.GetPath(); llvm::StringRef path_ref(path); for (const auto &it : m_pairs) { @@ -214,7 +214,8 @@ bool PathMappingList::ReverseRemapPath(const FileSpec &file, FileSpec &fixed) co llvm::Optional PathMappingList::FindFile(const FileSpec &orig_spec) const { - if (auto remapped = RemapPath(orig_spec.GetPath())) + std::string normalized_path = FileSpec(orig_spec.GetPath()).GetPath(); + if (auto remapped = RemapPath(normalized_path)) if (FileSystem::Instance().Exists(*remapped)) return remapped; diff --git a/lldb/source/Target/ThreadPlanStepInRange.cpp b/lldb/source/Target/ThreadPlanStepInRange.cpp index a03bd93ac638..84b92fdab1d1 100644 --- a/lldb/source/Target/ThreadPlanStepInRange.cpp +++ b/lldb/source/Target/ThreadPlanStepInRange.cpp @@ -124,7 +124,7 @@ void ThreadPlanStepInRange::GetDescription(Stream *s, s->PutChar('.'); } -bool ThreadPlanStepInRange::ShouldStop(Event *event_ptr) { +bool ThreadPlanStepInRange::ShouldStop (Event *event_ptr) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); if (log) { @@ -166,6 +166,16 @@ bool ThreadPlanStepInRange::ShouldStop(Event *event_ptr) { Thread &thread = GetThread(); if (frame_order == eFrameCompareOlder || frame_order == eFrameCompareSameParent) { + // Here we make a nasty hack to avoid double stepping on enclosing brace + // on ARM platforms. The problem is that before 'bx lr' we typically have + // some instruction modifying the stack pointer register. This confuses + // lldb and makes it think that we're already in a different frame where + // we should stop. + // TODO: Litmit this to OHOS targets + if (MaybeAArch32Or64FunctionTail()) { + SetNextBranchBreakpoint(); + return false; + } // If we're in an older frame then we should stop. // // A caveat to this is if we think the frame is older but we're actually diff --git a/lldb/source/Target/ThreadPlanStepRange.cpp b/lldb/source/Target/ThreadPlanStepRange.cpp index 3c42cd750dad..53953b5c33e6 100644 --- a/lldb/source/Target/ThreadPlanStepRange.cpp +++ b/lldb/source/Target/ThreadPlanStepRange.cpp @@ -205,6 +205,13 @@ bool ThreadPlanStepRange::InSymbol() { return false; } +// TODO: Limit this function scope to OHOS targets +bool ThreadPlanStepRange::MaybeAArch32Or64FunctionTail() { + const llvm::Triple &triple = GetTarget().GetArchitecture().GetTriple(); + const bool isArm32or64 = triple.isAArch64() || triple.isARM(); + return isArm32or64 && InSymbol() && InRange(); +} + // FIXME: This should also handle inlining if we aren't going to do inlining in // the // main stack. diff --git a/lldb/source/Utility/ArchSpec.cpp b/lldb/source/Utility/ArchSpec.cpp index c13e2389cfed..36ebeac81262 100644 --- a/lldb/source/Utility/ArchSpec.cpp +++ b/lldb/source/Utility/ArchSpec.cpp @@ -935,7 +935,7 @@ bool ArchSpec::IsCompatibleMatch(const ArchSpec &rhs) const { return IsEqualTo(rhs, false); } -static bool IsCompatibleEnvironment(llvm::Triple::EnvironmentType lhs, +static bool IsCompatibleEnvironment (llvm::Triple::EnvironmentType lhs, llvm::Triple::EnvironmentType rhs) { if (lhs == rhs) return true; @@ -957,6 +957,8 @@ static bool IsCompatibleEnvironment(llvm::Triple::EnvironmentType lhs, // that they are using the Android ABI. if ((lhs == llvm::Triple::Android && rhs == llvm::Triple::EABI) || (rhs == llvm::Triple::Android && lhs == llvm::Triple::EABI) || + (lhs == llvm::Triple::OpenHOS && rhs == llvm::Triple::EABI) || + (rhs == llvm::Triple::OpenHOS && lhs == llvm::Triple::EABI) || (lhs == llvm::Triple::GNUEABI && rhs == llvm::Triple::EABI) || (rhs == llvm::Triple::GNUEABI && lhs == llvm::Triple::EABI) || (lhs == llvm::Triple::GNUEABIHF && rhs == llvm::Triple::EABIHF) || diff --git a/lldb/source/Utility/TildeExpressionResolver.cpp b/lldb/source/Utility/TildeExpressionResolver.cpp index 75d9c47e656d..bcae7b1a006c 100644 --- a/lldb/source/Utility/TildeExpressionResolver.cpp +++ b/lldb/source/Utility/TildeExpressionResolver.cpp @@ -39,7 +39,7 @@ bool StandardTildeExpressionResolver::ResolveExact( return !fs::real_path(Expr, Output, true); } -bool StandardTildeExpressionResolver::ResolvePartial(StringRef Expr, +bool StandardTildeExpressionResolver::ResolvePartial (StringRef Expr, StringSet<> &Output) { // We expect the tilde expression to be ONLY the expression itself, and // contain no separators. @@ -47,7 +47,7 @@ bool StandardTildeExpressionResolver::ResolvePartial(StringRef Expr, assert(Expr.empty() || Expr[0] == '~'); Output.clear(); -#if defined(_WIN32) || defined(__ANDROID__) +#if defined(_WIN32) || defined(__ANDROID__) || defined(__OHOS_FAMILY__) return false; #else if (Expr.empty()) diff --git a/lldb/test/API/api/command-return-object/Makefile b/lldb/test/API/api/command-return-object/Makefile index 99998b20bcb0..680e1abfbef5 100644 --- a/lldb/test/API/api/command-return-object/Makefile +++ b/lldb/test/API/api/command-return-object/Makefile @@ -1,3 +1,4 @@ CXX_SOURCES := main.cpp +USE_LIBCPP := 1 include Makefile.rules diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/Makefile b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/Makefile index c825977b1a5d..4f8e551348d9 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/Makefile +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/Makefile @@ -1,6 +1,6 @@ CXX_SOURCES := main.cpp CFLAGS_EXTRAS := -O0 -USE_LIBSTDCPP := 1 +USE_LIBCPP := 1 include Makefile.rules diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/TestDataFormatterStdMap.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/TestDataFormatterStdMap.py index 861b24b3a08b..0a6dfdcee7c1 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/TestDataFormatterStdMap.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/TestDataFormatterStdMap.py @@ -10,7 +10,7 @@ from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil -class StdMapDataFormatterTestCase(TestBase): +class StdMapDataFormatterTestCase (TestBase): mydir = TestBase.compute_mydir(__file__) @@ -21,6 +21,7 @@ class StdMapDataFormatterTestCase(TestBase): self.line = line_number('main.cpp', '// Set break point at this line.') @add_test_categories(["libstdcxx"]) + @skipIfLinux # Not working on OHOS, because we use libc++ def test_with_run_command(self): """Test that that file and class static variables display correctly.""" self.build() diff --git a/lldb/test/API/functionalities/plugins/command_plugin/Makefile b/lldb/test/API/functionalities/plugins/command_plugin/Makefile index 3119c3707841..b792c8d50d98 100644 --- a/lldb/test/API/functionalities/plugins/command_plugin/Makefile +++ b/lldb/test/API/functionalities/plugins/command_plugin/Makefile @@ -2,5 +2,6 @@ DYLIB_CXX_SOURCES := plugin.cpp DYLIB_NAME := plugin DYLIB_ONLY := YES MAKE_DSYM := NO +USE_LIBCPP := 1 include Makefile.rules diff --git a/lldb/test/API/lang/c/fpeval/Makefile b/lldb/test/API/lang/c/fpeval/Makefile new file mode 100644 index 000000000000..10495940055b --- /dev/null +++ b/lldb/test/API/lang/c/fpeval/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/lldb/test/API/lang/c/fpeval/TestFPEval.py b/lldb/test/API/lang/c/fpeval/TestFPEval.py new file mode 100644 index 000000000000..fa8a4a211994 --- /dev/null +++ b/lldb/test/API/lang/c/fpeval/TestFPEval.py @@ -0,0 +1,34 @@ +"""Show bitfields and check that they display correctly.""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class FPEvalTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.line = line_number('main.c', '// Set break point at this line.') + + def test_and_run_command(self): + """Test 'frame variable ...' on a variable with bitfields.""" + self.build() + exe = self.getBuildArtifact("a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Break inside the main. + lldbutil.run_break_set_by_file_and_line( + self, "main.c", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + self.expect("expr --allow-jit false -- a + b", VARIABLES_DISPLAYED_CORRECTLY, + substrs=['double', '52']) + diff --git a/lldb/test/API/lang/c/fpeval/main.c b/lldb/test/API/lang/c/fpeval/main.c new file mode 100644 index 000000000000..1f5519401e32 --- /dev/null +++ b/lldb/test/API/lang/c/fpeval/main.c @@ -0,0 +1,10 @@ +#include +#include +#include + +int main (int argc, char const *argv[]) +{ + double a = 42.0; + double b = 10.0; + return (long)(a + b); //// Set break point at this line. +} diff --git a/lldb/test/API/tools/lldb-server/memory-allocation/TestGdbRemoteMemoryAllocation.py b/lldb/test/API/tools/lldb-server/memory-allocation/TestGdbRemoteMemoryAllocation.py index 0644e6c2e1ec..0dfa74ef010e 100644 --- a/lldb/test/API/tools/lldb-server/memory-allocation/TestGdbRemoteMemoryAllocation.py +++ b/lldb/test/API/tools/lldb-server/memory-allocation/TestGdbRemoteMemoryAllocation.py @@ -73,6 +73,7 @@ class TestGdbRemoteMemoryAllocation(gdbremote_testcase.GdbRemoteTestCaseBase): True) self.expect_gdbremote_sequence() + @skipOnHuaweiCI # investigate CI test failures def test_bad_packet(self): """Make sure we get a proper error for malformed packets.""" diff --git a/lldb/test/API/tools/lldb-server/platform-process-connect/TestPlatformProcessConnect.py b/lldb/test/API/tools/lldb-server/platform-process-connect/TestPlatformProcessConnect.py index 74b5f2e16eeb..ec960c962769 100644 --- a/lldb/test/API/tools/lldb-server/platform-process-connect/TestPlatformProcessConnect.py +++ b/lldb/test/API/tools/lldb-server/platform-process-connect/TestPlatformProcessConnect.py @@ -12,7 +12,7 @@ class TestPlatformProcessConnect(gdbremote_testcase.GdbRemoteTestCaseBase): @expectedFailureAll(hostoslist=["windows"], triple='.*-android') @skipIfWindows # lldb-server does not terminate correctly @skipIfDarwin # lldb-server not found correctly - @skipIf(oslist=["linux"], archs=["arm", "aarch64"]) # Fails randomly + @skipIfLinux def test_platform_process_connect(self): self.build() diff --git a/lldb/test/API/tools/lldb-server/signal-filtering/TestGdbRemote_QPassSignals.py b/lldb/test/API/tools/lldb-server/signal-filtering/TestGdbRemote_QPassSignals.py index 8d4f464b8dee..4c502b10ae69 100644 --- a/lldb/test/API/tools/lldb-server/signal-filtering/TestGdbRemote_QPassSignals.py +++ b/lldb/test/API/tools/lldb-server/signal-filtering/TestGdbRemote_QPassSignals.py @@ -61,6 +61,7 @@ class TestGdbRemote_QPassSignals(gdbremote_testcase.GdbRemoteTestCaseBase): self.expect_exit_code(len(signals_to_ignore)) @skipUnlessPlatform(["linux", "android"]) + @skipOnHuaweiCI #investigate CI timeouts def test_change_signals_at_runtime(self): self.build() self.set_inferior_startup_launch() diff --git a/lldb/test/API/tools/lldb-server/thread-name/TestGdbRemoteThreadName.py b/lldb/test/API/tools/lldb-server/thread-name/TestGdbRemoteThreadName.py index 469e5e5fedf2..abec2ade1eec 100644 --- a/lldb/test/API/tools/lldb-server/thread-name/TestGdbRemoteThreadName.py +++ b/lldb/test/API/tools/lldb-server/thread-name/TestGdbRemoteThreadName.py @@ -27,6 +27,7 @@ class TestGdbRemoteThreadName(gdbremote_testcase.GdbRemoteTestCaseBase): self.assertEqual(expected_name, kv_dict.get("name")) @skipIfWindows # the test is not updated for Windows. + @skipOnHuaweiCI # investigate CI timeouts def test(self): """ Make sure lldb-server can retrieve inferior thread name""" self.build() diff --git a/lldb/test/API/tools/lldb-vscode/attach/TestVSCode_attach.py b/lldb/test/API/tools/lldb-vscode/attach/TestVSCode_attach.py index aa7a3ae17cb0..8518efc541bd 100644 --- a/lldb/test/API/tools/lldb-vscode/attach/TestVSCode_attach.py +++ b/lldb/test/API/tools/lldb-vscode/attach/TestVSCode_attach.py @@ -44,6 +44,7 @@ class TestVSCode_attach(lldbvscode_testcase.VSCodeTestCaseBase): self.continue_to_exit() @skipIfWindows + @skipIfLinux @skipIfNetBSD # Hangs on NetBSD as well @skipIfRemote def test_by_pid(self): diff --git a/lldb/test/API/tools/lldb-vscode/runInTerminal/TestVSCode_runInTerminal.py b/lldb/test/API/tools/lldb-vscode/runInTerminal/TestVSCode_runInTerminal.py index 047cc317596f..6bb2965a1fe9 100644 --- a/lldb/test/API/tools/lldb-vscode/runInTerminal/TestVSCode_runInTerminal.py +++ b/lldb/test/API/tools/lldb-vscode/runInTerminal/TestVSCode_runInTerminal.py @@ -48,6 +48,7 @@ class TestVSCode_runInTerminal(lldbvscode_testcase.VSCodeTestCaseBase): return False @skipIfWindows + @skipIfLinux @skipIfRemote @skipIf(archs=no_match(['x86_64'])) def test_runInTerminal(self): diff --git a/lldb/tools/lldb-server/CMakeLists.txt b/lldb/tools/lldb-server/CMakeLists.txt index 930c327cf072..ae3c1069c64d 100644 --- a/lldb/tools/lldb-server/CMakeLists.txt +++ b/lldb/tools/lldb-server/CMakeLists.txt @@ -5,7 +5,7 @@ set_target_properties(LLGSOptionsTableGen PROPERTIES FOLDER "lldb misc") set(LLDB_PLUGINS) -if(CMAKE_SYSTEM_NAME MATCHES "Linux|Android") +if(CMAKE_SYSTEM_NAME MATCHES "Linux|Android|OHOS") list(APPEND LLDB_PLUGINS lldbPluginProcessLinux) endif() diff --git a/lldb/unittests/Expression/CppModuleConfigurationTest.cpp b/lldb/unittests/Expression/CppModuleConfigurationTest.cpp index c1d0d00dcbac..daffce0d8e6d 100644 --- a/lldb/unittests/Expression/CppModuleConfigurationTest.cpp +++ b/lldb/unittests/Expression/CppModuleConfigurationTest.cpp @@ -69,12 +69,30 @@ TEST_F(CppModuleConfigurationTest, Linux) { // C++ library libcpp + "/vector", libcpp + "/module.modulemap"}; - CppModuleConfiguration config(makeFiles(files)); + CppModuleConfiguration config(makeFiles(files), llvm::Triple()); EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std")); EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre(libcpp, ResourceInc(), usr)); } +TEST_F(CppModuleConfigurationTest, LinuxWithTargetSpecificPaths) { + // Test multiarch Linux configuration. + + std::string usr = "/usr/include"; + std::string usr_x64 = "/usr/include/x86_64-linux-gnu"; + std::string libcpp = "/usr/include/c++/v1"; + std::vector files = {// C library + usr + "/stdio.h", usr_x64 + "/endian.h", + // C++ library + libcpp + "/vector", + libcpp + "/module.modulemap"}; + CppModuleConfiguration config(makeFiles(files), + llvm::Triple("x86_64-unknown-linux-gnu")); + EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std")); + EXPECT_THAT(config.GetIncludeDirs(), + testing::ElementsAre(libcpp, ResourceInc(), usr, usr_x64)); +} + TEST_F(CppModuleConfigurationTest, Sysroot) { // Test that having a sysroot for the whole system works fine. @@ -85,7 +103,7 @@ TEST_F(CppModuleConfigurationTest, Sysroot) { // C++ library libcpp + "/vector", libcpp + "/module.modulemap"}; - CppModuleConfiguration config(makeFiles(files)); + CppModuleConfiguration config(makeFiles(files), llvm::Triple()); EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std")); EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre(libcpp, ResourceInc(), usr)); @@ -101,7 +119,7 @@ TEST_F(CppModuleConfigurationTest, LinuxLocalLibCpp) { // C++ library libcpp + "/vector", libcpp + "/module.modulemap"}; - CppModuleConfiguration config(makeFiles(files)); + CppModuleConfiguration config(makeFiles(files), llvm::Triple()); EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std")); EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre(libcpp, ResourceInc(), usr)); @@ -119,7 +137,7 @@ TEST_F(CppModuleConfigurationTest, UnrelatedLibrary) { // C++ library libcpp + "/vector", libcpp + "/module.modulemap"}; - CppModuleConfiguration config(makeFiles(files)); + CppModuleConfiguration config(makeFiles(files), llvm::Triple()); EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std")); EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre(libcpp, ResourceInc(), usr)); @@ -139,7 +157,7 @@ TEST_F(CppModuleConfigurationTest, Xcode) { libcpp + "/vector", libcpp + "/module.modulemap", }; - CppModuleConfiguration config(makeFiles(files)); + CppModuleConfiguration config(makeFiles(files), llvm::Triple()); EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std")); EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre(libcpp, ResourceInc(), usr)); @@ -154,7 +172,7 @@ TEST_F(CppModuleConfigurationTest, LibCppV2) { // C++ library libcpp + "/vector", libcpp + "/module.modulemap"}; - CppModuleConfiguration config(makeFiles(files)); + CppModuleConfiguration config(makeFiles(files), llvm::Triple()); EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std")); EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre("/usr/include/c++/v2", ResourceInc(), @@ -172,7 +190,7 @@ TEST_F(CppModuleConfigurationTest, UnknownLibCppFile) { libcpp + "/non_existing_file", libcpp + "/module.modulemap", libcpp + "/vector"}; - CppModuleConfiguration config(makeFiles(files)); + CppModuleConfiguration config(makeFiles(files), llvm::Triple()); EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre("std")); EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre("/usr/include/c++/v1", ResourceInc(), @@ -186,7 +204,7 @@ TEST_F(CppModuleConfigurationTest, MissingUsrInclude) { std::vector files = {// C++ library libcpp + "/vector", libcpp + "/module.modulemap"}; - CppModuleConfiguration config(makeFiles(files)); + CppModuleConfiguration config(makeFiles(files), llvm::Triple()); EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre()); EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre()); } @@ -199,7 +217,7 @@ TEST_F(CppModuleConfigurationTest, MissingLibCpp) { // C library usr + "/stdio.h", }; - CppModuleConfiguration config(makeFiles(files)); + CppModuleConfiguration config(makeFiles(files), llvm::Triple()); EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre()); EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre()); } @@ -214,7 +232,7 @@ TEST_F(CppModuleConfigurationTest, IgnoreLibStdCpp) { // C++ library usr + "/c++/8.0.1/vector", }; - CppModuleConfiguration config(makeFiles(files)); + CppModuleConfiguration config(makeFiles(files), llvm::Triple()); EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre()); EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre()); } @@ -235,7 +253,7 @@ TEST_F(CppModuleConfigurationTest, AmbiguousCLib) { libcpp + "/vector", libcpp + "/module.modulemap", }; - CppModuleConfiguration config(makeFiles(files)); + CppModuleConfiguration config(makeFiles(files), llvm::Triple()); EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre()); EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre()); } @@ -257,7 +275,7 @@ TEST_F(CppModuleConfigurationTest, AmbiguousLibCpp) { libcpp2 + "/vector", libcpp2 + "/module.modulemap", }; - CppModuleConfiguration config(makeFiles(files)); + CppModuleConfiguration config(makeFiles(files), llvm::Triple()); EXPECT_THAT(config.GetImportedModules(), testing::ElementsAre()); EXPECT_THAT(config.GetIncludeDirs(), testing::ElementsAre()); } diff --git a/lldb/unittests/Target/CMakeLists.txt b/lldb/unittests/Target/CMakeLists.txt index 2c3ba699b0eb..d0afeb3d0047 100644 --- a/lldb/unittests/Target/CMakeLists.txt +++ b/lldb/unittests/Target/CMakeLists.txt @@ -6,6 +6,7 @@ add_lldb_unittest(TargetTests PathMappingListTest.cpp RemoteAwarePlatformTest.cpp StackFrameRecognizerTest.cpp + FindFileTest.cpp LINK_LIBS lldbCore diff --git a/lldb/unittests/Target/FindFileTest.cpp b/lldb/unittests/Target/FindFileTest.cpp new file mode 100644 index 000000000000..198c0f62cb47 --- /dev/null +++ b/lldb/unittests/Target/FindFileTest.cpp @@ -0,0 +1,97 @@ +//===-- FindFileTest.cpp -------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "TestingSupport/TestUtilities.h" +#include "lldb/Host/FileSystem.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Target/PathMappingList.h" +#include "lldb/Utility/FileSpec.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/FileUtilities.h" +#include "gtest/gtest.h" +#include + +using namespace llvm; +using namespace llvm::sys::fs; +using namespace lldb_private; + +namespace { +struct Matches { + FileSpec original; + llvm::StringRef remapped; + Matches(const char *o, const char *r) : original(o), remapped(r) {} + Matches(const char *o, llvm::sys::path::Style style, const char *r) + : original(o, style), remapped(r) {} +}; + +class FindFileTest : public testing::Test { +public: + void SetUp() override { + FileSystem::Initialize(); + HostInfo::Initialize(); + } + void TearDown() override { + HostInfo::Terminate(); + FileSystem::Terminate(); + } +}; +} // namespace + +static void TestFileFindings(const PathMappingList &map, + llvm::ArrayRef matches, + llvm::ArrayRef fails) { + for (const auto &fail : fails) { + SCOPED_TRACE(fail.GetCString()); + EXPECT_FALSE(map.FindFile(fail)); + } + + for (const auto &match : matches) { + SCOPED_TRACE(match.original.GetPath() + " -> " + match.remapped); + llvm::Optional remapped; + + EXPECT_TRUE(bool(remapped = map.FindFile(match.original))); + EXPECT_TRUE(FileSpec(remapped.getValue()).GetPath() == + ConstString(match.remapped).GetStringRef()); + } +} + +TEST_F(FindFileTest, FindFileTests) { + const auto *Info = testing::UnitTest::GetInstance()->current_test_info(); + llvm::SmallString<128> DirName, FileName; + int fd; + + ASSERT_NO_ERROR(createUniqueDirectory(Info->name(), DirName)); + + sys::path::append(FileName, Twine(DirName), Twine("test")); + ASSERT_NO_ERROR(openFile(FileName, fd, CD_CreateAlways, FA_Read, OF_None)); + + llvm::FileRemover dir_remover(DirName); + llvm::FileRemover file_remover(FileName); + PathMappingList map; + + map.Append(ConstString("/old"), ConstString(DirName.str()), false); + map.Append(ConstString(R"(C:\foo)"), ConstString(DirName.str()), false); + + Matches matches[] = { + {"/old", llvm::sys::path::Style::posix, DirName.c_str()}, + {"/old/test", llvm::sys::path::Style::posix, FileName.c_str()}, + {R"(C:\foo)", llvm::sys::path::Style::windows, DirName.c_str()}, + {R"(C:\foo\test)", llvm::sys::path::Style::windows, FileName.c_str()}}; + + std::vector fails{ + // path not mapped + FileSpec("/foo", llvm::sys::path::Style::posix), + FileSpec("/new", llvm::sys::path::Style::posix), + FileSpec(R"(C:\new)", llvm::sys::path::Style::windows), + // path mapped, but file not exist + FileSpec("/old/test1", llvm::sys::path::Style::posix), + FileSpec(R"(C:\foo\test2)", llvm::sys::path::Style::windows)}; + + TestFileFindings(map, matches, fails); +} diff --git a/llvm-build/build.py b/llvm-build/build.py old mode 100644 new mode 100755 diff --git a/llvm-build/env_prepare.sh b/llvm-build/env_prepare.sh index 962777b33850..0cc61592e361 100755 --- a/llvm-build/env_prepare.sh +++ b/llvm-build/env_prepare.sh @@ -9,10 +9,10 @@ mkdir -p $cmake_dir wget https://mirrors.huaweicloud.com/harmonyos/compiler/clang/10.0.1-62608/linux/llvm.tar.gz wget https://mirrors.huaweicloud.com/harmonyos/compiler/cmake/3.16.5/linux/cmake-linux-x86-3.16.5.tar.gz -wget https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.1/clang+llvm-10.0.1-x86_64-linux-gnu-ubuntu-16.04.tar.xz +#wget https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.1/clang+llvm-10.0.1-x86_64-linux-gnu-ubuntu-16.04.tar.xz tar -xvf llvm.tar.gz tar -xvf cmake-linux-x86-3.16.5.tar.gz tar -xvf clang+llvm-10.0.1-x86_64-linux-gnu-ubuntu-16.04.tar.xz mv $llvm_name $llvm_dir/llvm mv $cmake_name $cmake_dir/linux-x86 -mv $clang_name $llvm_dir/clang-10.0.1 \ No newline at end of file +mv $clang_name $llvm_dir/clang-10.0.1 diff --git a/llvm-build/mingw.py b/llvm-build/mingw.py old mode 100644 new mode 100755 diff --git a/llvm-build/pack_clang_reproducers.py b/llvm-build/pack_clang_reproducers.py old mode 100644 new mode 100755 diff --git a/llvm-build/update_prebuilts_ohos.py b/llvm-build/update_prebuilts_ohos.py old mode 100644 new mode 100755 diff --git a/llvm-build/windres.sh b/llvm-build/windres.sh old mode 100644 new mode 100755 diff --git a/llvm/include/llvm/ADT/Triple.h b/llvm/include/llvm/ADT/Triple.h index eed315c929ad..183ac3787fdc 100644 --- a/llvm/include/llvm/ADT/Triple.h +++ b/llvm/include/llvm/ADT/Triple.h @@ -172,7 +172,7 @@ public: IOS, KFreeBSD, Linux, - Lv2, // PS3 + Lv2, // PS3 MacOSX, NetBSD, OpenBSD, @@ -182,15 +182,15 @@ public: Haiku, Minix, RTEMS, - NaCl, // Native Client + NaCl, // Native Client AIX, - CUDA, // NVIDIA CUDA - NVCL, // NVIDIA OpenCL - AMDHSA, // AMD HSA Runtime + CUDA, // NVIDIA CUDA + NVCL, // NVIDIA OpenCL + AMDHSA, // AMD HSA Runtime PS4, ELFIAMCU, - TvOS, // Apple tvOS - WatchOS, // Apple watchOS + TvOS, // Apple tvOS + WatchOS, // Apple watchOS Mesa3D, Contiki, AMDPAL, // AMD PAL Runtime @@ -198,7 +198,8 @@ public: Hurd, // GNU/Hurd WASI, // Experimental WebAssembly OS Emscripten, - LastOSType = Emscripten + LiteOS, + LastOSType = LiteOS }; enum EnvironmentType { UnknownEnvironment, @@ -223,8 +224,9 @@ public: Cygnus, CoreCLR, Simulator, // Simulator variants of other systems, e.g., Apple's iOS - MacABI, // Mac Catalyst variant of Apple's iOS deployment target. - LastEnvironmentType = MacABI + MacABI, // Mac Catalyst variant of Apple's iOS deployment target. + OpenHOS, + LastEnvironmentType = OpenHOS }; enum ObjectFormatType { UnknownObjectFormat, @@ -687,9 +689,19 @@ public: bool isMusl() const { return getEnvironment() == Triple::Musl || getEnvironment() == Triple::MuslEABI || - getEnvironment() == Triple::MuslEABIHF; + getEnvironment() == Triple::MuslEABIHF || + getEnvironment() == Triple::OpenHOS || + isOSLiteOS(); } + /// Tests whether the target is OHOS + /// LiteOS default enviroment is also OHOS, but omited on triple. + bool isOHOSFamily() const { return isOpenHOS() || isOSLiteOS(); } + + bool isOpenHOS() const { return getEnvironment() == Triple::OpenHOS; } + + bool isOSLiteOS() const { return getOS() == Triple::LiteOS; } + /// Tests whether the target is SPIR (32- or 64-bit). bool isSPIR() const { return getArch() == Triple::spir || getArch() == Triple::spir64; diff --git a/llvm/include/llvm/BinaryFormat/MinidumpConstants.def b/llvm/include/llvm/BinaryFormat/MinidumpConstants.def index 543305feea77..c03a4f8fd9ea 100644 --- a/llvm/include/llvm/BinaryFormat/MinidumpConstants.def +++ b/llvm/include/llvm/BinaryFormat/MinidumpConstants.def @@ -115,6 +115,7 @@ HANDLE_MDMP_PLATFORM(0x8202, Solaris) // Solaris HANDLE_MDMP_PLATFORM(0x8203, Android) // Android HANDLE_MDMP_PLATFORM(0x8204, PS3) // PS3 HANDLE_MDMP_PLATFORM(0x8205, NaCl) // Native Client (NaCl) +HANDLE_MDMP_PLATFORM(0x8207, OpenHOS) HANDLE_MDMP_PROTECT(0x01, NoAccess, PAGE_NO_ACCESS) HANDLE_MDMP_PROTECT(0x02, ReadOnly, PAGE_READ_ONLY) diff --git a/llvm/include/llvm/LTO/Config.h b/llvm/include/llvm/LTO/Config.h index 88c1452e5aa9..0f88c06d0fd4 100644 --- a/llvm/include/llvm/LTO/Config.h +++ b/llvm/include/llvm/LTO/Config.h @@ -51,6 +51,9 @@ struct Config { CodeGenOpt::Level CGOptLevel = CodeGenOpt::Default; CodeGenFileType CGFileType = CGFT_ObjectFile; unsigned OptLevel = 2; + unsigned SizeLevel = 0; + bool MergeFunctions = false; + bool DisableVerify = false; /// Use the new pass manager diff --git a/llvm/lib/CodeGen/LiveDebugValues/VarLocBasedImpl.cpp b/llvm/lib/CodeGen/LiveDebugValues/VarLocBasedImpl.cpp index 78f2c642f96a..9cc8dcc00fdc 100644 --- a/llvm/lib/CodeGen/LiveDebugValues/VarLocBasedImpl.cpp +++ b/llvm/lib/CodeGen/LiveDebugValues/VarLocBasedImpl.cpp @@ -448,7 +448,6 @@ private: case SpillLocKind: { // Spills are indirect DBG_VALUEs, with a base register and offset. // Use the original DBG_VALUEs expression to build the spilt location - // on top of. FIXME: spill locations created before this pass runs // are not recognized, and not handled here. auto *TRI = MF.getSubtarget().getRegisterInfo(); auto Deref = Indirect ? DIExpression::DerefAfter : 0; diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp index 9103d11059e0..da8d5606865e 100644 --- a/llvm/lib/LTO/LTO.cpp +++ b/llvm/lib/LTO/LTO.cpp @@ -129,6 +129,8 @@ void llvm::computeLTOCacheKey( AddUnsigned(Conf.CGOptLevel); AddUnsigned(Conf.CGFileType); AddUnsigned(Conf.OptLevel); + AddUnsigned(Conf.SizeLevel); + AddUnsigned(Conf.MergeFunctions); AddUnsigned(Conf.UseNewPM); AddUnsigned(Conf.Freestanding); AddString(Conf.OptPipeline); diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp index 1796d6ba60cc..b25191b16bd1 100644 --- a/llvm/lib/LTO/LTOBackend.cpp +++ b/llvm/lib/LTO/LTOBackend.cpp @@ -361,6 +361,9 @@ static void runOldPMPasses(const Config &Conf, Module &Mod, TargetMachine *TM, PMB.OptLevel = Conf.OptLevel; PMB.PGOSampleUse = Conf.SampleProfile; PMB.EnablePGOCSInstrGen = Conf.RunCSIRInstr; + PMB.MergeFunctions = Conf.MergeFunctions; + PMB.SizeLevel = Conf.SizeLevel; + if (!Conf.RunCSIRInstr && !Conf.CSIRProfile.empty()) { PMB.EnablePGOCSInstrUse = true; PMB.PGOInstrUse = Conf.CSIRProfile; diff --git a/llvm/lib/Support/AArch64TargetParser.cpp b/llvm/lib/Support/AArch64TargetParser.cpp index 503a7bd49d15..1f07ee0e1a73 100644 --- a/llvm/lib/Support/AArch64TargetParser.cpp +++ b/llvm/lib/Support/AArch64TargetParser.cpp @@ -193,7 +193,7 @@ void AArch64::fillValidCPUArchList(SmallVectorImpl &Values) { bool AArch64::isX18ReservedByDefault(const Triple &TT) { return TT.isAndroid() || TT.isOSDarwin() || TT.isOSFuchsia() || - TT.isOSWindows(); + TT.isOSWindows() || TT.isOHOSFamily(); } // Allows partial match, ex. "v8a" matches "armv8a". diff --git a/llvm/lib/Support/ARMTargetParser.cpp b/llvm/lib/Support/ARMTargetParser.cpp index eb425cbb1d25..cf7027cdd467 100644 --- a/llvm/lib/Support/ARMTargetParser.cpp +++ b/llvm/lib/Support/ARMTargetParser.cpp @@ -624,7 +624,7 @@ StringRef ARM::computeDefaultTargetABI(const Triple &TT, StringRef CPU) { default: if (TT.isOSNetBSD()) return "apcs-gnu"; - if (TT.isOSOpenBSD()) + if (TT.isOSOpenBSD() || TT.isOHOSFamily()) return "aapcs-linux"; return "aapcs"; } diff --git a/llvm/lib/Support/Triple.cpp b/llvm/lib/Support/Triple.cpp index 4f483c965282..c520d96db9fd 100644 --- a/llvm/lib/Support/Triple.cpp +++ b/llvm/lib/Support/Triple.cpp @@ -220,6 +220,8 @@ StringRef Triple::getOSTypeName(OSType Kind) { case WatchOS: return "watchos"; case Win32: return "windows"; case ZOS: return "zos"; + case LiteOS: + return "liteos"; } llvm_unreachable("Invalid OSType"); @@ -248,6 +250,8 @@ StringRef Triple::getEnvironmentTypeName(EnvironmentType Kind) { case MuslEABI: return "musleabi"; case MuslEABIHF: return "musleabihf"; case Simulator: return "simulator"; + case OpenHOS: + return "ohos"; } llvm_unreachable("Invalid EnvironmentType!"); @@ -495,43 +499,44 @@ static Triple::VendorType parseVendor(StringRef VendorName) { static Triple::OSType parseOS(StringRef OSName) { return StringSwitch(OSName) - .StartsWith("ananas", Triple::Ananas) - .StartsWith("cloudabi", Triple::CloudABI) - .StartsWith("darwin", Triple::Darwin) - .StartsWith("dragonfly", Triple::DragonFly) - .StartsWith("freebsd", Triple::FreeBSD) - .StartsWith("fuchsia", Triple::Fuchsia) - .StartsWith("ios", Triple::IOS) - .StartsWith("kfreebsd", Triple::KFreeBSD) - .StartsWith("linux", Triple::Linux) - .StartsWith("lv2", Triple::Lv2) - .StartsWith("macos", Triple::MacOSX) - .StartsWith("netbsd", Triple::NetBSD) - .StartsWith("openbsd", Triple::OpenBSD) - .StartsWith("solaris", Triple::Solaris) - .StartsWith("win32", Triple::Win32) - .StartsWith("windows", Triple::Win32) - .StartsWith("zos", Triple::ZOS) - .StartsWith("haiku", Triple::Haiku) - .StartsWith("minix", Triple::Minix) - .StartsWith("rtems", Triple::RTEMS) - .StartsWith("nacl", Triple::NaCl) - .StartsWith("aix", Triple::AIX) - .StartsWith("cuda", Triple::CUDA) - .StartsWith("nvcl", Triple::NVCL) - .StartsWith("amdhsa", Triple::AMDHSA) - .StartsWith("ps4", Triple::PS4) - .StartsWith("elfiamcu", Triple::ELFIAMCU) - .StartsWith("tvos", Triple::TvOS) - .StartsWith("watchos", Triple::WatchOS) - .StartsWith("mesa3d", Triple::Mesa3D) - .StartsWith("contiki", Triple::Contiki) - .StartsWith("amdpal", Triple::AMDPAL) - .StartsWith("hermit", Triple::HermitCore) - .StartsWith("hurd", Triple::Hurd) - .StartsWith("wasi", Triple::WASI) - .StartsWith("emscripten", Triple::Emscripten) - .Default(Triple::UnknownOS); + .StartsWith("ananas", Triple::Ananas) + .StartsWith("cloudabi", Triple::CloudABI) + .StartsWith("darwin", Triple::Darwin) + .StartsWith("dragonfly", Triple::DragonFly) + .StartsWith("freebsd", Triple::FreeBSD) + .StartsWith("fuchsia", Triple::Fuchsia) + .StartsWith("ios", Triple::IOS) + .StartsWith("kfreebsd", Triple::KFreeBSD) + .StartsWith("linux", Triple::Linux) + .StartsWith("lv2", Triple::Lv2) + .StartsWith("macos", Triple::MacOSX) + .StartsWith("netbsd", Triple::NetBSD) + .StartsWith("openbsd", Triple::OpenBSD) + .StartsWith("solaris", Triple::Solaris) + .StartsWith("win32", Triple::Win32) + .StartsWith("windows", Triple::Win32) + .StartsWith("zos", Triple::ZOS) + .StartsWith("haiku", Triple::Haiku) + .StartsWith("minix", Triple::Minix) + .StartsWith("rtems", Triple::RTEMS) + .StartsWith("nacl", Triple::NaCl) + .StartsWith("aix", Triple::AIX) + .StartsWith("cuda", Triple::CUDA) + .StartsWith("nvcl", Triple::NVCL) + .StartsWith("amdhsa", Triple::AMDHSA) + .StartsWith("ps4", Triple::PS4) + .StartsWith("elfiamcu", Triple::ELFIAMCU) + .StartsWith("tvos", Triple::TvOS) + .StartsWith("watchos", Triple::WatchOS) + .StartsWith("mesa3d", Triple::Mesa3D) + .StartsWith("contiki", Triple::Contiki) + .StartsWith("amdpal", Triple::AMDPAL) + .StartsWith("hermit", Triple::HermitCore) + .StartsWith("hurd", Triple::Hurd) + .StartsWith("wasi", Triple::WASI) + .StartsWith("emscripten", Triple::Emscripten) + .StartsWith("liteos", Triple::LiteOS) + .Default(Triple::UnknownOS); } static Triple::EnvironmentType parseEnvironment(StringRef EnvironmentName) { @@ -556,6 +561,7 @@ static Triple::EnvironmentType parseEnvironment(StringRef EnvironmentName) { .StartsWith("coreclr", Triple::CoreCLR) .StartsWith("simulator", Triple::Simulator) .StartsWith("macabi", Triple::MacABI) + .StartsWith("ohos", Triple::OpenHOS) .Default(Triple::UnknownEnvironment); } diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUPALMetadata.cpp b/llvm/lib/Target/AMDGPU/Utils/AMDGPUPALMetadata.cpp index b7dd757a8af3..9b616ae6f232 100644 --- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUPALMetadata.cpp +++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUPALMetadata.cpp @@ -526,8 +526,8 @@ static const char *getRegisterName(unsigned RegNum) { {0x2e09, "COMPUTE_NUM_THREAD_Z"}, {0xa2db, "VGT_TF_PARAM"}, {0xa2d6, "VGT_LS_HS_CONFIG"}, - {0xa287, "VGT_HOS_MIN_TESS_LEVEL"}, - {0xa286, "VGT_HOS_MAX_TESS_LEVEL"}, + {0xa287, "VGT_OHOS_MIN_TESS_LEVEL"}, + {0xa286, "VGT_OHOS_MAX_TESS_LEVEL"}, {0xa2f8, "PA_SC_AA_CONFIG"}, {0xa310, "PA_SC_SHADER_CONTROL"}, {0xa313, "PA_SC_CONSERVATIVE_RASTERIZATION_CNTL"}, diff --git a/llvm/lib/Target/ARM/ARMSubtarget.h b/llvm/lib/Target/ARM/ARMSubtarget.h index fd9b94fdaa23..c8275e8d8d0f 100644 --- a/llvm/lib/Target/ARM/ARMSubtarget.h +++ b/llvm/lib/Target/ARM/ARMSubtarget.h @@ -762,7 +762,8 @@ public: } bool isTargetMuslAEABI() const { return (TargetTriple.getEnvironment() == Triple::MuslEABI || - TargetTriple.getEnvironment() == Triple::MuslEABIHF) && + TargetTriple.getEnvironment() == Triple::MuslEABIHF || + TargetTriple.getEnvironment() == Triple::OpenHOS) && !isTargetDarwin() && !isTargetWindows(); } @@ -775,13 +776,14 @@ public: TargetTriple.getEnvironment() == Triple::EABIHF || TargetTriple.getEnvironment() == Triple::GNUEABIHF || TargetTriple.getEnvironment() == Triple::MuslEABIHF || - isTargetAndroid()) && + isTargetAndroid() || isTargetHOSFamily()) && !isTargetDarwin() && !isTargetWindows(); } bool isTargetHardFloat() const; bool isTargetAndroid() const { return TargetTriple.isAndroid(); } + bool isTargetHOSFamily() const { return TargetTriple.isOHOSFamily(); } bool isXRaySupported() const override; diff --git a/llvm/lib/Target/ARM/ARMTargetMachine.cpp b/llvm/lib/Target/ARM/ARMTargetMachine.cpp index 237ef54c8339..e6b085dd4571 100644 --- a/llvm/lib/Target/ARM/ARMTargetMachine.cpp +++ b/llvm/lib/Target/ARM/ARMTargetMachine.cpp @@ -234,7 +234,8 @@ ARMBaseTargetMachine::ARMBaseTargetMachine(const Target &T, const Triple &TT, if ((TargetTriple.getEnvironment() == Triple::GNUEABI || TargetTriple.getEnvironment() == Triple::GNUEABIHF || TargetTriple.getEnvironment() == Triple::MuslEABI || - TargetTriple.getEnvironment() == Triple::MuslEABIHF) && + TargetTriple.getEnvironment() == Triple::MuslEABIHF || + TargetTriple.getEnvironment() == Triple::OpenHOS) && !(TargetTriple.isOSWindows() || TargetTriple.isOSDarwin())) this->Options.EABIVersion = EABI::GNU; else diff --git a/llvm/test/CodeGen/AArch64/arm64-platform-reg.ll b/llvm/test/CodeGen/AArch64/arm64-platform-reg.ll index 89fc6457482f..0ea2e20cfa52 100644 --- a/llvm/test/CodeGen/AArch64/arm64-platform-reg.ll +++ b/llvm/test/CodeGen/AArch64/arm64-platform-reg.ll @@ -2,6 +2,7 @@ ; RUN: llc -mtriple=arm64-freebsd-gnu -mattr=+reserve-x18 -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE --check-prefix=CHECK-RESERVE-X18 ; RUN: llc -mtriple=arm64-linux-gnu -o - %s | FileCheck %s ; RUN: llc -mtriple=aarch64-linux-android -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE --check-prefix=CHECK-RESERVE-X18 +; RUN: llc -mtriple=aarch64-linux-ohos -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE --check-prefix=CHECK-RESERVE-X18 ; RUN: llc -mtriple=aarch64-fuchsia -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE --check-prefix=CHECK-RESERVE-X18 ; RUN: llc -mtriple=aarch64-windows -o - %s | FileCheck %s --check-prefix=CHECK-RESERVE --check-prefix=CHECK-RESERVE-X18 diff --git a/llvm/test/Transforms/SafeStack/AArch64/abi.ll b/llvm/test/Transforms/SafeStack/AArch64/abi.ll index bd6710d160c5..45961b767180 100644 --- a/llvm/test/Transforms/SafeStack/AArch64/abi.ll +++ b/llvm/test/Transforms/SafeStack/AArch64/abi.ll @@ -1,8 +1,10 @@ ; RUN: opt -safe-stack -S -mtriple=aarch64-linux-android < %s -o - | FileCheck %s +; RUN: opt -safe-stack -S -mtriple=aarch64-linux-ohos < %s -o - | FileCheck %s --check-prefix=OHOS define void @foo() nounwind uwtable safestack { entry: +; OHOS-NOT: call i8* @llvm.thread.pointer() ; CHECK: %[[TP:.*]] = call i8* @llvm.thread.pointer() ; CHECK: %[[SPA0:.*]] = getelementptr i8, i8* %[[TP]], i32 72 ; CHECK: %[[SPA:.*]] = bitcast i8* %[[SPA0]] to i8** diff --git a/llvm/test/Transforms/SafeStack/AArch64/abi_ssp.ll b/llvm/test/Transforms/SafeStack/AArch64/abi_ssp.ll index c78b20aaa01a..9069ea50a4d5 100644 --- a/llvm/test/Transforms/SafeStack/AArch64/abi_ssp.ll +++ b/llvm/test/Transforms/SafeStack/AArch64/abi_ssp.ll @@ -1,4 +1,5 @@ ; RUN: opt -safe-stack -S -mtriple=aarch64-linux-android < %s -o - | FileCheck --check-prefixes=TLS,ANDROID %s +; RUN: opt -safe-stack -S -mtriple=aarch64-linux-ohos < %s -o - | FileCheck --check-prefix=OHOS %s ; RUN: opt -safe-stack -S -mtriple=aarch64-unknown-fuchsia < %s -o - | FileCheck --check-prefixes=TLS,FUCHSIA %s define void @foo() nounwind uwtable safestack sspreq { @@ -6,6 +7,7 @@ entry: ; The first @llvm.thread.pointer is for the unsafe stack pointer, skip it. ; TLS: call i8* @llvm.thread.pointer() +; OHOS-NOT: call i8* @llvm.thread.pointer() ; TLS: %[[TP2:.*]] = call i8* @llvm.thread.pointer() ; ANDROID: %[[B:.*]] = getelementptr i8, i8* %[[TP2]], i32 40 ; FUCHSIA: %[[B:.*]] = getelementptr i8, i8* %[[TP2]], i32 -16 diff --git a/llvm/test/Transforms/SafeStack/AArch64/unreachable.ll b/llvm/test/Transforms/SafeStack/AArch64/unreachable.ll index 53ed690ebb09..7009fce7a4a4 100644 --- a/llvm/test/Transforms/SafeStack/AArch64/unreachable.ll +++ b/llvm/test/Transforms/SafeStack/AArch64/unreachable.ll @@ -1,7 +1,9 @@ ; RUN: opt -safe-stack -safe-stack-coloring -S -mtriple=aarch64-linux-android < %s -o - | FileCheck %s +; RUN: opt -safe-stack -safe-stack-coloring -S -mtriple=aarch64-linux-ohos < %s -o - | FileCheck %s --check-prefix=OHOSMUSL define void @foo() nounwind uwtable safestack { entry: +; OHOSMUSL-NOT: call i8* @llvm.thread.pointer() ; CHECK: %[[TP:.*]] = call i8* @llvm.thread.pointer() ; CHECK: %[[SPA0:.*]] = getelementptr i8, i8* %[[TP]], i32 72 ; CHECK: %[[SPA:.*]] = bitcast i8* %[[SPA0]] to i8** diff --git a/llvm/utils/lit/lit/llvm/config.py b/llvm/utils/lit/lit/llvm/config.py index 949c5e694db7..d96b5de5027b 100644 --- a/llvm/utils/lit/lit/llvm/config.py +++ b/llvm/utils/lit/lit/llvm/config.py @@ -11,7 +11,7 @@ from lit.llvm.subst import ToolSubst lit_path_displayed = False -class LLVMConfig(object): +class LLVMConfig (object): def __init__(self, lit_config, config): self.lit_config = lit_config @@ -62,6 +62,8 @@ class LLVMConfig(object): features.add('system-windows') elif platform.system() == 'Linux': features.add('system-linux') + if os.path.exists('/.dockerenv'): + features.add('ohos-ci') elif platform.system() in ['FreeBSD']: features.add('system-freebsd') elif platform.system() == 'NetBSD': diff --git a/llvm/utils/unittest/googletest/include/gtest/internal/gtest-port-arch.h b/llvm/utils/unittest/googletest/include/gtest/internal/gtest-port-arch.h index f1319c7f2e29..bcd18572cf3d 100644 --- a/llvm/utils/unittest/googletest/include/gtest/internal/gtest-port-arch.h +++ b/llvm/utils/unittest/googletest/include/gtest/internal/gtest-port-arch.h @@ -74,6 +74,9 @@ # if defined __ANDROID__ # define GTEST_OS_LINUX_ANDROID 1 # endif +# if defined __OHOS_FAMILY__ +# define GTEST_OS_LINUX_OHOS_FAMILY 1 +# endif #elif defined __MVS__ # define GTEST_OS_ZOS 1 #elif defined(__sun) && defined(__SVR4) diff --git a/llvm/utils/unittest/googletest/src/gtest-port.cc b/llvm/utils/unittest/googletest/src/gtest-port.cc index 6aeef4957cf5..6135ffdcb486 100644 --- a/llvm/utils/unittest/googletest/src/gtest-port.cc +++ b/llvm/utils/unittest/googletest/src/gtest-port.cc @@ -954,7 +954,7 @@ class CapturedStream { // directory, so we create the temporary file in the /tmp directory // instead. We use /tmp on most systems, and /sdcard on Android. // That's because Android doesn't have /tmp. -# if GTEST_OS_LINUX_ANDROID +# if GTEST_OS_LINUX_ANDROID || GTEST_OS_LINUX_OHOS_FAMILY // Note: Android applications are expected to call the framework's // Context.getExternalStorageDirectory() method through JNI to get // the location of the world-writable SD Card directory. However, diff --git a/openmp/runtime/src/kmp.h b/openmp/runtime/src/kmp.h index 87e91a0f8d10..a9256cf3da6a 100644 --- a/openmp/runtime/src/kmp.h +++ b/openmp/runtime/src/kmp.h @@ -54,9 +54,8 @@ #define KMP_CANCEL_THREADS #define KMP_THREAD_ATTR -// Android does not have pthread_cancel. Undefine KMP_CANCEL_THREADS if being // built on Android -#if defined(__ANDROID__) +#if defined(__ANDROID__) || defined(__OHOS__) #undef KMP_CANCEL_THREADS #endif diff --git a/openmp/runtime/src/kmp_i18n.cpp b/openmp/runtime/src/kmp_i18n.cpp index d2651cfabdf3..507d1a19955d 100644 --- a/openmp/runtime/src/kmp_i18n.cpp +++ b/openmp/runtime/src/kmp_i18n.cpp @@ -709,7 +709,8 @@ static char *sys_error(int err) { #if (defined(__GLIBC__) && defined(_GNU_SOURCE)) || \ (defined(__BIONIC__) && defined(_GNU_SOURCE) && \ - __ANDROID_API__ >= __ANDROID_API_M__) + __ANDROID_API__ >= __ANDROID_API_M__) || \ + (defined(__OHOS__) && defined(_GNU_SOURCE)) // GNU version of strerror_r. char buffer[2048]; diff --git a/openmp/runtime/test/tasking/hidden_helper_task/depend.cpp b/openmp/runtime/test/tasking/hidden_helper_task/depend.cpp index 3eb28607e462..cae7e885bb42 100644 --- a/openmp/runtime/test/tasking/hidden_helper_task/depend.cpp +++ b/openmp/runtime/test/tasking/hidden_helper_task/depend.cpp @@ -1,7 +1,7 @@ // RUN: %libomp-cxx-compile-and-run +// UNSUPPORTED: ohos-ci -/* - * This test aims to check whether hidden helper task can work with regular task +/* This test aims to check whether hidden helper task can work with regular task * in terms of dependences. It is equivalent to the following code: * * #pragma omp parallel diff --git a/openmp/runtime/test/tasking/hidden_helper_task/gtid.cpp b/openmp/runtime/test/tasking/hidden_helper_task/gtid.cpp index d5af89553caf..6819db432463 100644 --- a/openmp/runtime/test/tasking/hidden_helper_task/gtid.cpp +++ b/openmp/runtime/test/tasking/hidden_helper_task/gtid.cpp @@ -41,7 +41,9 @@ struct anon { }; } -kmp_int32 __kmp_hidden_helper_threads_num; +// OHOS specific: we use static libomp and get link error on this symbol +// probably push this to mainline +__attribute__((weak)) kmp_int32 __kmp_hidden_helper_threads_num; kmp_int32 omp_task_entry(kmp_int32 gtid, kmp_task_t_with_privates *task) { auto shareds = reinterpret_cast(task->task.shareds); -- Gitee From 5584885adcaa16bc3df2e0ba93c788af7d5bc1c2 Mon Sep 17 00:00:00 2001 From: liwentao_uiw Date: Fri, 1 Jul 2022 11:40:13 +0800 Subject: [PATCH 03/18] use 10.0.1 clang for building Change-Id: Ide01bb5f7a8243f477c44e6247d3823256c97383 --- llvm-build/env_prepare.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm-build/env_prepare.sh b/llvm-build/env_prepare.sh index 0cc61592e361..340045a62a07 100755 --- a/llvm-build/env_prepare.sh +++ b/llvm-build/env_prepare.sh @@ -9,7 +9,7 @@ mkdir -p $cmake_dir wget https://mirrors.huaweicloud.com/harmonyos/compiler/clang/10.0.1-62608/linux/llvm.tar.gz wget https://mirrors.huaweicloud.com/harmonyos/compiler/cmake/3.16.5/linux/cmake-linux-x86-3.16.5.tar.gz -#wget https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.1/clang+llvm-10.0.1-x86_64-linux-gnu-ubuntu-16.04.tar.xz +wget https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.1/clang+llvm-10.0.1-x86_64-linux-gnu-ubuntu-16.04.tar.xz tar -xvf llvm.tar.gz tar -xvf cmake-linux-x86-3.16.5.tar.gz tar -xvf clang+llvm-10.0.1-x86_64-linux-gnu-ubuntu-16.04.tar.xz -- Gitee From f74a8e2247a10338d288d0cfca759b63a2baa715 Mon Sep 17 00:00:00 2001 From: liwentao_uiw Date: Sun, 3 Jul 2022 10:30:17 +0800 Subject: [PATCH 04/18] fix CI func name & target name Change-Id: Ic2fb7f1c823d1f2b6f466ca5908c6c803bb19562 --- lldb/packages/Python/lldbsuite/test/decorators.py | 2 +- llvm/lib/Target/ARM/ARMSubtarget.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lldb/packages/Python/lldbsuite/test/decorators.py b/lldb/packages/Python/lldbsuite/test/decorators.py index 7cf1fc1e3729..f66cb7f1d6d0 100644 --- a/lldb/packages/Python/lldbsuite/test/decorators.py +++ b/lldb/packages/Python/lldbsuite/test/decorators.py @@ -642,7 +642,7 @@ def skipIfPlatform(oslist): "skip on %s" % (", ".join(oslist))) def skipOnHuaweiCI(func): - return unittest2.skipIf(lldbplatformutil.isHuawei(), "skip on Huawei CI")(func) + return unittest2.skipIf(lldbplatformutil.isHuaweiCI(), "skip on Huawei CI")(func) def skipUnlessPlatform(oslist): diff --git a/llvm/lib/Target/ARM/ARMSubtarget.h b/llvm/lib/Target/ARM/ARMSubtarget.h index c8275e8d8d0f..e124cfe2373a 100644 --- a/llvm/lib/Target/ARM/ARMSubtarget.h +++ b/llvm/lib/Target/ARM/ARMSubtarget.h @@ -776,14 +776,14 @@ public: TargetTriple.getEnvironment() == Triple::EABIHF || TargetTriple.getEnvironment() == Triple::GNUEABIHF || TargetTriple.getEnvironment() == Triple::MuslEABIHF || - isTargetAndroid() || isTargetHOSFamily()) && + isTargetAndroid() || isTargetOHOSFamily()) && !isTargetDarwin() && !isTargetWindows(); } bool isTargetHardFloat() const; bool isTargetAndroid() const { return TargetTriple.isAndroid(); } - bool isTargetHOSFamily() const { return TargetTriple.isOHOSFamily(); } + bool isTargetOHOSFamily() const { return TargetTriple.isOHOSFamily(); } bool isXRaySupported() const override; -- Gitee From f8f92d6c934d7a7903f410114b2bc0d37ad70401 Mon Sep 17 00:00:00 2001 From: liwentao_uiw Date: Sun, 3 Jul 2022 15:13:42 +0800 Subject: [PATCH 05/18] fix testing script name Change-Id: I1082a51791d68ad32bde70d10c8c8f9ad2e929db --- .../{pack_clang_reproducers.py => pack-clang-reproducers.py} | 0 llvm-build/{update_prebuilts_ohos.py => update-prebuilts-ohos.py} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename llvm-build/{pack_clang_reproducers.py => pack-clang-reproducers.py} (100%) rename llvm-build/{update_prebuilts_ohos.py => update-prebuilts-ohos.py} (100%) diff --git a/llvm-build/pack_clang_reproducers.py b/llvm-build/pack-clang-reproducers.py similarity index 100% rename from llvm-build/pack_clang_reproducers.py rename to llvm-build/pack-clang-reproducers.py diff --git a/llvm-build/update_prebuilts_ohos.py b/llvm-build/update-prebuilts-ohos.py similarity index 100% rename from llvm-build/update_prebuilts_ohos.py rename to llvm-build/update-prebuilts-ohos.py -- Gitee From 8ac77090439cd6ae87e6dfc70ac827a12b80a71b Mon Sep 17 00:00:00 2001 From: liwentao_uiw Date: Sun, 3 Jul 2022 16:40:20 +0800 Subject: [PATCH 06/18] add cpython mingw prepare and build script Change-Id: I418c8faf8b7253761020e37980f89dae1704f80d --- llvm-build/build_cpython-mingw.sh | 78 +++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100755 llvm-build/build_cpython-mingw.sh diff --git a/llvm-build/build_cpython-mingw.sh b/llvm-build/build_cpython-mingw.sh new file mode 100755 index 000000000000..0026a039a5ee --- /dev/null +++ b/llvm-build/build_cpython-mingw.sh @@ -0,0 +1,78 @@ +#!/bin/bash + +PROJECT_ROOT=$(pwd) +CPYTHON_MINGW_SRC=${PROJECT_ROOT}/third_party/python +MINGW_W64_SRC=${PROJECT_ROOT}/third_party/mingw-w64 + +# prepare SYSROOT for cpython-mingw build +CLANG_MINGW_BUILD=${PROJECT_ROOT}/out/clang_mingw +python3 ${PROJECT_ROOT}/toolchain/llvm-build/mingw.py + +# refreash cpython-mingw config +cd ${CPYTHON_MINGW_SRC} +rm -rf ${CPYTHON_MINGW_SRC}/configure +autoconf ${CPYTHON_MINGW_SRC}/configure.ac > ${CPYTHON_MINGW_SRC}/configure +chmod 777 ${CPYTHON_MINGW_SRC}/configure + +# # prepare build config and build libpython for cpython-mingw +CPYTHON_MINGW_BUILD=${PROJECT_ROOT}/out/cpython-mingw-build +mkdir -p ${CPYTHON_MINGW_BUILD} +cd ${CPYTHON_MINGW_BUILD} +MINGW_PREFIX=${CPYTHON_MINGW_BUILD}/mingw64 +MINGW_CHOST=x86_64-w64-mingw32 +MINGW_BUILD=x86_64-unknown-linux-gnu +TOOLCHAIN_ROOT=${CLANG_MINGW_BUILD}/clang-10.0.1/bin +SYSROOT=${CLANG_MINGW_BUILD}/clang-10.0.1/x86_64-w64-mingw32 +mkdir $MINGW_BUILD + +export CC=$TOOLCHAIN_ROOT/clang +export CXX=$TOOLCHAIN_ROOT/clang++ +export CFLAGS="-target ${MINGW_CHOST} --sysroot=$SYSROOT" +export LDFLAGS="--sysroot=$SYSROOT -rtlib=compiler-rt -target ${MINGW_CHOST} -lucrt -lucrtbase -fuse-ld=lld" + +${CPYTHON_MINGW_SRC}/configure \ + --prefix=${MINGW_PREFIX} \ + --host=${MINGW_CHOST} \ + --build=${MINGW_BUILD} \ + --enable-shared \ + --enable-static \ + --without-ensurepip \ + --without-c-locale-coercion \ + --enable-loadable-sqlite-extensions + +make -j4 + +# copy build result to mingw-w64 +cp ${CPYTHON_MINGW_BUILD}/libpython3.10.dll.a ${MINGW_W64_SRC}/mingw-w64-crt/lib64 +cp ${CPYTHON_MINGW_BUILD}/libpython3.10.dll ${MINGW_W64_SRC}/mingw-w64-python/3.10 +cd ../.. + +# example steps to install autoconf 2.71 +# wget http://ftp.gnu.org/gnu/autoconf/autoconf-2.71.tar.gz +# export PATH=/mnt/disk2/liwentao/workspace/tools/autoconf/autoconf-2.71/bin:$PATH +# sudo cp -r /mnt/disk2/liwentao/workspace/tools/autoconf/autoconf-2.71/lib /usr/local/share/autoconf + +# refreash configure and Makefile for mingw-w64 +# you need autoconf (2.69 for Ubuntu 20.04 LTS apt install, to support mingw-w64 9.x and later version, please install autoconf 2.71 http://ftp.gnu.org/gnu/autoconf/) +# and automake (1.16.1 for Ubuntu 20.04 LTS apt install) +cd ${MINGW_W64_SRC}/mingw-w64-crt +rm -rf configure +autoconf configure.ac > configure +chmod 777 configure + +aclocal +automake + +cd ${MINGW_W64_SRC}/mingw-w64-headers +rm -rf configure +autoconf configure.ac > configure +chmod 777 configure + +aclocal +automake + +# move cpython-mingw build result and python header file to mingw-w64 +cp -r ${CPYTHON_MINGW_SRC}/Include ${MINGW_W64_SRC}/mingw-w64-headers/include/python3.10 +cp ${CPYTHON_MINGW_SRC}/pyconfig.h ${MINGW_W64_SRC}/mingw-w64-headers/include/python3.10 +mkdir -p ${MINGW_W64_SRC}/mingw-w64-python/3.10 +cp -r ${CPYTHON_MINGW_SRC}/Lib ${MINGW_W64_SRC}/mingw-w64-python/3.10/lib \ No newline at end of file -- Gitee From aa41b3cef6f8ca0c55ffb177f739221eb229fcc3 Mon Sep 17 00:00:00 2001 From: liwentao_uiw Date: Tue, 5 Jul 2022 08:39:38 +0800 Subject: [PATCH 07/18] Add Instruction to build llvm toolchain and sysroot targets Change-Id: Id7a2776c6ddf2e455cacb95d0b4e537188a83fc1 --- llvm-build/README.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/llvm-build/README.md b/llvm-build/README.md index 13da47aebc2f..715e6d5fe0a5 100644 --- a/llvm-build/README.md +++ b/llvm-build/README.md @@ -1 +1,19 @@ -comming soon +### System requirements + +Ubuntu >= 16.04 +MacOS X >= 10.15.4 + +### Toolchain build process + +Here is an example of starting build process on Linux or MacOS: +``` +python3 ./build.py +``` + +### Output artifacts + +When build successfully completed. following artifacts will be available in `out` directory + +`sysroot` -> sysroots for OHOS targets +`install` -> toolchain build +`*.tar.bz2` -> archived versions of toolchain and sysroots \ No newline at end of file -- Gitee From 2249727448158c7e9e52f1b412e654450ab44f06 Mon Sep 17 00:00:00 2001 From: liwentao_uiw Date: Tue, 5 Jul 2022 09:48:56 +0800 Subject: [PATCH 08/18] update README.Opensource Change-Id: I263c8da0dbc096b65e91bfba44705ee9e4495372 --- README.OpenSource | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.OpenSource b/README.OpenSource index ca0e7c992457..999365386775 100644 --- a/README.OpenSource +++ b/README.OpenSource @@ -3,7 +3,7 @@ "Name": "LLVM", "License": "Apache License v2.0 with LLVM Exceptions", "License File": "./libunwind/LICENSE.TXT ./lld/LICENSE.TXT ./polly/tools/GPURuntime/LICENSE.TXT ./libcxxabi/LICENSE.TXT ./llvm/include/llvm/Support/LICENSE.TXT ./llvm/utils/unittest/googletest/LICENSE.TXT ./llvm/LICENSE.TXT ./compiler-rt/LICENSE.TXT ./clang-tools-extra/clang-tidy/cert/LICENSE.TXT ./clang-tools-extra/clang-tidy/hicpp/LICENSE.TXT ./clang-tools-extra/LICENSE.TXT ./lldb/LICENSE.TXT ./llgo/LICENSE.TXT ./libcxx/LICENSE.TXT ./clang/LICENSE.TXT ./libclc/LICENSE.TXT ./parallel-libs/acxxel/LICENSE.TXT", - "Version Number": "10.0.1", + "Version Number": "12.0.1", "Owner": "sunqiang13@huawei.com", "Upstream URL": "http://llvm.org/", "Description": "The LLVM Project is a collection of modular and reusable compiler and toolchain technologies. Despite its name, LLVM has little to do with traditional virtual machines. The name \"LLVM\" itself is not an acronym; it is the full name of the project." -- Gitee From d5b34228cd2c81d6e0204856685e770a2496041d Mon Sep 17 00:00:00 2001 From: xwx1135370 Date: Tue, 5 Jul 2022 12:46:55 +0800 Subject: [PATCH 09/18] =?UTF-8?q?=E3=80=90OHOS=E3=80=91=E3=80=90lldb?= =?UTF-8?q?=E3=80=91fport=20rm=20message=20sent=20by=20lldb=20to=20hdc=20d?= =?UTF-8?q?oes=20not=20match=20fport?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xwx1135370 --- .../Plugins/Platform/OHOS/HdcClient.cpp | 22 ++++++- lldb/source/Plugins/Platform/OHOS/HdcClient.h | 3 + .../OHOS/PlatformOHOSRemoteGDBServer.cpp | 63 ++++++++++++++----- .../OHOS/PlatformOHOSRemoteGDBServer.h | 1 + 4 files changed, 74 insertions(+), 15 deletions(-) diff --git a/lldb/source/Plugins/Platform/OHOS/HdcClient.cpp b/lldb/source/Plugins/Platform/OHOS/HdcClient.cpp index 97fa08fb44da..6807d24cf317 100644 --- a/lldb/source/Plugins/Platform/OHOS/HdcClient.cpp +++ b/lldb/source/Plugins/Platform/OHOS/HdcClient.cpp @@ -235,7 +235,27 @@ Status HdcClient::DeletePortForwarding(std::pair fwd) { if (error.Fail()) return error; - return ReadResponseStatus(nullptr); + return ReadResponseStatus("Remove forward ruler success"); +} + +Status HdcClient::DeletePortForwarding(const uint16_t local_port, + const std::string remote_socket_name, + const UnixSocketNamespace socket_namespace) { + const char *sock_namespace_str = + (socket_namespace == UnixSocketNamespaceAbstract) + ? kSocketNamespaceAbstract + : kSocketNamespaceFileSystem; + char message[PATH_MAX] = ""; + + snprintf(message, sizeof(message), "fport rm tcp:%d %s:%s", local_port, + sock_namespace_str, remote_socket_name.c_str()); + + const auto error = SendMessage(message); + if (error.Fail()){ + return error; + } + + return ReadResponseStatus("Remove forward ruler success"); } Status HdcClient::TransferFile(const char *direction, const FileSpec &src, diff --git a/lldb/source/Plugins/Platform/OHOS/HdcClient.h b/lldb/source/Plugins/Platform/OHOS/HdcClient.h index 64a5a324325a..39b6569b447a 100644 --- a/lldb/source/Plugins/Platform/OHOS/HdcClient.h +++ b/lldb/source/Plugins/Platform/OHOS/HdcClient.h @@ -51,6 +51,9 @@ public: const UnixSocketNamespace socket_namespace); Status DeletePortForwarding(std::pair fwd); + + Status DeletePortForwarding(const uint16_t local_port, const std::string remote_socket_name, + const UnixSocketNamespace socket_namespace); Status RecvFile(const FileSpec &src, const FileSpec &dst); diff --git a/lldb/source/Plugins/Platform/OHOS/PlatformOHOSRemoteGDBServer.cpp b/lldb/source/Plugins/Platform/OHOS/PlatformOHOSRemoteGDBServer.cpp index 62dc0639afef..1b54c2cce225 100644 --- a/lldb/source/Plugins/Platform/OHOS/PlatformOHOSRemoteGDBServer.cpp +++ b/lldb/source/Plugins/Platform/OHOS/PlatformOHOSRemoteGDBServer.cpp @@ -70,6 +70,21 @@ static Status DeleteForwardPortWithHdc(std::pair ports, return hdc.DeletePortForwarding(ports); } +static Status DeleteForwardPortWithHdc(std::pair remote_socket, + const llvm::Optional &socket_namespace, + const std::string &device_id) { + + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + uint16_t local_port = remote_socket.first; + std::string remote_socket_name = remote_socket.second; + if (log) + log->Printf("Delete port forwarding %d -> %s, device=%s", local_port, + remote_socket_name.c_str(), device_id.c_str()); + + HdcClient hdc(device_id); + return hdc.DeletePortForwarding(local_port, remote_socket_name, *socket_namespace); +} + static Status FindUnusedPort(uint16_t &port) { Status error; @@ -93,8 +108,12 @@ static Status FindUnusedPort(uint16_t &port) { PlatformOHOSRemoteGDBServer::PlatformOHOSRemoteGDBServer() {} PlatformOHOSRemoteGDBServer::~PlatformOHOSRemoteGDBServer() { - for (const auto &it : m_port_forwards) + for (const auto &it : m_port_forwards){ DeleteForwardPortWithHdc(it.second, m_device_id); + } + for (const auto &it_socket : m_remote_socket_name){ + DeleteForwardPortWithHdc(it_socket.second, m_socket_namespace, m_device_id); + } } bool PlatformOHOSRemoteGDBServer::LaunchGDBServer(lldb::pid_t &pid, @@ -173,19 +192,30 @@ void PlatformOHOSRemoteGDBServer::DeleteForwardPort(lldb::pid_t pid) { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); auto it = m_port_forwards.find(pid); - if (it == m_port_forwards.end()) - return; - - const auto port = it->second; - const auto error = DeleteForwardPortWithHdc(port, m_device_id); - if (error.Fail()) { - if (log) - log->Printf("Failed to delete port forwarding (pid=%" PRIu64 - ", fwd=(%d -> %d), device=%s): %s", - pid, port.first, port.second, m_device_id.c_str(), - error.AsCString()); + auto it_socket = m_remote_socket_name.find(pid); + if (it != m_port_forwards.end() && it->second.second != 0){ + const auto error = DeleteForwardPortWithHdc(it->second, m_device_id); + if (error.Fail()) { + if (log) + log->Printf("Failed to delete port forwarding (pid=%" PRIu64 + ", fwd=(%d -> %d), device=%s): %s", + pid, it->second.first, it->second.second, m_device_id.c_str(), + error.AsCString()); + } + m_port_forwards.erase(it); + } + + if(it_socket != m_remote_socket_name.end()){ + const auto error_Socket = DeleteForwardPortWithHdc(it_socket->second, m_socket_namespace, m_device_id); + if (error_Socket.Fail()) { + if (log) + log->Printf("Failed to delete port forwarding (pid=%" PRIu64 + ", fwd=(%d->%s)device=%s): %s", pid, it_socket->second.first, it_socket->second.second.c_str(), m_device_id.c_str(),error_Socket.AsCString()); + } + m_remote_socket_name.erase(it_socket); } - m_port_forwards.erase(it); + + return; } Status PlatformOHOSRemoteGDBServer::MakeConnectURL( @@ -206,7 +236,12 @@ Status PlatformOHOSRemoteGDBServer::MakeConnectURL( error = ForwardPortWithHdc(local_port, remote_port, remote_socket_name, m_socket_namespace, m_device_id); if (error.Success()) { - m_port_forwards[pid] = {local_port, remote_port}; + if (remote_port != 0){ + m_port_forwards[pid] = {local_port, remote_port}; + } + else{ + m_remote_socket_name[pid] ={local_port, remote_socket_name.str()}; + } std::ostringstream url_str; url_str << "connect://localhost:" << local_port; connect_url = url_str.str(); diff --git a/lldb/source/Plugins/Platform/OHOS/PlatformOHOSRemoteGDBServer.h b/lldb/source/Plugins/Platform/OHOS/PlatformOHOSRemoteGDBServer.h index f9818589275d..680ddc1e733c 100644 --- a/lldb/source/Plugins/Platform/OHOS/PlatformOHOSRemoteGDBServer.h +++ b/lldb/source/Plugins/Platform/OHOS/PlatformOHOSRemoteGDBServer.h @@ -41,6 +41,7 @@ public: protected: std::string m_device_id; std::map> m_port_forwards; + std::map> m_remote_socket_name; llvm::Optional m_socket_namespace; bool LaunchGDBServer(lldb::pid_t &pid, std::string &connect_url) override; -- Gitee From 9d41b6e4bfe19421a5d7a3bd27a59f76fc0bed25 Mon Sep 17 00:00:00 2001 From: liwentao_uiw Date: Tue, 5 Jul 2022 14:38:33 +0800 Subject: [PATCH 10/18] change hos target name to ohos Change-Id: I9b1fa690ecf1cbf87bf52fe23483989c41416184 --- .../ohos_family_commands/ohos_compile.py | 2 +- .../ohos_family_commands/ohos_run.py | 2 +- llvm-build/build.py | 18 +++++++++--------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_compile.py b/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_compile.py index f7d2a89540b9..1c8624fbd621 100644 --- a/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_compile.py +++ b/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_compile.py @@ -1,7 +1,7 @@ #!/usr/bin/python import os, sys, subprocess -from hos_common import * +from ohos_common import * here = os.path.abspath(os.path.dirname(sys.argv[0])) diff --git a/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_run.py b/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_run.py index 5bfe83ef3f56..84a8d9fb709c 100644 --- a/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_run.py +++ b/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_run.py @@ -2,7 +2,7 @@ import os, signal, sys, subprocess import re -from hos_common import * +from ohos_common import * device_binary = host_to_device_path(sys.argv[0]) diff --git a/llvm-build/build.py b/llvm-build/build.py index c2dff3deffac..f6f079f025b9 100755 --- a/llvm-build/build.py +++ b/llvm-build/build.py @@ -195,7 +195,7 @@ class BuildUtils(object): self.CMAKE_BIN_DIR = os.path.abspath( os.path.join(self.build_config.REPOROOT_DIR, 'prebuilts/cmake', self.use_platform()[:-3], 'bin')) - def open_hos_triple(self, arch): + def open_ohos_triple(self, arch): return arch + self.build_config.OPENHOS_SFX def liteos_triple(self, arch): @@ -815,13 +815,13 @@ class LlvmLibs(BuildUtils): ('arm', self.liteos_triple('arm'), '-march=armv7-a -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4', 'a7_hard_neon-vfpv4'), - ('arm', self.open_hos_triple('arm'), '-march=armv7-a -mfloat-abi=soft', ''), - ('arm', self.open_hos_triple('arm'), '-march=armv7-a -mcpu=cortex-a7 -mfloat-abi=soft', 'a7_soft'), - ('arm', self.open_hos_triple('arm'), + ('arm', self.open_ohos_triple('arm'), '-march=armv7-a -mfloat-abi=soft', ''), + ('arm', self.open_ohos_triple('arm'), '-march=armv7-a -mcpu=cortex-a7 -mfloat-abi=soft', 'a7_soft'), + ('arm', self.open_ohos_triple('arm'), '-march=armv7-a -mcpu=cortex-a7 -mfloat-abi=softfp -mfpu=neon-vfpv4', 'a7_softfp_neon-vfpv4'), - ('arm', self.open_hos_triple('arm'), + ('arm', self.open_ohos_triple('arm'), '-march=armv7-a -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4', 'a7_hard_neon-vfpv4'), - ('aarch64', self.open_hos_triple('aarch64'), '', ''), ] + ('aarch64', self.open_ohos_triple('aarch64'), '', ''), ] cc = os.path.join(llvm_install, 'bin', 'clang') cxx = os.path.join(llvm_install, 'bin', 'clang++') @@ -840,7 +840,7 @@ class LlvmLibs(BuildUtils): self.build_libs_defines(llvm_triple, defines, cc, cxx, llvm_config, ldflags, cflags, extra_flags) llvm_path = self.merge_out_path('llvm_make') - arch_list = [self.liteos_triple('arm'), self.open_hos_triple('arm'), self.open_hos_triple('aarch64')] + arch_list = [self.liteos_triple('arm'), self.open_ohos_triple('arm'), self.open_ohos_triple('aarch64')] if precompilation: self.build_crts(llvm_install, arch, llvm_triple, cflags, ldflags, multilib_suffix, defines) continue @@ -1951,10 +1951,10 @@ def main(): configs = [] if not build_config.no_build_arm: configs.append(('arm', build_utils.liteos_triple('arm'))) - configs.append(('arm', build_utils.open_hos_triple('arm'))) + configs.append(('arm', build_utils.open_ohos_triple('arm'))) if not build_config.no_build_aarch64: - configs.append(('arm64', build_utils.open_hos_triple('aarch64'))) + configs.append(('arm64', build_utils.open_ohos_triple('aarch64'))) if build_config.do_build and need_host: llvm_core.llvm_compile( -- Gitee From a5c547b0018cd54adcbd61a592276316667952fb Mon Sep 17 00:00:00 2001 From: wzjemo Date: Fri, 8 Jul 2022 10:05:23 +0800 Subject: [PATCH 11/18] change hos target name to ohos Signed-off-by: wzjemo --- .../sanitizer_common/ohos_family_commands/ohos_common.py | 6 +++--- .../sanitizer_common/ohos_family_commands/ohos_compile.py | 8 ++++---- .../sanitizer_common/ohos_family_commands/ohos_run.py | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_common.py b/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_common.py index da6e6b9d2fd4..e38f7a485189 100644 --- a/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_common.py +++ b/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_common.py @@ -1,15 +1,15 @@ import os, subprocess, tempfile -HOS_TMPDIR = '/data/local/tmp/Output' +OHOS_TMPDIR = '/data/local/tmp/Output' ADB = os.environ.get('ADB', 'adb') verbose = False -if os.environ.get('HOS_RUN_VERBOSE') == '1': +if os.environ.get('OHOS_RUN_VERBOSE') == '1': verbose = True def host_to_device_path(path): rel = os.path.relpath(path, "/") - dev = os.path.join(HOS_TMPDIR, rel) + dev = os.path.join(OHOS_TMPDIR, rel) return dev def adb(args, attempts = 1): diff --git a/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_compile.py b/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_compile.py index 1c8624fbd621..bc5cd811ebb2 100644 --- a/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_compile.py +++ b/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_compile.py @@ -5,7 +5,7 @@ from ohos_common import * here = os.path.abspath(os.path.dirname(sys.argv[0])) -hos_run = os.path.join(here, 'hos_run.py') +ohos_run = os.path.join(here, 'ohos_run.py') output = None output_type = 'executable' @@ -27,14 +27,14 @@ while args: check_trgt = False if arg.endswith('-linux-ohos'): arg = arg.split('=')[-1] - dyld = 'unknown_hos_dyld' + dyld = 'unknown_ohos_dyld' # FIXME: Handle -mfloat-abi=hard for arm # TODO: Support x86_64 if arg.startswith('arm'): dyld = 'ld-musl-arm.so.1' elif arg.startswith('aarch64'): dyld = 'ld-musl-aarch64.so.1' - append_args += ['-Wl,--dynamic-linker=' + os.path.join(HOS_TMPDIR, dyld)] + append_args += ['-Wl,--dynamic-linker=' + os.path.join(OHOS_TMPDIR, dyld)] if output == None: print "No output file name!" @@ -49,4 +49,4 @@ if output_type in ['executable', 'shared']: if output_type == 'executable': os.rename(output, output + '.real') - os.symlink(hos_run, output) + os.symlink(ohos_run, output) diff --git a/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_run.py b/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_run.py index 84a8d9fb709c..b5605e615dc3 100644 --- a/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_run.py +++ b/compiler-rt/test/sanitizer_common/ohos_family_commands/ohos_run.py @@ -9,7 +9,7 @@ device_binary = host_to_device_path(sys.argv[0]) def build_env(): args = [] # HOS linker ignores RPATH. Set LD_LIBRARY_PATH to Output dir. - args.append('LD_LIBRARY_PATH=%s' % (HOS_TMPDIR,)) + args.append('LD_LIBRARY_PATH=%s' % (OHOS_TMPDIR,)) for (key, value) in os.environ.items(): if key in ['ASAN_ACTIVATION_OPTIONS', 'SCUDO_OPTIONS'] or key.endswith('SAN_OPTIONS'): args.append('%s="%s"' % (key, value)) @@ -23,7 +23,7 @@ device_exitcode = device_binary + '.exitcode' device_linker = '' ret = adb(['shell', 'cd %s && %s %s %s %s >%s 2>%s ; echo $? >%s' % - (HOS_TMPDIR, device_env, device_linker, device_binary, device_args, + (OHOS_TMPDIR, device_env, device_linker, device_binary, device_args, device_stdout, device_stderr, device_exitcode)]) if ret != 0: sys.exit(ret) -- Gitee From e855855b396f1854dca7a9330770c5c13508b76a Mon Sep 17 00:00:00 2001 From: liwentao_uiw Date: Fri, 8 Jul 2022 17:04:50 +0800 Subject: [PATCH 12/18] Update README.md and remove redundant scripts Change-Id: I713218d1698b673ec51a0d4ecb6589688e180685 --- data/llvm_build.png | Bin 0 -> 32219 bytes data/one_time_setup.png | Bin 0 -> 21555 bytes llvm-build/README.md | 117 +++++++++++- llvm-build/pack-clang-reproducers.py | 77 -------- llvm-build/toolchain_readme.md | 28 --- llvm-build/update-prebuilts-ohos.py | 261 --------------------------- 6 files changed, 110 insertions(+), 373 deletions(-) create mode 100644 data/llvm_build.png create mode 100644 data/one_time_setup.png delete mode 100755 llvm-build/pack-clang-reproducers.py delete mode 100644 llvm-build/toolchain_readme.md delete mode 100755 llvm-build/update-prebuilts-ohos.py diff --git a/data/llvm_build.png b/data/llvm_build.png new file mode 100644 index 0000000000000000000000000000000000000000..86cdeeea3da2d2fe396fa4559494b20d8a0bbbf5 GIT binary patch literal 32219 zcmeFYXIPU<`!9;3s8kDrQpASzBE6#`(mRCSL_`7sDWMaVvP9|9g7i*E0-*;85KsgJ z1cVSGU8E<{2_+cV!S$B?KWCrw?R-1Aay?I`&wbC#Z|;_8V?!+#MlMD=Iyx2|?Z>8c zbmy+o(VgNs&p^xBK{$`mUT6Fs>6o9VeZtN^dq+!O_t&)YH}ih(AL#7sO6TU~4RRIp zbMbX`_40e+?Y~anrberz>TYi3ui@+J?C2w}HG!M%DHKpn~v7Ea{ z&13U=pwfPN@hQ```635fd2`Jg>_UT-*&A34gVoJ!;cQ|3tA^F@OnJdYbWDH4pTM8E zug%gi#hJ#NzCp2`GrF%2mcctCip=lO$MPb6ntciQeOuZ0saDMvm5$+bG-jXkjzf#X zm*aYXg$4hgIsbWl=-}hv{crLwQsjjv|4sV2yuS3GRQu!yr!)UaNy^{5cIrQ=ukrtX zGrIrpS#m@uq;F)lhQdYr%qr!%STah3f7KTXnzMIS6ZCQBMMDbY0~rIM6siBqx6(eN zZ(bNXv$nPdC!iY|+@J@G{aG%R6_u4{_gqaEWrh8wm7XPSsSu{8r{RS3%^*`+_Mfk~ zUWSDQZz$;cp#^f<^6&+oF=%UEhks>c25DJo2s%t}`@Jv{pscJc-B`fv$@UfQ$_(YO!Up>jF3Ii+**wOX5;d4)t zjb4DKukZIs=_Jo7FeUuyk0Taxi7w10IM>75+la=cSk|+&KC3NA$coQgag+5Yctl6H zabQ(ieUkvLZ*E3jz4nxzj_w1uhvex$Whajh+*jiMlb~BfU;bAiG;#efx%jRQ2hWAS zEHqka4XUj4|7nMM40VlVJ=GrL%i}h5i`F=7bW|9Se=^=*Y0eYqyKupnH(j^HEJaT` zuF^)1sy}7gCC3}tKRDp@rhFW8gHDnOOoI~| zBPyshmyIMTSP3276q1Ew?9UUGn5La{0`7EHYSvJlWS(y8mv`v^ zEM!_<`_ua$&z}@EUdFEL*(9(>(E<7p70$HfcsW)6`HTy@CXFvA6`+r3L@W!OYKL7u z^U983?@zlToO(`XQ}OgH@T7*-bu@_91&kqGh~rPX*n-4IbsqXJ@XbBIpK>R!e=Yi-)Q1V(e-&D((KwKteE0vz z9BZhU(iu9DUY~5ux3qQ}*0xBiSAWI>M1dxfiwgxgxZc*;RiE_Pe!Ifv_}xDX{bvli zukq~g^j~d9q_&-zW9m#SD}Cec(MsNt&hgRuF?LxJ%1CB%Kyt zIYEauziu0}Ur5>s82yKhNO^h|(N8C2BM`y^MOVrk|4P)NN^z5!Ha4MfNYB3)*jju9 z+}>?lit)-ASP_ibp^!aVL&(6P0#UrrDU=9N$*Eoxr`QS%uTP^*^@lnQ6zJ&G0+GYk zXa6GI9`svXTN77erk%@qKt<*5Tg`L-aQ)=@gJKme@Xyst!yQw)Q&u-dL}>Z3ooDX+ zDc9Y{N<@Pr>FlsHVBn=;Lc1G?|K7EtKL?jqql*2f0`#%^1v<5~o9E{-YlR)OOg%5! zzWZkvwKH1R8;a10Hs3t|r+Fj8|6vYJ|3feU+}0F68QbZAU9)=mB3-%Q1e)Jukd`Cb ztE(^h-1?pl4TkA*RGmoBU_mWV*QicQow!hwhW{>Hcb}cpPJX@~eGI(Q4o+-t^QdD-|LQtpDnK z`p=YK^4Eykod@GtTijs6YC?3&C+^o^H&c=!yZPSb7Zki)NgcmV6RG__8Pj?kDy zgUXpbPToHkf~Z~cT^elC_HDb{otWEGEx{*yxSgm=Z|&h>leOvg0s1QnmX9M;+4<+U zAJABWzAR)~`-d(X303SgK%|klVcoNB*WBDpJDqfZnNg6c=V)T9c>>eI%7a0^R`cOz z7-T%nO-xYjhw7g${(H$df$>D_IIm+DJn#weTmm-eNZ(n&_)_KQUDm4d|C0O6`bpPy zI?GQ!*=eCP=-ns~m9;HEdkkmE;5U|S=k#04gkWAhGNX0RKhzLWzoktP&^2<4hA_ol z|6`ohIpJPxn4dw^6{N!MtLiO>yEE`UDVFO|LP)iUukGDG{*go5(>B5#lWB6%Q~Fa? zz5sXXZMt@TNrQ}J^8~O$CEz)*33a1Q4m{^oY}f~dS8qMEoYHa>?8jP8?}6W&)PGg> zozkL=H5N2Kv`rGb>RvdFtDJwX!7`kXjY~8#jHfVWB{=}Kj2NOnQT#hhe)b(~z3H-T zxQf0bD+(8t;-AW0YtD#~Fk#pi?)>+G#vQ4sm}>CH8|I#E9J7Y3>s z3W^qMlZXu(^&L^7MdnGn?162`(qBdfF86FM4l`VbtHHF^6k{b%aOa z$0QC071Rrl-V|g4G>&&=07y<@meuRZMpuKexrsdC($@rmEm@LZ{oq(XEr`5H z&^4?4_9UWw9(=+8AJDQ=JX?j_W%D+lfRr8maFW8MuZPBDXN4#w0kr~bOU2#{GUEA) zd!H^%eJ{5tzfb2-4O%X@gG-FHPomALdkqIAhK`DcXUazPpBGacdKS5e7C$jje4Iyeg? zSZ}J*;l|+&_sU9n1ahoS_C|cddIzZ2I--Cx@>NvMofMQ+*&iwGzvyCRpTg-#O!ROZ zfcVWtt&uNxu5I#^7L_9nVK4}k)IZVF!?yDBdY3b5_OTQRoRj%PhLlOo4=KpyTOrw- z1wwcP1Kj3si@hawgF1B(Vf%nkfk$OXT?|j^>*-@S*six z48vOx;C+)b_Y$)(#~n$azLm#$?%DNUe!6#f<-hbcN=_yF#b-@#em5^$YNil7t+E;( zfyZ-+P(=e*r8NKS!dztO! zonxHTr?x{H9!^^4Er93RGAt4Am(`xR z5dohzZoQY*F`Fb)d`{Dq2yP~_#<)m$zqRi)uyn43DQ9_;Z!@y9%^1)_H47dct{51x zD-JO98Wro+lc2!N@a?Y(gEA`U){-YvsWRr7@rEFYG)%jlkXq6|`=)69a4S55hTF7H z`zL;#!jtQmfi6t0P%v3J)JL3_`9Z2bQ|7w66;F7p`E+z@+$ewAp}P+Mn887O<~{Ym ztFXDbiM>Z}_U`a^_bPq@A|{$)6~2~YZ6%&<+Aiu9D~*Ewo+$4T%aO4NCq!5SL(!^2 zjjTy7bApjCG-EvH)o#M-$onfY_3-H7M!&|vz~=M#D*dKS_=>6MHv}0^(^f9g{q=^6 zJb&FoY7+H)N}6{2Y#e;SyO+E7Z{XE~;Ol)>wq`|Xd3zr<+@E=X`b|Gz-8!y=sFKNm$3d zR3=VOBs-|5E$surp}NVrKfk5SsT00zu^-GEcH*6BbXQS&lZGAiu!Ildr63x;lCERm zrhem1r!tbvv^n!ra5CwtG)){h?S9h(WZ)ri%&bv5^?o95#2_}&)8#`=jxAJcA@ZFJ#MYza2Q|*NK9aHnQ)WmX#WaF{ zr(t(AI;p1pUWm`$!oZm!^nLTon#6^YySC2B#EH;^xE7?~`Kw^R3}?s41Z9_19Ww`c zv)w6;;3p^tk&$%AC?H!G@XU;G|7BUup_?6Ua}i=nw5^FU&w$SbhtxI0$Q8Cg3ii>& zdvnAW1}^5@6%wZ^`37rhfL+el-nOtOT>dt|Ea;;)wWUvsG|8^(qbUb6mEi@y=hSG& zVp8*1U-gp?{m74IQxQpJ#~{SR{er;eiLGXOG0#g^U?oTS^<}MdR|*|Y{WbV*0#`;1 zZ$Bs2WKt-axe1*`q;V*X0VRo8rRd6m;7++KY4~!|`-+#6fS|&bpdTW+_4Rpz>SHgY zxEY(_pVp!YZ{b~6daBB=xLB5QJ=D^9>Gioi?L;Q68jf+$Tb)t`O&^$853BeHgzLEu zrL03rIDLu}@{l+y%2kXdcc;$MEm4MkwdglY5A8_X^DQ1l*cjWBZm~-2utlT2&np-&- zQQUiHnt+s$X<~G+zcac}RS8{RgZaol8}Duq!=U2SkE{pxihE)u$b%l`hv(@O`q7{< zbnCL@OO_0jM4-m-i{haqbni{cdNjaN#s#~-6DmFGq|%{4682{s*MSnf^1XI_#IkT6 zk~buaear4{jVKI{ZYk4W73ll!onkQYmxmOy9(qpbS7}|dq*-Pu0s%b1EtGN*3UhyC zEw*x@>6Ow{Zb++@*o?*YriZ(-N+7ScXd4aaHffiDQ;9XYB-24;9mW+}YnE?=icpFt zR3S@49pTkQH{Za75QT-o!Bl zxrn!VzSQ~`FyD$B?TTdpX`;=GqeG0^lCxN3wUvQEyyUi3Va%~zXZ$(c@m%IwAC_Uv zX}Z5WoXyLw>D7S7ET`J9b#1j&l55dmfjGS92QE%}^6ygpLt#MX4fs-Mub!nd@{ZY? zVFycf6`-&Lr57_@XCOO1=vBat;r3^j)pxfOBn9G|*M)dlQ@d+NAJ7!2eXG(Ihf>RU zv{LIUr6IpncYE#t`+>;y5wCMvxxh0Vi8P_JT^D%{B-`w`{MId(*i?D*1!4sQ9O?IC zh++hHXiN0jQpCA=f@^#z!4p2@M!f0puRe8`>R(bIp)f$%(M<~u<@Mc#b6Yv3T#l+{ zBNt?U$&?<({zqV=9F01cmEym(sm9}pZ*(=Zag5x)Jm)?%O9(}wnI zbN7^VZE_#ka zGV>j}gfD3|r~WE$Ch3*5VyDZ*8{9oqlpLZaOS8c%gpUt8s8s&3$Fc&(#_CF|?qA&Z z$V3Z7V{n)LJ(`Xx8gpCoQqi5h=UYGZs6I4Mej9OIu1?L9U}xhF`97Fx7unE#>yG`)t{1NUp1g=aeCf=M2u}L^VZSabNGW zq!2jWuG*NH#N8c}p5}H};L!^~!sL&OVQyDVm@Tvs>+6H%1f$9;?xPDB&fi!XL|nMX znLaYgtIC{EY|WP_%f;D?dv!ye*VVb)VKRHHw~1ZLtU6a$$QkJ%Uz{fqoF{8*NcBHr zY<5PL${(&OnE`4`BnNhO#tg<*5>y6LmN35dOGI4P&qu8HIN^V6axOG|KRg2C3rN0u zVu!36Vb)_AwCvcvs+-)!wc8w1h;~rhU6^PZ{sypy3iDUYgcKIz6{OP;&UxU#V=Gt1 zB;W*wK>E@!ApFr(LuoS4{k=9H-NxoJ=WIBTTskfm@r2v0_~A0*U?kmpq1R@qLY{hQ zcS23pC7?H?Lz3TqS1GPE?)sI#&#hMawzR3^EV5mN&7rs>j7;twwho3CjdBkfha zlgdb_O#aHNh@nFpb%AgeTQU0{_BqIen`wfZ{vD`rx62B>jnk5d1r!#`n_g0!$-MoA z`-#27NE)XOZIx=wsSf39Y>D$M-Mw3^?xsHaG~3{7dE{4{?rC`g9MGXFh$>8o7TJ_NHkQ5M@Y~HF& z%4}H^$ryX^8TNbvJ>3#qyDW)11Lm!=QGlH)7ru9``f{(cWp4ew=8UrU#aIa!kU{+D z)t%q8!{3$3+;Hgi>F4W1y*suZ9?(xaTOFa5Lk}KKy_w0f)+}ZEE^sgA%ES^;29yzy|1pD& zhs*bMshq3{SDqT-3DuaTFO_>e(f7Xsu@;k9+CLJp)+dDz%nR&YCLh7aUxb=eb1K67<}<&Z`4PEmZIt_JL_nxIU{cTygL4Vas!<6Sc+l ze7+*PENLQ<71j>n2_C@I$s1Qjw0zyX3D_f_V?S{49$9DgFFyd3>N0p2XNnBU-i=Q^ z1GXmnjR(t`-Lqaze^fN|?ZkfD(Rg_TocBd5ah)0Oe$7TYlh{`2Cs#BX8_&}JolsM+ z=*DZLP5FCiN9%ZiL)07Y97MDqW?R;63r!OACrQQ2USC}3Y!TEXqzx@+V^_jo)s&&? zWz9Z14JG|h(U(MFq)c#DxbbnG2te6RWS|USoK%)BcC&Rx!2)?*NS3dRuDE%ypDft9M=P<`aoEMom61_Oc0^KZ6mPXezOF z&=5_jS7AopS|1ft+=ab(C{_iEaVZqU?D#to3Q@McDb9reBzRuJl%3*B0#gshDu+jT zJ9*cu+Hf1HAi}+nF;@Hvtan@Aeb^MY-sdZ?e)F_hKcH-NJlEk2szngcK(G+lnm^OT z)u2}Vbz8r9Jb|mo7&T)muamm-^en2<%^Nt*Xv-+7Q!_8eEd>cjmC~doe>{miLh6bM zv;4>wI==Dfz%p5$gY#H)AcwGw2t- zwzQM+1db_yMS*%=-XM|ZORzNt)?iBrtTIuxUmbA&9bP9&fC6*jHz{*#e)DTlK1R8K zYblOR4Cym!HsWvIppRc)2X0Z4xJpYfIP=u`LV-8I~3A>om-wT!#qdDJHBi{G> zs)zZa^zrfI!sFP}OJ<{GCBuL+Slc*e58=1wbX;;@6-=2H_&$Wc&m{()h|bn3xIJSr z+!AH^(L?n7>H3LPmzA(#8H>zPUwg}lgFeSEeG$>juoC}ep_PEN9Wz%Q#L@KQlyQul zs4ZCFTgpxIZ=TD`8BQY_WNF)}fb!}5ijA?{I_$0H*_AB5iI`0Co`0r(@RWWAZO2Vm zR^ka0s_x;nx8(N$6#;@v+9jScHoDTbs{!SZ;UOox-YTvW)hJ-Xa?Z)^x!LLfFN;T^?kv#X0NvQ%iMrjd`A$d1^8P9e;(v{x%*_+2wXe4>|( z7q&z6_xA(+{AlLrmhHnm{A#8!XcFmQzW_O+mX zVgHKe8%8DjFXoXjc$%v@A^iCYk@E*vA;kJMWdT10)Ib0m+A5#RUVwyxE602_tjdkw^_RhyFWRbuzv z+57)S_TC0X&Lsp9Bccvdrv&c0Q&+RNEeuHb)%Cql(>9fIv_}JC{m8_^g1kp;wk4(2 zSx<$Mo!t(!BKBq?5Njx-LsT1Y=v*Z}(!gT8(U!XNN;9viPfy$%9brB*g|I-ZnxC60 zX^Ut!!=u~aN3;MAav~p6ISWw-fl)Ra{9>Bk$L`%arZ^#!N0H6xFW;xbsWrlc75ZZB zPS10s3kTuxv9FY{cP3=&o?oNc;a_{9k3aasi``$W&g2p;4R*E($B6nn9;D)e64{~x zLpAfu3N>-E*0aYJ1nD}ON-2_6zgpGl47zg##6udHKrrmN5*aJhvI?^TLWKZZ_Sk>zg7IP(wAVk%d+fm3b|LeNwifC zRl&Y^{7QH2^^&>Dt5&Fv*}pHV`sO2a$HQndl#{95RryO>1jn!|-M%rQ6>{I+aV@HN zNW17xI*G|1=~nSEC@K*PXd`I1QayIczn4@eFDC6LqCZCUBzd&aMncGomi$q6tMsoQ zf@(L+$8&2-3QFqhqm+UR>gM{YVGGv)_Ffl7R4HUFt?}FLS`JgG&W*$y;sYj#Yo8fg zqC9c$eclsCy>oPJ0~WdB7L2J05)EE_Xo4pUUX?ZQ!Xr(Xf%oj%$0PkQ79(f*iJ9Hs zXdys1xRONYbYleUc7J38M*0lZ^eJwAFH}RQd(NQL`pmKvK>Zx*m$;tFbuX!<>!EEY zbS_Xv5cO1afqqwZ={q5~)B`U&(xat27r3f{^C}z5K=+g$D%>D^4Y=bWnd?5gw9_at zLvxs1eIZE_uwZ4k^0285Blkt_Hs5NnExT4XqOyC;C&H~K%m9?l2?Y5G7zYlxGCt8P zi1t*Bw=Tk~-j6uK!$V81ejm=yB69V!O2ovVBO6jy&oc-#L_N*|3_V zNh6!x>ZF5Qnc&TmqhJta;^_FPR@Zpj$_lrRcOGew=8%%M1II?XWFt8be2Js82UdAw z4Lx`u&8C)+%0aJ*67%afu9Y91%|r&2`DY`!F$h~67K-0sCo}1|EVLSXO=adH0U8cS z^`*;7cUZKp^dOMVgFzEO#1-|S2A}-EL5YFD$_hz5A|B1VlJsjLc-23h?$FD8P>ZOv`22mn{NE7|J6Jr zv@4bY4z-DM)=n`E=0PaeUG)#MCLdcu#>@{F*mOhS;|ZZE{Xc^8pH&Hf-Y`yW=iVPo zWuDgN4qV8qw$G?v=zQa;ZZ04xGjIhQI_N*ct80y58)%VBbQT??X%-%~fuF4Uqu@UG zjR(DZ>z2ytSmvrk+pG~cz$5Ec!-8fF_+gxc{ncLlp4h=`XCfT8Q%By1GxR)gt!*+_ z+?v6LBeUea#g*bj$ldBko2?T(#eLt$#!RfCI6uaAtpZ4fQf7i1oS1G>@Km%1?dk}A z-q+U%XiG17{zE9_;8En=6rQF1i6U%Bq^i5J`48>4O!n-mXCJ~t*pV~$Ww`v=RYOX@ zNu*6Q`6`=Eu7A1a7E`1>c-rx~swM2ck$zNh62-(!6=&JZ3HM6n+EoUs9@#jknP!4z z`sJSMPn@G!Hl6PUi-A2!lAYUC6RDxcCA}3BjN?f>ecu$;krUzN5)3PcIA~gi4GPvx zli!?+zgN4azNvv&wjRpMYPVTJTbh%~mt_~i$fgUsyk{$n!7eRr6-b$N5mLw!+Msfr z=J78Ys`J1ySI-BFuK=GGh@BPfqJ<6Q#d=JknjbB^C{DUt>(I6(+Yswuwq_|IJB=xk zT>Elgk7i3MNbeneHhYMPtCnzyxTp>~BxYg9b@ZNRAPF%$zf8PDeq4)Qpp%TP<^7&5V0o zEopM=Z?@uA8c_w&PpH}ucM(qkV3v!kPx12G$_395bCK>Q#x*J(3$Rb2Rtark$9 zQwJtlbOK<|M4{T5AbmpYYGy^0#@p^Q>s-02bJN>X$a8N5%@V)$IA_!>e1TPVz%(Zv z@0Ysoiw!H-90k2u)n?HXj@8#`fE{|3-tHgqVYYVAqIx&Stf^c2%)LrR3v_rcA6Ih` z3DV%mN^)UKiFdL#O9sL=xr_ddq1hlr_K&-B0&1O*dT%oh8-L487A`sx`)J|0S%md09WP(Y4db9xvLX7f!26Fjrz#L~cUbT{CW|%} z6A)u6dD-t- zNfcXhq9dgI#`JiZ`9%5J@1Wn9zyc32S&!V07RIlctKVqx7fxGQa6k@%IDhZDfS2M( ztIpiSthQC}&~FSAh#Ne5XLt69J@GdD@bSjOxoY&F_o1sNU+U%!ocTipaDol#m_QZy z?a+#8Xo}E>C<}&h8G(v0)TtSxh&`~yc#AF7zi@T)5Q3N(A85dTghA95#I=6@UYHHA z$ih#TLy!O&gAKUHs+P*dBn45%3yP!!_3W##Rj`DpXy%a>i7 zEv3*3RP$GMcv~CB5~Pdog7184vs9lRD@!2LW^G%c2kYjFnBems4FQvyBX~sSV9ne# zDM~d+R;%S4T%q0pGy|~;KkUx|ZcAzs$7YP`bBNFIlDvoJ^*(#Bj&(4F=dgmZGP??N zTN;SQ%uV@Nt8X3DcIUd4Xj7>#d46}Lq)=q4AuX~5D1llt%46MGqwz{p z0+d7l>(%2G>x)Xqe}qj0+!Tbwkbmfq=ht?d+2ODT>~|mK1~$crytRCX;n7wizM9_u zWf&S6Ed4m;Hko+hA`tCMb(QuroNb?Q!!)5w>!pwN4`AC`+F7};7o(f6{fZ*W8knW` zHyvX5h~N83QOIvI&}o_jfv*pi5An`#%|veeIM|a;?Xc^7Tmw4%s$2pzEL;9;zYU&A zrx{X8>Fw=n%IzZkjcoSVWfEuf-2T`!+Mie;bUbwnuxk@Z+Xo+07VWdPc> z2D3MHJiWYV!H;Q2$`WE-uX1vDX;DhL?wJsdz=G3xr^$UIg{1TozeBeRC@Eqz?`V)S z<}HirFE?F7hduEren;e>3+=|`9?rrhyBLfnQCiJYGK<>PeX>?d18-|YR$xHdHt9=z zZAE?|OGl53e%|gW0|NJ7adjV&SQHH`N#ka6Uv|wu^f)5=!rs>ngM0Fcn?JIFEHaH+$GeNhupAehS1@Fi#*4S1*O zoe8dlVw;Ziz+YAq!0)nf6>RxO;U)xT?e@}6%Y@_KvkX8l9q)5Jn=)`3G=H>pZ&vIt z_x+3^@p-Rjp*{6X`;#KdC0xItY!U9oLqQ2~k^r;T9RbxA5IktpYLAbaFP~yAMo8o9 z)E%(G6fQCV$GaV+TNiia^GcR}FB$~rV25QC9RgGTL^zbXr>p-G$PrmN7RIY+e(Z_q zf$}xl5VG6>SuUc%5B+w(2ULi+1-FPcdm-<+a>Gii5Z^V~jK#{YKunZ>Z-~(@WlAl!V zknBm|QTR;y-K(0_-ycA&LAHU9_Ok0PMe&4ob(dd<-(%%QE=+n*N8E}_fPWVR{5;eR zjgGmQDd+Tro`2;rso!{=+ma`-Ti7DSLOoQ&1At&gqA)_M9B*Pw1sF!fdxmzrV7(0% zmE6OF+nkoQ+=x8k?o5ZT0(V%LbavnJnCU@Z#N5w77Z)#VcDRCiV4gW?3ml+T&TJ8n1tdz5awyZKlWE>`rTsU-%|$Nm}j$BEGbm zxpw8q^Kj?rE9TDL*UM_^I?1%)M3F!cQHd_^jbKb2EfN@k5U;l*D!Ffu(!W_tiuxQ> zTzE}bFO>4B2Q0BBv`eyVnAbBY`*s~}WnhaI>u*{fOI!6oRZH~a)MTDn3+O6cqpvH! za;V_@*_r|5)#qcV%$PY5LZOMZk^sNskI9?)u#XM~^1pwW_v-Z380NS{-Re=eW~oA< z`1ko92b%2I5_hz;AorrmpX=pNS>HQ{5_jGbmgP$fy@709JW-+{pg$RyPQ6vQ?E_0@}zw0t1LS3l0B-6n^H>*K+2G z_}1RnEk7JL7Wi!p`>3*Hic^(8xEP=zOi?XKF*sYWH{FEV`k@ORmgc*^j z4>4PXs?Sm6hHv`g!-#zizOEG_7%^&1C4Swx@l|Hl;Ew-$K@plMeTOT@V07VZf5x`A zTm8%FL#IcI=52d+5{Us6;GL$NB6{r;7fPCx{&iU$F22KE*$#!PgAZ*zL&^=cyni*A z4YUL|@ffZ9PPG(yH_ygp!C47}<1zE-}avf$O!`~s%qD%gFHtKoRhi~f0dday0 z%O55Ky#deDw!dypTrY{vRaIAmW84|uUWt4A6=T;RjsytzG5`}O#K#3UjxP$oowhz;#^fP327WN;9bv03& z+0<3LdkPwWjG)x|{l_-Rz1EGeOW5EgmeC*NH^3e2 z=%9{c2SAT=`RBm;$x?EAX`XwPu&%<*0kPw$xA6oQOzY{KfC;i{W-d&B2*|F z&P2rjY6RJode=;)`~E?`Z8z(SJjre zCcls#PG$(T$xE_ca8dLr5XSB=eSKn<^Q?UGNY`E6;u4;%b|Rac#n=OY|S50V^-R_df@MvK6xXC$C&i4Esbw$Ox!P_*Be5)uZ@PV-{2jtSw`O~2F%4QSRL*l{}kQ}}J5X;^=&0fO+ zbDT07a~a=Ngp*;!cnmP}#fN^Ig=b}93Q0h6t=Z8BFdn2+WG5Xf*xj8ADObi(7o_EG zEQN!c?a4;+AF7;8*jH%(ib=Ow>>UBqsp;}`hmeVQnpa0^1ia17CwGy}^vu8uX=o9f z4YIEaM#_wjom~O& z<`qf9(+^sYHl?~Ft)>Vtb(4fBuEj&nj+9*n;=S%Zq3y>#9y(wnRQOH~6A!ND1M87> z?RMnc7Vl&=dcSL4K#tfWJ^HM1s)-{D`=Pp~5gz6G#Y);daaeDLe$hlQfVtv&ZgO8s zET^As4#lbl3aqn6Li*wIz%)$D-R4w*-hKI!XjV`WLSG`iq%gQ5Ez{u(xy&7 z2(?Kk<=6!;$l#dfEA-lSU2=Y9C7i2Hb}RuC(gUA!7u{0-4ghV{Vseh6ckSTi3%xa5 zz}0i^7;Fo8#o#h2sJ6`b@>xuTIsjmpxcIigz-Mer#WJ%r9WYHC0VD6kdsb9fGvf9< z6^c}?cK?KB`?D&6G{9U@qj9B_Y-~{ClcMUHC3Wx=PgjQ0l=+p4J|DJmF{md^nu^F- zy7NTGGLo$+qI|7qD)pXq;r#b~Q@H3FF*36ty`?g^8(XE&7i4JL|G*1md7qufj_VPCA_))JYFy)*yB{@i2P0AsPRIN3B&*C#5d*Cr?t$-QacaX-Sw7TY^yn ze4ak;GT5+^~(OmFWz1{Ddtma8=rSI$QXKqx{}i4Bgm+QG{~%I)`Nc)J)AKo zUs5yupbcox0y}!xz4|rWG2iGd$(i4@nByc)A3CF8#-mAWbE|!FkxzUlmJvx z4e&Zjbi!;TyYhm|VL{8TWk|J1#f(>9-X0(WbEiAm!HwRvM8dm^GHi<~$Xxi!=3+aHQO*zzGz(E&Pf~C~j4{@$29B(XJ#GTBCGX6D6Ca;y}8W@nc(ZmGUO`wp! z!~wQJ%JQ;X&1>WCm;q%*ETq6uK49lZbmfx{>?9Q;ykM*&VhYQ1R}gl!qJ;rMm3WVT zfqSOivdi2f;GChui>;Pi0i3c)uZ(6fc!?8tBk6@wn(0DNu?p{tJ%TD8y(YL8qzA4z z3Ifa0YgHUZ+icnzpxaC&jmD!ystckrdIRa-yb_q;K`sa4gR5a=?wK;#!5^;|kXQCn z!^x4SVdmEkfFDY_f*pPK-b{N=4mbF`T(kccUxqAOU)l6?91t{LR<4mT9bHH4{j|(z zz?!|Rl6=2_#H|Q5A4i^cE0*y@c*Ug(sPe0)k7GEI^)vYgAJ8kpRUq48;BE@a*8c7G zb%4fnMRhr8C#b)wa-jV^UvM{r@@8=JS8gHJ-Xc^=adZqstKz42bFrxG4HjDDi$hz^ zi#b5Kg2D@s)mE4msku3(Lpwm(c!~$9-3%0nnq19vVCQ81`0{FfKo*P*-nbn;<_$M9th*le^Q&+a(r_<#cu_ih zRZeCj%QxQc&Q-1*rQWyn?4aMvAfD> zQRSn!X9vghlgo1(w={3$b-Z2Tv0$KB)3xCv3r3tn-Hwmtxo*jsF%3ebozqwvOBtGo zH)Bsf203jy|FtM18e+3|iE^PFHt4i+mZ$sm_{!;4W@qGE2k1@6;iYYni5H5D#`ar{ zIfS&9$9Z0Wemh5lZ}B!(Ru`F=m{M5hvMMDyGtZo|n>V`bA<@Q)-CHQJO1oLSAhzjV z_qAv*_Z^#-1mv=WJhZdrZuI!?*H+_`R~_G6T$kfKYkY-Ud5J;Dp^|V$QbH~O>+pQ( z^IFH*Q=-|FX+pZkqt|x1` zyVYXUcSxYsV$WPna}(`P&*h#GYJm3bkJS!i9DHgm>{%XqPYdo{(3Y*Ps=Ifi?dWb7 zUv(@mZZDDZtfa)K1bEUruhbm}<~4|3DRWeduDGg0xBb+0t~%)V{{BqqcPm?t?aMT( z01fJ4%Ib+ZeR+c-M=H&1ov-TzpNLCuE-Z|HC#`!O+;*rOWYX4q>JqBe61r#j%d;X@ z^TJbS7p<_Sr|>+q<=_5R-GtH4eMk=f>Wb(JSDgnotqZGmY^3x}$O~#s^R30f7qQy) z!PSi|!g9GS9DIg3TIu_aV$-n#dKcf1c9J^M2g=@xZ?}b%`z+)Ri7OlhKe*gy%V*dY zVaV<2R&?(#963LzL5Snj{o_@-Y>#h?A2`_p)nlhBSgLCjB<^ZI%5-EG;hy+8wdoS! zkY#-S)@RF2cQ-xHa@KLdWZHs$O17H%epxy1$++9w?uDK&kO=Bc2X$*sk=X5y8T364 zD4?@zG-2N#5xr#*HXbas-w#ZFAC(v0NcAd4@yy7z8sN;^^tG~_om^ct_4OM3G86hl z4*;;RrASU78|0!9^zJElgO*&BcyAJIegBqeyM^6bcLo@k*=x=9>)OjVI^I8;PLpZ7 z2?dOH&Mg%kAHTWyv-W#%jX0DO_~`WC=CTP#~>M=bHruI}zNqjrUWwy3Y+5S0!`Q2Jsn-hGzhJ#u`Zx+|5-|43GN#JB zH_ioX(MAu1dr&?tjkTu}NFCU*!tY`7r7bxuCiI_w!sTb8yJIh2+dkgFjn=$Rm~lBu zkXUz&=_ZLhbr0%49eLFL`)7?+Xrov_VxGR%;htd_rd?6pYo-knBqV3ad2SC?oM~m} zz-bh~zMq8rTqhDs?7gxHX*|win%i>>3zo?BMnx}l z9u$4&NGH(vux>=Q9KgQy-3@h&B2c$RVM*)1-ou=04XwC^ANLA?1`Uvku4zJPo$AO1I=hZSf)J+HKOt!P2~=MMv>{IGpJ>9k;E#WhJY}#$Md( z!LZFBPMy0x{9BpeDxoz$AxRWw4`%hNIbHAd$(?^6UFyeRl+$6(=DC)6I@mC(kXY4n-c1zw;PKw$$_e_L4|88zzgq70vFB_%J~}M!XvBGyiY0dt z7A0Yg+D4#TT15~_DNzvuW;SR>!P^NIm}^uT?^-G~YR_KD3@vlXE+A{UT|5OHP`pfbdt!xuwBvl|FGFePrR;%BFMRIoa2I zO@B#GU6EqfJoQb}!lK=}cE(bXt27!G$_SMYtK;Hg-!U$}^=St35Zd-QNx`_FBQY>v z2BZQ)TFo%dj=H|UuzpsqO1?Mg7V&5zD52ftmPce=h(MjQT1YI=hs6u`wt#gMz|;ZT z=kMRR+yCv_K)3{(%P&`hMr*dHnb$~Wj!WsT*QF@S_tdg=BMEUs<{@9``Hql|v-y7y z^%Mjdd^R|1ap~jUar+&uC#_c;JXz>VSc_PTgA>I4%chuLtrwV-eSbG4Ql2!fdHLS= zZk17cZeZ&Wsdpc}eM&hhD$FY|Z`??=2T2 z_3(y`7MoLA63g62TXQ|qOYR#)U+-(M=yHXFv1+ATp4*qCg3qEj^G(uCz)Z!??;MYz zx2Fc)hk*0fZcUmD`9^eR0k0Z8%;m=sXrydIjV#C#OFox|nI8#lPF_VNx zUj7e7D2@>I@H1L$s0t>;9iLz+84x{o7&4a%EqziI!`$*BQ^T`K4V9QWcCG-JY|7%` zf6{WWiS{_V+x`}*2kPm%+L#md98GUh*!n|F<$=Pdw154dIS*r;oa}nMm zxzr3iC;HHmVQ$tGIX2i0tDDpnu}Yscuu~Eh@*@7E9_DG|q$7IA_j?NFwS4%7Pp|)y<@KQhhf!-A_zW*{W%`z|@kGCCtafw0U30NbWi>w`1L=|I-EEX@vmRZuj<-ec zR|uXRtmWhH;>a!f%GtPp)BJwzkNBQ!v$IfUVePz`uSt9Xd}o)Xm6r$K{4PK2(LGbB zp25^9$~Arw;u)hxB6;&W>3E#<2SUw;Z;d>)eu^sI={SvddcR@|b?XY=TMCX@-i8;v zS#Paa$@v~i!h$VmIAtSsU(n@+Iqzo@WGbL)edaH~y}UuHuY2g&w-2p9DJa?XvkIwt zu3+?eS};Tu{m_O+&%L!k6DxMNGdn1Z#4frCyl7|f#oPYwv87vV0Q+K|O^*Mi2?W2G zyty{^GNy)ji9hr0gguKeHjekiX8sIP72o<}f;m!N7P?THW~q0RiL zx3Yvm-{#q^I~J?puLgW)M=PF{JL}0TBWEv9C{gES^g-zt-xf43YLl%iX2AqdWu+)7 zS-zPa()ZEKR4C9-!v-d=9Jn43Kp*blz@$ZQ&s@%{?{3KwjUl;JVp8OO-K_khQzJ6x z4G60569>;5gRTUwulvP8i)G5EkXYQy*BSzSR#@9(Pcb%9Hr_EWXg=K?zF5=I5rg=t zB_j;5eTOoxxrTh)Y7rTeS<4u^o06?+_WtckHZB#zkx<<-EwfB^?ouG+dDEj+Mr3wP z@H%;kdh}qBSk#7KqmdwTMOnD*&Il|lCOMw#P>_?HN5+KR7Wi8}y>RJxCyK{XA5p{T zLf{cSee=F^$rJa!h8@(_B69KDL*DvkjD8ooXYTJ(^vo{}7;*Yi<1>pLUXLm0k_BqWGqJ}9C)(k@2Jbl5<9tD&I1n- z0_f?5wTV!0adB&EYk4*`tYJ>qD>^F3KDdvu@%vcEZQ7S6c|qf%$&NHqW5GV<%9w1V zuy`$8!jf+JmpV8+*)Qz7&Bm-NK;Ly6@db`~@ro+48tYy-a6(Tug-PPz1W0FOg1w5Z~ll70(HqpCpy@PrE?0Re&P zxC$d_z(NifT~-#%YV>XuftIXh7@8r4GQPtJI(os;Rt2LoqseMT5-jk@@X`QZ25UzJ zMx0Q&s71`X8Wj@8d~1#p95fTg(ep%o^f=Fl;N>pjqcyrNiK~t-;RZyT9imS<)E$05 z<;nY4vi4Oi%JYq11WPFY%EBB=Kr_gDD?jiIC2~b_z12ikR%_*;Sma9Sc*GTK^pwf% z#j7eY!N~m1nwO->I7sAyKJRHc44OV6Sl-~q;sz&Kztn%XfixD0^%%$|D72x`jJG>F ziA8pskFam988rZXbk5~ylN1@%=%AjX9NW%&{%)U<`iC)n2gE3~SZI?gIy%~Ra0FPE zhG_~|A0x;*5T8E(N-88@QLnILM67C8k)Q;pH3+4;s7;y zp0w5@P?na1hSv)IW@pR`{1!+lgk)3Sf#X@D7-5h28?N4%kr!mkV4Bw|dfh(r4<|x& zkWN=XhcS$HG1Fd$8=Aqb!ps^Yp%#iAf$`Sb+5XjRW3^9Nex|NyP`SJ{u5HtXKsSjt z-cjxeD!+uu)%^fw9I~=rCd-o98DaD1p563E+QTDu2esWVgl#u@)+{M7?y_*f40^vQ zEqQx1-`Wm;Ec}`Qd|9LtZ^}rY-y$EenqK;8fgWsBibG+qL!T(qBSxaB9C@?xq?SvP z-H_`EReCYvd34i~j0az7GgiMKgG{NgEegSJwCY9jhoTE1RoWX5F+vY;PS;<2q-tuK zEDGc3u;u%heN9zOP0IBgtwBF(b~|_AIit&&W=0O$tuNMS{p%KDu$IJ35@q{|zHsh{MytF9<9F7RX@i)i zr7nmV-|~a>wumgz5CQ0>W|TIX+n2cADAd>ewwH-xw!H(7srF7egsoz(SDDy9hc*2O zUWkVZSu~1h23O#*3ybgU#}9v>Mcwf+mB1aPPCIy_IPI1I9*QuwLZ`st3q>{>>6~&- z=z&(%tjNmB9v9dd$De-{uICB8I=buN603Jdl6ugk>t?Q0g*yY|}y!)KYn|;%v4+SawOE)+B2jm2pyz`UEsYo#RhgYO(b-H3f{2HyhPG5s?NnvD=bXe*MyX$Wxv0SqQ~i53vooia$zdl3E{$ zT#~Ho`5G-u%yJ=%+rBBeaE)#o^7@<~tQsQ9ETak0GY&Tg6PK6Cj@OvkMqQP6J2TpR z^L(l{iDC93?7Vx(KgqeL;$+eqSP8A)4K%Dal>+Eqz^;`o3ueO&&spsL6{V_@>~S}Q zK!`YYFdSwpB^AStdAKD&A(uv(!PXYn!@bzLC2a_S9)MZe5S56QVC_}|#%qd{4@*2~!P*!i-*o*pz9bXgNo z8g^f>^H`EeR)=-Cjg?>7_Nta{(Bt`^2Z;vb;A9=R`kqri813QYY}V6rgW9KujrQS8 zS9yMfWVK+3&h#5rm_B~B1mGY?3iry75%3KDb!=pBG$svkY8FOehmBgrKBG7=*_AO0dL`PBIAwGC5=r+4VV*C2U8}~0J;bQdDnaU7DoL2Pp`>o&Px}_nrK!pTDlm1ZF zIb#26dS<2@SZ%RThAy9s5E;R@ZJ)zcPFA+=*|=$Z+OpQfQ^jcoeNTje4X|&pr6f#V zf>nlBCH_l=FkM$q2d63_F>bE-tdwnefeET5(nx8{@HtLZ(jw^bbSydZ+aNh)&S4EI z!!3;}5nKKWml#c@2;Z{vrQ;8!2~%P0B9AU#=h~HcBD)(!F||p$2|oipqVMmoc0$>% z)pg@Nrduq_Y@eH`DBILmxVI4^!YK*X%oM`XZ`KE+hdH9E3I>K z_{7YMfQ@~$tE*h1CQ+`bDyHtad+lD=({%6e;*w625n41Ck^*wq{f{Xr{ge!meNI^OxV;s$+l9@2KN&W3-oA}m& z@xHm=r^p);j@i=I!KuwiU~=We^dKHkq5m9U^9v_K@!BEDxNi9GbDI{7^gRYqd#eqcb&_2x@m3p}Jm+w9_J?JJw0bXU&W0m$ zs1}~1TMP6vUH#U6xwt`hJO3tMcM}N7(6w4nz;)cF~G)<814dz2fqX z?k#&2IU(qw%>=dL>QwwgiN-F7(e>@sKAaoY8bosEz!wSJaG%tc{xY~8v2D8(Opd-n z>PFP@l z%#h4no7D0!nbB+b?+AjL#K+ANJ`#G{)<0%%q(ASzP_t@_88DHabnd`%rt2-evaJ|F z@>4g<;4m&@O55(gz=D>aGNjLPL&YHkoPLTmr@od)x+3 z55@%4+_;{j1M?sR3Nw(hP=nB<6lsN7;2p|KPI>+MMgE_q$%fI_E9I<%V;OYUMVPyh zak_33GRQiDZjmV&4jKTn68-r?iNttiiG{{2K{}8%gLnmQeskpVr#tNjP1FoVGnuI& zI;B+o2%sJ}(IrLKddc;s&#z-P%mXhsnbGOIsa~1hNP`0^O!_R~XCRjI%Lf<4g>BK5 zq(br+cK>6!QzK^#zU*7LxZnW`zrDqcfKWkkQj41tV0_RM)rqHK4gsHnvcMpLr2_@J zds%DVw=SxCCJTN+Bp2e@BKGg;#w)GD2loT>?;mKyNDsRF{WJ9G;&Pgci-10Q{1|8> z+B&{!`z>w=+*BG{{G0mwS6X%Q+ z`}aP{KUEOS#j+340?rVrEMJ()M9=K(>>sbBxe>7RfSZBm$kz+>3Ep|YF92ETtMTLiDUA`g;tlWC+~Y6%1#`|GJ^VngvmB-_ z?KA1$|I5(AFF4{c{u1vG3F(__(o+8^Qw%KR`hS^>`G0!(k8b#{lr;dTz^v&z^^#ZN zsvCZ!W2P4)m`cC_kgv6l|EAf~s(;4xKLmn9dnF?hcNgld-iPLZ9-h;`yIz+#+y@r% ze2Z(r_A!vInR<%T1}<}A6()PAa7pWK-g7oJQUHrh=)w-unVPfhT8eEj2;&Hymg?q=c{yRjI$Sf#`=046LlO|lT9bM&Ouq7M} zNUCaTv4d|iSEqOP?ZVwv(D}N=9ef_V*LruJ2zX%*qLOjMxz=KlFJNA*t!{@#H`aR1ZmM*1NhwZvz#ja_`I!y_ZA z!q|YQ<@;@$FjIA?4jcj1llJ|KpzNn{(b0hw`7FTq9l`J4zgLQq24qgl5f~O8=BU)n zS)U@f|M5dN9ELWusSXfs(|LlqhURPde#VU3^Q?_ZVr2c`i3A7c84s_YAA z9~&E^=H}-9gQ~nqro%`6f5Zszq)@uK;0hPo_WU2`4lcg}|Fzx(rfUB~tqx2O;RA_? zKAl?%Uqu-CUJ~H`)0chq`(Hq7A6&gBvTgvRg{J$zhOsUKU-yKF3ZS)V&ienD!!H&^ z`+*H@TR!D6>7LERtCUV1~d3^RE8yUSg185X$zQKZi@FlYJ|Nq zoiq1?EIV7=`5xw~Fi84nSv|<=gc$K<04(F~xr_&V8-sheO`dCBq!zW?AmTZUR$VyR za6)cb_`I@oMTxrOIWtL2#a4~3pT?&jVm}4S2FJiT%T6u`4v9#5&A3+M+ySF)O~v0B z3ikS=-I3b8`Hy`gBLgK8k>Oo)GR+B%wno|J1qdhHgS=u?sAv0Vs<5C*r>!UItSqhw zKz-CeAgcR40+_%4BBYW>Qu>+di0!4+C<#SkEC{JtH4FW`6xV_V`+oMJrW>?1Nd=T8&gd(rt?PVYDIGD_{2!`}&78@3Q4n;AwDxezFug+~u=HO)HN1{P{Cnuz~w7 zBeJ2~qaMF}#5cM6w1S<9JGi$rEXiu~r5i=Vd%qUyZLy_hly}qAQIyQL^!U29iH6%u z<*@;w0J%9Z5I|R?eAn$HgwdRZ{-p?S=y~oY|8*0u$|ab%!eQrYEmVu!y(B4=-YQGY znBZ=nwRrENu@1!Bn-vuX_mEM4388!=i=(ofuNlslow_6rtC%utMyTzc$V=(a?02ys zMfP{X^@t6#bX04Mnoj0ETWDV%6(0*a^15E1rCi&>p{&II`56BKH@?{yEcP9T!Zd6i_cYPb#i+H@TIfCta8>#y0p-kSHHJAH(jMeX(q#0AhsM*EGm!WIHF ztOf8E(;=n54`u}@>uV=q(ABC&Oe^w^Phi`@#a3-Ts^SUB@ec{&9)#<%lS*T*!<{~C zqf*H_wvmv_CZy69@rs`a<6P;tpLhYqWy}5-jcF?Q2YcahEFcSOxH?RPAd&)@>Eo^s z#cn>AZCKUY#_tu$Pc<`)py26O$XN~&c3!*z1>K&F1n){3#^QFl_aRA9)Q&P?Wdo@h zZ}Un|lKA(njA~WLBn1=}aZi1mr)fO8ua8|6z;be$xqzk@jwkSH7r$~l;{~)`U_78+ z0ZD?oQ3@vT0+Lkrn~9xS+RED&1tDFHs%-~PlxLUs?IVF=!j4+%r9|n-O_b<-&=(Zh zgjZ7^u&2o^FG|__aW#KDVbo7xx9gORvM;VbQI7VBiqj|5PB4u4vMwKk^uUX0 z>sC1M_#YB`muHoTRDmdZJ4|ZPdw`F|ES=$%|MwP`!(q2YAO2arFcPMLI#Qgrs77_F zCNrN-cPiu>Xe{rq{Rj2Km_KOnOt1PArSM`LmQzZqHSBQ>%)&baf~O-^`!;kzmSjAZ zq{$)V!ioxSUS#pfRO`xArZ9*lv24?;V;ws%?eHd+V*^u)#-&x^YZkfeqUe`6t8pe~ z`Z&KHf_g)3I6*;=(EIC~%0=aC@z@2aD?Y}tv2kT!cxJnp5(L+`#=t~Grej3EBjl!Z z@nVa5CnH2A>Jrgml5@RBgcjtO2_Am5Oc5o$nN}V-J(-4p4F;rD-+Bl(^g#IgUVG>%Uf5d_#8nfD4 zWn-7DvB<+llcaa#JJ!)Gv19IA8%64eac24NUv#Ku63(F~TwrBeKLnRVaQVh?9hk9F z$tJR=-VU6U>A9+4+|WyPVFQ*Jnnl#l4F}Umy|hV^EPzA`SMn#wl~OI6K*9n$XWMGH zHeQSkKvdS|?m(GoaNa|lY3J*?DCJQv!+?S#?STNSwE}diUipHD%d129sxK5c{bEg2 zD4<1gU!>D?LW*~3tFXOC@Mly>PK+ryseiZ%QQ*$uFPxdBuN8Kaa$}wRNNmml)Yq}a zFpyw592^mW^0B6dYm-aOw~d2QQqtf-;zEGf;Z#)RLplWW+odW&e;auEp4`WaJ+NlU z{8j4{T}E^}D?@+kAM@iYXWb-UqG8)l5x)2Q92#XFyt>@`sP~38*yqsoOyuhD;9H%l(fe_Eu=`0pr)Qlr%H*1{0SNLdns0uMB9vuTRF@Y&d`B9c zJ({$HcN$2#{o(hQ*sNDR2<)-_7T=(R;@F8xKa~%6`Oewqoj5S>vmfQZ94I+fPa)UP zQt#m+UGs?U7y5iWy?%TC1#kK58^#*fohB?gcxgK~8PS*T!|N}v^+a=ek93rB8#s)E z9fT#K)+m|n240PTcSn4aj?ioB?qDX0-7ndL@e~QlT7@d{mu)4h`^HETgS)3~H zlzhEseZ3r>)0&g$sOV43DWKc4b=lx8@%vjzNe)-HiT)tIt!3aR zrlqZn-c^sHxtnqkoHV}#U$#vI#4eo{evI?Qv z^2#N|#JK8JtH2HohjT2HqX*`t-t%)X-P?bfl)AyEy*(&}dhFhMlLK4~Ly9SC<;jo>knOzSsGodRkJ?Byc3*cj)Jm0jF0 zyAbU>LEqV%PQRL&)Gl>S77aao!K?lrX(Y5#Su&08F~R_os0~n7E|oHfx-yROnHz1| z0p;%XE?61d99+0rnutB{Scc-Ky2MgRcY98bdG&(A73}Wz6u2YhvHVtjSqUQOd1JW& z!FdpjGSnH9qcE9^u;JB0;+^k|QDu|)(njMSD3nxI=sIgV!Oz_=Hb&m!A#)(cWO$LX z;D8q82;U46nq*ueyHlq-V5!{@Wrq+gq^zjF3E z43ox2rF;6-zp=?=-lEw3i0~^Sm_=Fs#XzfnFn2lNM@|Xk+gvHGbhlBXvSqlodwm0e zwz!_)Ophkfyjt6)9eTzRi8DGLB1$3p10AFTWLy+j{}l9+d=i|#+DRsMvP~W=-kkN@ z_Kw4&?c_eO0;_c_1Vw6df`Vv?tu%(^U)#St%>SJoB7Q}{6o%AIN7hD#Rk4kZdc zO@ap0fo2-j8!8`SReb^-dlX*mzPi}7W);4XYG1N!F^bsLPi>ERHEXb7o4HiMIENdX zBt&3U5W=WD)_kmy|M;DdOU_olWVv(;ld|pxwG=V?*;6Z>2-Msco>532^U(5@=Dp{Wk^+WVqLW2jDP!X6Hy)0ydrkFY6`x}eNYS_0oM)@Hu4|2(; zVqlekr845k@^vF&ZQR0{8rSOEAtYM;&J7(|iK)f(NzWU{CMDMpz%JEEr~m~&@R>*8 z!;do^YuBsT%>EvqPMwqZLyCF5qrAejbT*SHDg)d=^X<$LD-=ZX;Ec);m*1ocS zcfnbjj={-R^?j=KS(=1<&SpOVlwiWdGMVb0=cu0FtIRArVA5%&pU*x7%-nQ!UOCiI zG5vC`dh0z{(>X<>G)?K$?)9}qW0b9goM|+Hyb{xKv=8wVzgH;ufzrEz_Kl94`IqlH z8c~<0S3DJ{9+~y;Xt@l#O*-i*#MI)BSD^LQpibyftG_!zo$%*Ko%+DapjzV6u1Y{n5Anw{9tvg386P?}H!|B&6p)olYiuz9Ku8Iu<#o5}rm>w=6I*=3m0>60&bnHUcif zy+lS2r*$>IT;e28O1iOyOPOna84->J{ATA@K(s{R)tH>NMGHMVi{@4P*8r_|-Tcca zS2z=E@#2~GO}27m!gJK(LDRiMl~H3!D~V{tndkNlrOpK^`P&1v*wWDe+01pf>M#~Y z0qn3@s&48#jT!s3E^cz#DDV5p&jA6Bd zjCR)^lZ>;-F~_{7X74(zC}+-iC%i=-Tr0`VR5G;<)-dNPI+&cf##EUJuFqlM#4Nm^ z#SkDJDCy!t(~4QMN?_l&fbzIF`@RGGSV$W#MgaJ?n**ii-y|W@Mb&IVAjR7qaPVcf zpB|sRDS-Axl`U!amJL#q0+xA>_XfA`iHs5PqsxxQ41|92zLJa}DzL)LIZ3Wv)C6&I z$$YtR?`B{(>#74fVIK)g;VYh`&Qt6+F${K})Z$s%pQ*cZrDLJ7=Kr!x1G0FUye=tp z8pG6}WbOPjQn9YTl*Y=U3HA|64Z}3e6~Nx}JcWrEKu}D=tOLTCI;go-S}xg6nKIUz z!PgxeDIP1>8>5vs2z4wH%-VWy_LHg5IYCeb5Nz_Om~6BB3Pl1&q1&>wnpfS{?h(d6 zq@b)&G04s(%QF5&46H>lp9rnAvtGVW(jM2pJhFY9xRn+u`K33^0DCUjf)nuu+iaR_ zvmT5e!Fs6|zUv>vzUHGn5y}C1Ef3|wD4~JSZ>^cKK^YZapOKgv2z+k7TCEc3bvK&~ zPE-oE{N=k{gs_|_IRZANT0N`sRRa_J%^wO&euPqhR|VK8HpQ`H3gu2XKsrZorPy`+ zOD6wsbZly=f*lY|>NDCkQ{gW+j~(^@2DlVk+QPU8rudMN+pQMoPuaKW#rJv}|l(}RZ1yrT0OKC(8o(A@VjPf3CsQ(j4i%pKIc6Yr&f zg}?W!fsnP)OA(#rR&&7DCDJvVuRS=b#-MD<3{yeClY9aLZXm-$f@Yj)SY5UR!H`l%-RnSjP;)uev$E4Tl7IRP~g z@~nNv_Y&z@wd4c&jSbvn5l%H#%@3)>*rL*uN|J3DGFPX@b9}kC#B{NEv}8D`3ODNy z@+wyv+k~_IS;hnp3x;K0@CX)Tjeg2y6?>-?J(YpQQ`e(;-H%N6QeU!+aX;>IvmiuySDXsrhS-@;y z^tG%QZ^}+@!$^;x<(|=e^Elud$$OC;-f~l0%O4u|GYkVt6=x343axR zmzUVN8A7k}>xOR|*JVuXMqQm!G-YO)FV)or%)aBgy3%&mRASK>wx!X#2lE{)-OefS zmgl-SGN@8mz+B&{lAIz2r=yHcaWoFCurP(P_aCVu=}d+0-y*{BUh6PjuM7P?SiW-S zr)v0+ALPnKs_!Q%!%R_wjRC~hO4InOGKMH2Kej9Pm5p3@!}HQ|vf zHj_`~6b^*0IC-I{y)*TbQF!ltei4L|s)qGpO7=lZSP@ql_XJM1as;7`_vg>3pE7bU z1{4?+p}aDdNxbZJ={v_cwK23l2~oxI6=o|zIE0=IsI8=KGEt$ojr`RW1xah(7t`S{ z8Er4|4i-bA_Pok*cEI#{b+ZyX^|^Ov zE-WyU0*aZ&--S+V4(Av85m7Bh;cKhryvGY;5YMrgCgaWkC zV=hbT?AEp4Q{b0b0d8!aV?I7(p5<&-bm~+AzYVG4PXgRH6n)J z*1xJKoYBl96m%st6??YlDV?)%*XR{B_{va|G&s=<6B8>%uBIZ=Y@C4|TYEvWX1Hc7 zFbsL^VXPy!3>hTv2$hH3z4Kec+$UZSk+!GJkArI=EC{!nYQ6qs;o5rW?!`Y^TRRO4;vJmaU!#aFyH0b@+vyok75o91QPhx zjJ{YKX%^kRgby)Vr$zy#)&Q;5Ss>i08T{-^h1c9#WtYBj75G41N!^YZ6s&ysXD2}5 zqsp{DTmOMTin=}2@YYq-VUUkAyXI}iKvgWm_Mc+iC_NGpK(2N7ookIVBhBBxnzaC- zq>rwDRseR`u#+Q-zq%1WgKsVRRs$fN9y7wrLF>A&Vu&DDlxK$JKmP2H3bavddcTn% z2=wORpDq-aIL+9mGo6u2hGb`FFR!jXB94>W1HSfj9^dg6rS`xB_O0reVR16S3-$nr z@CDe2>Mvtx-0|Q<0*;r7^gwzRuv??=f6$X<*k61U zc)mmRakD99Bwe4|^%@`{caDV@lY$A{*xg?*R3`@Bv1%2or14k{0vFZpCE$08EYR7R(xFvNHXu-d!8$-KGEqU3fh{8DwShJ}r9b@aM6k=V`E-DmJUiQ>FwI zJ&u(ARd*lv)~am_S^uLtJ$5zmM&oLA@w1;rN&nGQ@vy`2@Y2;jcked6R`Kxmx6IJ~ z{{FhU_nwvaT><*ES}{2;en8Dvt`riO~9Zu+9;XcFvL$D6W`D?#Fm!L&omcRR62U}vw|GD`e q^7U`tv;O~L0CoOjF#L}R5`=VWs*D45HK_kkCPT3J@Xm5<~v^yFeSiPX1qml-=j^@LUT3eh?sYF->glMRr(>a`p`kgi zp?=?hhUN?d4b3lnzn`XlQX+xhqQ3p+byoxUJM{?q-R1@L{HnK#k+-3nowuKrr!9@W ztDB3hke9Wmt*xtEjxW#P;F4vJhCW;`hH(n4G|Va6rD2g&U{5&MVPFHj;|VYtTSJEu=r_!oLGy0 zw!f5~AliE6m#;%UdHFJb$iMdUjD|+=Ok~8rPr3CKe*1YQs{fyzWDcchKvmV9-{i++dYh&x&HG@G#Yt9{f!srUWDerj8CNs(mj*0|NtjM<(k1x9->7&3^sbaz9U( z`Xi`1k$>{ODg1R@Z=fbGQzG!|S}@m%dRebAkMv6}=0l1e&iZvKhrPVPeZ0XlH2z6S ziwR2Yb>C)!;kSww^El%HE?GtoEj!Xa|CJ``SAXX3(**Zt&CvgtG7ZfePb2F6Y25Xb ztAx$=?fPW@ z|A!4^sjm8z3d8_bnwYQ{%ce0B>#{SP-H=%mMbP^*zfrlq{!Mq^3H+~mb*TgK z-*&wL%@zOZ2S}@O>UMc}&AwAIQPs zR>*(`4nICmHZ`n8L*&VKI&8%0nnl+{=O}oKhJgGuX}4B(f&q1S7^-T0lcu9eWJJe1 z54OXNHqQO59wBWOU z8yVxzKL4?u8PH^82)p)|*v&Ojnxbn%K5%vJ8G7qQ>eFY&_)}rPe>WvlD}T2}|Jz=e zw?0EZr2xc$6hn{9sGFEa#IFxqB-6BG+GeYpjpXLcX_&*mOY8y`&c{K2`qWN9Lv=IF z>t~)dW@Fa{c{YWgL{SC%by_c&|GVD&r?mvz^xW&&nyYmkv!XG&gI`}JVj#8tTXtjF zf=vH$N66bN)-&{v;4-mX8dQZDlzGyzLVyd1w+gld&;7UM|7Swx4rcbFS+Ekl;t(2Y z8GiTr*B#DGnAz`lt(X7H_IB=`2b&s<@wruz2Tjs2TmWJdJ*{N&XwLj$#g7fq{l!1s z^8Ulh7vJ9y{r%Ug)cKxzL+5D@d3pcF|MlED@%-K3cgOyR)}Gw$4S=NzRDP*!OFP`7 z%`;WU*!M=ZnTxwOA2JWFE`$E9{}k8pLpE2fT$xAT9H2MS5i{4_Pg_-?R0ENGYqx2p zOmD3qdsl?r;y+8|d6raGZW8imW50V#lW3|IfH9!M&&>?f$K9=4eOy(0XZOj>G@a9} zw2{%#DEa98dlN09QddFqQmAJ7j$&s1EL zU?^o%JwyQV>(k4HMl0c-o}L|2KF@Jmo6pd>_iq%oJ}i1_sV|lWCg{A^ktM*POMmw7 z&c+fJ|Gem^JFa3#$tkJ#zWdVKIDA7G~R86jzTn!AZrgb}R z05GD-U54Ia&U}#Jx%ANT%`xSeKj{mD`Qgz0fUVo1+T4k+JC@koT(wwsi0L5(e~g0V zmI+QfK963^K0SaM?>U?Bk0LTO1=2)NeRT7?tZe9b9NZm1*Lu$fogcOy{bw;yuJBRI z(A3$&ysVE~pOg7kkYEC5&>C+E>sKA1aaZEwm@)fvwQO@ucPW|;zKkDnv5e8w(RVjh zo;N4%uXDO^boyNtKqk#q7;c)d(;g~TILXFvPJ(NIL$_fDD*i1}i`tOYskz)Mkggm6{sy2#>Qmf%!um#*x~v=S6B9DX4yR~1_SOIrF~`ORs)9j|&{(V5ynuels2h5I zgr&R$kcCCcXDU`n8WfrsXOuBUMTZvZL}EO>x|a#1}ses#_i2e z?vkd9I;{*z23q>4Y@H8~5039auj)emK(2Az`Jj@-@`6d?ZdgKisRv|r4PR~nCLQmE z5(7NdMx9_V)7qW6mzmyB0;e12d7ucK7`urcFs+4<6WPhzQ-!el-Nyx!no3xV-zk1e zP&1h%?c`~AYESv_RZvZE(Gv&GbM^{AoEg}VM{4BhzOFp9I{uj@77aANKry~=4vJ!; zt;9fcQFaY^+n+W{mruf0>XCj4_bXlaGh;-yjri4scAFXc+2sJrhZSzyqAt_0LU!NcX$<=n$l z*%PxR+2dNo%I{b?zaL6*Xe-jVS+n)&ni@W{HAe~;oTy%CF(E;#rMfKLi3^+RtcZ>t z^zF>8!f8(`jooTbQP>|a>v`|sGNh2=BBN;8=iFsp-Iykb^S57n zo0>E~0q#@3>gBRN-dif4b|zG0d248WoC}wb*gGPHBgZ@0bF5y`5@&5Y<|rxF?vYY- z_a288h%%4X6-swLk2SB7xc1%Kocf^Isj#h}EA2KBEg$VRSUn21pESUm0igX#lh44`9+4|6Fyd*%9QYYqrM03)x3X z>dU<7J-U}M<9p_smq96umYVR?rL|R*X-|(uPo4laF>|$*ADxKH6VJz)L7B3e9p&$Zhf(lIpP;!*(?cF4J1$T^U|L~t-VID>;mt1(%Y*V>VuOA*D7!1vK9lPXD$kI&%`~POj_97)MTv&a(^{_eVrkp24$j z_PuOrkhh5}*(S3}=bh(=K@F|c2aN)3{16oK!-2-rN$@8SL)jV<<14CP2J8(w+>k^h z$X`v%klU|($?d2x;LhFN4ye0EEGRS1-!Zbfvh>i3*xcQ(nf1cDHg7SfXId~l-IMo` z*PIMu`{2;Wl=i1TLv`LRY((aia%+XNvJ;hG?>*cfDD2@xY!OBrj&fY(KU4z^G_8F` zpY9gd*KfATS9pPZB4qbs5F_Iy2cvO2%Pt!2J}wXz=%ALTGk+vK$M(&tHKcjRVtM?> zvr(D$wjCCq-;89g{p)g!$fHWGCkaaH777YS6Gr-y@kQs&w^#v%x*gn$HJnO$HiehV zD-6qu9UEbJdLhF^Vw<&XB>*}QMJO;-qp*Orsu*^oGpvVq&2%VzG7I;uV|a|!TB>#b zG8q`mTzh$iU#|Y0jxqd^c0(I}Bn%CelI9?8mE5QMcOW4+)S0T#frs^lRvmDcQB93VgIF`akm0vpo=g4X zi(!*B39-5Au!?FVP0BJ{yz!2i#}r+|LXt!V(RZkbqbg(CIce8A_Zs|Acm|7RwguF-#4NC)bdB1E8DfQr0vD4K>P+>8i+m>PX z&B*$hv-WEaL4v$0t z*~xV*f)7L&t}dh}<`!}Bv#|+MWVwJ-RRfz8xuZTCnGc`u2e1Lo@xn-afr6!@Eoj1W z-+D&nvpc4%PsoOPk6WaNH zf0i8e!oGpoh138OPvvvCHISwCGFL~X##__X3x8L(_tki+ld?hEI@D65rX{T9-s(V8 zXO+j5?pB#4HBLMTp<*zGiam+9zGEj;@q-LHdm)LLM58tdbX#^+woq}tXl<{lKWf^sQDx zVHp4v>A7hO7jIk|($Ti)083>dR8Li~YM;l^@`SEyZN=>tpO>{#aYYqr$`%3{(WB6% zCIPMGA*an`{flXKxU19%d-2AmYlFoQHSFinxO0K;_g`yDFjNpIq=EFHXWF8C{JF`{ zukert%%hMz&3vSpCJU{L)M2P&;)MRzyO3fhLjJFCb6qAZAFmYnqaziRv~2G(MYA6n z-LM4vA40~1%?xWUw|9)PFw||D2Fu1E>i6SnKzX)&M>S=U%i zU{HW>#Y&!=tKwWH+uR|ukWz*N232+R$3Y%?`m)s7Jv}JEE)X25EM&!U`}iTiB1__I zX5v^0CTK=NU0~VB0E6O#2V++6W_J1m z=SOx6+KY^-erQpJ53VM7d@OX=w_v<~d0AC6b)1)%A`|3d-{j=Rxtc81uD(3K-`^A2 zsnFmz?(9~QR*`4ReN`Yuj5VCyYq|IAmTSpQU6O8R#<&nJUV}wT9PHUuB;rizR;a78 z9!wZ4?-JTt`3$!wcU2U}gl!pX;3`XPOO%7GCX^an#bLwMJC8;-!)q$6t{RWdPcPfg zA5{q9#2P}{I}3(uD(o#nyY(P{&dN-#1bZ8s0Vld_#7_Y7lI7Hfh6ck)uieI^o_gl2 zmDD_&L0xTCw=Nt-y0cqo;8wWg9hvNAp_6~0rE%VzSi!9KIQ zKyPcU<(^lt(|D1wcp1zt*sE*6L@wsy0J%WR6eiLCkJ?EjNFt=Vj^(90bD7)9=9ejFN*UKum_;~Jmq%G|N_54i#JG6P_I6y_do1_p zBwEOm!clBIqN;S=Qi^x-N{jN^i`>!zMLHweLbgYQwjRxY@n&0gy6LFBbvz$i<8hpl za(KleRXz<7Ut!D99jw%5Sr+zKuXNw z#hz0fUYY|Zc7l%`cBdT|GO}JiR`Qp|2Z|x(_NQI*oC3Kj#;|@9Sl2nsCo|ArjfJAf zpnd0UBo?~X=nawHcK)areKw**@&{B)U;HjJg60X)y_!7jI5T3{gWGUZfs=ocDH6Zw$gGJPEL`5$SBg*Yl~_Rx`Pqr%(xS-vCPZ-(wr zvwN=@FL%l1Is8E1Er+P!D~5>9R1Phn>Ms?6e*Gx5tDtq($y{~JtXE%`i4R8L_ z4?Iaab~ityI`+SLM0k|sd;{RDulVt0IUrTL!Ec38m$Vt!W3z9`H1?a_&tkrz*P_7( zf;ug7hQPb-p64M71#hK(QK|{_ZBQR$c5sl;j0zXSl8|rwh;xpa+=-J2p2HYrC6Y zv+|XDqN|gpOQkL-Pm*Wpr*Y8{_rhVf>I+hdW@FQWaj$u>`ywi)sdA!%8RRl-L!gDG0E$0A6;f%rMq7KUHpeCAZb#qki!UU?I-NLdij?97m0shlLotH0ODhj%3bT^PE9Eeo0- z;})sNBbd;R0q#hB`SVh6KzjdSQ+njH4ZRGg<35Ke%3G%;65DieX;lAJ!2%$yk_sZq z?!llL*{z4@^!s;*p`n$B)fk=7oM_X5jXm`&aeP?MIAWBJ$=3-$V$XLr^(E-z$AF=N z{3~cMp+kecbr$9GsC`)7s_Hs6S>7Q@<`WmBNYEj0L}e8-U6A-1w<*`=doTL=k|eb) z3>r!8T?MwIl`G!hk|E${l=LpLSd|h}bXNsV+W}W?j%Bfh3_CtJBin9>W9?=nQfm$gA6 zK+fPJ2xBntp$jV5UTS|T>RHKtf)qS*uZJVcWwcDH7ikER^#r1-K)Nvuk0`75a3+BA ziU0_OG1uj1`GN+A5_N4&hpn{MBop=PiVh|@o$B$$nhj_(lgPLD5g|+En&9v|$6SH& z=SfLg`}s+IyN4wQecpRSBsSG_VD*lPDIA^ZujcFh#cwC9w&~u^C`qfd?PK9)uw{eA zI;&7(#+qq+9WM#wq^w_RnB+&ERP*omr4Ip!I>YCVwnbEyM>m&1r2fj*uvnAg(fv}^ zPhe?1mw33J{bH748nkriX;u`?SMFHWl)Qyci#?1&UxK`m-M$kYm# z*C(0}gFs}N96!3CcBbr^&T!ElGR#e(^b3oR-WlM5a$?VsmI-<<^4j&SL={-YbhcK3wfaX;qz3DTCOqL!l0J*7;W4V*FRA zvU064V|lN_zuHvPRG!=^Au;N^)!mVT5aG0tFb#iJv-^3+nc0mqB_l6de5k8GH%z3n z_@4ec zZQxS;`gfg%Iwz(pY9OKr8}T~b&JBURwP7KgWBaFfUnWu-oSanKUA8`dI-ezm=dHWR zf3td%@iCr5dDdh=CJx!$m`Pnjii~PySg+pEYL6o1S`pG?k zQs>307Aj6EDL*Ol9VfL*!M%KYbWoPz2tT|%?rUqO(WR2^sWpC04-*tLe=qO7@0<)w zHT&(>$3*@WEg&EJBjQQBvs> z*QZ@6eN`1Ka#lWVxCXsMs-W#XH}J>AdqUD22Y&i&Ym#>dfJ51e5TAgsA%QX-ojTeJ zY#sA@zqtR!&&0}3d&gAb(!HPfs39VQT>yC*6e4PHqyx#&-2EuUf*kiRX-~x%DD^o= z%I%66l*|EgA#`#JWuI=iFGkn7&{FyWP~w5dnq}jWnyh_!lVHCPSwcPUdeBV|Etu*Z zNb}1?p+G_xcTKq_Jm<2lu*L`Z@P2p-pGu(`h<(nhW5jQiPZ{6W>nW>MS<2{E`fOZlT?aaMH!79IRuLVF@H|2xF zvnuqbjlz7jNkL#o`Rw~QvhU9XQr+d_-qi(rwpNekr_V3(!@Dxg*2LlP<$1VPr~|4> z_hP=; zAZjn?X#jiMbG$)F3Q&$ll8m!^P=R)W6z4}M*#(Mv^!Ght76$z%{8 z;|#s6f1a5XC78)nyJE!LXZruv{OF9xiG>eBZxhh2thKWajL+fK1Ob;UXCH z?(I!X?l?VG%2w@dIz>!8%>H$HuWfGwr@|7)8(;}chii5zUr&1Ls&>y7eNcRYm zP(nrhPrUSu8#U)9G(PySsqSXj^ZE(=uFq??Sy4}WvP@L#8I`8a*tH4(A@i~p0FwZj z-z1QfZmE$+?@uW5r-DDb1opB&)IEC`-|EH0O;PY{-jHdH@DThoRH>`M#h-5wHBy*Z z#_f2p@fN}@q>1Q#oO+6R?!ls{w2owEooE!c;~-8!X`DG!DQkd|L>g}?u#Q#=jmA9t zyVp+5#qR_to{$D?Yd#t?VT714u-5GT!`tkQs6n?zqzoHI*&!Y8?Kl9+?d=co)FOw) z)~DRfE$;SzE*qSz$PwBURB<+@A55s^R>9%+>2-r|OvFE1yPfbrCEuEP_rWaXVi`X!)r;Gn^HNfuEXQB4_vNFkD_v!Og6jw&} zR1U&uZ-M+?2sD^gX!4muTtY=w9tS=Fb?F4kO5FC4^QDoQplf=12`$ z_E2cw$AmztG!i#k(ghm~s>ZWYiZ7ivg_citmdEa!?~oG+%v(5|O1C&(#)u-r(FMR7%c^!lJq~WR~AAOWX%u z*l^KgQe>j$)iMg?ylVW$T+oMgiBuzE@wpZsn+5^*ZB=52M?H{W9Of{5J=I~Vr-~Cb zdu9Y;;JRVmp)N;|tCYM76}3#0N1QTkG7GsX7DJd{Z(m8cv)_05?pZ!)4wU@9b6G< zdw5udKd8k5Ymf#&FU`ALh2KBaBgnT|1ZJIDM{KeX0RUNkm0bKt7ve~&+o8=Zoo~dJ z3Qem(n$f({E=~%ciO#!{#-j!e^Bhd)nL{Ile&4vEoVE47&d{n6tA{X?CU*&c=XX9y zPGO=tc%5bEcoN!^AKdhs51CLL5kuJAa&3^2+uh!;rMhS2_V(Qf>?&K}Drth<%f+eR zW{{eeinc9I>1;&|H*CGD5Ar)07wKvq*T&fy->gB1u?~?t<*lRrDV<}ZLdiQ+__U*_ zn7MPUp>V!fYRkr~uTs%ke2ulMqJQv*qv_aTb?P1MI@fZmTI=y{m4a6>?mhLHF&`D`DjWsdZG1Tz zLRZJnZhabzcx>ak z${6eUssbUFHagVRP>4%e2+jDX@6E`=-gp@QMJvK%f4M<_~E-LkQv z#uqq!YGf}FEabIPvDIGJhL4yR?oj!WO_|a=p%e-~EV)SKYdTI_7#a!XA_Nu+@tfqk zv`m+i!}F#6WZwP{4SaWJ-+6YQxxe>7eR9^ zABY|TsZ+6&amW=vnIs*)#`$IP9Aaq)Ybx`daTjadb8qS%H6N`OtXOSspj7l;zz!a% zN;jfi5olmnl})IU5<5+!vjCivmLnVj4f8?3s+o7}z4`yD1fX}EUB=xO6{?!Pla-a2 zB^aJElx{(Pd%9-nXG;zy0w5sNEv9I%%{3n)IZCsIor^~BUxj^OiiydciXs!`{V%Mq zkd}ruEPTOTkTk;eZ^q_PYv;WwYXg7(uGo6Jv8Oa|Z2vMSl>!dzzpY9diF`mY<1+E} z#b<{MPzl1{zHz%R^1mag?Ek^}Ji%P4zF$Ct#aDJ{4O^OtFqLBZH$L{Go_|()(HFVm z|LJRzm^uuB_vGM)fE~@RER@9j|GeWjhIi44PW%UlH#xsL?mI!-(?8ztDek8lUHGS5 z*KZu#bEi+OuCHVC_};P8Jz+}dAkENQ@l(@2f8+3eV}#q2zS3F|R(!Fu>ae$>(NgqN z;&q;+$Y`-KHLd9SvqhJGV)muZ{NJQ|^7>CpMo?4+=jl7wsEqa#?rq63AYT2121Dgu zSM&XZu}|m>KX3hJ_@5S_XiT=Szwt+cF#$&hHB`uYhMx9Kq~onLmbf;Lh*EDVlJ++a zzkt31+qu)!tmap?KgqME`ks*{bp-#W9E%`?zAG+uEdN=$fPx!UdJi8^x#0nyr|wXv zk~GK}dXTMryw`I=L;sV?2tWVx5v1m%zpFts*DSfFQ%O0umUK#;Ciu2ZPx9&l3VH?x2=(D&E$DS{kYOv4i*`CGQ*ruH z^H2otzG4k#e`iarE6L5}8h>K`%M-VM7t^@jEcma=_McT&8k5CxPcRqSN`odXeXh{B zzT(#K4hkv?B(D|AB|1@6=>O{THySetmE`{ElX{*e%@?O1O9qZ|{Kus+82TxIjd4Lj z!X+0Mmtr|a8tLfeS`7WP$&K}2znJ`hs4;Mf)@0Bb594pWNk4?pOr`z1R3+`@|Lia* zIKwF1Oos&ZBgWH&o>C;5o65=q1HE^O3*kAQvTE?{vsFW}HVdAfPQ%1ARnSn3SrTe( zJ`u-N0bwUV28$8!4kkuFF#8`T%SJ=ZbfU~1;WEimYWnfQckT#^A7 zTx%O0^qpE-4*`5@JvG1QN~C7xJ{P+S2>Adov5$5FR)bfi&1#6ZyU}6Bf2ir>avg|P z-&)gHHpN`=PcA@3i(%+z*PXVR=1(86;NdbJ#b5APGvTTw(GvE}waH<<@$$kAbn}}S zmG6ZKM#Zf93iV)B#fs(lgRzBAR(MU`9;4^Y z1iWZlSW)5%(h)Aa`&Va$7@P>~CfQ_F9rSFcZLX%TAdBya=u5eS1V5IoK4X&xRuKD# zVWUWPLiaEo3}0r)SLM**>$LynPfT`M9{RmNs6(OAE+hDoZS%0UZYKLYI&%j;$mOqd zr;<7p1gY(O{#khmy%8i|a%Be2g^A5?u@-W5q2_rC49bT!12%Q@lTo*vO`8SvdH666 zx^bnsS{rW z!K3;QW=^BIQ-o73lxzo_FqiiLS;JL(V-l&Y>(Z2^DknN~HClPzI=w_zU}BJw|0}zP z0!adx%59JEdlk8FZ5od!kKt()-SHz^!NU#Uafa#USYuDSPxAu}snq#ijVxn}L3{d( zwEcMK$8{u!zh}YW?a~ziS6`7JXSLN&vmT2Bi~)s*62VWmQUGS7#e$wJ$&`&_tFh8vRg#|nraWVkj11U5Bqnuz zG2-xnuO5iYk>7EE@p2&a@JmBI(r5lzy3i;>as~A-6(}FD0gk4W71t^o?0>0z3ze(U z`_vLSn4eId-wkuZj^`CmCPFSmWF4>YjAkB;I`Pq^v4s0n^q2Jcn&S-=4>&FLoo+%k z`b5VeW}MUv5eWOd-*Nf*5>Uav>e5bR_Acv76ODUPli4^_P`2un{!SVhw^{6AH|QzBrT%; z^`&;a(}n^fruA$W8AFITqRRw=a{%7em_Mm^<(4ELqPoAmCc{Dmz^^Bh8ngIT@xZ!&q5e`FbWsN8@@lB4 z!1bK=wTrolcloJ#P>k1&Vm0)^`f=`j)2Y=W4T9V9QPWfU5h;KBp+<)iR$t(T!gxrs zrUht+TfYz4E@GoOPkBHoU%l^9jm?A@!hCni#(_rfx3}B$JeD72p-)m)gRjg%Ku-QK zH-7C==x>!}3&#dP6o8H_b#9laY3P$0PuEbmFNWqn#K{dWv?ddoep6oZ@Z-kz>Gh34 zR%}KX?ymYpuw)(S@KH9|7xPAYAGr8^1QiO9whR#6OgC|{eahUtzXL5UFJIH2)9t=4 zjmD%X7~;hCV!4%1Z(^brnqD&rAa{V#P^csaa%ptw_`pqN`sh*UnXkI{#4W7}?(gH* zYy?O#6`AM~^0%jVg+~L$tLP_mEd!l6oJ~|=#*JHj^~!bo6lObVk=zPJFPY%QuEX{m+aztPOcZYN5dYsrinOFXVckZWLZbQGG7|m_%GA4z!V|XGvCUBMC%{Nm!jzmeC zZ|bfb9;tD&=$1NKYA&S~sA5IC^C!lnSrMHh#bM#MCKN`bOh*IfhewBvsAT#&oIKQG z!dx0=TglNNRh?N`S$Ph%X}Z}uHkmv(Sdn3GcN5bfFIuH3URK$;2w59XaG^$fX$%v> z<=bn+-EYg98>G14)a23FZV~&|qy3$u!}iKjZo?6IQHh48#a$lU28zwAq-wqiVN30f z;?_N%K%OUM)C6rl8Zt^9pTtoRLn&;#M;}(;HYWjb-Rt&R`?%(mkcE}VEcmigYu(;M zVU4t^`Ci|Ufb_|%(_*U_#CEC3dNRzWD8v5j-eXk1%mR65Tmom^uD(};-))esmf9Oz zXUoLz62>O~im!08NcTT(u@17gSeY+89CMze?Dp<*D-{RJ^jJ*rUv;!DP!0@r?s2U<0Imub#Y4Dl!P7))#bo>ce|bbNio*> zDBT6Gf4c(l5s;gPm_w6UDa&l>zK5bRThcJreZZoTV_=9*_4yX2_2wtE8ZdLjvQeM= zt0r&0JF?Lgjxq2`If?$4F@5(}tx=4voAxYw5Bx1XWTaht|6r^|4Cuml7Y50XS|pmU zs%j=w#)1%>)MV4j@$Jof{{D+qI`*z~Qd+Kz9T|!=n|Ce!GmxW;I;zSaGtsNDeZJZg zDL!hs@oa7J`K6~D_O4;YyHygN=B5OAHA@iSh&~;|cnL}^6A+X(u3wWWACrO7dWr!V z7-g`=nE%drhR1OXR7k04<%lh5A-2-cT(UX&zW|AqhA|+63$%bvm&S|5mL+>3rp0SU z2xbA{tS;Wl`ol_k21BWN&l*x2UB<8--5tIj*wLqg1T%XI`aWwPC%e?B{Z{Yo)x6wG z9S~b3RL1P18eyv3(rjqaty|W!Y$~PL`dFf4*G@|QZ4aYl({a!+O!7+5;J~=QvVnUg z>KRudU;8Fw7u!8kofe*0_F+S;>$415AokQ{@_SOq4-3EM~a^_M*=#k-Z`Y~l170Yw}blC7&AFzH) zc#UeIA>47>W8}3b@*_@C=TdNeiM&A-vA1-PsTD75C|}M7A%&lgOgM|0eLBDFsnV8` zcEjhDg&W^u1xHAu&GGSaWr$Mzz`A1zzpSnOb&fitL@vjV%3k&RC>Hp`edqV-R8s6o z>BA@G;|2Se{1()1iA?uZl2L_&`Th>CzmD-8GZ5DzA0@$FnTcJ^D=DF{e?cgYedu0p z?}zE>X>@b7Zw{XUqYBjp3qo+YiJ{s(c%@mlDVCU#UP!3uFn(E3Sg6j{ILQ&8gpx+k zkv3-}iQ#2IlL@Bj+S%nx+ek9gDr}qNPi;R(>()wwByrt8V|F3*pP-;YHS=A3Xg=<)JR3O%-n5s9EGjq zM27DT@jAr{|5YTyIQt5Fqz9XQZ!Dv2zULaUyK2FwtPDozxFPj*9p&_z&d&KiRS10L zD%U`={Rm2pfs>oP+yH>*QlML#`>PvdPXay%YOYZy|I(2^(BCpRz^prPl$q*le_hg| zLBH?*cy4Yk@w6C=PNZ4Bxgr#dV4NwSBeg`KnMa=Fitd6GHHlCLDma?2kIoAgbQuF3 z6y}~4ex+x0F+#CnO4g+MA#`-hi9w1bhR5k%poY2rMtuXIJI0Rhy|AG1knsD;f>q7F z*To-?@94%2l~+_@xxGp0cx;`>v1Oy+_z1D3rdr`a?b2y&DHuYoIAWi)cuxbNnHCR? zc@CIZ;SEli5eB#U93MRRQn%#0pr&srO*`BXX;9b_8x?(xa)ax9gmrNJA2x%JboM(3 z)e>e5rzJ*=@m)O9D4BS`9c?vbUZ^dIXoi~9NsQHs6ll6T>9e*gT-N7aX5L{jNLDX9 z3owGIHiy3*C>-SkIPnJTFMsKD@{f62FcbC8m$rRBK|5N9+*mzVJpy2)OXY88QlQPu zUl@k0sTfqK``rJk2EW%uDY%3EOI zF?JgH9RrnwZY}^`h1zmb3#-2_#W&af^2*!oUmxBfy-7M|x}|^4nwDre;8;P#0)Y=q zmkz8PahF4LKKT5iCHz4r@;R3VEt8TzvHIF*WnSrA_0xkr<4@g_pSN!ujoG&M>Lo0% zC!Fm#%*!4uEe|Oy*0J_Y9nwGc5_Sx6Oz#-=%uR(MZ#p6^q(LK4bZ-!vGYp@YkCsVt zKXk3+TTOLz!0e_q;DVbaRd5`!PX-Y{bXmq`ttSO2b}J`IV3e(Vl5X@`05PA zHf!zJ!GBVo4Z1rgL|{-fR`w-!aaRrLLrRwV(|`(-@FjL1wbFDQw6dV?)8m(1_DM{@ zG&(fwd9Y6%YDD8+*Mc(tr}Mof&4SI zjK8+rv6yw$%4pKd$SbDa&*L$QE}7f0er`C}K=<&-sEiG+ENgDA?^<&WRajo%Zpzq&KED%xs!dMGbD3ATHrx1Z%K$TfTLA*^Xi!m|UF!=~0(jV)@dmR#P&zv_}8 zB-k&+1T?fPl+o8}rfN$qc=o&+G7Y*s^-4M=r%XZKrGOpCRIJrlVXBEkn52|nZL3|G z+NCWFwo^8&UN69SdAo7EaU6E7I`a5-IJmzRimx_Vyt`@UHE)`|Ejpx5ABaQT>mS%xjK%}%y zOehF9kr`Z)t-3TAM6Hs7j&}eroTZ!5bDAxYTdg$7xI{WM%JxFN;nk6YR@#Y(#FZgT zusrZE24=n<`;Mr4a7pk8(kVpx%xdJ=qdOtiN1kLOV~lLo(O26?BArR_V4$@Z4dBI_~9-^Do+>6PBp15wiv~!wM^~HATQ-TVFsJy2jBCmM;Nrw!$ZaAf@B^OxS zU23yOSHQJM*OEiWg2~#kQ+pCq3%!YLd{{^8|CCp&ZHe1!l#|M(a2c(&5)i z=qngm)T2G_v|rdySm3BkTe2~bJvWyw%zA!c*>))yX+S>^*#SUU`*hbCw*o%h2=n@; z$?g*4FC4XIWf1EW4E;UV3KUfSLt~ce=4mF-4P6y&;dvhAg!!WCEbMjIul{3u+O}QBaX;kG~e$B$}wczEL%Cq!)-ZfCX=3`y$2(N@Y!$Y za-7cG_sDxAL>N>LE6U}Tg=tm+&tqp2n$SENIkU6Y<8^*+#B4JGBGiX?{orM(jY~T_ za84~Akd1lk@Ja_)QrLzVTpwV}3Q=rOw^}UasB(%-t3*>LX9Fd&F2So3kBbF_vW&LO zbby9t>q{H`>PN_&k0Ko$zC@_64aJn8+}J4*zz#~KK=+gvJw7>JXxn5*O}g;=ADQe@ zi?prn=h=CBz!IN{nAXjx%IC&8shY10(9)$v zYsHvTD6syNdYGhsuA$y*!@mBkg&uj`Y|Fl8aL(?_;%hPz;Z>{rpYs+pa`0>|_6u`s zK+@4?vytFzD}lt~oP!VW!)?@Ew^uUsBqkR}Ng(2;W@eUyOX2@%=S+i|x}rFqf!1{j zYO9q+rwUX@KuSW`WOOVw2nbXxTf(N0Ab}W`gb+{yW-w(WsbX0}uvHd;1P}}$OM-(? z5h4{NlmrqG6Uvq#0RjY)J|<%8w@#aT23Ywy`nYZ_MgaCL|7@a3Ix1 z!_a2>G|Ccd&;?%UD;*k24i8qJY?h8OvVijjihwUGt5eUSM?^Y~{NLf|)WlXOzCmC5ZgP|`% zyZ!s+%d&N6h-NQIGnFwU6y?3qF~{<4>v@a_Y)^A8;hZbjNGZPRuZ+R+&YIN`5?7xa z#gp2>wFx~pAzkz9Lfv>0A-=%N5-1|UEEQdiR;&%A%WX3lY(XD9rFIyOSWT8l7LmQguNltO4{r<3pFib9z-fF+ z1>!l~&B|-$zTOS^(*+Z}vJ$P%8BAcgjm?=)H5}VxCFn33J3N8&^9Ckq1}Ste>UkP1L7& z&=CBul9_i+Ldb4s(h#?{1hMHEDJx+fC%n+}lf~Mpxkd*FgYuC1o}QkM*lhOHx4xC1 zRxXQs@o_H~-IE<>l0qPdN9hwynXT|r;jCMh(+|e;9URjLC4HU?vuMph5By>%n4VuM zdhqi5j-MK;nSnlKh*#j2Z(Yi%NUNLL=C{fDse#+Q&ZjsTMWBE4 zYp`2hNGhAT7dUuv;ZSO?)ShNqE|yo@(6ELM?~oL2P@D28f`;U;cj`SMuoEX|1-Fg&(@f| z6$2H)+!R)Od%F)sXY@v-jiI3)1&G8189*7sD>U2JczY`SPum^BG6V3taG^xPn< zr-IyQAy(pXxMCX*GuIMtSK4?F6Jo5lxVkuM*|#wRA)*S(k&pAp;#ZtNj=%JeSBg`Grfv|EZW+RrN#dgbY(l33&3%= 16.04 -MacOS X >= 10.15.4 +This readme briefly describes the functionality of our LLVM toolchain and how to build it + +1. [Build WIKI](#build_wiki) +2. [Function Introduction](#function_introduction) + + +## Build WIKI +
+ +### System Requirements for Toolchain BUild + +Ubuntu >= 16.04 +MacOS X >= 10.15.4 + +
+ +### Get Code +``` +repo init -u https://gitee.com/OpenHarmony/manifest.git -b add_llvm_toolchain-dev (not ready yet) +repo sync -c +repo forall -c 'git lfs pull' +cp -r toolchain/llvm-project/llvm-build toolchain +# get prebuilts +./toolchain/llvm-project/llvm-build/env_prepare.sh +``` +
### Toolchain build process Here is an example of starting build process on Linux or MacOS: ``` +./env_prepare.sh python3 ./build.py ``` -### Output artifacts +1. env_prepare (one time only) +![输入图片说明](../data/one_time_setup.png) + +2. build +![输入图片说明](../data/llvm_build.png) + +
+ +### Options + +build.py options: + +``` +--skip-build # skip compile and goto package step +--skip-package # do compile without package step +--enable-assertions # enable assertion when compiling +--build-name # specify release package name +--debug # build debug version llvm toolchain +--no-build-arm # skip triplet arm +--no-build-aarch64 # skip triplet arm64 +--no-build-x86_64 # skip triplet x86_64 +--no-lto # disable LTO optimization when build toolchain +--build-instrumented # enable instrument pgo when build toolchain +--xunit-xml-output # specify LLVM unit test XML report path +--no-build # optional, skip some targets + windows + libs + lldb-mi + lldb-server + linux + check-api +``` +
+ +### Output Layout When build successfully completed. following artifacts will be available in `out` directory -`sysroot` -> sysroots for OHOS targets -`install` -> toolchain build -`*.tar.bz2` -> archived versions of toolchain and sysroots \ No newline at end of file +`sysroot` -> sysroots for OHOS targets +`install` -> toolchain build +`*.tar.bz2` -> archived versions of toolchain and sysroots +
+ +### OHOS Archive + +1. llvm +``` +Materials: +1. toolchain which provides clang compiler, lldb(-mi), clang-tidy etc. tools +2. libc++/clang_rt/asan/fuzzer libs for target device +Path: prebuilts/clang/ohos/${platform}/llvm +OHOS URL: https://mirrors.huaweicloud.com/openharmony/compiler/clang/ +Self Build: clang-dev-${platform}-${arch}.tar.bz2 +``` + +2. libcxx-ndk +``` +Materials: provide libc++ for ndk in target device +Path: prebuilts/clang/ohos/linux-x86_64/libcxx-ndk +OHOS URL: https://mirrors.huaweicloud.com/openharmony/compiler/clang/ +Self Build: libcxx-ndk-${platform}-${arch}.tar.bz2 +``` + + +## Function Introduction +
+ +### Functionality + +The LLVM toolchain is built based on LLVM 12.0.1. It is used to provide capability of building ohos image. For detailed information about LLVM 10.0.1, please refer to [LLVM 12.0.1](https://lists.llvm.org/pipermail/llvm-announce/2021-July/000093.html). +
+ +### Specifically Included Triplets + +Despite all the components provided by LLVM community, we included several triplets for different types of ohos devices to our LLVM toochain, listed as below. For specification, liteos is a newly included OS name which indicate the simplified linux kernel. + +| Triplet Name | Architecture | System Kernel | System | +| ---------------------- | ------------ | ------------- | --------------- | +| arm-liteos-ohos | ARM 32bits | LiteOS | Small system | +| arm-linux-ohos | ARM 32bits | Linux | Small system | +| arm-linux-ohos | ARM 32bits | Linux | Standard system | +| aarch64-linux-ohos | ARM 64bits | Linux | Standard system | + +For detailed definition of Small System and Standard System, please refer to [System Types](https://gitee.com/openharmony/docs/blob/master/en/device-dev/Readme-EN.md). + diff --git a/llvm-build/pack-clang-reproducers.py b/llvm-build/pack-clang-reproducers.py deleted file mode 100755 index 52a58371f949..000000000000 --- a/llvm-build/pack-clang-reproducers.py +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env python -# Copyright (C) 2021 Huawei Device Co., Ltd. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# 2021.3.15 update prebuilts for OHOS LLVM. -# Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. - -import argparse -import datetime -import logging -import os -import subprocess -import tempfile - - -def logger(): - return logging.getLogger(__name__) - - -def execute(cmd, *args, **kwargs): - logger().info('execute:%s %s', - datetime.datetime.now().strftime("%H:%M:%S"), - subprocess.list2cmdline(cmd)) - subprocess.check_call(cmd, *args, **kwargs) - - -def pack(tmpdir, reproducers, output): - args = ['tar', '-cjC', tmpdir] + reproducers + ['-f', output] - execute(args) - - -def consider_temp_file(tmpdir, f, reproducers): - src_ext = ['.cpp', '.c', '.cxx', '.asm', '.inl', '.s'] - (name, ext) = os.path.splitext(f) - if ext.lower() in src_ext: - script_name = name + '.sh' - script_full_path = os.path.join(tmpdir, script_name) - if os.path.exists(script_full_path): - logger().info('added reproducer files %s and %s', script_name, f) - reproducers += [script_name, f] - - -def parse_args(): - parser = argparse.ArgumentParser() - - parser.add_argument( - '--output', - help='Output file name') - return parser.parse_args() - - -def main(): - logging.basicConfig(level=logging.DEBUG) - args = parse_args() - tmpdir = tempfile.gettempdir() - logger().info('scanning temp dir %s for clang crash reproducers', tmpdir) - - reproducers = [] - for f in os.listdir(tmpdir): - consider_temp_file(tmpdir, f, reproducers) - - if len(reproducers): - pack(tmpdir, reproducers, args.output) - - -if __name__ == '__main__': - main() diff --git a/llvm-build/toolchain_readme.md b/llvm-build/toolchain_readme.md deleted file mode 100644 index c1afff332057..000000000000 --- a/llvm-build/toolchain_readme.md +++ /dev/null @@ -1,28 +0,0 @@ -## Overview - -This readme briefly describes the functionality of our LLVM toolchain and what we have included specially to the LLVM toolchain. - -## Functionality - -The LLVM toolchain is built based on LLVM 10.0.1. It is used to provide capability of building ohos image. For detailed information about LLVM 10.0.1, please refer to [LLVM 10.0.1](https://lists.llvm.org/pipermail/llvm-announce/2020-August/000088.html). - - -## Specifically Included Triplets - -Despite all the components provided by LLVM community, we included several triplets for different types of ohos devices to our LLVM toochain, listed as below. For specification, liteos is a newly included OS name which indicate the simplified linux kernel. - -| Triplet Name | Architecture | System Kernel | System | -| ---------------------- | ------------ | ------------- | --------------- | -| arm-liteos-ohos | ARM 32bits | LiteOS | Small system | -| arm-linux-ohos | ARM 32bits | Linux | Small system | -| arm-linux-ohos | ARM 32bits | Linux | Standard system | -| aarch64-linux-ohos | ARM 64bits | Linux | Standard system | - -For detailed definition of Small System and Standard System, please refer to [System Types](https://gitee.com/openharmony/docs/blob/master/en/device-dev/Readme-EN.md). - -### Specify the triplet - -To build images for different types of platform, you can configure the triplet in the build scripts by setting "--target=xxx" using cflags, xxx should be replaced with a specific triplet name. - -### - diff --git a/llvm-build/update-prebuilts-ohos.py b/llvm-build/update-prebuilts-ohos.py deleted file mode 100755 index 7875537a96a6..000000000000 --- a/llvm-build/update-prebuilts-ohos.py +++ /dev/null @@ -1,261 +0,0 @@ -#!/usr/bin/env python -# Copyright (C) 2021 Huawei Device Co., Ltd. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# 2021.3.15 update prebuilts for OHOS LLVM. -# Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. - -"""Update the prebuilt clang from the build server.""" - -import argparse -import inspect -import logging -import os -import shutil -import subprocess -import sys - - -def this_dir(): - return os.path.realpath(os.path.dirname(__file__)) - - -def repo_root(*args): - return os.path.realpath(os.path.join(this_dir(), '../../', *args)) - - -def out_root(*args): - out_dir = os.environ.get('OUT_DIR', repo_root('out')) - return os.path.realpath(os.path.join(out_dir, *args)) - - -def logger(): - return logging.getLogger(__name__) - - -def check_call(cmd, *args, **kwargs): - logger().info('check_call: %s', subprocess.list2cmdline(cmd)) - subprocess.check_call(cmd, *args, **kwargs) - - -def unchecked_call(cmd, *args, **kwargs): - logger().info('unchecked_call: %s', subprocess.list2cmdline(cmd)) - return subprocess.call(cmd, *args, **kwargs) - - -class ArgParser(argparse.ArgumentParser): - def __init__(self): - super(ArgParser, self).__init__( - description=inspect.getdoc(sys.modules.get(__name__))) - - self.add_argument( - 'build', - metavar='BUILD', - help='Number for build toolchain') - - self.add_argument( - '-b', - '--bug', - help='Bug to be referenced in the submission message') - - self.add_argument( - '--hosts', - nargs='+', - help='Update chosen hosts. Choices: linux (necessary), windows, darwin') - - self.add_argument( - '--source-dir', - metavar='PATH', - help='Path to directory with tar archives') - - self.add_argument( - '--is-lite', - action='store_true', - default=False, - help='Update only for OHOS Lite') - - self.add_argument( - '--no-linux-update', - action='store_true', - default=False, - help='Do not update Linux toolchain') - - -def extract_package(package, install_dir): - cmd = ['tar', '--extract', '--file', package, '--directory', install_dir] - check_call(cmd) - - -def create_package(prebuilt_dir, package_path, package_name): - cmd = ['tar', '--create', '--bzip2', '--directory', prebuilt_dir, '--file', package_path, package_name] - check_call(cmd) - - -def copy_linux_resource_dir(install_dir, linux_prebuilt_dir): - - copy_dir = os.path.join(install_dir, 'lib', 'clang') - src_dir = os.path.join(linux_prebuilt_dir, 'lib', 'clang') - version_dir = detect_clang_version(src_dir) - src_dir = os.path.join(src_dir, version_dir) - dst_dir = os.path.join(copy_dir, version_dir) - shutil.copytree(src_dir, dst_dir) - - - -def copy_linux_driver_include_dir(install_dir, linux_prebuilt_dir): - copy_dir = os.path.join(install_dir, 'include') - src_dir = os.path.join(linux_prebuilt_dir, 'include') - for d in ['c++', 'libcxx-ohos']: - shutil.copytree(os.path.join(src_dir, d), os.path.join(copy_dir, d)) - - -def copy_linux_driver_lib_dir(install_dir, linux_prebuilt_dir, llvm_triple): - copy_dir = os.path.join(install_dir, 'lib', llvm_triple) - src_dir = os.path.join(linux_prebuilt_dir, 'lib', llvm_triple) - shutil.copytree(src_dir, copy_dir) - - -def copy_runtime_from_linux(ndk_prebuilt_dir, linux_prebuilt_dir, is_lite): - clang_lib_root = os.path.join(ndk_prebuilt_dir, 'lib', 'clang') - clang_ver = detect_clang_version(clang_lib_root) - shutil.rmtree(os.path.join(clang_lib_root, clang_ver)) - shutil.rmtree(os.path.join(ndk_prebuilt_dir, './include/c++')) - copy_linux_resource_dir(ndk_prebuilt_dir, linux_prebuilt_dir) - copy_linux_driver_include_dir(ndk_prebuilt_dir, linux_prebuilt_dir) - if is_lite: - copy_linux_driver_lib_dir(ndk_prebuilt_dir, linux_prebuilt_dir, 'arm-liteos-ohos') - else: - copy_linux_driver_lib_dir(ndk_prebuilt_dir, linux_prebuilt_dir, 'arm-liteos-ohos') - copy_linux_driver_lib_dir(ndk_prebuilt_dir, linux_prebuilt_dir, 'arm-linux-ohos') - copy_linux_driver_lib_dir(ndk_prebuilt_dir, linux_prebuilt_dir, 'aarch64-linux-ohos') - - -def detect_clang_version(lib_root): - items = os.listdir(lib_root) - # We expect single directory which name represents clang version, - # e.g 10.0.1 (or 12.0.1) - if len(items) != 1 or not os.path.isdir(os.path.join(lib_root, items[0])): - logger().error('Cannot detect clang version') - return "" - return items[0] - - -def rmtree_if_exists(path): - if os.path.exists(path): - shutil.rmtree(path) - - -def shutil_remove(ndk_prebuilt_dir): - rmtree_if_exists(os.path.join(ndk_prebuilt_dir, './include/llvm-c')) - rmtree_if_exists(os.path.join(ndk_prebuilt_dir, './include/llvm')) - rmtree_if_exists(os.path.join(ndk_prebuilt_dir, './include/lldb')) - rmtree_if_exists(os.path.join(ndk_prebuilt_dir, './include/lld')) - rmtree_if_exists(os.path.join(ndk_prebuilt_dir, './include/clang-c')) - rmtree_if_exists(os.path.join(ndk_prebuilt_dir, './include/clang')) - - -# python update-prebuilts.py XXXX -def update_clang(host, build_number, source_dir, bug, is_lite, no_linux_update): - package = '{}/clang-{}-{}.tar.bz2'.format( - source_dir, build_number, host) - prebuilt_dir = os.path.join(source_dir, host) - clang_version_dir = 'clang-' + build_number - ndk_prebuilt_dir = os.path.join(prebuilt_dir, clang_version_dir) - linux_prebuilt_dir = os.path.join(source_dir, 'linux-x86_64', clang_version_dir) - - - if os.path.isdir(ndk_prebuilt_dir): - shutil.rmtree(ndk_prebuilt_dir) - extract_package(package, prebuilt_dir) - if (no_linux_update and host == 'linux-x86_64'): - return - - shutil_remove(ndk_prebuilt_dir) - - - # Copy from linux runtime - if host == 'darwin-x86_64': - copy_runtime_from_linux(ndk_prebuilt_dir, linux_prebuilt_dir, is_lite) - if host == 'windows-x86_64': - copy_runtime_from_linux(ndk_prebuilt_dir, linux_prebuilt_dir, is_lite) - # symlink not work on windows file system (samba works), so hard copy them - if is_lite: - os.remove(os.path.join(ndk_prebuilt_dir, './lib/CheckerDependencyHandlingAnalyzerPlugin.dll')) - os.remove(os.path.join(ndk_prebuilt_dir, './lib/CheckerOptionHandlingAnalyzerPlugin.dll')) - os.remove(os.path.join(ndk_prebuilt_dir, './lib/SampleAnalyzerPlugin.dll')) - os.remove(os.path.join(ndk_prebuilt_dir, './lib/CheckApi.dll')) - - # Delete no use runtimes - if host == 'linux-x86_64': - # Delete *omp.* in ./lib/clang/10.0.1/lib - clang_lib_root = os.path.join(ndk_prebuilt_dir, "lib", "clang") - clang_ver = detect_clang_version(clang_lib_root) - clang_lib_dir = os.path.join(clang_lib_root, clang_ver, 'lib') - lib_files = os.listdir(clang_lib_dir) - for lib_file in lib_files: - if lib_file.find('omp') != -1: - src_file = os.path.join(clang_lib_dir, lib_file) - os.remove(src_file) - - if is_lite: - - shutil.rmtree(os.path.join(clang_lib_root, clang_ver, 'lib', 'linux')) - os.remove(os.path.join(ndk_prebuilt_dir, './lib/CheckerDependencyHandlingAnalyzerPlugin.so')) - os.remove(os.path.join(ndk_prebuilt_dir, './lib/CheckerOptionHandlingAnalyzerPlugin.so')) - os.remove(os.path.join(ndk_prebuilt_dir, './lib/SampleAnalyzerPlugin.so')) - os.remove(os.path.join(ndk_prebuilt_dir, './lib/CheckApi.so')) - return - - # Currently libunwind.a and libomp.a have been archived in the target folder. The folder can be deleted. - - rmtree_if_exists(os.path.join(clang_lib_root, clang_ver, 'lib', 'linux')) - lib_files = os.listdir(clang_lib_dir) - for lib_file in lib_files: - if lib_file.find('clang_rt.') != -1: - src_file = os.path.join(clang_lib_dir, lib_file) - os.remove(src_file) - - # Packaging in tar.bz2 archive new updated toolchain - package_name = 'clang-{}-{}.tar.bz2'.format(build_number, host) - package_path = os.path.join(source_dir, package_name) - create_package(prebuilt_dir, package_path, clang_version_dir) - return - - # TODO aoto git add/commit - - -def main(): - args = ArgParser().parse_args() - - logging.basicConfig(level=logging.INFO) - source_dir = args.source_dir - os.chdir(source_dir) - - if 'linux' not in args.hosts: - logger().error('Updating Windows and Darwin toolchains needs Linux toolchain. Exiting...') - return - - hosts = ('{}-x86_64'.format(host) for host in args.hosts) - - for host in hosts: - if os.path.isdir(host): - shutil.rmtree(host) - os.makedirs(host) - update_clang(host, args.build, - source_dir, args.bug, args.is_lite, args.no_linux_update) - - return 0 - - -if __name__ == '__main__': - main() -- Gitee From 5f9a3e3c64b971747bd7449818cd3f8122debd49 Mon Sep 17 00:00:00 2001 From: liwentao_uiw Date: Fri, 8 Jul 2022 18:05:49 +0800 Subject: [PATCH 13/18] Update README.md Change-Id: Iaceb20b6f894425e633542efa2794545e1eeb783 --- data/llvm_build.png | Bin 32219 -> 34465 bytes llvm-build/README.md | 28 ++++++++++++++++------------ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/data/llvm_build.png b/data/llvm_build.png index 86cdeeea3da2d2fe396fa4559494b20d8a0bbbf5..a7f0bdb0c100cf88771a169dc06772109799650d 100644 GIT binary patch literal 34465 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
    a@q@LIokbhw)h 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 literal 32219 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 q^7U`tv;O~L0CoOjF#L}R5`=VWs* @@ -31,8 +29,10 @@ cp -r toolchain/llvm-project/llvm-build toolchain Here is an example of starting build process on Linux or MacOS: ``` -./env_prepare.sh -python3 ./build.py +# update prebuilts, no need to run each time +./toolchain/llvm-project/llvm-build/env_prepare.sh +# build +python3 ./toolchain/llvm-project/llvm-build/build.py ``` 1. env_prepare (one time only) @@ -82,20 +82,24 @@ When build successfully completed. following artifacts will be available in `out 1. llvm ``` -Materials: +contains: 1. toolchain which provides clang compiler, lldb(-mi), clang-tidy etc. tools 2. libc++/clang_rt/asan/fuzzer libs for target device -Path: prebuilts/clang/ohos/${platform}/llvm -OHOS URL: https://mirrors.huaweicloud.com/openharmony/compiler/clang/ -Self Build: clang-dev-${platform}-${arch}.tar.bz2 + +OHOS sync from: https://mirrors.huaweicloud.com/openharmony/compiler/clang/ +Which is the same as: out/clang-dev-${platform}-${arch}.tar.bz2 +OHOS archive to: prebuilts/clang/ohos//${platform}/llvm + +License: Apache License v2.0 with LLVM Exceptions ``` 2. libcxx-ndk ``` -Materials: provide libc++ for ndk in target device -Path: prebuilts/clang/ohos/linux-x86_64/libcxx-ndk -OHOS URL: https://mirrors.huaweicloud.com/openharmony/compiler/clang/ -Self Build: libcxx-ndk-${platform}-${arch}.tar.bz2 +contains: provide libc++ for ndk in target device + +OHOS fetch prebuilts from: https://mirrors.huaweicloud.com/openharmony/compiler/clang/ and archive it to prebuilts/clang/ohos//${platform}/libcxx-ndk. This tar is + +License: Apache License v2.0 with LLVM Exceptions ``` -- Gitee From afeda5fd74da170639a94ba5e20c217a71678c53 Mon Sep 17 00:00:00 2001 From: liwentao_uiw Date: Sun, 10 Jul 2022 21:23:29 +0800 Subject: [PATCH 14/18] update cpython-mingw build step Change-Id: I6589b9eea822bcfc4d81fd0145b344c3ed8e0751 --- llvm-build/build_cpython-mingw.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/llvm-build/build_cpython-mingw.sh b/llvm-build/build_cpython-mingw.sh index 0026a039a5ee..570741b720bc 100755 --- a/llvm-build/build_cpython-mingw.sh +++ b/llvm-build/build_cpython-mingw.sh @@ -10,9 +10,11 @@ python3 ${PROJECT_ROOT}/toolchain/llvm-build/mingw.py # refreash cpython-mingw config cd ${CPYTHON_MINGW_SRC} +cat ./patchs/cpython_mingw_v3.10.2.patch | patch -d ./ -p1 -E rm -rf ${CPYTHON_MINGW_SRC}/configure autoconf ${CPYTHON_MINGW_SRC}/configure.ac > ${CPYTHON_MINGW_SRC}/configure chmod 777 ${CPYTHON_MINGW_SRC}/configure +./configure # # prepare build config and build libpython for cpython-mingw CPYTHON_MINGW_BUILD=${PROJECT_ROOT}/out/cpython-mingw-build -- Gitee From c0e23f3eb0b11035f3949203226082ac341ba346 Mon Sep 17 00:00:00 2001 From: FondMemoryVVV Date: Mon, 11 Jul 2022 08:56:17 +0800 Subject: [PATCH 15/18] fix OAT problems Signed-off-by: FondMemoryVVV --- OAT.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/OAT.xml b/OAT.xml index 77785abdecf2..fe34bbf4d4a4 100644 --- a/OAT.xml +++ b/OAT.xml @@ -137,6 +137,8 @@ + + -- Gitee From a8c8e52729fe14aaae148c21b4ee90d4e60067de Mon Sep 17 00:00:00 2001 From: liwentao_uiw Date: Mon, 11 Jul 2022 10:39:16 +0800 Subject: [PATCH 16/18] add toolchain_readme.md which will be release with toolchain Change-Id: I0a5ffbf9e15cb68adfbd72550dfaab1ecb081dd4 --- llvm-build/toolchain_readme.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 llvm-build/toolchain_readme.md diff --git a/llvm-build/toolchain_readme.md b/llvm-build/toolchain_readme.md new file mode 100644 index 000000000000..441305ead76d --- /dev/null +++ b/llvm-build/toolchain_readme.md @@ -0,0 +1,25 @@ +## Overview + +This readme briefly describes the functionality of our LLVM toolchain and what we have included specially to the LLVM toolchain. + +## Functionality + +The LLVM toolchain is built based on LLVM 10.0.1. It is used to provide capability of building ohos image. For detailed information about LLVM 10.0.1, please refer to [LLVM 10.0.1](https://lists.llvm.org/pipermail/llvm-announce/2020-August/000088.html). + + +## Specifically Included Triplets + +Despite all the components provided by LLVM community, we included several triplets for different types of ohos devices to our LLVM toochain, listed as below. For specification, liteos is a newly included OS name which indicate the simplified linux kernel. + +| Triplet Name | Architecture | System Kernel | System | +| ---------------------- | ------------ | ------------- | --------------- | +| arm-liteos-ohos | ARM 32bits | LiteOS | Small system | +| arm-linux-ohos | ARM 32bits | Linux | Small system | +| arm-linux-ohos | ARM 32bits | Linux | Standard system | +| aarch64-linux-ohos | ARM 64bits | Linux | Standard system | + +For detailed definition of Small System and Standard System, please refer to [System Types](https://gitee.com/openharmony/docs/blob/master/en/device-dev/Readme-EN.md). + +### Specify the triplet + +To build images for different types of platform, you can configure the triplet in the build scripts by setting "--target=xxx" using cflags, xxx should be replaced with a specific triplet name. -- Gitee From 31ef7054ae5e2925fafc2b25ba173288adef7311 Mon Sep 17 00:00:00 2001 From: liuyaning6 Date: Mon, 11 Jul 2022 15:55:53 +0800 Subject: [PATCH 17/18] add llvm-build for openharmony in README.md Signed-off-by: liuyaning6 --- README.md | 2 ++ README_zh.md | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6e02ee378eb3..21370584c1c7 100644 --- a/README.md +++ b/README.md @@ -108,3 +108,5 @@ Consult the page for detailed information on configuring and compiling LLVM. You can visit [Directory Layout](https://llvm.org/docs/GettingStarted.html#directory-layout) to learn about the layout of the source code tree. + +For the llvm construction of openharmony, please refer to [llvm-build](https://gitee.com/openharmony-sig/third_party_llvm-project/tree/llvmorg-12.0.1-dev/llvm-build). \ No newline at end of file diff --git a/README_zh.md b/README_zh.md index f58d9cd8a031..cbbdef3546a9 100644 --- a/README_zh.md +++ b/README_zh.md @@ -67,4 +67,7 @@ LLVM入门文档可能已过期。[Clang入门](https://clang.llvm.org/get_start - 有关详细信息,请参阅 [CMake](https://llvm.org/docs/CMake.html) -请参阅 [LLVM入门](https://llvm.org/docs/GettingStarted.html#getting-started-with-llvm) 页面,了解有关配置和编译LLVM的详细信息。您可以访问 [目录布局](https://llvm.org/docs/GettingStarted.html#directory-layout) 以了解源代码树的布局。 \ No newline at end of file +请参阅 [LLVM入门](https://llvm.org/docs/GettingStarted.html#getting-started-with-llvm) 页面,了解有关配置和编译LLVM的详细信息。您可以访问 [目录布局](https://llvm.org/docs/GettingStarted.html#directory-layout) 以了解源代码树的布局。 + +有关Openharmony的llvm构建请参考[llvm-build](https://gitee.com/openharmony-sig/third_party_llvm-project/tree/llvmorg-12.0.1-dev/llvm-build)。 + -- Gitee From 972d674f4287c8e5e6c1a332ad75626f34676252 Mon Sep 17 00:00:00 2001 From: Hongjin Li Date: Wed, 20 Jul 2022 14:36:00 +0800 Subject: [PATCH 18/18] feat: memcpy_s checker Signed-off-by: Hongjin Li Change-Id: I8ede9fd67a117419e8bc61aea5ea5fad5f958154 --- .../Checkers/OpenHarmony/MemcpyChecker.cpp | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 clang/lib/StaticAnalyzer/Checkers/OpenHarmony/MemcpyChecker.cpp diff --git a/clang/lib/StaticAnalyzer/Checkers/OpenHarmony/MemcpyChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/OpenHarmony/MemcpyChecker.cpp new file mode 100644 index 000000000000..847f6661fa05 --- /dev/null +++ b/clang/lib/StaticAnalyzer/Checkers/OpenHarmony/MemcpyChecker.cpp @@ -0,0 +1,103 @@ +#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h" + +using namespace clang; +using namespace ento; + +namespace +{ +class MemcpyChecker : public Checker +{ + CallDescription MemcpyS; + + std::unique_ptr OverflowBugType; + + public: + MemcpyChecker(); + void checkPreCall(const CallEvent &Call, CheckerContext &C) const; +}; + +MemcpyChecker::MemcpyChecker() + : MemcpyS("memcpy_s") +{ + OverflowBugType.reset( + new BugType(this, "MyFistChecker memcpy_s overflow", "MyFistChecker error")); +} + +void MemcpyChecker::checkPreCall(const CallEvent &Call, CheckerContext &C) const +{ + if (!Call.isCalled(MemcpyS)) { + return; + } + + SValBuilder &SVB = C.getSValBuilder(); + ProgramStateRef state = C.getState(); + SVal dstAddrSVal = Call.getArgSVal(0); + SVal srcLengthSVal = Call.getArgSVal(3); + + const MemRegion *dstAddrMR = dstAddrSVal.getAsRegion(); + if (!dstAddrMR) { + return; + } + + const ElementRegion *dstAddrER = dyn_cast(dstAddrMR); + if (!dstAddrER) { + return; + } + + DefinedOrUnknownSVal Idx = dstAddrER->getIndex().castAs(); + Optional IdxSVal = Idx.getAs(); + if (!IdxSVal) { + return; + } + + DefinedOrUnknownSVal ElementCount = getDynamicElementCount( + state, dstAddrER->getSuperRegion(), C.getSValBuilder(), dstAddrER->getValueType()); + + Optional dstAddrLenSVal = ElementCount.getAs(); + if (!dstAddrLenSVal) { + return; + } + + Optional srcLengthDSVal = srcLengthSVal.getAs(); + + SVal srcLenDSval = SVB.evalBinOp(state, BO_Add, *srcLengthDSVal, *IdxSVal, SVB.getArrayIndexType()); + + SVal dstLessThanSrcLength = SVB.evalBinOp(state, BO_LT, *dstAddrLenSVal, srcLenDSval, SVB.getConditionType()); + + Optional dstLessThanSrcLengthDVal = dstLessThanSrcLength.getAs(); + if (!dstLessThanSrcLengthDVal) { + return; + } + + if (state->assume(*dstLessThanSrcLengthDVal, true)) { + // it is possible that dst less than src length + ExplodedNode *ErrNode = C.generateNonFatalErrorNode(); + // If we've already reached this node on another path, return. + if (!ErrNode) + return; + + // Generate the report. + auto R = std::make_unique( + *OverflowBugType, "MemcpyChecker BugReport", ErrNode); + R->addRange(Call.getSourceRange()); + C.emitReport(std::move(R)); + return; + } +} +} // namespace + +void ento::registerMemcpyChecker(CheckerManager &mgr) +{ + mgr.registerChecker(); +} + +// This checker should be enabled regardless of how language options are set. +bool ento::shouldRegisterMemcpyChecker(const CheckerManager &mgr) +{ + return true; +} -- Gitee