| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| //===--- InstallAPIDiagnostic.h - Diagnostics for InstallAPI ----*- 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_INSTALLAPI_INSTALLAPIDIAGNOSTIC_H | ||
| #define LLVM_CLANG_INSTALLAPI_INSTALLAPIDIAGNOSTIC_H | ||
|
|
||
| #include "clang/Basic/DiagnosticInstallAPI.h" | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1 @@ | ||
| BasedOnStyle: clang-format |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,11 +17,6 @@ | |
|
|
||
| #include "Encoding.h" | ||
| #include "FormatToken.h" | ||
|
|
||
| namespace clang { | ||
| class SourceManager; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,212 @@ | ||
| #include "clang/InstallAPI/DylibVerifier.h" | ||
| #include "clang/InstallAPI/FrontendRecords.h" | ||
| #include "llvm/Demangle/Demangle.h" | ||
|
|
||
| using namespace llvm::MachO; | ||
|
|
||
| namespace clang { | ||
| namespace installapi { | ||
|
|
||
| /// Metadata stored about a mapping of a declaration to a symbol. | ||
| struct DylibVerifier::SymbolContext { | ||
| // Name to use for printing in diagnostics. | ||
| std::string PrettyPrintName{""}; | ||
|
|
||
| // Name to use for all querying and verification | ||
| // purposes. | ||
| std::string SymbolName{""}; | ||
|
|
||
| // Kind to map symbol type against record. | ||
| EncodeKind Kind = EncodeKind::GlobalSymbol; | ||
|
|
||
| // Frontend Attributes tied to the AST. | ||
| const FrontendAttrs *FA = nullptr; | ||
|
|
||
| // The ObjCInterface symbol type, if applicable. | ||
| ObjCIFSymbolKind ObjCIFKind = ObjCIFSymbolKind::None; | ||
| }; | ||
|
|
||
| static std::string | ||
| getAnnotatedName(const Record *R, EncodeKind Kind, StringRef Name, | ||
| bool ValidSourceLoc = true, | ||
| ObjCIFSymbolKind ObjCIF = ObjCIFSymbolKind::None) { | ||
| assert(!Name.empty() && "Need symbol name for printing"); | ||
|
|
||
| std::string Annotation; | ||
| if (R->isWeakDefined()) | ||
| Annotation += "(weak-def) "; | ||
| if (R->isWeakReferenced()) | ||
| Annotation += "(weak-ref) "; | ||
| if (R->isThreadLocalValue()) | ||
| Annotation += "(tlv) "; | ||
|
|
||
| // Check if symbol represents only part of a @interface declaration. | ||
| const bool IsAnnotatedObjCClass = ((ObjCIF != ObjCIFSymbolKind::None) && | ||
| (ObjCIF <= ObjCIFSymbolKind::EHType)); | ||
|
|
||
| if (IsAnnotatedObjCClass) { | ||
| if (ObjCIF == ObjCIFSymbolKind::EHType) | ||
| Annotation += "Exception Type of "; | ||
| if (ObjCIF == ObjCIFSymbolKind::MetaClass) | ||
| Annotation += "Metaclass of "; | ||
| if (ObjCIF == ObjCIFSymbolKind::Class) | ||
| Annotation += "Class of "; | ||
| } | ||
|
|
||
| // Only print symbol type prefix or leading "_" if there is no source location | ||
| // tied to it. This can only ever happen when the location has to come from | ||
| // debug info. | ||
| if (ValidSourceLoc) { | ||
| if ((Kind == EncodeKind::GlobalSymbol) && Name.starts_with("_")) | ||
| return Annotation + Name.drop_front(1).str(); | ||
| return Annotation + Name.str(); | ||
| } | ||
|
|
||
| if (IsAnnotatedObjCClass) | ||
| return Annotation + Name.str(); | ||
|
|
||
| switch (Kind) { | ||
| case EncodeKind::GlobalSymbol: | ||
| return Annotation + Name.str(); | ||
| case EncodeKind::ObjectiveCInstanceVariable: | ||
| return Annotation + "(ObjC IVar) " + Name.str(); | ||
| case EncodeKind::ObjectiveCClass: | ||
| return Annotation + "(ObjC Class) " + Name.str(); | ||
| case EncodeKind::ObjectiveCClassEHType: | ||
| return Annotation + "(ObjC Class EH) " + Name.str(); | ||
| } | ||
|
|
||
| llvm_unreachable("unexpected case for EncodeKind"); | ||
| } | ||
|
|
||
| static std::string demangle(StringRef Name) { | ||
| // Itanium encoding requires 1 or 3 leading underscores, followed by 'Z'. | ||
| if (!(Name.starts_with("_Z") || Name.starts_with("___Z"))) | ||
| return Name.str(); | ||
| char *Result = llvm::itaniumDemangle(Name.data()); | ||
| if (!Result) | ||
| return Name.str(); | ||
|
|
||
| std::string Demangled(Result); | ||
| free(Result); | ||
| return Demangled; | ||
| } | ||
|
|
||
| static DylibVerifier::Result updateResult(const DylibVerifier::Result Prev, | ||
| const DylibVerifier::Result Curr) { | ||
| if (Prev == Curr) | ||
| return Prev; | ||
|
|
||
| // Never update from invalid or noverify state. | ||
| if ((Prev == DylibVerifier::Result::Invalid) || | ||
| (Prev == DylibVerifier::Result::NoVerify)) | ||
| return Prev; | ||
|
|
||
| // Don't let an ignored verification remove a valid one. | ||
| if (Prev == DylibVerifier::Result::Valid && | ||
| Curr == DylibVerifier::Result::Ignore) | ||
| return Prev; | ||
|
|
||
| return Curr; | ||
| } | ||
|
|
||
| void DylibVerifier::updateState(Result State) { | ||
| Ctx.FrontendState = updateResult(Ctx.FrontendState, State); | ||
| } | ||
|
|
||
| void DylibVerifier::addSymbol(const Record *R, SymbolContext &SymCtx, | ||
| TargetList &&Targets) { | ||
| if (Targets.empty()) | ||
| Targets = {Ctx.Target}; | ||
|
|
||
| Exports->addGlobal(SymCtx.Kind, SymCtx.SymbolName, R->getFlags(), Targets); | ||
| } | ||
|
|
||
| DylibVerifier::Result DylibVerifier::verifyImpl(Record *R, | ||
| SymbolContext &SymCtx) { | ||
| R->setVerify(); | ||
| if (!canVerify()) { | ||
| // Accumulate symbols when not in verifying against dylib. | ||
| if (R->isExported() && !SymCtx.FA->Avail.isUnconditionallyUnavailable() && | ||
| !SymCtx.FA->Avail.isObsoleted()) { | ||
| addSymbol(R, SymCtx); | ||
| } | ||
| return Ctx.FrontendState; | ||
| } | ||
| return Ctx.FrontendState; | ||
| } | ||
|
|
||
| bool DylibVerifier::canVerify() { | ||
| return Ctx.FrontendState != Result::NoVerify; | ||
| } | ||
|
|
||
| void DylibVerifier::setTarget(const Target &T) { | ||
| Ctx.Target = T; | ||
| Ctx.DiscoveredFirstError = false; | ||
| updateState(Dylib.empty() ? Result::NoVerify : Result::Ignore); | ||
| } | ||
|
|
||
| DylibVerifier::Result DylibVerifier::verify(ObjCIVarRecord *R, | ||
| const FrontendAttrs *FA, | ||
| const StringRef SuperClass) { | ||
| if (R->isVerified()) | ||
| return getState(); | ||
|
|
||
| std::string FullName = | ||
| ObjCIVarRecord::createScopedName(SuperClass, R->getName()); | ||
| SymbolContext SymCtx{ | ||
| getAnnotatedName(R, EncodeKind::ObjectiveCInstanceVariable, | ||
| Demangle ? demangle(FullName) : FullName), | ||
| FullName, EncodeKind::ObjectiveCInstanceVariable, FA}; | ||
| return verifyImpl(R, SymCtx); | ||
| } | ||
|
|
||
| static ObjCIFSymbolKind assignObjCIFSymbolKind(const ObjCInterfaceRecord *R) { | ||
| ObjCIFSymbolKind Result = ObjCIFSymbolKind::None; | ||
| if (R->getLinkageForSymbol(ObjCIFSymbolKind::Class) != RecordLinkage::Unknown) | ||
| Result |= ObjCIFSymbolKind::Class; | ||
| if (R->getLinkageForSymbol(ObjCIFSymbolKind::MetaClass) != | ||
| RecordLinkage::Unknown) | ||
| Result |= ObjCIFSymbolKind::MetaClass; | ||
| if (R->getLinkageForSymbol(ObjCIFSymbolKind::EHType) != | ||
| RecordLinkage::Unknown) | ||
| Result |= ObjCIFSymbolKind::EHType; | ||
| return Result; | ||
| } | ||
|
|
||
| DylibVerifier::Result DylibVerifier::verify(ObjCInterfaceRecord *R, | ||
| const FrontendAttrs *FA) { | ||
| if (R->isVerified()) | ||
| return getState(); | ||
| SymbolContext SymCtx; | ||
| SymCtx.SymbolName = R->getName(); | ||
| SymCtx.ObjCIFKind = assignObjCIFSymbolKind(R); | ||
|
|
||
| std::string DisplayName = | ||
| Demangle ? demangle(SymCtx.SymbolName) : SymCtx.SymbolName; | ||
| SymCtx.Kind = R->hasExceptionAttribute() ? EncodeKind::ObjectiveCClassEHType | ||
| : EncodeKind::ObjectiveCClass; | ||
| SymCtx.PrettyPrintName = getAnnotatedName(R, SymCtx.Kind, DisplayName); | ||
| SymCtx.FA = FA; | ||
|
|
||
| return verifyImpl(R, SymCtx); | ||
| } | ||
|
|
||
| DylibVerifier::Result DylibVerifier::verify(GlobalRecord *R, | ||
| const FrontendAttrs *FA) { | ||
| if (R->isVerified()) | ||
| return getState(); | ||
|
|
||
| // Global classifications could be obfusciated with `asm`. | ||
| SimpleSymbol Sym = parseSymbol(R->getName()); | ||
| SymbolContext SymCtx; | ||
| SymCtx.SymbolName = Sym.Name; | ||
| SymCtx.PrettyPrintName = | ||
| getAnnotatedName(R, Sym.Kind, Demangle ? demangle(Sym.Name) : Sym.Name); | ||
| SymCtx.Kind = Sym.Kind; | ||
| SymCtx.FA = FA; | ||
| return verifyImpl(R, SymCtx); | ||
| } | ||
|
|
||
| } // namespace installapi | ||
| } // namespace clang |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| // RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -o - | FileCheck %s | ||
|
|
||
| // CHECK-LABEL: builtin_test_clamp_int4 | ||
| // CHECK: %dx.clamp = call <4 x i32> @llvm.dx.clamp.v4i32(<4 x i32> %0, <4 x i32> %1, <4 x i32> %2) | ||
| // CHECK: ret <4 x i32> %dx.clamp | ||
| int4 builtin_test_clamp_int4(int4 p0, int4 p1, int4 p2) { | ||
| return __builtin_hlsl_elementwise_clamp(p0, p1, p2); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,134 @@ | ||
| // RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \ | ||
| // RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ | ||
| // RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ | ||
| // RUN: --check-prefixes=CHECK,NATIVE_HALF | ||
| // RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \ | ||
| // RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \ | ||
| // RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF | ||
|
|
||
| #ifdef __HLSL_ENABLE_16_BIT | ||
| // NATIVE_HALF: define noundef i16 @ | ||
| // NATIVE_HALF: call i16 @llvm.dx.clamp.i16( | ||
| int16_t test_clamp_short(int16_t p0, int16_t p1) { return clamp(p0, p1,p1); } | ||
| // NATIVE_HALF: define noundef <2 x i16> @ | ||
| // NATIVE_HALF: call <2 x i16> @llvm.dx.clamp.v2i16( | ||
| int16_t2 test_clamp_short2(int16_t2 p0, int16_t2 p1) { return clamp(p0, p1,p1); } | ||
| // NATIVE_HALF: define noundef <3 x i16> @ | ||
| // NATIVE_HALF: call <3 x i16> @llvm.dx.clamp.v3i16 | ||
| int16_t3 test_clamp_short3(int16_t3 p0, int16_t3 p1) { return clamp(p0, p1,p1); } | ||
| // NATIVE_HALF: define noundef <4 x i16> @ | ||
| // NATIVE_HALF: call <4 x i16> @llvm.dx.clamp.v4i16 | ||
| int16_t4 test_clamp_short4(int16_t4 p0, int16_t4 p1) { return clamp(p0, p1,p1); } | ||
|
|
||
| // NATIVE_HALF: define noundef i16 @ | ||
| // NATIVE_HALF: call i16 @llvm.dx.uclamp.i16( | ||
| uint16_t test_clamp_ushort(uint16_t p0, uint16_t p1) { return clamp(p0, p1,p1); } | ||
| // NATIVE_HALF: define noundef <2 x i16> @ | ||
| // NATIVE_HALF: call <2 x i16> @llvm.dx.uclamp.v2i16 | ||
| uint16_t2 test_clamp_ushort2(uint16_t2 p0, uint16_t2 p1) { return clamp(p0, p1,p1); } | ||
| // NATIVE_HALF: define noundef <3 x i16> @ | ||
| // NATIVE_HALF: call <3 x i16> @llvm.dx.uclamp.v3i16 | ||
| uint16_t3 test_clamp_ushort3(uint16_t3 p0, uint16_t3 p1) { return clamp(p0, p1,p1); } | ||
| // NATIVE_HALF: define noundef <4 x i16> @ | ||
| // NATIVE_HALF: call <4 x i16> @llvm.dx.uclamp.v4i16 | ||
| uint16_t4 test_clamp_ushort4(uint16_t4 p0, uint16_t4 p1) { return clamp(p0, p1,p1); } | ||
| #endif | ||
|
|
||
| // CHECK: define noundef i32 @ | ||
| // CHECK: call i32 @llvm.dx.clamp.i32( | ||
| int test_clamp_int(int p0, int p1) { return clamp(p0, p1,p1); } | ||
| // CHECK: define noundef <2 x i32> @ | ||
| // CHECK: call <2 x i32> @llvm.dx.clamp.v2i32 | ||
| int2 test_clamp_int2(int2 p0, int2 p1) { return clamp(p0, p1,p1); } | ||
| // CHECK: define noundef <3 x i32> @ | ||
| // CHECK: call <3 x i32> @llvm.dx.clamp.v3i32 | ||
| int3 test_clamp_int3(int3 p0, int3 p1) { return clamp(p0, p1,p1); } | ||
| // CHECK: define noundef <4 x i32> @ | ||
| // CHECK: call <4 x i32> @llvm.dx.clamp.v4i32 | ||
| int4 test_clamp_int4(int4 p0, int4 p1) { return clamp(p0, p1,p1); } | ||
|
|
||
| // CHECK: define noundef i32 @ | ||
| // CHECK: call i32 @llvm.dx.uclamp.i32( | ||
| int test_clamp_uint(uint p0, uint p1) { return clamp(p0, p1,p1); } | ||
| // CHECK: define noundef <2 x i32> @ | ||
| // CHECK: call <2 x i32> @llvm.dx.uclamp.v2i32 | ||
| uint2 test_clamp_uint2(uint2 p0, uint2 p1) { return clamp(p0, p1,p1); } | ||
| // CHECK: define noundef <3 x i32> @ | ||
| // CHECK: call <3 x i32> @llvm.dx.uclamp.v3i32 | ||
| uint3 test_clamp_uint3(uint3 p0, uint3 p1) { return clamp(p0, p1,p1); } | ||
| // CHECK: define noundef <4 x i32> @ | ||
| // CHECK: call <4 x i32> @llvm.dx.uclamp.v4i32 | ||
| uint4 test_clamp_uint4(uint4 p0, uint4 p1) { return clamp(p0, p1,p1); } | ||
|
|
||
| // CHECK: define noundef i64 @ | ||
| // CHECK: call i64 @llvm.dx.clamp.i64( | ||
| int64_t test_clamp_long(int64_t p0, int64_t p1) { return clamp(p0, p1,p1); } | ||
| // CHECK: define noundef <2 x i64> @ | ||
| // CHECK: call <2 x i64> @llvm.dx.clamp.v2i64 | ||
| int64_t2 test_clamp_long2(int64_t2 p0, int64_t2 p1) { return clamp(p0, p1,p1); } | ||
| // CHECK: define noundef <3 x i64> @ | ||
| // CHECK: call <3 x i64> @llvm.dx.clamp.v3i64 | ||
| int64_t3 test_clamp_long3(int64_t3 p0, int64_t3 p1) { return clamp(p0, p1,p1); } | ||
| // CHECK: define noundef <4 x i64> @ | ||
| // CHECK: call <4 x i64> @llvm.dx.clamp.v4i64 | ||
| int64_t4 test_clamp_long4(int64_t4 p0, int64_t4 p1) { return clamp(p0, p1,p1); } | ||
|
|
||
| // CHECK: define noundef i64 @ | ||
| // CHECK: call i64 @llvm.dx.uclamp.i64( | ||
| uint64_t test_clamp_long(uint64_t p0, uint64_t p1) { return clamp(p0, p1,p1); } | ||
| // CHECK: define noundef <2 x i64> @ | ||
| // CHECK: call <2 x i64> @llvm.dx.uclamp.v2i64 | ||
| uint64_t2 test_clamp_long2(uint64_t2 p0, uint64_t2 p1) { return clamp(p0, p1,p1); } | ||
| // CHECK: define noundef <3 x i64> @ | ||
| // CHECK: call <3 x i64> @llvm.dx.uclamp.v3i64 | ||
| uint64_t3 test_clamp_long3(uint64_t3 p0, uint64_t3 p1) { return clamp(p0, p1,p1); } | ||
| // CHECK: define noundef <4 x i64> @ | ||
| // CHECK: call <4 x i64> @llvm.dx.uclamp.v4i64 | ||
| uint64_t4 test_clamp_long4(uint64_t4 p0, uint64_t4 p1) { return clamp(p0, p1,p1); } | ||
|
|
||
| // NATIVE_HALF: define noundef half @ | ||
| // NATIVE_HALF: call half @llvm.dx.clamp.f16( | ||
| // NO_HALF: define noundef float @"?test_clamp_half | ||
| // NO_HALF: call float @llvm.dx.clamp.f32( | ||
| half test_clamp_half(half p0, half p1) { return clamp(p0, p1,p1); } | ||
| // NATIVE_HALF: define noundef <2 x half> @ | ||
| // NATIVE_HALF: call <2 x half> @llvm.dx.clamp.v2f16 | ||
| // NO_HALF: define noundef <2 x float> @"?test_clamp_half2 | ||
| // NO_HALF: call <2 x float> @llvm.dx.clamp.v2f32( | ||
| half2 test_clamp_half2(half2 p0, half2 p1) { return clamp(p0, p1,p1); } | ||
| // NATIVE_HALF: define noundef <3 x half> @ | ||
| // NATIVE_HALF: call <3 x half> @llvm.dx.clamp.v3f16 | ||
| // NO_HALF: define noundef <3 x float> @"?test_clamp_half3 | ||
| // NO_HALF: call <3 x float> @llvm.dx.clamp.v3f32( | ||
| half3 test_clamp_half3(half3 p0, half3 p1) { return clamp(p0, p1,p1); } | ||
| // NATIVE_HALF: define noundef <4 x half> @ | ||
| // NATIVE_HALF: call <4 x half> @llvm.dx.clamp.v4f16 | ||
| // NO_HALF: define noundef <4 x float> @"?test_clamp_half4 | ||
| // NO_HALF: call <4 x float> @llvm.dx.clamp.v4f32( | ||
| half4 test_clamp_half4(half4 p0, half4 p1) { return clamp(p0, p1,p1); } | ||
|
|
||
| // CHECK: define noundef float @"?test_clamp_float | ||
| // CHECK: call float @llvm.dx.clamp.f32( | ||
| float test_clamp_float(float p0, float p1) { return clamp(p0, p1,p1); } | ||
| // CHECK: define noundef <2 x float> @"?test_clamp_float2 | ||
| // CHECK: call <2 x float> @llvm.dx.clamp.v2f32 | ||
| float2 test_clamp_float2(float2 p0, float2 p1) { return clamp(p0, p1,p1); } | ||
| // CHECK: define noundef <3 x float> @"?test_clamp_float3 | ||
| // CHECK: call <3 x float> @llvm.dx.clamp.v3f32 | ||
| float3 test_clamp_float3(float3 p0, float3 p1) { return clamp(p0, p1,p1); } | ||
| // CHECK: define noundef <4 x float> @"?test_clamp_float4 | ||
| // CHECK: call <4 x float> @llvm.dx.clamp.v4f32 | ||
| float4 test_clamp_float4(float4 p0, float4 p1) { return clamp(p0, p1,p1); } | ||
|
|
||
| // CHECK: define noundef double @ | ||
| // CHECK: call double @llvm.dx.clamp.f64( | ||
| double test_clamp_double(double p0, double p1) { return clamp(p0, p1,p1); } | ||
| // CHECK: define noundef <2 x double> @ | ||
| // CHECK: call <2 x double> @llvm.dx.clamp.v2f64 | ||
| double2 test_clamp_double2(double2 p0, double2 p1) { return clamp(p0, p1,p1); } | ||
| // CHECK: define noundef <3 x double> @ | ||
| // CHECK: call <3 x double> @llvm.dx.clamp.v3f64 | ||
| double3 test_clamp_double3(double3 p0, double3 p1) { return clamp(p0, p1,p1); } | ||
| // CHECK: define noundef <4 x double> @ | ||
| // CHECK: call <4 x double> @llvm.dx.clamp.v4f64 | ||
| double4 test_clamp_double4(double4 p0, double4 p1) { return clamp(p0, p1,p1); } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| // RUN: rm -rf %t | ||
| // RUN: split-file %s %t | ||
| // RUN: sed -e "s|DSTROOT|%/t|g" %t/inputs.json.in > %t/inputs.json | ||
|
|
||
| // RUN: clang-installapi -target arm64-apple-macos13.1 \ | ||
| // RUN: -I%t/usr/include \ | ||
| // RUN: -install_name @rpath/lib/libasm.dylib \ | ||
| // RUN: %t/inputs.json -o %t/output.tbd 2>&1 | FileCheck %s --allow-empty | ||
| // RUN: llvm-readtapi -compare %t/output.tbd %t/expected.tbd 2>&1 | FileCheck %s --allow-empty | ||
|
|
||
| // CHECK-NOT: error: | ||
| // CHECK-NOT: warning: | ||
|
|
||
| //--- usr/include/asm.h | ||
| #ifndef ASM_H | ||
| #define ASM_H | ||
|
|
||
| extern int ivar __asm("_OBJC_IVAR_$_SomeClass._ivar1"); | ||
| extern int objcClass1 __asm("_OBJC_CLASS_$_SomeClass"); | ||
| extern int objcClass2 __asm("_OBJC_METACLASS_$_SomeClass"); | ||
| extern int objcClass3 __asm("_OBJC_EHTYPE_$_SomeClass"); | ||
| extern int objcClass4 __asm(".objc_class_name_SomeClass"); | ||
|
|
||
| __attribute__((visibility("hidden"))) | ||
| @interface NSString { | ||
| } | ||
| @end | ||
|
|
||
| extern int ivarExtra __asm("_OBJC_IVAR_$_NSString._ivar1"); | ||
| #endif // ASM_H | ||
|
|
||
| //--- inputs.json.in | ||
| { | ||
| "headers": [ { | ||
| "path" : "DSTROOT/usr/include/asm.h", | ||
| "type" : "public" | ||
| }], | ||
| "version": "3" | ||
| } | ||
|
|
||
| //--- expected.tbd | ||
| { | ||
| "main_library": { | ||
| "compatibility_versions": [ | ||
| { | ||
| "version": "0" | ||
| } | ||
| ], | ||
| "current_versions": [ | ||
| { | ||
| "version": "0" | ||
| } | ||
| ], | ||
| "exported_symbols": [ | ||
| { | ||
| "data": { | ||
| "objc_class": [ | ||
| "SomeClass" | ||
| ], | ||
| "objc_eh_type": [ | ||
| "SomeClass" | ||
| ], | ||
| "objc_ivar": [ | ||
| "NSString._ivar1", | ||
| "SomeClass._ivar1" | ||
| ] | ||
| } | ||
| } | ||
| ], | ||
| "flags": [ | ||
| { | ||
| "attributes": [ | ||
| "not_app_extension_safe" | ||
| ] | ||
| } | ||
| ], | ||
| "install_names": [ | ||
| { | ||
| "name": "@rpath/lib/libasm.dylib" | ||
| } | ||
| ], | ||
| "target_info": [ | ||
| { | ||
| "min_deployment": "13.1", | ||
| "target": "arm64-macos" | ||
| } | ||
| ] | ||
| }, | ||
| "tapi_tbd_version": 5 | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,9 @@ | ||
| /// Check non-darwin triple is rejected. | ||
| // RUN: not clang-installapi -target x86_64-unknown-unknown %s -o tmp.tbd 2> %t | ||
| // RUN: FileCheck --check-prefix INVALID_INSTALLAPI -input-file %t %s | ||
| // INVALID_INSTALLAPI: error: unsupported option 'installapi' for target 'x86_64-unknown-unknown' | ||
|
|
||
| /// Check that missing install_name is reported. | ||
| // RUN: not clang-installapi -target x86_64-apple-ios-simulator %s -o tmp.tbd 2> %t | ||
| // RUN: FileCheck --check-prefix INVALID_INSTALL_NAME -input-file %t %s | ||
| // INVALID_INSTALL_NAME: error: no install name specified: add -install_name <path> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| // RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected | ||
|
|
||
| float2 test_no_second_arg(float2 p0) { | ||
| return __builtin_hlsl_elementwise_clamp(p0); | ||
| // expected-error@-1 {{too few arguments to function call, expected 3, have 1}} | ||
| } | ||
|
|
||
| float2 test_no_third_arg(float2 p0) { | ||
| return __builtin_hlsl_elementwise_clamp(p0, p0); | ||
| // expected-error@-1 {{too few arguments to function call, expected 3, have 2}} | ||
| } | ||
|
|
||
| float2 test_too_many_arg(float2 p0) { | ||
| return __builtin_hlsl_elementwise_clamp(p0, p0, p0, p0); | ||
| // expected-error@-1 {{too many arguments to function call, expected 3, have 4}} | ||
| } | ||
|
|
||
| float2 test_clamp_no_second_arg(float2 p0) { | ||
| return clamp(p0); | ||
| // expected-error@-1 {{no matching function for call to 'clamp'}} | ||
| } | ||
|
|
||
| float2 test_clamp_vector_size_mismatch(float3 p0, float2 p1) { | ||
| return clamp(p0, p0, p1); | ||
| // expected-warning@-1 {{implicit conversion truncates vector: 'float3' (aka 'vector<float, 3>') to 'float __attribute__((ext_vector_type(2)))' (vector of 2 'float' values)}} | ||
| } | ||
|
|
||
| float2 test_clamp_builtin_vector_size_mismatch(float3 p0, float2 p1) { | ||
| return __builtin_hlsl_elementwise_clamp(p0, p1, p1); | ||
| // expected-error@-1 {{all arguments to '__builtin_hlsl_elementwise_clamp' must have the same type}} | ||
| } | ||
|
|
||
| float test_clamp_scalar_mismatch(float p0, half p1) { | ||
| return clamp(p1, p0, p1); | ||
| // expected-error@-1 {{call to 'clamp' is ambiguous}} | ||
| } | ||
|
|
||
| float2 test_clamp_element_type_mismatch(half2 p0, float2 p1) { | ||
| return clamp(p1, p0, p1); | ||
| // expected-error@-1 {{call to 'clamp' is ambiguous}} | ||
| } | ||
|
|
||
| float2 test_builtin_clamp_float2_splat(float p0, float2 p1) { | ||
| return __builtin_hlsl_elementwise_clamp(p0, p1, p1); | ||
| // expected-error@-1 {{all arguments to '__builtin_hlsl_elementwise_clamp' must be vectors}} | ||
| } | ||
|
|
||
| float3 test_builtin_clamp_float3_splat(float p0, float3 p1) { | ||
| return __builtin_hlsl_elementwise_clamp(p0, p1, p1); | ||
| // expected-error@-1 {{all arguments to '__builtin_hlsl_elementwise_clamp' must be vectors}} | ||
| } | ||
|
|
||
| float4 test_builtin_clamp_float4_splat(float p0, float4 p1) { | ||
| return __builtin_hlsl_elementwise_clamp(p0, p1, p1); | ||
| // expected-error@-1 {{all arguments to '__builtin_hlsl_elementwise_clamp' must be vectors}} | ||
| } | ||
|
|
||
| float2 test_clamp_float2_int_splat(float2 p0, int p1) { | ||
| return __builtin_hlsl_elementwise_clamp(p0, p1, p1); | ||
| // expected-error@-1 {{all arguments to '__builtin_hlsl_elementwise_clamp' must be vectors}} | ||
| } | ||
|
|
||
| float3 test_clamp_float3_int_splat(float3 p0, int p1) { | ||
| return __builtin_hlsl_elementwise_clamp(p0, p1, p1); | ||
| // expected-error@-1 {{all arguments to '__builtin_hlsl_elementwise_clamp' must be vectors}} | ||
| } | ||
|
|
||
| float2 test_builtin_clamp_int_vect_to_float_vec_promotion(int2 p0, float p1) { | ||
| return __builtin_hlsl_elementwise_clamp(p0, p1, p1); | ||
| // expected-error@-1 {{all arguments to '__builtin_hlsl_elementwise_clamp' must be vectors}} | ||
| } | ||
|
|
||
| float test_builtin_clamp_bool_type_promotion(bool p0) { | ||
| return __builtin_hlsl_elementwise_clamp(p0, p0, p0); | ||
| // expected-error@-1 {{1st argument must be a vector, integer or floating point type (was 'bool')}} | ||
| } | ||
|
|
||
| float builtin_bool_to_float_type_promotion(float p0, bool p1) { | ||
| return __builtin_hlsl_elementwise_clamp(p0, p0, p1); | ||
| // expected-error@-1 {{3rd argument must be a floating point type (was 'bool')}} | ||
| } | ||
|
|
||
| float builtin_bool_to_float_type_promotion2(bool p0, float p1) { | ||
| return __builtin_hlsl_elementwise_clamp(p1, p0, p1); | ||
| // expected-error@-1 {{2nd argument must be a floating point type (was 'bool')}} | ||
| } | ||
|
|
||
| float builtin_clamp_int_to_float_promotion(float p0, int p1) { | ||
| return __builtin_hlsl_elementwise_clamp(p0, p0, p1); | ||
| // expected-error@-1 {{3rd argument must be a floating point type (was 'int')}} | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1 @@ | ||
| BasedOnStyle: clang-format |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| //===--- InstallAPIOpts.td ------------------------------------------------===// | ||
| // | ||
| // 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // This file defines the specific options for InstallAPI. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // Include the common option parsing interfaces. | ||
| include "llvm/Option/OptParser.td" | ||
|
|
||
|
|
||
| ///////// | ||
| // Options | ||
|
|
||
| // TextAPI options. | ||
| def filetype : Joined<["--"], "filetype=">, | ||
| HelpText<"Specify the output file type (tbd-v4 or tbd-v5)">; | ||
|
|
||
| // Verification options. | ||
| def verify_against : Separate<["-"], "verify-against">, | ||
| HelpText<"Verify the specified dynamic library/framework against the headers">; | ||
| def verify_against_EQ : Joined<["--"], "verify-against=">, Alias<verify_against>; | ||
| def verify_mode_EQ : Joined<["--"], "verify-mode=">, | ||
| HelpText<"Specify the severity and extend of the validation. Valid modes are ErrorsOnly, ErrorsAndWarnings, and Pedantic.">; | ||
| def demangle : Flag<["--", "-"], "demangle">, | ||
| HelpText<"Demangle symbols when printing warnings and errors">; |